WidgetSetMinWidth -> PanedWindowSetMinWidth
[grace.git] / src / explorer.c
bloba80d2e01504a61a8a55f02b4fac17f10bfb0055e
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"
36 static void manage_plugin(ExplorerUI *ui, Widget managed_top)
38 if (managed_top == ui->project_ui->top) {
39 WidgetManage(ui->project_ui->top);
40 } else {
41 WidgetUnmanage(ui->project_ui->top);
43 if (managed_top == ui->ssd_ui->top) {
44 WidgetManage(ui->ssd_ui->top);
45 } else {
46 WidgetUnmanage(ui->ssd_ui->top);
48 if (managed_top == ui->frame_ui->top) {
49 WidgetManage(ui->frame_ui->top);
50 } else {
51 WidgetUnmanage(ui->frame_ui->top);
53 if (managed_top == ui->graph_ui->top) {
54 WidgetManage(ui->graph_ui->top);
55 } else {
56 WidgetUnmanage(ui->graph_ui->top);
58 if (managed_top == ui->set_ui->top) {
59 WidgetManage(ui->set_ui->top);
60 } else {
61 WidgetUnmanage(ui->set_ui->top);
63 if (managed_top == ui->axisgrid_ui->top) {
64 WidgetManage(ui->axisgrid_ui->top);
65 } else {
66 WidgetUnmanage(ui->axisgrid_ui->top);
68 if (managed_top == ui->axis_ui->top) {
69 WidgetManage(ui->axis_ui->top);
70 } else {
71 WidgetUnmanage(ui->axis_ui->top);
73 if (managed_top == ui->object_ui->top) {
74 WidgetManage(ui->object_ui->top);
75 } else {
76 WidgetUnmanage(ui->object_ui->top);
78 if (managed_top == ui->atext_ui->top) {
79 WidgetManage(ui->atext_ui->top);
80 } else {
81 WidgetUnmanage(ui->atext_ui->top);
83 if (managed_top == ui->region_ui->top) {
84 WidgetManage(ui->region_ui->top);
85 } else {
86 WidgetUnmanage(ui->region_ui->top);
90 static int highlight_cb(TreeEvent *event)
92 ExplorerUI *ui = (ExplorerUI *) event->anydata;
93 TreeItemList items;
94 int count;
95 Quark *q = NULL;
96 int fid = -1;
97 int parent_fid = -1;
98 int homogeneous_selection = TRUE;
100 TreeGetHighlighted(event->w, &items);
101 count = items.count;
103 ui->homogeneous_parent = TRUE;
105 if (count > 0) {
106 int i;
108 q = TreeGetQuark(items.items[0]);
109 fid = quark_fid_get(q);
110 parent_fid = quark_fid_get(quark_parent_get(q));
112 for (i = 1; i < count; i++) {
113 Quark *iq = TreeGetQuark(items.items[i]);
115 if ((int) quark_fid_get(iq) != fid) {
116 homogeneous_selection = FALSE;
118 if ((int) quark_fid_get(quark_parent_get(iq)) != parent_fid) {
119 ui->homogeneous_parent = FALSE;
123 xfree(items.items);
125 if (!count || !homogeneous_selection) {
126 WidgetSetSensitive(ui->aacbuts[0], FALSE);
127 WidgetSetSensitive(ui->aacbuts[1], FALSE);
129 manage_plugin(ui, NULL);
130 } else {
131 Widget managed_top;
133 WidgetSetSensitive(ui->aacbuts[0], TRUE);
134 WidgetSetSensitive(ui->aacbuts[1], TRUE);
136 switch (fid) {
137 case QFlavorProject:
138 update_project_ui(ui->project_ui, q);
139 managed_top = ui->project_ui->top;
140 break;
141 case QFlavorSSD:
142 update_ssd_ui(ui->ssd_ui, q);
143 managed_top = ui->ssd_ui->top;
144 break;
145 case QFlavorFrame:
146 update_frame_ui(ui->frame_ui, q);
147 managed_top = ui->frame_ui->top;
148 break;
149 case QFlavorGraph:
150 update_graph_ui(ui->graph_ui, q);
151 managed_top = ui->graph_ui->top;
152 break;
153 case QFlavorSet:
154 update_set_ui(ui->set_ui, q);
155 managed_top = ui->set_ui->top;
156 break;
157 case QFlavorAGrid:
158 update_axisgrid_ui(ui->axisgrid_ui, q);
159 managed_top = ui->axisgrid_ui->top;
160 break;
161 case QFlavorAxis:
162 update_axis_ui(ui->axis_ui, q);
163 managed_top = ui->axis_ui->top;
164 break;
165 case QFlavorDObject:
166 update_object_ui(ui->object_ui, q);
167 managed_top = ui->object_ui->top;
168 break;
169 case QFlavorAText:
170 update_atext_ui(ui->atext_ui, q);
171 managed_top = ui->atext_ui->top;
172 break;
173 case QFlavorRegion:
174 update_region_ui(ui->region_ui, q);
175 managed_top = ui->region_ui->top;
176 break;
177 default:
178 managed_top = NULL;
179 break;
182 manage_plugin(ui, managed_top);
185 WidgetSetSensitive(ui->insert_frame_bt, FALSE);
186 WidgetSetSensitive(ui->insert_graph_bt, FALSE);
187 WidgetSetSensitive(ui->insert_set_bt, FALSE);
188 WidgetSetSensitive(ui->insert_ssd_bt, FALSE);
189 WidgetSetSensitive(ui->insert_axisgrid_bt, FALSE);
190 WidgetSetSensitive(ui->insert_axis_bt, FALSE);
191 WidgetSetSensitive(ui->insert_object_pane, FALSE);
192 if (count == 1) {
193 WidgetSetSensitive(ui->idstr->form, TRUE);
194 TextSetString(ui->idstr, QIDSTR(q));
195 switch (fid) {
196 case QFlavorProject:
197 WidgetSetSensitive(ui->insert_frame_bt, TRUE);
198 WidgetSetSensitive(ui->insert_object_pane, TRUE);
199 break;
200 case QFlavorFrame:
201 WidgetSetSensitive(ui->insert_graph_bt, TRUE);
202 WidgetSetSensitive(ui->insert_object_pane, TRUE);
203 break;
204 case QFlavorGraph:
205 WidgetSetSensitive(ui->insert_ssd_bt, TRUE);
206 WidgetSetSensitive(ui->insert_axisgrid_bt, TRUE);
207 WidgetSetSensitive(ui->insert_object_pane, TRUE);
208 break;
209 case QFlavorAGrid:
210 WidgetSetSensitive(ui->insert_axis_bt, TRUE);
211 break;
212 case QFlavorAxis:
213 WidgetSetSensitive(ui->insert_object_pane, TRUE);
214 break;
217 if (get_parent_ssd(q) &&
218 (fid == QFlavorGraph || fid == QFlavorSSD)) {
219 WidgetSetSensitive(ui->insert_set_bt, TRUE);
221 } else {
222 WidgetSetSensitive(ui->idstr->form, FALSE);
223 TextSetString(ui->idstr, NULL);
226 return TRUE;
230 static int menu_cb(TreeEvent *event)
232 ExplorerUI *ui = (ExplorerUI *) event->anydata;
233 TreeItemList items;
234 int count;
235 Quark *q = NULL;
236 Quark *p = NULL;
237 int parent_child_selection = FALSE;
238 int all_shown = TRUE;
239 int all_hidden = TRUE;
241 TreeGetHighlighted(event->w, &items);
242 count = items.count;
244 if (count > 0) {
245 int i, j;
247 q = TreeGetQuark(items.items[0]);
249 for (i = 0; i < count; i++) {
250 Quark *iq = TreeGetQuark(items.items[i]);
252 p = quark_parent_get(iq);
253 while (p) {
254 for (j = 0; j < count; j++) {
255 if (TreeGetQuark(items.items[j]) == p) {
256 parent_child_selection = TRUE;
259 p = quark_parent_get(p);
262 if (quark_is_active(iq)) {
263 all_hidden = FALSE;
264 } else {
265 all_shown = FALSE;
269 if (count == 1 && quark_fid_get(q) == QFlavorProject) {
270 WidgetSetSensitive(ui->project_popup_show_bt, FALSE);
271 WidgetSetSensitive(ui->project_popup_save_bt, FALSE);
272 WidgetSetSensitive(ui->project_popup_save_as_bt, FALSE);
273 WidgetSetSensitive(ui->project_popup_revert_to_saved_bt, FALSE);
274 WidgetSetSensitive(ui->project_popup_close_bt, FALSE);
276 if (quark_is_active(q)) {
277 WidgetSetSensitive(ui->project_popup_show_bt, FALSE);
278 } else {
279 WidgetSetSensitive(ui->project_popup_show_bt, TRUE);
282 WidgetSetSensitive(ui->project_popup_save_bt, TRUE);
283 WidgetSetSensitive(ui->project_popup_save_as_bt, TRUE);
284 WidgetSetSensitive(ui->project_popup_revert_to_saved_bt, TRUE);
286 if (gapp->gpcount > 1) {
287 WidgetSetSensitive(ui->project_popup_close_bt, TRUE);
288 } else {
289 WidgetSetSensitive(ui->project_popup_close_bt, FALSE);
292 ShowMenu(ui->project_popup, event->udata);
293 } else {
294 WidgetSetSensitive(ui->popup_hide_bt, !all_hidden);
295 WidgetSetSensitive(ui->popup_show_bt, !all_shown);
297 if (parent_child_selection) {
298 WidgetSetSensitive(ui->popup_delete_bt, FALSE);
299 WidgetSetSensitive(ui->popup_duplicate_bt, FALSE);
300 } else {
301 WidgetSetSensitive(ui->popup_delete_bt, TRUE);
302 WidgetSetSensitive(ui->popup_duplicate_bt, TRUE);
305 ShowMenu(ui->popup, event->udata);
309 xfree(items.items);
311 return TRUE;
314 static void explorer_snapshot(GraceApp *gapp, GProject *gp, int all)
316 if (gp == gapp->gp) {
317 snapshot_and_update(gp, all);
318 } else {
319 amem_snapshot(quark_get_amem(gproject_get_top(gp)));
323 static void add_to_list(GProject **gplist, int *gpcount, GProject *gp)
325 int i, add = TRUE;
327 for (i = 0; i < *gpcount; i++) {
328 if (gp == gplist[i]) {
329 add = FALSE;
333 if (add) {
334 gplist[*gpcount] = gp;
335 (*gpcount)++;
339 static int drop_cb(TreeEvent *event)
341 ExplorerUI *ui = (ExplorerUI *) event->anydata;
343 int gpcount = 0;
344 GProject **gplist;
346 if (ui->homogeneous_parent) {
347 int count;
348 TreeItemList items;
350 TreeGetHighlighted(ui->tree, &items);
351 count = items.count;
352 if (count > 0) {
353 TreeItem *item = (TreeItem *) event->udata;
354 Quark *drop_q = TreeGetQuark(item);
355 Quark *drop_parent = quark_parent_get(drop_q);
356 GProject *drop_gp = gproject_from_quark(drop_q);
357 Quark *parent = quark_parent_get(TreeGetQuark(items.items[0]));
359 gplist = xmalloc(gapp->gpcount*sizeof(GProject));
360 if (!gplist) {
361 return FALSE;
364 if (parent) {
365 int i, id;
366 Quark *newparent;
368 if (quark_fid_get(parent) == quark_fid_get(drop_q)) {
369 id = 0;
370 newparent = drop_q;
371 } else if (quark_fid_get(parent) == quark_fid_get(drop_parent)) {
372 id = quark_get_id(drop_q) + 1;
373 newparent = quark_parent_get(drop_q);
374 } else {
375 return FALSE;
378 for (i = 0; i < count; i++) {
379 Quark *q = TreeGetQuark(items.items[i]);
381 switch (event->drop_action) {
382 case DROP_ACTION_COPY:
383 quark_copy2(q, newparent, id);
384 break;
385 case DROP_ACTION_MOVE:
386 add_to_list(gplist, &gpcount, gproject_from_quark(q));
387 quark_move2(q, newparent, id);
388 break;
389 default:
390 errmsg("unknown drop type");
391 break;
395 switch (event->drop_action) {
396 case DROP_ACTION_COPY:
397 explorer_snapshot(gapp, drop_gp, TRUE);
398 break;
399 case DROP_ACTION_MOVE:
400 add_to_list(gplist, &gpcount, drop_gp);
401 for (i = 0; i < gpcount; i++) {
402 explorer_snapshot(gapp, gplist[i], TRUE);
404 xfree(gplist);
405 break;
408 return TRUE;
412 return FALSE;
415 static void init_item(ExplorerUI *eui, TreeItem *item, Quark *q)
417 int active;
418 char *s;
420 s = q_labeling(q);
421 TreeSetItemText(eui->tree, item, s);
422 xfree(s);
424 active = quark_is_active(q);
426 if (active && quark_count_children(q) > 0) {
427 TreeSetItemOpen(eui->tree, item, TRUE);
428 } else {
429 if (quark_fid_get(q) != QFlavorProject) {
430 TreeSetItemOpen(eui->tree, item, FALSE);
434 if (active) {
435 TreeSetItemPixmap(eui->tree, item, eui->a_icon);
436 } else {
437 TreeSetItemPixmap(eui->tree, item, eui->h_icon);
441 static int create_hook(Quark *q, void *udata, QTraverseClosure *closure)
443 TreeItem *item;
444 ExplorerUI *eui = (ExplorerUI *) udata;
445 Quark *qparent = quark_parent_get(q);
447 item = TreeInsertItem(eui->tree, quark_get_udata(qparent), q, quark_get_id(q));
449 init_item(eui, item, q);
451 quark_set_udata(q, item);
453 return TRUE;
456 static int nsquarks;
457 static Quark **squarks;
459 static void explorer_save_quark_state(ExplorerUI *eui)
461 int i;
462 TreeItemList items;
464 TreeGetHighlighted(eui->tree, &items);
465 nsquarks = items.count;
467 squarks = xmalloc(nsquarks*SIZEOF_VOID_P);
469 for (i = 0; i < nsquarks; i++) {
470 TreeItem *item = items.items[i];
471 squarks[i] = TreeGetQuark(item);
474 xfree(items.items);
477 static void explorer_restore_quark_state(ExplorerUI *eui)
479 int i;
481 for (i = 0; i < nsquarks; i++) {
482 TreeItem *item = quark_get_udata(squarks[i]);
483 TreeHighlightItem(eui->tree, item);
486 xfree(squarks);
489 static int create_children_hook(unsigned int step, void *data, void *udata)
491 ExplorerUI *eui = (ExplorerUI *) udata;
492 Quark *q = (Quark *) data;
494 quark_traverse(q, create_hook, eui);
496 return TRUE;
499 static int explorer_cb(Quark *q, int etype, void *udata)
501 ExplorerUI *eui = (ExplorerUI *) udata;
502 TreeItem *item = quark_get_udata(q);
503 TreeItem *parent_item;
505 switch (etype) {
506 case QUARK_ETYPE_DELETE:
507 TreeDeleteItem(eui->tree, item);
508 break;
509 case QUARK_ETYPE_MODIFY:
510 init_item(eui, item, q);
511 break;
512 case QUARK_ETYPE_NEW:
513 create_hook(q, eui, NULL);
514 break;
515 case QUARK_ETYPE_MOVE:
516 explorer_save_quark_state(eui);
517 TreeDeleteItem(eui->tree, item);
519 parent_item = quark_get_udata(quark_parent_get(q));
520 item = TreeInsertItem(eui->tree, parent_item, q, quark_get_id(q));
521 init_item(eui, item, q);
522 quark_set_udata(q, item);
523 storage_traverse(quark_get_children(q), create_children_hook, eui);
525 explorer_restore_quark_state(eui);
526 break;
529 TreeRefresh(eui->tree);
531 return TRUE;
534 static void init_quark_tree(ExplorerUI *eui)
536 storage_traverse(quark_get_children(gapp->pc), create_children_hook, eui);
537 quark_cb_add(gapp->pc, explorer_cb, eui);
538 TreeRefresh(eui->tree);
541 static void select_quark_explorer(Quark *q)
543 GUI *gui = gui_from_quark(q);
545 if (gui->eui) {
546 TreeItem *item = quark_get_udata(q);
548 TreeClearSelection(gui->eui->tree);
549 TreeHighlightItem(gui->eui->tree, item);
550 TreeScrollToItem(gui->eui->tree, item);
554 static int explorer_apply(ExplorerUI *ui, void *caller)
556 TreeItemList items;
557 int count, i, res = RETURN_SUCCESS;
559 int gpcount = 0;
560 GProject **gplist;
562 if (caller && !GetToggleButtonState(ui->instantupdate)) {
563 return RETURN_FAILURE;
566 TreeGetHighlighted(ui->tree, &items);
567 count = items.count;
569 if (!count) {
570 xfree(items.items);
571 return RETURN_FAILURE;
574 gplist = xmalloc(gapp->gpcount*sizeof(GProject));
575 if (!gplist) {
576 return RETURN_FAILURE;
579 for (i = 0; i < count && res == RETURN_SUCCESS; i++) {
580 Quark *q = TreeGetQuark(items.items[i]);
582 add_to_list(gplist, &gpcount, gproject_from_quark(q));
584 if (count == 1 && (!caller || caller == ui->idstr)) {
585 char *s = TextGetString(ui->idstr);
586 quark_idstr_set(q, s);
587 xfree(s);
590 switch (quark_fid_get(q)) {
591 case QFlavorProject:
592 if (set_project_data(ui->project_ui, q, caller) != RETURN_SUCCESS) {
593 res = RETURN_FAILURE;
595 break;
596 case QFlavorSSD:
597 if (set_ssd_data(ui->ssd_ui, q, caller) != RETURN_SUCCESS) {
598 res = RETURN_FAILURE;
600 break;
601 case QFlavorFrame:
602 if (set_frame_data(ui->frame_ui, q, caller) != RETURN_SUCCESS) {
603 res = RETURN_FAILURE;
605 break;
606 case QFlavorGraph:
607 if (graph_set_data(ui->graph_ui, q, caller) != RETURN_SUCCESS) {
608 res = RETURN_FAILURE;
610 break;
611 case QFlavorSet:
612 if (set_set_data(ui->set_ui, q, caller) != RETURN_SUCCESS) {
613 res = RETURN_FAILURE;
615 break;
616 case QFlavorAGrid:
617 if (set_axisgrid_data(ui->axisgrid_ui, q, caller) != RETURN_SUCCESS) {
618 res = RETURN_FAILURE;
620 break;
621 case QFlavorAxis:
622 if (set_axis_data(ui->axis_ui, q, caller) != RETURN_SUCCESS) {
623 res = RETURN_FAILURE;
625 break;
626 case QFlavorDObject:
627 if (set_object_data(ui->object_ui, q, caller) != RETURN_SUCCESS) {
628 res = RETURN_FAILURE;
630 break;
631 case QFlavorAText:
632 if (set_atext_data(ui->atext_ui, q, caller) != RETURN_SUCCESS) {
633 res = RETURN_FAILURE;
635 break;
636 case QFlavorRegion:
637 if (set_region_data(ui->region_ui, q, caller) != RETURN_SUCCESS) {
638 res = RETURN_FAILURE;
640 break;
641 default:
642 res = RETURN_FAILURE;
643 break;
646 xfree(items.items);
648 for (i = 0; i < gpcount; i++) {
649 explorer_snapshot(gapp, gplist[i], FALSE);
651 xfree(gplist);
653 return res;
656 static int explorer_aac(void *data)
658 ExplorerUI *ui = (ExplorerUI *) data;
660 return explorer_apply(ui, NULL);
663 void explorer_before_undo(GraceApp *gapp, Quark *pr)
665 ExplorerUI *eui = gapp->gui->eui;
667 if (!eui) {
668 return;
671 explorer_save_quark_state(eui);
672 TreeDeleteItem(eui->tree, quark_get_udata(pr));
675 void explorer_after_undo(GraceApp *gapp, Quark *pr)
677 ExplorerUI *eui = gapp->gui->eui;
679 if (!eui) {
680 return;
683 quark_traverse(pr, create_hook, eui);
684 explorer_restore_quark_state(eui);
688 #define HIDE_CB 0
689 #define SHOW_CB 1
690 #define DELETE_CB 2
691 #define DUPLICATE_CB 3
692 #define ADD_FRAME_CB 4
693 #define ADD_GRAPH_CB 5
694 #define ADD_SSD_CB 6
695 #define ADD_SET_CB 7
696 #define ADD_AXISGRID_CB 8
697 #define ADD_AXIS_CB 9
698 #define ADD_LINE_CB 10
699 #define ADD_BOX_CB 11
700 #define ADD_ARC_CB 12
701 #define ADD_TEXT_CB 13
703 static void popup_any_cb(ExplorerUI *eui, int type)
705 TreeItemList items;
706 int count, i;
707 Quark *qnew = NULL;
708 Quark *q;
709 GProject *gp;
711 int gpcount = 0;
712 GProject **gplist;
714 TreeGetHighlighted(eui->tree, &items);
715 count = items.count;
717 if (!count) {
718 xfree(items.items);
719 return;
722 gplist = xmalloc(gapp->gpcount*sizeof(GProject));
723 if (!gplist) {
724 return;
727 for (i = 0; i < count; i++) {
729 q = TreeGetQuark(items.items[i]);
730 gp = gproject_from_quark(q);
731 add_to_list(gplist, &gpcount, gp);
733 switch (type) {
734 case HIDE_CB:
735 quark_set_active(q, FALSE);
736 break;
737 case SHOW_CB:
738 quark_set_active(q, TRUE);
739 break;
740 case DELETE_CB:
741 quark_free(q);
742 break;
743 case DUPLICATE_CB:
744 quark_copy(q);
745 break;
746 case ADD_FRAME_CB:
747 qnew = frame_new(q);
748 break;
749 case ADD_GRAPH_CB:
750 qnew = graph_new(q);
751 break;
752 case ADD_SSD_CB:
753 qnew = gapp_ssd_new(q);
754 break;
755 case ADD_SET_CB:
756 qnew = gapp_set_new(q);
757 break;
758 case ADD_AXISGRID_CB:
759 qnew = axisgrid_new(q);
760 break;
761 case ADD_AXIS_CB:
762 qnew = axis_new(q);
763 break;
764 case ADD_LINE_CB:
765 qnew = object_new_complete(q, DO_LINE);
766 break;
767 case ADD_BOX_CB:
768 qnew = object_new_complete(q, DO_BOX);
769 break;
770 case ADD_ARC_CB:
771 qnew = object_new_complete(q, DO_ARC);
772 break;
773 case ADD_TEXT_CB:
774 qnew = atext_new(q);
775 break;
778 xfree(items.items);
780 for (i = 0; i < gpcount; i++) {
781 explorer_snapshot(gapp, gplist[i], TRUE);
783 xfree(gplist);
785 if (qnew) {
786 select_quark_explorer(qnew);
790 static void hide_cb(Widget but, void *udata)
792 popup_any_cb((ExplorerUI *) udata, HIDE_CB);
795 static void show_cb(Widget but, void *udata)
797 popup_any_cb((ExplorerUI *) udata, SHOW_CB);
800 static void delete_cb(Widget but, void *udata)
802 if (yesno("Really delete selected item(s)?", NULL, NULL, NULL)) {
803 popup_any_cb((ExplorerUI *) udata, DELETE_CB);
807 static void duplicate_cb(Widget but, void *udata)
809 popup_any_cb((ExplorerUI *) udata, DUPLICATE_CB);
812 static void add_frame_cb(Widget but, void *udata)
814 popup_any_cb((ExplorerUI *) udata, ADD_FRAME_CB);
817 static void add_graph_cb(Widget but, void *udata)
819 popup_any_cb((ExplorerUI *) udata, ADD_GRAPH_CB);
822 static void add_ssd_cb(Widget but, void *udata)
824 popup_any_cb((ExplorerUI *) udata, ADD_SSD_CB);
827 static void add_set_cb(Widget but, void *udata)
829 popup_any_cb((ExplorerUI *) udata, ADD_SET_CB);
832 static void add_axisgrid_cb(Widget but, void *udata)
834 popup_any_cb((ExplorerUI *) udata, ADD_AXISGRID_CB);
837 static void add_axis_cb(Widget but, void *udata)
839 popup_any_cb((ExplorerUI *) udata, ADD_AXIS_CB);
842 static void add_object_cb(Widget but, void *udata)
844 ExplorerUI *eui = (ExplorerUI *) udata;
845 if (but == eui->insert_line_bt) {
846 popup_any_cb(eui, ADD_LINE_CB);
847 } else
848 if (but == eui->insert_box_bt) {
849 popup_any_cb(eui, ADD_BOX_CB);
850 } else
851 if (but == eui->insert_arc_bt) {
852 popup_any_cb(eui, ADD_ARC_CB);
853 } else
854 if (but == eui->insert_text_bt) {
855 popup_any_cb(eui, ADD_TEXT_CB);
859 #define PROJECT_SHOW_CB 0
860 #define PROJECT_SAVE_CB 1
861 #define PROJECT_SAVE_AS_CB 2
862 #define PROJECT_REVERT_TO_SAVED_CB 3
863 #define PROJECT_CLOSE_CB 4
865 static void project_popup_any_cb(ExplorerUI *eui, int type)
867 TreeItemList items;
868 Quark *q;
869 GraceApp *gapp;
870 GProject *gp;
872 TreeGetHighlighted(eui->tree, &items);
874 if (!items.count || items.count > 1) {
875 xfree(items.items);
876 return;
879 q = TreeGetQuark(items.items[0]);
880 gapp = gapp_from_quark(q);
881 gp = gproject_from_quark(q);
883 switch (type) {
884 case PROJECT_SHOW_CB:
885 gapp_set_active_gproject(gapp, gp);
886 xdrawgraph(gp);
887 update_all();
888 break;
889 case PROJECT_SAVE_CB:
890 project_save(gp);
891 break;
892 case PROJECT_SAVE_AS_CB:
893 project_save_as(gp);
894 break;
895 case PROJECT_REVERT_TO_SAVED_CB:
896 revert_project(gapp, gp);
897 xdrawgraph(gapp->gp);
898 update_all();
899 break;
900 case PROJECT_CLOSE_CB:
901 if (gapp->gpcount == 1) {
902 errmsg("Can't close the last project");
903 return;
906 if (gp && gproject_get_top(gp) &&
907 quark_dirtystate_get(gproject_get_top(gp)) &&
908 !yesno("Abandon unsaved changes?", NULL, NULL, NULL)) {
909 return;
912 gapp_delete_gproject(gapp, gp);
914 if (gapp->gp == NULL) {
915 gapp_set_active_gproject(gapp, gapp->gplist[0]);
918 xdrawgraph(gapp->gp);
919 update_all();
920 break;
923 xfree(items.items);
926 static void project_show_cb(Widget but, void *udata)
928 project_popup_any_cb((ExplorerUI *) udata, PROJECT_SHOW_CB);
931 static void project_save_cb(Widget but, void *udata)
933 project_popup_any_cb((ExplorerUI *) udata, PROJECT_SAVE_CB);
936 static void project_save_as_cb(Widget but, void *udata)
938 project_popup_any_cb((ExplorerUI *) udata, PROJECT_SAVE_AS_CB);
941 static void project_revert_to_saved_cb(Widget but, void *udata)
943 project_popup_any_cb((ExplorerUI *) udata, PROJECT_REVERT_TO_SAVED_CB);
946 static void project_close_cb(Widget but, void *udata)
948 project_popup_any_cb((ExplorerUI *) udata, PROJECT_CLOSE_CB);
951 void raise_explorer(GUI *gui, Quark *q)
953 GraceApp *gapp = gui->P;
955 set_wait_cursor();
957 if (!gui->eui) {
958 ExplorerUI *eui;
959 Widget menubar, menupane, panel, form, fr;
961 eui = xmalloc(sizeof(ExplorerUI));
962 gui->eui = eui;
964 /* Create pixmaps */
965 CreatePixmaps(eui);
967 eui->top = CreateDialog(app_shell, "Explorer");
968 menubar = CreateMenuBar(eui->top);
969 WidgetManage(menubar);
970 FormAddVChild(eui->top, menubar);
972 menupane = CreateMenu(menubar, "File", 'F', FALSE);
973 CreateMenuButtonA(menupane, "Close", 'C', "<Key>Escape", "Esc", destroy_dialog_cb, eui->top);
975 menupane = CreateMenu(menubar, "Edit", 'E', FALSE);
976 eui->edit_undo_bt = CreateMenuButtonA(menupane, "Undo", 'U', "Ctrl<Key>z", "Ctrl+Z",
977 undo_cb, gapp);
978 eui->edit_redo_bt = CreateMenuButtonA(menupane, "Redo", 'R', "Ctrl Shift<Key>z", "Ctrl+Shift+Z",
979 redo_cb, gapp);
981 menupane = CreateMenu(menubar, "Insert", 'I', FALSE);
982 eui->insert_frame_bt = CreateMenuButton(menupane,
983 "Frame", '\0', add_frame_cb, eui);
984 WidgetSetSensitive(eui->insert_frame_bt, FALSE);
985 eui->insert_graph_bt = CreateMenuButton(menupane,
986 "Graph", '\0', add_graph_cb, eui);
987 WidgetSetSensitive(eui->insert_graph_bt, FALSE);
988 eui->insert_ssd_bt = CreateMenuButton(menupane,
989 "SSData", '\0', add_ssd_cb, eui);
990 WidgetSetSensitive(eui->insert_ssd_bt, FALSE);
991 eui->insert_set_bt = CreateMenuButton(menupane,
992 "Set", '\0', add_set_cb, eui);
993 WidgetSetSensitive(eui->insert_set_bt, FALSE);
994 eui->insert_axisgrid_bt = CreateMenuButton(menupane,
995 "Axis grid", '\0', add_axisgrid_cb, eui);
996 WidgetSetSensitive(eui->insert_axisgrid_bt, FALSE);
997 eui->insert_axis_bt = CreateMenuButton(menupane,
998 "Axis", '\0', add_axis_cb, eui);
999 WidgetSetSensitive(eui->insert_axis_bt, FALSE);
1000 eui->insert_object_pane = CreateMenu(menupane, "Annotating objects", 'o', FALSE);
1001 WidgetSetSensitive(eui->insert_object_pane, FALSE);
1002 eui->insert_text_bt = CreateMenuButton(eui->insert_object_pane,
1003 "Text", '\0', add_object_cb, eui);
1004 eui->insert_line_bt = CreateMenuButton(eui->insert_object_pane,
1005 "Line", '\0', add_object_cb, eui);
1006 eui->insert_box_bt = CreateMenuButton(eui->insert_object_pane,
1007 "Box", '\0', add_object_cb, eui);
1008 eui->insert_arc_bt = CreateMenuButton(eui->insert_object_pane,
1009 "Arc", '\0', add_object_cb, eui);
1011 menupane = CreateMenu(menubar, "Options", 'O', FALSE);
1012 eui->instantupdate = CreateMenuToggle(menupane, "Instantaneous update",
1013 'u', NULL, NULL);
1014 SetToggleButtonState(eui->instantupdate, gui->instant_update);
1016 menupane = CreateMenu(menubar, "Help", 'H', TRUE);
1017 CreateMenuHelpButton(menupane, "On explorer", 'e',
1018 eui->top, "doc/UsersGuide.html#explorer");
1020 panel = CreatePanedWindow(eui->top);
1022 form = CreateForm(panel);
1023 PlaceGridChild(panel, form, 0, 0); /* in case if CreatePanedWindow creates a grid */
1025 eui->tree = CreateTree(form);
1026 AddTreeHighlightItemsCB(eui->tree, highlight_cb, eui);
1027 AddTreeContextMenuCB(eui->tree, menu_cb, eui);
1028 AddTreeDropItemsCB(eui->tree, drop_cb, eui);
1029 FormAddVChild(form, eui->tree);
1031 fr = CreateFrame(form, NULL);
1032 eui->idstr = CreateText(fr, "ID string:");
1033 AddTextActivateCB(eui->idstr, text_explorer_cb, eui);
1034 FormAddVChild(form, fr);
1035 FormFixateVChild(fr);
1037 eui->scrolled_window = CreateScrolledWindow(panel);
1038 PlaceGridChild(panel, eui->scrolled_window, 1, 0); /* in case if CreatePanedWindow creates a grid */
1040 PanedWindowSetMinWidth(form, 150);
1041 WidgetSetSize(form, 250, 0);
1043 WidgetManage(form);
1045 #ifdef HAVE_LESSTIF
1046 # if !defined(SF_BUG_993209_FIXED) && !defined(SF_BUG_993209_NOT_FIXED)
1047 # error "You should check whether SF bug #993209 is fixed in your version of LessTif."
1048 # error "Then define either SF_BUG_993209_FIXED or SF_BUG_993209_NOT_FIXED, accordingly."
1049 # error "See http://sourceforge.net/tracker/index.php?func=detail&aid=993209&group_id=8596&atid=108596."
1050 # endif
1051 # ifdef SF_BUG_993209_NOT_FIXED
1052 /* A dirty workaround */
1053 eui->scrolled_window = CreateVContainer(eui->scrolled_window);
1054 # endif
1055 #endif
1057 eui->project_ui = create_project_ui(eui);
1058 WidgetUnmanage(eui->project_ui->top);
1060 eui->ssd_ui = create_ssd_ui(eui);
1061 WidgetUnmanage(eui->ssd_ui->top);
1063 eui->frame_ui = create_frame_ui(eui);
1064 WidgetUnmanage(eui->frame_ui->top);
1066 eui->graph_ui = create_graph_ui(eui);
1067 WidgetUnmanage(eui->graph_ui->top);
1069 eui->set_ui = create_set_ui(eui);
1070 WidgetUnmanage(eui->set_ui->top);
1072 eui->axisgrid_ui = create_axisgrid_ui(eui);
1073 WidgetUnmanage(eui->axisgrid_ui->top);
1075 eui->axis_ui = create_axis_ui(eui);
1076 WidgetUnmanage(eui->axis_ui->top);
1078 eui->object_ui = create_object_ui(eui);
1079 WidgetUnmanage(eui->object_ui->top);
1081 eui->atext_ui = create_atext_ui(eui);
1082 WidgetUnmanage(eui->atext_ui->top);
1084 eui->region_ui = create_region_ui(eui);
1085 WidgetUnmanage(eui->region_ui->top);
1087 eui->aacbuts = CreateAACDialog(eui->top, panel, explorer_aac, eui);
1089 WidgetManage(eui->tree);
1091 /* Menu popup */
1092 eui->popup = CreatePopupMenu(eui->tree);
1093 eui->popup_hide_bt = CreateMenuButton(eui->popup,
1094 "Hide", '\0', hide_cb, eui);
1095 eui->popup_show_bt = CreateMenuButton(eui->popup,
1096 "Show", '\0', show_cb, eui);
1098 CreateMenuSeparator(eui->popup);
1100 eui->popup_delete_bt = CreateMenuButton(eui->popup,
1101 "Delete", '\0', delete_cb, eui);
1102 eui->popup_duplicate_bt = CreateMenuButton(eui->popup,
1103 "Duplicate", '\0', duplicate_cb, eui);
1105 /* Project menu popup */
1106 eui->project_popup = CreatePopupMenu(eui->tree);
1107 eui->project_popup_show_bt = CreateMenuButton(eui->project_popup,
1108 "Show", '\0', project_show_cb, eui);
1110 CreateMenuSeparator(eui->project_popup);
1112 eui->project_popup_save_bt = CreateMenuButton(eui->project_popup,
1113 "Save", '\0', project_save_cb, eui);
1114 eui->project_popup_save_as_bt = CreateMenuButton(eui->project_popup,
1115 "Save as...", '\0', project_save_as_cb, eui);
1116 eui->project_popup_revert_to_saved_bt = CreateMenuButton(eui->project_popup,
1117 "Revert to saved", '\0', project_revert_to_saved_cb, eui);
1119 CreateMenuSeparator(eui->project_popup);
1121 eui->project_popup_close_bt = CreateMenuButton(eui->project_popup,
1122 "Close", '\0', project_close_cb, eui);
1124 init_quark_tree(eui);
1126 if (!q && gapp->gp) {
1127 select_quark_explorer(gproject_get_top(gapp->gp));
1130 #ifdef QT_GUI
1131 /* TODO: use resources */
1132 WidgetSetSize(gui->eui->top, 650, 600);
1133 #endif
1134 DialogRaise(gui->eui->top);
1136 if (q) {
1137 select_quark_explorer(q);
1140 update_undo_buttons(gapp->gp);
1142 unset_wait_cursor();
1145 void define_explorer_popup(Widget but, void *data)
1147 GUI *gui = (GUI *) data;
1148 raise_explorer(gui, NULL);
1152 void oc_explorer_cb(OptionStructure *opt, int a, void *data)
1154 ExplorerUI *eui = (ExplorerUI *) data;
1155 explorer_apply(eui, opt);
1157 void tb_explorer_cb(Widget but, int a, void *data)
1159 ExplorerUI *eui = (ExplorerUI *) data;
1160 explorer_apply(eui, but);
1162 void scale_explorer_cb(Widget scale, int a, void *data)
1164 ExplorerUI *eui = (ExplorerUI *) data;
1165 explorer_apply(eui, scale);
1167 void sp_explorer_cb(SpinStructure *spinp, double a, void *data)
1169 ExplorerUI *eui = (ExplorerUI *) data;
1170 explorer_apply(eui, spinp);
1172 void text_explorer_cb(TextStructure *cst, char *s, void *data)
1174 ExplorerUI *eui = (ExplorerUI *) data;
1175 explorer_apply(eui, cst);
1177 void pen_explorer_cb(Widget but, const Pen *pen, void *data)
1179 ExplorerUI *eui = (ExplorerUI *) data;
1180 explorer_apply(eui, but);
1182 void format_explorer_cb(FormatStructure *fstr, const Format *format, void *data)
1184 ExplorerUI *eui = (ExplorerUI *) data;
1185 explorer_apply(eui, fstr);