* added GDK_PIXBUF_LIBS in order to create pixbuf.dll
[dia.git] / lib / propdialogs.c
blobf176b0c4504561a8f0534428548d051b55847438
1 /* Dia -- a diagram creation/manipulation program -*- c -*-
2 * Copyright (C) 1998 Alexander Larsson
4 * Property system for dia objects/shapes.
5 * Copyright (C) 2000 James Henstridge
6 * Copyright (C) 2001 Cyrille Chepelov
7 * Major restructuration done in August 2001 by C. Chepelov
9 * Routines for the construction of a property dialog.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
29 #include <string.h>
31 #undef GTK_DISABLE_DEPRECATED /* gtk_signal_connect, ... */
32 #include <gtk/gtk.h>
33 #define WIDGET GtkWidget
34 #include "widgets.h"
35 #include "properties.h"
36 #include "propinternals.h"
37 #include "object.h"
39 const gchar *prop_dialogdata_key = "object-props:dialogdata";
41 static void prop_dialog_signal_destroy(GtkWidget *dialog_widget);
42 static void prop_dialog_fill(PropDialog *dialog, Object *obj, gboolean is_default);
44 PropDialog *
45 prop_dialog_new(Object *obj, gboolean is_default)
47 PropDialog *dialog = g_new0(PropDialog,1);
48 dialog->props = NULL;
49 dialog->widget = gtk_vbox_new(FALSE,1);
50 dialog->prop_widgets = g_array_new(FALSE,TRUE,sizeof(PropWidgetAssoc));
51 dialog->obj_copy = NULL;
52 dialog->curtable = NULL;
53 dialog->containers = g_ptr_array_new();
55 prop_dialog_container_push(dialog,dialog->widget);
57 gtk_object_set_data(GTK_OBJECT(dialog->widget), prop_dialogdata_key, dialog);
58 gtk_signal_connect(GTK_OBJECT(dialog->widget), "destroy",
59 GTK_SIGNAL_FUNC(prop_dialog_signal_destroy), NULL);
61 prop_dialog_fill(dialog,obj,is_default);
63 return dialog;
66 void
67 prop_dialog_destroy(PropDialog *dialog)
69 if (dialog->props) prop_list_free(dialog->props);
70 g_array_free(dialog->prop_widgets,TRUE);
71 g_ptr_array_free(dialog->containers,TRUE);
72 if (dialog->obj_copy) dialog->obj_copy->ops->destroy(dialog->obj_copy);
73 g_free(dialog);
76 PropDialog *
77 prop_dialog_from_widget(GtkWidget *dialog_widget)
79 return gtk_object_get_data(GTK_OBJECT(dialog_widget),
80 prop_dialogdata_key);
83 static void
84 prop_dialog_signal_destroy(GtkWidget *dialog_widget)
86 prop_dialog_destroy(prop_dialog_from_widget(dialog_widget));
89 WIDGET *
90 prop_dialog_get_widget(const PropDialog *dialog)
92 return dialog->widget;
95 void
96 prop_dialog_add_raw(PropDialog *dialog, GtkWidget *widget)
98 dialog->curtable = NULL;
99 if (!widget) return;
100 gtk_container_add(GTK_CONTAINER(dialog->lastcont),widget);
103 void
104 prop_dialog_add_raw_with_flags(PropDialog *dialog, GtkWidget *widget,
105 gboolean expand, gboolean fill)
107 g_return_if_fail(GTK_IS_BOX(dialog->lastcont));
109 dialog->curtable = NULL;
110 if (!widget) return;
111 gtk_box_pack_start(GTK_BOX(dialog->lastcont),widget, expand, fill, 0);
114 static void
115 prop_dialog_make_curtable(PropDialog *dialog)
117 GtkWidget *table = gtk_table_new(1,2,FALSE);
118 gtk_table_set_row_spacings(GTK_TABLE(table), 2);
119 gtk_table_set_col_spacings(GTK_TABLE(table), 5);
120 gtk_widget_show(table);
121 prop_dialog_add_raw(dialog,table);
123 dialog->currow = 0;
124 dialog->curtable = table;
127 static void
128 prop_dialog_add_widget(PropDialog *dialog, GtkWidget *label, GtkWidget *widget)
130 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
132 if (!dialog->curtable) prop_dialog_make_curtable(dialog);
133 gtk_table_attach(GTK_TABLE(dialog->curtable),label,
134 0,1,
135 dialog->currow, dialog->currow+1,
136 GTK_FILL, GTK_FILL|GTK_EXPAND,
137 0,0);
138 gtk_table_attach(GTK_TABLE(dialog->curtable),widget,
139 1,2,
140 dialog->currow, dialog->currow+1,
141 GTK_FILL, GTK_FILL|GTK_EXPAND,
142 0,0);
143 gtk_widget_show(label);
144 gtk_widget_show(widget);
145 dialog->currow++;
148 /* Register a new container widget (which won't be automatically added) */
149 void
150 prop_dialog_container_push(PropDialog *dialog, GtkWidget *container)
152 g_ptr_array_add(dialog->containers,container);
153 dialog->lastcont = container;
154 dialog->curtable = NULL;
157 /* De-register the last container of the stack. */
158 GtkWidget *
159 prop_dialog_container_pop(PropDialog *dialog)
161 GtkWidget *res = g_ptr_array_remove_index(dialog->containers,
162 dialog->containers->len-1);
163 dialog->lastcont = g_ptr_array_index(dialog->containers,
164 dialog->containers->len-1);
165 dialog->curtable = NULL;
167 return res;
170 static void
171 property_signal_handler(GtkObject *obj,
172 gpointer func_data)
174 PropEventData *ped = (PropEventData *)func_data;
175 if (ped) {
176 PropDialog *dialog = ped->dialog;
177 Property *prop = ped->self;
178 Object *obj = dialog->obj_copy;
179 int j;
181 g_assert(prop->event_handler);
182 g_assert(obj);
183 g_assert(object_complies_with_stdprop(obj));
184 g_assert(obj->ops->set_props);
185 g_assert(obj->ops->get_props);
187 /* g_message("Received a signal for object %s from property %s",
188 obj->type->name,prop->name); */
190 /* obj is a scratch object ; we can do what we want with it. */
191 prop_get_data_from_widgets(dialog);
193 obj->ops->set_props(obj,dialog->props);
194 prop->event_handler(obj,prop);
195 obj->ops->get_props(obj,dialog->props);
197 for (j = 0; j < dialog->prop_widgets->len; j++) {
198 PropWidgetAssoc *pwa =
199 &g_array_index(dialog->prop_widgets,PropWidgetAssoc,j);
201 g_message("going to reset widget %p for prop %s/%s "
202 "[in response to event on %s/%s]",
203 pwa->widget,pwa->prop->type,pwa->prop->name,
204 prop->type,prop->name); */
205 pwa->prop->ops->reset_widget(pwa->prop,pwa->widget);
207 } else {
208 g_assert_not_reached();
212 void
213 prophandler_connect(const Property *prop,
214 GtkObject *object,
215 const gchar *signal)
217 Object *obj = prop->self.dialog->obj_copy;
219 if (!prop->event_handler) return;
220 if (0==strcmp(signal,"FIXME")) {
221 g_warning("signal type unknown for this kind of property (name is %s), \n"
222 "handler ignored.",prop->name);
223 return;
225 if ((!obj->ops->set_props) || (!obj->ops->get_props)) {
226 g_warning("object has no [sg]et_props() routine(s).\n"
227 "event handler for property %s ignored.",
228 prop->name);
229 return;
232 /* g_message("connected signal %s to property %s",signal,prop->name); */
234 gtk_signal_connect(object,
235 signal,
236 GTK_SIGNAL_FUNC(property_signal_handler),
237 (gpointer)(&prop->self));
240 void
241 prop_dialog_add_property(PropDialog *dialog, Property *prop)
243 GtkWidget *widget = NULL;
244 PropWidgetAssoc pwa;
245 GtkWidget *label;
247 if ((prop->event_handler) && (!dialog->obj_copy))
248 dialog->obj_copy = dialog->orig_obj->ops->copy(dialog->orig_obj);
250 prop->self.dialog = dialog;
251 prop->self.self = prop;
252 prop->self.my_index = dialog->prop_widgets->len;
254 if (prop->ops->get_widget) widget = prop->ops->get_widget(prop,dialog);
255 if (!widget) return; /* either property has no widget or it's a container */
257 prop->self.widget = widget;
258 if (prop->ops->reset_widget) prop->ops->reset_widget(prop,widget);
260 pwa.prop = prop;
261 pwa.widget = widget;
262 g_array_append_val(dialog->prop_widgets,pwa);
264 label = gtk_label_new(_(prop->descr->description));
265 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
267 prop_dialog_add_widget(dialog, label, widget);
270 static void
271 prop_dialog_add_properties(PropDialog *dialog, GPtrArray *props)
273 guint i;
275 for (i = 0; i < props->len; i++) {
276 Property *prop = (Property*)g_ptr_array_index(props,i);
277 prop_dialog_add_property(dialog, prop);
281 void
282 prop_get_data_from_widgets(PropDialog *dialog)
284 guint i;
285 for (i = 0; i < dialog->prop_widgets->len; i++) {
286 PropWidgetAssoc *pwa = &g_array_index(dialog->prop_widgets,
287 PropWidgetAssoc,i);
288 pwa->prop->ops->set_from_widget(pwa->prop,pwa->widget);
292 extern gboolean pdtpp_is_visible_no_standard(const PropDescription *pdesc);
293 static void
294 prop_dialog_fill(PropDialog *dialog, Object *obj, gboolean is_default) {
295 const PropDescription *pdesc;
296 GPtrArray *props;
298 g_return_if_fail(object_complies_with_stdprop(obj));
300 dialog->orig_obj = obj;
302 pdesc = object_get_prop_descriptions(obj);
303 if (!pdesc) return;
305 if (is_default)
306 props = prop_list_from_descs(pdesc,pdtpp_is_visible_no_standard);
307 else
308 props = prop_list_from_descs(pdesc,pdtpp_is_visible);
310 if (!props) return;
312 dialog->props = props;
313 obj->ops->get_props(obj,props);
315 prop_dialog_add_properties(dialog, props);