1 /*
2 * FIG : Facility for Interactive Generation of figures
3 * Copyright (c) 1985-1988 by Supoj Sutanthavibul
4 * Parts Copyright (c) 1989-2007 by Brian V. Smith
5 * Parts Copyright (c) 1991 by Paul King
6 *
7 * Any party obtaining a copy of these files is granted, free of charge, a
8 * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
9 * nonexclusive right and license to deal in this software and documentation
10 * files (the "Software"), including without limitation the rights to use,
11 * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
12 * the Software, and to permit persons who receive copies from any such
13 * party to do so, with the only requirement being that the above copyright
14 * and this permission notice remain intact.
15 *
16 */
17
18
19 #include "fig.h"
20 #include "figx.h"
21 #include "resources.h"
22 #include "object.h"
23 #include "mode.h"
24 #include "f_read.h"
25 #include "w_drawprim.h"
26 #include "w_dir.h"
27 #include "w_file.h"
28 #include "w_indpanel.h"
29 #include "w_layers.h"
30 #include "w_util.h"
31 #include "w_setup.h"
32 #include "u_redraw.h"
33 #include "w_snap.h"
34
35 #include "w_cmdpanel.h"
36 #include "w_msgpanel.h"
37 #include "w_canvas.h"
38
39 /* EXPORTS */
40
41 /* which layer buttons are active */
42 Boolean active_layers[MAX_DEPTH +1];
43 Boolean any_active_in_compound(F_compound *cmpnd);
44 Widget layer_form;
45 Boolean gray_layers = True;
46 int object_depths[MAX_DEPTH +1]; /* count of objects at each depth */
47 int saved_depths[MAX_DEPTH +1]; /* saved when delete all is done */
48 int saved_min_depth, saved_max_depth; /* saved min/max depth */
49 int max_depth_request, min_depth_request;
50 Boolean save_layers[MAX_DEPTH+1];
51 int LAYER_WD=DEF_LAYER_WD;
52 int LAYER_HT;
53
54 /* LOCALS */
55
56 DeclareStaticArgs(20);
57
58 static Widget all_active_but, all_inactive_but, toggle_all_but;
59 static Widget graytoggle, blanktoggle, graylabel, blanklabel;
60 static Widget layer_viewp, layer_canvas;
61 static void toggle_layer(Widget w, XButtonEvent *event, String *params, Cardinal *nparams);
62 static void set_depth_to_layer(Widget w, XButtonEvent *event, String *params, Cardinal *nparams);
63 static void sweep_layer(Widget w, XButtonEvent *event, String *params, Cardinal *nparams);
64 static void leave_layer(Widget w, XButtonEvent *event, String *params, Cardinal *nparams);
65 static void all_active(Widget w, XtPointer closure, XtPointer call_data);
66 static void all_inactive(Widget w, XtPointer closure, XtPointer call_data);
67 static void toggle_all(Widget w, XtPointer closure, XtPointer call_data);
68 static void switch_layer_mode(Widget w, XtPointer closure, XtPointer call_data);
69 static void layer_exposed(Widget w, XExposeEvent *event, String *params, Cardinal *nparams);
70
71 #ifndef XAW3D1_5E
72 /* popup message over command button when mouse enters it */
73 static void layer_balloon_trigger(Widget widget, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch);
74 static void layer_unballoon(Widget widget, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch);
75 #endif /* XAW3D1_5E */
76
77 static void draw_layer_button(Window win, int but);
78 static void draw_layer_buttons(void);
79
80 XtActionsRec layer_actions[] =
81 {
82 {"ExposeLayerButtons", (XtActionProc) layer_exposed},
83 {"ToggleLayerButton", (XtActionProc) toggle_layer},
84 {"SetDepthToLayer", (XtActionProc) set_depth_to_layer},
85 {"SweepLayerButton", (XtActionProc) sweep_layer},
86 {"LeaveLayerButton", (XtActionProc) leave_layer},
87 };
88
89 static String layer_translations =
90 "<Btn1Down>:ToggleLayerButton()\n\
91 <Btn1Motion>: SweepLayerButton()\n\
92 <Btn3Down>:SetDepthToLayer()\n\
93 <Leave>: LeaveLayerButton()\n\
94 <Expose>:ExposeLayerButtons()\n";
95
96
97
98 void
reset_layers(void)99 reset_layers(void)
100 {
101 int i;
102 for (i=0; i<=MAX_DEPTH; i++) {
103 active_layers[i] = True;
104 }
105 }
106
107 void
reset_depths(void)108 reset_depths(void)
109 {
110 int i;
111 for (i=0; i<=MAX_DEPTH; i++) {
112 object_depths[i] = 0;
113 }
114 }
115
116 void
init_depth_panel(Widget parent)117 init_depth_panel(Widget parent)
118 {
119 Widget label, below;
120 Widget layer_viewform;
121
122 /* MOUSEFUN_HT and ind_panel height aren't known yet */
123 LAYER_HT = TOPRULER_HT + CANVAS_HT;
124
125 /* main form to hold all the layer stuff */
126
127 FirstArg(XtNfromHoriz, sideruler_sw);
128 NextArg(XtNdefaultDistance, 1);
129 NextArg(XtNwidth, LAYER_WD);
130 NextArg(XtNheight, LAYER_HT);
131 NextArg(XtNleft, XtChainRight);
132 NextArg(XtNright, XtChainRight);
133 NextArg(XtNfromVert, snap_indicator_panel);
134 layer_form = XtCreateWidget("layer_form",formWidgetClass, parent, Args, ArgCount);
135 if (appres.showdepthmanager)
136 XtManageChild(layer_form);
137
138 /* a label */
139 FirstArg(XtNlabel, "Depths ");
140 NextArg(XtNtop, XtChainTop);
141 NextArg(XtNbottom, XtChainTop);
142 NextArg(XtNleft, XtChainLeft);
143 NextArg(XtNright, XtChainRight);
144 label = XtCreateManagedWidget("layer_label", labelWidgetClass, layer_form,
145 Args, ArgCount);
146
147 /* buttons to make all active, all inactive or toggle all */
148
149 FirstArg(XtNlabel, "All On ");
150 NextArg(XtNfromVert, label);
151 NextArg(XtNtop, XtChainTop);
152 NextArg(XtNbottom, XtChainTop);
153 NextArg(XtNleft, XtChainLeft);
154 NextArg(XtNright, XtChainRight);
155 below = all_active_but = XtCreateManagedWidget("all_active", commandWidgetClass,
156 layer_form, Args, ArgCount);
157 XtAddCallback(below, XtNcallback, (XtCallbackProc)all_active, (XtPointer) NULL);
158 #ifndef XAW3D1_5E
159 /* popup when mouse passes over button */
160 XtAddEventHandler(below, EnterWindowMask, False,
161 (XtEventHandler)layer_balloon_trigger, (XtPointer) "Display all depths");
162 XtAddEventHandler(below, LeaveWindowMask, False,
163 (XtEventHandler)layer_unballoon, (XtPointer) NULL);
164 #endif /* XAW3D1_5E */
165
166 FirstArg(XtNlabel, "All Off ");
167 NextArg(XtNfromVert, below);
168 NextArg(XtNtop, XtChainTop);
169 NextArg(XtNbottom, XtChainTop);
170 NextArg(XtNleft, XtChainLeft);
171 NextArg(XtNright, XtChainRight);
172 below = all_inactive_but = XtCreateManagedWidget("all_inactive", commandWidgetClass,
173 layer_form, Args, ArgCount);
174 XtAddCallback(below, XtNcallback, (XtCallbackProc)all_inactive, (XtPointer) NULL);
175 #ifndef XAW3D1_5E
176 /* popup when mouse passes over button */
177 XtAddEventHandler(below, EnterWindowMask, False,
178 (XtEventHandler)layer_balloon_trigger, (XtPointer) "Hide all depths");
179 XtAddEventHandler(below, LeaveWindowMask, False,
180 (XtEventHandler)layer_unballoon, (XtPointer) NULL);
181 #endif /* XAW3D1_5E */
182
183 FirstArg(XtNlabel, "Toggle ");
184 NextArg(XtNfromVert, below);
185 NextArg(XtNtop, XtChainTop);
186 NextArg(XtNbottom, XtChainTop);
187 NextArg(XtNleft, XtChainLeft);
188 NextArg(XtNright, XtChainRight);
189 below = toggle_all_but = XtCreateManagedWidget("toggle_all", commandWidgetClass,
190 layer_form, Args, ArgCount);
191 XtAddCallback(below, XtNcallback, (XtCallbackProc)toggle_all, (XtPointer) NULL);
192 #ifndef XAW3D1_5E
193 /* popup when mouse passes over button */
194 XtAddEventHandler(below, EnterWindowMask, False,
195 (XtEventHandler)layer_balloon_trigger, (XtPointer) "Toggle displayed/hidden depths");
196 XtAddEventHandler(below, LeaveWindowMask, False,
197 (XtEventHandler)layer_unballoon, (XtPointer) NULL);
198 #endif /* XAW3D1_5E */
199
200 /* radio buttons to switch between graying out inactive layers or blanking altogether */
201
202 /* radio for graying out */
203 /* we'll insert the checkmark bitmap in setup_depth_panel */
204 FirstArg(XtNwidth, sm_check_width+6);
205 NextArg(XtNheight, sm_check_height+6);
206 NextArg(XtNfromVert, below);
207 NextArg(XtNtop, XtChainTop);
208 NextArg(XtNbottom, XtChainTop);
209 NextArg(XtNleft, XtChainLeft);
210 NextArg(XtNright, XtChainLeft);
211 NextArg(XtNinternalWidth, 1);
212 NextArg(XtNinternalHeight, 1);
213 NextArg(XtNfont, bold_font);
214 NextArg(XtNlabel, " ");
215 NextArg(XtNsensitive, (gray_layers? False : True)); /* make opposite button sens */
216 NextArg(XtNstate, gray_layers); /* initial state */
217 NextArg(XtNradioData, 1); /* when this is pressed the value is 1 */
218 graytoggle = XtCreateManagedWidget("graytoggle", toggleWidgetClass,
219 layer_form, Args, ArgCount);
220 XtAddCallback(graytoggle, XtNcallback, (XtCallbackProc) switch_layer_mode,
221 (XtPointer) NULL);
222
223 /* label - "Gray" */
224
225 FirstArg(XtNborderWidth, 0);
226 NextArg(XtNfromVert, below);
227 NextArg(XtNfromHoriz, graytoggle);
228 NextArg(XtNtop, XtChainTop);
229 NextArg(XtNbottom, XtChainTop);
230 NextArg(XtNleft, XtChainRight);
231 NextArg(XtNright, XtChainRight);
232 NextArg(XtNlabel, "Gray ");
233 graylabel = below = XtCreateManagedWidget("graylabel", labelWidgetClass,
234 layer_form, Args, ArgCount);
235 #ifndef XAW3D1_5E
236 /* popup when mouse passes over button */
237 XtAddEventHandler(below, EnterWindowMask, False,
238 (XtEventHandler)layer_balloon_trigger, (XtPointer) "Display inactive layers in gray");
239 XtAddEventHandler(below, LeaveWindowMask, False,
240 (XtEventHandler)layer_unballoon, (XtPointer) NULL);
241 #endif /* XAW3D1_5E */
242
243 /* radio for blanking */
244 FirstArg(XtNwidth, sm_check_width+6);
245 NextArg(XtNheight, sm_check_height+6);
246 NextArg(XtNfromVert, graytoggle);
247 NextArg(XtNtop, XtChainTop);
248 NextArg(XtNbottom, XtChainTop);
249 NextArg(XtNleft, XtChainLeft);
250 NextArg(XtNright, XtChainLeft);
251 NextArg(XtNinternalWidth, 1);
252 NextArg(XtNinternalHeight, 1);
253 NextArg(XtNfont, bold_font);
254 NextArg(XtNlabel, " ");
255 NextArg(XtNsensitive, (gray_layers? True : False)); /* make opposite button sens */
256 NextArg(XtNstate, !gray_layers); /* initial state */
257 NextArg(XtNradioData, 2); /* when this is pressed the value is 2 */
258 NextArg(XtNradioGroup, graytoggle); /* this is the other radio button in the group */
259 blanktoggle = XtCreateManagedWidget("blanktoggle", toggleWidgetClass,
260 layer_form, Args, ArgCount);
261 XtAddCallback(blanktoggle, XtNcallback, (XtCallbackProc) switch_layer_mode,
262 (XtPointer) NULL);
263
264 /* label - "Blank" */
265
266 FirstArg(XtNborderWidth, 0);
267 NextArg(XtNfromVert, graytoggle);
268 NextArg(XtNfromHoriz, blanktoggle);
269 NextArg(XtNlabel, "Blank ");
270 NextArg(XtNtop, XtChainTop);
271 NextArg(XtNbottom, XtChainTop);
272 NextArg(XtNleft, XtChainRight);
273 NextArg(XtNright, XtChainRight);
274 blanklabel = below = XtCreateManagedWidget("blanklabel", labelWidgetClass,
275 layer_form, Args, ArgCount);
276 #ifndef XAW3D1_5E
277 /* popup when mouse passes over button */
278 XtAddEventHandler(below, EnterWindowMask, False,
279 (XtEventHandler)layer_balloon_trigger, (XtPointer) "Blank inactive layers");
280 XtAddEventHandler(below, LeaveWindowMask, False,
281 (XtEventHandler)layer_unballoon, (XtPointer) NULL);
282 #endif /* XAW3D1_5E */
283
284 /* a form to hold the "Front" and "Back" labels and the viewport widget */
285
286 FirstArg(XtNborderWidth, 1);
287 NextArg(XtNfromVert, below);
288 NextArg(XtNdefaultDistance, 1);
289 NextArg(XtNtop, XtChainTop);
290 NextArg(XtNbottom, XtChainBottom);
291 NextArg(XtNleft, XtChainRight);
292 NextArg(XtNright, XtChainRight);
293 layer_viewform = XtCreateManagedWidget("layer_viewform",formWidgetClass,
294 layer_form, Args, ArgCount);
295
296 /* label - "Front" */
297
298 FirstArg(XtNborderWidth, 0);
299 NextArg(XtNlabel, " Front ");
300 NextArg(XtNtop, XtChainTop);
301 NextArg(XtNbottom, XtChainTop);
302 NextArg(XtNleft, XtChainRight);
303 NextArg(XtNright, XtChainRight);
304 below = XtCreateManagedWidget("frontlabel", labelWidgetClass,
305 layer_viewform, Args, ArgCount);
306
307 /* viewport to be able to scroll the layer buttons */
308
309 FirstArg(XtNborderWidth, 1);
310 NextArg(XtNwidth, LAYER_WD);
311 NextArg(XtNallowVert, True);
312 NextArg(XtNfromVert, below);
313 NextArg(XtNtop, XtChainTop);
314 NextArg(XtNbottom, XtChainBottom);
315 NextArg(XtNleft, XtChainLeft);
316 NextArg(XtNright, XtChainRight);
317 layer_viewp = XtCreateManagedWidget("layer_viewp", viewportWidgetClass,
318 layer_viewform, Args, ArgCount);
319 /* popup when mouse passes over button */
320
321 /* pass null pointer for trigger message so we'll use the two-line one */
322 #ifndef XAW3D1_5E
323 XtAddEventHandler(layer_viewp, EnterWindowMask, False,
324 (XtEventHandler)layer_balloon_trigger, (XtPointer) NULL);
325 XtAddEventHandler(layer_viewp, LeaveWindowMask, False,
326 (XtEventHandler)layer_unballoon, (XtPointer) NULL);
327 #endif /* XAW3D1_5E */
328 XtAddEventHandler(layer_viewp, StructureNotifyMask, False,
329 (XtEventHandler)update_layers, (XtPointer) NULL);
330
331 /* canvas (label, actually) in which to create the buttons */
332 /* we're not using real commandButtons because of the time to create
333 potentially hundreds of them depending on the number of layers in the figure */
334 FirstArg(XtNleft, XtChainLeft);
335 NextArg(XtNright, XtChainRight);
336 NextArg(XtNlabel, "");
337 layer_canvas = XtCreateManagedWidget("layer_canvas", labelWidgetClass,
338 layer_viewp, Args, ArgCount);
339 /* label - "Back" */
340
341 FirstArg(XtNborderWidth, 0);
342 NextArg(XtNfromVert, layer_viewp);
343 NextArg(XtNlabel, " Back ");
344 NextArg(XtNtop, XtChainBottom);
345 NextArg(XtNbottom, XtChainBottom);
346 NextArg(XtNleft, XtChainRight);
347 NextArg(XtNright, XtChainRight);
348 below = XtCreateManagedWidget("backlabel", labelWidgetClass,
349 layer_viewform, Args, ArgCount);
350
351 /* make actions/translations for user to click on a layer "button" and
352 to redraw buttons on expose */
353 XtAppAddActions(tool_app, layer_actions, XtNumber(layer_actions));
354 XtOverrideTranslations(layer_canvas,
355 XtParseTranslationTable(layer_translations));
356
357 #ifdef XAW3D1_5E
358 update_layerpanel();
359 #endif /* XAW3D1_5E */
360 }
361
362 /* now that the mouse function and indicator panels have been sized
363 correctly, resize our form */
364
365 void
setup_depth_panel(void)366 setup_depth_panel(void)
367 {
368 Dimension ind_ht, snap_ht=0;
369 /* get height of indicator and snap panels */
370 FirstArg(XtNheight, &ind_ht);
371 GetValues(ind_panel);
372 FirstArg(XtNheight, &snap_ht);
373 GetValues(snap_indicator_panel);
374 LAYER_HT = MOUSEFUN_HT + TOPRULER_HT + CANVAS_HT + ind_ht - snap_ht + INTERNAL_BW*4;
375
376 /* now that the bitmaps have been created, put the checkmark in the proper toggle */
377 FirstArg(XtNbitmap, (gray_layers? sm_check_pm : sm_null_check_pm));
378 SetValues(graytoggle);
379 FirstArg(XtNbitmap, (gray_layers? sm_null_check_pm : sm_check_pm));
380 SetValues(blanktoggle);
381
382 XtUnmanageChild(layer_form);
383 FirstArg(XtNheight, LAYER_HT);
384 SetValues(layer_form);
385 XtManageChild(layer_form);
386 }
387
388 #define B_WIDTH 48
389 #define B_BORDER 2
390 #define C_SIZE 10
391 #define TOT_B_HEIGHT (C_SIZE+2*B_BORDER)
392
393 /* now make a checkbox for each layer in the figure */
394 /* get_min_max_depth() must have already been called */
395
396 void
update_layers(void)397 update_layers(void)
398 {
399 Window w = XtWindow(layer_canvas);
400 int i, height;
401
402 /* don't update depth panel when previewing or reading in a Fig file */
403 if (preview_in_progress || defer_update_layers)
404 return;
405
406 XClearWindow(tool_d, w);
407 if (min_depth < 0) return; /* if no objects, return */
408
409 height = B_BORDER * 3;
410 for (i = min_depth; i <= max_depth; i++) {
411 if (object_depths[i] > 0) height += TOT_B_HEIGHT;
412 }
413
414 /* set height of canvas for all buttons */
415 FirstArg(XtNheight, (Dimension)height);
416 SetValues(layer_canvas);
417 /* force drawing */
418 draw_layer_buttons();
419 }
420
421 static void
draw_layer_buttons(void)422 draw_layer_buttons(void)
423 {
424 Window w = XtWindow(layer_canvas);
425 int i;
426
427 XClearWindow(tool_d, w);
428 if (min_depth < 0) return; /* if no objects, return */
429
430 for (i = min_depth; i <= max_depth; i++) {
431 if (object_depths[i] > 0) draw_layer_button(w, i);
432 }
433 }
434
435
436 #define draw_l(w, x1, y1, x2, y2) \
437 XDrawLine(tool_d, w, button_gc, x1, y1, x2, y2);
438
439 static void
draw_layer_button(Window win,int but)440 draw_layer_button(Window win, int but)
441 {
442 char str[20];
443 int x, y, w, h, i;
444
445 if (object_depths[but] == 0) return; /* no object for the depth */
446
447 x = B_BORDER;
448 w = B_WIDTH;
449
450 y = B_BORDER;
451 for (i = min_depth; i < but; i++) {
452 if (object_depths[i]) y += TOT_B_HEIGHT;
453 }
454 h = TOT_B_HEIGHT;
455
456 /* the whole border */
457 draw_l(win, x, y,x+w, y);
458 draw_l(win,x+w, y,x+w,y+h);
459 draw_l(win,x+w,y+h, x,y+h);
460 draw_l(win,x, y+h, x, y);
461
462 /* now the checkbox border */
463 x=x+B_BORDER; y=y+B_BORDER;
464 w=C_SIZE;
465
466 draw_l(win, x, y,x+w, y);
467 draw_l(win,x+w, y,x+w,y+w);
468 draw_l(win,x+w,y+w, x,y+w);
469 draw_l(win, x,y+w, x, y);
470
471 /* draw in the checkmark or a blank */
472 if (active_layer(but))
473 XCopyArea(tool_d, sm_check_pm, win, button_gc, 0, 0,
474 sm_check_width, sm_check_height, x+1, y+1);
475 else
476 XCopyArea(tool_d, sm_null_check_pm, win, button_gc, 0, 0,
477 sm_check_width, sm_check_height, x+1, y+1);
478
479 /* now draw in the layer number for the button */
480 sprintf(str, "%3d", but);
481 XDrawString(tool_d, win, button_gc, x+w+3*B_BORDER, y+w, str, strlen(str));
482 }
483
484 /* this is the callback to refresh the layer buttons that have been exposed */
485
486 static void
layer_exposed(Widget w,XExposeEvent * event,String * params,Cardinal * nparams)487 layer_exposed(Widget w, XExposeEvent *event, String *params, Cardinal *nparams)
488 {
489 int y, i;
490
491 if (min_depth < 0) return; /* if no objects return */
492
493 y = 0;
494 for (i = min_depth; i <= max_depth; i++) {
495 if (object_depths[i] > 0) {
496 y += TOT_B_HEIGHT;
497 if (event->y <= y && y - TOT_B_HEIGHT <= event->y + event->height)
498 draw_layer_button(XtWindow(w), i);
499 }
500 }
501 }
502
503 /* come here when user toggles layer button */
504
505 static int pressed_but = -1;
506
507 static int
calculate_pressed_depth(int y)508 calculate_pressed_depth(int y)
509 {
510 int i, y1;
511
512 y1 = TOT_B_HEIGHT;
513 for (i = min_depth; i <= max_depth; i++) {
514 if (object_depths[i] > 0) {
515 if (y < y1) return i;
516 y1 += TOT_B_HEIGHT;
517 }
518 }
519 return max_depth + 1;
520 }
521
522 /* user pressed right button on layer checkbox, set depth attribute to that layer */
523
524 static void
set_depth_to_layer(Widget w,XButtonEvent * event,String * params,Cardinal * nparams)525 set_depth_to_layer(Widget w, XButtonEvent *event, String *params, Cardinal *nparams)
526 {
527 int but;
528
529 but = calculate_pressed_depth(event->y);
530 if (but < min_depth || max_depth < but)
531 return; /* no such button */
532 cur_depth = but;
533 show_depth(depth_button);
534 }
535
536 static void
toggle_layer(Widget w,XButtonEvent * event,String * params,Cardinal * nparams)537 toggle_layer(Widget w, XButtonEvent *event, String *params, Cardinal *nparams)
538 {
539 Window win = XtWindow(layer_canvas);
540 int but, i;
541 Boolean obscure;
542
543 if (min_depth < 0) return; /* if no objects, return */
544
545 but = calculate_pressed_depth(event->y);
546 if (but < min_depth || max_depth < but)
547 return; /* no such button */
548
549 /* yes, toggle visibility and redraw */
550 active_layers[but] = !active_layers[but];
551 draw_layer_button(win, but);
552 /* if user just turned on a layer, draw only it if there are no active layers on top */
553 if (active_layers[but]) {
554 obscure = False;
555 for (i=0; i<but; i++)
556 if (active_layers[i]) {
557 obscure = True;
558 break;
559 }
560 if (!obscure) {
561 clearcounts();
562 redisplay_compoundobject(&objects, but);
563 } else
564 redisplay_canvas();
565 } else {
566 /* otherwise redraw whole canvas to get rid of that layer */
567 redisplay_canvas();
568 }
569 pressed_but = but;
570 }
571
572 static void
sweep_layer(Widget w,XButtonEvent * event,String * params,Cardinal * nparams)573 sweep_layer(Widget w, XButtonEvent *event, String *params, Cardinal *nparams)
574 {
575 Window win = XtWindow(layer_canvas);
576 int but;
577 int i;
578 Boolean changed = FALSE;
579
580 if (min_depth < 0) return;
581 if (pressed_but < 0) return;
582
583 but = calculate_pressed_depth(event->y);
584 if (but < min_depth) but = min_depth;
585 if (max_depth < but) but = max_depth;
586
587 if (pressed_but < but) {
588 for (i = pressed_but + 1; i <= but; i++) {
589 if (object_depths[i] > 0
590 && active_layers[i] != active_layers[pressed_but]) {
591 active_layers[i] = active_layers[pressed_but];
592 draw_layer_button(win, i);
593 changed = TRUE;
594 }
595 }
596 } else {
597 for (i = pressed_but - 1; but <= i; i--) {
598 if (object_depths[i] > 0
599 && active_layers[i] != active_layers[pressed_but]) {
600 active_layers[i] = active_layers[pressed_but];
601 draw_layer_button(win, i);
602 changed = TRUE;
603 }
604 }
605 }
606
607 if (changed)
608 redisplay_canvas();
609 }
610
611 static void
leave_layer(Widget w,XButtonEvent * event,String * params,Cardinal * nparams)612 leave_layer(Widget w, XButtonEvent *event, String *params, Cardinal *nparams)
613 {
614 pressed_but = -1;
615 }
616
617 static void
all_active(Widget w,XtPointer closure,XtPointer call_data)618 all_active(Widget w, XtPointer closure, XtPointer call_data)
619 {
620 int i;
621 Boolean changed = False;
622
623 if (min_depth < 0) return;
624
625 for (i=min_depth; i<=max_depth; i++) {
626 if (!active_layers[i]) {
627 active_layers[i] = True;
628 changed = True;
629 }
630 }
631 /* only redisplay if any of the buttons changed */
632 if (changed) {
633 draw_layer_buttons();
634 redisplay_canvas();
635 }
636 }
637
638 static void
all_inactive(Widget w,XtPointer closure,XtPointer call_data)639 all_inactive(Widget w, XtPointer closure, XtPointer call_data)
640 {
641 int i;
642 Boolean changed = False;
643
644 if (min_depth < 0) return;
645
646 for (i=min_depth; i<=max_depth; i++) {
647 if (active_layers[i]) {
648 active_layers[i] = False;
649 changed = True;
650 }
651 }
652 /* only redisplay if any of the buttons changed */
653 if (changed) {
654 draw_layer_buttons();
655 redisplay_canvas();
656 }
657 }
658
659 static void
toggle_all(Widget w,XtPointer closure,XtPointer call_data)660 toggle_all(Widget w, XtPointer closure, XtPointer call_data)
661 {
662 int i;
663
664 if (min_depth < 0) return;
665
666 for (i=min_depth; i<=max_depth; i++) {
667 active_layers[i] = !active_layers[i];
668 }
669 draw_layer_buttons();
670 redisplay_canvas();
671 }
672
673 /* when user toggles between gray-out and blank inactive layers */
674
675 static void
switch_layer_mode(Widget w,XtPointer closure,XtPointer call_data)676 switch_layer_mode(Widget w, XtPointer closure, XtPointer call_data)
677 {
678 Boolean state;
679 intptr_t which;
680
681 /* check state of the toggle and set/remove checkmark */
682 FirstArg(XtNstate, &state);
683 GetValues(w);
684
685 if (state ) {
686 FirstArg(XtNbitmap, sm_check_pm);
687 } else {
688 FirstArg(XtNbitmap, sm_null_check_pm);
689 }
690 SetValues(w);
691
692 /* set the sensitivity of the toggle button to the opposite of its state
693 so that the user must press the other one now */
694 XtSetSensitive(w, !state);
695 /* and make the *other* button the opposite state */
696 if (w == graytoggle) {
697 XtSetSensitive(blanktoggle, state);
698 } else {
699 XtSetSensitive(graytoggle, state);
700 }
701 /* which button */
702 which = (intptr_t) XawToggleGetCurrent(w);
703 if (which == 0) /* no buttons on, in transition so return now */
704 return;
705 if (which == 2) /* "blank" button, invert state */
706 state = !state;
707
708 /* set global state */
709 gray_layers = state;
710
711 /* now simply redisplay everything */
712 clear_canvas();
713 redisplay_canvas();
714 }
715
716 /* return True if *any* object in the compound is in any active layer */
717
718 Boolean
any_active_in_compound(F_compound * cmpnd)719 any_active_in_compound(F_compound *cmpnd)
720 {
721 F_ellipse *e;
722 F_arc *a;
723 F_line *l;
724 F_spline *s;
725 F_text *t;
726 F_compound *c;
727
728 for (a = cmpnd->arcs; a != NULL; a = a->next)
729 if (active_layer(a->depth))
730 return True;
731 for (e = cmpnd->ellipses; e != NULL; e = e->next)
732 if (active_layer(e->depth))
733 return True;
734 for (l = cmpnd->lines; l != NULL; l = l->next)
735 if (active_layer(l->depth))
736 return True;
737 for (s = cmpnd->splines; s != NULL; s = s->next)
738 if (active_layer(s->depth))
739 return True;
740 for (t = cmpnd->texts; t != NULL; t = t->next)
741 if (active_layer(t->depth))
742 return True;
743 for (c = cmpnd->compounds; c != NULL; c = c->next)
744 if (any_active_in_compound(c))
745 return True;
746 return False;
747 }
748
749 #ifdef XAW3D1_5E
update_layerpanel()750 void update_layerpanel()
751 {
752 /*
753 * We must test for the widgets, as this is called by
754 * w_cmdpanel.c:refresh_view_menu().
755 */
756
757 if (all_active_but)
758 if (appres.showballoons)
759 XawTipEnable(all_active_but, "Display all depths");
760 else
761 XawTipDisable(all_active_but);
762 if (all_inactive_but)
763 if (appres.showballoons)
764 XawTipEnable(all_inactive_but, "Hide all depths");
765 else
766 XawTipDisable(all_inactive_but);
767 if (toggle_all_but)
768 if (appres.showballoons)
769 XawTipEnable(toggle_all_but, "Toggle displayed/hidden depths");
770 else
771 XawTipDisable(toggle_all_but);
772 if (layer_viewp)
773 if (appres.showballoons)
774 XawTipEnable(layer_viewp, "Display or hide any depth");
775 else
776 XawTipDisable(layer_viewp);
777 if (graylabel)
778 if (appres.showballoons)
779 XawTipEnable(graylabel, "Display inactive layers in gray");
780 else
781 XawTipDisable(graylabel);
782 if (blanklabel)
783 if (appres.showballoons)
784 XawTipEnable(blanklabel, "Blank inactive layers");
785 else
786 XawTipDisable(blanklabel);
787 }
788 #else
789 static Widget layer_balloon_popup = (Widget) 0;
790 static XtIntervalId balloon_id = (XtIntervalId) 0;
791 static Widget balloon_w;
792 static char *popmsg;
793
794 static void layer_balloon(Widget w, XtPointer closure, XtPointer call_data);
795
796 /* come here when the mouse passes over a button in the depths panel */
797
798 static void
layer_balloon_trigger(Widget widget,XtPointer closure,XEvent * event,Boolean * continue_to_dispatch)799 layer_balloon_trigger(Widget widget, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch)
800 {
801 if (!appres.showballoons)
802 return;
803 balloon_w = widget;
804 /* save the message to popup */
805 popmsg = (char *) closure;
806 /* if an old balloon is still up, destroy it */
807 if ((balloon_id != 0) || (layer_balloon_popup != (Widget) 0)) {
808 layer_unballoon((Widget) 0, (XtPointer) 0, (XEvent*) 0, (Boolean*) 0);
809 }
810 balloon_id = XtAppAddTimeOut(tool_app, appres.balloon_delay,
811 (XtTimerCallbackProc) layer_balloon, (XtPointer) widget);
812 }
813
814 /* come here when the timer times out (and the mouse is still over the button) */
815
816 static void
layer_balloon(Widget w,XtPointer closure,XtPointer call_data)817 layer_balloon(Widget w, XtPointer closure, XtPointer call_data)
818 {
819 Position x, y;
820 Dimension wid, ht;
821 Widget box, balloon_label;
822 XtWidgetGeometry xtgeom,comp;
823
824 XtTranslateCoords(w, 0, 0, &x, &y);
825 FirstArg(XtNx, x);
826 NextArg(XtNy, y);
827 layer_balloon_popup = XtCreatePopupShell("layer_balloon_popup",
828 overrideShellWidgetClass, tool, Args, ArgCount);
829 FirstArg(XtNborderWidth, 0);
830 NextArg(XtNhSpace, 0);
831 NextArg(XtNvSpace, 0);
832 NextArg(XtNorientation, XtorientVertical);
833 box = XtCreateManagedWidget("box", boxWidgetClass,
834 layer_balloon_popup, Args, ArgCount);
835
836 /* make label for mouse message */
837 /* if the message was passed via the callback */
838 if (popmsg) {
839 FirstArg(XtNborderWidth, 0);
840 NextArg(XtNlabel, popmsg);
841 balloon_label = XtCreateManagedWidget("l_label", labelWidgetClass,
842 box, Args, ArgCount);
843 } else {
844 /* otherwise it is the two-line message with mouse indicators */
845 FirstArg(XtNborderWidth, 0);
846 NextArg(XtNleftBitmap, mouse_l); /* bitmap of mouse with left button pushed */
847 NextArg(XtNlabel, "Display or hide depth ");
848 balloon_label = XtCreateManagedWidget("l_label", labelWidgetClass,
849 box, Args, ArgCount);
850 FirstArg(XtNborderWidth, 0);
851 NextArg(XtNleftBitmap, mouse_r); /* bitmap of mouse with right button pushed */
852 NextArg(XtNlabel, "Set current depth to this");
853 (void) XtCreateManagedWidget("r_label", labelWidgetClass,
854 box, Args, ArgCount);
855 }
856
857 /* realize the popup so we can get its size */
858 XtRealizeWidget(layer_balloon_popup);
859
860 /* get width/height */
861 FirstArg(XtNwidth, &wid);
862 NextArg(XtNheight, &ht);
863 GetValues(balloon_label);
864 /* only change X position of widget */
865 xtgeom.request_mode = CWX;
866 /* shift popup left */
867 xtgeom.x = x-wid-5;
868 /* if the mouse is in the depth button area, position the y there */
869 if (w == layer_viewp) {
870 int wx, wy; /* XTranslateCoordinates wants int, not Position */
871 get_pointer_win_xy(&wx, &wy);
872 xtgeom.request_mode |= CWY;
873 xtgeom.y = y+wy - (int) ht - 60;
874 }
875 (void) XtMakeGeometryRequest(layer_balloon_popup, &xtgeom, &comp);
876
877 XtPopup(layer_balloon_popup,XtGrabNone);
878 XtRemoveTimeOut(balloon_id);
879 balloon_id = (XtIntervalId) 0;
880 }
881
882 /* come here when the mouse leaves a button in the layer panel */
883
884 static void
layer_unballoon(Widget widget,XtPointer closure,XEvent * event,Boolean * continue_to_dispatch)885 layer_unballoon(Widget widget, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch)
886 {
887 if (balloon_id) {
888 XtRemoveTimeOut(balloon_id);
889 }
890 balloon_id = (XtIntervalId) 0;
891 if (layer_balloon_popup != (Widget) 0) {
892 XtDestroyWidget(layer_balloon_popup);
893 layer_balloon_popup = (Widget) 0;
894 }
895 }
896 #endif /* XAW3D1_5E */
897
898 /* map/unmap the depth manager on the right side */
899
900 void
toggle_show_depths(void)901 toggle_show_depths(void)
902 {
903 Dimension wid, b;
904
905 appres.showdepthmanager = !appres.showdepthmanager;
906 put_msg("%s depth manager",
907 appres.showdepthmanager? "Show": "Don't show");
908 /* get actual width of layer form */
909 FirstArg(XtNwidth, &wid);
910 NextArg(XtNborderWidth, &b);
911 GetValues(layer_form);
912 if (appres.showdepthmanager) {
913 /* make sure it's the right size */
914 setup_depth_panel();
915 /* make canvas smaller to fit depth manager */
916 resize_all(CANVAS_WD-wid-2*b, CANVAS_HT);
917 } else {
918 XtUnmanageChild(layer_form);
919 /* make canvas larger to fill space where depth manager was */
920 resize_all(CANVAS_WD+wid+2*b, CANVAS_HT);
921 }
922 /* update the View menu */
923 refresh_view_menu();
924 /* and redraw the objects */
925 redisplay_canvas();
926 }
927
928 void
save_active_layers(void)929 save_active_layers(void)
930 {
931 int i;
932 for (i=0; i<=MAX_DEPTH; i++)
933 save_layers[i] = active_layers[i];
934 }
935
936 /* save depth counts and min/max depth */
937
938 void
save_depths(void)939 save_depths(void)
940 {
941 int i;
942 saved_min_depth = min_depth;
943 saved_max_depth = max_depth;
944 for (i=0; i<=MAX_DEPTH; i++)
945 saved_depths[i] = object_depths[i];
946 }
947
948 void
save_counts(void)949 save_counts(void)
950 {
951 int i;
952 for (i=0; i<=MAX_DEPTH; i++)
953 saved_counts[i] = counts[i];
954 }
955
956 void
save_counts_and_clear(void)957 save_counts_and_clear(void)
958 {
959 save_counts();
960 clearallcounts();
961 }
962
963 void
restore_active_layers(void)964 restore_active_layers(void)
965 {
966 int i;
967 for (i=0; i<=MAX_DEPTH; i++)
968 active_layers[i] = save_layers[i];
969 }
970
971 /* restore depth counts and reset min/max depth */
972
973 void
restore_depths(void)974 restore_depths(void)
975 {
976 int i;
977 min_depth = saved_min_depth;
978 max_depth = saved_max_depth;
979 for (i=0; i<=MAX_DEPTH; i++)
980 object_depths[i] = saved_depths[i];
981 /* refresh the layer manager */
982 update_layers();
983 }
984
985 void
restore_counts(void)986 restore_counts(void)
987 {
988 int i;
989 for (i=0; i<=MAX_DEPTH; i++)
990 counts[i] = saved_counts[i];
991 }
992
993 /* swap depth counts and reset min/max depth */
994
995 void
swap_depths(void)996 swap_depths(void)
997 {
998 int i;
999 int temp;
1000
1001 temp = min_depth;
1002 min_depth = saved_min_depth;
1003 saved_min_depth = temp;
1004
1005 temp = max_depth;
1006 max_depth = saved_max_depth;
1007 saved_max_depth = temp;
1008
1009 for (i=0; i<=MAX_DEPTH; i++){
1010 temp = object_depths[i];
1011 object_depths[i] = saved_depths[i];
1012 saved_depths[i] = temp;
1013 }
1014 /* refresh the layer manager */
1015 update_layers();
1016 }
1017
1018 void
swap_counts(void)1019 swap_counts(void)
1020 {
1021 int i;
1022 struct counts temp;
1023 for (i=0; i<=MAX_DEPTH; i++){
1024 temp = counts[i];
1025 counts[i] = saved_counts[i];
1026 saved_counts[i] = temp;
1027 }
1028 }
1029