Removed debugging include.
[dia.git] / app / sheets.c
blobdf0eb9fc85a9187c426e0f7fddef730463ada685
1 /* Dia -- a diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * sheets.c : a sheets and objects dialog
5 * Copyright (C) 2002 M.C. Nelson
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include <string.h>
25 #ifdef GNOME
26 #include <gnome.h>
27 #else
28 #include <gtk/gtk.h>
29 #endif
31 #include <gdk-pixbuf/gdk-pixbuf.h>
32 #include <gmodule.h>
34 #include "../lib/plug-ins.h"
35 #include "../lib/sheet.h"
36 #include "../lib/message.h"
37 #include "../lib/object.h"
38 #include "../app/pixmaps/missing.xpm"
40 #include "interface.h"
41 #include "sheets.h"
42 #include "sheets_dialog.h"
43 #include "gtkhwrapbox.h"
45 GtkWidget *sheets_dialog = NULL;
46 GSList *sheets_mods_list = NULL;
47 GtkTooltips *sheets_dialog_tooltips = NULL;
48 static gpointer custom_type_symbol;
50 /* Given a SheetObject and a SheetMod, create a new SheetObjectMod
51 and hook it into the 'objects' list in the SheetMod->sheet
53 NOTE: that the objects structure points to SheetObjectMod's and
54 *not* SheetObject's */
56 SheetObjectMod *
57 sheets_append_sheet_object_mod(SheetObject *so, SheetMod *sm)
59 SheetObjectMod *sheet_object_mod;
60 DiaObjectType *ot;
62 sheet_object_mod = g_new(SheetObjectMod, 1);
63 sheet_object_mod->sheet_object = *so;
64 sheet_object_mod->mod = SHEET_OBJECT_MOD_NONE;
66 ot = object_get_type(so->object_type);
67 g_assert(ot);
68 if (ot->ops == ((DiaObjectType *)(custom_type_symbol))->ops)
69 sheet_object_mod->type = OBJECT_TYPE_SVG;
70 else
71 sheet_object_mod->type = OBJECT_TYPE_PROGRAMMED;
73 sm->sheet.objects = g_slist_append(sm->sheet.objects, sheet_object_mod);
75 return sheet_object_mod;
78 /* Given a Sheet, create a SheetMod wrapper for a list of SheetObjectMod's */
80 SheetMod *
81 sheets_append_sheet_mods(Sheet *sheet)
83 SheetMod *sheet_mod;
84 GSList *sheet_objects_list;
86 sheet_mod = g_new(SheetMod, 1);
87 sheet_mod->sheet = *sheet;
88 sheet_mod->type = SHEETMOD_TYPE_NORMAL;
89 sheet_mod->mod = SHEETMOD_MOD_NONE;
90 sheet_mod->sheet.objects = NULL;
92 for (sheet_objects_list = sheet->objects; sheet_objects_list;
93 sheet_objects_list = g_slist_next(sheet_objects_list))
94 sheets_append_sheet_object_mod(sheet_objects_list->data, sheet_mod);
96 sheets_mods_list = g_slist_append(sheets_mods_list, sheet_mod);
98 return sheet_mod;
101 static gint
102 menu_item_compare_labels(gconstpointer a, gconstpointer b)
104 GList *a_list;
105 gchar *label;
107 a_list = gtk_container_children(GTK_CONTAINER(GTK_MENU_ITEM(a)));
108 g_assert(g_list_length(a_list) == 1);
110 gtk_label_get(GTK_LABEL(a_list->data), &label);
111 g_list_free(a_list);
113 if (!strcmp(label, (gchar *)b))
114 return 0;
115 else
116 return 1;
119 void
120 sheets_optionmenu_create(GtkWidget *option_menu, GtkWidget *wrapbox,
121 gchar *sheet_name)
123 GtkWidget *optionmenu_menu;
124 GSList *sheets_list;
125 GList *menu_item_list;
127 /* Delete the contents, if any, of this optionemnu first */
129 optionmenu_menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(option_menu));
130 gtk_container_foreach(GTK_CONTAINER(optionmenu_menu),
131 (GtkCallback)gtk_widget_destroy, NULL);
133 if (!sheets_dialog_tooltips)
134 sheets_dialog_tooltips = gtk_tooltips_new();
136 for (sheets_list = sheets_mods_list; sheets_list;
137 sheets_list = g_slist_next(sheets_list))
139 SheetMod *sheet_mod;
140 GtkWidget *menu_item;
141 gchar *tip;
143 sheet_mod = sheets_list->data;
145 /* We don't display sheets which have been deleted prior to Apply */
147 if (sheet_mod->mod == SHEETMOD_MOD_DELETED)
148 continue;
151 menu_item = gtk_menu_item_new_with_label(gettext(sheet_mod->sheet.name));
153 gtk_menu_append(GTK_MENU(optionmenu_menu), menu_item);
155 if (sheet_mod->sheet.scope == SHEET_SCOPE_SYSTEM)
156 tip = g_strdup_printf(_("%s\nSystem sheet"), sheet_mod->sheet.description);
157 else
158 tip = g_strdup_printf(_("%s\nUser sheet"), sheet_mod->sheet.description);
160 gtk_tooltips_set_tip(GTK_TOOLTIPS(sheets_dialog_tooltips), menu_item, tip,
161 NULL);
162 g_free(tip);
165 gtk_widget_show(menu_item);
167 gtk_object_set_data(GTK_OBJECT(menu_item), "wrapbox", wrapbox);
169 g_signal_connect(GTK_OBJECT(menu_item), "activate",
170 G_CALLBACK(on_sheets_dialog_optionmenu_activate),
171 (gpointer)sheet_mod);
174 menu_item_list = gtk_container_children(GTK_CONTAINER(optionmenu_menu));
176 /* If we were passed a sheet_name, then make the optionmenu point to that
177 name after creation */
179 if (sheet_name)
181 gint index = 0;
182 GList *list;
184 list = g_list_find_custom(menu_item_list, sheet_name,
185 menu_item_compare_labels);
186 if (list)
187 index = g_list_position(menu_item_list, list);
188 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), index);
189 gtk_menu_item_activate(GTK_MENU_ITEM(g_list_nth_data(menu_item_list,
190 index)));
192 else
194 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), 0);
195 gtk_menu_item_activate(GTK_MENU_ITEM(menu_item_list->data));
198 g_list_free(menu_item_list);
201 gboolean
202 sheets_dialog_create(void)
204 GList *plugin_list;
205 GSList *sheets_list;
206 GtkWidget *option_menu;
207 GtkWidget *sw;
208 GtkWidget *wrapbox;
209 gchar *sheet_left;
210 gchar *sheet_right;
212 if (sheets_mods_list)
214 /* FIXME: not sure if I understood the data structure
215 but simply leaking isn't acceptable ... --hb
217 g_slist_foreach(sheets_mods_list, (GFunc)g_free, NULL);
218 g_slist_free(sheets_mods_list);
220 sheets_mods_list = NULL;
222 if (sheets_dialog == NULL)
224 sheets_dialog = create_sheets_main_dialog();
225 /* Make sure to null our pointer when destroyed */
226 g_signal_connect (GTK_OBJECT (sheets_dialog), "destroy",
227 G_CALLBACK (gtk_widget_destroyed),
228 &sheets_dialog);
229 g_signal_connect (GTK_OBJECT (sheets_dialog), "destroy",
230 G_CALLBACK (gtk_widget_destroyed),
231 &sheets_dialog_tooltips);
233 sheet_left = NULL;
234 sheet_right = NULL;
236 else
238 option_menu = lookup_widget(sheets_dialog, "optionmenu_left");
239 sheet_left = gtk_object_get_data(GTK_OBJECT(option_menu),
240 "active_sheet_name");
242 option_menu = lookup_widget(sheets_dialog, "optionmenu_right");
243 sheet_right = gtk_object_get_data(GTK_OBJECT(option_menu),
244 "active_sheet_name");
246 wrapbox = lookup_widget(sheets_dialog, "wrapbox_left");
247 gtk_widget_destroy(wrapbox);
249 wrapbox = lookup_widget(sheets_dialog, "wrapbox_right");
250 gtk_widget_destroy(wrapbox);
253 if (custom_type_symbol == NULL)
255 /* This little bit identifies a custom object symbol so we can tell the
256 difference later between a SVG shape and a Programmed shape */
258 custom_type_symbol = NULL;
259 for (plugin_list = dia_list_plugins(); plugin_list != NULL;
260 plugin_list = g_list_next(plugin_list))
262 PluginInfo *info = plugin_list->data;
264 custom_type_symbol = (gpointer)dia_plugin_get_symbol (info,
265 "custom_type");
266 if (custom_type_symbol)
267 break;
271 if (!custom_type_symbol)
273 message_warning (_("Can't get symbol 'custom_type' from any module.\n"
274 "Editing shapes is disabled."));
275 return FALSE;
278 for (sheets_list = get_sheets_list(); sheets_list;
279 sheets_list = g_slist_next(sheets_list))
280 sheets_append_sheet_mods(sheets_list->data);
282 sw = lookup_widget(sheets_dialog, "scrolledwindow_right");
283 wrapbox = gtk_hwrap_box_new(FALSE);
284 gtk_widget_ref(wrapbox);
285 gtk_object_set_data(GTK_OBJECT(sheets_dialog), "wrapbox_right", wrapbox);
286 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), wrapbox);
287 gtk_wrap_box_set_justify(GTK_WRAP_BOX(wrapbox), GTK_JUSTIFY_TOP);
288 gtk_wrap_box_set_line_justify(GTK_WRAP_BOX(wrapbox), GTK_JUSTIFY_LEFT);
289 gtk_widget_show(wrapbox);
290 gtk_object_set_data(GTK_OBJECT(wrapbox), "is_left", FALSE);
291 option_menu = lookup_widget(sheets_dialog, "optionmenu_right");
292 sheets_optionmenu_create(option_menu, wrapbox, sheet_right);
294 sw = lookup_widget(sheets_dialog, "scrolledwindow_left");
295 wrapbox = gtk_hwrap_box_new(FALSE);
296 gtk_widget_ref(wrapbox);
297 gtk_object_set_data(GTK_OBJECT(sheets_dialog), "wrapbox_left", wrapbox);
298 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), wrapbox);
299 gtk_wrap_box_set_justify(GTK_WRAP_BOX(wrapbox), GTK_JUSTIFY_TOP);
300 gtk_wrap_box_set_line_justify(GTK_WRAP_BOX(wrapbox), GTK_JUSTIFY_LEFT);
301 gtk_widget_show(wrapbox);
302 gtk_object_set_data(GTK_OBJECT(wrapbox), "is_left", (gpointer)TRUE);
303 option_menu = lookup_widget(sheets_dialog, "optionmenu_left");
304 sheets_optionmenu_create(option_menu, wrapbox, sheet_left);
306 return TRUE;
309 void
310 create_object_pixmap(SheetObject *so, GtkWidget *parent,
311 GdkPixmap **pixmap, GdkBitmap **mask)
313 GtkStyle *style;
315 g_assert(so);
316 g_assert(pixmap);
317 g_assert(mask);
319 style = gtk_widget_get_style(parent);
321 if (so->pixmap != NULL)
323 *pixmap =
324 gdk_pixmap_colormap_create_from_xpm_d(NULL,
325 gtk_widget_get_colormap(parent),
326 mask,
327 &style->bg[GTK_STATE_NORMAL],
328 so->pixmap);
330 else
332 if (so->pixmap_file != NULL)
334 GdkPixbuf *pixbuf;
335 GError *error = NULL;
337 pixbuf = gdk_pixbuf_new_from_file(so->pixmap_file, &error);
338 if (pixbuf != NULL)
340 gdk_pixbuf_render_pixmap_and_mask(pixbuf, pixmap, mask, 1.0);
341 gdk_pixbuf_unref(pixbuf);
342 } else {
343 message_warning ("%s", error->message);
344 g_error_free (error);
345 *pixmap = gdk_pixmap_colormap_create_from_xpm_d
346 (NULL,
347 gtk_widget_get_colormap(parent),
348 mask,
349 &style->bg[GTK_STATE_NORMAL],
350 missing);
353 else
355 *pixmap = NULL;
356 *mask = NULL;
361 GtkWidget*
362 lookup_widget (GtkWidget *widget,
363 const gchar *widget_name)
365 GtkWidget *parent, *found_widget;
367 for (;;)
369 if (GTK_IS_MENU (widget))
370 parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
371 else
372 parent = widget->parent;
373 if (parent == NULL)
374 break;
375 widget = parent;
378 found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget),
379 widget_name);
380 if (!found_widget)
381 g_warning (_("Widget not found: %s"), widget_name);
382 return found_widget;
385 #include "pixmaps/n_a.xpm"
386 #include "pixmaps/line_break.xpm"
388 /* This is only called by the code written by glade and at the moment
389 it is only used to create the static pixmap of the current sheet object. */
391 GtkWidget *
392 create_pixmap(GtkWidget *dialog, gchar *filename, gboolean arg3)
394 GdkPixmap *pixmap, *mask;
395 GtkWidget *button;
396 GtkWidget *wrapbox;
397 GList *button_list;
398 SheetObjectMod *som;
400 button = sheets_dialog_get_active_button(&wrapbox, &button_list);
401 som = gtk_object_get_data(GTK_OBJECT(button), "sheet_object_mod");
403 if (som)
404 create_object_pixmap(&som->sheet_object, wrapbox, &pixmap, &mask);
405 else
407 GtkStyle *style;
408 gchar **icon;
410 style = gtk_widget_get_style(wrapbox);
412 if ((gboolean)gtk_object_get_data(GTK_OBJECT(button), "is_hidden_button")
413 == TRUE)
414 icon = n_a_xpm;
415 else
416 icon = line_break_xpm;
418 pixmap =
419 gdk_pixmap_colormap_create_from_xpm_d(NULL,
420 gtk_widget_get_colormap(wrapbox),
421 &mask,
422 &style->bg[GTK_STATE_NORMAL],
423 icon);
426 return gtk_pixmap_new(pixmap, mask);
429 /* The menu calls us here, after we've been instantiated */
431 void
432 sheets_dialog_show_callback(gpointer data, guint action, GtkWidget *widget)
434 GtkWidget *wrapbox;
435 GtkWidget *option_menu;
437 if (!sheets_dialog)
438 sheets_dialog_create();
439 if (!sheets_dialog)
440 return;
442 wrapbox = gtk_object_get_data(GTK_OBJECT(sheets_dialog), "wrapbox_left");
443 option_menu = lookup_widget(sheets_dialog, "optionmenu_left");
444 sheets_optionmenu_create(option_menu, wrapbox, interface_current_sheet_name);
446 g_assert(GTK_IS_WIDGET(sheets_dialog));
447 gtk_widget_show(sheets_dialog);
450 gchar *
451 sheet_object_mod_get_type_string(SheetObjectMod *som)
453 switch (som->type)
455 case OBJECT_TYPE_SVG:
456 return _("SVG Shape");
457 case OBJECT_TYPE_PROGRAMMED:
458 return _("Programmed DiaObject");
459 default:
460 g_assert_not_reached();
461 return "";