offset fixes, admit to textline, proper updating of height/font at attr set,
[dia.git] / lib / propobject.c
blob1d8bda7e445ae5971378f20098d8edf447832b42
1 /* Dia -- a diagram creation/manipulation program
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 * Propobject.c: routines which deal with Dia Objects and affect their
10 * properties.
12 * Most of these routines used to exist in code before the restructuration.
13 * They've lost most of their meat, in favour for more modularity.
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
34 #include <string.h>
36 #include <glib.h>
37 #include "properties.h"
38 #include "propinternals.h"
39 #include "object.h"
41 const PropDescription *
42 object_get_prop_descriptions(const DiaObject *obj) {
43 const PropDescription *pdesc;
44 if (!obj->ops->describe_props) return NULL;
46 pdesc = obj->ops->describe_props((DiaObject *)obj); /* Yes... */
47 if (pdesc[0].quark != 0) return pdesc;
49 prop_desc_list_calculate_quarks((PropDescription *)pdesc); /* Yes again... */
50 return pdesc;
54 /* ------------------------------------------------------ */
55 /* Change management */
57 /* an ObjectChange structure for setting of properties */
58 typedef struct _ObjectPropChange ObjectPropChange;
59 struct _ObjectPropChange {
60 ObjectChange obj_change;
62 DiaObject *obj;
63 GPtrArray *saved_props;
66 static void
67 object_prop_change_apply_revert(ObjectPropChange *change, DiaObject *obj)
69 GPtrArray *old_props;
71 old_props = prop_list_copy_empty(change->saved_props);
73 if (change->obj->ops->get_props)
74 change->obj->ops->get_props(change->obj, old_props);
76 /* set saved property values */
77 if (change->obj->ops->set_props)
78 change->obj->ops->set_props(change->obj, change->saved_props);
80 /* move old props to saved properties */
81 prop_list_free(change->saved_props);
82 change->saved_props = old_props;
85 static void
86 object_prop_change_free(ObjectPropChange *change)
88 prop_list_free(change->saved_props);
91 ObjectChange *
92 object_apply_props(DiaObject *obj, GPtrArray *props)
94 ObjectPropChange *change;
95 GPtrArray *old_props;
97 change = g_new0(ObjectPropChange, 1);
99 change->obj_change.apply =
100 (ObjectChangeApplyFunc) object_prop_change_apply_revert;
101 change->obj_change.revert =
102 (ObjectChangeRevertFunc) object_prop_change_apply_revert;
103 change->obj_change.free =
104 (ObjectChangeFreeFunc) object_prop_change_free;
106 change->obj = obj;
108 /* create new properties structure with current values */
109 old_props = prop_list_copy_empty(props);
111 if (obj->ops->get_props)
112 obj->ops->get_props(obj, old_props);
114 /* set saved property values */
115 if (obj->ops->set_props)
116 obj->ops->set_props(obj, props);
118 change->saved_props = old_props;
120 return (ObjectChange *)change;
124 /* Get/Set routines */
126 gboolean
127 object_get_props_from_offsets(DiaObject *obj, PropOffset *offsets,
128 GPtrArray *props)
130 prop_offset_list_calculate_quarks(offsets);
131 do_get_props_from_offsets(obj,props,offsets);
133 return TRUE;
136 gboolean
137 object_set_props_from_offsets(DiaObject *obj, PropOffset *offsets,
138 GPtrArray *props)
140 prop_offset_list_calculate_quarks(offsets);
141 do_set_props_from_offsets(obj,props,offsets);
143 return TRUE;
147 WIDGET *
148 object_create_props_dialog(DiaObject *obj, gboolean is_default)
150 return prop_dialog_new(obj, is_default)->widget;
154 ObjectChange *
155 object_apply_props_from_dialog(DiaObject *obj, WIDGET *dialog_widget)
157 PropDialog *dialog = prop_dialog_from_widget(dialog_widget);
159 prop_get_data_from_widgets(dialog);
160 return object_apply_props(obj, dialog->props);
164 gboolean
165 object_complies_with_stdprop(const DiaObject *obj)
167 if (obj->ops->set_props == NULL) {
168 g_warning("No set_props !");
169 return FALSE;
171 if (obj->ops->get_props == NULL) {
172 g_warning("No get_props !");
173 return FALSE;
175 if (obj->ops->describe_props == NULL) {
176 g_warning("No describe_props !");
177 return FALSE;
179 if (object_get_prop_descriptions(obj) == NULL) {
180 g_warning("No properties !");
181 return FALSE;
183 return TRUE;
186 static gboolean
187 pdtpp_do_save_no_standard_default (const PropDescription *pdesc)
189 return pdtpp_do_save_no_standard(pdesc) && pdtpp_defaults (pdesc);
192 void
193 object_copy_props(DiaObject *dest, const DiaObject *src, gboolean is_default)
195 GPtrArray *props;
197 g_return_if_fail(src != NULL);
198 g_return_if_fail(dest != NULL);
199 g_return_if_fail(strcmp(src->type->name,dest->type->name)==0);
200 g_return_if_fail(src->ops == dest->ops);
201 g_return_if_fail(object_complies_with_stdprop(src));
202 g_return_if_fail(object_complies_with_stdprop(dest));
204 props = prop_list_from_descs(object_get_prop_descriptions(src),
205 (is_default?pdtpp_do_save_no_standard_default:
206 pdtpp_do_save));
208 src->ops->get_props((DiaObject *)src, props); /* FIXME: really should make
209 get_props' first argument
210 a (const DiaObject *) */
211 dest->ops->set_props(dest, props);
213 prop_list_free(props);
216 void
217 object_load_props(DiaObject *obj, ObjectNode obj_node)
219 GPtrArray *props;
220 GError *err = NULL;
222 g_return_if_fail(obj != NULL);
223 g_return_if_fail(obj_node != NULL);
224 g_return_if_fail(object_complies_with_stdprop(obj));
226 props = prop_list_from_descs(object_get_prop_descriptions(obj),
227 pdtpp_do_load);
229 if (!prop_list_load(props,obj_node, &err)) {
230 g_warning ("%s: %s", obj->type->name, err->message);
231 g_error_free(err);
234 obj->ops->set_props(obj, props);
235 prop_list_free(props);
238 void
239 object_save_props(DiaObject *obj, ObjectNode obj_node)
241 GPtrArray *props;
243 g_return_if_fail(obj != NULL);
244 g_return_if_fail(obj_node != NULL);
245 g_return_if_fail(object_complies_with_stdprop(obj));
247 props = prop_list_from_descs(object_get_prop_descriptions(obj),
248 pdtpp_do_save);
250 obj->ops->get_props(obj, props);
251 prop_list_save(props,obj_node);
252 prop_list_free(props);
255 Property *
256 object_prop_by_name_type(DiaObject *obj, const char *name, const char *type)
258 const PropDescription *pdesc;
259 GQuark name_quark = g_quark_from_string(name);
261 if (!object_complies_with_stdprop(obj)) return NULL;
263 for (pdesc = object_get_prop_descriptions(obj);
264 pdesc->name != NULL;
265 pdesc++) {
266 if ((pdesc->quark == name_quark)) {
267 Property *prop;
268 static GPtrArray *plist = NULL;
270 if (type && (0 != strcmp(pdesc->type,type))) continue;
272 if (!plist) {
273 plist = g_ptr_array_new();
274 g_ptr_array_set_size(plist,1);
276 prop = pdesc->ops->new_prop(pdesc,pdtpp_from_object);
277 g_ptr_array_index(plist,0) = prop;
278 obj->ops->get_props(obj,plist);
279 return prop;
282 return NULL;
285 Property *
286 object_prop_by_name(DiaObject *obj, const char *name)
288 return object_prop_by_name_type(obj,name,NULL);