2 * Grace - GRaphing, Advanced Computation and Exploration of data
4 * Home page: http://plasma-gate.weizmann.ac.il/Grace/
6 * Copyright (c) 1996-2004 Grace Development Team
8 * Maintained by Evgeny Stambulchik
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
40 #include "core_utils.h"
45 static void scroll_bar_pix(Widget bar
, int pix
)
47 int value
, slider_size
, maxvalue
, increment
;
49 GetScrollBarValues(bar
, &value
, &maxvalue
, &slider_size
, &increment
);
54 if (value
> maxvalue
- slider_size
) {
55 value
= maxvalue
- slider_size
;
57 SetScrollBarValue(bar
, value
);
60 static void scroll_pix(Widget w
, int dx
, int dy
)
64 if (dx
&& (bar
= GetHorizontalScrollBar(w
))) {
65 scroll_bar_pix(bar
, dx
);
67 if (dy
&& (bar
= GetVerticalScrollBar(w
))) {
68 scroll_bar_pix(bar
, dy
);
71 static void scroll(Widget w
, int up
, int horiz
)
73 int value
, slider_size
, increment
, maxvalue
;
77 vbar
= GetHorizontalScrollBar(w
);
79 vbar
= GetVerticalScrollBar(w
);
86 GetScrollBarValues(vbar
, &value
, &maxvalue
, &slider_size
, &increment
);
94 if (value
> maxvalue
- slider_size
) {
95 value
= maxvalue
- slider_size
;
98 SetScrollBarValue(vbar
, value
);
110 static void target_consider(canvas_target
*ct
, Quark
*q
, int part
,
113 if (is_vpoint_inside(v
, &ct
->vp
, 0.0)) {
121 static int target_hook(Quark
*q
, void *udata
, QTraverseClosure
*closure
)
123 canvas_target
*ct
= (canvas_target
*) udata
;
129 if (!quark_is_active(q
)) {
130 closure
->descend
= FALSE
;
134 switch (quark_fid_get(q
)) {
139 frame_get_view(q
, &v
);
140 target_consider(ct
, q
, 0, &v
);
142 if ((l
= frame_get_legend(q
)) && l
->active
) {
143 target_consider(ct
, q
, 1, &l
->bb
);
148 if (ct
->include_graphs
) {
149 GraceApp
*gapp
= gapp_from_quark(q
);
150 Quark
*cg
= graph_get_current(gproject_get_top(gapp
->gp
));
151 if (cg
== q
&& graph_get_viewport(q
, &v
) == RETURN_SUCCESS
) {
155 target_consider(ct
, q
, 0, &v
);
157 locator
= graph_get_locator(cg
);
158 Wpoint2Vpoint(cg
, &locator
->origin
, &vp
);
159 v
.xv1
= v
.xv2
= vp
.x
;
160 v
.yv1
= v
.yv2
= vp
.y
;
161 view_extend(&v
, 0.01);
162 target_consider(ct
, q
, 1, &v
);
167 at
= atext_get_data(q
);
170 target_consider(ct
, q
, 0, &at
->bb
);
172 if (at
->arrow_flag
&&
173 Apoint2Vpoint(q
, &at
->ap
, &vp
) == RETURN_SUCCESS
) {
174 double arrsize
= MAX2(0.01*at
->arrow
.length
, 0.005);
175 v
.xv1
= v
.xv2
= vp
.x
;
176 v
.yv1
= v
.yv2
= vp
.y
;
177 view_extend(&v
, arrsize
);
178 target_consider(ct
, q
, 1, &v
);
183 if (axis_get_bb(q
, &v
) == RETURN_SUCCESS
) {
184 target_consider(ct
, q
, 0, &v
);
188 o
= object_get_data(q
);
189 target_consider(ct
, q
, 0, &o
->bb
);
192 x
= set_get_col(q
, DATA_X
);
193 y
= set_get_col(q
, DATA_Y
);
198 set
*p
= set_get_data(q
);
199 double symsize
= MAX2(0.01*p
->sym
.size
, 0.005);
200 for (i
= 0; i
< set_get_length(q
); i
++) {
203 Wpoint2Vpoint(q
, &wp
, &vp
);
204 v
.xv1
= v
.xv2
= vp
.x
;
205 v
.yv1
= v
.yv2
= vp
.y
;
206 view_extend(&v
, symsize
);
207 target_consider(ct
, q
, i
, &v
);
216 static int find_target(GProject
*gp
, canvas_target
*ct
)
219 quark_traverse(gproject_get_top(gp
), target_hook
, ct
);
221 return ct
->found
? RETURN_SUCCESS
:RETURN_FAILURE
;
224 static void move_target(canvas_target
*ct
, const VPoint
*vp
)
228 vshift
.x
= vp
->x
- ct
->vp
.x
;
229 vshift
.y
= vp
->y
- ct
->vp
.y
;
231 switch (quark_fid_get(ct
->q
)) {
235 frame_shift(ct
->q
, &vshift
);
238 frame_legend_shift(ct
->q
, &vshift
);
245 atext_shift(ct
->q
, &vshift
);
248 atext_at_shift(ct
->q
, &vshift
);
253 axis_shift(ct
->q
, &vshift
);
256 object_shift(ct
->q
, &vshift
);
259 set_point_shift(ct
->q
, ct
->part
, &vshift
);
264 static Widget popup
= NULL
, poplab
, drop_pt_bt
, as_set_bt
, atext_bt
;
265 static Widget set_locator_bt
, clear_locator_bt
;
266 static Widget bring_to_front_bt
, move_up_bt
, move_down_bt
, send_to_back_bt
;
271 #define DUPLICATE_CB 3
272 #define BRING_TO_FRONT_CB 4
273 #define SEND_TO_BACK_CB 5
275 #define MOVE_DOWN_CB 7
276 #define DROP_POINT_CB 8
277 #define AUTOSCALE_BY_SET_CB 9
279 static void popup_any_cb(canvas_target
*ct
, int type
)
285 raise_explorer(gui_from_quark(q
), q
);
289 quark_set_active(q
, FALSE
);
297 case BRING_TO_FRONT_CB
:
300 case SEND_TO_BACK_CB
:
301 quark_push(q
, FALSE
);
307 quark_move(q
, FALSE
);
310 if (quark_fid_get(q
) == QFlavorSet
&& ct
->part
>= 0) {
311 del_point(q
, ct
->part
);
314 case AUTOSCALE_BY_SET_CB
:
315 if (quark_fid_get(q
) == QFlavorSet
) {
316 autoscale_bysets(&q
, 1, AUTOSCALE_XY
);
321 snapshot_and_update(gapp
->gp
, TRUE
);
324 static void edit_cb(Widget but
, void *udata
)
326 popup_any_cb((canvas_target
*) udata
, EDIT_CB
);
329 static void hide_cb(Widget but
, void *udata
)
331 popup_any_cb((canvas_target
*) udata
, HIDE_CB
);
334 static void delete_cb(Widget but
, void *udata
)
336 if (yesno("Really delete this item?", NULL
, NULL
, NULL
)) {
337 popup_any_cb((canvas_target
*) udata
, DELETE_CB
);
341 static void duplicate_cb(Widget but
, void *udata
)
343 popup_any_cb((canvas_target
*) udata
, DUPLICATE_CB
);
346 static void bring_to_front_cb(Widget but
, void *udata
)
348 popup_any_cb((canvas_target
*) udata
, BRING_TO_FRONT_CB
);
351 static void send_to_back_cb(Widget but
, void *udata
)
353 popup_any_cb((canvas_target
*) udata
, SEND_TO_BACK_CB
);
356 static void move_up_cb(Widget but
, void *udata
)
358 popup_any_cb((canvas_target
*) udata
, MOVE_UP_CB
);
361 static void move_down_cb(Widget but
, void *udata
)
363 popup_any_cb((canvas_target
*) udata
, MOVE_DOWN_CB
);
366 static void autoscale_cb(Widget but
, void *udata
)
368 popup_any_cb((canvas_target
*) udata
, AUTOSCALE_BY_SET_CB
);
371 static void drop_point_cb(Widget but
, void *udata
)
373 popup_any_cb((canvas_target
*) udata
, DROP_POINT_CB
);
376 static void atext_cb(Widget but
, void *udata
)
378 canvas_target
*ct
= (canvas_target
*) udata
;
382 q
= atext_new(ct
->q
);
383 Vpoint2Apoint(q
, &ct
->vp
, &ap
);
384 atext_set_ap(q
, &ap
);
385 atext_set_pointer(q
, TRUE
);
387 snapshot_and_update(gapp
->gp
, TRUE
);
389 raise_explorer(gui_from_quark(ct
->q
), q
);
393 * clear the locator reference point
395 static void do_clear_point(Widget but
, void *udata
)
397 canvas_target
*ct
= (canvas_target
*) udata
;
400 locator
= graph_get_locator(ct
->q
);
401 locator
->pointset
= FALSE
;
402 quark_dirtystate_set(ct
->q
, TRUE
);
404 snapshot_and_update(gapp
->gp
, TRUE
);
408 * set the locator reference point
410 static void set_locator_cb(Widget but
, void *udata
)
412 canvas_target
*ct
= (canvas_target
*) udata
;
416 Vpoint2Wpoint(ct
->q
, &ct
->vp
, &wp
);
418 locator
= graph_get_locator(ct
->q
);
419 locator
->origin
= wp
;
420 locator
->pointset
= TRUE
;
421 quark_dirtystate_set(ct
->q
, TRUE
);
423 snapshot_and_update(gapp
->gp
, TRUE
);
426 void canvas_event(CanvasEvent
*event
)
428 int x
, y
; /* pointer coordinates */
430 Quark
*cg
= graph_get_current(gproject_get_top(gapp
->gp
));
431 X11Stuff
*xstuff
= gapp
->gui
->xstuff
;
432 Widget drawing_window
= gapp
->gui
->mwui
->drawing_window
;
434 static unsigned long lastc_time
= 0; /* time of last mouse click */
435 static int lastc_x
, lastc_y
; /* coords of last mouse click */
436 static int last_b1down_x
, last_b1down_y
; /* coords of last event */
439 int undo_point
= FALSE
;
440 int abort_action
= FALSE
;
442 static canvas_target ct
;
448 switch (event
->type
) {
450 if (gapp
->gui
->crosshair_cursor
) {
451 crosshair_motion(gapp
->gui
, x
, y
);
454 x11_dev2VPoint(x
, y
, &vp
);
456 if (xstuff
->collect_points
&& xstuff
->npoints
) {
457 switch (xstuff
->sel_type
) {
458 case SELECTION_TYPE_RECT
:
459 select_region(gapp
->gui
,
460 x
, y
, last_b1down_x
, last_b1down_y
, TRUE
);
462 case SELECTION_TYPE_VERT
:
463 select_vregion(gapp
->gui
, x
, last_b1down_x
, TRUE
);
465 case SELECTION_TYPE_HORZ
:
466 select_hregion(gapp
->gui
, y
, last_b1down_y
, TRUE
);
470 if (event
->button
& LEFT_BUTTON
) {
471 if (event
->modifiers
& CONTROL_MODIFIER
) {
473 resize_region(gapp
->gui
, xstuff
->f_v
, on_focus
,
474 x
- last_b1down_x
, y
- last_b1down_y
, TRUE
);
477 slide_region(gapp
->gui
, ct
.bbox
,
478 x
- last_b1down_x
, y
- last_b1down_y
, TRUE
);
481 scroll_pix(drawing_window
, last_b1down_x
- x
, last_b1down_y
- y
);
484 if (gapp
->gui
->focus_policy
== FOCUS_FOLLOWS
) {
485 cg
= next_graph_containing(cg
, &vp
);
488 if (event
->modifiers
& CONTROL_MODIFIER
) {
489 if (abs(x
- xstuff
->f_x1
) <= 5 &&
490 abs(y
- xstuff
->f_y1
) <= 5) {
493 if (abs(x
- xstuff
->f_x1
) <= 5 &&
494 abs(y
- xstuff
->f_y2
) <= 5) {
497 if (abs(x
- xstuff
->f_x2
) <= 5 &&
498 abs(y
- xstuff
->f_y2
) <= 5) {
501 if (abs(x
- xstuff
->f_x2
) <= 5 &&
502 abs(y
- xstuff
->f_y1
) <= 5) {
508 set_cursor(gapp
->gui
, 4);
510 set_cursor(gapp
->gui
, -1);
515 update_locator_lab(cg
, &vp
);
521 x11_dev2VPoint(x
, y
, &vp
);
523 switch (event
->button
) {
525 /* first, determine if it's a double click */
526 if (event
->time
- lastc_time
< CLICK_INT
&&
527 abs(x
- lastc_x
) < CLICK_DIST
&&
528 abs(y
- lastc_y
) < CLICK_DIST
) {
533 lastc_time
= event
->time
;
538 if (event
->modifiers
& CONTROL_MODIFIER
) {
540 ct
.include_graphs
= FALSE
;
542 resize_region(gapp
->gui
, xstuff
->f_v
, on_focus
,
545 if (find_target(gapp
->gp
, &ct
) == RETURN_SUCCESS
) {
546 slide_region(gapp
->gui
, ct
.bbox
, 0, 0, FALSE
);
549 if (xstuff
->collect_points
) {
555 xrealloc(xstuff
->xps
, xstuff
->npoints
*sizeof(XPoint
));
556 xstuff
->xps
[xstuff
->npoints
- 1] = xp
;
557 select_region(gapp
->gui
, x
, y
, x
, y
, FALSE
);
559 if (gapp
->gui
->focus_policy
== FOCUS_CLICK
) {
560 cg
= next_graph_containing(cg
, &vp
);
562 update_locator_lab(cg
, &vp
);
566 ct
.include_graphs
= (event
->modifiers
& CONTROL_MODIFIER
) ? FALSE
:TRUE
;
567 if (find_target(gapp
->gp
, &ct
) == RETURN_SUCCESS
) {
568 raise_explorer(gapp
->gui
, ct
.q
);
576 if (!xstuff
->collect_points
) {
577 set_cursor(gapp
->gui
, 5);
582 fprintf(stderr
, "Button2\n");
585 if (xstuff
->collect_points
) {
587 if (xstuff
->npoints
) {
590 if (xstuff
->npoints
== 0) {
595 ct
.include_graphs
= (event
->modifiers
& CONTROL_MODIFIER
) ? FALSE
:TRUE
;
596 if (find_target(gapp
->gp
, &ct
) == RETURN_SUCCESS
) {
601 popup
= CreatePopupMenu(gapp
->gui
->xstuff
->canvas
);
603 poplab
= CreateMenuLabel(popup
, "");
605 CreateMenuSeparator(popup
);
607 CreateMenuButton(popup
,
608 "Properties...", '\0', edit_cb
, &ct
);
610 CreateMenuSeparator(popup
);
612 CreateMenuButton(popup
, "Hide", '\0', hide_cb
, &ct
);
614 CreateMenuSeparator(popup
);
616 CreateMenuButton(popup
,
617 "Delete", '\0', delete_cb
, &ct
);
618 CreateMenuButton(popup
,
619 "Duplicate", '\0', duplicate_cb
, &ct
);
621 CreateMenuSeparator(popup
);
623 bring_to_front_bt
= CreateMenuButton(popup
,
624 "Bring to front", '\0', bring_to_front_cb
, &ct
);
625 move_up_bt
= CreateMenuButton(popup
,
626 "Move up", '\0', move_up_cb
, &ct
);
627 move_down_bt
= CreateMenuButton(popup
,
628 "Move down", '\0', move_down_cb
, &ct
);
629 send_to_back_bt
= CreateMenuButton(popup
,
630 "Send to back", '\0', send_to_back_cb
, &ct
);
632 CreateMenuSeparator(popup
);
634 as_set_bt
= CreateMenuButton(popup
,
635 "Autoscale by this set", '\0', autoscale_cb
, &ct
);
637 atext_bt
= CreateMenuButton(popup
,
638 "Annotate this point", '\0', atext_cb
, &ct
);
640 CreateMenuSeparator(popup
);
642 drop_pt_bt
= CreateMenuButton(popup
,
643 "Drop this point", '\0', drop_point_cb
, &ct
);
645 set_locator_bt
= CreateMenuButton(popup
,
646 "Set locator fixed point", '\0', set_locator_cb
, &ct
);
647 clear_locator_bt
= CreateMenuButton(popup
,
648 "Clear locator fixed point", '\0', do_clear_point
, &ct
);
650 s
= q_labeling(ct
.q
);
653 if (quark_is_last_child(ct
.q
)) {
654 SetSensitive(bring_to_front_bt
, FALSE
);
655 SetSensitive(move_up_bt
, FALSE
);
657 SetSensitive(bring_to_front_bt
, TRUE
);
658 SetSensitive(move_up_bt
, TRUE
);
660 if (quark_is_first_child(ct
.q
)) {
661 SetSensitive(send_to_back_bt
, FALSE
);
662 SetSensitive(move_down_bt
, FALSE
);
664 SetSensitive(send_to_back_bt
, TRUE
);
665 SetSensitive(move_down_bt
, TRUE
);
668 if ((quark_fid_get(ct
.q
) == QFlavorFrame
&& ct
.part
== 0) ||
669 (quark_fid_get(ct
.q
) == QFlavorGraph
&& ct
.part
== 0)) {
670 ManageChild(atext_bt
);
672 UnmanageChild(atext_bt
);
674 if (quark_fid_get(ct
.q
) == QFlavorGraph
&& ct
.part
!= 1) {
675 ManageChild(set_locator_bt
);
677 UnmanageChild(set_locator_bt
);
679 if (quark_fid_get(ct
.q
) == QFlavorGraph
&& ct
.part
== 1) {
680 ManageChild(clear_locator_bt
);
682 UnmanageChild(clear_locator_bt
);
685 if (quark_fid_get(ct
.q
) == QFlavorSet
) {
686 ManageChild(as_set_bt
);
688 UnmanageChild(as_set_bt
);
690 if (quark_fid_get(ct
.q
) == QFlavorSet
&& ct
.part
>= 0) {
691 ManageChild(drop_pt_bt
);
693 UnmanageChild(drop_pt_bt
);
696 ShowMenu(popup
, event
->udata
);
700 case WHEEL_UP_BUTTON
:
701 scroll(drawing_window
, TRUE
, event
->modifiers
& CONTROL_MODIFIER
);
703 case WHEEL_DOWN_BUTTON
:
704 scroll(drawing_window
, FALSE
, event
->modifiers
& CONTROL_MODIFIER
);
711 switch (event
->button
) {
713 if (event
->modifiers
& CONTROL_MODIFIER
) {
714 x11_dev2VPoint(x
, y
, &vp
);
717 Quark
*fr
= get_parent_frame(graph_get_current(gproject_get_top(gapp
->gp
)));
718 frame_get_view(fr
, &v
);
737 frame_set_view(fr
, &v
);
740 slide_region(gapp
->gui
, ct
.bbox
, x
- last_b1down_x
, y
- last_b1down_y
, FALSE
);
742 move_target(&ct
, &vp
);
746 snapshot_and_update(gapp
->gp
, TRUE
);
748 if (!xstuff
->collect_points
) {
749 set_cursor(gapp
->gui
, -1);
755 switch (event
->key
) {
756 case KEY_ESCAPE
: /* Esc */
759 case KEY_PLUS
: /* "Grey" plus */
760 if (event
->modifiers
& CONTROL_MODIFIER
) {
761 page_zoom_inout(gapp
, +1);
764 case KEY_MINUS
: /* "Grey" minus */
765 if (event
->modifiers
& CONTROL_MODIFIER
) {
766 page_zoom_inout(gapp
, -1);
770 if (event
->modifiers
& CONTROL_MODIFIER
) {
771 page_zoom_inout(gapp
, 0);
777 if (event
->modifiers
& CONTROL_MODIFIER
) {
779 set_cursor(gapp
->gui
, -1);
782 slide_region(gapp
->gui
, ct
.bbox
, x
- last_b1down_x
, y
- last_b1down_y
, FALSE
);
791 if (abort_action
&& xstuff
->collect_points
) {
792 /* clear selection */
793 switch (xstuff
->sel_type
) {
794 case SELECTION_TYPE_RECT
:
795 select_region(gapp
->gui
,
796 x
, y
, last_b1down_x
, last_b1down_y
, FALSE
);
798 case SELECTION_TYPE_VERT
:
799 select_vregion(gapp
->gui
, x
, last_b1down_x
, FALSE
);
801 case SELECTION_TYPE_HORZ
:
802 select_hregion(gapp
->gui
, y
, last_b1down_y
, FALSE
);
807 xstuff
->collect_points
= FALSE
;
808 set_cursor(gapp
->gui
, -1);
809 set_left_footer(NULL
);
812 /* previous action */
814 if (xstuff
->npoints_requested
&&
815 xstuff
->npoints
== xstuff
->npoints_requested
) {
818 VPoint
*vps
= xmalloc(xstuff
->npoints
*sizeof(VPoint
));
819 for (i
= 0; i
< xstuff
->npoints
; i
++) {
820 XPoint xp
= xstuff
->xps
[i
];
821 x11_dev2VPoint(xp
.x
, xp
.y
, &vps
[i
]);
823 /* return points to caller */
824 ret
= xstuff
->point_sink(xstuff
->npoints
, vps
, xstuff
->sink_data
);
825 if (ret
!= RETURN_SUCCESS
) {
831 xstuff
->npoints_requested
= 0;
832 xstuff
->collect_points
= FALSE
;
834 set_cursor(gapp
->gui
, -1);
836 snapshot_and_update(gapp
->gp
, TRUE
);
840 static int hook(Quark
*q
, void *udata
, QTraverseClosure
*closure
)
842 if (quark_fid_get(q
) == QFlavorGraph
) {
843 Quark
*pr
= get_parent_project(q
);
844 VPoint
*vp
= (VPoint
*) udata
;
847 closure
->descend
= FALSE
;
849 if (quark_is_active(q
) == TRUE
&&
850 graph_get_viewport(q
, &v
) == RETURN_SUCCESS
&&
851 is_vpoint_inside(&v
, vp
, 0.0) == TRUE
&&
852 graph_get_current(pr
) != q
) {
853 switch_current_graph(q
);
857 if (quark_fid_get(q
) == QFlavorFrame
&& !quark_is_active(q
)) {
858 closure
->descend
= FALSE
;
865 * Given the graph quark, find the (non-hidden) graph that contains
868 Quark
*next_graph_containing(Quark
*q
, VPoint
*vp
)
870 Quark
*pr
= get_parent_project(q
);
872 quark_traverse(pr
, hook
, vp
);
874 return graph_get_current(pr
);
878 * locator on main_panel
880 void update_locator_lab(Quark
*cg
, VPoint
*vpp
)
882 static VPoint vp
= {0.0, 0.0};
891 if (quark_is_active(cg
) == TRUE
&&
892 graph_get_viewport(cg
, &v
) == RETURN_SUCCESS
&&
893 is_vpoint_inside(&v
, &vp
, 0.0) == TRUE
&&
894 (locator
= graph_get_locator(cg
)) != NULL
&&
895 locator
->type
!= GLOCATOR_TYPE_NONE
) {
896 char bufx
[64], bufy
[64], *s
, *prefix
, *sx
, *sy
;
898 double wx
, wy
, xtmp
, ytmp
;
900 Vpoint2Wpoint(cg
, &vp
, &wp
);
904 if (locator
->pointset
) {
905 wx
-= locator
->origin
.x
;
906 wy
-= locator
->origin
.y
;
912 switch (locator
->type
) {
913 case GLOCATOR_TYPE_XY
:
919 case GLOCATOR_TYPE_POLAR
:
920 xy2polar(wx
, wy
, &xtmp
, &ytmp
);
927 s
= create_fstring(get_parent_project(cg
),
928 &locator
->fx
, xtmp
, LFORMAT_TYPE_PLAIN
);
930 s
= create_fstring(get_parent_project(cg
),
931 &locator
->fy
, ytmp
, LFORMAT_TYPE_PLAIN
);
934 sprintf(buf
, "%s: %s%s, %s%s = (%s, %s)", QIDSTR(cg
),
935 prefix
, sx
, prefix
, sy
, bufx
, bufy
);
937 sprintf(buf
, "VX, VY = (%.4f, %.4f)", vp
.x
, vp
.y
);
940 set_tracker_string(buf
);
943 void switch_current_graph(Quark
*gr
)
946 if (quark_is_active(gr
)) {
947 GraceApp
*gapp
= gapp_from_quark(gr
);
948 Quark
*cg
= graph_get_current(gproject_get_top(gapp
->gp
));
954 graph_set_selectors(gr
);
955 update_locator_lab(cg
, NULL
);
959 static int zoom_sink(unsigned int npoints
, const VPoint
*vps
, void *data
)
961 GraceApp
*gapp
= (GraceApp
*) data
;
963 Quark
*cg
= graph_get_current(gproject_get_top(gapp
->gp
));
966 if (!cg
|| npoints
!= 2) {
967 return RETURN_FAILURE
;
970 Vpoint2Wpoint(cg
, &vps
[0], &wp
);
973 Vpoint2Wpoint(cg
, &vps
[1], &wp
);
978 fswap(&w
.xg1
, &w
.xg2
);
981 fswap(&w
.yg1
, &w
.yg2
);
984 return graph_set_world(cg
, &w
);
987 static int zoomx_sink(unsigned int npoints
, const VPoint
*vps
, void *data
)
989 GraceApp
*gapp
= (GraceApp
*) data
;
991 Quark
*cg
= graph_get_current(gproject_get_top(gapp
->gp
));
994 if (!cg
|| npoints
!= 2) {
995 return RETURN_FAILURE
;
998 graph_get_world(cg
, &w
);
1000 Vpoint2Wpoint(cg
, &vps
[0], &wp
);
1002 Vpoint2Wpoint(cg
, &vps
[1], &wp
);
1005 if (w
.xg1
> w
.xg2
) {
1006 fswap(&w
.xg1
, &w
.xg2
);
1009 return graph_set_world(cg
, &w
);
1012 static int zoomy_sink(unsigned int npoints
, const VPoint
*vps
, void *data
)
1014 GraceApp
*gapp
= (GraceApp
*) data
;
1016 Quark
*cg
= graph_get_current(gproject_get_top(gapp
->gp
));
1019 if (!cg
|| npoints
!= 2) {
1020 return RETURN_FAILURE
;
1023 graph_get_world(cg
, &w
);
1025 Vpoint2Wpoint(cg
, &vps
[0], &wp
);
1027 Vpoint2Wpoint(cg
, &vps
[1], &wp
);
1030 if (w
.yg1
> w
.yg2
) {
1031 fswap(&w
.yg1
, &w
.yg2
);
1034 return graph_set_world(cg
, &w
);
1037 static int atext_sink(unsigned int npoints
, const VPoint
*vps
, void *data
)
1039 GraceApp
*gapp
= (GraceApp
*) data
;
1040 Quark
*cg
= graph_get_current(gproject_get_top(gapp
->gp
)), *q
;
1044 if (!cg
|| npoints
!= 1) {
1045 return RETURN_FAILURE
;
1048 if (Vpoint2Wpoint(cg
, &vps
[0], &wp
) == RETURN_SUCCESS
&&
1049 is_validWPoint(cg
, &wp
) == TRUE
) {
1051 ap
.x
= wp
.x
; ap
.y
= wp
.y
;
1052 atext_set_ap(q
, &ap
);
1054 q
= atext_new(gproject_get_top(gapp
->gp
));
1055 ap
.x
= vps
[0].x
; ap
.y
= vps
[0].y
;
1056 atext_set_ap(q
, &ap
);
1059 raise_explorer(gapp
->gui
, q
);
1061 return RETURN_SUCCESS
;
1064 void set_action(GUI
*gui
, unsigned int npoints
, int seltype
,
1065 CanvasPointSink sink
, void *data
)
1067 X11Stuff
*xstuff
= gui
->xstuff
;
1069 xstuff
->npoints
= 0;
1070 xstuff
->npoints_requested
= npoints
;
1071 xstuff
->point_sink
= sink
;
1072 xstuff
->sink_data
= data
;
1073 xstuff
->sel_type
= seltype
;
1075 xstuff
->collect_points
= TRUE
;
1077 SetFocus(xstuff
->canvas
);
1080 /* -------------------------------------------------------------- */
1081 /* canvas_actions */
1082 void set_zoom_cb(Widget but
, void *data
)
1084 GraceApp
*gapp
= (GraceApp
*) data
;
1085 set_cursor(gapp
->gui
, 0);
1086 set_action(gapp
->gui
, 2, SELECTION_TYPE_RECT
, zoom_sink
, gapp
);
1089 void set_zoomx_cb(Widget but
, void *data
)
1091 GraceApp
*gapp
= (GraceApp
*) data
;
1092 set_cursor(gapp
->gui
, 0);
1093 set_action(gapp
->gui
, 2, SELECTION_TYPE_VERT
, zoomx_sink
, gapp
);
1096 void set_zoomy_cb(Widget but
, void *data
)
1098 GraceApp
*gapp
= (GraceApp
*) data
;
1099 set_cursor(gapp
->gui
, 0);
1100 set_action(gapp
->gui
, 2, SELECTION_TYPE_HORZ
, zoomy_sink
, gapp
);
1104 void atext_add_proc(Widget but
, void *data
)
1106 GraceApp
*gapp
= (GraceApp
*) data
;
1107 set_cursor(gapp
->gui
, 2);
1108 set_action(gapp
->gui
, 1, SELECTION_TYPE_NONE
, atext_sink
, gapp
);
1109 set_left_footer("Select an anchor point");