Created WidgetSetWidth
[grace.git] / src / explorer.c
blobbbe318930f5baa17edac591bb3d33f8cd790ba82
1 /*
2 * Grace - GRaphing, Advanced Computation and Exploration of data
3 *
4 * Home page: http://plasma-gate.weizmann.ac.il/Grace/
5 *
6 * Copyright (c) 2002-2005 Grace Development Team
7 *
8 * Maintained by Evgeny Stambulchik
9 *
11 * All Rights Reserved
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.
28 #include <config.h>
30 #include "globals.h"
31 #include "utils.h"
32 #include "explorer.h"
33 #include "xprotos.h"
34 #include "files.h"
35 #include "qbitmaps.h"
37 static void manage_plugin(ExplorerUI *ui, Widget managed_top)
39 if (managed_top == ui->project_ui->top) {
40 WidgetManage(ui->project_ui->top);
41 } else {
42 WidgetUnmanage(ui->project_ui->top);
44 if (managed_top == ui->ssd_ui->top) {
45 WidgetManage(ui->ssd_ui->top);
46 } else {
47 WidgetUnmanage(ui->ssd_ui->top);
49 if (managed_top == ui->frame_ui->top) {
50 WidgetManage(ui->frame_ui->top);
51 } else {
52 WidgetUnmanage(ui->frame_ui->top);
54 if (managed_top == ui->graph_ui->top) {
55 WidgetManage(ui->graph_ui->top);
56 } else {
57 WidgetUnmanage(ui->graph_ui->top);
59 if (managed_top == ui->set_ui->top) {
60 WidgetManage(ui->set_ui->top);
61 } else {
62 WidgetUnmanage(ui->set_ui->top);
64 if (managed_top == ui->axisgrid_ui->top) {
65 WidgetManage(ui->axisgrid_ui->top);
66 } else {
67 WidgetUnmanage(ui->axisgrid_ui->top);
69 if (managed_top == ui->axis_ui->top) {
70 WidgetManage(ui->axis_ui->top);
71 } else {
72 WidgetUnmanage(ui->axis_ui->top);
74 if (managed_top == ui->object_ui->top) {
75 WidgetManage(ui->object_ui->top);
76 } else {
77 WidgetUnmanage(ui->object_ui->top);
79 if (managed_top == ui->atext_ui->top) {
80 WidgetManage(ui->atext_ui->top);
81 } else {
82 WidgetUnmanage(ui->atext_ui->top);
84 if (managed_top == ui->region_ui->top) {
85 WidgetManage(ui->region_ui->top);
86 } else {
87 WidgetUnmanage(ui->region_ui->top);
91 static int highlight_cb(TreeEvent *event)
93 ExplorerUI *ui = (ExplorerUI *) event->anydata;
94 TreeItemList items;
95 int count;
96 Quark *q = NULL;
97 int fid = -1;
98 int parent_fid = -1;
99 int homogeneous_selection = TRUE;
101 TreeGetHighlighted(event->w, &items);
102 count = items.count;
104 ui->homogeneous_parent = TRUE;
106 if (count > 0) {
107 int i;
109 q = TreeGetQuark(items.items[0]);
110 fid = quark_fid_get(q);
111 parent_fid = quark_fid_get(quark_parent_get(q));
113 for (i = 1; i < count; i++) {
114 Quark *iq = TreeGetQuark(items.items[i]);
116 if ((int) quark_fid_get(iq) != fid) {
117 homogeneous_selection = FALSE;
119 if ((int) quark_fid_get(quark_parent_get(iq)) != parent_fid) {
120 ui->homogeneous_parent = FALSE;
124 xfree(items.items);
126 if (!count || !homogeneous_selection) {
127 WidgetSetSensitive(ui->aacbuts[0], FALSE);
128 WidgetSetSensitive(ui->aacbuts[1], FALSE);
130 manage_plugin(ui, NULL);
131 } else {
132 Widget managed_top;
134 WidgetSetSensitive(ui->aacbuts[0], TRUE);
135 WidgetSetSensitive(ui->aacbuts[1], TRUE);
137 switch (fid) {
138 case QFlavorProject:
139 update_project_ui(ui->project_ui, q);
140 managed_top = ui->project_ui->top;
141 break;
142 case QFlavorSSD:
143 update_ssd_ui(ui->ssd_ui, q);
144 managed_top = ui->ssd_ui->top;
145 break;
146 case QFlavorFrame:
147 update_frame_ui(ui->frame_ui, q);
148 managed_top = ui->frame_ui->top;
149 break;
150 case QFlavorGraph:
151 update_graph_ui(ui->graph_ui, q);
152 managed_top = ui->graph_ui->top;
153 break;
154 case QFlavorSet:
155 update_set_ui(ui->set_ui, q);
156 managed_top = ui->set_ui->top;
157 break;
158 case QFlavorAGrid:
159 update_axisgrid_ui(ui->axisgrid_ui, q);
160 managed_top = ui->axisgrid_ui->top;
161 break;
162 case QFlavorAxis:
163 update_axis_ui(ui->axis_ui, q);
164 managed_top = ui->axis_ui->top;
165 break;
166 case QFlavorDObject:
167 update_object_ui(ui->object_ui, q);
168 managed_top = ui->object_ui->top;
169 break;
170 case QFlavorAText:
171 update_atext_ui(ui->atext_ui, q);
172 managed_top = ui->atext_ui->top;
173 break;
174 case QFlavorRegion:
175 update_region_ui(ui->region_ui, q);
176 managed_top = ui->region_ui->top;
177 break;
178 default:
179 managed_top = NULL;
180 break;
183 manage_plugin(ui, managed_top);
186 WidgetSetSensitive(ui->insert_frame_bt, FALSE);
187 WidgetSetSensitive(ui->insert_graph_bt, FALSE);
188 WidgetSetSensitive(ui->insert_set_bt, FALSE);
189 WidgetSetSensitive(ui->insert_ssd_bt, FALSE);
190 WidgetSetSensitive(ui->insert_axisgrid_bt, FALSE);
191 WidgetSetSensitive(ui->insert_axis_bt, FALSE);
192 WidgetSetSensitive(ui->insert_object_pane, FALSE);
193 if (count == 1) {
194 WidgetSetSensitive(ui->idstr->form, TRUE);
195 TextSetString(ui->idstr, QIDSTR(q));
196 switch (fid) {
197 case QFlavorProject:
198 WidgetSetSensitive(ui->insert_frame_bt, TRUE);
199 WidgetSetSensitive(ui->insert_object_pane, TRUE);
200 break;
201 case QFlavorFrame:
202 WidgetSetSensitive(ui->insert_graph_bt, TRUE);
203 WidgetSetSensitive(ui->insert_object_pane, TRUE);
204 break;
205 case QFlavorGraph:
206 WidgetSetSensitive(ui->insert_ssd_bt, TRUE);
207 WidgetSetSensitive(ui->insert_axisgrid_bt, TRUE);
208 WidgetSetSensitive(ui->insert_object_pane, TRUE);
209 break;
210 case QFlavorAGrid:
211 WidgetSetSensitive(ui->insert_axis_bt, TRUE);
212 break;
213 case QFlavorAxis:
214 WidgetSetSensitive(ui->insert_object_pane, TRUE);
215 break;
218 if (get_parent_ssd(q) &&
219 (fid == QFlavorGraph || fid == QFlavorSSD)) {
220 WidgetSetSensitive(ui->insert_set_bt, TRUE);
222 } else {
223 WidgetSetSensitive(ui->idstr->form, FALSE);
224 TextSetString(ui->idstr, NULL);
227 return TRUE;
231 static int menu_cb(TreeEvent *event)
233 ExplorerUI *ui = (ExplorerUI *) event->anydata;
234 TreeItemList items;
235 int count;
236 Quark *q = NULL;
237 Quark *p = NULL;
238 int parent_child_selection = FALSE;
239 int all_shown = TRUE;
240 int all_hidden = TRUE;
242 TreeGetHighlighted(event->w, &items);
243 count = items.count;
245 if (count > 0) {
246 int i, j;
248 q = TreeGetQuark(items.items[0]);
250 for (i = 0; i < count; i++) {
251 Quark *iq = TreeGetQuark(items.items[i]);
253 p = quark_parent_get(iq);
254 while (p) {
255 for (j = 0; j < count; j++) {
256 if (TreeGetQuark(items.items[j]) == p) {
257 parent_child_selection = TRUE;
260 p = quark_parent_get(p);
263 if (quark_is_active(iq)) {
264 all_hidden = FALSE;
265 } else {
266 all_shown = FALSE;
270 if (count == 1 && quark_fid_get(q) == QFlavorProject) {
271 WidgetSetSensitive(ui->project_popup_show_bt, FALSE);
272 WidgetSetSensitive(ui->project_popup_save_bt, FALSE);
273 WidgetSetSensitive(ui->project_popup_save_as_bt, FALSE);
274 WidgetSetSensitive(ui->project_popup_revert_to_saved_bt, FALSE);
275 WidgetSetSensitive(ui->project_popup_close_bt, FALSE);
277 if (quark_is_active(q)) {
278 WidgetSetSensitive(ui->project_popup_show_bt, FALSE);
279 } else {
280 WidgetSetSensitive(ui->project_popup_show_bt, TRUE);
283 WidgetSetSensitive(ui->project_popup_save_bt, TRUE);
284 WidgetSetSensitive(ui->project_popup_save_as_bt, TRUE);
285 WidgetSetSensitive(ui->project_popup_revert_to_saved_bt, TRUE);
287 if (gapp->gpcount > 1) {
288 WidgetSetSensitive(ui->project_popup_close_bt, TRUE);
289 } else {
290 WidgetSetSensitive(ui->project_popup_close_bt, FALSE);
293 PopupMenuShow(ui->project_popup, event->udata);
294 } else {
295 WidgetSetSensitive(ui->popup_hide_bt, !all_hidden);
296 WidgetSetSensitive(ui->popup_show_bt, !all_shown);
298 if (parent_child_selection) {
299 WidgetSetSensitive(ui->popup_delete_bt, FALSE);
300 WidgetSetSensitive(ui->popup_duplicate_bt, FALSE);
301 } else {
302 WidgetSetSensitive(ui->popup_delete_bt, TRUE);
303 WidgetSetSensitive(ui->popup_duplicate_bt, TRUE);
306 PopupMenuShow(ui->popup, event->udata);
310 xfree(items.items);
312 return TRUE;
315 static void explorer_snapshot(GraceApp *gapp, GProject *gp, int all)
317 if (gp == gapp->gp) {
318 snapshot_and_update(gp, all);
319 } else {
320 amem_snapshot(quark_get_amem(gproject_get_top(gp)));
324 static void add_to_list(GProject **gplist, int *gpcount, GProject *gp)
326 int i, add = TRUE;
328 for (i = 0; i < *gpcount; i++) {
329 if (gp == gplist[i]) {
330 add = FALSE;
334 if (add) {
335 gplist[*gpcount] = gp;
336 (*gpcount)++;
340 static int drop_cb(TreeEvent *event)
342 ExplorerUI *ui = (ExplorerUI *) event->anydata;
344 int gpcount = 0;
345 GProject **gplist;
347 if (ui->homogeneous_parent) {
348 int count;
349 TreeItemList items;
351 TreeGetHighlighted(ui->tree, &items);
352 count = items.count;
353 if (count > 0) {
354 TreeItem *item = (TreeItem *) event->udata;
355 Quark *drop_q = TreeGetQuark(item);
356 Quark *drop_parent = quark_parent_get(drop_q);
357 GProject *drop_gp = gproject_from_quark(drop_q);
358 Quark *parent = quark_parent_get(TreeGetQuark(items.items[0]));
360 gplist = xmalloc(gapp->gpcount*sizeof(GProject));
361 if (!gplist) {
362 return FALSE;
365 if (parent) {
366 int i, id;
367 Quark *newparent;
369 if (quark_fid_get(parent) == quark_fid_get(drop_q)) {
370 id = 0;
371 newparent = drop_q;
372 } else if (quark_fid_get(parent) == quark_fid_get(drop_parent)) {
373 id = quark_get_id(drop_q) + 1;
374 newparent = quark_parent_get(drop_q);
375 } else {
376 return FALSE;
379 for (i = 0; i < count; i++) {
380 Quark *q = TreeGetQuark(items.items[i]);
382 switch (event->drop_action) {
383 case DROP_ACTION_COPY:
384 quark_copy2(q, newparent, id);
385 break;
386 case DROP_ACTION_MOVE:
387 add_to_list(gplist, &gpcount, gproject_from_quark(q));
388 quark_move2(q, newparent, id);
389 break;
390 default:
391 errmsg("unknown drop type");
392 break;
396 switch (event->drop_action) {
397 case DROP_ACTION_COPY:
398 explorer_snapshot(gapp, drop_gp, TRUE);
399 break;
400 case DROP_ACTION_MOVE:
401 add_to_list(gplist, &gpcount, drop_gp);
402 for (i = 0; i < gpcount; i++) {
403 explorer_snapshot(gapp, gplist[i], TRUE);
405 xfree(gplist);
406 break;
409 return TRUE;
413 return FALSE;
416 static void init_item(ExplorerUI *eui, TreeItem *item, Quark *q)
418 int active;
419 char *s;
421 s = q_labeling(q);
422 TreeSetItemText(eui->tree, item, s);
423 xfree(s);
425 active = quark_is_active(q);
427 if (active && quark_count_children(q) > 0) {
428 TreeSetItemOpen(eui->tree, item, TRUE);
429 } else {
430 if (quark_fid_get(q) != QFlavorProject) {
431 TreeSetItemOpen(eui->tree, item, FALSE);
435 if (active) {
436 TreeSetItemPixmap(eui->tree, item, eui->a_icon);
437 } else {
438 TreeSetItemPixmap(eui->tree, item, eui->h_icon);
442 static int create_hook(Quark *q, void *udata, QTraverseClosure *closure)
444 TreeItem *item;
445 ExplorerUI *eui = (ExplorerUI *) udata;
446 Quark *qparent = quark_parent_get(q);
448 item = TreeInsertItem(eui->tree, quark_get_udata(qparent), q, quark_get_id(q));
450 init_item(eui, item, q);
452 quark_set_udata(q, item);
454 return TRUE;
457 static int nsquarks;
458 static Quark **squarks;
460 static void explorer_save_quark_state(ExplorerUI *eui)
462 int i;
463 TreeItemList items;
465 TreeGetHighlighted(eui->tree, &items);
466 nsquarks = items.count;
468 squarks = xmalloc(nsquarks*SIZEOF_VOID_P);
470 for (i = 0; i < nsquarks; i++) {
471 TreeItem *item = items.items[i];
472 squarks[i] = TreeGetQuark(item);
475 xfree(items.items);
478 static void explorer_restore_quark_state(ExplorerUI *eui)
480 int i;
482 for (i = 0; i < nsquarks; i++) {
483 TreeItem *item = quark_get_udata(squarks[i]);
484 TreeHighlightItem(eui->tree, item);
487 xfree(squarks);
490 static int create_children_hook(unsigned int step, void *data, void *udata)
492 ExplorerUI *eui = (ExplorerUI *) udata;
493 Quark *q = (Quark *) data;
495 quark_traverse(q, create_hook, eui);
497 return TRUE;
500 static int explorer_cb(Quark *q, int etype, void *udata)
502 ExplorerUI *eui = (ExplorerUI *) udata;
503 TreeItem *item = quark_get_udata(q);
504 TreeItem *parent_item;
506 switch (etype) {
507 case QUARK_ETYPE_DELETE:
508 TreeDeleteItem(eui->tree, item);
509 break;
510 case QUARK_ETYPE_MODIFY:
511 init_item(eui, item, q);
512 break;
513 case QUARK_ETYPE_NEW:
514 create_hook(q, eui, NULL);
515 break;
516 case QUARK_ETYPE_MOVE:
517 explorer_save_quark_state(eui);
518 TreeDeleteItem(eui->tree, item);
520 parent_item = quark_get_udata(quark_parent_get(q));
521 item = TreeInsertItem(eui->tree, parent_item, q, quark_get_id(q));
522 init_item(eui, item, q);
523 quark_set_udata(q, item);
524 storage_traverse(quark_get_children(q), create_children_hook, eui);
526 explorer_restore_quark_state(eui);
527 break;
530 TreeRefresh(eui->tree);
532 return TRUE;
535 static void init_quark_tree(ExplorerUI *eui)
537 storage_traverse(quark_get_children(gapp->pc), create_children_hook, eui);
538 quark_cb_add(gapp->pc, explorer_cb, eui);
539 TreeRefresh(eui->tree);
542 static void select_quark_explorer(Quark *q)
544 GUI *gui = gui_from_quark(q);
546 if (gui->eui) {
547 TreeItem *item = quark_get_udata(q);
549 TreeClearSelection(gui->eui->tree);
550 TreeHighlightItem(gui->eui->tree, item);
551 TreeScrollToItem(gui->eui->tree, item);
555 static int explorer_apply(ExplorerUI *ui, void *caller)
557 TreeItemList items;
558 int count, i, res = RETURN_SUCCESS;
560 int gpcount = 0;
561 GProject **gplist;
563 if (caller && !GetToggleButtonState(ui->instantupdate)) {
564 return RETURN_FAILURE;
567 TreeGetHighlighted(ui->tree, &items);
568 count = items.count;
570 if (!count) {
571 xfree(items.items);
572 return RETURN_FAILURE;
575 gplist = xmalloc(gapp->gpcount*sizeof(GProject));
576 if (!gplist) {
577 return RETURN_FAILURE;
580 for (i = 0; i < count && res == RETURN_SUCCESS; i++) {
581 Quark *q = TreeGetQuark(items.items[i]);
583 add_to_list(gplist, &gpcount, gproject_from_quark(q));
585 if (count == 1 && (!caller || caller == ui->idstr)) {
586 char *s = TextGetString(ui->idstr);
587 quark_idstr_set(q, s);
588 xfree(s);
591 switch (quark_fid_get(q)) {
592 case QFlavorProject:
593 if (set_project_data(ui->project_ui, q, caller) != RETURN_SUCCESS) {
594 res = RETURN_FAILURE;
596 break;
597 case QFlavorSSD:
598 if (set_ssd_data(ui->ssd_ui, q, caller) != RETURN_SUCCESS) {
599 res = RETURN_FAILURE;
601 break;
602 case QFlavorFrame:
603 if (set_frame_data(ui->frame_ui, q, caller) != RETURN_SUCCESS) {
604 res = RETURN_FAILURE;
606 break;
607 case QFlavorGraph:
608 if (graph_set_data(ui->graph_ui, q, caller) != RETURN_SUCCESS) {
609 res = RETURN_FAILURE;
611 break;
612 case QFlavorSet:
613 if (set_set_data(ui->set_ui, q, caller) != RETURN_SUCCESS) {
614 res = RETURN_FAILURE;
616 break;
617 case QFlavorAGrid:
618 if (set_axisgrid_data(ui->axisgrid_ui, q, caller) != RETURN_SUCCESS) {
619 res = RETURN_FAILURE;
621 break;
622 case QFlavorAxis:
623 if (set_axis_data(ui->axis_ui, q, caller) != RETURN_SUCCESS) {
624 res = RETURN_FAILURE;
626 break;
627 case QFlavorDObject:
628 if (set_object_data(ui->object_ui, q, caller) != RETURN_SUCCESS) {
629 res = RETURN_FAILURE;
631 break;
632 case QFlavorAText:
633 if (set_atext_data(ui->atext_ui, q, caller) != RETURN_SUCCESS) {
634 res = RETURN_FAILURE;
636 break;
637 case QFlavorRegion:
638 if (set_region_data(ui->region_ui, q, caller) != RETURN_SUCCESS) {
639 res = RETURN_FAILURE;
641 break;
642 default:
643 res = RETURN_FAILURE;
644 break;
647 xfree(items.items);
649 for (i = 0; i < gpcount; i++) {
650 explorer_snapshot(gapp, gplist[i], FALSE);
652 xfree(gplist);
654 return res;
657 static int explorer_aac(void *data)
659 ExplorerUI *ui = (ExplorerUI *) data;
661 return explorer_apply(ui, NULL);
664 void explorer_before_undo(GraceApp *gapp, Quark *pr)
666 ExplorerUI *eui = gapp->gui->eui;
668 if (!eui) {
669 return;
672 explorer_save_quark_state(eui);
673 TreeDeleteItem(eui->tree, quark_get_udata(pr));
676 void explorer_after_undo(GraceApp *gapp, Quark *pr)
678 ExplorerUI *eui = gapp->gui->eui;
680 if (!eui) {
681 return;
684 quark_traverse(pr, create_hook, eui);
685 explorer_restore_quark_state(eui);
689 #define HIDE_CB 0
690 #define SHOW_CB 1
691 #define DELETE_CB 2
692 #define DUPLICATE_CB 3
693 #define ADD_FRAME_CB 4
694 #define ADD_GRAPH_CB 5
695 #define ADD_SSD_CB 6
696 #define ADD_SET_CB 7
697 #define ADD_AXISGRID_CB 8
698 #define ADD_AXIS_CB 9
699 #define ADD_LINE_CB 10
700 #define ADD_BOX_CB 11
701 #define ADD_ARC_CB 12
702 #define ADD_TEXT_CB 13
704 static void popup_any_cb(ExplorerUI *eui, int type)
706 TreeItemList items;
707 int count, i;
708 Quark *qnew = NULL;
709 Quark *q;
710 GProject *gp;
712 int gpcount = 0;
713 GProject **gplist;
715 TreeGetHighlighted(eui->tree, &items);
716 count = items.count;
718 if (!count) {
719 xfree(items.items);
720 return;
723 gplist = xmalloc(gapp->gpcount*sizeof(GProject));
724 if (!gplist) {
725 return;
728 for (i = 0; i < count; i++) {
730 q = TreeGetQuark(items.items[i]);
731 gp = gproject_from_quark(q);
732 add_to_list(gplist, &gpcount, gp);
734 switch (type) {
735 case HIDE_CB:
736 quark_set_active(q, FALSE);
737 break;
738 case SHOW_CB:
739 quark_set_active(q, TRUE);
740 break;
741 case DELETE_CB:
742 quark_free(q);
743 break;
744 case DUPLICATE_CB:
745 quark_copy(q);
746 break;
747 case ADD_FRAME_CB:
748 qnew = frame_new(q);
749 break;
750 case ADD_GRAPH_CB:
751 qnew = graph_new(q);
752 break;
753 case ADD_SSD_CB:
754 qnew = gapp_ssd_new(q);
755 break;
756 case ADD_SET_CB:
757 qnew = gapp_set_new(q);
758 break;
759 case ADD_AXISGRID_CB:
760 qnew = axisgrid_new(q);
761 break;
762 case ADD_AXIS_CB:
763 qnew = axis_new(q);
764 break;
765 case ADD_LINE_CB:
766 qnew = object_new_complete(q, DO_LINE);
767 break;
768 case ADD_BOX_CB:
769 qnew = object_new_complete(q, DO_BOX);
770 break;
771 case ADD_ARC_CB:
772 qnew = object_new_complete(q, DO_ARC);
773 break;
774 case ADD_TEXT_CB:
775 qnew = atext_new(q);
776 break;
779 xfree(items.items);
781 for (i = 0; i < gpcount; i++) {
782 explorer_snapshot(gapp, gplist[i], TRUE);
784 xfree(gplist);
786 if (qnew) {
787 select_quark_explorer(qnew);
791 static void hide_cb(Widget but, void *udata)
793 popup_any_cb((ExplorerUI *) udata, HIDE_CB);
796 static void show_cb(Widget but, void *udata)
798 popup_any_cb((ExplorerUI *) udata, SHOW_CB);
801 static void delete_cb(Widget but, void *udata)
803 if (yesno("Really delete selected item(s)?", NULL, NULL, NULL)) {
804 popup_any_cb((ExplorerUI *) udata, DELETE_CB);
808 static void duplicate_cb(Widget but, void *udata)
810 popup_any_cb((ExplorerUI *) udata, DUPLICATE_CB);
813 static void add_frame_cb(Widget but, void *udata)
815 popup_any_cb((ExplorerUI *) udata, ADD_FRAME_CB);
818 static void add_graph_cb(Widget but, void *udata)
820 popup_any_cb((ExplorerUI *) udata, ADD_GRAPH_CB);
823 static void add_ssd_cb(Widget but, void *udata)
825 popup_any_cb((ExplorerUI *) udata, ADD_SSD_CB);
828 static void add_set_cb(Widget but, void *udata)
830 popup_any_cb((ExplorerUI *) udata, ADD_SET_CB);
833 static void add_axisgrid_cb(Widget but, void *udata)
835 popup_any_cb((ExplorerUI *) udata, ADD_AXISGRID_CB);
838 static void add_axis_cb(Widget but, void *udata)
840 popup_any_cb((ExplorerUI *) udata, ADD_AXIS_CB);
843 static void add_object_cb(Widget but, void *udata)
845 ExplorerUI *eui = (ExplorerUI *) udata;
846 if (but == eui->insert_line_bt) {
847 popup_any_cb(eui, ADD_LINE_CB);
848 } else
849 if (but == eui->insert_box_bt) {
850 popup_any_cb(eui, ADD_BOX_CB);
851 } else
852 if (but == eui->insert_arc_bt) {
853 popup_any_cb(eui, ADD_ARC_CB);
854 } else
855 if (but == eui->insert_text_bt) {
856 popup_any_cb(eui, ADD_TEXT_CB);
860 #define PROJECT_SHOW_CB 0
861 #define PROJECT_SAVE_CB 1
862 #define PROJECT_SAVE_AS_CB 2
863 #define PROJECT_REVERT_TO_SAVED_CB 3
864 #define PROJECT_CLOSE_CB 4
866 static void project_popup_any_cb(ExplorerUI *eui, int type)
868 TreeItemList items;
869 Quark *q;
870 GraceApp *gapp;
871 GProject *gp;
873 TreeGetHighlighted(eui->tree, &items);
875 if (!items.count || items.count > 1) {
876 xfree(items.items);
877 return;
880 q = TreeGetQuark(items.items[0]);
881 gapp = gapp_from_quark(q);
882 gp = gproject_from_quark(q);
884 switch (type) {
885 case PROJECT_SHOW_CB:
886 gapp_set_active_gproject(gapp, gp);
887 xdrawgraph(gp);
888 update_all();
889 break;
890 case PROJECT_SAVE_CB:
891 project_save(gp);
892 break;
893 case PROJECT_SAVE_AS_CB:
894 project_save_as(gp);
895 break;
896 case PROJECT_REVERT_TO_SAVED_CB:
897 revert_project(gapp, gp);
898 xdrawgraph(gapp->gp);
899 update_all();
900 break;
901 case PROJECT_CLOSE_CB:
902 if (gapp->gpcount == 1) {
903 errmsg("Can't close the last project");
904 return;
907 if (gp && gproject_get_top(gp) &&
908 quark_dirtystate_get(gproject_get_top(gp)) &&
909 !yesno("Abandon unsaved changes?", NULL, NULL, NULL)) {
910 return;
913 gapp_delete_gproject(gapp, gp);
915 if (gapp->gp == NULL) {
916 gapp_set_active_gproject(gapp, gapp->gplist[0]);
919 xdrawgraph(gapp->gp);
920 update_all();
921 break;
924 xfree(items.items);
927 static void project_show_cb(Widget but, void *udata)
929 project_popup_any_cb((ExplorerUI *) udata, PROJECT_SHOW_CB);
932 static void project_save_cb(Widget but, void *udata)
934 project_popup_any_cb((ExplorerUI *) udata, PROJECT_SAVE_CB);
937 static void project_save_as_cb(Widget but, void *udata)
939 project_popup_any_cb((ExplorerUI *) udata, PROJECT_SAVE_AS_CB);
942 static void project_revert_to_saved_cb(Widget but, void *udata)
944 project_popup_any_cb((ExplorerUI *) udata, PROJECT_REVERT_TO_SAVED_CB);
947 static void project_close_cb(Widget but, void *udata)
949 project_popup_any_cb((ExplorerUI *) udata, PROJECT_CLOSE_CB);
952 void raise_explorer(GUI *gui, Quark *q)
954 GraceApp *gapp = gui->P;
956 set_wait_cursor();
958 if (!gui->eui) {
959 ExplorerUI *eui;
960 Widget menubar, menupane, panel, form, fr;
962 eui = xmalloc(sizeof(ExplorerUI));
963 gui->eui = eui;
965 eui->a_icon = XpmToPixmap(active_xpm);
966 eui->h_icon = XpmToPixmap(hidden_xpm);
968 eui->top = CreateDialog(app_shell, "Explorer");
969 menubar = CreateMenuBar(eui->top);
970 WidgetManage(menubar);
971 FormAddVChild(eui->top, menubar);
973 menupane = CreateMenu(menubar, "File", 'F', FALSE);
974 CreateMenuButtonA(menupane, "Close", 'C', "<Key>Escape", "Esc", destroy_dialog_cb, eui->top);
976 menupane = CreateMenu(menubar, "Edit", 'E', FALSE);
977 eui->edit_undo_bt = CreateMenuButtonA(menupane, "Undo", 'U', "Ctrl<Key>z", "Ctrl+Z",
978 undo_cb, gapp);
979 eui->edit_redo_bt = CreateMenuButtonA(menupane, "Redo", 'R', "Ctrl Shift<Key>z", "Ctrl+Shift+Z",
980 redo_cb, gapp);
982 menupane = CreateMenu(menubar, "Insert", 'I', FALSE);
983 eui->insert_frame_bt = CreateMenuButton(menupane,
984 "Frame", '\0', add_frame_cb, eui);
985 WidgetSetSensitive(eui->insert_frame_bt, FALSE);
986 eui->insert_graph_bt = CreateMenuButton(menupane,
987 "Graph", '\0', add_graph_cb, eui);
988 WidgetSetSensitive(eui->insert_graph_bt, FALSE);
989 eui->insert_ssd_bt = CreateMenuButton(menupane,
990 "SSData", '\0', add_ssd_cb, eui);
991 WidgetSetSensitive(eui->insert_ssd_bt, FALSE);
992 eui->insert_set_bt = CreateMenuButton(menupane,
993 "Set", '\0', add_set_cb, eui);
994 WidgetSetSensitive(eui->insert_set_bt, FALSE);
995 eui->insert_axisgrid_bt = CreateMenuButton(menupane,
996 "Axis grid", '\0', add_axisgrid_cb, eui);
997 WidgetSetSensitive(eui->insert_axisgrid_bt, FALSE);
998 eui->insert_axis_bt = CreateMenuButton(menupane,
999 "Axis", '\0', add_axis_cb, eui);
1000 WidgetSetSensitive(eui->insert_axis_bt, FALSE);
1001 eui->insert_object_pane = CreateMenu(menupane, "Annotating objects", 'o', FALSE);
1002 WidgetSetSensitive(eui->insert_object_pane, FALSE);
1003 eui->insert_text_bt = CreateMenuButton(eui->insert_object_pane,
1004 "Text", '\0', add_object_cb, eui);
1005 eui->insert_line_bt = CreateMenuButton(eui->insert_object_pane,
1006 "Line", '\0', add_object_cb, eui);
1007 eui->insert_box_bt = CreateMenuButton(eui->insert_object_pane,
1008 "Box", '\0', add_object_cb, eui);
1009 eui->insert_arc_bt = CreateMenuButton(eui->insert_object_pane,
1010 "Arc", '\0', add_object_cb, eui);
1012 menupane = CreateMenu(menubar, "Options", 'O', FALSE);
1013 eui->instantupdate = CreateMenuToggle(menupane, "Instantaneous update",
1014 'u', NULL, NULL);
1015 SetToggleButtonState(eui->instantupdate, gui->instant_update);
1017 menupane = CreateMenu(menubar, "Help", 'H', TRUE);
1018 CreateMenuHelpButton(menupane, "On explorer", 'e',
1019 eui->top, "doc/UsersGuide.html#explorer");
1021 panel = CreatePanedWindow(eui->top);
1023 form = CreateForm(panel);
1024 PlaceGridChild(panel, form, 0, 0); /* in case if CreatePanedWindow creates a grid */
1026 eui->tree = CreateTree(form);
1027 AddTreeHighlightItemsCB(eui->tree, highlight_cb, eui);
1028 AddTreeContextMenuCB(eui->tree, menu_cb, eui);
1029 AddTreeDropItemsCB(eui->tree, drop_cb, eui);
1030 FormAddVChild(form, eui->tree);
1032 fr = CreateFrame(form, NULL);
1033 eui->idstr = CreateText(fr, "ID string:");
1034 AddTextActivateCB(eui->idstr, text_explorer_cb, eui);
1035 FormAddVChild(form, fr);
1036 FormFixateVChild(fr);
1038 eui->scrolled_window = CreateScrolledWindow(panel);
1039 PlaceGridChild(panel, eui->scrolled_window, 1, 0); /* in case if CreatePanedWindow creates a grid */
1041 PanedWindowSetMinWidth(form, 150);
1042 WidgetSetWidth(form, 250);
1044 WidgetManage(form);
1046 #ifdef HAVE_LESSTIF
1047 # if !defined(SF_BUG_993209_FIXED) && !defined(SF_BUG_993209_NOT_FIXED)
1048 # error "You should check whether SF bug #993209 is fixed in your version of LessTif."
1049 # error "Then define either SF_BUG_993209_FIXED or SF_BUG_993209_NOT_FIXED, accordingly."
1050 # error "See http://sourceforge.net/tracker/index.php?func=detail&aid=993209&group_id=8596&atid=108596."
1051 # endif
1052 # ifdef SF_BUG_993209_NOT_FIXED
1053 /* A dirty workaround */
1054 eui->scrolled_window = CreateVContainer(eui->scrolled_window);
1055 # endif
1056 #endif
1058 eui->project_ui = create_project_ui(eui);
1059 WidgetUnmanage(eui->project_ui->top);
1061 eui->ssd_ui = create_ssd_ui(eui);
1062 WidgetUnmanage(eui->ssd_ui->top);
1064 eui->frame_ui = create_frame_ui(eui);
1065 WidgetUnmanage(eui->frame_ui->top);
1067 eui->graph_ui = create_graph_ui(eui);
1068 WidgetUnmanage(eui->graph_ui->top);
1070 eui->set_ui = create_set_ui(eui);
1071 WidgetUnmanage(eui->set_ui->top);
1073 eui->axisgrid_ui = create_axisgrid_ui(eui);
1074 WidgetUnmanage(eui->axisgrid_ui->top);
1076 eui->axis_ui = create_axis_ui(eui);
1077 WidgetUnmanage(eui->axis_ui->top);
1079 eui->object_ui = create_object_ui(eui);
1080 WidgetUnmanage(eui->object_ui->top);
1082 eui->atext_ui = create_atext_ui(eui);
1083 WidgetUnmanage(eui->atext_ui->top);
1085 eui->region_ui = create_region_ui(eui);
1086 WidgetUnmanage(eui->region_ui->top);
1088 eui->aacbuts = CreateAACDialog(eui->top, panel, explorer_aac, eui);
1090 WidgetManage(eui->tree);
1092 /* Menu popup */
1093 eui->popup = CreatePopupMenu(eui->tree);
1094 eui->popup_hide_bt = CreateMenuButton(eui->popup,
1095 "Hide", '\0', hide_cb, eui);
1096 eui->popup_show_bt = CreateMenuButton(eui->popup,
1097 "Show", '\0', show_cb, eui);
1099 CreateMenuSeparator(eui->popup);
1101 eui->popup_delete_bt = CreateMenuButton(eui->popup,
1102 "Delete", '\0', delete_cb, eui);
1103 eui->popup_duplicate_bt = CreateMenuButton(eui->popup,
1104 "Duplicate", '\0', duplicate_cb, eui);
1106 /* Project menu popup */
1107 eui->project_popup = CreatePopupMenu(eui->tree);
1108 eui->project_popup_show_bt = CreateMenuButton(eui->project_popup,
1109 "Show", '\0', project_show_cb, eui);
1111 CreateMenuSeparator(eui->project_popup);
1113 eui->project_popup_save_bt = CreateMenuButton(eui->project_popup,
1114 "Save", '\0', project_save_cb, eui);
1115 eui->project_popup_save_as_bt = CreateMenuButton(eui->project_popup,
1116 "Save as...", '\0', project_save_as_cb, eui);
1117 eui->project_popup_revert_to_saved_bt = CreateMenuButton(eui->project_popup,
1118 "Revert to saved", '\0', project_revert_to_saved_cb, eui);
1120 CreateMenuSeparator(eui->project_popup);
1122 eui->project_popup_close_bt = CreateMenuButton(eui->project_popup,
1123 "Close", '\0', project_close_cb, eui);
1125 init_quark_tree(eui);
1127 if (!q && gapp->gp) {
1128 select_quark_explorer(gproject_get_top(gapp->gp));
1131 #ifdef QT_GUI
1132 /* TODO: use resources */
1133 WidgetSetSize(gui->eui->top, 650, 600);
1134 #endif
1135 DialogRaise(gui->eui->top);
1137 if (q) {
1138 select_quark_explorer(q);
1141 update_undo_buttons(gapp->gp);
1143 unset_wait_cursor();
1146 void define_explorer_popup(Widget but, void *data)
1148 GUI *gui = (GUI *) data;
1149 raise_explorer(gui, NULL);
1153 void oc_explorer_cb(OptionStructure *opt, int a, void *data)
1155 ExplorerUI *eui = (ExplorerUI *) data;
1156 explorer_apply(eui, opt);
1158 void tb_explorer_cb(Widget but, int a, void *data)
1160 ExplorerUI *eui = (ExplorerUI *) data;
1161 explorer_apply(eui, but);
1163 void scale_explorer_cb(Widget scale, int a, void *data)
1165 ExplorerUI *eui = (ExplorerUI *) data;
1166 explorer_apply(eui, scale);
1168 void sp_explorer_cb(SpinStructure *spinp, double a, void *data)
1170 ExplorerUI *eui = (ExplorerUI *) data;
1171 explorer_apply(eui, spinp);
1173 void text_explorer_cb(TextStructure *cst, char *s, void *data)
1175 ExplorerUI *eui = (ExplorerUI *) data;
1176 explorer_apply(eui, cst);
1178 void pen_explorer_cb(Widget but, const Pen *pen, void *data)
1180 ExplorerUI *eui = (ExplorerUI *) data;
1181 explorer_apply(eui, but);
1183 void format_explorer_cb(FormatStructure *fstr, const Format *format, void *data)
1185 ExplorerUI *eui = (ExplorerUI *) data;
1186 explorer_apply(eui, fstr);