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