Patch to add Sheets & Objects Dialog from M. C. Nelson
[dia.git] / app / sheets.c
blob897b0b7e8c12640fbd864eb6af9e813dddcfb035
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 #ifdef GNOME
24 #include <gnome.h>
25 #else
26 #include <gtk/gtk.h>
27 #endif
29 #include <gdk-pixbuf/gdk-pixbuf.h>
30 #include <gmodule.h>
32 #include "../lib/plug-ins.h"
33 #include "../lib/sheet.h"
35 #include "interface.h"
36 #include "sheets.h"
37 #include "sheets_dialog.h"
38 #include "gtkhwrapbox.h"
40 GtkWidget *sheets_dialog = NULL;
41 GSList *sheets_mods_list = NULL;
42 GtkTooltips *sheets_dialog_tooltips = NULL;
43 static gpointer custom_type_symbol;
45 /* Given a SheetObject and a SheetMod, create a new SheetObjectMod
46 and hook it into the 'objects' list in the SheetMod->sheet
48 NOTE: that the objects structure points to SheetObjectMod's and
49 *not* SheetObject's */
51 SheetObjectMod *
52 sheets_append_sheet_object_mod(SheetObject *so, SheetMod *sm)
54 SheetObjectMod *sheet_object_mod;
55 ObjectType *ot;
57 sheet_object_mod = g_new(SheetObjectMod, 1);
58 sheet_object_mod->sheet_object = *so;
59 sheet_object_mod->mod = SHEET_OBJECT_MOD_NONE;
61 ot = object_get_type(so->object_type);
62 g_assert(ot);
63 if (ot->ops == ((ObjectType *)(custom_type_symbol))->ops)
64 sheet_object_mod->type = OBJECT_TYPE_SVG;
65 else
66 sheet_object_mod->type = OBJECT_TYPE_PROGRAMMED;
68 sm->sheet.objects = g_slist_append(sm->sheet.objects, sheet_object_mod);
70 return sheet_object_mod;
73 /* Given a Sheet, create a SheetMod wrapper for a list of SheetObjectMod's */
75 SheetMod *
76 sheets_append_sheet_mods(Sheet *sheet)
78 SheetMod *sheet_mod;
79 GSList *sheet_objects_list;
81 sheet_mod = g_new(SheetMod, 1);
82 sheet_mod->sheet = *sheet;
83 sheet_mod->type = SHEETMOD_TYPE_NORMAL;
84 sheet_mod->mod = SHEETMOD_MOD_NONE;
85 sheet_mod->sheet.objects = NULL;
87 for (sheet_objects_list = sheet->objects; sheet_objects_list;
88 sheet_objects_list = g_slist_next(sheet_objects_list))
89 sheets_append_sheet_object_mod(sheet_objects_list->data, sheet_mod);
91 sheets_mods_list = g_slist_append(sheets_mods_list, sheet_mod);
93 return sheet_mod;
96 static gint
97 menu_item_compare_labels(gconstpointer a, gconstpointer b)
99 GList *a_list;
100 gchar *label;
102 a_list = gtk_container_children(GTK_CONTAINER(GTK_MENU_ITEM(a)));
103 g_assert(g_list_length(a_list) == 1);
105 gtk_label_get(GTK_LABEL(a_list->data), &label);
106 g_list_free(a_list);
108 if (!strcmp(label, (gchar *)b))
109 return 0;
110 else
111 return 1;
114 void
115 sheets_optionmenu_create(GtkWidget *option_menu, GtkWidget *wrapbox,
116 gchar *sheet_name)
118 GtkWidget *optionmenu_menu;
119 GSList *sheets_list;
120 GList *menu_item_list;
122 /* Delete the contents, if any, of this optionemnu first */
124 optionmenu_menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(option_menu));
125 gtk_container_foreach(GTK_CONTAINER(optionmenu_menu),
126 (GtkCallback)gtk_widget_destroy, NULL);
128 if (!sheets_dialog_tooltips)
129 sheets_dialog_tooltips = gtk_tooltips_new();
131 for (sheets_list = sheets_mods_list; sheets_list;
132 sheets_list = g_slist_next(sheets_list))
134 SheetMod *sheet_mod;
135 GtkWidget *menu_item;
136 gchar *tip;
138 sheet_mod = sheets_list->data;
140 /* We don't display sheets which have been deleted prior to Apply */
142 if (sheet_mod->mod == SHEETMOD_MOD_DELETED)
143 continue;
145 menu_item = gtk_menu_item_new_with_label(sheet_mod->sheet.name);
146 gtk_menu_append(GTK_MENU(optionmenu_menu), menu_item);
148 tip = g_strdup_printf("%s\n%s", sheet_mod->sheet.description,
149 sheet_mod->sheet.scope == SHEET_SCOPE_SYSTEM
150 ? "System sheet" : "User sheet");
151 gtk_tooltips_set_tip(GTK_TOOLTIPS(sheets_dialog_tooltips), menu_item, tip,
152 NULL);
153 g_free(tip);
155 gtk_widget_show(menu_item);
157 gtk_object_set_data(GTK_OBJECT(menu_item), "wrapbox", wrapbox);
159 gtk_signal_connect(GTK_OBJECT(menu_item), "activate",
160 GTK_SIGNAL_FUNC(on_sheets_dialog_optionmenu_activate),
161 (gpointer)sheet_mod);
164 menu_item_list = gtk_container_children(GTK_CONTAINER(optionmenu_menu));
166 /* If we were passed a sheet_name, then make the optionmenu point to that
167 name after creation */
169 if (sheet_name)
171 gint index;
172 GList *list;
174 list = g_list_find_custom(menu_item_list, sheet_name,
175 menu_item_compare_labels);
176 g_assert(list);
178 index = g_list_position(menu_item_list, list);
179 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), index);
180 gtk_menu_item_activate(GTK_MENU_ITEM(g_list_nth_data(menu_item_list,
181 index)));
183 else
185 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), 0);
186 gtk_menu_item_activate(GTK_MENU_ITEM(menu_item_list->data));
189 g_list_free(menu_item_list);
192 void
193 sheets_dialog_create(void)
195 GList *plugin_list;
196 GSList *sheets_list;
197 GtkWidget *option_menu;
198 GtkWidget *sw;
199 GtkWidget *wrapbox;
200 gchar *sheet_left;
201 gchar *sheet_right;
203 sheets_mods_list = NULL; /* This is a leak, but it is better
204 than the alternative :-) */
205 if (!GTK_IS_WIDGET(sheets_dialog))
207 sheets_dialog = create_sheets_main_dialog();
209 /* This little bit identifies a custom object symbol so we can tell the
210 difference later between a SVG shape and a Programmed shape */
212 custom_type_symbol = NULL;
213 for (plugin_list = dia_list_plugins(); plugin_list != NULL;
214 plugin_list = g_list_next(plugin_list))
216 GModule *module = ((PluginInfo *)(plugin_list->data))->module;
218 if (module == NULL)
219 continue;
221 if (g_module_symbol(module, "custom_type", &custom_type_symbol) == TRUE)
222 break;
224 g_assert(custom_type_symbol);
226 sheet_left = NULL;
227 sheet_right = NULL;
229 else
231 option_menu = lookup_widget(sheets_dialog, "optionmenu_left");
232 sheet_left = gtk_object_get_data(GTK_OBJECT(option_menu),
233 "active_sheet_name");
235 option_menu = lookup_widget(sheets_dialog, "optionmenu_right");
236 sheet_right = gtk_object_get_data(GTK_OBJECT(option_menu),
237 "active_sheet_name");
239 wrapbox = lookup_widget(sheets_dialog, "wrapbox_left");
240 gtk_widget_destroy(wrapbox);
242 wrapbox = lookup_widget(sheets_dialog, "wrapbox_right");
243 gtk_widget_destroy(wrapbox);
247 for (sheets_list = get_sheets_list(); sheets_list;
248 sheets_list = g_slist_next(sheets_list))
249 sheets_append_sheet_mods(sheets_list->data);
251 sw = lookup_widget(sheets_dialog, "scrolledwindow_right");
252 wrapbox = gtk_hwrap_box_new(FALSE);
253 gtk_widget_ref(wrapbox);
254 gtk_object_set_data(GTK_OBJECT(sheets_dialog), "wrapbox_right", wrapbox);
255 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), wrapbox);
256 gtk_wrap_box_set_justify(GTK_WRAP_BOX(wrapbox), GTK_JUSTIFY_TOP);
257 gtk_wrap_box_set_line_justify(GTK_WRAP_BOX(wrapbox), GTK_JUSTIFY_LEFT);
258 gtk_widget_show(wrapbox);
259 gtk_object_set_data(GTK_OBJECT(wrapbox), "is_left", FALSE);
260 option_menu = lookup_widget(sheets_dialog, "optionmenu_right");
261 sheets_optionmenu_create(option_menu, wrapbox, sheet_right);
263 sw = lookup_widget(sheets_dialog, "scrolledwindow_left");
264 wrapbox = gtk_hwrap_box_new(FALSE);
265 gtk_widget_ref(wrapbox);
266 gtk_object_set_data(GTK_OBJECT(sheets_dialog), "wrapbox_left", wrapbox);
267 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), wrapbox);
268 gtk_wrap_box_set_justify(GTK_WRAP_BOX(wrapbox), GTK_JUSTIFY_TOP);
269 gtk_wrap_box_set_line_justify(GTK_WRAP_BOX(wrapbox), GTK_JUSTIFY_LEFT);
270 gtk_widget_show(wrapbox);
271 gtk_object_set_data(GTK_OBJECT(wrapbox), "is_left", (gpointer)TRUE);
272 option_menu = lookup_widget(sheets_dialog, "optionmenu_left");
273 sheets_optionmenu_create(option_menu, wrapbox, sheet_left);
275 return;
278 void
279 create_object_pixmap(SheetObject *so, GtkWidget *parent,
280 GdkPixmap **pixmap, GdkBitmap **mask)
282 GtkStyle *style;
284 g_assert(so);
285 g_assert(pixmap);
286 g_assert(mask);
288 style = gtk_widget_get_style(parent);
290 if (so->pixmap != NULL)
292 *pixmap =
293 gdk_pixmap_colormap_create_from_xpm_d(NULL,
294 gtk_widget_get_colormap(parent),
295 mask,
296 &style->bg[GTK_STATE_NORMAL],
297 so->pixmap);
299 else
301 if (so->pixmap_file != NULL)
303 GdkPixbuf *pixbuf;
305 pixbuf = gdk_pixbuf_new_from_file(so->pixmap_file);
306 if (pixbuf != NULL)
308 gdk_pixbuf_render_pixmap_and_mask(pixbuf, pixmap, mask, 1.0);
309 gdk_pixbuf_unref(pixbuf);
312 else
314 *pixmap = NULL;
315 *mask = NULL;
320 GtkWidget*
321 lookup_widget (GtkWidget *widget,
322 const gchar *widget_name)
324 GtkWidget *parent, *found_widget;
326 for (;;)
328 if (GTK_IS_MENU (widget))
329 parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
330 else
331 parent = widget->parent;
332 if (parent == NULL)
333 break;
334 widget = parent;
337 found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget),
338 widget_name);
339 if (!found_widget)
340 g_warning ("Widget not found: %s", widget_name);
341 return found_widget;
344 #include "pixmaps/n_a.xpm"
345 #include "pixmaps/line_break.xpm"
347 /* This is only called by the code written by glade and at the moment
348 it is only used to create the static pixmap of the current sheet object. */
350 GtkWidget *
351 create_pixmap(GtkWidget *dialog, gchar *filename, gboolean arg3)
353 GdkPixmap *pixmap, *mask;
354 GtkWidget *button;
355 GtkWidget *wrapbox;
356 GList *button_list;
357 SheetObjectMod *som;
359 button = sheets_dialog_get_active_button(&wrapbox, &button_list);
360 som = gtk_object_get_data(GTK_OBJECT(button), "sheet_object_mod");
362 if (som)
363 create_object_pixmap(&som->sheet_object, wrapbox, &pixmap, &mask);
364 else
366 GtkStyle *style;
367 gchar **icon;
369 style = gtk_widget_get_style(wrapbox);
371 if ((gboolean)gtk_object_get_data(GTK_OBJECT(button), "is_hidden_button")
372 == TRUE)
373 icon = n_a_xpm;
374 else
375 icon = line_break_xpm;
377 pixmap =
378 gdk_pixmap_colormap_create_from_xpm_d(NULL,
379 gtk_widget_get_colormap(wrapbox),
380 &mask,
381 &style->bg[GTK_STATE_NORMAL],
382 icon);
385 return gtk_pixmap_new(pixmap, mask);
388 /* The menu calls us here, after we've been instantiated */
390 void
391 sheets_dialog_show_callback(gpointer data, guint action, GtkWidget *widget)
393 GtkWidget *wrapbox;
394 GtkWidget *option_menu;
396 wrapbox = gtk_object_get_data(GTK_OBJECT(sheets_dialog), "wrapbox_left");
397 option_menu = lookup_widget(sheets_dialog, "optionmenu_left");
398 sheets_optionmenu_create(option_menu, wrapbox, interface_current_sheet_name);
400 g_assert(GTK_IS_WIDGET(sheets_dialog));
401 gtk_widget_show(sheets_dialog);
404 gchar *
405 sheet_object_mod_get_type_string(SheetObjectMod *som)
407 switch (som->type)
409 case OBJECT_TYPE_SVG:
410 return "SVG Shape";
411 case OBJECT_TYPE_PROGRAMMED:
412 return "Programmed Object";
413 default:
414 g_assert_not_reached();
415 return FALSE; /* shut gcc up */