UML class fix bigtime.
[dia.git] / app / sheets_dialog_callbacks.c
blob7e25c7bc814b71dfb0fe23f5399bbbacfbd511ff
1 /* Dia -- a diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * sheets_dialog_callbacks.c : a sheets and objects dialog
5 * Copyright (C) 2002 M.C. Nelson
6 Steffen Macke
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
28 #include <errno.h>
29 #include <string.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35 #include <time.h>
36 #ifdef HAVE_UTIME_H
37 #include <utime.h>
38 #else
39 /* isn't this placement common ? */
40 #include <sys/utime.h>
41 #ifdef G_OS_WIN32
42 # define utime(n,b) _(n,b)
43 # define utim_buf _utimbuf
44 #endif
45 #endif
47 #include <gmodule.h>
49 #ifdef GNOME
50 #include <gnome.h>
51 #else
52 #include <gtk/gtk.h>
53 #endif
55 #include <libxml/tree.h>
56 #include <libxml/parser.h>
57 #include <libxml/xmlmemory.h>
59 #include "gtkwrapbox.h"
61 #include "../lib/dia_dirs.h"
62 #include "../lib/dia_xml_libxml.h"
63 #include "../lib/plug-ins.h"
65 #include "interface.h"
66 #include "message.h"
67 #include "sheets.h"
68 #include "sheets_dialog_callbacks.h"
69 #include "sheets_dialog.h"
71 #include "pixmaps/line_break.xpm"
72 #include "intl.h"
74 static GSList *radio_group = NULL;
76 static void
77 sheets_dialog_hide(void)
79 gtk_widget_hide(sheets_dialog);
82 gboolean
83 on_sheets_main_dialog_delete_event (GtkWidget *widget,
84 GdkEvent *event,
85 gpointer user_data)
87 sheets_dialog_hide();
88 return TRUE;
92 static void
93 sheets_dialog_up_down_set_sensitive(GList *wrapbox_button_list,
94 GtkToggleButton *togglebutton)
96 GtkWidget *button;
98 button = lookup_widget(sheets_dialog, "button_move_up");
100 /* If the active button is the 1st in the wrapbox, OR
101 if the active button is a linebreak AND is 2nd in the wrapbox
102 THEN set the 'Up' button to insensitive */
104 if (!wrapbox_button_list
105 || GTK_TOGGLE_BUTTON(g_list_first(wrapbox_button_list)->data) == togglebutton
106 || (!gtk_object_get_data(GTK_OBJECT(togglebutton), "sheet_object_mod")
107 && g_list_nth(wrapbox_button_list, 1)
108 && GTK_TOGGLE_BUTTON(g_list_nth(wrapbox_button_list, 1)->data)
109 == togglebutton))
110 gtk_widget_set_sensitive(button, FALSE);
111 else
112 gtk_widget_set_sensitive(button, TRUE);
114 button = lookup_widget(sheets_dialog, "button_move_down");
115 if (!wrapbox_button_list
116 || GTK_TOGGLE_BUTTON(g_list_last(wrapbox_button_list)->data) == togglebutton
117 || (!gtk_object_get_data(GTK_OBJECT(togglebutton), "sheet_object_mod")
118 && g_list_previous(g_list_last(wrapbox_button_list))
119 && GTK_TOGGLE_BUTTON(g_list_previous(g_list_last(wrapbox_button_list))
120 ->data)
121 == togglebutton))
122 gtk_widget_set_sensitive(button, FALSE);
123 else
124 gtk_widget_set_sensitive(button, TRUE);
127 static void
128 on_sheets_dialog_object_button_toggled(GtkToggleButton *togglebutton,
129 gpointer ud_wrapbox)
131 GList *wrapbox_button_list;
132 GtkWidget *button;
133 GtkWidget *table_sheets;
134 GtkWidget *optionmenu_left;
135 GtkWidget *optionmenu_right;
136 gchar *sheet_left;
137 gchar *sheet_right;
139 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(togglebutton)) == FALSE)
140 return;
142 /* We remember the active button so we don't have to search for it later */
144 gtk_object_set_data(GTK_OBJECT(ud_wrapbox), "active_button", togglebutton);
146 /* Same with the active wrapbox */
148 table_sheets = lookup_widget(sheets_dialog, "table_sheets");
149 gtk_object_set_data(GTK_OBJECT(table_sheets), "active_wrapbox", ud_wrapbox);
151 optionmenu_left = lookup_widget(sheets_dialog, "optionmenu_left");
152 sheet_left = gtk_object_get_data(GTK_OBJECT(optionmenu_left),
153 "active_sheet_name");
155 optionmenu_right = lookup_widget(sheets_dialog, "optionmenu_right");
156 sheet_right = gtk_object_get_data(GTK_OBJECT(optionmenu_right),
157 "active_sheet_name");
159 if ((gboolean)gtk_object_get_data(GTK_OBJECT(ud_wrapbox), "is_left") ==TRUE)
161 gtk_object_set_data(GTK_OBJECT(table_sheets), "active_optionmenu",
162 optionmenu_left);
163 button = lookup_widget(sheets_dialog, "button_copy");
164 gtk_object_set(GTK_OBJECT(button), "label", _("Copy ->"), NULL);
165 button = lookup_widget(sheets_dialog, "button_copy_all");
166 gtk_object_set(GTK_OBJECT(button), "label", _("Copy All ->"), NULL);
167 button = lookup_widget(sheets_dialog, "button_move");
168 gtk_object_set(GTK_OBJECT(button), "label", _("Move ->"), NULL);
169 button = lookup_widget(sheets_dialog, "button_move_all");
170 gtk_object_set(GTK_OBJECT(button), "label", _("Move All ->"), NULL);
172 else
174 gtk_object_set_data(GTK_OBJECT(table_sheets), "active_optionmenu",
175 optionmenu_right);
176 button = lookup_widget(sheets_dialog, "button_copy");
177 gtk_object_set(GTK_OBJECT(button), "label", _("<- Copy"), NULL);
178 button = lookup_widget(sheets_dialog, "button_copy_all");
179 gtk_object_set(GTK_OBJECT(button), "label", _("<- Copy All"), NULL);
180 button = lookup_widget(sheets_dialog, "button_move");
181 gtk_object_set(GTK_OBJECT(button), "label", _("<- Move"), NULL);
182 button = lookup_widget(sheets_dialog, "button_move_all");
183 gtk_object_set(GTK_OBJECT(button), "label", _("<- Move All"), NULL);
186 sheet_left = sheet_left ? sheet_left : ""; /* initial value can be NULL */
188 if (!strcmp(sheet_left, sheet_right)
189 || gtk_object_get_data(GTK_OBJECT(togglebutton), "is_hidden_button")
190 || !gtk_object_get_data(GTK_OBJECT(togglebutton), "sheet_object_mod"))
192 button = lookup_widget(sheets_dialog, "button_copy");
193 gtk_widget_set_sensitive(button, FALSE);
194 button = lookup_widget(sheets_dialog, "button_copy_all");
195 gtk_widget_set_sensitive(button, FALSE);
196 button = lookup_widget(sheets_dialog, "button_move");
197 gtk_widget_set_sensitive(button, FALSE);
198 button = lookup_widget(sheets_dialog, "button_move_all");
199 gtk_widget_set_sensitive(button, FALSE);
201 else
203 button = lookup_widget(sheets_dialog, "button_copy");
204 gtk_widget_set_sensitive(button, TRUE);
205 button = lookup_widget(sheets_dialog, "button_copy_all");
206 gtk_widget_set_sensitive(button, TRUE);
207 button = lookup_widget(sheets_dialog, "button_move");
208 gtk_widget_set_sensitive(button, TRUE);
209 button = lookup_widget(sheets_dialog, "button_move_all");
210 gtk_widget_set_sensitive(button, TRUE);
213 wrapbox_button_list = gtk_container_children(GTK_CONTAINER(ud_wrapbox));
215 if (g_list_length(wrapbox_button_list))
217 SheetMod *sm;
219 sheets_dialog_up_down_set_sensitive(wrapbox_button_list, togglebutton);
221 sm = gtk_object_get_data(GTK_OBJECT(togglebutton), "sheet_mod");
223 button = lookup_widget(sheets_dialog, "button_edit");
224 if (!gtk_object_get_data(GTK_OBJECT(togglebutton), "sheet_object_mod")
225 && sm->sheet.scope == SHEET_SCOPE_SYSTEM)
226 gtk_widget_set_sensitive(button, FALSE);
227 else
228 gtk_widget_set_sensitive(button, TRUE);
230 button = lookup_widget(sheets_dialog, "button_remove");
231 if (gtk_object_get_data(GTK_OBJECT(togglebutton), "is_hidden_button")
232 && sm->sheet.shadowing == NULL
233 && sm->sheet.scope == SHEET_SCOPE_SYSTEM)
234 gtk_widget_set_sensitive(button, FALSE);
235 else
236 gtk_widget_set_sensitive(button, TRUE);
238 else
240 button = lookup_widget(sheets_dialog, "button_move_up");
241 gtk_widget_set_sensitive(button, FALSE);
242 button = lookup_widget(sheets_dialog, "button_move_down");
243 gtk_widget_set_sensitive(button, FALSE);
244 button = lookup_widget(sheets_dialog, "button_edit");
245 gtk_widget_set_sensitive(button, FALSE);
246 button = lookup_widget(sheets_dialog, "button_remove");
247 gtk_widget_set_sensitive(button, FALSE);
249 g_list_free(wrapbox_button_list);
252 static void
253 sheets_dialog_wrapbox_add_line_break(GtkWidget *wrapbox)
255 SheetMod *sm;
256 GtkWidget *button;
257 GtkStyle *style;
258 GdkPixmap *pixmap, *mask;
259 GtkWidget *gtkpixmap;
261 sm = gtk_object_get_data(GTK_OBJECT(wrapbox), "sheet_mod");
262 g_assert(sm);
264 button = gtk_radio_button_new(radio_group);
265 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
267 gtk_object_set_data(GTK_OBJECT(button), "sheet_mod", sm);
269 radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
271 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(button), FALSE);
272 gtk_container_set_border_width(GTK_CONTAINER(button), 0);
274 style = gtk_widget_get_style(wrapbox);
275 pixmap =
276 gdk_pixmap_colormap_create_from_xpm_d(NULL,
277 gtk_widget_get_colormap(wrapbox),
278 &mask,
279 &style->bg[GTK_STATE_NORMAL],
280 line_break_xpm);
282 gtkpixmap = gtk_pixmap_new(pixmap, mask);
283 gtk_container_add(GTK_CONTAINER(button), gtkpixmap);
284 gtk_widget_show(gtkpixmap);
286 gtk_wrap_box_pack(GTK_WRAP_BOX(wrapbox), button, FALSE, TRUE, FALSE, TRUE);
287 gtk_widget_show(button);
289 gtk_tooltips_set_tip(sheets_dialog_tooltips, button, _("Line Break"), NULL);
291 g_signal_connect(GTK_OBJECT(button), "toggled",
292 G_CALLBACK(on_sheets_dialog_object_button_toggled),
293 wrapbox);
296 static void
297 sheets_dialog_object_set_tooltip(SheetObjectMod *som, GtkWidget *button)
299 gchar *tip;
301 switch (som->type){
302 case OBJECT_TYPE_SVG:
303 tip = g_strdup_printf(_("%s\nShape"), som->sheet_object.description);
304 break;
305 case OBJECT_TYPE_PROGRAMMED:
306 tip = g_strdup_printf(_("%s\nObject"), som->sheet_object.description);
307 break;
308 default:
309 tip = g_strdup_printf(_("%s\nUnassigned type"), som->sheet_object.description);
310 break;
313 gtk_tooltips_set_tip(sheets_dialog_tooltips, button, tip, NULL);
314 g_free(tip);
317 static GtkWidget *
318 sheets_dialog_create_object_button(SheetObjectMod *som, SheetMod *sm,
319 GtkWidget *wrapbox)
321 GtkWidget *button;
322 GdkPixmap *pixmap, *mask;
323 GtkWidget *gtkpixmap;
325 button = gtk_radio_button_new(radio_group);
326 radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
328 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(button), FALSE);
329 gtk_container_set_border_width(GTK_CONTAINER(button), 0);
331 create_object_pixmap(&som->sheet_object, wrapbox, &pixmap, &mask);
332 gtkpixmap = gtk_pixmap_new(pixmap, mask);
333 gtk_container_add(GTK_CONTAINER(button), gtkpixmap);
334 gtk_widget_show(gtkpixmap);
336 sheets_dialog_object_set_tooltip(som, button);
338 gtk_object_set_data(GTK_OBJECT(button), "sheet_mod", sm);
339 gtk_object_set_data(GTK_OBJECT(button), "sheet_object_mod", som);
341 g_signal_connect(GTK_OBJECT(button), "toggled",
342 G_CALLBACK(on_sheets_dialog_object_button_toggled),
343 wrapbox);
344 return button;
347 gboolean optionmenu_activate_first_pass = TRUE;
349 void
350 on_sheets_dialog_optionmenu_activate (GtkMenuItem *menuitem,
351 gpointer user_data)
353 GtkWidget *wrapbox;
354 Sheet *sheet;
355 GtkWidget *optionmenu;
356 GSList *object_mod_list;
357 GtkWidget *hidden_button;
358 GList *button_list;
360 sheet = &(((SheetMod *)(user_data))->sheet);
362 wrapbox = gtk_object_get_data(GTK_OBJECT(menuitem), "wrapbox");
363 g_assert(wrapbox);
365 /* The hidden button is necessary to keep track of radio_group
366 when there are no objects and to force 'toggled' events */
368 if (optionmenu_activate_first_pass)
370 hidden_button = gtk_radio_button_new(NULL);
371 optionmenu_activate_first_pass = FALSE;
373 else
375 hidden_button = gtk_radio_button_new(radio_group);
376 radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(hidden_button));
379 g_signal_connect(GTK_OBJECT(hidden_button), "toggled",
380 G_CALLBACK(on_sheets_dialog_object_button_toggled),
381 wrapbox);
382 gtk_object_set_data(GTK_OBJECT(hidden_button), "is_hidden_button",
383 (gpointer)TRUE);
384 gtk_object_set_data(GTK_OBJECT(wrapbox), "hidden_button", hidden_button);
385 gtk_object_set_data(GTK_OBJECT(hidden_button), "sheet_mod", user_data);
387 if (gtk_object_get_data(GTK_OBJECT(wrapbox), "is_left"))
388 optionmenu = lookup_widget(sheets_dialog, "optionmenu_left");
389 else
390 optionmenu = lookup_widget(sheets_dialog, "optionmenu_right");
391 gtk_object_set_data(GTK_OBJECT(optionmenu), "active_sheet_name", sheet->name);
393 gtk_container_foreach(GTK_CONTAINER(wrapbox),
394 (GtkCallback)gtk_widget_destroy, NULL);
396 radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(hidden_button));
398 gtk_wrap_box_set_aspect_ratio(GTK_WRAP_BOX(wrapbox), 4 * 1.0 / 9);
399 /* MCNFIXME: calculate this */
400 #ifdef CHANGE_COLOUR_OF_MODIFIED_SHEETS
402 GtkRcStyle *style;
404 style->fg[0].red = style->bg[0].red = 56000;
405 style->fg[1].red = style->bg[1].red = 56000;
406 style->fg[2].red = style->bg[2].red = 56000;
407 style->fg[3].red = style->bg[3].red = 56000;
408 style->fg[4].red = style->bg[4].red = 56000;
409 style->color_flags[0] |= 0x0f;
410 style->color_flags[1] |= 0x0f;
411 style->color_flags[2] |= 0x0f;
412 style->color_flags[3] |= 0x0f;
413 style->color_flags[4] |= 0x0f;
415 sw = lookup_widget(sheets_dialog, "scrolledwindow_right");
416 gtk_widget_modify_style(wrapbox, style);
418 #endif
420 gtk_object_set_data(GTK_OBJECT(wrapbox), "sheet_mod", user_data);
422 for (object_mod_list = sheet->objects; object_mod_list;
423 object_mod_list = g_slist_next(object_mod_list))
425 GtkWidget *button;
426 SheetObjectMod *som;
428 som = object_mod_list->data;
429 if (som->mod == SHEET_OBJECT_MOD_DELETED)
430 continue;
432 if (som->sheet_object.line_break == TRUE)
433 sheets_dialog_wrapbox_add_line_break(wrapbox);
435 button = sheets_dialog_create_object_button(som, user_data, wrapbox);
437 gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(wrapbox), button,
438 FALSE, TRUE, FALSE, TRUE, som->sheet_object.line_break);
440 gtk_widget_show(button);
443 button_list = gtk_container_children(GTK_CONTAINER(wrapbox));
445 if (g_list_length(button_list))
447 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hidden_button), TRUE);
448 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_list->data), TRUE);
450 else
451 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hidden_button), TRUE);
453 g_list_free(button_list);
456 static void
457 sheets_dialog_apply_revert_set_sensitive(gboolean is_sensitive)
459 GtkWidget *button;
461 button = lookup_widget(sheets_dialog, "button_apply");
462 gtk_widget_set_sensitive(button, is_sensitive);
464 button = lookup_widget(sheets_dialog, "button_revert");
465 gtk_widget_set_sensitive(button, is_sensitive);
468 typedef enum
470 SHEETS_DIALOG_MOVE_UP = -1,
471 SHEETS_DIALOG_MOVE_DOWN = +1
473 SheetsDialogMoveDir;
474 #define \
475 SHEETS_DIALOG_MOVE_NONE SHEETS_DIALOG_MOVE_UP
477 static void
478 _gtk_wrap_box_set_child_forced_break (GtkWrapBox* box, GtkWidget* child,
479 gboolean wrapped)
481 gboolean hexpand, hfill, vexpand, vfill, dummy;
483 gtk_wrap_box_query_child_packing (box, child, &hexpand, &hfill,
484 &vexpand, &vfill, &dummy);
485 gtk_wrap_box_set_child_packing (box, child, hexpand, hfill,
486 vexpand, vfill, wrapped);
488 static void
489 sheets_dialog_normalize_line_breaks(GtkWidget *wrapbox, SheetsDialogMoveDir dir)
491 GList *button_list;
492 GList *iter_list;
493 gboolean is_line_break;
495 button_list = gtk_container_children(GTK_CONTAINER(wrapbox));
497 is_line_break = FALSE;
498 for (iter_list = button_list; iter_list; iter_list = g_list_next(iter_list))
500 SheetMod *sm;
501 SheetObjectMod *som;
503 sm = gtk_object_get_data(GTK_OBJECT(iter_list->data), "sheet_mod");
504 som = gtk_object_get_data(GTK_OBJECT(iter_list->data), "sheet_object_mod");
505 if (som)
507 if (is_line_break)
509 if (som->sheet_object.line_break == FALSE)
511 if (sm->mod == SHEETMOD_MOD_NONE)
512 sm->mod = SHEETMOD_MOD_CHANGED;
514 som->mod = SHEET_OBJECT_MOD_CHANGED;
517 som->sheet_object.line_break = TRUE;
518 _gtk_wrap_box_set_child_forced_break(GTK_WRAP_BOX(wrapbox),
519 GTK_WIDGET(iter_list->data), TRUE);
521 else
523 if (som->sheet_object.line_break == TRUE)
525 if (sm->mod == SHEETMOD_MOD_NONE)
526 sm->mod = SHEETMOD_MOD_CHANGED;
527 som->mod = SHEET_OBJECT_MOD_CHANGED;
530 som->sheet_object.line_break = FALSE;
531 _gtk_wrap_box_set_child_forced_break(GTK_WRAP_BOX(wrapbox),
532 GTK_WIDGET(iter_list->data), FALSE);
534 is_line_break = FALSE;
536 else
538 if (is_line_break)
540 if (dir == SHEETS_DIALOG_MOVE_UP)
542 iter_list = g_list_previous(iter_list);
543 gtk_widget_destroy(GTK_WIDGET(iter_list->data));
544 iter_list = g_list_next(iter_list);
545 radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(iter_list
546 ->data));
548 else
550 GList *tmp_list;
552 tmp_list = g_list_previous(iter_list);
553 gtk_widget_destroy(GTK_WIDGET(iter_list->data));
554 radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(tmp_list
555 ->data));
558 else
559 is_line_break = TRUE;
563 /* We delete a trailing linebreak button in the wrapbox */
565 iter_list = g_list_last(button_list);
566 if (iter_list && !gtk_object_get_data(GTK_OBJECT(iter_list->data),
567 "sheet_object_mod"))
569 gtk_widget_destroy(GTK_WIDGET(iter_list->data));
570 if (g_list_previous(iter_list))
572 gtk_toggle_button_set_active(g_list_previous(iter_list)->data, TRUE);
573 radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(
574 g_list_previous(iter_list)->data));
578 g_list_free(button_list);
581 GtkWidget *
582 sheets_dialog_get_active_button(GtkWidget **wrapbox, GList **button_list)
584 GtkWidget *table_sheets;
586 table_sheets = lookup_widget(sheets_dialog, "table_sheets");
587 *wrapbox = gtk_object_get_data(GTK_OBJECT(table_sheets), "active_wrapbox");
588 *button_list = gtk_container_children(GTK_CONTAINER(*wrapbox));
589 return gtk_object_get_data(GTK_OBJECT(*wrapbox), "active_button");
593 static void
594 sheets_dialog_move_up_or_down(SheetsDialogMoveDir dir)
596 GtkWidget *table_sheets;
597 GtkWidget *wrapbox;
598 GList *button_list;
599 GtkWidget *active_button;
600 gint button_pos;
601 SheetObjectMod *som;
602 SheetObjectMod *som_next;
603 GList *next_button_list;
605 table_sheets = lookup_widget(sheets_dialog, "table_sheets");
606 wrapbox = gtk_object_get_data(GTK_OBJECT(table_sheets), "active_wrapbox");
608 button_list = gtk_container_children(GTK_CONTAINER(wrapbox));
609 active_button = gtk_object_get_data(GTK_OBJECT(wrapbox), "active_button");
611 button_pos = g_list_index(button_list, active_button);
612 gtk_wrap_box_reorder_child(GTK_WRAP_BOX(wrapbox),
613 GTK_WIDGET(active_button), button_pos + dir);
614 g_list_free(button_list);
616 sheets_dialog_normalize_line_breaks(wrapbox, dir);
618 /* And then reorder the backing store if necessary */
620 button_list = gtk_container_children(GTK_CONTAINER(wrapbox));
621 active_button = gtk_object_get_data(GTK_OBJECT(wrapbox), "active_button");
623 som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
625 next_button_list = g_list_next(g_list_find(button_list, active_button));
626 if (next_button_list)
627 som_next = gtk_object_get_data(GTK_OBJECT(next_button_list->data),
628 "sheet_object_mod");
629 else
630 som_next = NULL; /* either 1) no button after 'active_button'
631 or 2) button after 'active_button' is line break */
633 /* This is all a little hairy, but the idea is that we don't need
634 to reorder the backing store if the button was moved to the other
635 side of a line break button since a line break button doesn't
636 exist in the backing store. Starting to look a little like lisp... */
638 if (som && (((dir == SHEETS_DIALOG_MOVE_DOWN)
639 && (som->sheet_object.line_break == FALSE))
640 || (((dir == SHEETS_DIALOG_MOVE_UP)
641 && som_next))))
643 SheetMod *sm;
644 GSList *object_list;
645 gint object_pos;
647 som->mod = SHEET_OBJECT_MOD_CHANGED;
649 sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
650 if (sm->mod == SHEETMOD_MOD_NONE)
651 sm->mod = SHEETMOD_MOD_CHANGED;
653 object_list = g_slist_find(sm->sheet.objects, som);
654 g_assert(object_list);
656 object_pos = g_slist_position(sm->sheet.objects, object_list);
657 sm->sheet.objects = g_slist_remove_link(sm->sheet.objects, object_list);
658 sm->sheet.objects = g_slist_insert(sm->sheet.objects, object_list->data,
659 object_pos + dir);
662 sheets_dialog_apply_revert_set_sensitive(TRUE);
664 sheets_dialog_up_down_set_sensitive(button_list,
665 GTK_TOGGLE_BUTTON(active_button));
666 g_list_free(button_list);
669 void
670 on_sheets_dialog_button_move_up_clicked(GtkButton *button, gpointer user_data)
672 sheets_dialog_move_up_or_down(SHEETS_DIALOG_MOVE_UP);
675 void
676 on_sheets_dialog_button_move_down_clicked(GtkButton *button, gpointer user_data)
678 sheets_dialog_move_up_or_down(SHEETS_DIALOG_MOVE_DOWN);
681 void
682 on_sheets_dialog_button_close_clicked (GtkButton *button,
683 gpointer user_data)
685 sheets_dialog_hide();
688 static GtkWidget *sheets_new_dialog;
690 typedef enum
692 SHEETS_NEW_DIALOG_TYPE_SVG_SHAPE = 1, /* allows g_assert() */
693 SHEETS_NEW_DIALOG_TYPE_LINE_BREAK,
694 SHEETS_NEW_DIALOG_TYPE_SHEET
696 SheetsNewDialogType;
698 GList *sheets_new_dialog_combo_list = NULL;
700 void
701 on_sheets_dialog_button_new_clicked (GtkButton *button,
702 gpointer user_data)
704 GtkWidget *combo;
705 GtkWidget *wrapbox;
706 GList *button_list;
707 GtkWidget *active_button;
708 gboolean is_line_break_sensitive;
710 sheets_new_dialog = create_sheets_new_dialog();
712 if (sheets_new_dialog_combo_list)
714 combo = lookup_widget(sheets_new_dialog, "combo_from_file");
715 gtk_combo_set_popdown_strings(GTK_COMBO(combo),
716 sheets_new_dialog_combo_list);
719 /* Deterine if a line break button can be put after the active button */
721 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
722 is_line_break_sensitive = TRUE;
723 if (gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod"))
725 button_list = g_list_next(g_list_find(button_list, active_button));
726 if (!button_list || !gtk_object_get_data(GTK_OBJECT(button_list->data),
727 "sheet_mod"))
728 is_line_break_sensitive = FALSE;
729 g_list_free(button_list);
731 else
732 is_line_break_sensitive = FALSE;
734 active_button = lookup_widget(sheets_new_dialog, "radiobutton_line_break");
735 gtk_widget_set_sensitive(active_button, is_line_break_sensitive);
737 /* Use the 'ok' button to hold the current 'type' selection */
739 active_button = lookup_widget(sheets_new_dialog, "button_ok");
740 gtk_object_set_data(GTK_OBJECT(active_button), "active_type",
741 (gpointer)SHEETS_NEW_DIALOG_TYPE_SVG_SHAPE);
743 gtk_widget_show(sheets_new_dialog);
746 void
747 on_sheets_new_dialog_button_cancel_clicked
748 (GtkButton *button,
749 gpointer user_data)
751 gtk_widget_destroy(sheets_new_dialog);
752 sheets_new_dialog = NULL;
755 void
756 on_sheets_new_dialog_button_ok_clicked (GtkButton *button,
757 gpointer user_data)
759 SheetsNewDialogType active_type;
760 GtkWidget *table_sheets;
761 GtkWidget *wrapbox;
762 GList *button_list;
763 GtkWidget *active_button;
765 table_sheets = lookup_widget(sheets_dialog, "table_sheets");
766 wrapbox = gtk_object_get_data(GTK_OBJECT(table_sheets), "active_wrapbox");
768 active_type = (SheetsNewDialogType)gtk_object_get_data(GTK_OBJECT(button),
769 "active_type");
770 g_assert(active_type);
772 switch (active_type)
774 GtkWidget *entry;
775 gchar *file_name;
776 gchar *p;
777 struct stat stat_buf;
778 GList *plugin_list;
779 DiaObjectType *ot;
780 typedef gboolean (*CustomObjectLoadFunc) (gchar*, DiaObjectType **);
781 CustomObjectLoadFunc custom_object_load_fn;
782 gint pos;
783 GtkWidget *active_button;
784 GList *button_list;
785 SheetObjectMod *som;
786 SheetMod *sm;
787 SheetObject *sheet_obj;
788 Sheet *sheet;
789 GtkWidget *optionmenu;
791 case SHEETS_NEW_DIALOG_TYPE_SVG_SHAPE:
793 entry = lookup_widget(sheets_new_dialog, "combo_entry_from_file");
794 /* Since this is a file name, no utf8 translation is needed */
795 file_name = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
797 p = file_name + strlen(file_name) - 6;
798 if (strcmp(p, ".shape"))
800 message_error(_("Filename must end with '%s': '%s'"),
801 ".shape", dia_message_filename(file_name));
802 g_free(file_name);
803 return;
806 if (stat(file_name, &stat_buf) == -1)
808 message_error(_("Error examining %s: %s"),
809 dia_message_filename(file_name), strerror(errno));
810 g_free(file_name);
811 return;
814 custom_object_load_fn = NULL;
815 for (plugin_list = dia_list_plugins(); plugin_list != NULL;
816 plugin_list = g_list_next(plugin_list))
818 PluginInfo *info = plugin_list->data;
820 custom_object_load_fn =
821 (CustomObjectLoadFunc)dia_plugin_get_symbol (info, "custom_object_load");
822 if (custom_object_load_fn)
823 break;
825 g_assert(custom_object_load_fn);
827 if (!(*custom_object_load_fn)(file_name, &ot))
829 message_error(_("Could not interpret shape file: '%s'"),
830 dia_message_filename(file_name));
831 g_free(file_name);
832 return;
834 object_register_type(ot);
836 entry = lookup_widget(sheets_new_dialog, "entry_svg_description");
837 sheet_obj = g_new(SheetObject, 1);
838 sheet_obj->object_type = g_strdup(ot->name);
840 sheet_obj->description =
841 gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
843 sheet_obj->pixmap = ot->pixmap;
844 sheet_obj->user_data = ot->default_user_data;
845 sheet_obj->user_data_type = USER_DATA_IS_OTHER;
846 sheet_obj->line_break = FALSE;
847 sheet_obj->pixmap_file = g_strdup(ot->pixmap_file);
848 sheet_obj->has_icon_on_sheet = FALSE;
850 sm = gtk_object_get_data(GTK_OBJECT(wrapbox), "sheet_mod");
851 som = sheets_append_sheet_object_mod(sheet_obj, sm);
852 som->mod = SHEET_OBJECT_MOD_NEW;
853 som->svg_filename = g_strdup(file_name);
854 if (sm->mod == SHEETMOD_MOD_NONE)
855 sm->mod = SHEETMOD_MOD_CHANGED;
857 active_button = sheets_dialog_create_object_button(som, sm, wrapbox);
858 gtk_wrap_box_pack(GTK_WRAP_BOX(wrapbox), active_button,
859 FALSE, TRUE, FALSE, TRUE);
860 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(active_button), TRUE);
861 gtk_widget_show(active_button);
863 sheets_new_dialog_combo_list = g_list_append(sheets_new_dialog_combo_list,
864 file_name);
865 break;
867 case SHEETS_NEW_DIALOG_TYPE_LINE_BREAK:
869 sheets_dialog_wrapbox_add_line_break(wrapbox);
871 button_list = gtk_container_children(GTK_CONTAINER(wrapbox));
872 active_button = gtk_object_get_data(GTK_OBJECT(wrapbox), "active_button");
873 pos = g_list_index(button_list, active_button);
874 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_list_last(button_list)
875 ->data), TRUE);
876 gtk_wrap_box_reorder_child(GTK_WRAP_BOX(wrapbox),
877 g_list_last(button_list)->data, pos + 1);
879 sheets_dialog_normalize_line_breaks(wrapbox, SHEETS_DIALOG_MOVE_NONE);
881 sm = gtk_object_get_data(GTK_OBJECT(wrapbox), "sheet_mod");
882 if (sm->mod == SHEETMOD_MOD_NONE)
883 sm->mod = SHEETMOD_MOD_CHANGED;
885 g_list_free(button_list);
886 break;
888 case SHEETS_NEW_DIALOG_TYPE_SHEET:
890 gchar *sheet_name;
891 gchar *sheet_descrip;
893 entry = lookup_widget(sheets_new_dialog, "entry_sheet_name");
894 sheet_name = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
896 sheet_name = g_strchug(g_strchomp(sheet_name));
897 if (!*sheet_name)
899 message_error(_("Sheet must have a Name"));
900 return;
903 entry = lookup_widget(sheets_new_dialog, "entry_sheet_description");
904 sheet_descrip = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
906 sheet = g_new(Sheet, 1);
907 sheet->name = sheet_name;
908 sheet->filename = "";
909 sheet->description = sheet_descrip;
910 sheet->scope = SHEET_SCOPE_USER;
911 sheet->shadowing = NULL;
912 sheet->objects = NULL;
914 sm = sheets_append_sheet_mods(sheet);
915 sm->mod = SHEETMOD_MOD_NEW;
917 table_sheets = lookup_widget(sheets_dialog, "table_sheets");
918 optionmenu = gtk_object_get_data(GTK_OBJECT(table_sheets),
919 "active_optionmenu");
920 g_assert(optionmenu);
921 sheets_optionmenu_create(optionmenu, wrapbox, NULL);
923 break;
925 default:
926 g_assert_not_reached();
929 sheets_dialog_apply_revert_set_sensitive(TRUE);
931 button_list = gtk_container_children(GTK_CONTAINER(wrapbox));
932 active_button = gtk_object_get_data(GTK_OBJECT(wrapbox), "active_button");
933 sheets_dialog_up_down_set_sensitive(button_list,
934 GTK_TOGGLE_BUTTON(active_button));
935 g_list_free(button_list);
937 gtk_widget_destroy(sheets_new_dialog);
938 sheets_new_dialog = NULL;
941 static GtkWidget *sheets_shapeselection_dialog;
943 void
944 on_sheets_new_dialog_button_browse_clicked
945 (GtkButton *button,
946 gpointer user_data)
948 sheets_shapeselection_dialog = create_sheets_shapeselection_dialog();
949 gtk_widget_show(sheets_shapeselection_dialog);
952 void
953 on_sheets_shapeselection_dialog_button_cancel_clicked
954 (GtkButton *button,
955 gpointer user_data)
957 gtk_widget_destroy(sheets_shapeselection_dialog);
958 sheets_shapeselection_dialog = NULL;
961 void
962 on_sheets_shapeselection_dialog_button_ok_clicked
963 (GtkButton *button,
964 gpointer user_data)
966 const gchar *filename;
967 GtkWidget *entry;
969 filename =
970 gtk_file_selection_get_filename(
971 GTK_FILE_SELECTION(sheets_shapeselection_dialog));
973 entry = lookup_widget(sheets_new_dialog, "combo_entry_from_file");
974 /* Since this is a filename entry from the dialog, no utf is needed */
975 gtk_entry_set_text(GTK_ENTRY(entry), filename);
977 gtk_widget_destroy(sheets_shapeselection_dialog);
978 sheets_shapeselection_dialog = NULL;
981 static GtkWidget *sheets_edit_dialog;
983 void
984 on_sheets_dialog_button_edit_clicked (GtkButton *button,
985 gpointer user_data)
987 GtkWidget *wrapbox;
988 GList *button_list;
989 GtkWidget *active_button;
990 SheetObjectMod *som;
991 gchar *descrip = "";
992 gchar *type = "";
993 GtkWidget *entry;
994 SheetMod *sm;
995 gchar *name = "";
997 if (sheets_edit_dialog == NULL)
998 sheets_edit_dialog = create_sheets_edit_dialog();
1000 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1001 som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
1002 if (som)
1004 descrip = som->sheet_object.description;
1005 type = sheet_object_mod_get_type_string(som);
1008 entry = lookup_widget(sheets_edit_dialog, "entry_object_description");
1009 if (som)
1010 gtk_entry_set_text(GTK_ENTRY(entry), descrip);
1011 else
1012 gtk_widget_set_sensitive(entry, FALSE);
1014 entry = lookup_widget(sheets_edit_dialog, "entry_object_type");
1015 if (som)
1016 gtk_entry_set_text(GTK_ENTRY(entry), type);
1017 else
1018 gtk_widget_set_sensitive(entry, FALSE);
1020 sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1021 if (sm)
1023 name = sm->sheet.name;
1024 descrip = sm->sheet.description;
1027 entry = lookup_widget(sheets_edit_dialog, "entry_sheet_name");
1028 gtk_entry_set_text(GTK_ENTRY(entry), name);
1029 #if CAN_EDIT_SHEET_NAME
1030 if (sm->sheet.scope == SHEET_SCOPE_SYSTEM)
1031 #endif
1032 gtk_widget_set_sensitive(entry, FALSE);
1034 entry = lookup_widget(sheets_edit_dialog, "entry_sheet_description");
1035 gtk_entry_set_text(GTK_ENTRY(entry), descrip);
1037 gtk_widget_show(sheets_edit_dialog);
1040 void
1041 on_sheets_edit_dialog_button_cancel_clicked
1042 (GtkButton *button,
1043 gpointer user_data)
1045 gtk_widget_destroy(sheets_edit_dialog);
1046 sheets_edit_dialog = NULL;
1049 static GtkWidget *sheets_remove_dialog;
1051 typedef enum
1053 SHEETS_REMOVE_DIALOG_TYPE_OBJECT = 1,
1054 SHEETS_REMOVE_DIALOG_TYPE_SHEET
1056 SheetsRemoveDialogType;
1058 void
1059 on_sheets_dialog_button_remove_clicked (GtkButton *button,
1060 gpointer user_data)
1062 GtkWidget *wrapbox;
1063 GList *button_list;
1064 GtkWidget *active_button;
1065 SheetMod *sm;
1066 GtkWidget *entry;
1067 GtkWidget *radio_button;
1069 sheets_remove_dialog = create_sheets_remove_dialog();
1071 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1072 g_assert(active_button);
1074 /* Force a change in state in the radio button for set sensitive */
1076 radio_button = lookup_widget(sheets_remove_dialog, "radiobutton_sheet");
1077 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
1079 entry = lookup_widget(sheets_remove_dialog, "entry_object");
1080 if (gtk_object_get_data(GTK_OBJECT(active_button), "is_hidden_button"))
1082 radio_button = lookup_widget(sheets_remove_dialog, "radiobutton_object");
1083 gtk_widget_set_sensitive(radio_button, FALSE);
1084 gtk_widget_set_sensitive(entry, FALSE);
1086 else
1088 SheetObjectMod *som;
1090 som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
1091 if (!som)
1092 gtk_entry_set_text(GTK_ENTRY(entry), _("Line Break"));
1093 else
1094 gtk_entry_set_text(GTK_ENTRY(entry), som->sheet_object.description);
1096 radio_button = lookup_widget(sheets_remove_dialog, "radiobutton_object");
1097 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
1100 entry = lookup_widget(sheets_remove_dialog, "entry_sheet");
1101 sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1103 /* Note: It is currently impossible to remove a user sheet that has
1104 been shadowed by a more recent system sheet--the logic is just
1105 too hairy. Once the user sheet has been updated, or the [copy of
1106 system] sheet has been removed, then they can remove the user
1107 sheet just fine (in the next invocation of dia). This would
1108 be rare, to say the least... */
1110 if (sm->sheet.shadowing == NULL && sm->sheet.scope == SHEET_SCOPE_SYSTEM)
1112 GtkWidget *radio_button;
1114 radio_button = lookup_widget(sheets_remove_dialog, "radiobutton_sheet");
1115 gtk_widget_set_sensitive(radio_button, FALSE);
1116 gtk_widget_set_sensitive(entry, FALSE);
1118 gtk_entry_set_text(GTK_ENTRY(entry), sm->sheet.name);
1120 gtk_widget_show(sheets_remove_dialog);
1123 void
1124 on_sheets_remove_dialog_button_cancel_clicked
1125 (GtkButton *button,
1126 gpointer user_data)
1128 gtk_widget_destroy(sheets_remove_dialog);
1129 sheets_remove_dialog = NULL;
1132 static void
1133 sheets_dialog_togglebutton_set_sensitive(GtkToggleButton *togglebutton,
1134 GtkWidget *dialog,
1135 gchar *widget_names[], gint type)
1137 gboolean is_sensitive;
1138 guint i;
1139 GtkWidget *tmp;
1141 is_sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(togglebutton));
1142 if (is_sensitive)
1144 tmp = lookup_widget(dialog, "button_ok");
1145 gtk_object_set_data(GTK_OBJECT(tmp), "active_type", (gpointer)type);
1148 for (i = 0; widget_names[i]; i++)
1150 tmp = lookup_widget(dialog, widget_names[i]);
1151 gtk_widget_set_sensitive(tmp, is_sensitive);
1155 void
1156 on_sheets_new_dialog_radiobutton_svg_shape_toggled
1157 (GtkToggleButton *togglebutton,
1158 gpointer user_data)
1160 static gchar *widget_names[] =
1162 "combo_from_file",
1163 "button_browse",
1164 "label_svg_description",
1165 "entry_svg_description",
1166 NULL
1169 sheets_dialog_togglebutton_set_sensitive(togglebutton, sheets_new_dialog,
1170 widget_names,
1171 SHEETS_NEW_DIALOG_TYPE_SVG_SHAPE);
1174 void
1175 on_sheets_new_dialog_radiobutton_sheet_toggled
1176 (GtkToggleButton *togglebutton,
1177 gpointer user_data)
1179 static gchar *widget_names[] =
1181 "entry_sheet_name",
1182 "entry_sheet_description",
1183 "label_description",
1184 NULL
1187 sheets_dialog_togglebutton_set_sensitive(togglebutton, sheets_new_dialog,
1188 widget_names,
1189 SHEETS_NEW_DIALOG_TYPE_SHEET);
1192 void
1193 on_sheets_new_dialog_radiobutton_line_break_toggled
1194 (GtkToggleButton *togglebutton,
1195 gpointer user_data)
1197 static gchar *widget_names[] =
1199 NULL
1202 sheets_dialog_togglebutton_set_sensitive(togglebutton, sheets_new_dialog,
1203 widget_names,
1204 SHEETS_NEW_DIALOG_TYPE_LINE_BREAK);
1207 void
1208 on_sheets_remove_dialog_radiobutton_object_toggled
1209 (GtkToggleButton *togglebutton,
1210 gpointer user_data)
1212 gchar *widget_names[] =
1214 "pixmap_object",
1215 "entry_object",
1216 NULL
1219 sheets_dialog_togglebutton_set_sensitive(togglebutton, sheets_remove_dialog,
1220 widget_names,
1221 SHEETS_REMOVE_DIALOG_TYPE_OBJECT);
1224 void
1225 on_sheets_remove_dialog_radiobutton_sheet_toggled
1226 (GtkToggleButton *togglebutton,
1227 gpointer user_data)
1229 gchar *widget_names[] =
1231 "entry_sheet",
1232 NULL
1235 sheets_dialog_togglebutton_set_sensitive(togglebutton, sheets_remove_dialog,
1236 widget_names,
1237 SHEETS_REMOVE_DIALOG_TYPE_SHEET);
1240 static GtkWidget *
1241 sheets_dialog_set_new_active_button(void)
1243 GtkWidget *active_button;
1244 GtkWidget *wrapbox;
1245 GList *button_list;
1246 GList *active_button_list;
1247 GtkWidget *new_active_button;
1249 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1251 active_button_list = g_list_find(button_list, active_button);
1252 g_assert(active_button_list);
1253 if (g_list_next(active_button_list))
1254 new_active_button = g_list_next(active_button_list)->data;
1255 else
1257 if (g_list_previous(active_button_list))
1258 new_active_button = g_list_previous(active_button_list)->data;
1259 else
1260 new_active_button = gtk_object_get_data(GTK_OBJECT(wrapbox),
1261 "hidden_button");
1263 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(new_active_button), TRUE);
1265 return new_active_button;
1268 void
1269 on_sheets_remove_dialog_button_ok_clicked
1270 (GtkButton *button,
1271 gpointer user_data)
1273 SheetsRemoveDialogType type;
1274 GtkWidget *wrapbox;
1275 GList *button_list;
1276 GtkWidget *active_button;
1278 type = (SheetsRemoveDialogType)gtk_object_get_data(GTK_OBJECT(button),
1279 "active_type");
1281 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1283 switch (type)
1285 SheetObjectMod *som;
1286 GtkWidget *new_active_button;
1287 SheetMod *sm;
1288 GtkWidget *table_sheets;
1289 GtkWidget *optionmenu;
1291 case SHEETS_REMOVE_DIALOG_TYPE_OBJECT:
1293 som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
1294 if (som)
1296 sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1297 sm->mod = SHEETMOD_MOD_CHANGED;
1298 som->mod = SHEET_OBJECT_MOD_DELETED;
1300 new_active_button = sheets_dialog_set_new_active_button();
1302 gtk_widget_destroy(active_button);
1303 radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(new_active_button));
1305 sheets_dialog_normalize_line_breaks(wrapbox, SHEETS_DIALOG_MOVE_NONE);
1306 break;
1308 case SHEETS_REMOVE_DIALOG_TYPE_SHEET:
1310 sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1311 sm->mod = SHEETMOD_MOD_DELETED;
1313 if (sm->sheet.shadowing && sm->sheet.scope == SHEET_SCOPE_USER)
1314 sheets_append_sheet_mods(sm->sheet.shadowing);
1316 table_sheets = lookup_widget(sheets_dialog, "table_sheets");
1317 optionmenu = gtk_object_get_data(GTK_OBJECT(table_sheets),
1318 "active_optionmenu");
1319 g_assert(optionmenu);
1320 sheets_optionmenu_create(optionmenu, wrapbox, NULL);
1322 break;
1324 default:
1325 g_assert_not_reached();
1328 g_list_free(button_list);
1330 sheets_dialog_apply_revert_set_sensitive(TRUE);
1331 gtk_widget_destroy(sheets_remove_dialog);
1332 sheets_remove_dialog = NULL;
1335 void
1336 on_sheets_edit_dialog_button_ok_clicked
1337 (GtkButton *button,
1338 gpointer user_data)
1340 GtkWidget *active_button;
1341 GtkWidget *wrapbox;
1342 GList *button_list;
1343 GtkWidget *entry;
1344 gboolean something_changed = FALSE;
1346 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1347 g_assert(active_button);
1349 entry = lookup_widget(sheets_edit_dialog, "entry_object_description");
1350 if ((gboolean)gtk_object_get_data(GTK_OBJECT(entry), "changed") == TRUE)
1352 SheetMod *sm;
1353 SheetObjectMod *som;
1355 som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
1356 som->sheet_object.description =
1357 gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
1358 sheets_dialog_object_set_tooltip(som, active_button);
1360 som->mod = SHEET_OBJECT_MOD_CHANGED;
1362 sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1363 if (sm->mod == SHEETMOD_MOD_NONE)
1364 sm->mod = SHEETMOD_MOD_CHANGED;
1366 something_changed = TRUE;
1369 entry = lookup_widget(sheets_edit_dialog, "entry_sheet_description");
1370 if ((gboolean)gtk_object_get_data(GTK_OBJECT(entry), "changed") == TRUE)
1372 SheetMod *sm;
1374 sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1375 sm->sheet.description =
1376 gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
1378 if (sm->mod == SHEETMOD_MOD_NONE)
1379 sm->mod = SHEETMOD_MOD_CHANGED;
1380 something_changed = TRUE;
1383 #ifdef CAN_EDIT_SHEET_NAME
1384 /* This must be last because we reload the sheets if changed */
1386 entry = lookup_widget(sheets_edit_dialog, "entry_sheet_name");
1387 if ((gboolean)gtk_object_get_data(GTK_OBJECT(entry), "changed") == TRUE)
1389 SheetMod *sm;
1390 GtkWidget *table_sheets;
1391 GtkWidget *optionmenu;
1393 sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1394 sm->sheet.name = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
1395 if (sm->mod == SHEETMOD_MOD_NONE)
1396 sm->mod = SHEETMOD_MOD_CHANGED;
1398 table_sheets = lookup_widget(sheets_dialog, "table_sheets");
1399 optionmenu = gtk_object_get_data(GTK_OBJECT(table_sheets),
1400 "active_optionmenu");
1401 sheets_optionmenu_create(optionmenu, wrapbox, NULL);
1403 something_changed = TRUE;
1405 #endif
1406 if (something_changed == TRUE)
1407 sheets_dialog_apply_revert_set_sensitive(TRUE);
1409 gtk_widget_destroy(sheets_edit_dialog);
1410 sheets_edit_dialog = NULL;
1413 void
1414 on_sheets_edit_dialog_entry_object_description_changed
1415 (GtkEditable *editable,
1416 gpointer user_data)
1418 gtk_object_set_data(GTK_OBJECT(editable), "changed", (gpointer)TRUE);
1422 void
1423 on_sheets_edit_dialog_entry_sheet_description_changed
1424 (GtkEditable *editable,
1425 gpointer user_data)
1427 gtk_object_set_data(GTK_OBJECT(editable), "changed", (gpointer)TRUE);
1430 void
1431 on_sheets_edit_dialog_entry_sheet_name_changed
1432 (GtkEditable *editable,
1433 gpointer user_data)
1435 gtk_object_set_data(GTK_OBJECT(editable), "changed", (gpointer)TRUE);
1438 static GtkWidget *
1439 sheets_dialog_get_target_wrapbox(GtkWidget *wrapbox)
1441 if (gtk_object_get_data(GTK_OBJECT(wrapbox), "is_left"))
1442 return gtk_object_get_data(GTK_OBJECT(sheets_dialog), "wrapbox_right");
1443 else
1444 return gtk_object_get_data(GTK_OBJECT(sheets_dialog), "wrapbox_left");
1447 static void
1448 sheets_dialog_copy_object(GtkWidget *active_button, GtkWidget *target_wrapbox)
1450 GtkWidget *button;
1451 SheetMod *sm;
1452 SheetObjectMod *som;
1453 SheetObjectMod *som_new;
1454 SheetObject *so;
1456 sm = gtk_object_get_data(GTK_OBJECT(target_wrapbox), "sheet_mod");
1457 som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
1459 if (!som)
1460 return;
1462 so = g_new(SheetObject, 1);
1463 so->object_type = g_strdup(som->sheet_object.object_type);
1464 so->description = g_strdup(som->sheet_object.description);
1465 so->pixmap = som->sheet_object.pixmap;
1466 so->user_data = som->sheet_object.user_data;
1467 so->user_data_type = som->sheet_object.user_data_type;
1468 so->line_break = FALSE; /* must be false--we don't copy linebreaks */
1469 so->pixmap_file = g_strdup(som->sheet_object.pixmap_file);
1470 so->has_icon_on_sheet = som->sheet_object.has_icon_on_sheet;
1472 som_new = g_new(SheetObjectMod, 1);
1473 som_new->sheet_object = *so;
1474 som_new->type = som->type;
1475 som_new->mod = SHEET_OBJECT_MOD_NONE;
1477 sm->sheet.objects = g_slist_append(sm->sheet.objects, som_new);
1478 if (sm->mod == SHEETMOD_MOD_NONE)
1479 sm->mod = SHEETMOD_MOD_CHANGED;
1481 button = sheets_dialog_create_object_button(som_new, sm, target_wrapbox);
1482 gtk_wrap_box_pack(GTK_WRAP_BOX(target_wrapbox), button,
1483 FALSE, TRUE, FALSE, TRUE);
1484 gtk_widget_show(button);
1486 sheets_dialog_apply_revert_set_sensitive(TRUE);
1489 void
1490 on_sheets_dialog_button_copy_clicked (GtkButton *button,
1491 gpointer user_data)
1493 GtkWidget *active_button;
1494 GtkWidget *wrapbox;
1495 GList *button_list;
1496 GtkWidget *target_wrapbox;
1498 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1500 target_wrapbox = sheets_dialog_get_target_wrapbox(wrapbox);
1502 sheets_dialog_copy_object(active_button, target_wrapbox);
1505 void
1506 on_sheets_dialog_button_copy_all_clicked
1507 (GtkButton *button,
1508 gpointer user_data)
1510 GtkWidget *active_button;
1511 GtkWidget *wrapbox;
1512 GList *button_list, *iter_list;
1513 GtkWidget *target_wrapbox;
1515 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1517 target_wrapbox = sheets_dialog_get_target_wrapbox(wrapbox);
1519 for (iter_list = button_list; iter_list; iter_list = g_list_next(iter_list))
1520 sheets_dialog_copy_object(iter_list->data, target_wrapbox);
1523 void
1524 on_sheets_dialog_button_move_clicked (GtkButton *button,
1525 gpointer user_data)
1527 GtkWidget *active_button;
1528 GtkWidget *wrapbox;
1529 GList *button_list;
1530 GtkWidget *target_wrapbox;
1531 SheetObjectMod *som;
1532 GtkWidget *new_active_button;
1534 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1536 target_wrapbox = sheets_dialog_get_target_wrapbox(wrapbox);
1538 sheets_dialog_copy_object(active_button, target_wrapbox);
1540 som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
1541 if (som)
1542 som->mod = SHEET_OBJECT_MOD_DELETED;
1544 new_active_button = sheets_dialog_set_new_active_button();
1546 gtk_widget_destroy(active_button);
1547 radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(new_active_button));
1549 sheets_dialog_normalize_line_breaks(wrapbox, SHEETS_DIALOG_MOVE_NONE);
1552 void
1553 on_sheets_dialog_button_move_all_clicked
1554 (GtkButton *button,
1555 gpointer user_data)
1557 GtkWidget *active_button;
1558 GtkWidget *wrapbox;
1559 GList *button_list;
1560 GList *iter_list;
1561 GtkWidget *target_wrapbox;
1562 SheetObjectMod *som;
1564 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1566 target_wrapbox = sheets_dialog_get_target_wrapbox(wrapbox);
1568 for (iter_list = button_list; iter_list; iter_list = g_list_next(iter_list))
1570 sheets_dialog_copy_object(iter_list->data, target_wrapbox);
1572 som = gtk_object_get_data(GTK_OBJECT(iter_list->data), "sheet_object_mod");
1573 if (som)
1574 som->mod = SHEET_OBJECT_MOD_DELETED;
1576 gtk_widget_destroy(iter_list->data);
1578 /* MCNFIXME: do we have to resanitize the radio_group? */
1581 /* Force the 1st button in the target wrapbox to be active after moving */
1583 button_list = gtk_container_children(GTK_CONTAINER(target_wrapbox));
1584 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_list->data), TRUE);
1587 static gboolean
1588 copy_file(gchar *src, gchar *dst)
1590 FILE *fp_src;
1591 FILE *fp_dst;
1592 int c;
1594 if ((fp_src = fopen(src, "rb")) == NULL)
1596 message_error(_("Couldn't open '%s': %s"),
1597 dia_message_filename(src), strerror(errno));
1598 return FALSE;
1601 if ((fp_dst = fopen(dst, "wb")) == NULL)
1603 message_error(_("Couldn't open '%s': %s"),
1604 dia_message_filename(dst), strerror(errno));
1605 return FALSE;
1608 while ((c = fgetc(fp_src)) != EOF)
1609 fputc(c, fp_dst);
1611 fclose(fp_src);
1612 fclose(fp_dst);
1614 return TRUE;
1617 /* write a sheet to ~/.dia/sheets */
1618 static gboolean
1619 write_user_sheet(Sheet *sheet)
1621 FILE *file;
1622 xmlDocPtr doc;
1623 xmlNodePtr root;
1624 xmlNodePtr node;
1625 xmlNodePtr object_node;
1626 xmlNodePtr desc_node;
1627 xmlNodePtr icon_node;
1628 gchar buf[512];
1629 time_t time_now;
1630 const char *username;
1631 gchar *dir_user_sheets;
1632 gchar *filename;
1633 SheetObject *sheetobject;
1634 GSList *sheet_objects;
1636 dir_user_sheets = dia_config_filename("sheets");
1637 if (!*(sheet->filename))
1639 gchar *basename;
1641 basename = g_strdup(sheet->name);
1642 basename = g_strdelimit(basename, G_STR_DELIMITERS G_DIR_SEPARATOR_S, '_');
1643 filename = g_strdup_printf("%s%s%s.sheet", dir_user_sheets,
1644 G_DIR_SEPARATOR_S, basename);
1645 g_free(basename);
1647 else
1648 filename = g_strdup_printf("%s%s%s", dir_user_sheets,
1649 G_DIR_SEPARATOR_S, g_basename(sheet->filename));
1651 file = fopen(filename, "w");
1653 if (file==NULL)
1655 message_error(_("Couldn't open: '%s' for writing"),
1656 dia_message_filename(filename));
1657 g_free(filename);
1658 return FALSE;
1660 fclose(file);
1662 time_now = time(NULL);
1663 username = g_get_user_name();
1664 if (username==NULL)
1665 username = _("a user");
1667 doc = xmlNewDoc("1.0");
1668 doc->encoding = xmlStrdup("UTF-8");
1669 doc->standalone = FALSE;
1670 root = xmlNewDocNode(doc, NULL, "sheet", NULL);
1671 doc->xmlRootNode = root;
1672 xmlSetProp(root, "xmlns", DIA_XML_NAME_SPACE_BASE "dia-sheet-ns");
1674 /* comments */
1675 xmlAddChild(root, xmlNewText("\n"));
1676 xmlAddChild(root, xmlNewComment("Dia-Version: "VERSION));
1677 xmlAddChild(root, xmlNewText("\n"));
1678 g_snprintf(buf, sizeof(buf), _("File: %s"), filename);
1679 xmlAddChild(root, xmlNewComment(buf));
1680 xmlAddChild(root, xmlNewText("\n"));
1681 g_snprintf(buf, sizeof(buf), _("Date: %s"), ctime(&time_now));
1682 buf[strlen(buf)-1] = '\0'; /* remove the trailing new line */
1683 xmlAddChild(root, xmlNewComment(buf));
1684 xmlAddChild(root, xmlNewText("\n"));
1685 g_snprintf(buf, sizeof(buf), _("For: %s"), username);
1686 xmlAddChild(root, xmlNewComment(buf));
1687 xmlAddChild(root, xmlNewText("\n\n"));
1689 /* sheet name */
1690 node = xmlNewChild(root, NULL, "name", NULL);
1691 xmlAddChild(node, xmlNewText(sheet->name));
1692 xmlAddChild(root, xmlNewText("\n"));
1694 /* sheet description */
1695 node = xmlNewChild(root, NULL, "description", NULL);
1696 xmlAddChild(node, xmlNewText(sheet->description));
1697 xmlAddChild(root, xmlNewText("\n"));
1699 /* content */
1700 node = xmlNewChild(root, NULL, "contents", NULL);
1701 xmlAddChild(node, xmlNewText("\n"));
1702 xmlAddChild(node, xmlNewComment(_("add shapes here")));
1703 xmlAddChild(node, xmlNewText("\n"));
1705 /* objects */
1706 for (sheet_objects = sheet->objects; sheet_objects;
1707 sheet_objects = g_slist_next(sheet_objects))
1709 SheetObjectMod *som;
1711 som = sheet_objects->data;
1713 if (som->mod == SHEET_OBJECT_MOD_DELETED)
1714 continue;
1716 /* If its a new shape, then copy the .shape and .xpm files from
1717 their current location to ~/.dia/shapes/ */
1719 if (som->mod == SHEET_OBJECT_MOD_NEW)
1721 gchar *dia_user_shapes;
1722 gchar *dest;
1724 dia_user_shapes = dia_config_filename("shapes");
1726 dest = g_strdup_printf("%s%s%s", dia_user_shapes, G_DIR_SEPARATOR_S,
1727 g_basename(som->svg_filename));
1728 copy_file(som->svg_filename, dest);
1729 g_free(dest);
1731 dest = g_strdup_printf("%s%s%s", dia_user_shapes, G_DIR_SEPARATOR_S,
1732 g_basename(som->sheet_object.pixmap_file));
1733 copy_file(som->sheet_object.pixmap_file, dest);
1734 g_free(dest);
1737 sheetobject = &som->sheet_object;
1738 object_node = xmlNewChild(node, NULL, "object", NULL);
1740 xmlSetProp(object_node, "name", sheetobject->object_type);
1742 if (sheetobject->user_data_type == USER_DATA_IS_INTDATA)
1744 gchar *user_data;
1746 user_data = g_strdup_printf("%u", (guint)(sheetobject->user_data));
1747 xmlSetProp(object_node, "intdata", user_data);
1748 g_free(user_data);
1751 xmlAddChild(object_node, xmlNewText("\n"));
1752 desc_node = xmlNewChild(object_node, NULL, "description", NULL);
1753 xmlAddChild(desc_node, xmlNewText(sheetobject->description));
1754 /* xmlAddChild(object_node, xmlNewText("\n")); */
1756 if (sheetobject->has_icon_on_sheet == TRUE)
1758 xmlAddChild(object_node, xmlNewText("\n"));
1759 icon_node = xmlNewChild(desc_node, NULL, "icon", NULL);
1760 xmlAddChild(icon_node, xmlNewText(sheetobject->pixmap_file));
1761 xmlAddChild(object_node, xmlNewText("\n"));
1764 xmlSetDocCompressMode(doc, 0);
1765 xmlDiaSaveFile(filename, doc);
1766 xmlFreeDoc(doc);
1767 return TRUE;
1770 static void
1771 touch_file(gchar *filename)
1773 struct stat stat_buf;
1774 struct utimbuf utim_buf;
1776 stat(filename, &stat_buf);
1777 utim_buf.actime = stat_buf.st_atime;
1778 utim_buf.modtime = time(NULL);
1779 utime(filename, &utim_buf);
1782 static gint
1783 sheets_find_sheet(gconstpointer a, gconstpointer b)
1785 if (!strcmp(((Sheet *)a)->name, ((Sheet *)b)->name))
1786 return 0;
1787 else
1788 return 1;
1791 extern GSList *sheets_mods_list;
1793 void
1794 on_sheets_dialog_button_apply_clicked (GtkButton *button,
1795 gpointer user_data)
1797 GSList *iter_list;
1799 for (iter_list = sheets_mods_list; iter_list;
1800 iter_list = g_slist_next(iter_list))
1802 SheetMod *sm;
1803 GSList *sheets_list;
1804 GSList *find_list;
1806 sm = iter_list->data;
1807 switch (sm->mod)
1809 GSList *sheet_object_mods_list;
1810 GSList *list;
1812 case SHEETMOD_MOD_NEW:
1813 write_user_sheet(&sm->sheet);
1815 sheet_object_mods_list = sm->sheet.objects;
1816 sm->sheet.objects = NULL;
1817 register_sheet(&sm->sheet);
1819 for (list = sheet_object_mods_list; list; list = g_slist_next(list))
1821 SheetObjectMod *som;
1823 som = list->data;
1824 if (som->mod == SHEET_OBJECT_MOD_DELETED)
1825 continue;
1827 sheet_append_sheet_obj(&sm->sheet, &som->sheet_object);
1830 dia_sort_sheets();
1831 fill_sheet_menu();
1832 break;
1834 case SHEETMOD_MOD_CHANGED:
1835 write_user_sheet(&sm->sheet);
1837 sheet_object_mods_list = sm->sheet.objects;
1838 sheets_list = get_sheets_list();
1840 sheets_list = g_slist_find_custom(sheets_list, &sm->sheet,
1841 sheets_find_sheet);
1842 g_assert(sheets_list);
1843 ((Sheet *)(sheets_list->data))->objects = NULL;
1845 for (list = sheet_object_mods_list; list; list = g_slist_next(list))
1847 SheetObjectMod *som;
1849 som = list->data;
1850 if (som->mod == SHEET_OBJECT_MOD_DELETED)
1851 continue;
1853 sheet_append_sheet_obj(sheets_list->data, &som->sheet_object);
1855 fill_sheet_menu();
1856 break;
1858 case SHEETMOD_MOD_DELETED:
1859 if (sm->sheet.scope == SHEET_SCOPE_SYSTEM)
1860 touch_file(sm->sheet.shadowing->filename);
1861 else
1862 unlink(sm->sheet.filename);
1864 sheets_list = get_sheets_list();
1865 find_list = g_slist_find_custom(sheets_list, &sm->sheet,
1866 sheets_find_sheet);
1867 g_assert(sheets_list);
1868 g_slist_remove_link(sheets_list, find_list);
1869 dia_sort_sheets();
1870 fill_sheet_menu();
1871 break;
1873 case SHEETMOD_MOD_NONE:
1874 break;
1876 default:
1877 g_assert_not_reached();
1881 optionmenu_activate_first_pass = TRUE;
1883 sheets_dialog_apply_revert_set_sensitive(FALSE);
1884 sheets_dialog_create();
1888 void
1889 on_sheets_dialog_button_revert_clicked (GtkButton *button,
1890 gpointer user_data)
1892 optionmenu_activate_first_pass = TRUE;
1894 sheets_dialog_apply_revert_set_sensitive(FALSE);
1895 sheets_dialog_create();