2006-12-03 Dimitris Glezos <dimitris@glezos.com>
[dia.git] / lib / prop_sdarray.c
blob5c1962fefba1d11297eb4ea5734dd70e638ce473
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 * Property types for static and dynamic arrays.
10 * These arrays are simply arrays of records whose structures are themselves
11 * described by property descriptors.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
31 #include <gtk/gtk.h>
32 #define WIDGET GtkWidget
33 #include "widgets.h"
34 #include "properties.h"
35 #include "propinternals.h"
37 /******************************************/
38 /* The SARRAY and DARRAY property types. */
39 /******************************************/
41 static ArrayProperty *
42 arrayprop_new(const PropDescription *pdesc, PropDescToPropPredicate reason)
44 ArrayProperty *prop = g_new0(ArrayProperty,1);
45 const PropDescCommonArrayExtra *extra = pdesc->extra_data;
47 initialize_property(&prop->common, pdesc, reason);
48 prop->ex_props = prop_list_from_descs(extra->record,reason);
49 prop->records = g_ptr_array_new();
50 return prop;
53 static void
54 arrayprop_freerecords(ArrayProperty *prop) /* but not the array itself. */
56 guint i;
58 for (i=0; i < prop->records->len; i++)
59 prop_list_free(g_ptr_array_index(prop->records,i));
62 static void
63 arrayprop_free(ArrayProperty *prop)
65 arrayprop_freerecords(prop);
66 g_ptr_array_free(prop->records,TRUE);
67 g_free(prop);
70 static ArrayProperty *
71 arrayprop_copy(ArrayProperty *src)
73 ArrayProperty *prop =
74 (ArrayProperty *)src->common.ops->new_prop(src->common.descr,
75 src->common.reason);
76 guint i;
77 copy_init_property(&prop->common,&src->common);
78 prop->ex_props = prop_list_copy(src->ex_props);
79 prop->records = g_ptr_array_new();
80 for (i = 0; i < src->records->len; i++) {
81 g_ptr_array_add(prop->records,
82 prop_list_copy(g_ptr_array_index(src->records,i)));
84 return prop;
87 static void
88 arrayprop_load(ArrayProperty *prop, AttributeNode attr, DataNode data)
90 const PropDescCommonArrayExtra *extra = prop->common.descr->extra_data;
91 DataNode composite;
92 GError *err = NULL;
94 arrayprop_freerecords(prop);
95 g_ptr_array_set_size(prop->records,0);
97 for (composite = data;
98 composite != NULL;
99 composite = data_next(composite)) {
100 GPtrArray *record = prop_list_from_descs(extra->record,
101 prop->common.reason);
102 if (!prop_list_load(record,composite, &err)) {
103 g_warning ("%s:%s", prop->common.name, err->message);
104 g_error_free (err);
105 err = NULL;
107 g_ptr_array_add(prop->records,record);
111 static void
112 arrayprop_save(ArrayProperty *prop, AttributeNode attr)
114 int i;
115 const PropDescCommonArrayExtra *extra = prop->common.descr->extra_data;
117 for (i = 0; i < prop->records->len; i++) {
118 prop_list_save(g_ptr_array_index(prop->records,i),
119 data_add_composite(attr,extra->composite_type));
123 static void
124 sarrayprop_get_from_offset(ArrayProperty *prop,
125 void *base, guint offset, guint offset2)
127 const PropDescSArrayExtra *extra = prop->common.descr->extra_data;
128 PropOffset *suboffsets = extra->common.offsets;
129 guint i;
131 prop_offset_list_calculate_quarks(suboffsets);
133 arrayprop_freerecords(prop);
134 g_ptr_array_set_size(prop->records,extra->array_len);
136 for (i=0; i < prop->records->len; i++) {
137 void *rec_in_obj = &struct_member(base,
138 offset + (i * extra->element_size),
139 char);
140 GPtrArray *subprops = prop_list_copy(prop->ex_props);
142 do_get_props_from_offsets(rec_in_obj,subprops,suboffsets);
144 g_ptr_array_index(prop->records,i) = subprops;
148 static void
149 sarrayprop_set_from_offset(ArrayProperty *prop,
150 void *base, guint offset, guint offset2)
152 const PropDescSArrayExtra *extra = prop->common.descr->extra_data;
153 PropOffset *suboffsets = extra->common.offsets;
154 guint i;
156 g_assert(prop->records->len == extra->array_len);
158 prop_offset_list_calculate_quarks(suboffsets);
160 for (i=0; i < prop->records->len; i++) {
161 void *rec_in_obj = &struct_member(base,
162 offset + (i * extra->element_size),
163 char);
164 GPtrArray *subprops = g_ptr_array_index(prop->records,i);
166 do_set_props_from_offsets(rec_in_obj,subprops,suboffsets);
170 static void
171 darrayprop_get_from_offset(ArrayProperty *prop,
172 void *base, guint offset, guint offset2)
174 /* This sucks. We do almost exactly like in sarrayprop_get_from_offset(). */
175 const PropDescSArrayExtra *extra = prop->common.descr->extra_data;
176 PropOffset *suboffsets = extra->common.offsets;
177 guint i;
178 GList *obj_rec = struct_member(base,offset,GList *);
180 prop_offset_list_calculate_quarks(suboffsets);
182 arrayprop_freerecords(prop);
183 g_ptr_array_set_size(prop->records,0);
185 for (obj_rec = g_list_first(obj_rec), i = 0;
186 obj_rec != NULL;
187 obj_rec = g_list_next(obj_rec), i++) {
188 void *rec_in_obj = obj_rec->data;
189 GPtrArray *subprops = prop_list_copy(prop->ex_props);
191 do_get_props_from_offsets(rec_in_obj,subprops,suboffsets);
193 g_ptr_array_add(prop->records,subprops);
197 static GList *
198 darrayprop_adjust_object_records(ArrayProperty *prop,
199 const PropDescDArrayExtra *extra,
200 GList *obj_rec) {
201 guint list_len = g_list_length(obj_rec);
203 while (list_len > prop->records->len) {
204 gpointer rec = obj_rec->data;
205 obj_rec = g_list_remove(obj_rec,rec);
206 extra->freerec(rec);
207 list_len--;
209 while (list_len < prop->records->len) {
210 obj_rec = g_list_append(obj_rec,extra->newrec());
211 list_len++;
213 return obj_rec;
216 static void
217 darrayprop_set_from_offset(ArrayProperty *prop,
218 void *base, guint offset, guint offset2)
220 /* This sucks. We do almost exactly like in darrayprop_set_from_offset(). */
221 const PropDescDArrayExtra *extra = prop->common.descr->extra_data;
222 PropOffset *suboffsets = extra->common.offsets;
223 guint i;
224 GList *obj_rec = struct_member(base,offset,GList *);
226 prop_offset_list_calculate_quarks(suboffsets);
228 obj_rec = darrayprop_adjust_object_records(prop,extra,obj_rec);
229 struct_member(base,offset,GList *) = obj_rec;
231 for (obj_rec = g_list_first(obj_rec), i = 0;
232 obj_rec != NULL;
233 obj_rec = g_list_next(obj_rec), i++) {
234 void *rec_in_obj = obj_rec->data;
235 GPtrArray *subprops = g_ptr_array_index(prop->records,i);
237 do_set_props_from_offsets(rec_in_obj,subprops,suboffsets);
241 static gboolean
242 arrayprop_can_merge(const PropDescription *pd1, const PropDescription *pd2)
244 if (pd1->extra_data != pd2->extra_data) return FALSE;
245 return TRUE;
248 static const PropertyOps sarrayprop_ops = {
249 (PropertyType_New) arrayprop_new,
250 (PropertyType_Free) arrayprop_free,
251 (PropertyType_Copy) arrayprop_copy,
252 (PropertyType_Load) arrayprop_load,
253 (PropertyType_Save) arrayprop_save,
255 (PropertyType_GetWidget) unimplementedprop_get_widget,
256 (PropertyType_ResetWidget) unimplementedprop_reset_widget,
257 (PropertyType_SetFromWidget) unimplementedprop_set_from_widget,
259 (PropertyType_CanMerge) arrayprop_can_merge,
260 (PropertyType_GetFromOffset) sarrayprop_get_from_offset,
261 (PropertyType_SetFromOffset) sarrayprop_set_from_offset
264 static const PropertyOps darrayprop_ops = {
265 (PropertyType_New) arrayprop_new,
266 (PropertyType_Free) arrayprop_free,
267 (PropertyType_Copy) arrayprop_copy,
268 (PropertyType_Load) arrayprop_load,
269 (PropertyType_Save) arrayprop_save,
271 (PropertyType_GetWidget) unimplementedprop_get_widget,
272 (PropertyType_ResetWidget) unimplementedprop_reset_widget,
273 (PropertyType_SetFromWidget) unimplementedprop_set_from_widget,
275 (PropertyType_CanMerge) noopprop_can_merge,
276 (PropertyType_GetFromOffset) darrayprop_get_from_offset,
277 (PropertyType_SetFromOffset) darrayprop_set_from_offset
280 /* ************************************************************** */
282 void
283 prop_sdarray_register(void)
285 prop_type_register(PROP_TYPE_SARRAY,&sarrayprop_ops);
286 prop_type_register(PROP_TYPE_DARRAY,&darrayprop_ops);