Set set length on assignment.
[grace.git] / src / explorer.c
blob44e742c67885829e1bddfd110203262a55f964cd
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 #ifdef MOTIF_GUI
37 #include <Xm/Form.h>
38 #endif
40 static void manage_plugin(ExplorerUI *ui, Widget managed_top)
42 if (managed_top == ui->project_ui->top) {
43 ManageChild(ui->project_ui->top);
44 } else {
45 UnmanageChild(ui->project_ui->top);
47 if (managed_top == ui->ssd_ui->top) {
48 ManageChild(ui->ssd_ui->top);
49 } else {
50 UnmanageChild(ui->ssd_ui->top);
52 if (managed_top == ui->frame_ui->top) {
53 ManageChild(ui->frame_ui->top);
54 } else {
55 UnmanageChild(ui->frame_ui->top);
57 if (managed_top == ui->graph_ui->top) {
58 ManageChild(ui->graph_ui->top);
59 } else {
60 UnmanageChild(ui->graph_ui->top);
62 if (managed_top == ui->set_ui->top) {
63 ManageChild(ui->set_ui->top);
64 } else {
65 UnmanageChild(ui->set_ui->top);
67 if (managed_top == ui->axisgrid_ui->top) {
68 ManageChild(ui->axisgrid_ui->top);
69 } else {
70 UnmanageChild(ui->axisgrid_ui->top);
72 if (managed_top == ui->axis_ui->top) {
73 ManageChild(ui->axis_ui->top);
74 } else {
75 UnmanageChild(ui->axis_ui->top);
77 if (managed_top == ui->object_ui->top) {
78 ManageChild(ui->object_ui->top);
79 } else {
80 UnmanageChild(ui->object_ui->top);
82 if (managed_top == ui->atext_ui->top) {
83 ManageChild(ui->atext_ui->top);
84 } else {
85 UnmanageChild(ui->atext_ui->top);
87 if (managed_top == ui->region_ui->top) {
88 ManageChild(ui->region_ui->top);
89 } else {
90 UnmanageChild(ui->region_ui->top);
94 static int highlight_cb(TreeEvent *event)
96 ExplorerUI *ui = (ExplorerUI *) event->anydata;
97 TreeItemList items;
98 int count;
99 Quark *q = NULL;
100 int fid = -1;
101 int parent_fid = -1;
102 int homogeneous_selection = TRUE;
104 TreeGetHighlighted(event->w, &items);
105 count = items.count;
107 ui->homogeneous_parent = TRUE;
109 if (count > 0) {
110 int i;
112 q = TreeGetQuark(items.items[0]);
113 fid = quark_fid_get(q);
114 parent_fid = quark_fid_get(quark_parent_get(q));
116 for (i = 1; i < count; i++) {
117 Quark *iq = TreeGetQuark(items.items[i]);
119 if ((int) quark_fid_get(iq) != fid) {
120 homogeneous_selection = FALSE;
122 if ((int) quark_fid_get(quark_parent_get(iq)) != parent_fid) {
123 ui->homogeneous_parent = FALSE;
127 xfree(items.items);
129 if (!count || !homogeneous_selection) {
130 SetSensitive(ui->aacbuts[0], FALSE);
131 SetSensitive(ui->aacbuts[1], FALSE);
133 manage_plugin(ui, NULL);
134 } else {
135 Widget managed_top;
137 SetSensitive(ui->aacbuts[0], TRUE);
138 SetSensitive(ui->aacbuts[1], TRUE);
140 switch (fid) {
141 case QFlavorProject:
142 update_project_ui(ui->project_ui, q);
143 managed_top = ui->project_ui->top;
144 break;
145 case QFlavorSSD:
146 update_ssd_ui(ui->ssd_ui, q);
147 managed_top = ui->ssd_ui->top;
148 break;
149 case QFlavorFrame:
150 update_frame_ui(ui->frame_ui, q);
151 managed_top = ui->frame_ui->top;
152 break;
153 case QFlavorGraph:
154 update_graph_ui(ui->graph_ui, q);
155 managed_top = ui->graph_ui->top;
156 break;
157 case QFlavorSet:
158 update_set_ui(ui->set_ui, q);
159 managed_top = ui->set_ui->top;
160 break;
161 case QFlavorAGrid:
162 update_axisgrid_ui(ui->axisgrid_ui, q);
163 managed_top = ui->axisgrid_ui->top;
164 break;
165 case QFlavorAxis:
166 update_axis_ui(ui->axis_ui, q);
167 managed_top = ui->axis_ui->top;
168 break;
169 case QFlavorDObject:
170 update_object_ui(ui->object_ui, q);
171 managed_top = ui->object_ui->top;
172 break;
173 case QFlavorAText:
174 update_atext_ui(ui->atext_ui, q);
175 managed_top = ui->atext_ui->top;
176 break;
177 case QFlavorRegion:
178 update_region_ui(ui->region_ui, q);
179 managed_top = ui->region_ui->top;
180 break;
181 default:
182 managed_top = NULL;
183 break;
186 manage_plugin(ui, managed_top);
189 SetSensitive(ui->insert_frame_bt, FALSE);
190 SetSensitive(ui->insert_graph_bt, FALSE);
191 SetSensitive(ui->insert_set_bt, FALSE);
192 SetSensitive(ui->insert_ssd_bt, FALSE);
193 SetSensitive(ui->insert_axisgrid_bt, FALSE);
194 SetSensitive(ui->insert_axis_bt, FALSE);
195 SetSensitive(ui->insert_object_pane, FALSE);
196 if (count == 1) {
197 SetSensitive(ui->idstr->form, TRUE);
198 SetTextString(ui->idstr, QIDSTR(q));
199 switch (fid) {
200 case QFlavorProject:
201 SetSensitive(ui->insert_frame_bt, TRUE);
202 SetSensitive(ui->insert_object_pane, TRUE);
203 break;
204 case QFlavorFrame:
205 SetSensitive(ui->insert_graph_bt, TRUE);
206 SetSensitive(ui->insert_object_pane, TRUE);
207 break;
208 case QFlavorGraph:
209 SetSensitive(ui->insert_ssd_bt, TRUE);
210 SetSensitive(ui->insert_axisgrid_bt, TRUE);
211 SetSensitive(ui->insert_object_pane, TRUE);
212 break;
213 case QFlavorAGrid:
214 SetSensitive(ui->insert_axis_bt, TRUE);
215 break;
216 case QFlavorAxis:
217 SetSensitive(ui->insert_object_pane, TRUE);
218 break;
221 if (get_parent_ssd(q) &&
222 (fid == QFlavorGraph || fid == QFlavorSSD)) {
223 SetSensitive(ui->insert_set_bt, TRUE);
225 } else {
226 SetSensitive(ui->idstr->form, FALSE);
227 SetTextString(ui->idstr, NULL);
230 return TRUE;
234 static int menu_cb(TreeEvent *event)
236 ExplorerUI *ui = (ExplorerUI *) event->anydata;
237 TreeItemList items;
238 int count;
239 Quark *q = NULL;
240 Quark *p = NULL;
241 int parent_child_selection = FALSE;
242 int all_shown = TRUE;
243 int all_hidden = TRUE;
245 TreeGetHighlighted(event->w, &items);
246 count = items.count;
248 if (count > 0) {
249 int i, j;
251 q = TreeGetQuark(items.items[0]);
253 for (i = 0; i < count; i++) {
254 Quark *iq = TreeGetQuark(items.items[i]);
256 p = quark_parent_get(iq);
257 while (p) {
258 for (j = 0; j < count; j++) {
259 if (TreeGetQuark(items.items[j]) == p) {
260 parent_child_selection = TRUE;
263 p = quark_parent_get(p);
266 if (quark_is_active(iq)) {
267 all_hidden = FALSE;
268 } else {
269 all_shown = FALSE;
273 if (count == 1 && quark_fid_get(q) == QFlavorProject) {
274 SetSensitive(ui->project_popup_show_bt, FALSE);
275 SetSensitive(ui->project_popup_save_bt, FALSE);
276 SetSensitive(ui->project_popup_save_as_bt, FALSE);
277 SetSensitive(ui->project_popup_revert_to_saved_bt, FALSE);
278 SetSensitive(ui->project_popup_close_bt, FALSE);
280 if (quark_is_active(q)) {
281 SetSensitive(ui->project_popup_show_bt, FALSE);
282 } else {
283 SetSensitive(ui->project_popup_show_bt, TRUE);
286 SetSensitive(ui->project_popup_save_bt, TRUE);
287 SetSensitive(ui->project_popup_save_as_bt, TRUE);
288 SetSensitive(ui->project_popup_revert_to_saved_bt, TRUE);
290 if (gapp->gpcount > 1) {
291 SetSensitive(ui->project_popup_close_bt, TRUE);
292 } else {
293 SetSensitive(ui->project_popup_close_bt, FALSE);
296 ShowMenu(ui->project_popup, event->udata);
297 } else {
298 SetSensitive(ui->popup_hide_bt, !all_hidden);
299 SetSensitive(ui->popup_show_bt, !all_shown);
301 if (parent_child_selection) {
302 SetSensitive(ui->popup_delete_bt, FALSE);
303 SetSensitive(ui->popup_duplicate_bt, FALSE);
304 } else {
305 SetSensitive(ui->popup_delete_bt, TRUE);
306 SetSensitive(ui->popup_duplicate_bt, TRUE);
309 ShowMenu(ui->popup, event->udata);
313 xfree(items.items);
315 return TRUE;
318 static void explorer_snapshot(GraceApp *gapp, GProject *gp, int all)
320 if (gp == gapp->gp) {
321 snapshot_and_update(gp, all);
322 } else {
323 amem_snapshot(quark_get_amem(gproject_get_top(gp)));
327 static void add_to_list(GProject **gplist, int *gpcount, GProject *gp)
329 int i, add = TRUE;
331 for (i = 0; i < *gpcount; i++) {
332 if (gp == gplist[i]) {
333 add = FALSE;
337 if (add) {
338 gplist[*gpcount] = gp;
339 (*gpcount)++;
343 static int drop_cb(TreeEvent *event)
345 ExplorerUI *ui = (ExplorerUI *) event->anydata;
347 int gpcount = 0;
348 GProject **gplist;
350 if (ui->homogeneous_parent) {
351 int count;
352 TreeItemList items;
354 TreeGetHighlighted(ui->tree, &items);
355 count = items.count;
356 if (count > 0) {
357 TreeItem *item = (TreeItem *) event->udata;
358 Quark *drop_q = TreeGetQuark(item);
359 Quark *drop_parent = quark_parent_get(drop_q);
360 GProject *drop_gp = gproject_from_quark(drop_q);
361 Quark *parent = quark_parent_get(TreeGetQuark(items.items[0]));
363 gplist = xmalloc(gapp->gpcount*sizeof(GProject));
364 if (!gplist) {
365 return FALSE;
368 if (parent) {
369 int i, id;
370 Quark *newparent;
372 if (quark_fid_get(parent) == quark_fid_get(drop_q)) {
373 id = 0;
374 newparent = drop_q;
375 } else if (quark_fid_get(parent) == quark_fid_get(drop_parent)) {
376 id = quark_get_id(drop_q) + 1;
377 newparent = quark_parent_get(drop_q);
378 } else {
379 return FALSE;
382 for (i = 0; i < count; i++) {
383 Quark *q = TreeGetQuark(items.items[i]);
385 switch (event->drop_action) {
386 case DROP_ACTION_COPY:
387 quark_copy2(q, newparent, id);
388 break;
389 case DROP_ACTION_MOVE:
390 add_to_list(gplist, &gpcount, gproject_from_quark(q));
391 quark_move2(q, newparent, id);
392 break;
393 default:
394 errmsg("unknown drop type");
395 break;
399 switch (event->drop_action) {
400 case DROP_ACTION_COPY:
401 explorer_snapshot(gapp, drop_gp, TRUE);
402 break;
403 case DROP_ACTION_MOVE:
404 add_to_list(gplist, &gpcount, drop_gp);
405 for (i = 0; i < gpcount; i++) {
406 explorer_snapshot(gapp, gplist[i], TRUE);
408 xfree(gplist);
409 break;
412 return TRUE;
416 return FALSE;
419 static void init_item(ExplorerUI *eui, TreeItem *item, Quark *q)
421 int active;
422 char *s;
424 s = q_labeling(q);
425 TreeSetItemText(eui->tree, item, s);
426 xfree(s);
428 active = quark_is_active(q);
430 if (active && quark_count_children(q) > 0) {
431 TreeSetItemOpen(eui->tree, item, TRUE);
432 } else {
433 if (quark_fid_get(q) != QFlavorProject) {
434 TreeSetItemOpen(eui->tree, item, FALSE);
438 if (active) {
439 TreeSetItemPixmap(eui->tree, item, eui->a_icon);
440 } else {
441 TreeSetItemPixmap(eui->tree, item, eui->h_icon);
445 static int create_hook(Quark *q, void *udata, QTraverseClosure *closure)
447 TreeItem *item;
448 ExplorerUI *eui = (ExplorerUI *) udata;
449 Quark *qparent = quark_parent_get(q);
451 item = TreeInsertItem(eui->tree, quark_get_udata(qparent), q, quark_get_id(q));
453 init_item(eui, item, q);
455 quark_set_udata(q, item);
457 return TRUE;
460 static int nsquarks;
461 static Quark **squarks;
463 static void explorer_save_quark_state(ExplorerUI *eui)
465 int i;
466 TreeItemList items;
468 TreeGetHighlighted(eui->tree, &items);
469 nsquarks = items.count;
471 squarks = xmalloc(nsquarks*SIZEOF_VOID_P);
473 for (i = 0; i < nsquarks; i++) {
474 TreeItem *item = items.items[i];
475 squarks[i] = TreeGetQuark(item);
478 xfree(items.items);
481 static void explorer_restore_quark_state(ExplorerUI *eui)
483 int i;
485 for (i = 0; i < nsquarks; i++) {
486 TreeItem *item = quark_get_udata(squarks[i]);
487 TreeHighlightItem(eui->tree, item);
490 xfree(squarks);
493 static int create_children_hook(unsigned int step, void *data, void *udata)
495 ExplorerUI *eui = (ExplorerUI *) udata;
496 Quark *q = (Quark *) data;
498 quark_traverse(q, create_hook, eui);
500 return TRUE;
503 static int explorer_cb(Quark *q, int etype, void *udata)
505 ExplorerUI *eui = (ExplorerUI *) udata;
506 TreeItem *item = quark_get_udata(q);
507 TreeItem *parent_item;
509 switch (etype) {
510 case QUARK_ETYPE_DELETE:
511 TreeDeleteItem(eui->tree, item);
512 break;
513 case QUARK_ETYPE_MODIFY:
514 init_item(eui, item, q);
515 break;
516 case QUARK_ETYPE_NEW:
517 create_hook(q, eui, NULL);
518 break;
519 case QUARK_ETYPE_MOVE:
520 explorer_save_quark_state(eui);
521 TreeDeleteItem(eui->tree, item);
523 parent_item = quark_get_udata(quark_parent_get(q));
524 item = TreeInsertItem(eui->tree, parent_item, q, quark_get_id(q));
525 init_item(eui, item, q);
526 quark_set_udata(q, item);
527 storage_traverse(quark_get_children(q), create_children_hook, eui);
529 explorer_restore_quark_state(eui);
530 break;
533 TreeRefresh(eui->tree);
535 return TRUE;
538 static void init_quark_tree(ExplorerUI *eui)
540 storage_traverse(quark_get_children(gapp->pc), create_children_hook, eui);
541 quark_cb_add(gapp->pc, explorer_cb, eui);
542 TreeRefresh(eui->tree);
545 static void select_quark_explorer(Quark *q)
547 GUI *gui = gui_from_quark(q);
549 if (gui->eui) {
550 TreeItem *item = quark_get_udata(q);
552 TreeClearSelection(gui->eui->tree);
553 TreeHighlightItem(gui->eui->tree, item);
554 TreeScrollToItem(gui->eui->tree, item);
558 static int explorer_apply(ExplorerUI *ui, void *caller)
560 TreeItemList items;
561 int count, i, res = RETURN_SUCCESS;
563 int gpcount = 0;
564 GProject **gplist;
566 if (caller && !GetToggleButtonState(ui->instantupdate)) {
567 return RETURN_FAILURE;
570 TreeGetHighlighted(ui->tree, &items);
571 count = items.count;
573 if (!count) {
574 xfree(items.items);
575 return RETURN_FAILURE;
578 gplist = xmalloc(gapp->gpcount*sizeof(GProject));
579 if (!gplist) {
580 return RETURN_FAILURE;
583 for (i = 0; i < count && res == RETURN_SUCCESS; i++) {
584 Quark *q = TreeGetQuark(items.items[i]);
586 add_to_list(gplist, &gpcount, gproject_from_quark(q));
588 if (count == 1 && (!caller || caller == ui->idstr)) {
589 char *s = GetTextString(ui->idstr);
590 quark_idstr_set(q, s);
591 xfree(s);
594 switch (quark_fid_get(q)) {
595 case QFlavorProject:
596 if (set_project_data(ui->project_ui, q, caller) != RETURN_SUCCESS) {
597 res = RETURN_FAILURE;
599 break;
600 case QFlavorSSD:
601 if (set_ssd_data(ui->ssd_ui, q, caller) != RETURN_SUCCESS) {
602 res = RETURN_FAILURE;
604 break;
605 case QFlavorFrame:
606 if (set_frame_data(ui->frame_ui, q, caller) != RETURN_SUCCESS) {
607 res = RETURN_FAILURE;
609 break;
610 case QFlavorGraph:
611 if (graph_set_data(ui->graph_ui, q, caller) != RETURN_SUCCESS) {
612 res = RETURN_FAILURE;
614 break;
615 case QFlavorSet:
616 if (set_set_data(ui->set_ui, q, caller) != RETURN_SUCCESS) {
617 res = RETURN_FAILURE;
619 break;
620 case QFlavorAGrid:
621 if (set_axisgrid_data(ui->axisgrid_ui, q, caller) != RETURN_SUCCESS) {
622 res = RETURN_FAILURE;
624 break;
625 case QFlavorAxis:
626 if (set_axis_data(ui->axis_ui, q, caller) != RETURN_SUCCESS) {
627 res = RETURN_FAILURE;
629 break;
630 case QFlavorDObject:
631 if (set_object_data(ui->object_ui, q, caller) != RETURN_SUCCESS) {
632 res = RETURN_FAILURE;
634 break;
635 case QFlavorAText:
636 if (set_atext_data(ui->atext_ui, q, caller) != RETURN_SUCCESS) {
637 res = RETURN_FAILURE;
639 break;
640 case QFlavorRegion:
641 if (set_region_data(ui->region_ui, q, caller) != RETURN_SUCCESS) {
642 res = RETURN_FAILURE;
644 break;
645 default:
646 res = RETURN_FAILURE;
647 break;
650 xfree(items.items);
652 for (i = 0; i < gpcount; i++) {
653 explorer_snapshot(gapp, gplist[i], FALSE);
655 xfree(gplist);
657 return res;
660 static int explorer_aac(void *data)
662 ExplorerUI *ui = (ExplorerUI *) data;
664 return explorer_apply(ui, NULL);
667 void explorer_before_undo(GraceApp *gapp, Quark *pr)
669 ExplorerUI *eui = gapp->gui->eui;
671 if (!eui) {
672 return;
675 explorer_save_quark_state(eui);
676 TreeDeleteItem(eui->tree, quark_get_udata(pr));
679 void explorer_after_undo(GraceApp *gapp, Quark *pr)
681 ExplorerUI *eui = gapp->gui->eui;
683 if (!eui) {
684 return;
687 quark_traverse(pr, create_hook, eui);
688 explorer_restore_quark_state(eui);
692 #define HIDE_CB 0
693 #define SHOW_CB 1
694 #define DELETE_CB 2
695 #define DUPLICATE_CB 3
696 #define ADD_FRAME_CB 4
697 #define ADD_GRAPH_CB 5
698 #define ADD_SSD_CB 6
699 #define ADD_SET_CB 7
700 #define ADD_AXISGRID_CB 8
701 #define ADD_AXIS_CB 9
702 #define ADD_LINE_CB 10
703 #define ADD_BOX_CB 11
704 #define ADD_ARC_CB 12
705 #define ADD_TEXT_CB 13
707 static void popup_any_cb(ExplorerUI *eui, int type)
709 TreeItemList items;
710 int count, i;
711 Quark *qnew = NULL;
712 Quark *q;
713 GProject *gp;
715 int gpcount = 0;
716 GProject **gplist;
718 TreeGetHighlighted(eui->tree, &items);
719 count = items.count;
721 if (!count) {
722 xfree(items.items);
723 return;
726 gplist = xmalloc(gapp->gpcount*sizeof(GProject));
727 if (!gplist) {
728 return;
731 for (i = 0; i < count; i++) {
733 q = TreeGetQuark(items.items[i]);
734 gp = gproject_from_quark(q);
735 add_to_list(gplist, &gpcount, gp);
737 switch (type) {
738 case HIDE_CB:
739 quark_set_active(q, FALSE);
740 break;
741 case SHOW_CB:
742 quark_set_active(q, TRUE);
743 break;
744 case DELETE_CB:
745 quark_free(q);
746 break;
747 case DUPLICATE_CB:
748 quark_copy(q);
749 break;
750 case ADD_FRAME_CB:
751 qnew = frame_new(q);
752 break;
753 case ADD_GRAPH_CB:
754 qnew = graph_new(q);
755 break;
756 case ADD_SSD_CB:
757 qnew = gapp_ssd_new(q);
758 break;
759 case ADD_SET_CB:
760 qnew = gapp_set_new(q);
761 break;
762 case ADD_AXISGRID_CB:
763 qnew = axisgrid_new(q);
764 break;
765 case ADD_AXIS_CB:
766 qnew = axis_new(q);
767 break;
768 case ADD_LINE_CB:
769 qnew = object_new_complete(q, DO_LINE);
770 break;
771 case ADD_BOX_CB:
772 qnew = object_new_complete(q, DO_BOX);
773 break;
774 case ADD_ARC_CB:
775 qnew = object_new_complete(q, DO_ARC);
776 break;
777 case ADD_TEXT_CB:
778 qnew = atext_new(q);
779 break;
782 xfree(items.items);
784 for (i = 0; i < gpcount; i++) {
785 explorer_snapshot(gapp, gplist[i], TRUE);
787 xfree(gplist);
789 if (qnew) {
790 select_quark_explorer(qnew);
794 static void hide_cb(Widget but, void *udata)
796 popup_any_cb((ExplorerUI *) udata, HIDE_CB);
799 static void show_cb(Widget but, void *udata)
801 popup_any_cb((ExplorerUI *) udata, SHOW_CB);
804 static void delete_cb(Widget but, void *udata)
806 if (yesno("Really delete selected item(s)?", NULL, NULL, NULL)) {
807 popup_any_cb((ExplorerUI *) udata, DELETE_CB);
811 static void duplicate_cb(Widget but, void *udata)
813 popup_any_cb((ExplorerUI *) udata, DUPLICATE_CB);
816 static void add_frame_cb(Widget but, void *udata)
818 popup_any_cb((ExplorerUI *) udata, ADD_FRAME_CB);
821 static void add_graph_cb(Widget but, void *udata)
823 popup_any_cb((ExplorerUI *) udata, ADD_GRAPH_CB);
826 static void add_ssd_cb(Widget but, void *udata)
828 popup_any_cb((ExplorerUI *) udata, ADD_SSD_CB);
831 static void add_set_cb(Widget but, void *udata)
833 popup_any_cb((ExplorerUI *) udata, ADD_SET_CB);
836 static void add_axisgrid_cb(Widget but, void *udata)
838 popup_any_cb((ExplorerUI *) udata, ADD_AXISGRID_CB);
841 static void add_axis_cb(Widget but, void *udata)
843 popup_any_cb((ExplorerUI *) udata, ADD_AXIS_CB);
846 static void add_object_cb(Widget but, void *udata)
848 ExplorerUI *eui = (ExplorerUI *) udata;
849 if (but == eui->insert_line_bt) {
850 popup_any_cb(eui, ADD_LINE_CB);
851 } else
852 if (but == eui->insert_box_bt) {
853 popup_any_cb(eui, ADD_BOX_CB);
854 } else
855 if (but == eui->insert_arc_bt) {
856 popup_any_cb(eui, ADD_ARC_CB);
857 } else
858 if (but == eui->insert_text_bt) {
859 popup_any_cb(eui, ADD_TEXT_CB);
863 #define PROJECT_SHOW_CB 0
864 #define PROJECT_SAVE_CB 1
865 #define PROJECT_SAVE_AS_CB 2
866 #define PROJECT_REVERT_TO_SAVED_CB 3
867 #define PROJECT_CLOSE_CB 4
869 static void project_popup_any_cb(ExplorerUI *eui, int type)
871 TreeItemList items;
872 Quark *q;
873 GraceApp *gapp;
874 GProject *gp;
876 TreeGetHighlighted(eui->tree, &items);
878 if (!items.count || items.count > 1) {
879 xfree(items.items);
880 return;
883 q = TreeGetQuark(items.items[0]);
884 gapp = gapp_from_quark(q);
885 gp = gproject_from_quark(q);
887 switch (type) {
888 case PROJECT_SHOW_CB:
889 gapp_set_active_gproject(gapp, gp);
890 xdrawgraph(gp);
891 update_all();
892 break;
893 case PROJECT_SAVE_CB:
894 project_save(gp);
895 break;
896 case PROJECT_SAVE_AS_CB:
897 project_save_as(gp);
898 break;
899 case PROJECT_REVERT_TO_SAVED_CB:
900 revert_project(gapp, gp);
901 xdrawgraph(gapp->gp);
902 update_all();
903 break;
904 case PROJECT_CLOSE_CB:
905 if (gapp->gpcount == 1) {
906 errmsg("Can't close the last project");
907 return;
910 if (gp && gproject_get_top(gp) &&
911 quark_dirtystate_get(gproject_get_top(gp)) &&
912 !yesno("Abandon unsaved changes?", NULL, NULL, NULL)) {
913 return;
916 gapp_delete_gproject(gapp, gp);
918 if (gapp->gp == NULL) {
919 gapp_set_active_gproject(gapp, gapp->gplist[0]);
922 xdrawgraph(gapp->gp);
923 update_all();
924 break;
927 xfree(items.items);
930 static void project_show_cb(Widget but, void *udata)
932 project_popup_any_cb((ExplorerUI *) udata, PROJECT_SHOW_CB);
935 static void project_save_cb(Widget but, void *udata)
937 project_popup_any_cb((ExplorerUI *) udata, PROJECT_SAVE_CB);
940 static void project_save_as_cb(Widget but, void *udata)
942 project_popup_any_cb((ExplorerUI *) udata, PROJECT_SAVE_AS_CB);
945 static void project_revert_to_saved_cb(Widget but, void *udata)
947 project_popup_any_cb((ExplorerUI *) udata, PROJECT_REVERT_TO_SAVED_CB);
950 static void project_close_cb(Widget but, void *udata)
952 project_popup_any_cb((ExplorerUI *) udata, PROJECT_CLOSE_CB);
955 void raise_explorer(GUI *gui, Quark *q)
957 GraceApp *gapp = gui->P;
959 set_wait_cursor();
961 if (!gui->eui) {
962 ExplorerUI *eui;
963 Widget menubar, menupane, panel, form, fr;
965 eui = xmalloc(sizeof(ExplorerUI));
966 gui->eui = eui;
968 /* Create pixmaps */
969 CreatePixmaps(eui);
971 eui->top = CreateDialogForm(app_shell, "Explorer");
972 menubar = CreateMenuBar(eui->top);
973 ManageChild(menubar);
974 AddDialogFormChild(eui->top, menubar);
976 menupane = CreateMenu(menubar, "File", 'F', FALSE);
977 CreateMenuButton(menupane,
978 "Close", 'C', destroy_dialog_cb, GetParent(eui->top));
980 menupane = CreateMenu(menubar, "Edit", 'E', FALSE);
981 eui->edit_undo_bt = CreateMenuButtonA(menupane, "Undo", 'U', "Ctrl+Z",
982 undo_cb, gapp);
983 eui->edit_redo_bt = CreateMenuButtonA(menupane, "Redo", 'R', "Ctrl+Shift+Z",
984 redo_cb, gapp);
986 menupane = CreateMenu(menubar, "Insert", 'I', FALSE);
987 eui->insert_frame_bt = CreateMenuButton(menupane,
988 "Frame", '\0', add_frame_cb, eui);
989 SetSensitive(eui->insert_frame_bt, FALSE);
990 eui->insert_graph_bt = CreateMenuButton(menupane,
991 "Graph", '\0', add_graph_cb, eui);
992 SetSensitive(eui->insert_graph_bt, FALSE);
993 eui->insert_ssd_bt = CreateMenuButton(menupane,
994 "SSData", '\0', add_ssd_cb, eui);
995 SetSensitive(eui->insert_ssd_bt, FALSE);
996 eui->insert_set_bt = CreateMenuButton(menupane,
997 "Set", '\0', add_set_cb, eui);
998 SetSensitive(eui->insert_set_bt, FALSE);
999 eui->insert_axisgrid_bt = CreateMenuButton(menupane,
1000 "Axis grid", '\0', add_axisgrid_cb, eui);
1001 SetSensitive(eui->insert_axisgrid_bt, FALSE);
1002 eui->insert_axis_bt = CreateMenuButton(menupane,
1003 "Axis", '\0', add_axis_cb, eui);
1004 SetSensitive(eui->insert_axis_bt, FALSE);
1005 eui->insert_object_pane = CreateMenu(menupane, "Annotating objects", 'o', FALSE);
1006 SetSensitive(eui->insert_object_pane, FALSE);
1007 eui->insert_text_bt = CreateMenuButton(eui->insert_object_pane,
1008 "Text", '\0', add_object_cb, eui);
1009 eui->insert_line_bt = CreateMenuButton(eui->insert_object_pane,
1010 "Line", '\0', add_object_cb, eui);
1011 eui->insert_box_bt = CreateMenuButton(eui->insert_object_pane,
1012 "Box", '\0', add_object_cb, eui);
1013 eui->insert_arc_bt = CreateMenuButton(eui->insert_object_pane,
1014 "Arc", '\0', add_object_cb, eui);
1016 menupane = CreateMenu(menubar, "Options", 'O', FALSE);
1017 eui->instantupdate = CreateMenuToggle(menupane, "Instantaneous update",
1018 'u', NULL, NULL);
1019 SetToggleButtonState(eui->instantupdate, gui->instant_update);
1021 menupane = CreateMenu(menubar, "Help", 'H', TRUE);
1022 CreateMenuHelpButton(menupane, "On explorer", 'e',
1023 eui->top, "doc/UsersGuide.html#explorer");
1025 panel = CreatePanedWindow(eui->top);
1027 form = CreateForm(panel);
1029 eui->tree = CreateTree(form);
1030 AddTreeHighlightItemsCB(eui->tree, highlight_cb, eui);
1031 AddTreeContextMenuCB(eui->tree, menu_cb, eui);
1032 AddTreeDropItemsCB(eui->tree, drop_cb, eui);
1034 fr = CreateFrame(form, NULL);
1035 eui->idstr = CreateTextInput(fr, "ID string:");
1036 AddTextInputCB(eui->idstr, text_explorer_cb, eui);
1037 #ifdef MOTIF_GUI
1038 XtVaSetValues(GetParent(eui->tree),
1039 XmNleftAttachment, XmATTACH_FORM,
1040 XmNrightAttachment, XmATTACH_FORM,
1041 XmNtopAttachment, XmATTACH_FORM,
1042 XmNbottomAttachment, XmATTACH_WIDGET,
1043 XmNbottomWidget, fr,
1044 NULL);
1045 XtVaSetValues(fr,
1046 XmNleftAttachment, XmATTACH_FORM,
1047 XmNrightAttachment, XmATTACH_FORM,
1048 XmNtopAttachment, XmATTACH_NONE,
1049 XmNbottomAttachment, XmATTACH_FORM,
1050 NULL);
1051 #endif
1052 ManageChild(form);
1054 eui->scrolled_window = CreateScrolledWindow(panel);
1056 ManageChild(panel);
1057 SetMinimumDimensions(form, 150, 0);
1058 SetDimensions(form, 250, 0);
1060 #ifdef HAVE_LESSTIF
1061 # if !defined(SF_BUG_993209_FIXED) && !defined(SF_BUG_993209_NOT_FIXED)
1062 # error "You should check whether SF bug #993209 is fixed in your version of LessTif."
1063 # error "Then define either SF_BUG_993209_FIXED or SF_BUG_993209_NOT_FIXED, accordingly."
1064 # error "See http://sourceforge.net/tracker/index.php?func=detail&aid=993209&group_id=8596&atid=108596."
1065 # endif
1066 # ifdef SF_BUG_993209_NOT_FIXED
1067 /* A dirty workaround */
1068 eui->scrolled_window = CreateVContainer(eui->scrolled_window);
1069 # endif
1070 #endif
1072 eui->project_ui = create_project_ui(eui);
1073 UnmanageChild(eui->project_ui->top);
1075 eui->ssd_ui = create_ssd_ui(eui);
1076 UnmanageChild(eui->ssd_ui->top);
1078 eui->frame_ui = create_frame_ui(eui);
1079 UnmanageChild(eui->frame_ui->top);
1081 eui->graph_ui = create_graph_ui(eui);
1082 UnmanageChild(eui->graph_ui->top);
1084 eui->set_ui = create_set_ui(eui);
1085 UnmanageChild(eui->set_ui->top);
1087 eui->axisgrid_ui = create_axisgrid_ui(eui);
1088 UnmanageChild(eui->axisgrid_ui->top);
1090 eui->axis_ui = create_axis_ui(eui);
1091 UnmanageChild(eui->axis_ui->top);
1093 eui->object_ui = create_object_ui(eui);
1094 UnmanageChild(eui->object_ui->top);
1096 eui->atext_ui = create_atext_ui(eui);
1097 UnmanageChild(eui->atext_ui->top);
1099 eui->region_ui = create_region_ui(eui);
1100 UnmanageChild(eui->region_ui->top);
1102 eui->aacbuts = CreateAACDialog(eui->top, panel, explorer_aac, eui);
1104 ManageChild(eui->tree);
1106 /* Menu popup */
1107 eui->popup = CreatePopupMenu(eui->tree);
1108 eui->popup_hide_bt = CreateMenuButton(eui->popup,
1109 "Hide", '\0', hide_cb, eui);
1110 eui->popup_show_bt = CreateMenuButton(eui->popup,
1111 "Show", '\0', show_cb, eui);
1113 CreateMenuSeparator(eui->popup);
1115 eui->popup_delete_bt = CreateMenuButton(eui->popup,
1116 "Delete", '\0', delete_cb, eui);
1117 eui->popup_duplicate_bt = CreateMenuButton(eui->popup,
1118 "Duplicate", '\0', duplicate_cb, eui);
1120 /* Project menu popup */
1121 eui->project_popup = CreatePopupMenu(eui->tree);
1122 eui->project_popup_show_bt = CreateMenuButton(eui->project_popup,
1123 "Show", '\0', project_show_cb, eui);
1125 CreateMenuSeparator(eui->project_popup);
1127 eui->project_popup_save_bt = CreateMenuButton(eui->project_popup,
1128 "Save", '\0', project_save_cb, eui);
1129 eui->project_popup_save_as_bt = CreateMenuButton(eui->project_popup,
1130 "Save as...", '\0', project_save_as_cb, eui);
1131 eui->project_popup_revert_to_saved_bt = CreateMenuButton(eui->project_popup,
1132 "Revert to saved", '\0', project_revert_to_saved_cb, eui);
1134 CreateMenuSeparator(eui->project_popup);
1136 eui->project_popup_close_bt = CreateMenuButton(eui->project_popup,
1137 "Close", '\0', project_close_cb, eui);
1139 init_quark_tree(eui);
1141 if (!q && gapp->gp) {
1142 select_quark_explorer(gproject_get_top(gapp->gp));
1145 #ifdef QT_GUI
1146 /* TODO: use resources */
1147 SetDimensions(gui->eui->top, 650, 600);
1148 #endif
1149 RaiseWindow(GetParent(gui->eui->top));
1151 if (q) {
1152 select_quark_explorer(q);
1155 update_undo_buttons(gapp->gp);
1157 unset_wait_cursor();
1160 void define_explorer_popup(Widget but, void *data)
1162 GUI *gui = (GUI *) data;
1163 raise_explorer(gui, NULL);
1167 void oc_explorer_cb(OptionStructure *opt, int a, void *data)
1169 ExplorerUI *eui = (ExplorerUI *) data;
1170 explorer_apply(eui, opt);
1172 void tb_explorer_cb(Widget but, int a, void *data)
1174 ExplorerUI *eui = (ExplorerUI *) data;
1175 explorer_apply(eui, but);
1177 void scale_explorer_cb(Widget scale, int a, void *data)
1179 ExplorerUI *eui = (ExplorerUI *) data;
1180 explorer_apply(eui, scale);
1182 void sp_explorer_cb(SpinStructure *spinp, double a, void *data)
1184 ExplorerUI *eui = (ExplorerUI *) data;
1185 explorer_apply(eui, spinp);
1187 void text_explorer_cb(TextStructure *cst, char *s, void *data)
1189 ExplorerUI *eui = (ExplorerUI *) data;
1190 explorer_apply(eui, cst);
1192 void titem_explorer_cb(Widget w, char *s, void *data)
1194 ExplorerUI *eui = (ExplorerUI *) data;
1195 explorer_apply(eui, w);
1197 void pen_explorer_cb(Widget but, const Pen *pen, void *data)
1199 ExplorerUI *eui = (ExplorerUI *) data;
1200 explorer_apply(eui, but);
1202 void format_explorer_cb(FormatStructure *fstr, const Format *format, void *data)
1204 ExplorerUI *eui = (ExplorerUI *) data;
1205 explorer_apply(eui, fstr);