re-adding .pngs as binary
[dia.git] / app / sheets_dialog_callbacks.c
blobf80bc65a5ec45de733fa4bae133444996c76670e
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"
64 #include "../lib/charconv.h"
66 #include "interface.h"
67 #include "message.h"
68 #include "sheets.h"
69 #include "sheets_dialog_callbacks.h"
70 #include "sheets_dialog.h"
72 #include "pixmaps/line_break.xpm"
73 #include "intl.h"
75 static GSList *radio_group = NULL;
77 static void
78 sheets_dialog_hide(void)
80 gtk_widget_hide(sheets_dialog);
83 gboolean
84 on_sheets_main_dialog_delete_event (GtkWidget *widget,
85 GdkEvent *event,
86 gpointer user_data)
88 sheets_dialog_hide();
89 return TRUE;
93 gboolean
94 on_sheets_main_dialog_destroy_event (GtkWidget *widget,
95 GdkEvent *event,
96 gpointer user_data)
98 sheets_dialog_hide();
99 return TRUE;
102 static void
103 sheets_dialog_up_down_set_sensitive(GList *wrapbox_button_list,
104 GtkToggleButton *togglebutton)
106 GtkWidget *button;
108 button = lookup_widget(sheets_dialog, "button_move_up");
110 /* If the active button is the 1st in the wrapbox, OR
111 if the active button is a linebreak AND is 2nd in the wrapbox
112 THEN set the 'Up' button to insensitive */
114 if (GTK_TOGGLE_BUTTON(g_list_first(wrapbox_button_list)->data) == togglebutton
115 || (!gtk_object_get_data(GTK_OBJECT(togglebutton), "sheet_object_mod")
116 && g_list_nth(wrapbox_button_list, 1)
117 && GTK_TOGGLE_BUTTON(g_list_nth(wrapbox_button_list, 1)->data)
118 == togglebutton))
119 gtk_widget_set_sensitive(button, FALSE);
120 else
121 gtk_widget_set_sensitive(button, TRUE);
123 button = lookup_widget(sheets_dialog, "button_move_down");
124 if (GTK_TOGGLE_BUTTON(g_list_last(wrapbox_button_list)->data) == togglebutton
125 || (!gtk_object_get_data(GTK_OBJECT(togglebutton), "sheet_object_mod")
126 && g_list_previous(g_list_last(wrapbox_button_list))
127 && GTK_TOGGLE_BUTTON(g_list_previous(g_list_last(wrapbox_button_list))
128 ->data)
129 == togglebutton))
130 gtk_widget_set_sensitive(button, FALSE);
131 else
132 gtk_widget_set_sensitive(button, TRUE);
135 static void
136 on_sheets_dialog_object_button_toggled(GtkToggleButton *togglebutton,
137 gpointer ud_wrapbox)
139 GList *wrapbox_button_list;
140 GtkWidget *button;
141 GtkWidget *table_sheets;
142 GtkWidget *optionmenu_left;
143 GtkWidget *optionmenu_right;
144 gchar *sheet_left;
145 gchar *sheet_right;
147 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(togglebutton)) == FALSE)
148 return;
150 /* We remember the active button so we don't have to search for it later */
152 gtk_object_set_data(GTK_OBJECT(ud_wrapbox), "active_button", togglebutton);
154 /* Same with the active wrapbox */
156 table_sheets = lookup_widget(sheets_dialog, "table_sheets");
157 gtk_object_set_data(GTK_OBJECT(table_sheets), "active_wrapbox", ud_wrapbox);
159 optionmenu_left = lookup_widget(sheets_dialog, "optionmenu_left");
160 sheet_left = gtk_object_get_data(GTK_OBJECT(optionmenu_left),
161 "active_sheet_name");
163 optionmenu_right = lookup_widget(sheets_dialog, "optionmenu_right");
164 sheet_right = gtk_object_get_data(GTK_OBJECT(optionmenu_right),
165 "active_sheet_name");
167 if ((gboolean)gtk_object_get_data(GTK_OBJECT(ud_wrapbox), "is_left") ==TRUE)
169 gtk_object_set_data(GTK_OBJECT(table_sheets), "active_optionmenu",
170 optionmenu_left);
171 button = lookup_widget(sheets_dialog, "button_copy");
172 gtk_object_set(GTK_OBJECT(button), "label", _("Copy ->"), NULL);
173 button = lookup_widget(sheets_dialog, "button_copy_all");
174 gtk_object_set(GTK_OBJECT(button), "label", _("Copy All ->"), NULL);
175 button = lookup_widget(sheets_dialog, "button_move");
176 gtk_object_set(GTK_OBJECT(button), "label", _("Move ->"), NULL);
177 button = lookup_widget(sheets_dialog, "button_move_all");
178 gtk_object_set(GTK_OBJECT(button), "label", _("Move All ->"), NULL);
180 else
182 gtk_object_set_data(GTK_OBJECT(table_sheets), "active_optionmenu",
183 optionmenu_right);
184 button = lookup_widget(sheets_dialog, "button_copy");
185 gtk_object_set(GTK_OBJECT(button), "label", _("<- Copy"), NULL);
186 button = lookup_widget(sheets_dialog, "button_copy_all");
187 gtk_object_set(GTK_OBJECT(button), "label", _("<- Copy All"), NULL);
188 button = lookup_widget(sheets_dialog, "button_move");
189 gtk_object_set(GTK_OBJECT(button), "label", _("<- Move"), NULL);
190 button = lookup_widget(sheets_dialog, "button_move_all");
191 gtk_object_set(GTK_OBJECT(button), "label", _("<- Move All"), NULL);
194 sheet_left = sheet_left ? sheet_left : ""; /* initial value can be NULL */
196 if (!strcmp(sheet_left, sheet_right)
197 || gtk_object_get_data(GTK_OBJECT(togglebutton), "is_hidden_button")
198 || !gtk_object_get_data(GTK_OBJECT(togglebutton), "sheet_object_mod"))
200 button = lookup_widget(sheets_dialog, "button_copy");
201 gtk_widget_set_sensitive(button, FALSE);
202 button = lookup_widget(sheets_dialog, "button_copy_all");
203 gtk_widget_set_sensitive(button, FALSE);
204 button = lookup_widget(sheets_dialog, "button_move");
205 gtk_widget_set_sensitive(button, FALSE);
206 button = lookup_widget(sheets_dialog, "button_move_all");
207 gtk_widget_set_sensitive(button, FALSE);
209 else
211 button = lookup_widget(sheets_dialog, "button_copy");
212 gtk_widget_set_sensitive(button, TRUE);
213 button = lookup_widget(sheets_dialog, "button_copy_all");
214 gtk_widget_set_sensitive(button, TRUE);
215 button = lookup_widget(sheets_dialog, "button_move");
216 gtk_widget_set_sensitive(button, TRUE);
217 button = lookup_widget(sheets_dialog, "button_move_all");
218 gtk_widget_set_sensitive(button, TRUE);
221 wrapbox_button_list = gtk_container_children(GTK_CONTAINER(ud_wrapbox));
223 if (g_list_length(wrapbox_button_list))
225 SheetMod *sm;
227 sheets_dialog_up_down_set_sensitive(wrapbox_button_list, togglebutton);
229 sm = gtk_object_get_data(GTK_OBJECT(togglebutton), "sheet_mod");
231 button = lookup_widget(sheets_dialog, "button_edit");
232 if (!gtk_object_get_data(GTK_OBJECT(togglebutton), "sheet_object_mod")
233 && sm->sheet.scope == SHEET_SCOPE_SYSTEM)
234 gtk_widget_set_sensitive(button, FALSE);
235 else
236 gtk_widget_set_sensitive(button, TRUE);
238 button = lookup_widget(sheets_dialog, "button_remove");
239 if (gtk_object_get_data(GTK_OBJECT(togglebutton), "is_hidden_button")
240 && sm->sheet.shadowing == NULL
241 && sm->sheet.scope == SHEET_SCOPE_SYSTEM)
242 gtk_widget_set_sensitive(button, FALSE);
243 else
244 gtk_widget_set_sensitive(button, TRUE);
246 else
248 button = lookup_widget(sheets_dialog, "button_move_up");
249 gtk_widget_set_sensitive(button, FALSE);
250 button = lookup_widget(sheets_dialog, "button_move_down");
251 gtk_widget_set_sensitive(button, FALSE);
252 button = lookup_widget(sheets_dialog, "button_edit");
253 gtk_widget_set_sensitive(button, FALSE);
254 button = lookup_widget(sheets_dialog, "button_remove");
255 gtk_widget_set_sensitive(button, FALSE);
257 g_list_free(wrapbox_button_list);
260 static void
261 sheets_dialog_wrapbox_add_line_break(GtkWidget *wrapbox)
263 SheetMod *sm;
264 GtkWidget *button;
265 GtkStyle *style;
266 GdkPixmap *pixmap, *mask;
267 GtkWidget *gtkpixmap;
269 sm = gtk_object_get_data(GTK_OBJECT(wrapbox), "sheet_mod");
270 g_assert(sm);
272 button = gtk_radio_button_new(radio_group);
273 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
275 gtk_object_set_data(GTK_OBJECT(button), "sheet_mod", sm);
277 radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
279 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(button), FALSE);
280 gtk_container_set_border_width(GTK_CONTAINER(button), 0);
282 style = gtk_widget_get_style(wrapbox);
283 pixmap =
284 gdk_pixmap_colormap_create_from_xpm_d(NULL,
285 gtk_widget_get_colormap(wrapbox),
286 &mask,
287 &style->bg[GTK_STATE_NORMAL],
288 line_break_xpm);
290 gtkpixmap = gtk_pixmap_new(pixmap, mask);
291 gtk_container_add(GTK_CONTAINER(button), gtkpixmap);
292 gtk_widget_show(gtkpixmap);
294 gtk_wrap_box_pack(GTK_WRAP_BOX(wrapbox), button, FALSE, TRUE, FALSE, TRUE);
295 gtk_widget_show(button);
297 gtk_tooltips_set_tip(sheets_dialog_tooltips, button, _("Line Break"), NULL);
299 gtk_signal_connect(GTK_OBJECT(button), "toggled",
300 GTK_SIGNAL_FUNC(on_sheets_dialog_object_button_toggled),
301 wrapbox);
304 static void
305 sheets_dialog_object_set_tooltip(SheetObjectMod *som, GtkWidget *button)
307 gchar *tip;
308 utfchar *descstr;
310 #ifdef GTK_DOESNT_TALK_UTF8_WE_DO
311 descstr = charconv_utf8_to_local8(som->sheet_object.description);
312 #else
313 descstr = g_strdup(som->sheet_object.description);
314 #endif
316 if (som->type == SHEET_SCOPE_SYSTEM)
317 tip = g_strdup_printf(_("%s\nSystem sheet"), descstr);
318 else
319 tip = g_strdup_printf(_("%s\nUser sheet"), descstr);
321 gtk_tooltips_set_tip(sheets_dialog_tooltips, button, tip, NULL);
322 g_free(tip);
323 g_free(descstr);
326 static GtkWidget *
327 sheets_dialog_create_object_button(SheetObjectMod *som, SheetMod *sm,
328 GtkWidget *wrapbox)
330 GtkWidget *button;
331 GdkPixmap *pixmap, *mask;
332 GtkWidget *gtkpixmap;
334 button = gtk_radio_button_new(radio_group);
335 radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
337 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(button), FALSE);
338 gtk_container_set_border_width(GTK_CONTAINER(button), 0);
340 create_object_pixmap(&som->sheet_object, wrapbox, &pixmap, &mask);
341 gtkpixmap = gtk_pixmap_new(pixmap, mask);
342 gtk_container_add(GTK_CONTAINER(button), gtkpixmap);
343 gtk_widget_show(gtkpixmap);
345 sheets_dialog_object_set_tooltip(som, button);
347 gtk_object_set_data(GTK_OBJECT(button), "sheet_mod", sm);
348 gtk_object_set_data(GTK_OBJECT(button), "sheet_object_mod", som);
350 gtk_signal_connect(GTK_OBJECT(button), "toggled",
351 GTK_SIGNAL_FUNC(on_sheets_dialog_object_button_toggled),
352 wrapbox);
353 return button;
356 gboolean optionmenu_activate_first_pass = TRUE;
358 void
359 on_sheets_dialog_optionmenu_activate (GtkMenuItem *menuitem,
360 gpointer user_data)
362 GtkWidget *wrapbox;
363 Sheet *sheet;
364 GtkWidget *optionmenu;
365 GSList *object_mod_list;
366 GtkWidget *hidden_button;
367 GList *button_list;
369 sheet = &(((SheetMod *)(user_data))->sheet);
371 wrapbox = gtk_object_get_data(GTK_OBJECT(menuitem), "wrapbox");
372 g_assert(wrapbox);
374 /* The hidden button is necessary to keep track of radio_group
375 when there are no objects and to force 'toggled' events */
377 if (optionmenu_activate_first_pass)
379 hidden_button = gtk_radio_button_new(NULL);
380 optionmenu_activate_first_pass = FALSE;
382 else
384 hidden_button = gtk_radio_button_new(radio_group);
385 radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(hidden_button));
388 gtk_signal_connect(GTK_OBJECT(hidden_button), "toggled",
389 GTK_SIGNAL_FUNC(on_sheets_dialog_object_button_toggled),
390 wrapbox);
391 gtk_object_set_data(GTK_OBJECT(hidden_button), "is_hidden_button",
392 (gpointer)TRUE);
393 gtk_object_set_data(GTK_OBJECT(wrapbox), "hidden_button", hidden_button);
394 gtk_object_set_data(GTK_OBJECT(hidden_button), "sheet_mod", user_data);
396 if (gtk_object_get_data(GTK_OBJECT(wrapbox), "is_left"))
397 optionmenu = lookup_widget(sheets_dialog, "optionmenu_left");
398 else
399 optionmenu = lookup_widget(sheets_dialog, "optionmenu_right");
400 gtk_object_set_data(GTK_OBJECT(optionmenu), "active_sheet_name", sheet->name);
402 gtk_container_foreach(GTK_CONTAINER(wrapbox),
403 (GtkCallback)gtk_widget_destroy, NULL);
405 radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(hidden_button));
407 gtk_wrap_box_set_aspect_ratio(GTK_WRAP_BOX(wrapbox), 4 * 1.0 / 9);
408 /* MCNFIXME: calculate this */
409 #ifdef CHANGE_COLOUR_OF_MODIFIED_SHEETS
411 GtkRcStyle *style;
413 style->fg[0].red = style->bg[0].red = 56000;
414 style->fg[1].red = style->bg[1].red = 56000;
415 style->fg[2].red = style->bg[2].red = 56000;
416 style->fg[3].red = style->bg[3].red = 56000;
417 style->fg[4].red = style->bg[4].red = 56000;
418 style->color_flags[0] |= 0x0f;
419 style->color_flags[1] |= 0x0f;
420 style->color_flags[2] |= 0x0f;
421 style->color_flags[3] |= 0x0f;
422 style->color_flags[4] |= 0x0f;
424 sw = lookup_widget(sheets_dialog, "scrolledwindow_right");
425 gtk_widget_modify_style(wrapbox, style);
427 #endif
429 gtk_object_set_data(GTK_OBJECT(wrapbox), "sheet_mod", user_data);
431 for (object_mod_list = sheet->objects; object_mod_list;
432 object_mod_list = g_slist_next(object_mod_list))
434 GtkWidget *button;
435 SheetObjectMod *som;
437 som = object_mod_list->data;
438 if (som->mod == SHEET_OBJECT_MOD_DELETED)
439 continue;
441 if (som->sheet_object.line_break == TRUE)
442 sheets_dialog_wrapbox_add_line_break(wrapbox);
444 button = sheets_dialog_create_object_button(som, user_data, wrapbox);
446 gtk_wrap_box_pack(GTK_WRAP_BOX(wrapbox), button, FALSE, TRUE, FALSE, TRUE);
448 if (som->sheet_object.line_break == TRUE)
449 gtk_wrap_box_set_child_forced_break(GTK_WRAP_BOX(wrapbox), button, TRUE);
451 gtk_widget_show(button);
454 button_list = gtk_container_children(GTK_CONTAINER(wrapbox));
456 if (g_list_length(button_list))
458 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hidden_button), TRUE);
459 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_list->data), TRUE);
461 else
462 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hidden_button), TRUE);
464 g_list_free(button_list);
467 static void
468 sheets_dialog_apply_revert_set_sensitive(gboolean is_sensitive)
470 GtkWidget *button;
472 button = lookup_widget(sheets_dialog, "button_apply");
473 gtk_widget_set_sensitive(button, is_sensitive);
475 button = lookup_widget(sheets_dialog, "button_revert");
476 gtk_widget_set_sensitive(button, is_sensitive);
479 typedef enum
481 SHEETS_DIALOG_MOVE_UP = -1,
482 SHEETS_DIALOG_MOVE_DOWN = +1
484 SheetsDialogMoveDir;
485 #define \
486 SHEETS_DIALOG_MOVE_NONE SHEETS_DIALOG_MOVE_UP
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);
754 void
755 on_sheets_new_dialog_button_ok_clicked (GtkButton *button,
756 gpointer user_data)
758 SheetsNewDialogType active_type;
759 GtkWidget *table_sheets;
760 GtkWidget *wrapbox;
761 GList *button_list;
762 GtkWidget *active_button;
764 table_sheets = lookup_widget(sheets_dialog, "table_sheets");
765 wrapbox = gtk_object_get_data(GTK_OBJECT(table_sheets), "active_wrapbox");
767 active_type = (SheetsNewDialogType)gtk_object_get_data(GTK_OBJECT(button),
768 "active_type");
769 g_assert(active_type);
771 switch (active_type)
773 GtkWidget *entry;
774 gchar *file_name;
775 gchar *p;
776 struct stat stat_buf;
777 GList *plugin_list;
778 ObjectType *ot;
779 gboolean (*custom_object_load_fn)();
780 gint pos;
781 GtkWidget *active_button;
782 GList *button_list;
783 SheetObjectMod *som;
784 SheetMod *sm;
785 SheetObject *sheet_obj;
786 utfchar *sheet_name;
787 utfchar *sheet_descrip;
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", file_name);
802 g_free(file_name);
803 return;
806 if (stat(file_name, &stat_buf) == -1)
808 message_error(_("Error examining %s: %s"), file_name, strerror(errno));
809 g_free(file_name);
810 return;
813 custom_object_load_fn = NULL;
814 for (plugin_list = dia_list_plugins(); plugin_list != NULL;
815 plugin_list = g_list_next(plugin_list))
817 GModule *module = ((PluginInfo *)(plugin_list->data))->module;
819 if (module == NULL)
820 continue;
822 if (g_module_symbol(module, "custom_object_load",
823 (gpointer)&custom_object_load_fn) == TRUE)
824 break;
826 g_assert(custom_object_load_fn);
828 if (!(*custom_object_load_fn)(file_name, &ot))
830 message_error(_("Could not interpret shape file: '%s'"), 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 charconv_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 = 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 entry = lookup_widget(sheets_new_dialog, "entry_sheet_name");
891 sheet_name = charconv_gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
893 sheet_name = g_strchug(g_strchomp(sheet_name));
894 if (!*sheet_name)
896 message_error(_("Sheet must have a Name"));
897 return;
900 entry = lookup_widget(sheets_new_dialog, "entry_sheet_description");
901 sheet_descrip = charconv_gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
903 sheet = g_new(Sheet, 1);
904 sheet->name = sheet_name;
905 sheet->filename = "";
906 sheet->description = sheet_descrip;
907 sheet->scope = SHEET_SCOPE_USER;
908 sheet->shadowing = NULL;
909 sheet->objects = NULL;
911 sm = sheets_append_sheet_mods(sheet);
912 sm->mod = SHEETMOD_MOD_NEW;
914 table_sheets = lookup_widget(sheets_dialog, "table_sheets");
915 optionmenu = gtk_object_get_data(GTK_OBJECT(table_sheets),
916 "active_optionmenu");
917 g_assert(optionmenu);
918 sheets_optionmenu_create(optionmenu, wrapbox, NULL);
920 break;
922 default:
923 g_assert_not_reached();
926 sheets_dialog_apply_revert_set_sensitive(TRUE);
928 button_list = gtk_container_children(GTK_CONTAINER(wrapbox));
929 active_button = gtk_object_get_data(GTK_OBJECT(wrapbox), "active_button");
930 sheets_dialog_up_down_set_sensitive(button_list,
931 GTK_TOGGLE_BUTTON(active_button));
932 g_list_free(button_list);
934 gtk_widget_destroy(sheets_new_dialog);
937 static GtkWidget *sheets_shapeselection_dialog;
939 void
940 on_sheets_new_dialog_button_browse_clicked
941 (GtkButton *button,
942 gpointer user_data)
944 sheets_shapeselection_dialog = create_sheets_shapeselection_dialog();
945 gtk_widget_show(sheets_shapeselection_dialog);
948 void
949 on_sheets_shapeselection_dialog_button_cancel_clicked
950 (GtkButton *button,
951 gpointer user_data)
953 gtk_widget_destroy(sheets_shapeselection_dialog);
956 void
957 on_sheets_shapeselection_dialog_button_ok_clicked
958 (GtkButton *button,
959 gpointer user_data)
961 gchar *filename;
962 GtkWidget *entry;
964 filename = gtk_file_selection_get_filename(
965 GTK_FILE_SELECTION(sheets_shapeselection_dialog));
967 entry = lookup_widget(sheets_new_dialog, "combo_entry_from_file");
968 /* Since this is a filename entry from the dialog, no utf is needed */
969 gtk_entry_set_text(GTK_ENTRY(entry), filename);
971 gtk_widget_destroy(sheets_shapeselection_dialog);
974 static GtkWidget *sheets_edit_dialog;
976 void
977 on_sheets_dialog_button_edit_clicked (GtkButton *button,
978 gpointer user_data)
980 GtkWidget *wrapbox;
981 GList *button_list;
982 GtkWidget *active_button;
983 SheetObjectMod *som;
984 utfchar *descrip;
985 utfchar *type;
986 GtkWidget *entry;
987 SheetMod *sm;
988 gchar *name;
990 sheets_edit_dialog = create_sheets_edit_dialog();
992 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
993 som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
994 if (som)
996 descrip = som->sheet_object.description;
997 type = sheet_object_mod_get_type_string(som);
1000 entry = lookup_widget(sheets_edit_dialog, "entry_object_description");
1001 if (som)
1002 charconv_gtk_entry_set_text(GTK_ENTRY(entry), descrip);
1003 else
1004 gtk_widget_set_sensitive(entry, FALSE);
1006 entry = lookup_widget(sheets_edit_dialog, "entry_object_type");
1007 if (som)
1008 charconv_gtk_entry_set_text(GTK_ENTRY(entry), type);
1009 else
1010 gtk_widget_set_sensitive(entry, FALSE);
1012 sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1013 if (sm)
1015 name = sm->sheet.name;
1016 descrip = sm->sheet.description;
1019 entry = lookup_widget(sheets_edit_dialog, "entry_sheet_name");
1020 charconv_gtk_entry_set_text(GTK_ENTRY(entry), name);
1021 #if CAN_EDIT_SHEET_NAME
1022 if (sm->sheet.scope == SHEET_SCOPE_SYSTEM)
1023 #endif
1024 gtk_widget_set_sensitive(entry, FALSE);
1026 entry = lookup_widget(sheets_edit_dialog, "entry_sheet_description");
1027 charconv_gtk_entry_set_text(GTK_ENTRY(entry), descrip);
1029 gtk_widget_show(sheets_edit_dialog);
1032 void
1033 on_sheets_edit_dialog_button_cancel_clicked
1034 (GtkButton *button,
1035 gpointer user_data)
1037 gtk_widget_destroy(sheets_edit_dialog);
1040 static GtkWidget *sheets_remove_dialog;
1042 typedef enum
1044 SHEETS_REMOVE_DIALOG_TYPE_OBJECT = 1,
1045 SHEETS_REMOVE_DIALOG_TYPE_SHEET
1047 SheetsRemoveDialogType;
1049 void
1050 on_sheets_dialog_button_remove_clicked (GtkButton *button,
1051 gpointer user_data)
1053 GtkWidget *wrapbox;
1054 GList *button_list;
1055 GtkWidget *active_button;
1056 SheetMod *sm;
1057 GtkWidget *entry;
1058 GtkWidget *radio_button;
1060 sheets_remove_dialog = create_sheets_remove_dialog();
1062 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1063 g_assert(active_button);
1065 /* Force a change in state in the radio button for set sensitive */
1067 radio_button = lookup_widget(sheets_remove_dialog, "radiobutton_sheet");
1068 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
1070 entry = lookup_widget(sheets_remove_dialog, "entry_object");
1071 if (gtk_object_get_data(GTK_OBJECT(active_button), "is_hidden_button"))
1073 radio_button = lookup_widget(sheets_remove_dialog, "radiobutton_object");
1074 gtk_widget_set_sensitive(radio_button, FALSE);
1075 gtk_widget_set_sensitive(entry, FALSE);
1077 else
1079 SheetObjectMod *som;
1081 som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
1082 if (!som)
1083 gtk_entry_set_text(GTK_ENTRY(entry), _("Line Break"));
1084 else
1085 charconv_gtk_entry_set_text(GTK_ENTRY(entry), som->sheet_object.description);
1087 radio_button = lookup_widget(sheets_remove_dialog, "radiobutton_object");
1088 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
1091 entry = lookup_widget(sheets_remove_dialog, "entry_sheet");
1092 sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1094 /* Note: It is currently impossible to remove a user sheet that has
1095 been shadowed by a more recent system sheet--the logic is just
1096 too hairy. Once the user sheet has been updated, or the [copy of
1097 system] sheet has been removed, then they can remove the user
1098 sheet just fine (in the next invocation of dia). This would
1099 be rare, to say the least... */
1101 if (sm->sheet.shadowing == NULL && sm->sheet.scope == SHEET_SCOPE_SYSTEM)
1103 GtkWidget *radio_button;
1105 radio_button = lookup_widget(sheets_remove_dialog, "radiobutton_sheet");
1106 gtk_widget_set_sensitive(radio_button, FALSE);
1107 gtk_widget_set_sensitive(entry, FALSE);
1109 charconv_gtk_entry_set_text(GTK_ENTRY(entry), sm->sheet.name);
1111 gtk_widget_show(sheets_remove_dialog);
1114 void
1115 on_sheets_remove_dialog_button_cancel_clicked
1116 (GtkButton *button,
1117 gpointer user_data)
1119 gtk_widget_destroy(sheets_remove_dialog);
1122 static void
1123 sheets_dialog_togglebutton_set_sensitive(GtkToggleButton *togglebutton,
1124 GtkWidget *dialog,
1125 gchar *widget_names[], gint type)
1127 gboolean is_sensitive;
1128 guint i;
1129 GtkWidget *tmp;
1131 is_sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(togglebutton));
1132 if (is_sensitive)
1134 tmp = lookup_widget(dialog, "button_ok");
1135 gtk_object_set_data(GTK_OBJECT(tmp), "active_type", (gpointer)type);
1138 for (i = 0; widget_names[i]; i++)
1140 tmp = lookup_widget(dialog, widget_names[i]);
1141 gtk_widget_set_sensitive(tmp, is_sensitive);
1145 void
1146 on_sheets_new_dialog_radiobutton_svg_shape_toggled
1147 (GtkToggleButton *togglebutton,
1148 gpointer user_data)
1150 static gchar *widget_names[] =
1152 "combo_from_file",
1153 "button_browse",
1154 "label_svg_description",
1155 "entry_svg_description",
1156 NULL
1159 sheets_dialog_togglebutton_set_sensitive(togglebutton, sheets_new_dialog,
1160 widget_names,
1161 SHEETS_NEW_DIALOG_TYPE_SVG_SHAPE);
1164 void
1165 on_sheets_new_dialog_radiobutton_sheet_toggled
1166 (GtkToggleButton *togglebutton,
1167 gpointer user_data)
1169 static gchar *widget_names[] =
1171 "entry_sheet_name",
1172 "entry_sheet_description",
1173 "label_description",
1174 NULL
1177 sheets_dialog_togglebutton_set_sensitive(togglebutton, sheets_new_dialog,
1178 widget_names,
1179 SHEETS_NEW_DIALOG_TYPE_SHEET);
1182 void
1183 on_sheets_new_dialog_radiobutton_line_break_toggled
1184 (GtkToggleButton *togglebutton,
1185 gpointer user_data)
1187 static gchar *widget_names[] =
1189 NULL
1192 sheets_dialog_togglebutton_set_sensitive(togglebutton, sheets_new_dialog,
1193 widget_names,
1194 SHEETS_NEW_DIALOG_TYPE_LINE_BREAK);
1197 void
1198 on_sheets_remove_dialog_radiobutton_object_toggled
1199 (GtkToggleButton *togglebutton,
1200 gpointer user_data)
1202 gchar *widget_names[] =
1204 "pixmap_object",
1205 "entry_object",
1206 NULL
1209 sheets_dialog_togglebutton_set_sensitive(togglebutton, sheets_remove_dialog,
1210 widget_names,
1211 SHEETS_REMOVE_DIALOG_TYPE_OBJECT);
1214 void
1215 on_sheets_remove_dialog_radiobutton_sheet_toggled
1216 (GtkToggleButton *togglebutton,
1217 gpointer user_data)
1219 gchar *widget_names[] =
1221 "entry_sheet",
1222 NULL
1225 sheets_dialog_togglebutton_set_sensitive(togglebutton, sheets_remove_dialog,
1226 widget_names,
1227 SHEETS_REMOVE_DIALOG_TYPE_SHEET);
1230 static GtkWidget *
1231 sheets_dialog_set_new_active_button(void)
1233 GtkWidget *active_button;
1234 GtkWidget *wrapbox;
1235 GList *button_list;
1236 GList *active_button_list;
1237 GtkWidget *new_active_button;
1239 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1241 active_button_list = g_list_find(button_list, active_button);
1242 g_assert(active_button_list);
1243 if (g_list_next(active_button_list))
1244 new_active_button = g_list_next(active_button_list)->data;
1245 else
1247 if (g_list_previous(active_button_list))
1248 new_active_button = g_list_previous(active_button_list)->data;
1249 else
1250 new_active_button = gtk_object_get_data(GTK_OBJECT(wrapbox),
1251 "hidden_button");
1253 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(new_active_button), TRUE);
1255 return new_active_button;
1258 void
1259 on_sheets_remove_dialog_button_ok_clicked
1260 (GtkButton *button,
1261 gpointer user_data)
1263 SheetsRemoveDialogType type;
1264 GtkWidget *wrapbox;
1265 GList *button_list;
1266 GtkWidget *active_button;
1268 type = (SheetsRemoveDialogType)gtk_object_get_data(GTK_OBJECT(button),
1269 "active_type");
1271 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1273 switch (type)
1275 SheetObjectMod *som;
1276 GtkWidget *new_active_button;
1277 SheetMod *sm;
1278 GtkWidget *table_sheets;
1279 GtkWidget *optionmenu;
1281 case SHEETS_REMOVE_DIALOG_TYPE_OBJECT:
1283 som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
1284 if (som)
1286 sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1287 sm->mod = SHEETMOD_MOD_CHANGED;
1288 som->mod = SHEET_OBJECT_MOD_DELETED;
1290 new_active_button = sheets_dialog_set_new_active_button();
1292 gtk_widget_destroy(active_button);
1293 radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(new_active_button));
1295 sheets_dialog_normalize_line_breaks(wrapbox, SHEETS_DIALOG_MOVE_NONE);
1296 break;
1298 case SHEETS_REMOVE_DIALOG_TYPE_SHEET:
1300 sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1301 sm->mod = SHEETMOD_MOD_DELETED;
1303 if (sm->sheet.shadowing && sm->sheet.scope == SHEET_SCOPE_USER)
1304 sheets_append_sheet_mods(sm->sheet.shadowing);
1306 table_sheets = lookup_widget(sheets_dialog, "table_sheets");
1307 optionmenu = gtk_object_get_data(GTK_OBJECT(table_sheets),
1308 "active_optionmenu");
1309 g_assert(optionmenu);
1310 sheets_optionmenu_create(optionmenu, wrapbox, NULL);
1312 break;
1314 default:
1315 g_assert_not_reached();
1318 g_list_free(button_list);
1320 sheets_dialog_apply_revert_set_sensitive(TRUE);
1321 gtk_widget_destroy(sheets_remove_dialog);
1324 void
1325 on_sheets_edit_dialog_button_ok_clicked
1326 (GtkButton *button,
1327 gpointer user_data)
1329 GtkWidget *active_button;
1330 GtkWidget *wrapbox;
1331 GList *button_list;
1332 GtkWidget *entry;
1333 gboolean something_changed = FALSE;
1335 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1336 g_assert(active_button);
1338 entry = lookup_widget(sheets_edit_dialog, "entry_object_description");
1339 if ((gboolean)gtk_object_get_data(GTK_OBJECT(entry), "changed") == TRUE)
1341 SheetMod *sm;
1342 SheetObjectMod *som;
1344 som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
1345 som->sheet_object.description =
1346 charconv_gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
1347 sheets_dialog_object_set_tooltip(som, active_button);
1349 som->mod = SHEET_OBJECT_MOD_CHANGED;
1351 sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1352 if (sm->mod == SHEETMOD_MOD_NONE)
1353 sm->mod = SHEETMOD_MOD_CHANGED;
1355 something_changed = TRUE;
1358 entry = lookup_widget(sheets_edit_dialog, "entry_sheet_description");
1359 if ((gboolean)gtk_object_get_data(GTK_OBJECT(entry), "changed") == TRUE)
1361 SheetMod *sm;
1363 sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1364 sm->sheet.description =
1365 charconv_gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
1367 if (sm->mod == SHEETMOD_MOD_NONE)
1368 sm->mod = SHEETMOD_MOD_CHANGED;
1369 something_changed = TRUE;
1372 #ifdef CAN_EDIT_SHEET_NAME
1373 /* This must be last because we reload the sheets if changed */
1375 entry = lookup_widget(sheets_edit_dialog, "entry_sheet_name");
1376 if ((gboolean)gtk_object_get_data(GTK_OBJECT(entry), "changed") == TRUE)
1378 SheetMod *sm;
1379 GtkWidget *table_sheets;
1380 GtkWidget *optionmenu;
1382 sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1383 sm->sheet.name = charconv_gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
1384 if (sm->mod == SHEETMOD_MOD_NONE)
1385 sm->mod = SHEETMOD_MOD_CHANGED;
1387 table_sheets = lookup_widget(sheets_dialog, "table_sheets");
1388 optionmenu = gtk_object_get_data(GTK_OBJECT(table_sheets),
1389 "active_optionmenu");
1390 sheets_optionmenu_create(optionmenu, wrapbox, NULL);
1392 something_changed = TRUE;
1394 #endif
1395 if (something_changed == TRUE)
1396 sheets_dialog_apply_revert_set_sensitive(TRUE);
1398 gtk_widget_destroy(sheets_edit_dialog);
1401 void
1402 on_sheets_edit_dialog_entry_object_description_changed
1403 (GtkEditable *editable,
1404 gpointer user_data)
1406 gtk_object_set_data(GTK_OBJECT(editable), "changed", (gpointer)TRUE);
1410 void
1411 on_sheets_edit_dialog_entry_sheet_description_changed
1412 (GtkEditable *editable,
1413 gpointer user_data)
1415 gtk_object_set_data(GTK_OBJECT(editable), "changed", (gpointer)TRUE);
1418 void
1419 on_sheets_edit_dialog_entry_sheet_name_changed
1420 (GtkEditable *editable,
1421 gpointer user_data)
1423 gtk_object_set_data(GTK_OBJECT(editable), "changed", (gpointer)TRUE);
1426 static GtkWidget *
1427 sheets_dialog_get_target_wrapbox(GtkWidget *wrapbox)
1429 if (gtk_object_get_data(GTK_OBJECT(wrapbox), "is_left"))
1430 return gtk_object_get_data(GTK_OBJECT(sheets_dialog), "wrapbox_right");
1431 else
1432 return gtk_object_get_data(GTK_OBJECT(sheets_dialog), "wrapbox_left");
1435 static void
1436 sheets_dialog_copy_object(GtkWidget *active_button, GtkWidget *target_wrapbox)
1438 GtkWidget *button;
1439 SheetMod *sm;
1440 SheetObjectMod *som;
1441 SheetObjectMod *som_new;
1442 SheetObject *so;
1444 sm = gtk_object_get_data(GTK_OBJECT(target_wrapbox), "sheet_mod");
1445 som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
1447 if (!som)
1448 return;
1450 so = g_new(SheetObject, 1);
1451 so->object_type = g_strdup(som->sheet_object.object_type);
1452 so->description = g_strdup(som->sheet_object.description);
1453 so->pixmap = som->sheet_object.pixmap;
1454 so->user_data = som->sheet_object.user_data;
1455 so->user_data_type = som->sheet_object.user_data_type;
1456 so->line_break = FALSE; /* must be false--we don't copy linebreaks */
1457 so->pixmap_file = g_strdup(som->sheet_object.pixmap_file);
1458 so->has_icon_on_sheet = som->sheet_object.has_icon_on_sheet;
1460 som_new = g_new(SheetObjectMod, 1);
1461 som_new->sheet_object = *so;
1462 som_new->type = som->type;
1463 som_new->mod = SHEET_OBJECT_MOD_NONE;
1465 sm->sheet.objects = g_slist_append(sm->sheet.objects, som_new);
1466 if (sm->mod == SHEETMOD_MOD_NONE)
1467 sm->mod = SHEETMOD_MOD_CHANGED;
1469 button = sheets_dialog_create_object_button(som_new, sm, target_wrapbox);
1470 gtk_wrap_box_pack(GTK_WRAP_BOX(target_wrapbox), button,
1471 FALSE, TRUE, FALSE, TRUE);
1472 gtk_widget_show(button);
1474 sheets_dialog_apply_revert_set_sensitive(TRUE);
1477 void
1478 on_sheets_dialog_button_copy_clicked (GtkButton *button,
1479 gpointer user_data)
1481 GtkWidget *active_button;
1482 GtkWidget *wrapbox;
1483 GList *button_list;
1484 GtkWidget *target_wrapbox;
1486 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1488 target_wrapbox = sheets_dialog_get_target_wrapbox(wrapbox);
1490 sheets_dialog_copy_object(active_button, target_wrapbox);
1493 void
1494 on_sheets_dialog_button_copy_all_clicked
1495 (GtkButton *button,
1496 gpointer user_data)
1498 GtkWidget *active_button;
1499 GtkWidget *wrapbox;
1500 GList *button_list, *iter_list;
1501 GtkWidget *target_wrapbox;
1503 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1505 target_wrapbox = sheets_dialog_get_target_wrapbox(wrapbox);
1507 for (iter_list = button_list; iter_list; iter_list = g_list_next(iter_list))
1508 sheets_dialog_copy_object(iter_list->data, target_wrapbox);
1511 void
1512 on_sheets_dialog_button_move_clicked (GtkButton *button,
1513 gpointer user_data)
1515 GtkWidget *active_button;
1516 GtkWidget *wrapbox;
1517 GList *button_list;
1518 GtkWidget *target_wrapbox;
1519 SheetObjectMod *som;
1520 GtkWidget *new_active_button;
1522 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1524 target_wrapbox = sheets_dialog_get_target_wrapbox(wrapbox);
1526 sheets_dialog_copy_object(active_button, target_wrapbox);
1528 som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
1529 if (som)
1530 som->mod = SHEET_OBJECT_MOD_DELETED;
1532 new_active_button = sheets_dialog_set_new_active_button();
1534 gtk_widget_destroy(active_button);
1535 radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(new_active_button));
1537 sheets_dialog_normalize_line_breaks(wrapbox, SHEETS_DIALOG_MOVE_NONE);
1540 void
1541 on_sheets_dialog_button_move_all_clicked
1542 (GtkButton *button,
1543 gpointer user_data)
1545 GtkWidget *active_button;
1546 GtkWidget *wrapbox;
1547 GList *button_list;
1548 GList *iter_list;
1549 GtkWidget *target_wrapbox;
1550 SheetObjectMod *som;
1552 active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1554 target_wrapbox = sheets_dialog_get_target_wrapbox(wrapbox);
1556 for (iter_list = button_list; iter_list; iter_list = g_list_next(iter_list))
1558 sheets_dialog_copy_object(iter_list->data, target_wrapbox);
1560 som = gtk_object_get_data(GTK_OBJECT(iter_list->data), "sheet_object_mod");
1561 if (som)
1562 som->mod = SHEET_OBJECT_MOD_DELETED;
1564 gtk_widget_destroy(iter_list->data);
1566 /* MCNFIXME: do we have to resanitize the radio_group? */
1569 /* Force the 1st button in the target wrapbox to be active after moving */
1571 button_list = gtk_container_children(GTK_CONTAINER(target_wrapbox));
1572 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_list->data), TRUE);
1575 static gboolean
1576 copy_file(gchar *src, gchar *dst)
1578 FILE *fp_src;
1579 FILE *fp_dst;
1580 int c;
1582 if ((fp_src = fopen(src, "rb")) == NULL)
1584 message_error(_("Couldn't open '%s': %s"), src, strerror(errno));
1585 return FALSE;
1588 if ((fp_dst = fopen(dst, "wb")) == NULL)
1590 message_error(_("Couldn't open '%s': %s"), dst, strerror(errno));
1591 return FALSE;
1594 while ((c = fgetc(fp_src)) != EOF)
1595 fputc(c, fp_dst);
1597 fclose(fp_src);
1598 fclose(fp_dst);
1600 return TRUE;
1603 /* write a sheet to ~/.dia/sheets */
1604 static gboolean
1605 write_user_sheet(Sheet *sheet)
1607 FILE *file;
1608 xmlDocPtr doc;
1609 xmlNodePtr root;
1610 xmlNodePtr node;
1611 xmlNodePtr object_node;
1612 xmlNodePtr desc_node;
1613 xmlNodePtr icon_node;
1614 gchar buf[512];
1615 time_t time_now;
1616 char *username;
1617 gchar *dir_user_sheets;
1618 gchar *filename;
1619 SheetObject *sheetobject;
1620 GSList *sheet_objects;
1622 dir_user_sheets = dia_config_filename("sheets");
1623 if (!*(sheet->filename))
1625 gchar *basename;
1627 basename = g_strdup(sheet->name);
1628 basename = g_strdelimit(basename, G_STR_DELIMITERS G_DIR_SEPARATOR_S, '_');
1629 filename = g_strdup_printf("%s%s%s.sheet", dir_user_sheets,
1630 G_DIR_SEPARATOR_S, basename);
1631 g_free(basename);
1633 else
1634 filename = g_strdup_printf("%s%s%s", dir_user_sheets,
1635 G_DIR_SEPARATOR_S, g_basename(sheet->filename));
1637 file = fopen(filename, "w");
1639 if (file==NULL)
1641 message_error(_("Couldn't open: '%s' for writing"), filename);
1642 g_free(filename);
1643 return FALSE;
1645 fclose(file);
1647 time_now = time(NULL);
1648 username = getlogin();
1649 if (username==NULL)
1650 username = _("a user");
1652 doc = xmlNewDoc("1.0");
1653 doc->encoding = xmlStrdup("UTF-8");
1654 doc->standalone = FALSE;
1655 root = xmlNewDocNode(doc, NULL, "sheet", NULL);
1656 doc->xmlRootNode = root;
1657 xmlSetProp(root, "xmlns", "http://www.lysator.liu.se/~alla/dia/dia-sheet-ns");
1659 /* comments */
1660 xmlAddChild(root, xmlNewText("\n"));
1661 xmlAddChild(root, xmlNewComment("Dia-Version: "VERSION));
1662 xmlAddChild(root, xmlNewText("\n"));
1663 g_snprintf(buf, sizeof(buf), _("File: %s"), filename);
1664 xmlAddChild(root, xmlNewComment(buf));
1665 xmlAddChild(root, xmlNewText("\n"));
1666 g_snprintf(buf, sizeof(buf), _("Date: %s"), ctime(&time_now));
1667 buf[strlen(buf)-1] = '\0'; /* remove the trailing new line */
1668 xmlAddChild(root, xmlNewComment(buf));
1669 xmlAddChild(root, xmlNewText("\n"));
1670 g_snprintf(buf, sizeof(buf), _("For: %s"), username);
1671 xmlAddChild(root, xmlNewComment(buf));
1672 xmlAddChild(root, xmlNewText("\n\n"));
1674 /* sheet name */
1675 node = xmlNewChild(root, NULL, "name", NULL);
1676 xmlAddChild(node, xmlNewText(sheet->name));
1677 xmlAddChild(root, xmlNewText("\n"));
1679 /* sheet description */
1680 node = xmlNewChild(root, NULL, "description", NULL);
1681 xmlAddChild(node, xmlNewText(sheet->description));
1682 xmlAddChild(root, xmlNewText("\n"));
1684 /* content */
1685 node = xmlNewChild(root, NULL, "contents", NULL);
1686 xmlAddChild(node, xmlNewText("\n"));
1687 xmlAddChild(node, xmlNewComment(_("add shapes here")));
1688 xmlAddChild(node, xmlNewText("\n"));
1690 /* objects */
1691 for (sheet_objects = sheet->objects; sheet_objects;
1692 sheet_objects = g_slist_next(sheet_objects))
1694 SheetObjectMod *som;
1696 som = sheet_objects->data;
1698 if (som->mod == SHEET_OBJECT_MOD_DELETED)
1699 continue;
1701 /* If its a new shape, then copy the .shape and .xpm files from
1702 their current location to ~/.dia/shapes/ */
1704 if (som->mod == SHEET_OBJECT_MOD_NEW)
1706 gchar *dia_user_shapes;
1707 gchar *dest;
1709 dia_user_shapes = dia_config_filename("shapes");
1711 dest = g_strdup_printf("%s%s%s", dia_user_shapes, G_DIR_SEPARATOR_S,
1712 g_basename(som->svg_filename));
1713 copy_file(som->svg_filename, dest);
1714 g_free(dest);
1716 dest = g_strdup_printf("%s%s%s", dia_user_shapes, G_DIR_SEPARATOR_S,
1717 g_basename(som->sheet_object.pixmap_file));
1718 copy_file(som->sheet_object.pixmap_file, dest);
1719 g_free(dest);
1722 sheetobject = &som->sheet_object;
1723 object_node = xmlNewChild(node, NULL, "object", NULL);
1725 xmlSetProp(object_node, "name", sheetobject->object_type);
1727 if (sheetobject->user_data_type == USER_DATA_IS_INTDATA)
1729 gchar *user_data;
1731 user_data = g_strdup_printf("%u", (guint)(sheetobject->user_data));
1732 xmlSetProp(object_node, "intdata", user_data);
1733 g_free(user_data);
1736 xmlAddChild(object_node, xmlNewText("\n"));
1737 desc_node = xmlNewChild(object_node, NULL, "description", NULL);
1738 xmlAddChild(desc_node, xmlNewText(sheetobject->description));
1739 /* xmlAddChild(object_node, xmlNewText("\n")); */
1741 if (sheetobject->has_icon_on_sheet == TRUE)
1743 xmlAddChild(object_node, xmlNewText("\n"));
1744 icon_node = xmlNewChild(desc_node, NULL, "icon", NULL);
1745 xmlAddChild(icon_node, xmlNewText(sheetobject->pixmap_file));
1746 xmlAddChild(object_node, xmlNewText("\n"));
1749 xmlSetDocCompressMode(doc, 0);
1750 xmlDiaSaveFile(filename, doc);
1751 xmlFreeDoc(doc);
1752 return TRUE;
1755 static void
1756 touch_file(gchar *filename)
1758 struct stat stat_buf;
1759 struct utimbuf utim_buf;
1761 stat(filename, &stat_buf);
1762 utim_buf.actime = stat_buf.st_atime;
1763 utim_buf.modtime = time(NULL);
1764 utime(filename, &utim_buf);
1767 static gint
1768 sheets_find_sheet(gconstpointer a, gconstpointer b)
1770 if (!strcmp(((Sheet *)a)->name, ((Sheet *)b)->name))
1771 return 0;
1772 else
1773 return 1;
1776 extern GSList *sheets_mods_list;
1778 void
1779 on_sheets_dialog_button_apply_clicked (GtkButton *button,
1780 gpointer user_data)
1782 GSList *iter_list;
1784 for (iter_list = sheets_mods_list; iter_list;
1785 iter_list = g_slist_next(iter_list))
1787 SheetMod *sm;
1788 GSList *sheets_list;
1789 GSList *find_list;
1791 sm = iter_list->data;
1792 switch (sm->mod)
1794 GSList *sheet_object_mods_list;
1795 GSList *list;
1797 case SHEETMOD_MOD_NEW:
1798 write_user_sheet(&sm->sheet);
1800 sheet_object_mods_list = sm->sheet.objects;
1801 sm->sheet.objects = NULL;
1802 register_sheet(&sm->sheet);
1804 for (list = sheet_object_mods_list; list; list = g_slist_next(list))
1806 SheetObjectMod *som;
1808 som = list->data;
1809 if (som->mod == SHEET_OBJECT_MOD_DELETED)
1810 continue;
1812 sheet_append_sheet_obj(&sm->sheet, &som->sheet_object);
1815 dia_sort_sheets();
1816 fill_sheet_menu();
1817 break;
1819 case SHEETMOD_MOD_CHANGED:
1820 write_user_sheet(&sm->sheet);
1822 sheet_object_mods_list = sm->sheet.objects;
1823 sheets_list = get_sheets_list();
1825 sheets_list = g_slist_find_custom(sheets_list, &sm->sheet,
1826 sheets_find_sheet);
1827 g_assert(sheets_list);
1828 ((Sheet *)(sheets_list->data))->objects = NULL;
1830 for (list = sheet_object_mods_list; list; list = g_slist_next(list))
1832 SheetObjectMod *som;
1834 som = list->data;
1835 if (som->mod == SHEET_OBJECT_MOD_DELETED)
1836 continue;
1838 sheet_append_sheet_obj(sheets_list->data, &som->sheet_object);
1840 fill_sheet_menu();
1841 break;
1843 case SHEETMOD_MOD_DELETED:
1844 if (sm->sheet.scope == SHEET_SCOPE_SYSTEM)
1845 touch_file(sm->sheet.shadowing->filename);
1846 else
1847 unlink(sm->sheet.filename);
1849 sheets_list = get_sheets_list();
1850 find_list = g_slist_find_custom(sheets_list, &sm->sheet,
1851 sheets_find_sheet);
1852 g_assert(sheets_list);
1853 g_slist_remove_link(sheets_list, find_list);
1854 dia_sort_sheets();
1855 fill_sheet_menu();
1856 break;
1858 case SHEETMOD_MOD_NONE:
1859 break;
1861 default:
1862 g_assert_not_reached();
1866 optionmenu_activate_first_pass = TRUE;
1868 sheets_dialog_apply_revert_set_sensitive(FALSE);
1869 sheets_dialog_create();
1873 void
1874 on_sheets_dialog_button_revert_clicked (GtkButton *button,
1875 gpointer user_data)
1877 optionmenu_activate_first_pass = TRUE;
1879 sheets_dialog_apply_revert_set_sensitive(FALSE);
1880 sheets_dialog_create();