1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 /* Parts of this file are derived from the file layers_dialog.c in the Gimp:
20 *
21 * The GIMP -- an image manipulation program
22 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <assert.h>
30 #include <string.h>
31 #include <gdk/gdkkeysyms.h>
32 #undef GTK_DISABLE_DEPRECATED
33 #include <gtk/gtk.h>
34
35 #include "intl.h"
36
37 #include "layer_dialog.h"
38 #include "persistence.h"
39 #include "widgets.h"
40 #include "interface.h"
41
42 #include "dia-app-icons.h"
43
44 /* DiaLayerWidget: */
45 #define DIA_LAYER_WIDGET(obj) \
46 GTK_CHECK_CAST (obj, dia_layer_widget_get_type (), DiaLayerWidget)
47 #define DIA_LAYER_WIDGET_CLASS(klass) \
48 GTK_CHECK_CLASS_CAST (klass, dia_layer_widget_get_type (), DiaLayerWidgetClass)
49 #define IS_DIA_LAYER_WIDGET(obj) \
50 GTK_CHECK_TYPE (obj, dia_layer_widget_get_type ())
51
52 typedef struct _DiaLayerWidgetClass DiaLayerWidgetClass;
53 typedef struct _EditLayerDialog EditLayerDialog;
54
55 struct _DiaLayerWidget
56 {
57 GtkListItem list_item;
58
59 Diagram *dia;
60 Layer *layer;
61
62 GtkWidget *visible;
63 GtkWidget *connectable;
64 GtkWidget *label;
65
66 EditLayerDialog *edit_dialog;
67
68 /** If true, the user has set this layers connectivity to on
69 * while it was not selected.
70 */
71 gboolean connect_on;
72 /** If true, the user has set this layers connectivity to off
73 * while it was selected.
74 */
75 gboolean connect_off;
76 };
77
78 struct _EditLayerDialog {
79 GtkWidget *dialog;
80 GtkWidget *name_entry;
81 DiaLayerWidget *layer_widget;
82 };
83
84
85 struct _DiaLayerWidgetClass
86 {
87 GtkListItemClass parent_class;
88 };
89
90 GtkType dia_layer_widget_get_type(void);
91
92 struct LayerDialog {
93 GtkWidget *dialog;
94 GtkWidget *diagram_omenu;
95
96 GtkWidget *layer_list;
97
98 Diagram *diagram;
99 };
100
101 static struct LayerDialog *layer_dialog = NULL;
102
103 typedef struct _ButtonData ButtonData;
104
105 struct _ButtonData {
106 gchar *stock_name;
107 gpointer callback;
108 char *tooltip;
109 };
110
111 enum LayerChangeType {
112 TYPE_DELETE_LAYER,
113 TYPE_ADD_LAYER,
114 TYPE_RAISE_LAYER,
115 TYPE_LOWER_LAYER,
116 };
117
118 struct LayerChange {
119 Change change;
120
121 enum LayerChangeType type;
122 Layer *layer;
123 int index;
124 int applied;
125 };
126
127 struct LayerVisibilityChange {
128 Change change;
129
130 GList *original_visibility;
131 Layer *layer;
132 gboolean is_exclusive;
133 int applied;
134 };
135
136 /** If TRUE, we're in the middle of a internal call to
137 * dia_layer_widget_*_toggled and should not make undo, update diagram etc.
138 *
139 * If these calls were not done by simulating button presses, we could avoid
140 * this hack.
141 */
142 static gboolean internal_call = FALSE;
143
144 static Change *
145 undo_layer(Diagram *dia, Layer *layer, enum LayerChangeType, int index);
146 static struct LayerVisibilityChange *
147 undo_layer_visibility(Diagram *dia, Layer *layer, gboolean exclusive);
148 static void
149 layer_visibility_change_apply(struct LayerVisibilityChange *change,
150 Diagram *dia);
151
152 static void layer_dialog_new_callback(GtkWidget *widget, gpointer gdata);
153 static void layer_dialog_raise_callback(GtkWidget *widget, gpointer gdata);
154 static void layer_dialog_lower_callback(GtkWidget *widget, gpointer gdata);
155 static void layer_dialog_delete_callback(GtkWidget *widget, gpointer gdata);
156 static void layer_dialog_edit_layer(DiaLayerWidget *layer_widget, Diagram *dia, Layer *layer);
157
158 static ButtonData buttons[] = {
159 { GTK_STOCK_ADD, layer_dialog_new_callback, N_("New Layer") },
160 { GTK_STOCK_GO_UP, layer_dialog_raise_callback, N_("Raise Layer") },
161 { GTK_STOCK_GO_DOWN, layer_dialog_lower_callback, N_("Lower Layer") },
162 { GTK_STOCK_DELETE, layer_dialog_delete_callback, N_("Delete Layer") },
163 };
164
165 enum {
166 BUTTON_NEW = 0,
167 BUTTON_RAISE,
168 BUTTON_LOWER,
169 BUTTON_DELETE
170 };
171
172 #define BUTTON_EVENT_MASK GDK_EXPOSURE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | \
173 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
174
175 static int num_buttons = sizeof(buttons)/sizeof(ButtonData);
176
177 #define NORMAL 0
178 #define SELECTED 1
179 #define INSENSITIVE 2
180
181 static GtkWidget *
create_button_box(GtkWidget * parent,gboolean show_labels)182 create_button_box(GtkWidget *parent, gboolean show_labels)
183 {
184 GtkWidget *button;
185 GtkWidget *button_box;
186 int i;
187
188 button_box = gtk_hbox_new (TRUE, 1);
189
190 for (i=0;i<num_buttons;i++) {
191 if (show_labels == TRUE)
192 {
193 button = gtk_button_new_from_stock(buttons[i].stock_name);
194 }
195 else
196 {
197 GtkWidget * image;
198
199 button = gtk_button_new ();
200
201 image = gtk_image_new_from_stock (buttons[i].stock_name,
202 GTK_ICON_SIZE_BUTTON);
203
204 gtk_button_set_image (GTK_BUTTON (button), image);
205 }
206
207 g_signal_connect_swapped (GTK_OBJECT (button), "clicked",
208 G_CALLBACK(buttons[i].callback),
209 GTK_OBJECT (parent));
210
211 if (tool_tips != NULL)
212 gtk_tooltips_set_tip (tool_tips, button, gettext(buttons[i].tooltip), NULL);
213
214 gtk_box_pack_start (GTK_BOX(button_box), button, TRUE, TRUE, 0);
215
216 gtk_widget_show (button);
217 }
218
219 return button_box;
220 }
221
222 static gint
layer_list_events(GtkWidget * widget,GdkEvent * event)223 layer_list_events (GtkWidget *widget,
224 GdkEvent *event)
225 {
226 GdkEventKey *kevent;
227 GdkEventButton *bevent;
228 GtkWidget *event_widget;
229 DiaLayerWidget *layer_widget;
230
231 event_widget = gtk_get_event_widget (event);
232
233 if (GTK_IS_LIST_ITEM (event_widget)) {
234 layer_widget = DIA_LAYER_WIDGET(event_widget);
235
236 switch (event->type) {
237 case GDK_BUTTON_PRESS:
238 bevent = (GdkEventButton *) event;
239 break;
240
241 case GDK_2BUTTON_PRESS:
242 bevent = (GdkEventButton *) event;
243 layer_dialog_edit_layer(layer_widget, NULL, NULL);
244 return TRUE;
245
246 case GDK_KEY_PRESS:
247 kevent = (GdkEventKey *) event;
248 switch (kevent->keyval) {
249 case GDK_Up:
250 /* printf ("up arrow\n"); */
251 break;
252 case GDK_Down:
253 /* printf ("down arrow\n"); */
254 break;
255 default:
256 return FALSE;
257 }
258 return TRUE;
259
260 default:
261 break;
262 }
263 }
264
265 return FALSE;
266 }
267
268 static gboolean
layer_dialog_delete(GtkWidget * widget,gpointer data)269 layer_dialog_delete(GtkWidget *widget, gpointer data)
270 {
271 gtk_widget_hide(widget);
272 /* We're caching, so don't destroy */
273 return TRUE;
274 }
275
276 static void
layer_view_hide_button_clicked(void * not_used)277 layer_view_hide_button_clicked (void * not_used)
278 {
279 integrated_ui_layer_view_hide ();
280 }
281
create_layer_view_widget(void)282 GtkWidget * create_layer_view_widget (void)
283 {
284 GtkWidget *vbox;
285 GtkWidget *hbox;
286 GtkWidget *label;
287 GtkWidget *hide_button;
288 GtkRcStyle *rcstyle; /* For hide_button */
289 GtkWidget *image; /* For hide_button */
290 GtkWidget *list;
291 GtkWidget *separator;
292 GtkWidget *scrolled_win;
293 GtkWidget *button_box;
294
295 /* if layer_dialog were renamed to layer_view_data this would make
296 * more sense.
297 */
298 layer_dialog = g_new (struct LayerDialog, 1);
299
300 layer_dialog->diagram = NULL;
301
302 layer_dialog->dialog = vbox = gtk_vbox_new (FALSE, 1);
303
304 hbox = gtk_hbox_new (FALSE, 1);
305
306 label = gtk_label_new (_ ("Layers:"));
307 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2);
308 gtk_widget_show (label);
309
310 layer_dialog->diagram_omenu = NULL;
311
312 /* Hide Button */
313 hide_button = gtk_button_new ();
314 gtk_button_set_relief (GTK_BUTTON (hide_button), GTK_RELIEF_NONE);
315 gtk_button_set_focus_on_click (GTK_BUTTON (hide_button), FALSE);
316
317 /* make it as small as possible */
318 rcstyle = gtk_rc_style_new ();
319 rcstyle->xthickness = rcstyle->ythickness = 0;
320 gtk_widget_modify_style (hide_button, rcstyle);
321 gtk_rc_style_unref (rcstyle);
322
323 image = gtk_image_new_from_stock (GTK_STOCK_CLOSE,
324 GTK_ICON_SIZE_MENU);
325
326 gtk_container_add (GTK_CONTAINER(hide_button), image);
327 gtk_signal_connect (GTK_OBJECT (hide_button), "clicked",
328 GTK_SIGNAL_FUNC (layer_view_hide_button_clicked), NULL);
329
330 gtk_box_pack_start (GTK_BOX (hbox), hide_button, FALSE, FALSE, 2);
331
332 gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
333 gtk_widget_show_all (hbox);
334
335 button_box = create_button_box(vbox, FALSE);
336
337 gtk_box_pack_start (GTK_BOX (vbox), button_box, FALSE, FALSE, 2);
338 gtk_widget_show (button_box);
339
340 separator = gtk_hseparator_new();
341 gtk_box_pack_start(GTK_BOX(vbox), separator, FALSE, FALSE, 2);
342 gtk_widget_show (separator);
343
344 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
345 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
346 GTK_POLICY_AUTOMATIC,
347 GTK_POLICY_AUTOMATIC);
348 gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 2);
349
350 layer_dialog->layer_list = list = gtk_list_new();
351
352 gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_BROWSE);
353 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), list);
354 gtk_container_set_focus_vadjustment (GTK_CONTAINER (list),
355 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_win)));
356 gtk_widget_show (scrolled_win);
357 gtk_widget_show (list);
358
359 g_signal_connect (GTK_OBJECT (list), "event",
360 (GtkSignalFunc) layer_list_events,
361 NULL);
362
363 return vbox;
364 }
365
366 void
create_layer_dialog(void)367 create_layer_dialog(void)
368 {
369 GtkWidget *dialog;
370 GtkWidget *vbox;
371 GtkWidget *hbox;
372 GtkWidget *label;
373 GtkWidget *omenu;
374 GtkWidget *menu;
375 GtkWidget *list;
376 GtkWidget *separator;
377 GtkWidget *scrolled_win;
378 GtkWidget *button_box;
379 GtkWidget *button;
380
381 layer_dialog = g_new(struct LayerDialog, 1);
382
383 layer_dialog->diagram = NULL;
384
385 layer_dialog->dialog = dialog = gtk_dialog_new ();
386 gtk_window_set_title (GTK_WINDOW (dialog), _("Layers"));
387 gtk_window_set_role (GTK_WINDOW (dialog), "layer_window");
388 gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
389
390 g_signal_connect (GTK_OBJECT (dialog), "delete_event",
391 G_CALLBACK(layer_dialog_delete), NULL);
392 g_signal_connect (GTK_OBJECT (dialog), "destroy",
393 G_CALLBACK(gtk_widget_destroyed),
394 &(layer_dialog->dialog));
395
396 vbox = GTK_DIALOG(dialog)->vbox;
397
398 hbox = gtk_hbox_new(FALSE, 1);
399
400 label = gtk_label_new(_("Diagram:"));
401 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
402 gtk_widget_show (label);
403
404 layer_dialog->diagram_omenu = omenu = gtk_option_menu_new();
405 gtk_box_pack_start(GTK_BOX(hbox), omenu, TRUE, TRUE, 2);
406 gtk_widget_show (omenu);
407
408 menu = gtk_menu_new();
409 gtk_option_menu_set_menu(GTK_OPTION_MENU(omenu), menu);
410
411 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
412 gtk_widget_show (hbox);
413
414 separator = gtk_hseparator_new();
415 gtk_box_pack_start(GTK_BOX(vbox), separator, FALSE, FALSE, 2);
416 gtk_widget_show (separator);
417
418 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
419 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
420 GTK_POLICY_AUTOMATIC,
421 GTK_POLICY_AUTOMATIC);
422 gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 2);
423
424 layer_dialog->layer_list = list = gtk_list_new();
425
426 gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_BROWSE);
427 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), list);
428 gtk_container_set_focus_vadjustment (GTK_CONTAINER (list),
429 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_win)));
430 gtk_widget_show (scrolled_win);
431 gtk_widget_show (list);
432
433 g_signal_connect (GTK_OBJECT (list), "event",
434 (GtkSignalFunc) layer_list_events,
435 NULL);
436
437 button_box = create_button_box(dialog, TRUE);
438
439 gtk_box_pack_start (GTK_BOX (vbox), button_box, FALSE, FALSE, 2);
440 gtk_widget_show (button_box);
441
442 gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
443 2);
444
445 button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
446 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
447 button, TRUE, TRUE, 0);
448 g_signal_connect_swapped(GTK_OBJECT (button), "clicked",
449 G_CALLBACK(gtk_widget_hide),
450 GTK_OBJECT(dialog));
451
452 gtk_widget_show (button);
453
454 persistence_register_window(GTK_WINDOW(dialog));
455
456 layer_dialog_update_diagram_list();
457 }
458
459 static void
dia_layer_select_callback(GtkWidget * widget,gpointer data)460 dia_layer_select_callback(GtkWidget *widget, gpointer data)
461 {
462 DiaLayerWidget *lw;
463 lw = DIA_LAYER_WIDGET(widget);
464
465 /* Don't deselect if we're selected the active layer. This can happen
466 * if the window has been defocused. */
467 if (lw->dia->data->active_layer != lw->layer) {
468 diagram_remove_all_selected(lw->dia, TRUE);
469 }
470 diagram_update_extents(lw->dia);
471 data_set_active_layer(lw->dia->data, lw->layer);
472 diagram_add_update_all(lw->dia);
473 diagram_flush(lw->dia);
474
475 internal_call = TRUE;
476 if (lw->connect_off) { /* If the user wants this off, it becomes so */
477 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lw->connectable), FALSE);
478 } else {
479 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lw->connectable), TRUE);
480 }
481 internal_call = FALSE;
482 }
483
484 static void
dia_layer_deselect_callback(GtkWidget * widget,gpointer data)485 dia_layer_deselect_callback(GtkWidget *widget, gpointer data)
486 {
487 DiaLayerWidget *lw = DIA_LAYER_WIDGET(widget);
488
489 /** If layer dialog or diagram is missing, we are so dead. */
490 if (layer_dialog == NULL || layer_dialog->diagram == NULL) return;
491
492 internal_call = TRUE;
493 /** Set to on if the user has requested so. */
494 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lw->connectable),
495 lw->connect_on);
496 internal_call = FALSE;
497 }
498
499
500 static void
layer_dialog_new_callback(GtkWidget * widget,gpointer gdata)501 layer_dialog_new_callback(GtkWidget *widget, gpointer gdata)
502 {
503 Layer *layer;
504 Diagram *dia;
505 GtkWidget *selected;
506 GList *list = NULL;
507 GtkWidget *layer_widget;
508 int pos;
509 static int next_layer_num = 1;
510
511 dia = layer_dialog->diagram;
512
513 if (dia != NULL) {
514 gchar* new_layer_name = g_strdup_printf(_("New layer %d"),
515 next_layer_num++);
516 layer = new_layer(new_layer_name, dia->data);
517
518 assert(GTK_LIST(layer_dialog->layer_list)->selection != NULL);
519 selected = GTK_LIST(layer_dialog->layer_list)->selection->data;
520 pos = gtk_list_child_position(GTK_LIST(layer_dialog->layer_list), selected);
521
522 data_add_layer_at(dia->data, layer, dia->data->layers->len - pos);
523
524 diagram_add_update_all(dia);
525 diagram_flush(dia);
526
527 layer_widget = dia_layer_widget_new(dia, layer);
528 gtk_widget_show(layer_widget);
529
530 list = g_list_prepend(list, layer_widget);
531
532 gtk_list_insert_items(GTK_LIST(layer_dialog->layer_list), list, pos);
533
534 gtk_list_select_item(GTK_LIST(layer_dialog->layer_list), pos);
535
536 undo_layer(dia, layer, TYPE_ADD_LAYER, dia->data->layers->len - pos);
537 undo_set_transactionpoint(dia->undo);
538 }
539 }
540
541 static void
layer_dialog_delete_callback(GtkWidget * widget,gpointer gdata)542 layer_dialog_delete_callback(GtkWidget *widget, gpointer gdata)
543 {
544 Diagram *dia;
545 GtkWidget *selected;
546 Layer *layer;
547 int pos;
548
549 dia = layer_dialog->diagram;
550
551 if ((dia != NULL) && (dia->data->layers->len>1)) {
552 assert(GTK_LIST(layer_dialog->layer_list)->selection != NULL);
553 selected = GTK_LIST(layer_dialog->layer_list)->selection->data;
554
555 layer = dia->data->active_layer;
556
557 data_delete_layer(dia->data, layer);
558 diagram_add_update_all(dia);
559 diagram_flush(dia);
560
561 pos = gtk_list_child_position(GTK_LIST(layer_dialog->layer_list), selected);
562 gtk_container_remove(GTK_CONTAINER(layer_dialog->layer_list), selected);
563
564 undo_layer(dia, layer, TYPE_DELETE_LAYER,
565 dia->data->layers->len - pos);
566 undo_set_transactionpoint(dia->undo);
567
568 if (--pos<0)
569 pos = 0;
570
571 gtk_list_select_item(GTK_LIST(layer_dialog->layer_list), pos);
572 }
573 }
574
575 static void
layer_dialog_raise_callback(GtkWidget * widget,gpointer gdata)576 layer_dialog_raise_callback(GtkWidget *widget, gpointer gdata)
577 {
578 Layer *layer;
579 Diagram *dia;
580 GtkWidget *selected;
581 GList *list = NULL;
582 int pos;
583
584 dia = layer_dialog->diagram;
585
586 if ((dia != NULL) && (dia->data->layers->len>1)) {
587 assert(GTK_LIST(layer_dialog->layer_list)->selection != NULL);
588 selected = GTK_LIST(layer_dialog->layer_list)->selection->data;
589
590 pos = gtk_list_child_position(GTK_LIST(layer_dialog->layer_list), selected);
591
592 if (pos > 0) {
593 layer = DIA_LAYER_WIDGET(selected)->layer;
594 data_raise_layer(dia->data, layer);
595
596 list = g_list_prepend(list, selected);
597
598 gtk_widget_ref(selected);
599
600 gtk_list_remove_items(GTK_LIST(layer_dialog->layer_list),
601 list);
602
603 gtk_list_insert_items(GTK_LIST(layer_dialog->layer_list),
604 list, pos - 1);
605
606 gtk_widget_unref(selected);
607
608 gtk_list_select_item(GTK_LIST(layer_dialog->layer_list), pos-1);
609
610 diagram_add_update_all(dia);
611 diagram_flush(dia);
612
613 undo_layer(dia, layer, TYPE_RAISE_LAYER, 0);
614 undo_set_transactionpoint(dia->undo);
615 }
616
617 }
618 }
619
620 static void
layer_dialog_lower_callback(GtkWidget * widget,gpointer gdata)621 layer_dialog_lower_callback(GtkWidget *widget, gpointer gdata)
622 {
623 Layer *layer;
624 Diagram *dia;
625 GtkWidget *selected;
626 GList *list = NULL;
627 int pos;
628
629 dia = layer_dialog->diagram;
630
631 if ((dia != NULL) && (dia->data->layers->len>1)) {
632 assert(GTK_LIST(layer_dialog->layer_list)->selection != NULL);
633 selected = GTK_LIST(layer_dialog->layer_list)->selection->data;
634
635 pos = gtk_list_child_position(GTK_LIST(layer_dialog->layer_list), selected);
636
637 if (pos < dia->data->layers->len-1) {
638 layer = DIA_LAYER_WIDGET(selected)->layer;
639 data_lower_layer(dia->data, layer);
640
641 list = g_list_prepend(list, selected);
642
643 gtk_widget_ref(selected);
644
645 gtk_list_remove_items(GTK_LIST(layer_dialog->layer_list),
646 list);
647
648 gtk_list_insert_items(GTK_LIST(layer_dialog->layer_list),
649 list, pos + 1);
650
651 gtk_widget_unref(selected);
652
653 gtk_list_select_item(GTK_LIST(layer_dialog->layer_list), pos+1);
654
655 diagram_add_update_all(dia);
656 diagram_flush(dia);
657
658 undo_layer(dia, layer, TYPE_LOWER_LAYER, 0);
659 undo_set_transactionpoint(dia->undo);
660 }
661
662 }
663 }
664
665
666 static void
layer_dialog_select_diagram_callback(GtkWidget * widget,gpointer gdata)667 layer_dialog_select_diagram_callback(GtkWidget *widget, gpointer gdata)
668 {
669 Diagram *dia = (Diagram *) gdata;
670
671 layer_dialog_set_diagram(dia);
672 }
673
674 void
layer_dialog_update_diagram_list(void)675 layer_dialog_update_diagram_list(void)
676 {
677 GtkWidget *new_menu;
678 GtkWidget *menu_item;
679 GList *dia_list;
680 Diagram *dia;
681 char *filename;
682 int i;
683 int current_nr;
684
685 if (layer_dialog == NULL || layer_dialog->dialog == NULL) {
686 if (!dia_open_diagrams())
687 return; /* shortcut; maybe session end w/o this dialog */
688 else
689 create_layer_dialog();
690 }
691 /* oh this options: here integrated UI ;( */
692 if (!layer_dialog->diagram_omenu)
693 return;
694
695 new_menu = gtk_menu_new();
696
697 current_nr = -1;
698
699 i = 0;
700 dia_list = dia_open_diagrams();
701 while (dia_list != NULL) {
702 dia = (Diagram *) dia_list->data;
703
704 if (dia == layer_dialog->diagram) {
705 current_nr = i;
706 }
707
708 filename = strrchr(dia->filename, G_DIR_SEPARATOR);
709 if (filename==NULL) {
710 filename = dia->filename;
711 } else {
712 filename++;
713 }
714
715 menu_item = gtk_menu_item_new_with_label(filename);
716
717 g_signal_connect (GTK_OBJECT (menu_item), "activate",
718 (GtkSignalFunc) layer_dialog_select_diagram_callback,
719 (gpointer) dia);
720
721 gtk_menu_append( GTK_MENU(new_menu), menu_item);
722 gtk_widget_show (menu_item);
723
724 dia_list = g_list_next(dia_list);
725 i++;
726 }
727
728 if (dia_open_diagrams()==NULL) {
729 menu_item = gtk_menu_item_new_with_label (_("none"));
730 g_signal_connect (GTK_OBJECT (menu_item), "activate",
731 (GtkSignalFunc) layer_dialog_select_diagram_callback,
732 (gpointer) NULL);
733 gtk_menu_append( GTK_MENU(new_menu), menu_item);
734 gtk_widget_show (menu_item);
735 }
736
737 gtk_option_menu_remove_menu(GTK_OPTION_MENU(layer_dialog->diagram_omenu));
738
739 gtk_option_menu_set_menu(GTK_OPTION_MENU(layer_dialog->diagram_omenu),
740 new_menu);
741
742 gtk_option_menu_set_history(GTK_OPTION_MENU(layer_dialog->diagram_omenu),
743 current_nr);
744 gtk_menu_set_active(GTK_MENU(new_menu), current_nr);
745
746 if (current_nr == -1) {
747 dia = NULL;
748 if (dia_open_diagrams()!=NULL) {
749 dia = (Diagram *) dia_open_diagrams()->data;
750 }
751 layer_dialog_set_diagram(dia);
752 }
753 }
754
755 void
layer_dialog_show()756 layer_dialog_show()
757 {
758 if (is_integrated_ui () == FALSE)
759 {
760 if (layer_dialog == NULL || layer_dialog->dialog == NULL)
761 create_layer_dialog();
762 gtk_window_present(GTK_WINDOW(layer_dialog->dialog));
763 }
764 }
765
766 /*
767 * Used to avoid writing to possibly already deleted layer in
768 * dia_layer_widget_connectable_toggled(). Must be called before
769 * e.g. gtk_list_clear_items() cause that will emit the toggled
770 * signal to last focus widget. See bug #329096
771 */
772 static void
_layer_widget_clear_layer(GtkWidget * widget,gpointer user_data)773 _layer_widget_clear_layer (GtkWidget *widget, gpointer user_data)
774 {
775 DiaLayerWidget *lw = DIA_LAYER_WIDGET(widget);
776 lw->layer = NULL;
777 }
778
779 void
layer_dialog_set_diagram(Diagram * dia)780 layer_dialog_set_diagram(Diagram *dia)
781 {
782 DiagramData *data;
783 GtkWidget *layer_widget;
784 Layer *layer;
785 Layer *active_layer = NULL;
786 int sel_pos;
787 int i,j;
788
789 if (dia!=NULL)
790 active_layer = dia->data->active_layer;
791
792 if (layer_dialog == NULL || layer_dialog->dialog == NULL)
793 create_layer_dialog(); /* May have been destroyed */
794
795 gtk_container_foreach (GTK_CONTAINER(layer_dialog->layer_list),
796 _layer_widget_clear_layer, NULL);
797 gtk_list_clear_items(GTK_LIST(layer_dialog->layer_list), 0, -1);
798 layer_dialog->diagram = dia;
799 if (dia != NULL) {
800 i = g_list_index(dia_open_diagrams(), dia);
801 if (i >= 0 && layer_dialog->diagram_omenu != NULL)
802 gtk_option_menu_set_history(GTK_OPTION_MENU(layer_dialog->diagram_omenu),
803 i);
804 }
805
806 if (dia != NULL) {
807 data = dia->data;
808
809 sel_pos = 0;
810 for (i=data->layers->len-1,j=0;i>=0;i--,j++) {
811 layer = (Layer *) g_ptr_array_index(data->layers, i);
812 layer_widget = dia_layer_widget_new(dia, layer);
813 gtk_widget_show(layer_widget);
814 gtk_container_add(GTK_CONTAINER(layer_dialog->layer_list), layer_widget);
815 if (layer==active_layer)
816 sel_pos = j;
817 }
818 gtk_list_select_item(GTK_LIST(layer_dialog->layer_list), sel_pos);
819 }
820 }
821
822
823
824 /******* DiaLayerWidget: *****/
825
826 /* The connectability buttons don't quite behave the way they should.
827 * The shift-click behaviour messes up the active layer.
828 * To fix this, we need to rework the code so that the setting of
829 * connect_on and connect_off is not tied to the button toggling,
830 * but determined by what caused it (creation, user selection,
831 * shift-selection).
832 */
833
834 static void
dia_layer_widget_unrealize(GtkWidget * widget)835 dia_layer_widget_unrealize(GtkWidget *widget)
836 {
837 DiaLayerWidget *lw = DIA_LAYER_WIDGET(widget);
838
839 if (lw->edit_dialog != NULL) {
840 gtk_widget_destroy(lw->edit_dialog->dialog);
841 g_free(lw->edit_dialog);
842 lw->edit_dialog = NULL;
843 }
844
845 (* GTK_WIDGET_CLASS (gtk_type_class(gtk_list_item_get_type ()))->unrealize) (widget);
846 }
847
848 static void
dia_layer_widget_class_init(DiaLayerWidgetClass * klass)849 dia_layer_widget_class_init(DiaLayerWidgetClass *klass)
850 {
851 GtkObjectClass *object_class;
852 GtkWidgetClass *widget_class;
853
854 object_class = (GtkObjectClass*) klass;
855 widget_class = (GtkWidgetClass*) klass;
856
857 widget_class->unrealize = dia_layer_widget_unrealize;
858 }
859
860 static void
dia_layer_widget_set_connectable(DiaLayerWidget * widget,gboolean on)861 dia_layer_widget_set_connectable(DiaLayerWidget *widget, gboolean on)
862 {
863 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget->connectable), on);
864 }
865
866 static void
dia_layer_widget_exclusive_connectable(DiaLayerWidget * layer_widget)867 dia_layer_widget_exclusive_connectable(DiaLayerWidget *layer_widget)
868 {
869 GList *list;
870 DiaLayerWidget *lw;
871 Layer *layer;
872 int connectable = FALSE;
873 int i;
874
875 /* First determine if _any_ other layer widgets are set to connectable */
876 for (i=0;i<layer_widget->dia->data->layers->len;i++) {
877 layer = g_ptr_array_index(layer_widget->dia->data->layers, i);
878 if (layer_widget->layer != layer) {
879 connectable |= layer->connectable;
880 }
881 }
882
883 /* Now, toggle the connectability for all layers except the specified one */
884 list = GTK_LIST(layer_dialog->layer_list)->children;
885 while (list) {
886 lw = DIA_LAYER_WIDGET(list->data);
887 if (lw != layer_widget)
888 dia_layer_widget_set_connectable(lw, !connectable);
889 else {
890 dia_layer_widget_set_connectable(lw, TRUE);
891 }
892 gtk_widget_queue_draw(GTK_WIDGET(lw));
893
894 list = g_list_next(list);
895 }
896 }
897
898 static gboolean shifted = FALSE;
899
900 static gboolean
dia_layer_widget_button_event(GtkWidget * widget,GdkEventButton * event,gpointer userdata)901 dia_layer_widget_button_event(GtkWidget *widget,
902 GdkEventButton *event,
903 gpointer userdata)
904 {
905 DiaLayerWidget *lw = DIA_LAYER_WIDGET(userdata);
906
907 shifted = event->state & GDK_SHIFT_MASK;
908 internal_call = FALSE;
909 /* Redraw the label? */
910 gtk_widget_queue_draw(GTK_WIDGET(lw));
911 return FALSE;
912 }
913
914 static void
dia_layer_widget_connectable_toggled(GtkToggleButton * widget,gpointer userdata)915 dia_layer_widget_connectable_toggled(GtkToggleButton *widget,
916 gpointer userdata)
917 {
918 DiaLayerWidget *lw = DIA_LAYER_WIDGET(userdata);
919 if (!lw->layer)
920 return;
921 if (shifted) {
922 shifted = FALSE;
923 internal_call = TRUE;
924 dia_layer_widget_exclusive_connectable(lw);
925 internal_call = FALSE;
926 } else {
927 lw->layer->connectable = gtk_toggle_button_get_active(widget);
928 }
929 if (lw->layer == lw->dia->data->active_layer) {
930 lw->connect_off = !gtk_toggle_button_get_active(widget);
931 if (lw->connect_off) lw->connect_on = FALSE;
932 } else {
933 lw->connect_on = gtk_toggle_button_get_active(widget);
934 if (lw->connect_on) lw->connect_off = FALSE;
935 }
936 gtk_widget_queue_draw(GTK_WIDGET(lw));
937 if (!internal_call) {
938 diagram_add_update_all(lw->dia);
939 diagram_flush(lw->dia);
940 }
941 }
942
943 static void
dia_layer_widget_visible_clicked(GtkToggleButton * widget,gpointer userdata)944 dia_layer_widget_visible_clicked(GtkToggleButton *widget,
945 gpointer userdata)
946 {
947 DiaLayerWidget *lw = DIA_LAYER_WIDGET(userdata);
948 struct LayerVisibilityChange *change;
949
950 /* Have to use this internal_call hack 'cause there's no way to switch
951 * a toggle button without causing the 'clicked' event:(
952 */
953 if (!internal_call) {
954 Diagram *dia = lw->dia;
955 change = undo_layer_visibility(dia, lw->layer, shifted);
956 /** This apply kills 'lw', thus we have to hold onto 'lw->dia' */
957 layer_visibility_change_apply(change, dia);
958 undo_set_transactionpoint(dia->undo);
959 }
960 }
961
962 static void
dia_layer_widget_init(DiaLayerWidget * lw)963 dia_layer_widget_init(DiaLayerWidget *lw)
964 {
965 GtkWidget *hbox;
966 GtkWidget *visible;
967 GtkWidget *connectable;
968 GtkWidget *label;
969
970 hbox = gtk_hbox_new(FALSE, 0);
971
972 lw->dia = NULL;
973 lw->layer = NULL;
974 lw->edit_dialog = NULL;
975
976 lw->connect_on = FALSE;
977 lw->connect_off = FALSE;
978
979 lw->visible = visible =
980 dia_toggle_button_new_with_icons(dia_visible_icon, dia_visible_empty_icon);
981
982 g_signal_connect(G_OBJECT(visible), "button-release-event",
983 G_CALLBACK(dia_layer_widget_button_event), lw);
984 g_signal_connect(G_OBJECT(visible), "button-press-event",
985 G_CALLBACK(dia_layer_widget_button_event), lw);
986 g_signal_connect(G_OBJECT(visible), "clicked",
987 G_CALLBACK(dia_layer_widget_visible_clicked), lw);
988 gtk_box_pack_start (GTK_BOX (hbox), visible, FALSE, TRUE, 2);
989 gtk_widget_show(visible);
990
991 /*gtk_image_new_from_stock(GTK_STOCK_CONNECT,
992 GTK_ICON_SIZE_BUTTON), */
993 lw->connectable = connectable =
994 dia_toggle_button_new_with_icons(dia_connectable_icon,
995 dia_connectable_empty_icon);
996
997 g_signal_connect(G_OBJECT(connectable), "button-release-event",
998 G_CALLBACK(dia_layer_widget_button_event), lw);
999 g_signal_connect(G_OBJECT(connectable), "button-press-event",
1000 G_CALLBACK(dia_layer_widget_button_event), lw);
1001 g_signal_connect(G_OBJECT(connectable), "clicked",
1002 G_CALLBACK(dia_layer_widget_connectable_toggled), lw);
1003
1004 gtk_box_pack_start (GTK_BOX (hbox), connectable, FALSE, TRUE, 2);
1005 gtk_widget_show(connectable);
1006
1007 lw->label = label = gtk_label_new("layer_default_label");
1008 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
1009 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
1010 gtk_widget_show(label);
1011
1012 gtk_widget_show(hbox);
1013
1014 gtk_container_add(GTK_CONTAINER(lw), hbox);
1015
1016 g_signal_connect (GTK_OBJECT (lw), "select",
1017 (GtkSignalFunc) dia_layer_select_callback,
1018 (gpointer) NULL);
1019 g_signal_connect (GTK_OBJECT (lw), "deselect",
1020 (GtkSignalFunc) dia_layer_deselect_callback,
1021 (gpointer) NULL);
1022 }
1023
1024 GtkType
dia_layer_widget_get_type(void)1025 dia_layer_widget_get_type(void)
1026 {
1027 static GtkType dlw_type = 0;
1028
1029 if (!dlw_type) {
1030 static const GtkTypeInfo dlw_info = {
1031 "DiaLayerWidget",
1032 sizeof (DiaLayerWidget),
1033 sizeof (DiaLayerWidgetClass),
1034 (GtkClassInitFunc) dia_layer_widget_class_init,
1035 (GtkObjectInitFunc) dia_layer_widget_init,
1036 NULL,
1037 NULL,
1038 (GtkClassInitFunc) NULL,
1039 };
1040
1041 dlw_type = gtk_type_unique (gtk_list_item_get_type (), &dlw_info);
1042 }
1043
1044 return dlw_type;
1045 }
1046
1047 GtkWidget *
dia_layer_widget_new(Diagram * dia,Layer * layer)1048 dia_layer_widget_new(Diagram *dia, Layer *layer)
1049 {
1050 GtkWidget *widget;
1051
1052 widget = GTK_WIDGET ( gtk_type_new (dia_layer_widget_get_type ()));
1053 dia_layer_set_layer(DIA_LAYER_WIDGET(widget), dia, layer);
1054
1055 /* These may get toggled when the button is set without the widget being
1056 * selected first. */
1057 DIA_LAYER_WIDGET(widget)->connect_on = FALSE;
1058 DIA_LAYER_WIDGET(widget)->connect_off = FALSE;
1059
1060 return widget;
1061 }
1062
1063 /** Layer has either been selected or created */
1064 void
dia_layer_set_layer(DiaLayerWidget * widget,Diagram * dia,Layer * layer)1065 dia_layer_set_layer(DiaLayerWidget *widget, Diagram *dia, Layer *layer)
1066 {
1067 widget->dia = dia;
1068 widget->layer = layer;
1069
1070 dia_layer_update_from_layer(widget);
1071 }
1072
1073 void
dia_layer_update_from_layer(DiaLayerWidget * widget)1074 dia_layer_update_from_layer (DiaLayerWidget *widget)
1075 {
1076 internal_call = TRUE;
1077 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget->visible),
1078 widget->layer->visible);
1079
1080 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget->connectable),
1081 widget->layer->connectable);
1082 internal_call = FALSE;
1083
1084 gtk_label_set_text (GTK_LABEL (widget->label), widget->layer->name);
1085 }
1086
1087
1088 /*
1089 * The edit layer attributes dialog
1090 */
1091 /* called from the layer widget for rename */
1092 static void
edit_layer_ok_callback(GtkWidget * w,gpointer client_data)1093 edit_layer_ok_callback (GtkWidget *w, gpointer client_data)
1094 {
1095 EditLayerDialog *dialog = (EditLayerDialog *) client_data;
1096 Layer *layer;
1097
1098 g_return_if_fail (dialog->layer_widget != NULL);
1099
1100 layer = dialog->layer_widget->layer;
1101
1102 g_free (layer->name);
1103 layer->name = g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->name_entry)));
1104
1105 diagram_add_update_all (dialog->layer_widget->dia);
1106 diagram_flush (dialog->layer_widget->dia);
1107
1108 dia_layer_update_from_layer (dialog->layer_widget);
1109
1110 dialog->layer_widget->edit_dialog = NULL;
1111 gtk_widget_destroy (dialog->dialog);
1112 g_free (dialog);
1113 }
1114
1115 static void
edit_layer_add_ok_callback(GtkWidget * w,gpointer client_data)1116 edit_layer_add_ok_callback (GtkWidget *w, gpointer client_data)
1117 {
1118 EditLayerDialog *dialog = (EditLayerDialog *) client_data;
1119 Diagram *dia = ddisplay_active_diagram();
1120 Layer *layer;
1121 int pos = data_layer_get_index (dia->data, dia->data->active_layer) + 1;
1122
1123 layer = new_layer(g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->name_entry))), dia->data);
1124 data_add_layer_at(dia->data, layer, pos);
1125 data_set_active_layer(dia->data, layer);
1126
1127 diagram_add_update_all(dia);
1128 diagram_flush(dia);
1129
1130 undo_layer(dia, layer, TYPE_ADD_LAYER, pos);
1131 undo_set_transactionpoint(dia->undo);
1132
1133 gtk_widget_destroy (dialog->dialog);
1134 g_free (dialog);
1135 }
1136
1137 static void
edit_layer_rename_ok_callback(GtkWidget * w,gpointer client_data)1138 edit_layer_rename_ok_callback (GtkWidget *w, gpointer client_data)
1139 {
1140 EditLayerDialog *dialog = (EditLayerDialog *) client_data;
1141 Diagram *dia = ddisplay_active_diagram();
1142 Layer *layer = dia->data->active_layer;
1143
1144 g_free (layer->name);
1145 layer->name = g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->name_entry)));
1146
1147 diagram_add_update_all(dia);
1148 diagram_flush(dia);
1149 /* FIXME: undo handling */
1150
1151 gtk_widget_destroy (dialog->dialog);
1152 g_free (dialog);
1153 }
1154 static void
edit_layer_cancel_callback(GtkWidget * w,gpointer client_data)1155 edit_layer_cancel_callback (GtkWidget *w,
1156 gpointer client_data)
1157 {
1158 EditLayerDialog *dialog;
1159
1160 dialog = (EditLayerDialog *) client_data;
1161
1162 if (dialog->layer_widget)
1163 dialog->layer_widget->edit_dialog = NULL;
1164 if (dialog->dialog != NULL)
1165 gtk_widget_destroy (dialog->dialog);
1166 g_free (dialog);
1167 }
1168
1169 static gint
edit_layer_delete_callback(GtkWidget * w,GdkEvent * e,gpointer client_data)1170 edit_layer_delete_callback (GtkWidget *w,
1171 GdkEvent *e,
1172 gpointer client_data)
1173 {
1174 edit_layer_cancel_callback (w, client_data);
1175
1176 return TRUE;
1177 }
1178
1179 static void
layer_dialog_edit_layer(DiaLayerWidget * layer_widget,Diagram * dia,Layer * layer)1180 layer_dialog_edit_layer (DiaLayerWidget *layer_widget, Diagram *dia, Layer *layer)
1181 {
1182 EditLayerDialog *dialog;
1183 GtkWidget *vbox;
1184 GtkWidget *hbox;
1185 GtkWidget *label;
1186 GtkWidget *button;
1187
1188 /* the new dialog structure */
1189 dialog = (EditLayerDialog *) g_malloc (sizeof (EditLayerDialog));
1190 dialog->layer_widget = layer_widget;
1191
1192 /* the dialog */
1193 dialog->dialog = gtk_dialog_new ();
1194 gtk_window_set_role (GTK_WINDOW (dialog->dialog), "edit_layer_attrributes");
1195 gtk_window_set_title (GTK_WINDOW (dialog->dialog),
1196 (layer_widget || layer) ? _("Edit Layer") : _("Add Layer"));
1197 gtk_window_set_position (GTK_WINDOW (dialog->dialog), GTK_WIN_POS_MOUSE);
1198
1199 /* handle the wm close signal */
1200 g_signal_connect (GTK_OBJECT (dialog->dialog), "delete_event",
1201 G_CALLBACK (edit_layer_delete_callback),
1202 dialog);
1203 g_signal_connect (GTK_OBJECT (dialog->dialog), "destroy",
1204 G_CALLBACK (gtk_widget_destroy),
1205 &dialog->dialog);
1206
1207 /* the main vbox */
1208 vbox = gtk_vbox_new (FALSE, 1);
1209 gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
1210 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog->dialog)->vbox), vbox, TRUE, TRUE, 0);
1211
1212 /* the name entry hbox, label and entry */
1213 hbox = gtk_hbox_new (FALSE, 1);
1214 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1215 label = gtk_label_new (_("Layer name:"));
1216 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1217 gtk_widget_show (label);
1218 dialog->name_entry = gtk_entry_new ();
1219 gtk_box_pack_start (GTK_BOX (hbox), dialog->name_entry, TRUE, TRUE, 0);
1220 if (layer_widget)
1221 gtk_entry_set_text (GTK_ENTRY (dialog->name_entry), layer_widget->layer->name);
1222 else if (layer)
1223 gtk_entry_set_text (GTK_ENTRY (dialog->name_entry), layer->name);
1224 else if (dia) {
1225 gchar *name = g_strdup_printf (_("New layer %d"), dia->data->layers->len);
1226 gtk_entry_set_text (GTK_ENTRY (dialog->name_entry), name);
1227 g_free (name);
1228 }
1229
1230 gtk_widget_show (dialog->name_entry);
1231 gtk_widget_show (hbox);
1232
1233 button = gtk_button_new_from_stock (GTK_STOCK_OK);
1234 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
1235 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog->dialog)->action_area),
1236 button, TRUE, TRUE, 0);
1237 if (layer_widget)
1238 g_signal_connect (GTK_OBJECT (button), "clicked",
1239 G_CALLBACK(edit_layer_ok_callback), dialog);
1240 else if (layer)
1241 g_signal_connect (GTK_OBJECT (button), "clicked",
1242 G_CALLBACK(edit_layer_rename_ok_callback), dialog);
1243 else if (dia)
1244 g_signal_connect (GTK_OBJECT (button), "clicked",
1245 G_CALLBACK(edit_layer_add_ok_callback), dialog);
1246
1247 gtk_widget_grab_default (button);
1248 gtk_widget_show (button);
1249
1250 button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
1251 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
1252 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog->dialog)->action_area),
1253 button, TRUE, TRUE, 0);
1254 g_signal_connect (GTK_OBJECT (button), "clicked",
1255 G_CALLBACK(edit_layer_cancel_callback),
1256 dialog);
1257 gtk_widget_show (button);
1258
1259 gtk_widget_show (vbox);
1260 gtk_widget_show (dialog->dialog);
1261
1262 if (layer_widget)
1263 layer_widget->edit_dialog = dialog;
1264 }
1265
1266
1267 /******** layer changes: */
1268
1269 static void
layer_change_apply(struct LayerChange * change,Diagram * dia)1270 layer_change_apply(struct LayerChange *change, Diagram *dia)
1271 {
1272 change->applied = 1;
1273
1274 switch (change->type) {
1275 case TYPE_DELETE_LAYER:
1276 data_delete_layer(dia->data, change->layer);
1277 break;
1278 case TYPE_ADD_LAYER:
1279 data_add_layer_at(dia->data, change->layer, change->index);
1280 break;
1281 case TYPE_RAISE_LAYER:
1282 data_raise_layer(dia->data, change->layer);
1283 break;
1284 case TYPE_LOWER_LAYER:
1285 data_lower_layer(dia->data, change->layer);
1286 break;
1287 }
1288
1289 diagram_add_update_all(dia);
1290
1291 if (layer_dialog->diagram == dia) {
1292 layer_dialog_set_diagram(dia);
1293 }
1294 }
1295
1296 static void
layer_change_revert(struct LayerChange * change,Diagram * dia)1297 layer_change_revert(struct LayerChange *change, Diagram *dia)
1298 {
1299 switch (change->type) {
1300 case TYPE_DELETE_LAYER:
1301 data_add_layer_at(dia->data, change->layer, change->index);
1302 break;
1303 case TYPE_ADD_LAYER:
1304 data_delete_layer(dia->data, change->layer);
1305 break;
1306 case TYPE_RAISE_LAYER:
1307 data_lower_layer(dia->data, change->layer);
1308 break;
1309 case TYPE_LOWER_LAYER:
1310 data_raise_layer(dia->data, change->layer);
1311 break;
1312 }
1313
1314 diagram_add_update_all(dia);
1315
1316 if (layer_dialog->diagram == dia) {
1317 layer_dialog_set_diagram(dia);
1318 }
1319
1320 change->applied = 0;
1321 }
1322
1323 static void
layer_change_free(struct LayerChange * change)1324 layer_change_free(struct LayerChange *change)
1325 {
1326 switch (change->type) {
1327 case TYPE_DELETE_LAYER:
1328 if (change->applied) {
1329 layer_destroy(change->layer);
1330 }
1331 break;
1332 case TYPE_ADD_LAYER:
1333 if (!change->applied) {
1334 layer_destroy(change->layer);
1335 }
1336 break;
1337 case TYPE_RAISE_LAYER:
1338 break;
1339 case TYPE_LOWER_LAYER:
1340 break;
1341 }
1342 }
1343
1344 static Change *
undo_layer(Diagram * dia,Layer * layer,enum LayerChangeType type,int index)1345 undo_layer(Diagram *dia, Layer *layer, enum LayerChangeType type, int index)
1346 {
1347 struct LayerChange *change;
1348
1349 change = g_new0(struct LayerChange, 1);
1350
1351 change->change.apply = (UndoApplyFunc) layer_change_apply;
1352 change->change.revert = (UndoRevertFunc) layer_change_revert;
1353 change->change.free = (UndoFreeFunc) layer_change_free;
1354
1355 change->type = type;
1356 change->layer = layer;
1357 change->index = index;
1358 change->applied = 1;
1359
1360 undo_push_change(dia->undo, (Change *) change);
1361 return (Change *)change;
1362 }
1363
1364 static void
layer_visibility_change_apply(struct LayerVisibilityChange * change,Diagram * dia)1365 layer_visibility_change_apply(struct LayerVisibilityChange *change,
1366 Diagram *dia)
1367 {
1368 GPtrArray *layers;
1369 Layer *layer = change->layer;
1370 int visible = FALSE;
1371 int i;
1372
1373 if (change->is_exclusive) {
1374 /* First determine if _any_ other layer widgets are set to visible.
1375 * If there is, exclusive switching turns all off. */
1376 for (i=0;i<dia->data->layers->len;i++) {
1377 Layer *temp_layer = g_ptr_array_index(dia->data->layers, i);
1378 if (temp_layer != layer) {
1379 visible |= temp_layer->visible;
1380 }
1381 }
1382
1383 /* Now, toggle the visibility for all layers except the specified one */
1384 layers = dia->data->layers;
1385 for (i = 0; i < layers->len; i++) {
1386 Layer *temp_layer = (Layer *) g_ptr_array_index(layers, i);
1387 if (temp_layer == layer) {
1388 temp_layer->visible = TRUE;
1389 } else {
1390 temp_layer->visible = !visible;
1391 }
1392 }
1393 } else {
1394 layer->visible = !layer->visible;
1395 }
1396 diagram_add_update_all(dia);
1397
1398 if (layer_dialog->diagram == dia) {
1399 layer_dialog_set_diagram(dia);
1400 }
1401 }
1402
1403 /** Revert to the visibility before this change was applied.
1404 */
1405 static void
layer_visibility_change_revert(struct LayerVisibilityChange * change,Diagram * dia)1406 layer_visibility_change_revert(struct LayerVisibilityChange *change,
1407 Diagram *dia)
1408 {
1409 GList *vis = change->original_visibility;
1410 GPtrArray *layers = dia->data->layers;
1411 int i;
1412
1413 for (i = 0; vis != NULL && i < layers->len; vis = g_list_next(vis), i++) {
1414 Layer *layer = (Layer*) g_ptr_array_index(layers, i);
1415 layer->visible = (gboolean)vis->data;
1416 }
1417
1418 if (vis != NULL || i < layers->len) {
1419 printf("Internal error: visibility undo has %d visibilities, but %d layers\n",
1420 g_list_length(change->original_visibility), layers->len);
1421 }
1422
1423 diagram_add_update_all(dia);
1424
1425 if (layer_dialog->diagram == dia) {
1426 layer_dialog_set_diagram(dia);
1427 }
1428 }
1429
1430 static void
layer_visibility_change_free(struct LayerVisibilityChange * change)1431 layer_visibility_change_free(struct LayerVisibilityChange *change)
1432 {
1433 g_list_free(change->original_visibility);
1434 }
1435
1436 static struct LayerVisibilityChange *
undo_layer_visibility(Diagram * dia,Layer * layer,gboolean exclusive)1437 undo_layer_visibility(Diagram *dia, Layer *layer, gboolean exclusive)
1438 {
1439 struct LayerVisibilityChange *change;
1440 GList *visibilities = NULL;
1441 int i;
1442 GPtrArray *layers = dia->data->layers;
1443
1444 change = g_new0(struct LayerVisibilityChange, 1);
1445
1446 change->change.apply = (UndoApplyFunc) layer_visibility_change_apply;
1447 change->change.revert = (UndoRevertFunc) layer_visibility_change_revert;
1448 change->change.free = (UndoFreeFunc) layer_visibility_change_free;
1449
1450 for (i = 0; i < layers->len; i++) {
1451 Layer *temp_layer = (Layer *) g_ptr_array_index(layers, i);
1452 visibilities = g_list_append(visibilities, (gpointer)temp_layer->visible);
1453 }
1454
1455 change->original_visibility = visibilities;
1456 change->layer = layer;
1457 change->is_exclusive = exclusive;
1458
1459 undo_push_change(dia->undo, (Change *) change);
1460 return change;
1461 }
1462
1463 /*!
1464 * \brief edit a layers name, possibly also creating the layer
1465 */
1466 void
diagram_edit_layer(Diagram * dia,Layer * layer)1467 diagram_edit_layer(Diagram *dia, Layer *layer)
1468 {
1469 g_return_if_fail(dia != NULL);
1470
1471 layer_dialog_edit_layer (NULL, layer ? NULL : dia, layer);
1472 }
1473