1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
28 #include <libgeda/libgeda.h>
30 #include "../include/globals.h"
31 #include "../include/prototype.h"
33 #ifdef HAVE_LIBDMALLOC
37 /* used in key_press, since it isn't passed this information */
38 /* filled in x_event_motion */
41 /* used by mouse pan */
42 extern int current_center_x
, current_center_y
;
43 int start_pan_x
, start_pan_y
;
46 /* used for the stroke stuff */
49 #define MAX_SEQUENCE 20
50 static int DOING_STROKE
= FALSE
;
51 char sequence
[MAX_SEQUENCE
+1];
53 /* libstroke prototypes */
54 void stroke_init (void);
55 void stroke_record (int x
, int y
);
56 int stroke_trans (char *sequence
);
59 /*! \todo Finish function documentation!!!
61 * \par Function Description
64 gint
x_event_expose(GtkWidget
*widget
, GdkEventExpose
*event
,
71 exit_if_null(w_current
);
72 /* nasty global variable */
73 global_window_current
= (TOPLEVEL
*) w_current
;
75 gdk_draw_pixmap(widget
->window
,
76 widget
->style
->fg_gc
[GTK_WIDGET_STATE (widget
)],
77 w_current
->backingstore
,
78 event
->area
.x
, event
->area
.y
,
79 event
->area
.x
, event
->area
.y
,
80 event
->area
.width
, event
->area
.height
);
82 /* either this or put xor's and friends into backingstore */
83 /* take care of ghosting when you get an expose event */
84 if (w_current
->inside_action
) {
85 switch(w_current
->event_state
) {
91 o_drawbounding(w_current
, NULL
,
92 geda_list_get_glist( w_current
->page_current
->selection_list
),
93 x_get_darkcolor(w_current
->bb_color
), FALSE
);
98 o_drawbounding(w_current
, NULL
,
99 w_current
->page_current
->complex_place_list
,
100 x_get_darkcolor(w_current
->bb_color
), FALSE
);
105 o_bus_xorrubber(w_current
);
109 o_net_xorrubber(w_current
);
112 o_arc_rubberarc_xor(w_current
);
114 case(ENDATTRIB
): /*! \todo how to test ??? */
115 o_attrib_rubberattrib(w_current
);
118 o_box_rubberbox_xor(w_current
);
121 o_circle_rubbercircle_xor(w_current
);
124 o_line_rubberline_xor(w_current
);
126 case(ENDPIN
): /*! \todo (no function in o_pin.nw available) */
129 o_text_rubberattrib(w_current
);
131 case(GRIPS
): /*! \todo (larger changes in o_grips.nw necessary) */
133 case(ZOOMBOXEND
): /*! \todo (not realy a problem as zoom will redraw) */
138 /* raise the dialog boxes if this feature is enabled */
139 if (w_current
->raise_dialog_boxes
) {
140 x_dialog_raise_all(w_current
);
146 /*! \todo Finish function documentation!!!
148 * \par Function Description
151 gint
x_event_button_pressed(GtkWidget
*widget
, GdkEventButton
*event
,
157 exit_if_null(w_current
);
158 global_window_current
= w_current
;
161 printf("pressed button %d! \n", event
->button
);
162 printf("event state: %d \n", event
->state
);
163 printf("w_current state: %d \n", w_current
->event_state
);
164 printf("Selection is:\n");
165 o_selection_print_all(&(w_current
->page_current
->selection_list
));
169 if (event
->type
== GDK_2BUTTON_PRESS
&&
170 (w_current
->event_state
== STARTSELECT
||
171 w_current
->event_state
== SELECT
)) {
172 o_find_object(w_current
, (int) event
->x
, (int) event
->y
, TRUE
);
173 if ( geda_list_get_glist( w_current
->page_current
->selection_list
)) {
174 o_edit(w_current
, geda_list_get_glist( w_current
->page_current
->selection_list
));
179 w_current
->SHIFTKEY
= (event
->state
& GDK_SHIFT_MASK
) ? 1 : 0;
180 w_current
->CONTROLKEY
= (event
->state
& GDK_CONTROL_MASK
) ? 1 : 0;
181 w_current
->ALTKEY
= (event
->state
& GDK_MOD1_MASK
) ? 1 : 0;
183 if (event
->button
== 1) {
184 switch(w_current
->event_state
) {
187 /* look for grips or fall through if not enabled */
189 w_current
, (int) event
->x
, (int) event
->y
)) {
190 /* now go into normal SELECT */
191 w_current
->event_state
= STARTSELECT
;
192 w_current
->start_x
= w_current
->last_x
=
194 w_current
->start_y
= w_current
->last_y
=
197 /* a grip was found */
198 w_current
->event_state
= GRIPS
;
199 w_current
->inside_action
= 1;
204 if (o_select_selected(w_current
)) {
205 w_current
->rotated_inside
= 0;
206 o_copy_start(w_current
,
207 (int) event
->x
, (int) event
->y
);
208 w_current
->event_state
= COPY
;
209 w_current
->inside_action
= 1;
214 if (o_select_selected(w_current
)) {
215 w_current
->rotated_inside
= 0;
216 o_copy_start(w_current
,
217 (int) event
->x
, (int) event
->y
);
218 w_current
->event_state
= MCOPY
;
219 w_current
->inside_action
= 1;
224 if (o_select_selected(w_current
)) {
225 w_current
->rotated_inside
= 0;
226 o_move_start(w_current
,
227 (int) event
->x
, (int) event
->y
);
228 w_current
->event_state
= MOVE
;
229 w_current
->inside_action
= 1;
234 o_buffer_paste_start(w_current
,
237 w_current
->buffer_number
);
238 w_current
->event_state
= ENDPASTE
;
239 w_current
->inside_action
= 1;
243 o_line_start(w_current
,
246 w_current
->event_state
= ENDLINE
;
247 w_current
->inside_action
= 1;
251 o_line_end(w_current
,
254 w_current
->inside_action
= 0;
255 w_current
->event_state
= DRAWLINE
;
259 o_box_start(w_current
,
262 w_current
->event_state
= ENDBOX
;
263 w_current
->inside_action
= 1;
270 w_current
->inside_action
= 0;
271 w_current
->event_state
= DRAWBOX
;
275 o_picture_start(w_current
,
278 w_current
->event_state
= ENDPICTURE
;
279 w_current
->inside_action
= 1;
283 o_picture_end(w_current
,
286 w_current
->inside_action
= 0;
287 w_current
->event_state
= DRAWPICTURE
;
291 o_circle_start(w_current
,
294 w_current
->event_state
= ENDCIRCLE
;
295 w_current
->inside_action
= 1;
299 o_circle_end(w_current
,
302 w_current
->inside_action
= 0;
303 w_current
->event_state
= DRAWCIRCLE
;
307 o_arc_start(w_current
,
310 w_current
->event_state
= ENDARC
;
311 w_current
->inside_action
= 1;
315 o_arc_end1(w_current
,
318 w_current
->inside_action
= 0;
319 w_current
->event_state
= DRAWARC
;
323 o_pin_start(w_current
,
326 w_current
->event_state
= ENDPIN
;
327 w_current
->inside_action
= 1;
334 w_current
->inside_action
= 0;
335 w_current
->event_state
= DRAWPIN
;
338 case(STARTDRAWNET
): /*! \todo change state name? */
339 o_net_start(w_current
,
342 w_current
->inside_action
= 1;
343 w_current
->event_state
=DRAWNET
;
348 o_bus_start(w_current
,
351 w_current
->inside_action
= 1;
352 w_current
->event_state
=DRAWBUS
;
358 /* Only continue the net if net end worked */
359 if (o_net_end(w_current
, (int) event
->x
,
361 o_net_start(w_current
,
362 (int) w_current
->save_x
,
363 (int) w_current
->save_y
);
364 w_current
->event_state
=NETCONT
;
370 /* Only continue the net if net end worked */
371 if (o_bus_end(w_current
, (int) event
->x
,
373 o_bus_start(w_current
,
374 (int) w_current
->save_x
,
375 (int) w_current
->save_y
);
376 w_current
->event_state
=BUSCONT
;
381 o_complex_end(w_current
,
382 fix_x(w_current
, (int) event
->x
),
383 fix_y(w_current
, (int) event
->y
));
384 /* not sure on this one */
385 /* probably keep this one */
387 o_redraw_single(w_current
, w_current
->page_current
->
389 if (w_current
->continue_component_place
) {
390 o_complex_start(w_current
,
394 w_current
->inside_action
= 0;
395 i_set_state(w_current
, SELECT
);
396 i_update_toolbar(w_current
);
401 o_buffer_paste_end(w_current
,
402 fix_x(w_current
, (int) event
->x
),
403 fix_y(w_current
, (int) event
->y
),
404 w_current
->buffer_number
);
405 w_current
->inside_action
= 0;
406 i_set_state(w_current
, SELECT
);
407 i_update_toolbar(w_current
);
411 o_attrib_end(w_current
);
412 /* not sure on this one either... */
413 /* keep it as well */
414 w_current
->inside_action
= 0;
415 i_set_state(w_current
, SELECT
);
416 i_update_toolbar(w_current
);
417 /* the following happen inside attrib_end */
418 /* therefore they are commeneted out here */
419 /* o_redraw_single(object_tail);*/
420 /* o_redraw_selected(); not sure on this */
424 prev_state
= w_current
->DONT_REDRAW
;
425 w_current
->DONT_REDRAW
= 0;
427 SCREENtoWORLD( w_current
,
431 w_x
= snap_grid(w_current
, w_x
);
432 w_y
= snap_grid(w_current
, w_y
);
436 geda_list_get_glist( w_current
->page_current
->selection_list
),
438 w_current
->DONT_REDRAW
= prev_state
;
440 w_current
->inside_action
= 0;
441 i_set_state(w_current
, SELECT
);
442 i_update_toolbar(w_current
);
446 SCREENtoWORLD( w_current
,
450 o_mirror_world(w_current
,
451 geda_list_get_glist( w_current
->page_current
->selection_list
),
453 w_x
= snap_grid(w_current
, w_x
);
454 w_y
= snap_grid(w_current
, w_y
);
456 w_current
->inside_action
= 0;
457 i_set_state(w_current
, SELECT
);
458 i_update_toolbar(w_current
);
462 o_text_end(w_current
);
463 /* not sure on this one either... */
464 /* keep it as well */
465 w_current
->inside_action
= 0;
466 i_set_state(w_current
, SELECT
);
467 i_update_toolbar(w_current
);
468 /* the following happen inside attrib_end */
469 /* therefore they are commeneted out here */
470 /* o_redraw_single(object_tail);*/
471 /* o_redraw_selected(); not sure on this */
479 /* keep this one too */
480 i_set_state(w_current
, SELECT
);
481 i_update_toolbar(w_current
);
482 /* go to select state or not? hack */
486 a_zoom_box_start(w_current
,
489 w_current
->event_state
= ZOOMBOXEND
;
490 w_current
->inside_action
= 1;
494 } else if (event
->button
== 2) {
496 /* try this out and see how it behaves */
497 if (w_current
->inside_action
) {
498 if (w_current
->event_state
== ENDCOMP
||
499 w_current
->event_state
== ENDTEXT
||
500 w_current
->event_state
== ENDMOVE
||
501 w_current
->event_state
== ENDCOPY
||
502 w_current
->event_state
== ENDMCOPY
) {
505 i_callback_cancel(w_current
, 0, NULL
);
510 switch(w_current
->middle_button
) {
513 /* determine here if copy or move */
514 /* for now do move only */
515 /* make sure the list is not empty */
516 if (o_select_selected(w_current
)) {
518 /* don't want to search if shift */
519 /* key is depresed */
520 if (!w_current
->SHIFTKEY
) {
521 o_find_object(w_current
,
523 (int) event
->y
, TRUE
);
526 o_select_unselect_all(w_current
);
527 /* don't want to search if shift */
528 /* key is depresed */
529 if (!w_current
->SHIFTKEY
) {
530 o_find_object(w_current
,
532 (int) event
->y
, TRUE
);
536 if (!o_select_selected(w_current
)) {
537 /* this means the above find did not
539 w_current
->inside_action
= 0;
540 i_set_state(w_current
, SELECT
);
541 i_update_toolbar(w_current
);
545 if (w_current
->ALTKEY
) {
546 o_copy_start(w_current
,
549 w_current
->inside_action
= 1;
550 i_set_state(w_current
, COPY
);
552 o_move_start(w_current
,
555 w_current
->inside_action
= 1;
556 i_set_state(w_current
, MOVE
);
561 if (w_current
->last_callback
!= NULL
) {
562 (*w_current
->last_callback
)(w_current
,
572 case(MID_MOUSEPAN_ENABLED
):
573 w_current
->event_state
= MOUSEPAN
; /* start */
574 w_current
->inside_action
= 1;
575 w_current
->doing_pan
= TRUE
;
576 start_pan_x
= (int) event
->x
;
577 start_pan_y
= (int) event
->y
;
582 } else if (event
->button
== 3) {
583 if (!w_current
->inside_action
) {
584 if (w_current
->third_button
== POPUP_ENABLED
) {
585 i_update_menus(w_current
); /* update menus before popup */
586 do_popup(w_current
, event
);
588 w_current
->event_state
= MOUSEPAN
; /* start */
589 w_current
->inside_action
= 1;
590 w_current
->doing_pan
= TRUE
;
591 start_pan_x
= (int) event
->x
;
592 start_pan_y
= (int) event
->y
;
595 } else { /* this is the default cancel */
596 switch (w_current
->event_state
) {
600 w_current
->inside_action
= 0;
601 i_set_state(w_current
, STARTDRAWNET
);
602 o_net_eraserubber(w_current
);
608 w_current
->inside_action
= 0;
609 i_set_state(w_current
, STARTDRAWBUS
);
610 o_bus_eraserubber(w_current
);
615 w_current
->inside_action
= 0;
616 i_set_state(w_current
, DRAWPIN
);
617 o_pin_eraserubber(w_current
);
622 w_current
->inside_action
= 0;
623 i_set_state(w_current
, DRAWLINE
);
624 o_line_eraserubber(w_current
);
629 w_current
->inside_action
= 0;
630 i_set_state(w_current
, DRAWBOX
);
631 o_box_eraserubber(w_current
);
636 w_current
->inside_action
= 0;
637 i_set_state(w_current
, DRAWPICTURE
);
638 o_picture_eraserubber(w_current
);
643 w_current
->inside_action
= 0;
644 i_set_state(w_current
, DRAWCIRCLE
);
645 o_circle_eraserubber(w_current
);
650 w_current
->inside_action
= 0;
651 i_set_state(w_current
, DRAWARC
);
652 o_arc_eraserubber(w_current
);
656 i_callback_cancel(w_current
, 0, NULL
);
659 i_update_toolbar(w_current
);
665 /*! \todo Finish function documentation!!!
667 * \par Function Description
670 gint
x_event_button_released(GtkWidget
*widget
, GdkEventButton
*event
,
677 exit_if_null(w_current
);
678 global_window_current
= w_current
;
681 printf("released! %d \n", w_current
->event_state
);
684 w_current
->SHIFTKEY
= (event
->state
& GDK_SHIFT_MASK
) ? 1 : 0;
685 w_current
->CONTROLKEY
= (event
->state
& GDK_CONTROL_MASK
) ? 1 : 0;
686 w_current
->ALTKEY
= (event
->state
& GDK_MOD1_MASK
) ? 1 : 0;
688 if (event
->button
== 1) {
689 switch(w_current
->event_state
) {
695 w_current
->event_state
= ENDMOVE
;
699 w_current
->event_state
= ENDCOPY
;
703 w_current
->event_state
= ENDMCOPY
;
707 o_grips_end(w_current
),
708 w_current
->inside_action
= 0;
709 i_set_state(w_current
, SELECT
);
710 i_update_toolbar(w_current
);
714 o_move_end(w_current
);
715 /* having this stay in copy was driving me nuts*/
716 w_current
->inside_action
= 0;
717 i_set_state(w_current
, SELECT
);
718 i_update_toolbar(w_current
);
722 o_copy_end(w_current
);
723 /* having this stay in copy was driving me nuts*/
724 w_current
->inside_action
= 0;
725 i_set_state(w_current
, SELECT
);
726 i_update_toolbar(w_current
);
730 o_copy_end(w_current
);
731 /* having this stay in copy was driving me nuts*/
732 w_current
->inside_action
= 1;
733 /* Keep the state and the inside_action, as the copy has not finished. */
734 w_current
->last_x
= w_current
->start_x
= fix_x(w_current
, mouse_x
);
735 w_current
->last_y
= w_current
->start_y
= fix_y(w_current
, mouse_y
);
736 i_set_state(w_current
, ENDMCOPY
);
737 i_update_toolbar(w_current
);
738 o_undo_savestate(w_current
, UNDO_ALL
);
742 /* fix_x,y was removed to allow more flex */
743 w_current
->last_x
= (int) event
->x
;
744 w_current
->last_y
= (int) event
->y
;
745 /* NEW SELECTION code */
746 o_select_box_end(w_current
,
750 w_current
->inside_action
= 0;
751 i_set_state(w_current
, SELECT
);
752 i_update_toolbar(w_current
);
756 /* fix_x,y was removed to allow more flex */
757 w_current
->last_x
= (int) event
->x
;
758 w_current
->last_y
= (int) event
->y
;
759 a_zoom_box_end(w_current
,
763 w_current
->inside_action
= 0;
764 i_set_state(w_current
, SELECT
);
765 i_update_toolbar(w_current
);
769 /* first look for grips */
771 w_current
, (int) event
->x
, (int) event
->y
)) {
772 /* now go looking for objects to select */
773 o_find_object(w_current
,
775 (int) event
->y
, TRUE
);
776 w_current
->event_state
= SELECT
;
777 w_current
->inside_action
= 0;
779 /* an grip was found */
780 w_current
->event_state
= GRIPS
;
781 w_current
->inside_action
= 1;
786 } else if (event
->button
== 2) {
788 if (w_current
->inside_action
) {
789 if (w_current
->event_state
== ENDCOMP
) {
790 o_drawbounding(w_current
,
792 w_current
->page_current
->complex_place_list
,
793 x_get_darkcolor(w_current
->bb_color
), TRUE
);
795 w_current
->complex_rotate
=
796 (w_current
->complex_rotate
+ 90) % 360;
798 o_complex_place_rotate(w_current
);
800 /* Run the complex place list changed hook without redrawing */
801 /* since all objects are being redrawn afterwards */
802 prev_state
= w_current
->DONT_REDRAW
;
803 w_current
->DONT_REDRAW
= 1;
804 o_complex_place_changed_run_hook (w_current
);
805 w_current
->DONT_REDRAW
= prev_state
;
807 o_drawbounding(w_current
,
809 w_current
->page_current
->complex_place_list
,
810 x_get_darkcolor(w_current
->bb_color
), TRUE
);
812 } else if (w_current
->event_state
== ENDTEXT
) {
813 o_drawbounding(w_current
,
814 w_current
->page_current
->
815 attrib_place_head
->next
,
817 x_get_darkcolor(w_current
->bb_color
), TRUE
);
819 w_current
->complex_rotate
=
820 (w_current
->complex_rotate
+ 90) % 360;
822 o_text_place_rotate(w_current
);
824 o_drawbounding(w_current
,
825 w_current
->page_current
->
826 attrib_place_head
->next
,
828 x_get_darkcolor(w_current
->bb_color
), TRUE
);
832 else if (w_current
->event_state
== ENDMOVE
) {
833 prev_state
= w_current
->event_state
;
835 o_drawbounding(w_current
, NULL
,
836 w_current
->page_current
->complex_place_list
,
837 x_get_darkcolor(w_current
->bb_color
), TRUE
);
839 /* Don't allow o_rotate_90 to erase the selection, neither to
840 redraw the objects after rotating */
841 /* skip over head node */
842 redraw_state
= w_current
->DONT_REDRAW
;
843 w_current
->DONT_REDRAW
= 1;
844 SCREENtoWORLD( w_current
,
845 w_current
->start_x
, w_current
->start_y
,
847 w_x
= snap_grid(w_current
, w_x
);
848 w_y
= snap_grid(w_current
, w_y
);
849 o_rotate_90_world(w_current
, w_current
->page_current
->complex_place_list
, w_x
, w_y
);
850 w_current
->DONT_REDRAW
= redraw_state
;
851 w_current
->rotated_inside
++;
852 w_current
->event_state
= prev_state
;
854 o_drawbounding(w_current
, NULL
,
855 w_current
->page_current
->complex_place_list
,
856 x_get_darkcolor(w_current
->bb_color
), TRUE
);
860 else if ((w_current
->event_state
== ENDCOPY
) ||
861 (w_current
->event_state
== ENDMCOPY
)) {
862 /* Rotating while copying is still not supported, so do nothing */
868 switch(w_current
->middle_button
) {
870 switch(w_current
->event_state
) {
872 o_move_end(w_current
);
873 w_current
->inside_action
= 0;
874 i_set_state(w_current
, SELECT
);
875 i_update_toolbar(w_current
);
879 o_copy_end(w_current
);
880 w_current
->inside_action
= 0;
881 i_set_state(w_current
, SELECT
);
882 i_update_toolbar(w_current
);
890 DOING_STROKE
= FALSE
;
892 if (stroke_trans (sequence
) == TRUE
) {
893 if (stroke_info_mode
) {
894 printf ("LibStroke Translation"
898 if (stroke_info_mode
) {
899 printf ("LibStroke Translation"
904 if (stroke_info_mode
) {
905 printf ("Sequence=\"%s\"\n",sequence
);
908 /* new way written by Stefan Petersen */
910 if (x_stroke_search_execute(sequence
)) {
912 if (stroke_info_mode
) {
913 printf("Sequence understood\n");
915 x_stroke_erase_all(w_current
);
920 case(MID_MOUSEPAN_ENABLED
):
921 w_current
->doing_pan
=FALSE
;
922 o_redraw_all_fast(w_current
);
923 o_undo_savestate(w_current
, UNDO_VIEWPORT_ONLY
);
924 /* this needs to be REDONE */
925 /* if you mouse pan, you will be thrown out of the current mode. */
927 w_current
->inside_action
= 0;
928 i_set_state(w_current
, SELECT
);
929 i_update_toolbar(w_current
);
933 } else if (event
->button
== 3) {
934 if (w_current
->doing_pan
) { /* just for ending a mouse pan */
935 w_current
->doing_pan
=FALSE
;
936 o_redraw_all_fast(w_current
);
937 o_undo_savestate(w_current
, UNDO_VIEWPORT_ONLY
);
938 /* this needs to be REDONE */
939 /* if you mouse pan, you will be thrown out of the current mode. */
941 w_current
->inside_action
= 0;
942 i_set_state(w_current
, SELECT
);
943 i_update_toolbar(w_current
);
949 /*! \todo Finish function documentation!!!
951 * \par Function Description
954 gint
x_event_motion(GtkWidget
*widget
, GdkEventMotion
*event
,
958 int pdiff_x
, pdiff_y
;
963 GdkEvent
*test_event
;
965 exit_if_null(w_current
);
966 global_window_current
= w_current
;
968 w_current
->SHIFTKEY
= (event
->state
& GDK_SHIFT_MASK
) ? 1 : 0;
969 w_current
->CONTROLKEY
= (event
->state
& GDK_CONTROL_MASK
) ? 1 : 0;
970 w_current
->ALTKEY
= (event
->state
& GDK_MOD1_MASK
) ? 1 : 0;
973 /* printf("MOTION!\n");*/
977 if (DOING_STROKE
== TRUE
) {
978 x_stroke_add_point(w_current
, (int) event
->x
, (int) event
->y
);
980 stroke_record ((int) event
->x
, (int) event
->y
);
985 /* skip the moving event if there are other moving events in the
986 gdk event queue (Werner)
987 Only skip the event if is the same event and no buttons or modifier
989 if ((test_event
= gdk_event_get()) != NULL
) {
990 if (test_event
->type
== GDK_MOTION_NOTIFY
991 && ((GdkEventMotion
*) test_event
)->state
== event
->state
) {
994 gdk_event_put(test_event
); /* put it back in front of the queue */
995 gdk_event_free(test_event
);
1000 mouse_x
= (int) event
->x
;
1001 mouse_y
= (int) event
->y
;
1003 if (w_current
->cowindow
) {
1004 coord_display_update(w_current
, mouse_x
, mouse_y
);
1007 if (w_current
->third_button
== MOUSEPAN_ENABLED
|| w_current
->middle_button
== MID_MOUSEPAN_ENABLED
) {
1008 if((w_current
->event_state
== MOUSEPAN
) &&
1009 w_current
->inside_action
) {
1010 pdiff_x
= mouse_x
- start_pan_x
;
1011 pdiff_y
= mouse_y
- start_pan_y
;
1013 if (!(throttle
% 5)) {
1014 a_pan_mouse(w_current
, pdiff_x
*w_current
->mousepan_gain
,
1015 pdiff_y
*w_current
->mousepan_gain
);
1017 start_pan_x
= (int) event
->x
;
1018 start_pan_y
= (int) event
->y
;
1025 switch(w_current
->event_state
) {
1032 o_grips_motion(w_current
, (int) event
->x
, (int) event
->y
);
1036 if ( (!w_current
->drag_can_move
) ||
1037 (w_current
->drag_can_move
&&
1038 (! o_find_selected_object(w_current
,
1039 w_current
->start_x
, w_current
->start_y
)))) {
1040 temp_x
= fix_x(w_current
, (int) event
->x
);
1041 temp_y
= fix_y(w_current
, (int) event
->y
);
1042 /* is eight enough of a threshold? */
1043 /* make this configurable anyways */
1044 diff_x
= fabs(w_current
->page_current
->right
-
1045 w_current
->page_current
->left
);
1048 zoom_scale
= (int) rint(w_current
->init_right
/ diff_x
);
1050 zoom_scale
= (int) w_current
->init_right
/ diff_x
;
1053 if (zoom_scale
< 10) {
1057 if ( (abs(temp_x
- w_current
->start_x
) > zoom_scale
) ||
1058 (abs(temp_y
- w_current
->start_y
) > zoom_scale
) ) {
1059 w_current
->event_state
= SBOX
;
1060 /* NEW SELECTION code */
1061 o_select_box_start(w_current
,
1064 w_current
->inside_action
= 1;
1069 /* Start the object movement */
1070 w_current
->rotated_inside
= 0;
1071 o_move_start(w_current
,
1072 (int) event
->x
, (int) event
->y
);
1073 w_current
->event_state
= ENDMOVE
;
1074 w_current
->inside_action
= 1;
1076 /* Continue to the MOVE actions */
1077 /* Important!! keep the MOVE and ENDMOVE cases below this
1078 without the break statement!! */
1083 if (w_current
->inside_action
) {
1085 if (w_current
->netconn_rubberband
) {
1086 o_move_stretch_rubberband(w_current
);
1089 o_complex_rubbercomplex(w_current
);
1090 w_current
->last_x
= fix_x(w_current
, (int) event
->x
);
1091 w_current
->last_y
= fix_y(w_current
, (int) event
->y
);
1092 o_complex_rubbercomplex(w_current
);
1093 if (w_current
->netconn_rubberband
) {
1094 o_move_stretch_rubberband(w_current
);
1104 if (w_current
->inside_action
) {
1105 o_drawbounding(w_current
, NULL
,
1106 geda_list_get_glist( w_current
->page_current
->selection_list
),
1107 x_get_darkcolor(w_current
->bb_color
), FALSE
);
1108 w_current
->last_x
= fix_x(w_current
, (int) event
->x
);
1109 w_current
->last_y
= fix_y(w_current
, (int) event
->y
);
1110 o_drawbounding(w_current
, NULL
,
1111 geda_list_get_glist( w_current
->page_current
->selection_list
),
1112 x_get_darkcolor(w_current
->bb_color
), FALSE
);
1117 if (w_current
->inside_action
)
1118 o_line_rubberline(w_current
,
1124 if (w_current
->inside_action
)
1125 o_box_rubberbox( w_current
,
1131 if (w_current
->inside_action
)
1132 o_picture_rubberbox( w_current
,
1138 if (w_current
->inside_action
)
1139 o_circle_rubbercircle(w_current
,
1145 if (w_current
->inside_action
)
1146 /* pb20011022 - changed name to _rubberarc() and added a parameter */
1147 o_arc_rubberarc(w_current
,
1149 (int) event
->y
, ARC_RADIUS
);
1154 if (w_current
->inside_action
)
1155 o_net_rubbernet(w_current
,
1162 if (w_current
->inside_action
)
1163 o_bus_rubberbus(w_current
,
1169 if (w_current
->inside_action
)
1170 o_pin_rubberpin(w_current
,
1176 w_current
->complex_rotate
= 0; /* reset to known state */
1177 o_complex_start(w_current
,
1180 w_current
->event_state
= ENDCOMP
;
1181 w_current
->inside_action
= 1;
1185 o_complex_rubbercomplex(w_current
);
1186 w_current
->last_x
= fix_x(w_current
, (int) event
->x
);
1187 w_current
->last_y
= fix_y(w_current
, (int) event
->y
);
1188 o_complex_rubbercomplex(w_current
);
1192 o_buffer_paste_rubberpaste(w_current
, w_current
->buffer_number
);
1193 w_current
->last_x
= fix_x(w_current
, (int) event
->x
);
1194 w_current
->last_y
= fix_y(w_current
, (int) event
->y
);
1195 o_buffer_paste_rubberpaste(w_current
, w_current
->buffer_number
);
1199 o_attrib_start(w_current
, (int) event
->x
, (int) event
->y
);
1200 w_current
->event_state
= ENDATTRIB
;
1201 w_current
->inside_action
= 1;
1205 w_current
->complex_rotate
= 0; /* reset to known state */
1206 o_text_start(w_current
, (int) event
->x
, (int) event
->y
);
1207 w_current
->event_state
= ENDTEXT
;
1208 w_current
->inside_action
= 1;
1212 o_attrib_rubberattrib(w_current
);
1213 w_current
->last_x
= fix_x(w_current
, (int) event
->x
);
1214 w_current
->last_y
= fix_y(w_current
, (int) event
->y
);
1215 o_attrib_rubberattrib(w_current
);
1219 o_text_rubberattrib(w_current
);
1220 w_current
->last_x
= fix_x(w_current
, (int) event
->x
);
1221 w_current
->last_y
= fix_y(w_current
, (int) event
->y
);
1222 o_text_rubberattrib(w_current
);
1226 if (w_current
->inside_action
)
1227 /* NEW SELECTION code */
1228 o_select_box_rubberband(w_current
,
1234 if (w_current
->inside_action
)
1235 a_zoom_box_rubberband( w_current
,
1244 /*! \brief Updates the toplevel and display when drawing area is configured.
1245 * \par Function Description
1246 * This is the callback function connected to the configure event of
1247 * the drawing area of the main window.
1249 * It updates the size of the backingstore for the associated
1250 * toplevel structure (creates a new pixmap) and re-pans each of its
1251 * pages to keep their contents centered in the drawing area.
1253 * When the window is maximised, the zoom of every page is changed to
1254 * best fit the previously displayed area of the page in the new
1255 * area. Otherwise the current zoom level is left unchanged.
1257 * \param [in] widget The drawing area which received the signal.
1258 * \param [in] event The event structure of signal configure-event.
1259 * \param [in] user_data The toplevel environment as user data.
1260 * \returns FALSE to propagate the event further.
1263 x_event_configure (GtkWidget
*widget
,
1264 GdkEventConfigure
*event
,
1267 TOPLEVEL
*toplevel
= (TOPLEVEL
*)user_data
;
1268 PAGE
*old_page_current
, *p_current
;
1269 gint old_win_width
, old_win_height
, new_win_width
, new_win_height
;
1270 gdouble relativ_zoom_factor
= 1.0;
1272 g_assert (toplevel
!= NULL
);
1273 global_window_current
= toplevel
;
1275 if (toplevel
->page_current
== NULL
) {
1276 /* don't want to call this if the current page isn't setup yet */
1280 old_win_width
= toplevel
->win_width
;
1281 old_win_height
= toplevel
->win_height
;
1282 new_win_width
= event
->width
;
1283 new_win_height
= event
->height
;
1285 if (old_win_width
== new_win_width
&&
1286 old_win_height
== new_win_height
) {
1287 /* the size of the drawing area has not changed */
1288 /* nothing to do here */
1292 /* update the backingstore of toplevel */
1293 if (toplevel
->backingstore
!= NULL
) {
1294 gdk_pixmap_unref (toplevel
->backingstore
);
1296 toplevel
->backingstore
= gdk_pixmap_new (widget
->window
,
1300 /* update the toplevel with new size of drawing area */
1301 toplevel
->win_width
= toplevel
->width
= new_win_width
;
1302 toplevel
->win_height
= toplevel
->height
= new_win_height
;
1305 /* in the case the user has maximised the window (hence the */
1306 /* configure event) fit the view by playing with zoom level */
1307 if (gdk_window_get_state (
1308 (gtk_widget_get_toplevel (
1309 widget
))->window
) & GDK_WINDOW_STATE_MAXIMIZED
) {
1310 gdouble width_ratio
, height_ratio
;
1312 /* tweak relative_zoom to better fit page in maximized window */
1313 width_ratio
= ((gdouble
)new_win_width
) / ((gdouble
)old_win_width
);
1314 height_ratio
= ((gdouble
)new_win_height
) / ((gdouble
)old_win_height
);
1315 /* keep smallest ratio as relative zoom factor when panning */
1316 relativ_zoom_factor
=
1317 (width_ratio
< height_ratio
) ? width_ratio
: height_ratio
;
1321 /* save current page */
1322 old_page_current
= toplevel
->page_current
;
1323 /* re-pan each page of the toplevel */
1324 for (p_current
= toplevel
->page_head
->next
;
1326 p_current
= p_current
->next
) {
1329 /* doing this the aspectratio is kept when changing (hw)*/
1330 cx
= ((gdouble
)(p_current
->left
+ p_current
->right
)) / 2;
1331 cy
= ((gdouble
)(p_current
->top
+ p_current
->bottom
)) / 2;
1332 s_page_goto (toplevel
, p_current
);
1333 a_pan_general (toplevel
, cx
, cy
, relativ_zoom_factor
, A_PAN_DONT_REDRAW
);
1336 /* restore current page to saved value */
1337 s_page_goto (toplevel
, old_page_current
);
1339 if (!toplevel
->DONT_REDRAW
) {
1340 /* redraw the current page and update UI */
1341 o_redraw_all_fast (toplevel
);
1342 x_scrollbars_update (toplevel
);
1348 /*! \todo Finish function documentation!!!
1350 * \par Function Description
1353 * this is used during an open command
1354 * to setup the correct sizes
1356 void x_manual_resize(TOPLEVEL
*w_current
)
1359 /* of the actual win window (drawing_area) */
1360 w_current
->win_width
= w_current
->drawing_area
->allocation
.width
;
1361 w_current
->win_height
= w_current
->drawing_area
->allocation
.height
;
1364 printf("manual: %d %d\n", w_current
->win_width
, w_current
->win_height
);
1367 w_current
->width
= w_current
->win_width
;
1368 w_current
->height
= w_current
->win_height
;
1370 /* need to do this every time you change width / height */
1371 set_window(w_current
, w_current
->page_current
,
1372 w_current
->page_current
->left
,
1373 w_current
->page_current
->right
,
1374 w_current
->page_current
->top
,
1375 w_current
->page_current
->bottom
);
1378 printf("Window aspect: %f\n",
1379 (float) w_current
->win_width
/ (float) w_current
->win_height
);
1381 printf("w: %d h: %d\n", width, height); */
1382 printf("aw: %d ah: %d\n", w_current
->win_width
, w_current
->win_height
);
1385 /* I'm assuming that the backingstore pixmap is of the right
1389 /*! \todo Finish function documentation!!!
1391 * \par Function Description
1394 void x_event_hschanged (GtkAdjustment
*adj
, TOPLEVEL
*w_current
)
1398 GtkAdjustment
*hadjustment
;
1400 exit_if_null(w_current
);
1401 global_window_current
= w_current
;
1403 if (w_current
->scrollbars_flag
== FALSE
) {
1408 gtk_range_get_adjustment(GTK_RANGE(w_current
->h_scrollbar
));
1410 current_left
= w_current
->page_current
->left
;
1411 new_left
= (int) hadjustment
->value
;
1413 if (!w_current
->DONT_RECALC
) {
1414 w_current
->page_current
->left
= new_left
;
1415 w_current
->page_current
->right
=
1416 w_current
->page_current
->right
-
1417 (current_left
- new_left
);
1420 if (!w_current
->DONT_REDRAW
) {
1421 o_redraw_all_fast(w_current
);
1425 /*! \todo Finish function documentation!!!
1427 * \par Function Description
1430 void x_event_vschanged (GtkAdjustment
*adj
, TOPLEVEL
*w_current
)
1434 GtkAdjustment
*vadjustment
;
1436 exit_if_null(w_current
);
1437 global_window_current
= w_current
;
1439 if (w_current
->scrollbars_flag
== FALSE
) {
1443 vadjustment
= gtk_range_get_adjustment(
1444 GTK_RANGE(w_current
->v_scrollbar
));
1446 current_bottom
= w_current
->page_current
->bottom
;
1447 new_bottom
= w_current
->init_bottom
- (int) vadjustment
->value
;
1449 if (!w_current
->DONT_RECALC
) {
1450 w_current
->page_current
->bottom
= new_bottom
;
1451 w_current
->page_current
->top
=
1452 w_current
->page_current
->top
-
1453 (current_bottom
- new_bottom
);
1457 printf("vrange %f %f\n", vadjustment
->lower
, vadjustment
->upper
);
1458 printf("vvalue %f\n", vadjustment
->value
);
1459 printf("actual: %d %d\n", w_current
->page_current
->top
,
1460 w_current
->page_current
->bottom
);
1463 if (!w_current
->DONT_REDRAW
) {
1464 o_redraw_all_fast(w_current
);
1468 /*! \todo Finish function documentation!!!
1470 * \par Function Description
1473 gint
x_event_enter(GtkWidget
*widget
, GdkEventCrossing
*event
,
1474 TOPLEVEL
*w_current
)
1476 exit_if_null(w_current
);
1477 global_window_current
= w_current
;
1478 /* do nothing or now */
1482 /*! \todo Finish function documentation!!!
1484 * \par Function Description
1487 gboolean
x_event_key_press (GtkWidget
*widget
, GdkEventKey
*event
,
1488 TOPLEVEL
*w_current
)
1494 exit_if_null(w_current
);
1495 global_window_current
= w_current
;
1499 printf("x_event_key_pressed: Pressed key %i.\n", event
->keyval
);
1501 retval
= g_keys_execute(event
->state
, event
->keyval
) ? TRUE
: FALSE
;
1508 /*! \todo Finish function documentation!!!
1510 * \par Function Description
1513 gint
x_event_scroll (GtkWidget
*widget
, GdkEventScroll
*event
,
1514 TOPLEVEL
*w_current
)
1518 exit_if_null(w_current
);
1519 global_window_current
= w_current
;
1521 /* update the state of the modifiers */
1522 w_current
->SHIFTKEY
= (event
->state
& GDK_SHIFT_MASK
) ? 1 : 0;
1523 w_current
->CONTROLKEY
= (event
->state
& GDK_CONTROL_MASK
) ? 1 : 0;
1524 w_current
->ALTKEY
= (event
->state
& GDK_MOD1_MASK
) ? 1 : 0;
1526 switch (event
->direction
) {
1527 case(GDK_SCROLL_UP
):
1528 if (!w_current
->CONTROLKEY
&& !w_current
->SHIFTKEY
)
1530 /* turn the up/down scroll wheel into a zoom in / out */
1531 /*! \todo Change "HOTKEY" TO new "MOUSE" specifier?
1533 a_zoom(w_current
, ZOOM_IN
, HOTKEY
, 0);
1534 o_undo_savestate(w_current
, UNDO_VIEWPORT_ONLY
);
1535 } else if ( !w_current
->CONTROLKEY
) {
1536 /* if the control key is not held down, scroll up / down */
1537 /* You must have scrollbars enabled if you want to use the scroll wheel to pan */
1538 if (w_current
->scrollbars_flag
== FALSE
)
1540 adj
= gtk_range_get_adjustment(GTK_RANGE(w_current
->v_scrollbar
));
1541 gtk_adjustment_set_value(adj
, adj
->value
- (adj
->page_increment
/ 4));
1543 /* if the control key is held down, then scroll left as well */
1544 /* You must have scrollbars enabled if you want to use the scroll wheel to pan */
1545 if (w_current
->scrollbars_flag
== FALSE
)
1547 adj
= gtk_range_get_adjustment(GTK_RANGE(w_current
->h_scrollbar
));
1548 gtk_adjustment_set_value(adj
, adj
->value
- (adj
->page_increment
/ 4));
1552 case(GDK_SCROLL_DOWN
):
1553 if (!w_current
->CONTROLKEY
&& !w_current
->SHIFTKEY
)
1555 /* turn the up/down scroll wheel into a zoom in / out */
1556 /*! \todo Change "HOTKEY" TO new "MOUSE" specifier?
1558 a_zoom(w_current
, ZOOM_OUT
, HOTKEY
, 0);
1559 o_undo_savestate(w_current
, UNDO_VIEWPORT_ONLY
);
1560 } else if ( !w_current
->CONTROLKEY
) {
1561 /* if the control key is not held down, scroll up / down */
1562 /* You must have scrollbars enabled if you want to use the scroll wheel to pan */
1563 if (w_current
->scrollbars_flag
== FALSE
)
1565 adj
= gtk_range_get_adjustment(GTK_RANGE(w_current
->v_scrollbar
));
1566 gtk_adjustment_set_value(adj
, min(adj
->value
+ (adj
->page_increment
/ 4),
1567 adj
->upper
- adj
->page_size
));
1569 /* if the control key is held down, then scroll right as well */
1570 /* You must have scrollbars enabled if you want to use the scroll wheel to pan */
1571 if (w_current
->scrollbars_flag
== FALSE
)
1573 adj
= gtk_range_get_adjustment(GTK_RANGE(w_current
->h_scrollbar
));
1574 gtk_adjustment_set_value(adj
, min(adj
->value
+ (adj
->page_increment
/ 4),
1575 adj
->upper
- adj
->page_size
));
1579 case(GDK_SCROLL_LEFT
):
1580 /* You must have scrollbars enabled if you want to use the scroll wheel to pan */
1581 if (w_current
->scrollbars_flag
== FALSE
)
1583 adj
= gtk_range_get_adjustment(GTK_RANGE(w_current
->h_scrollbar
));
1584 gtk_adjustment_set_value(adj
, adj
->value
- (adj
->page_increment
/ 4));
1587 case(GDK_SCROLL_RIGHT
):
1588 /* You must have scrollbars enabled if you want to use the scroll wheel to pan */
1589 if (w_current
->scrollbars_flag
== FALSE
)
1591 adj
= gtk_range_get_adjustment(GTK_RANGE(w_current
->h_scrollbar
));
1592 gtk_adjustment_set_value(adj
, min(adj
->value
+ (adj
->page_increment
/ 4),
1593 adj
->upper
- adj
->page_size
));