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 * Basic Property types definition.
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.
33 #define WIDGET GtkWidget
34 #include "properties.h"
35 #include "prop_basic.h"
36 #include "propinternals.h"
44 desc_hash_hash(const PropMoniker
*desc
)
46 guint name_hash
= g_str_hash(desc
->name
);
47 guint type_hash
= g_str_hash(desc
->type
);
49 return (name_hash
^ ((type_hash
& 0xFFFF0000) >> 16) ^
50 ((type_hash
& 0x0000FFFF) << 16) ^ (type_hash
));
54 desc_hash_compare(const PropMoniker
*a
, const PropMoniker
*b
)
56 return ((0 == strcmp(a
->name
,b
->name
)) && (0 == strcmp(a
->type
,b
->type
)));
60 make_new_prop(const char *name
, PropertyType type
, guint flags
)
62 static GHashTable
*hash
= NULL
;
63 PropMoniker
*moniker
= g_new0(PropMoniker
, 1);
64 PropDescription
*descr
;
69 if (!hash
) hash
= g_hash_table_new((GHashFunc
)desc_hash_hash
,
70 (GCompareFunc
)desc_hash_compare
);
72 descr
= g_hash_table_lookup(hash
,moniker
);
76 descr
= g_new0(PropDescription
,1);
80 descr
->quark
= g_quark_from_static_string(descr
->name
);
81 descr
->type_quark
= g_quark_from_static_string(descr
->type
);
82 descr
->ops
= prop_type_get_ops(type
);
83 g_hash_table_insert(hash
,moniker
,descr
);
84 /* we don't ever free anything allocated here. */
86 return descr
->ops
->new_prop(descr
,pdtpp_synthetic
);
90 /**************************************************************************/
91 /* The COMMON property type. prop->ops will always point to these ops, */
92 /* whose role is to update the prop->experience flag field and then call */
93 /* the original property routines. Exception is commonprop_new which does */
95 /**************************************************************************/
98 commonprop_new(const PropDescription
*pdesc
, PropDescToPropPredicate reason
)
100 /* Will be called mostly when doing copies and empty copies.
101 Will NOT be called upon the creation of an original property. */
102 return pdesc
->ops
->new_prop(pdesc
,reason
);
106 commonprop_free(Property
*prop
)
108 prop
->real_ops
->free(prop
);
112 commonprop_copy(Property
*src
)
114 Property
*prop
= src
->real_ops
->copy(src
);
115 src
->experience
|= PXP_COPIED
;
116 prop
->experience
|= PXP_COPY
;
121 commonprop_get_widget(Property
*prop
, PropDialog
*dialog
)
123 WIDGET
*wid
= prop
->real_ops
->get_widget(prop
,dialog
);
124 prop
->experience
|= PXP_GET_WIDGET
;
129 commonprop_reset_widget(Property
*prop
, WIDGET
*widget
)
131 prop
->real_ops
->reset_widget(prop
,widget
);
132 prop
->experience
|= PXP_RESET_WIDGET
;
136 commonprop_set_from_widget(Property
*prop
, WIDGET
*widget
)
138 prop
->real_ops
->set_from_widget(prop
,widget
);
139 prop
->experience
|= PXP_SET_FROM_WIDGET
;
143 commonprop_load(Property
*prop
, AttributeNode attr
, DataNode data
)
145 prop
->real_ops
->load(prop
,attr
,data
);
146 prop
->experience
|= PXP_LOADED
;
150 commonprop_save(Property
*prop
, AttributeNode attr
)
152 prop
->real_ops
->save(prop
,attr
);
153 prop
->experience
|= PXP_SAVED
;
157 commonprop_can_merge(const PropDescription
*pd1
, const PropDescription
*pd2
)
159 return pd1
->ops
->can_merge(pd1
,pd2
);
163 commonprop_get_from_offset(const Property
*prop
,
164 void *base
, guint offset
, guint offset2
)
166 prop
->real_ops
->get_from_offset(prop
,base
,offset
,offset2
);
167 ((Property
*)prop
)->experience
|= PXP_GFO
;
171 commonprop_set_from_offset(Property
*prop
,
172 void *base
, guint offset
, guint offset2
)
174 prop
->real_ops
->set_from_offset(prop
,base
,offset
,offset2
);
175 prop
->experience
|= PXP_SFO
;
178 static const PropertyOps commonprop_ops
= {
179 (PropertyType_New
) commonprop_new
,
180 (PropertyType_Free
) commonprop_free
,
181 (PropertyType_Copy
) commonprop_copy
,
182 (PropertyType_Load
) commonprop_load
,
183 (PropertyType_Save
) commonprop_save
,
184 (PropertyType_GetWidget
) commonprop_get_widget
,
185 (PropertyType_ResetWidget
) commonprop_reset_widget
,
186 (PropertyType_SetFromWidget
) commonprop_set_from_widget
,
188 (PropertyType_CanMerge
) commonprop_can_merge
,
189 (PropertyType_GetFromOffset
) commonprop_get_from_offset
,
190 (PropertyType_SetFromOffset
) commonprop_set_from_offset
195 void initialize_property(Property
*prop
, const PropDescription
*pdesc
,
196 PropDescToPropPredicate reason
)
198 prop
->reason
= reason
;
199 prop
->name
= pdesc
->name
;
200 prop
->name_quark
= pdesc
->quark
;
201 if (!prop
->name_quark
) {
202 prop
->name_quark
= g_quark_from_string(prop
->name
);
203 g_error(G_GNUC_FUNCTION
": late quark construction for property %s",
206 prop
->type
= pdesc
->type
;
207 prop
->type_quark
= pdesc
->type_quark
;
208 prop
->ops
= &commonprop_ops
;
209 prop
->real_ops
= pdesc
->ops
;
210 /* if late quark construction, we'll have NULL here */
212 prop
->reason
= reason
;
213 prop
->extra_data
= pdesc
->extra_data
;
214 /* prop->self remains 0 until we get a widget from this. */
215 prop
->event_handler
= pdesc
->event_handler
;
217 prop
->experience
= 0;
220 void copy_init_property(Property
*dest
, const Property
*src
)
221 { /* XXX: inline this ? */
222 memcpy(dest
,src
,sizeof(*dest
));
223 dest
->experience
= 0;
227 /**************************************************************************/
228 /* The NOOP property type. It is mostly useful to serve as both a library */
229 /* and a cut-n-paste template library; this is the reason why its member */
230 /* functions are not declared static (in the general case, they should). */
231 /**************************************************************************/
234 noopprop_new(const PropDescription
*pdesc
, PropDescToPropPredicate reason
)
236 NoopProperty
*prop
= g_new(NoopProperty
,1);
237 initialize_property(&prop
->common
, pdesc
, reason
);
242 noopprop_free(NoopProperty
*prop
)
248 noopprop_copy(NoopProperty
*src
)
251 (NoopProperty
*)src
->common
.ops
->new_prop(src
->common
.descr
,
253 copy_init_property(&prop
->common
,&src
->common
);
254 return prop
; /* Yes, this one could be just be _new().
255 It's actually a placeholder. */
259 noopprop_get_widget(NoopProperty
*prop
, PropDialog
*dialog
)
265 noopprop_reset_widget(NoopProperty
*prop
, WIDGET
*widget
)
270 noopprop_set_from_widget(NoopProperty
*prop
, WIDGET
*widget
)
275 noopprop_load(NoopProperty
*prop
, AttributeNode attr
, DataNode data
)
280 noopprop_save(NoopProperty
*prop
, AttributeNode attr
)
285 noopprop_can_merge(const PropDescription
*pd1
, const PropDescription
*pd2
)
291 noopprop_cannot_merge(const PropDescription
*pd1
, const PropDescription
*pd2
)
297 noopprop_get_from_offset(const NoopProperty
*prop
,
298 void *base
, guint offset
, guint offset2
)
303 noopprop_set_from_offset(NoopProperty
*prop
,
304 void *base
, guint offset
, guint offset2
)
308 static const PropertyOps noopprop_ops
= {
309 (PropertyType_New
) noopprop_new
,
310 (PropertyType_Free
) noopprop_free
,
311 (PropertyType_Copy
) noopprop_copy
,
312 (PropertyType_Load
) noopprop_load
,
313 (PropertyType_Save
) noopprop_save
,
314 (PropertyType_GetWidget
) noopprop_get_widget
,
315 (PropertyType_ResetWidget
) noopprop_reset_widget
,
316 (PropertyType_SetFromWidget
) noopprop_set_from_widget
,
318 (PropertyType_CanMerge
) noopprop_can_merge
, /* but we have noopprop_cannot_merge */
319 (PropertyType_GetFromOffset
) noopprop_get_from_offset
,
320 (PropertyType_SetFromOffset
) noopprop_set_from_offset
323 /***************************************************************************/
324 /* The INVALID property type. It is mostly useful to serve a library. */
325 /* Each time its code is executed, a g_assert_not_reached() will be run... */
326 /***************************************************************************/
329 invalidprop_new(const PropDescription
*pdesc
,
330 PropDescToPropPredicate reason
)
332 g_assert_not_reached();
337 invalidprop_free(InvalidProperty
*prop
)
339 g_assert_not_reached();
343 invalidprop_copy(InvalidProperty
*src
)
345 g_assert_not_reached();
350 invalidprop_get_widget(InvalidProperty
*prop
, PropDialog
*dialog
)
352 g_assert_not_reached();
357 invalidprop_reset_widget(InvalidProperty
*prop
, WIDGET
*widget
)
359 g_assert_not_reached();
363 invalidprop_set_from_widget(InvalidProperty
*prop
, WIDGET
*widget
)
365 g_assert_not_reached();
369 invalidprop_load(InvalidProperty
*prop
, AttributeNode attr
, DataNode data
)
371 g_assert_not_reached();
375 invalidprop_save(InvalidProperty
*prop
, AttributeNode attr
)
377 g_assert_not_reached();
381 invalidprop_can_merge(const PropDescription
*pd1
, const PropDescription
*pd2
)
383 g_assert_not_reached();
388 invalidprop_get_from_offset(const InvalidProperty
*prop
,
389 void *base
, guint offset
, guint offset2
)
391 g_assert_not_reached();
395 invalidprop_set_from_offset(InvalidProperty
*prop
,
396 void *base
, guint offset
, guint offset2
)
398 g_assert_not_reached();
401 static const PropertyOps invalidprop_ops
= {
402 (PropertyType_New
) invalidprop_new
,
403 (PropertyType_Free
) invalidprop_free
,
404 (PropertyType_Copy
) invalidprop_copy
,
405 (PropertyType_Load
) invalidprop_load
,
406 (PropertyType_Save
) invalidprop_save
,
407 (PropertyType_GetWidget
) invalidprop_get_widget
,
408 (PropertyType_ResetWidget
) invalidprop_reset_widget
,
409 (PropertyType_SetFromWidget
) invalidprop_set_from_widget
,
411 (PropertyType_CanMerge
) invalidprop_can_merge
,
412 (PropertyType_GetFromOffset
) invalidprop_get_from_offset
,
413 (PropertyType_SetFromOffset
) invalidprop_set_from_offset
416 /***************************************************************************/
417 /* The UNIMPLEMENTED property type. It is mostly useful to serve a library */
418 /* for unfinished property types. */
419 /***************************************************************************/
421 UnimplementedProperty
*
422 unimplementedprop_new(const PropDescription
*pdesc
,
423 PropDescToPropPredicate reason
)
425 g_warning(G_GNUC_FUNCTION
" for property %s",pdesc
->name
);
430 unimplementedprop_free(UnimplementedProperty
*prop
)
432 g_warning(G_GNUC_FUNCTION
" for property %s",prop
->common
.descr
->name
);
435 UnimplementedProperty
*
436 unimplementedprop_copy(UnimplementedProperty
*src
)
438 g_warning(G_GNUC_FUNCTION
" for property %s",src
->common
.descr
->name
);
443 unimplementedprop_get_widget(UnimplementedProperty
*prop
, PropDialog
*dialog
)
445 g_warning(G_GNUC_FUNCTION
" for property %s",prop
->common
.descr
->name
);
450 unimplementedprop_reset_widget(UnimplementedProperty
*prop
, WIDGET
*widget
)
452 g_warning(G_GNUC_FUNCTION
" for property %s",prop
->common
.descr
->name
);
456 unimplementedprop_set_from_widget(UnimplementedProperty
*prop
, WIDGET
*widget
)
458 g_warning(G_GNUC_FUNCTION
" for property %s",prop
->common
.descr
->name
);
462 unimplementedprop_load(UnimplementedProperty
*prop
,
463 AttributeNode attr
, DataNode data
)
465 g_warning(G_GNUC_FUNCTION
" for property %s",prop
->common
.descr
->name
);
469 unimplementedprop_save(UnimplementedProperty
*prop
, AttributeNode attr
)
471 g_warning(G_GNUC_FUNCTION
" for property %s",prop
->common
.descr
->name
);
475 unimplementedprop_can_merge(const PropDescription
*pd1
, const PropDescription
*pd2
)
477 g_warning(G_GNUC_FUNCTION
" for property %s/%s",pd1
->name
,pd2
->name
);
482 unimplementedprop_get_from_offset(const UnimplementedProperty
*prop
,
483 void *base
, guint offset
, guint offset2
)
485 g_warning(G_GNUC_FUNCTION
" for property %s",prop
->common
.descr
->name
);
489 unimplementedprop_set_from_offset(UnimplementedProperty
*prop
,
490 void *base
, guint offset
, guint offset2
)
492 g_warning(G_GNUC_FUNCTION
" for property %s",prop
->common
.descr
->name
);
495 static const PropertyOps unimplementedprop_ops
= {
496 (PropertyType_New
) unimplementedprop_new
,
497 (PropertyType_Free
) unimplementedprop_free
,
498 (PropertyType_Copy
) unimplementedprop_copy
,
499 (PropertyType_Load
) unimplementedprop_load
,
500 (PropertyType_Save
) unimplementedprop_save
,
501 (PropertyType_GetWidget
) unimplementedprop_get_widget
,
502 (PropertyType_ResetWidget
) unimplementedprop_reset_widget
,
503 (PropertyType_SetFromWidget
) unimplementedprop_set_from_widget
,
505 (PropertyType_CanMerge
) unimplementedprop_can_merge
,
506 (PropertyType_GetFromOffset
) unimplementedprop_get_from_offset
,
507 (PropertyType_SetFromOffset
) unimplementedprop_set_from_offset
510 /* ************************************************************** */
513 prop_basic_register(void)
515 prop_type_register(PROP_TYPE_NOOP
,&noopprop_ops
);
516 prop_type_register(PROP_TYPE_INVALID
,&invalidprop_ops
);
517 prop_type_register(PROP_TYPE_UNIMPLEMENTED
,&unimplementedprop_ops
);