1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
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.
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.
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.
19 /* Parts of this file are derived from the file layers_dialog.c in the Gimp:
21 * The GIMP -- an image manipulation program
22 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
31 #include <gdk/gdkkeysyms.h>
36 #include "layer_dialog.h"
37 #include "persistence.h"
39 #include "interface.h"
41 #include "dia-app-icons.h"
43 static struct LayerDialog
*layer_dialog
= NULL
;
45 typedef struct _ButtonData ButtonData
;
53 enum LayerChangeType
{
63 enum LayerChangeType type
;
69 struct LayerVisibilityChange
{
72 GList
*original_visibility
;
74 gboolean is_exclusive
;
78 /** If TRUE, we're in the middle of a internal call to
79 * dia_layer_widget_*_toggled and should not make undo, update diagram etc.
81 * If these calls were not done by simulating button presses, we could avoid
84 static gboolean internal_call
= FALSE
;
87 undo_layer(Diagram
*dia
, Layer
*layer
, enum LayerChangeType
, int index
);
88 static struct LayerVisibilityChange
*
89 undo_layer_visibility(Diagram
*dia
, Layer
*layer
, gboolean exclusive
);
91 layer_visibility_change_apply(struct LayerVisibilityChange
*change
,
94 static void layer_dialog_new_callback(GtkWidget
*widget
, gpointer gdata
);
95 static void layer_dialog_raise_callback(GtkWidget
*widget
, gpointer gdata
);
96 static void layer_dialog_lower_callback(GtkWidget
*widget
, gpointer gdata
);
97 static void layer_dialog_delete_callback(GtkWidget
*widget
, gpointer gdata
);
98 static void layer_dialog_edit_layer(DiaLayerWidget
*layer_widget
);
100 static ButtonData buttons
[] = {
101 { GTK_STOCK_ADD
, layer_dialog_new_callback
, N_("New Layer") },
102 { GTK_STOCK_GO_UP
, layer_dialog_raise_callback
, N_("Raise Layer") },
103 { GTK_STOCK_GO_DOWN
, layer_dialog_lower_callback
, N_("Lower Layer") },
104 { GTK_STOCK_DELETE
, layer_dialog_delete_callback
, N_("Delete Layer") },
114 #define BUTTON_EVENT_MASK GDK_EXPOSURE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | \
115 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
117 static int num_buttons
= sizeof(buttons
)/sizeof(ButtonData
);
121 #define INSENSITIVE 2
124 create_button_box(GtkWidget
*parent
)
127 GtkWidget
*button_box
;
130 button_box
= gtk_hbox_new (TRUE
, 1);
132 for (i
=0;i
<num_buttons
;i
++) {
133 button
= gtk_button_new_from_stock(buttons
[i
].stock_name
);
134 g_signal_connect_swapped (GTK_OBJECT (button
), "clicked",
135 G_CALLBACK(buttons
[i
].callback
),
136 GTK_OBJECT (parent
));
138 if (tool_tips
!= NULL
)
139 gtk_tooltips_set_tip (tool_tips
, button
, gettext(buttons
[i
].tooltip
), NULL
);
141 gtk_box_pack_start (GTK_BOX(button_box
), button
, TRUE
, TRUE
, 0);
143 layer_dialog
->buttons
[i
] = button
;
145 gtk_widget_show (button
);
152 layer_list_events (GtkWidget
*widget
,
156 GdkEventButton
*bevent
;
157 GtkWidget
*event_widget
;
158 DiaLayerWidget
*layer_widget
;
160 event_widget
= gtk_get_event_widget (event
);
162 if (GTK_IS_LIST_ITEM (event_widget
)) {
163 layer_widget
= DIA_LAYER_WIDGET(event_widget
);
165 switch (event
->type
) {
166 case GDK_BUTTON_PRESS
:
167 bevent
= (GdkEventButton
*) event
;
170 case GDK_2BUTTON_PRESS
:
171 bevent
= (GdkEventButton
*) event
;
172 layer_dialog_edit_layer(layer_widget
);
176 kevent
= (GdkEventKey
*) event
;
177 switch (kevent
->keyval
) {
179 /* printf ("up arrow\n"); */
182 /* printf ("down arrow\n"); */
198 layer_dialog_delete(GtkWidget
*widget
, gpointer data
)
200 gtk_widget_hide(widget
);
201 /* We're caching, so don't destroy */
206 create_layer_dialog(void)
215 GtkWidget
*separator
;
216 GtkWidget
*scrolled_win
;
217 GtkWidget
*button_box
;
220 layer_dialog
= g_new(struct LayerDialog
, 1);
222 layer_dialog
->diagram
= NULL
;
224 layer_dialog
->dialog
= dialog
= gtk_dialog_new ();
225 gtk_window_set_title (GTK_WINDOW (dialog
), _("Layers"));
226 gtk_window_set_role (GTK_WINDOW (dialog
), "layer_window");
227 gtk_window_set_resizable (GTK_WINDOW (dialog
), TRUE
);
229 g_signal_connect (GTK_OBJECT (dialog
), "delete_event",
230 G_CALLBACK(layer_dialog_delete
), NULL
);
231 g_signal_connect (GTK_OBJECT (dialog
), "destroy",
232 G_CALLBACK(gtk_widget_destroyed
),
233 &(layer_dialog
->dialog
));
235 vbox
= GTK_DIALOG(dialog
)->vbox
;
237 hbox
= gtk_hbox_new(FALSE
, 1);
239 label
= gtk_label_new(_("Diagram:"));
240 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 2);
241 gtk_widget_show (label
);
243 layer_dialog
->diagram_omenu
= omenu
= gtk_option_menu_new();
244 gtk_box_pack_start(GTK_BOX(hbox
), omenu
, TRUE
, TRUE
, 2);
245 gtk_widget_show (omenu
);
247 menu
= gtk_menu_new();
248 gtk_option_menu_set_menu(GTK_OPTION_MENU(omenu
), menu
);
250 gtk_box_pack_start(GTK_BOX(vbox
), hbox
, FALSE
, FALSE
, 2);
251 gtk_widget_show (hbox
);
253 separator
= gtk_hseparator_new();
254 gtk_box_pack_start(GTK_BOX(vbox
), separator
, FALSE
, FALSE
, 2);
255 gtk_widget_show (separator
);
257 scrolled_win
= gtk_scrolled_window_new (NULL
, NULL
);
258 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win
),
259 GTK_POLICY_AUTOMATIC
,
260 GTK_POLICY_AUTOMATIC
);
261 gtk_box_pack_start (GTK_BOX (vbox
), scrolled_win
, TRUE
, TRUE
, 2);
263 layer_dialog
->layer_list
= list
= gtk_list_new();
265 gtk_list_set_selection_mode (GTK_LIST (list
), GTK_SELECTION_BROWSE
);
266 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win
), list
);
267 gtk_container_set_focus_vadjustment (GTK_CONTAINER (list
),
268 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_win
)));
269 gtk_widget_show (scrolled_win
);
270 gtk_widget_show (list
);
272 g_signal_connect (GTK_OBJECT (list
), "event",
273 (GtkSignalFunc
) layer_list_events
,
276 button_box
= create_button_box(dialog
);
278 gtk_box_pack_start (GTK_BOX (vbox
), button_box
, FALSE
, FALSE
, 2);
279 gtk_widget_show (button_box
);
281 gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog
)->action_area
),
284 button
= gtk_button_new_from_stock (GTK_STOCK_CLOSE
);
285 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog
)->action_area
),
286 button
, TRUE
, TRUE
, 0);
287 g_signal_connect_swapped(GTK_OBJECT (button
), "clicked",
288 G_CALLBACK(gtk_widget_hide
),
291 gtk_widget_show (button
);
293 persistence_register_window(GTK_WINDOW(dialog
));
295 layer_dialog_update_diagram_list();
299 dia_layer_select_callback(GtkWidget
*widget
, gpointer data
)
302 lw
= DIA_LAYER_WIDGET(widget
);
304 diagram_remove_all_selected(lw
->dia
, TRUE
);
305 diagram_update_extents(lw
->dia
);
306 data_set_active_layer(lw
->dia
->data
, lw
->layer
);
307 diagram_add_update_all(lw
->dia
);
308 diagram_flush(lw
->dia
);
310 internal_call
= TRUE
;
311 if (lw
->connect_off
) { /* If the user wants this off, it becomes so */
312 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lw
->connectable
), FALSE
);
314 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lw
->connectable
), TRUE
);
316 internal_call
= FALSE
;
320 dia_layer_deselect_callback(GtkWidget
*widget
, gpointer data
)
322 DiaLayerWidget
*lw
= DIA_LAYER_WIDGET(widget
);
324 /** If layer dialog or diagram is missing, we are so dead. */
325 if (layer_dialog
== NULL
|| layer_dialog
->diagram
== NULL
) return;
327 internal_call
= TRUE
;
328 /** Set to on if the user has requested so. */
329 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lw
->connectable
),
331 internal_call
= FALSE
;
336 layer_dialog_new_callback(GtkWidget
*widget
, gpointer gdata
)
342 GtkWidget
*layer_widget
;
344 static int next_layer_num
= 1;
346 dia
= layer_dialog
->diagram
;
349 gchar
* new_layer_name
= g_strdup_printf(_("New layer %d"),
351 layer
= new_layer(new_layer_name
, dia
->data
);
353 assert(GTK_LIST(layer_dialog
->layer_list
)->selection
!= NULL
);
354 selected
= GTK_LIST(layer_dialog
->layer_list
)->selection
->data
;
355 pos
= gtk_list_child_position(GTK_LIST(layer_dialog
->layer_list
), selected
);
357 data_add_layer_at(dia
->data
, layer
, dia
->data
->layers
->len
- pos
);
359 diagram_add_update_all(dia
);
362 layer_widget
= dia_layer_widget_new(dia
, layer
);
363 gtk_widget_show(layer_widget
);
365 list
= g_list_prepend(list
, layer_widget
);
367 gtk_list_insert_items(GTK_LIST(layer_dialog
->layer_list
), list
, pos
);
369 gtk_list_select_item(GTK_LIST(layer_dialog
->layer_list
), pos
);
371 undo_layer(dia
, layer
, TYPE_ADD_LAYER
, dia
->data
->layers
->len
- pos
);
372 undo_set_transactionpoint(dia
->undo
);
377 layer_dialog_delete_callback(GtkWidget
*widget
, gpointer gdata
)
384 dia
= layer_dialog
->diagram
;
386 if ((dia
!= NULL
) && (dia
->data
->layers
->len
>1)) {
387 assert(GTK_LIST(layer_dialog
->layer_list
)->selection
!= NULL
);
388 selected
= GTK_LIST(layer_dialog
->layer_list
)->selection
->data
;
390 layer
= dia
->data
->active_layer
;
392 data_delete_layer(dia
->data
, layer
);
393 diagram_add_update_all(dia
);
396 pos
= gtk_list_child_position(GTK_LIST(layer_dialog
->layer_list
), selected
);
397 gtk_container_remove(GTK_CONTAINER(layer_dialog
->layer_list
), selected
);
399 undo_layer(dia
, layer
, TYPE_DELETE_LAYER
,
400 dia
->data
->layers
->len
- pos
);
401 undo_set_transactionpoint(dia
->undo
);
406 gtk_list_select_item(GTK_LIST(layer_dialog
->layer_list
), pos
);
411 layer_dialog_raise_callback(GtkWidget
*widget
, gpointer gdata
)
419 dia
= layer_dialog
->diagram
;
421 if ((dia
!= NULL
) && (dia
->data
->layers
->len
>1)) {
422 assert(GTK_LIST(layer_dialog
->layer_list
)->selection
!= NULL
);
423 selected
= GTK_LIST(layer_dialog
->layer_list
)->selection
->data
;
425 pos
= gtk_list_child_position(GTK_LIST(layer_dialog
->layer_list
), selected
);
428 layer
= DIA_LAYER_WIDGET(selected
)->layer
;
429 data_raise_layer(dia
->data
, layer
);
431 list
= g_list_prepend(list
, selected
);
433 gtk_widget_ref(selected
);
435 gtk_list_remove_items(GTK_LIST(layer_dialog
->layer_list
),
438 gtk_list_insert_items(GTK_LIST(layer_dialog
->layer_list
),
441 gtk_widget_unref(selected
);
443 gtk_list_select_item(GTK_LIST(layer_dialog
->layer_list
), pos
-1);
445 diagram_add_update_all(dia
);
448 undo_layer(dia
, layer
, TYPE_RAISE_LAYER
, 0);
449 undo_set_transactionpoint(dia
->undo
);
456 layer_dialog_lower_callback(GtkWidget
*widget
, gpointer gdata
)
464 dia
= layer_dialog
->diagram
;
466 if ((dia
!= NULL
) && (dia
->data
->layers
->len
>1)) {
467 assert(GTK_LIST(layer_dialog
->layer_list
)->selection
!= NULL
);
468 selected
= GTK_LIST(layer_dialog
->layer_list
)->selection
->data
;
470 pos
= gtk_list_child_position(GTK_LIST(layer_dialog
->layer_list
), selected
);
472 if (pos
< dia
->data
->layers
->len
-1) {
473 layer
= DIA_LAYER_WIDGET(selected
)->layer
;
474 data_lower_layer(dia
->data
, layer
);
476 list
= g_list_prepend(list
, selected
);
478 gtk_widget_ref(selected
);
480 gtk_list_remove_items(GTK_LIST(layer_dialog
->layer_list
),
483 gtk_list_insert_items(GTK_LIST(layer_dialog
->layer_list
),
486 gtk_widget_unref(selected
);
488 gtk_list_select_item(GTK_LIST(layer_dialog
->layer_list
), pos
+1);
490 diagram_add_update_all(dia
);
493 undo_layer(dia
, layer
, TYPE_LOWER_LAYER
, 0);
494 undo_set_transactionpoint(dia
->undo
);
502 layer_dialog_select_diagram_callback(GtkWidget
*widget
, gpointer gdata
)
504 Diagram
*dia
= (Diagram
*) gdata
;
506 layer_dialog_set_diagram(dia
);
510 layer_dialog_update_diagram_list(void)
513 GtkWidget
*menu_item
;
520 if (layer_dialog
== NULL
|| layer_dialog
->dialog
== NULL
) {
521 if (!dia_open_diagrams())
522 return; /* shortcut; maybe session end w/o this dialog */
524 create_layer_dialog();
527 new_menu
= gtk_menu_new();
532 dia_list
= dia_open_diagrams();
533 while (dia_list
!= NULL
) {
534 dia
= (Diagram
*) dia_list
->data
;
536 if (dia
== layer_dialog
->diagram
) {
540 filename
= strrchr(dia
->filename
, G_DIR_SEPARATOR
);
541 if (filename
==NULL
) {
542 filename
= dia
->filename
;
547 menu_item
= gtk_menu_item_new_with_label(filename
);
549 g_signal_connect (GTK_OBJECT (menu_item
), "activate",
550 (GtkSignalFunc
) layer_dialog_select_diagram_callback
,
553 gtk_menu_append( GTK_MENU(new_menu
), menu_item
);
554 gtk_widget_show (menu_item
);
556 dia_list
= g_list_next(dia_list
);
560 if (dia_open_diagrams()==NULL
) {
561 menu_item
= gtk_menu_item_new_with_label (_("none"));
562 g_signal_connect (GTK_OBJECT (menu_item
), "activate",
563 (GtkSignalFunc
) layer_dialog_select_diagram_callback
,
565 gtk_menu_append( GTK_MENU(new_menu
), menu_item
);
566 gtk_widget_show (menu_item
);
569 gtk_option_menu_remove_menu(GTK_OPTION_MENU(layer_dialog
->diagram_omenu
));
571 gtk_option_menu_set_menu(GTK_OPTION_MENU(layer_dialog
->diagram_omenu
),
574 gtk_option_menu_set_history(GTK_OPTION_MENU(layer_dialog
->diagram_omenu
),
576 gtk_menu_set_active(GTK_MENU(new_menu
), current_nr
);
578 if (current_nr
== -1) {
580 if (dia_open_diagrams()!=NULL
) {
581 dia
= (Diagram
*) dia_open_diagrams()->data
;
583 layer_dialog_set_diagram(dia
);
590 if (layer_dialog
== NULL
|| layer_dialog
->dialog
== NULL
)
591 create_layer_dialog();
592 gtk_window_present(GTK_WINDOW(layer_dialog
->dialog
));
596 * Used to avoid writing to possibly already deleted layer in
597 * dia_layer_widget_connectable_toggled(). Must be called before
598 * e.g. gtk_list_clear_items() cause that will emit the toggled
599 * signal to last focus widget. See bug #329096
602 _layer_widget_clear_layer (GtkWidget
*widget
, gpointer user_data
)
604 DiaLayerWidget
*lw
= DIA_LAYER_WIDGET(widget
);
609 layer_dialog_set_diagram(Diagram
*dia
)
612 GtkWidget
*layer_widget
;
614 Layer
*active_layer
= NULL
;
619 active_layer
= dia
->data
->active_layer
;
621 if (layer_dialog
== NULL
|| layer_dialog
->dialog
== NULL
)
622 create_layer_dialog(); /* May have been destroyed */
624 gtk_container_foreach (GTK_LIST(layer_dialog
->layer_list
),
625 _layer_widget_clear_layer
, NULL
);
626 gtk_list_clear_items(GTK_LIST(layer_dialog
->layer_list
), 0, -1);
627 layer_dialog
->diagram
= dia
;
629 i
= g_list_index(dia_open_diagrams(), dia
);
631 gtk_option_menu_set_history(GTK_OPTION_MENU(layer_dialog
->diagram_omenu
),
639 for (i
=data
->layers
->len
-1,j
=0;i
>=0;i
--,j
++) {
640 layer
= (Layer
*) g_ptr_array_index(data
->layers
, i
);
641 layer_widget
= dia_layer_widget_new(dia
, layer
);
642 gtk_widget_show(layer_widget
);
643 gtk_container_add(GTK_CONTAINER(layer_dialog
->layer_list
), layer_widget
);
644 if (layer
==active_layer
)
647 gtk_list_select_item(GTK_LIST(layer_dialog
->layer_list
), sel_pos
);
653 /******* DiaLayerWidget: *****/
655 /* The connectability buttons don't quite behave the way they should.
656 * The shift-click behaviour messes up the active layer.
657 * To fix this, we need to rework the code so that the setting of
658 * connect_on and connect_off is not tied to the button toggling,
659 * but determined by what caused it (creation, user selection,
664 dia_layer_widget_unrealize(GtkWidget
*widget
)
666 DiaLayerWidget
*lw
= DIA_LAYER_WIDGET(widget
);
668 if (lw
->edit_dialog
!= NULL
) {
669 gtk_widget_destroy(lw
->edit_dialog
->dialog
);
670 g_free(lw
->edit_dialog
);
671 lw
->edit_dialog
= NULL
;
674 (* GTK_WIDGET_CLASS (gtk_type_class(gtk_list_item_get_type ()))->unrealize
) (widget
);
678 dia_layer_widget_class_init(DiaLayerWidgetClass
*klass
)
680 GtkObjectClass
*object_class
;
681 GtkWidgetClass
*widget_class
;
683 object_class
= (GtkObjectClass
*) klass
;
684 widget_class
= (GtkWidgetClass
*) klass
;
686 widget_class
->unrealize
= dia_layer_widget_unrealize
;
690 dia_layer_widget_set_connectable(DiaLayerWidget
*widget
, gboolean on
)
692 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget
->connectable
), on
);
696 dia_layer_widget_exclusive_connectable(DiaLayerWidget
*layer_widget
)
701 int connectable
= FALSE
;
704 /* First determine if _any_ other layer widgets are set to connectable */
705 for (i
=0;i
<layer_widget
->dia
->data
->layers
->len
;i
++) {
706 layer
= g_ptr_array_index(layer_widget
->dia
->data
->layers
, i
);
707 if (layer_widget
->layer
!= layer
) {
708 connectable
|= layer
->connectable
;
712 /* Now, toggle the connectability for all layers except the specified one */
713 list
= GTK_LIST(layer_dialog
->layer_list
)->children
;
715 lw
= DIA_LAYER_WIDGET(list
->data
);
716 if (lw
!= layer_widget
)
717 dia_layer_widget_set_connectable(lw
, !connectable
);
719 dia_layer_widget_set_connectable(lw
, TRUE
);
721 gtk_widget_queue_draw(GTK_WIDGET(lw
));
723 list
= g_list_next(list
);
727 static gboolean shifted
= FALSE
;
730 dia_layer_widget_button_event(GtkWidget
*widget
,
731 GdkEventButton
*event
,
734 DiaLayerWidget
*lw
= DIA_LAYER_WIDGET(userdata
);
736 shifted
= event
->state
& GDK_SHIFT_MASK
;
737 internal_call
= FALSE
;
738 /* Redraw the label? */
739 gtk_widget_queue_draw(GTK_WIDGET(lw
));
744 dia_layer_widget_connectable_toggled(GtkToggleButton
*widget
,
747 DiaLayerWidget
*lw
= DIA_LAYER_WIDGET(userdata
);
752 internal_call
= TRUE
;
753 dia_layer_widget_exclusive_connectable(lw
);
754 internal_call
= FALSE
;
756 lw
->layer
->connectable
= gtk_toggle_button_get_active(widget
);
758 if (lw
->layer
== lw
->dia
->data
->active_layer
) {
759 lw
->connect_off
= !gtk_toggle_button_get_active(widget
);
760 if (lw
->connect_off
) lw
->connect_on
= FALSE
;
762 lw
->connect_on
= gtk_toggle_button_get_active(widget
);
763 if (lw
->connect_on
) lw
->connect_off
= FALSE
;
765 gtk_widget_queue_draw(GTK_WIDGET(lw
));
766 if (!internal_call
) {
767 diagram_add_update_all(lw
->dia
);
768 diagram_flush(lw
->dia
);
773 dia_layer_widget_visible_clicked(GtkToggleButton
*widget
,
776 DiaLayerWidget
*lw
= DIA_LAYER_WIDGET(userdata
);
777 struct LayerVisibilityChange
*change
;
779 /* Have to use this internal_call hack 'cause there's no way to switch
780 * a toggle button without causing the 'clicked' event:(
782 if (!internal_call
) {
783 Diagram
*dia
= lw
->dia
;
784 change
= undo_layer_visibility(dia
, lw
->layer
, shifted
);
785 /** This apply kills 'lw', thus we have to hold onto 'lw->dia' */
786 layer_visibility_change_apply(change
, dia
);
787 undo_set_transactionpoint(dia
->undo
);
792 dia_layer_widget_init(DiaLayerWidget
*lw
)
796 GtkWidget
*connectable
;
799 hbox
= gtk_hbox_new(FALSE
, 0);
803 lw
->edit_dialog
= NULL
;
805 lw
->connect_on
= FALSE
;
806 lw
->connect_off
= FALSE
;
808 lw
->visible
= visible
=
809 dia_toggle_button_new_with_icons(dia_visible_icon
, dia_visible_empty_icon
);
811 g_signal_connect(G_OBJECT(visible
), "button-release-event",
812 G_CALLBACK(dia_layer_widget_button_event
), lw
);
813 g_signal_connect(G_OBJECT(visible
), "button-press-event",
814 G_CALLBACK(dia_layer_widget_button_event
), lw
);
815 g_signal_connect(G_OBJECT(visible
), "clicked",
816 G_CALLBACK(dia_layer_widget_visible_clicked
), lw
);
817 gtk_box_pack_start (GTK_BOX (hbox
), visible
, FALSE
, TRUE
, 2);
818 gtk_widget_show(visible
);
820 /*gtk_image_new_from_stock(GTK_STOCK_CONNECT,
821 GTK_ICON_SIZE_BUTTON), */
822 lw
->connectable
= connectable
=
823 dia_toggle_button_new_with_icons(dia_connectable_icon
,
824 dia_connectable_empty_icon
);
826 g_signal_connect(G_OBJECT(connectable
), "button-release-event",
827 G_CALLBACK(dia_layer_widget_button_event
), lw
);
828 g_signal_connect(G_OBJECT(connectable
), "button-press-event",
829 G_CALLBACK(dia_layer_widget_button_event
), lw
);
830 g_signal_connect(G_OBJECT(connectable
), "clicked",
831 G_CALLBACK(dia_layer_widget_connectable_toggled
), lw
);
833 gtk_box_pack_start (GTK_BOX (hbox
), connectable
, FALSE
, TRUE
, 2);
834 gtk_widget_show(connectable
);
836 lw
->label
= label
= gtk_label_new("layer_default_label");
837 gtk_label_set_justify(GTK_LABEL(label
), GTK_JUSTIFY_LEFT
);
838 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, TRUE
, 0);
839 gtk_widget_show(label
);
841 gtk_widget_show(hbox
);
843 gtk_container_add(GTK_CONTAINER(lw
), hbox
);
845 g_signal_connect (GTK_OBJECT (lw
), "select",
846 (GtkSignalFunc
) dia_layer_select_callback
,
848 g_signal_connect (GTK_OBJECT (lw
), "deselect",
849 (GtkSignalFunc
) dia_layer_deselect_callback
,
854 dia_layer_widget_get_type(void)
856 static GtkType dlw_type
= 0;
859 static const GtkTypeInfo dlw_info
= {
861 sizeof (DiaLayerWidget
),
862 sizeof (DiaLayerWidgetClass
),
863 (GtkClassInitFunc
) dia_layer_widget_class_init
,
864 (GtkObjectInitFunc
) dia_layer_widget_init
,
867 (GtkClassInitFunc
) NULL
,
870 dlw_type
= gtk_type_unique (gtk_list_item_get_type (), &dlw_info
);
877 dia_layer_widget_new(Diagram
*dia
, Layer
*layer
)
881 widget
= GTK_WIDGET ( gtk_type_new (dia_layer_widget_get_type ()));
882 dia_layer_set_layer(DIA_LAYER_WIDGET(widget
), dia
, layer
);
884 /* These may get toggled when the button is set without the widget being
886 DIA_LAYER_WIDGET(widget
)->connect_on
= FALSE
;
887 DIA_LAYER_WIDGET(widget
)->connect_off
= FALSE
;
892 /** Layer has either been selected or created */
894 dia_layer_set_layer(DiaLayerWidget
*widget
, Diagram
*dia
, Layer
*layer
)
897 widget
->layer
= layer
;
899 dia_layer_update_from_layer(widget
);
903 dia_layer_update_from_layer (DiaLayerWidget
*widget
)
905 internal_call
= TRUE
;
906 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget
->visible
),
907 widget
->layer
->visible
);
909 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget
->connectable
),
910 widget
->layer
->connectable
);
911 internal_call
= FALSE
;
913 gtk_label_set_text (GTK_LABEL (widget
->label
), widget
->layer
->name
);
918 * The edit layer attributes dialog
922 edit_layer_ok_callback (GtkWidget
*w
, gpointer client_data
)
924 EditLayerDialog
*dialog
;
927 dialog
= (EditLayerDialog
*) client_data
;
928 layer
= dialog
->layer_widget
->layer
;
930 g_free (layer
->name
);
931 layer
->name
= g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog
->name_entry
)));
933 diagram_add_update_all (dialog
->layer_widget
->dia
);
934 diagram_flush (dialog
->layer_widget
->dia
);
936 dia_layer_update_from_layer (dialog
->layer_widget
);
938 dialog
->layer_widget
->edit_dialog
= NULL
;
939 gtk_widget_destroy (dialog
->dialog
);
944 edit_layer_cancel_callback (GtkWidget
*w
,
945 gpointer client_data
)
947 EditLayerDialog
*dialog
;
949 dialog
= (EditLayerDialog
*) client_data
;
951 dialog
->layer_widget
->edit_dialog
= NULL
;
952 if (dialog
->dialog
!= NULL
)
953 gtk_widget_destroy (dialog
->dialog
);
958 edit_layer_delete_callback (GtkWidget
*w
,
960 gpointer client_data
)
962 edit_layer_cancel_callback (w
, client_data
);
968 layer_dialog_edit_layer (DiaLayerWidget
*layer_widget
)
970 EditLayerDialog
*dialog
;
976 /* the new dialog structure */
977 dialog
= (EditLayerDialog
*) g_malloc (sizeof (EditLayerDialog
));
978 dialog
->layer_widget
= layer_widget
;
981 dialog
->dialog
= gtk_dialog_new ();
982 gtk_window_set_role (GTK_WINDOW (dialog
->dialog
), "edit_layer_attrributes");
983 gtk_window_set_title (GTK_WINDOW (dialog
->dialog
), _("Edit Layer Attributes"));
984 gtk_window_set_position (GTK_WINDOW (dialog
->dialog
), GTK_WIN_POS_MOUSE
);
986 /* handle the wm close signal */
987 g_signal_connect (GTK_OBJECT (dialog
->dialog
), "delete_event",
988 G_CALLBACK (edit_layer_delete_callback
),
990 g_signal_connect (GTK_OBJECT (dialog
->dialog
), "destroy",
991 G_CALLBACK (gtk_widget_destroy
),
995 vbox
= gtk_vbox_new (FALSE
, 1);
996 gtk_container_set_border_width (GTK_CONTAINER (vbox
), 2);
997 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog
->dialog
)->vbox
), vbox
, TRUE
, TRUE
, 0);
999 /* the name entry hbox, label and entry */
1000 hbox
= gtk_hbox_new (FALSE
, 1);
1001 gtk_box_pack_start (GTK_BOX (vbox
), hbox
, FALSE
, FALSE
, 0);
1002 label
= gtk_label_new (_("Layer name:"));
1003 gtk_box_pack_start (GTK_BOX (hbox
), label
, FALSE
, FALSE
, 0);
1004 gtk_widget_show (label
);
1005 dialog
->name_entry
= gtk_entry_new ();
1006 gtk_box_pack_start (GTK_BOX (hbox
), dialog
->name_entry
, TRUE
, TRUE
, 0);
1007 gtk_entry_set_text (GTK_ENTRY (dialog
->name_entry
), layer_widget
->layer
->name
);
1008 gtk_widget_show (dialog
->name_entry
);
1009 gtk_widget_show (hbox
);
1011 button
= gtk_button_new_from_stock (GTK_STOCK_OK
);
1012 GTK_WIDGET_SET_FLAGS (button
, GTK_CAN_DEFAULT
);
1013 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog
->dialog
)->action_area
),
1014 button
, TRUE
, TRUE
, 0);
1015 g_signal_connect (GTK_OBJECT (button
), "clicked",
1016 G_CALLBACK(edit_layer_ok_callback
),
1018 gtk_widget_grab_default (button
);
1019 gtk_widget_show (button
);
1021 button
= gtk_button_new_from_stock (GTK_STOCK_CANCEL
);
1022 GTK_WIDGET_SET_FLAGS (button
, GTK_CAN_DEFAULT
);
1023 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog
->dialog
)->action_area
),
1024 button
, TRUE
, TRUE
, 0);
1025 g_signal_connect (GTK_OBJECT (button
), "clicked",
1026 G_CALLBACK(edit_layer_cancel_callback
),
1028 gtk_widget_show (button
);
1030 gtk_widget_show (vbox
);
1031 gtk_widget_show (dialog
->dialog
);
1033 layer_widget
->edit_dialog
= dialog
;
1037 /******** layer changes: */
1040 layer_change_apply(struct LayerChange
*change
, Diagram
*dia
)
1042 change
->applied
= 1;
1044 switch (change
->type
) {
1045 case TYPE_DELETE_LAYER
:
1046 data_delete_layer(dia
->data
, change
->layer
);
1048 case TYPE_ADD_LAYER
:
1049 data_add_layer_at(dia
->data
, change
->layer
, change
->index
);
1051 case TYPE_RAISE_LAYER
:
1052 data_raise_layer(dia
->data
, change
->layer
);
1054 case TYPE_LOWER_LAYER
:
1055 data_lower_layer(dia
->data
, change
->layer
);
1059 diagram_add_update_all(dia
);
1061 if (layer_dialog
->diagram
== dia
) {
1062 layer_dialog_set_diagram(dia
);
1067 layer_change_revert(struct LayerChange
*change
, Diagram
*dia
)
1069 switch (change
->type
) {
1070 case TYPE_DELETE_LAYER
:
1071 data_add_layer_at(dia
->data
, change
->layer
, change
->index
);
1073 case TYPE_ADD_LAYER
:
1074 data_delete_layer(dia
->data
, change
->layer
);
1076 case TYPE_RAISE_LAYER
:
1077 data_lower_layer(dia
->data
, change
->layer
);
1079 case TYPE_LOWER_LAYER
:
1080 data_raise_layer(dia
->data
, change
->layer
);
1084 diagram_add_update_all(dia
);
1086 if (layer_dialog
->diagram
== dia
) {
1087 layer_dialog_set_diagram(dia
);
1090 change
->applied
= 0;
1094 layer_change_free(struct LayerChange
*change
)
1096 switch (change
->type
) {
1097 case TYPE_DELETE_LAYER
:
1098 if (change
->applied
) {
1099 layer_destroy(change
->layer
);
1102 case TYPE_ADD_LAYER
:
1103 if (!change
->applied
) {
1104 layer_destroy(change
->layer
);
1107 case TYPE_RAISE_LAYER
:
1109 case TYPE_LOWER_LAYER
:
1115 undo_layer(Diagram
*dia
, Layer
*layer
, enum LayerChangeType type
, int index
)
1117 struct LayerChange
*change
;
1119 change
= g_new0(struct LayerChange
, 1);
1121 change
->change
.apply
= (UndoApplyFunc
) layer_change_apply
;
1122 change
->change
.revert
= (UndoRevertFunc
) layer_change_revert
;
1123 change
->change
.free
= (UndoFreeFunc
) layer_change_free
;
1125 change
->type
= type
;
1126 change
->layer
= layer
;
1127 change
->index
= index
;
1128 change
->applied
= 1;
1130 undo_push_change(dia
->undo
, (Change
*) change
);
1131 return (Change
*)change
;
1135 layer_visibility_change_apply(struct LayerVisibilityChange
*change
,
1139 Layer
*layer
= change
->layer
;
1140 int visible
= FALSE
;
1143 if (change
->is_exclusive
) {
1144 /* First determine if _any_ other layer widgets are set to visible.
1145 * If there is, exclusive switching turns all off. */
1146 for (i
=0;i
<dia
->data
->layers
->len
;i
++) {
1147 Layer
*temp_layer
= g_ptr_array_index(dia
->data
->layers
, i
);
1148 if (temp_layer
!= layer
) {
1149 visible
|= temp_layer
->visible
;
1153 /* Now, toggle the visibility for all layers except the specified one */
1154 layers
= dia
->data
->layers
;
1155 for (i
= 0; i
< layers
->len
; i
++) {
1156 Layer
*temp_layer
= (Layer
*) g_ptr_array_index(layers
, i
);
1157 if (temp_layer
== layer
) {
1158 temp_layer
->visible
= TRUE
;
1160 temp_layer
->visible
= !visible
;
1164 layer
->visible
= !layer
->visible
;
1166 diagram_add_update_all(dia
);
1168 if (layer_dialog
->diagram
== dia
) {
1169 layer_dialog_set_diagram(dia
);
1173 /** Revert to the visibility before this change was applied.
1176 layer_visibility_change_revert(struct LayerVisibilityChange
*change
,
1179 GList
*vis
= change
->original_visibility
;
1180 GPtrArray
*layers
= dia
->data
->layers
;
1183 for (i
= 0; vis
!= NULL
&& i
< layers
->len
; vis
= g_list_next(vis
), i
++) {
1184 Layer
*layer
= (Layer
*) g_ptr_array_index(layers
, i
);
1185 layer
->visible
= (gboolean
)vis
->data
;
1188 if (vis
!= NULL
|| i
< layers
->len
) {
1189 printf("Internal error: visibility undo has %d visibilities, but %d layers\n",
1190 g_list_length(change
->original_visibility
), layers
->len
);
1193 diagram_add_update_all(dia
);
1195 if (layer_dialog
->diagram
== dia
) {
1196 layer_dialog_set_diagram(dia
);
1201 layer_visibility_change_free(struct LayerVisibilityChange
*change
)
1203 g_list_free(change
->original_visibility
);
1206 static struct LayerVisibilityChange
*
1207 undo_layer_visibility(Diagram
*dia
, Layer
*layer
, gboolean exclusive
)
1209 struct LayerVisibilityChange
*change
;
1210 GList
*visibilities
= NULL
;
1212 GPtrArray
*layers
= dia
->data
->layers
;
1214 change
= g_new0(struct LayerVisibilityChange
, 1);
1216 change
->change
.apply
= (UndoApplyFunc
) layer_visibility_change_apply
;
1217 change
->change
.revert
= (UndoRevertFunc
) layer_visibility_change_revert
;
1218 change
->change
.free
= (UndoFreeFunc
) layer_visibility_change_free
;
1220 for (i
= 0; i
< layers
->len
; i
++) {
1221 Layer
*temp_layer
= (Layer
*) g_ptr_array_index(layers
, i
);
1222 visibilities
= g_list_append(visibilities
, (gpointer
)temp_layer
->visible
);
1225 change
->original_visibility
= visibilities
;
1226 change
->layer
= layer
;
1227 change
->is_exclusive
= exclusive
;
1229 undo_push_change(dia
->undo
, (Change
*) change
);