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 integral types (and arrays thereof).
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.
30 #include <stdlib.h> /* strtol */
32 #undef GTK_DISABLE_DEPRECATED /* gtk_signal_connect, gtk_object_set_user_data */
34 #define WIDGET GtkWidget
35 #include "properties.h"
36 #include "propinternals.h"
38 /***************************/
39 /* The CHAR property type. */
40 /***************************/
43 charprop_new(const PropDescription
*pdesc
, PropDescToPropPredicate reason
)
45 CharProperty
*prop
= g_new0(CharProperty
,1);
46 initialize_property(&prop
->common
,pdesc
,reason
);
52 charprop_copy(CharProperty
*src
)
55 (CharProperty
*)src
->common
.ops
->new_prop(src
->common
.descr
,
57 copy_init_property(&prop
->common
,&src
->common
);
58 prop
->char_data
= src
->char_data
;
63 charprop_get_widget(CharProperty
*prop
, PropDialog
*dialog
)
65 GtkWidget
*ret
= gtk_entry_new();
66 prophandler_connect(&prop
->common
,GTK_OBJECT(ret
),"changed");
71 charprop_reset_widget(CharProperty
*prop
, WIDGET
*widget
)
74 int unilen
= g_unichar_to_utf8 (prop
->char_data
, ch
);
76 gtk_entry_set_text(GTK_ENTRY(widget
), ch
);
80 charprop_set_from_widget(CharProperty
*prop
, WIDGET
*widget
)
82 gchar
*buf
= gtk_editable_get_chars(GTK_EDITABLE(widget
), 0, 1);
83 prop
->char_data
= g_utf8_get_char(buf
);
88 charprop_load(CharProperty
*prop
, AttributeNode attr
, DataNode data
)
90 gchar
*str
= data_string(data
);
93 prop
->char_data
= g_utf8_get_char(str
);
96 g_warning("Could not read character data for attribute %s",
102 charprop_save(CharProperty
*prop
, AttributeNode attr
)
105 gint n
= g_unichar_to_utf8 (prop
->char_data
, utf
);
107 data_add_string (attr
, utf
);
111 charprop_get_from_offset(CharProperty
*prop
,
112 void *base
, guint offset
, guint offset2
)
114 prop
->char_data
= struct_member(base
,offset
,gunichar
);
118 charprop_set_from_offset(CharProperty
*prop
,
119 void *base
, guint offset
, guint offset2
)
121 struct_member(base
,offset
,gunichar
) = prop
->char_data
;
125 static const PropertyOps charprop_ops
= {
126 (PropertyType_New
) charprop_new
,
127 (PropertyType_Free
) noopprop_free
,
128 (PropertyType_Copy
) charprop_copy
,
129 (PropertyType_Load
) charprop_load
,
130 (PropertyType_Save
) charprop_save
,
131 (PropertyType_GetWidget
) charprop_get_widget
,
132 (PropertyType_ResetWidget
) charprop_reset_widget
,
133 (PropertyType_SetFromWidget
) charprop_set_from_widget
,
135 (PropertyType_CanMerge
) noopprop_can_merge
,
136 (PropertyType_GetFromOffset
) charprop_get_from_offset
,
137 (PropertyType_SetFromOffset
) charprop_set_from_offset
140 /* ************************************ */
143 /***************************/
144 /* The BOOL property type. */
145 /***************************/
148 bool_toggled(GtkWidget
*wid
)
150 if (GTK_TOGGLE_BUTTON(wid
)->active
)
151 gtk_label_set_text(GTK_LABEL(GTK_BIN(wid
)->child
), _("Yes"));
153 gtk_label_set_text(GTK_LABEL(GTK_BIN(wid
)->child
), _("No"));
157 boolprop_new(const PropDescription
*pdesc
, PropDescToPropPredicate reason
)
159 BoolProperty
*prop
= g_new0(BoolProperty
,1);
160 initialize_property(&prop
->common
, pdesc
, reason
);
161 prop
->bool_data
= FALSE
;
162 return &prop
->common
;
165 static BoolProperty
*
166 boolprop_copy(BoolProperty
*src
)
169 (BoolProperty
*)src
->common
.ops
->new_prop(src
->common
.descr
,
171 copy_init_property(&prop
->common
,&src
->common
);
172 prop
->bool_data
= src
->bool_data
;
177 boolprop_get_widget(BoolProperty
*prop
, PropDialog
*dialog
)
179 GtkWidget
*ret
= gtk_toggle_button_new_with_label(_("No"));
180 gtk_signal_connect(GTK_OBJECT(ret
), "toggled",
181 GTK_SIGNAL_FUNC(bool_toggled
), NULL
);
182 prophandler_connect(&prop
->common
,GTK_OBJECT(ret
),"toggled");
187 boolprop_reset_widget(BoolProperty
*prop
, WIDGET
*widget
)
189 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget
),prop
->bool_data
);
193 boolprop_set_from_widget(BoolProperty
*prop
, WIDGET
*widget
)
195 prop
->bool_data
= GTK_TOGGLE_BUTTON(widget
)->active
;
199 boolprop_load(BoolProperty
*prop
, AttributeNode attr
, DataNode data
)
201 prop
->bool_data
= data_boolean(data
);
205 boolprop_save(BoolProperty
*prop
, AttributeNode attr
)
207 data_add_boolean(attr
, prop
->bool_data
);
211 boolprop_get_from_offset(BoolProperty
*prop
,
212 void *base
, guint offset
, guint offset2
)
214 prop
->bool_data
= struct_member(base
,offset
,gboolean
);
218 boolprop_set_from_offset(BoolProperty
*prop
,
219 void *base
, guint offset
, guint offset2
)
221 struct_member(base
,offset
,gboolean
) = prop
->bool_data
;
225 static const PropertyOps boolprop_ops
= {
226 (PropertyType_New
) boolprop_new
,
227 (PropertyType_Free
) noopprop_free
,
228 (PropertyType_Copy
) boolprop_copy
,
229 (PropertyType_Load
) boolprop_load
,
230 (PropertyType_Save
) boolprop_save
,
231 (PropertyType_GetWidget
) boolprop_get_widget
,
232 (PropertyType_ResetWidget
) boolprop_reset_widget
,
233 (PropertyType_SetFromWidget
) boolprop_set_from_widget
,
235 (PropertyType_CanMerge
) noopprop_can_merge
,
236 (PropertyType_GetFromOffset
) boolprop_get_from_offset
,
237 (PropertyType_SetFromOffset
) boolprop_set_from_offset
240 /***************************/
241 /* The INT property type. */
242 /***************************/
245 intprop_new(const PropDescription
*pdesc
, PropDescToPropPredicate reason
)
247 IntProperty
*prop
= g_new0(IntProperty
,1);
248 initialize_property(&prop
->common
, pdesc
, reason
);
254 intprop_copy(IntProperty
*src
)
257 (IntProperty
*)src
->common
.ops
->new_prop(src
->common
.descr
,
259 copy_init_property(&prop
->common
,&src
->common
);
260 prop
->int_data
= src
->int_data
;
265 intprop_get_widget(IntProperty
*prop
, PropDialog
*dialog
)
267 GtkAdjustment
*adj
= GTK_ADJUSTMENT(gtk_adjustment_new(prop
->int_data
,
270 GtkWidget
*ret
= gtk_spin_button_new(adj
, 1.0, 0);
271 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(ret
),TRUE
);
272 prophandler_connect(&prop
->common
,GTK_OBJECT(adj
),"value_changed");
278 intprop_reset_widget(IntProperty
*prop
, WIDGET
*widget
)
281 if (prop
->common
.extra_data
) {
282 PropNumData
*numdata
= prop
->common
.extra_data
;
283 adj
= GTK_ADJUSTMENT(gtk_adjustment_new(prop
->int_data
,
284 numdata
->min
, numdata
->max
,
285 numdata
->step
, 10.0 * numdata
->step
,
286 10.0 * numdata
->step
));
288 adj
= GTK_ADJUSTMENT(gtk_adjustment_new(prop
->int_data
,
292 gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(widget
), adj
);
293 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(widget
), TRUE
);
297 intprop_set_from_widget(IntProperty
*prop
, WIDGET
*widget
)
299 prop
->int_data
= gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget
));
303 intprop_load(IntProperty
*prop
, AttributeNode attr
, DataNode data
)
305 prop
->int_data
= data_int(data
);
309 intprop_save(IntProperty
*prop
, AttributeNode attr
)
311 data_add_int(attr
, prop
->int_data
);
315 intprop_get_from_offset(IntProperty
*prop
,
316 void *base
, guint offset
, guint offset2
)
318 prop
->int_data
= struct_member(base
,offset
,gint
);
322 intprop_set_from_offset(IntProperty
*prop
,
323 void *base
, guint offset
, guint offset2
)
325 struct_member(base
,offset
,gint
) = prop
->int_data
;
328 static const PropertyOps intprop_ops
= {
329 (PropertyType_New
) intprop_new
,
330 (PropertyType_Free
) noopprop_free
,
331 (PropertyType_Copy
) intprop_copy
,
332 (PropertyType_Load
) intprop_load
,
333 (PropertyType_Save
) intprop_save
,
334 (PropertyType_GetWidget
) intprop_get_widget
,
335 (PropertyType_ResetWidget
) intprop_reset_widget
,
336 (PropertyType_SetFromWidget
) intprop_set_from_widget
,
338 (PropertyType_CanMerge
) noopprop_can_merge
,
339 (PropertyType_GetFromOffset
) intprop_get_from_offset
,
340 (PropertyType_SetFromOffset
) intprop_set_from_offset
343 /********************************/
344 /* The INTARRAY property type. */
345 /********************************/
347 static IntarrayProperty
*
348 intarrayprop_new(const PropDescription
*pdesc
,
349 PropDescToPropPredicate reason
)
351 IntarrayProperty
*prop
= g_new0(IntarrayProperty
,1);
352 initialize_property(&prop
->common
, pdesc
, reason
);
353 prop
->intarray_data
= g_array_new(FALSE
,TRUE
,sizeof(gint
));
358 intarrayprop_free(IntarrayProperty
*prop
)
360 g_array_free(prop
->intarray_data
,TRUE
);
364 static IntarrayProperty
*
365 intarrayprop_copy(IntarrayProperty
*src
)
368 IntarrayProperty
*prop
=
369 (IntarrayProperty
*)src
->common
.ops
->new_prop(src
->common
.descr
,
371 copy_init_property(&prop
->common
,&src
->common
);
372 g_array_set_size(prop
->intarray_data
,src
->intarray_data
->len
);
373 for (i
= 0 ; i
< src
->intarray_data
->len
; i
++)
374 g_array_index(prop
->intarray_data
,gint
,i
) =
375 g_array_index(src
->intarray_data
,gint
,i
);
380 intarrayprop_load(IntarrayProperty
*prop
, AttributeNode attr
, DataNode data
)
382 guint nvals
= attribute_num_data(attr
);
384 g_array_set_size(prop
->intarray_data
,nvals
);
385 for (i
=0; (i
< nvals
) && data
; i
++, data
= data_next(data
))
386 g_array_index(prop
->intarray_data
,gint
,i
) = data_int(data
);
388 g_warning("attribute_num_data() and actual data count mismatch "
389 "(shouldn't happen)");
393 intarrayprop_save(IntarrayProperty
*prop
, AttributeNode attr
)
396 for (i
= 0; i
< prop
->intarray_data
->len
; i
++)
397 data_add_int(attr
, g_array_index(prop
->intarray_data
,gint
,i
));
401 intarrayprop_get_from_offset(IntarrayProperty
*prop
,
402 void *base
, guint offset
, guint offset2
)
404 guint nvals
= struct_member(base
,offset2
,guint
);
406 void *ofs_val
= struct_member(base
,offset
,void *);
407 g_array_set_size(prop
->intarray_data
,nvals
);
408 for (i
= 0; i
< nvals
; i
++)
409 g_array_index(prop
->intarray_data
,gint
,i
) =
410 struct_member(ofs_val
,i
* sizeof(gint
),gint
);
414 intarrayprop_set_from_offset(IntarrayProperty
*prop
,
415 void *base
, guint offset
, guint offset2
)
417 guint nvals
= prop
->intarray_data
->len
;
418 gint
*vals
= g_memdup(&g_array_index(prop
->intarray_data
,gint
,0),
419 sizeof(gint
) * nvals
);
420 g_free(struct_member(base
,offset
,gint
*));
421 struct_member(base
,offset
,gint
*) = vals
;
422 struct_member(base
,offset2
,guint
) = nvals
;
425 static const PropertyOps intarrayprop_ops
= {
426 (PropertyType_New
) intarrayprop_new
,
427 (PropertyType_Free
) intarrayprop_free
,
428 (PropertyType_Copy
) intarrayprop_copy
,
429 (PropertyType_Load
) intarrayprop_load
,
430 (PropertyType_Save
) intarrayprop_save
,
431 (PropertyType_GetWidget
) noopprop_get_widget
,
432 (PropertyType_ResetWidget
) noopprop_reset_widget
,
433 (PropertyType_SetFromWidget
) noopprop_set_from_widget
,
435 (PropertyType_CanMerge
) noopprop_can_merge
,
436 (PropertyType_GetFromOffset
) intarrayprop_get_from_offset
,
437 (PropertyType_SetFromOffset
) intarrayprop_set_from_offset
440 /***************************/
441 /* The ENUM property type. */
442 /***************************/
444 static EnumProperty
*
445 enumprop_new(const PropDescription
*pdesc
, PropDescToPropPredicate reason
)
447 EnumProperty
*prop
= g_new0(EnumProperty
,1);
448 initialize_property(&prop
->common
, pdesc
, reason
);
453 static EnumProperty
*
454 enumprop_copy(EnumProperty
*src
)
457 (EnumProperty
*)src
->common
.ops
->new_prop(src
->common
.descr
,
459 copy_init_property(&prop
->common
,&src
->common
);
460 prop
->enum_data
= src
->enum_data
;
465 enumprop_get_widget(EnumProperty
*prop
, PropDialog
*dialog
)
469 if (prop
->common
.extra_data
) {
470 PropEnumData
*enumdata
= prop
->common
.extra_data
;
474 ret
= gtk_option_menu_new();
475 menu
= gtk_menu_new();
476 for (i
= 0; enumdata
[i
].name
!= NULL
; i
++) {
477 GtkWidget
*item
= gtk_menu_item_new_with_label(_(enumdata
[i
].name
));
479 gtk_object_set_user_data(GTK_OBJECT(item
),
480 GUINT_TO_POINTER(enumdata
[i
].enumv
));
481 gtk_container_add(GTK_CONTAINER(menu
), item
);
482 gtk_widget_show(item
);
483 prophandler_connect(&prop
->common
,GTK_OBJECT(item
),"activate");
485 gtk_option_menu_set_menu(GTK_OPTION_MENU(ret
), menu
);
487 ret
= gtk_entry_new(); /* should use spin button/option menu */
493 enumprop_reset_widget(EnumProperty
*prop
, WIDGET
*widget
)
495 if (prop
->common
.extra_data
) {
496 PropEnumData
*enumdata
= prop
->common
.extra_data
;
499 for (i
= 0; enumdata
[i
].name
!= NULL
; i
++) {
500 if (enumdata
[i
].enumv
== prop
->enum_data
) {
505 gtk_option_menu_set_history(GTK_OPTION_MENU(widget
), pos
);
508 g_snprintf(buf
, sizeof(buf
), "%d", prop
->enum_data
);
509 gtk_entry_set_text(GTK_ENTRY(widget
), buf
);
514 enumprop_set_from_widget(EnumProperty
*prop
, WIDGET
*widget
)
516 if (GTK_IS_OPTION_MENU(widget
)) {
518 GPOINTER_TO_UINT(gtk_object_get_user_data(
519 GTK_OBJECT(GTK_OPTION_MENU(widget
)->menu_item
)));
521 prop
->enum_data
= strtol(gtk_entry_get_text(GTK_ENTRY(widget
)),
527 enumprop_load(EnumProperty
*prop
, AttributeNode attr
, DataNode data
)
529 prop
->enum_data
= data_enum(data
);
533 enumprop_save(EnumProperty
*prop
, AttributeNode attr
)
535 data_add_enum(attr
, prop
->enum_data
);
539 enumprop_get_from_offset(EnumProperty
*prop
,
540 void *base
, guint offset
, guint offset2
)
542 prop
->enum_data
= struct_member(base
,offset
,gint
);
546 enumprop_set_from_offset(EnumProperty
*prop
,
547 void *base
, guint offset
, guint offset2
)
549 struct_member(base
,offset
,gint
) = prop
->enum_data
;
552 static const PropertyOps enumprop_ops
= {
553 (PropertyType_New
) enumprop_new
,
554 (PropertyType_Free
) noopprop_free
,
555 (PropertyType_Copy
) enumprop_copy
,
556 (PropertyType_Load
) enumprop_load
,
557 (PropertyType_Save
) enumprop_save
,
558 (PropertyType_GetWidget
) enumprop_get_widget
,
559 (PropertyType_ResetWidget
) enumprop_reset_widget
,
560 (PropertyType_SetFromWidget
) enumprop_set_from_widget
,
562 (PropertyType_CanMerge
) noopprop_can_merge
,
563 (PropertyType_GetFromOffset
) enumprop_get_from_offset
,
564 (PropertyType_SetFromOffset
) enumprop_set_from_offset
567 /********************************/
568 /* The ENUMARRAY property type. */
569 /********************************/
571 static EnumarrayProperty
*
572 enumarrayprop_new(const PropDescription
*pdesc
,
573 PropDescToPropPredicate reason
)
575 EnumarrayProperty
*prop
= g_new0(EnumarrayProperty
,1);
576 initialize_property(&prop
->common
, pdesc
, reason
);
577 prop
->enumarray_data
= g_array_new(FALSE
,TRUE
,sizeof(gint
));
582 enumarrayprop_free(EnumarrayProperty
*prop
)
584 g_array_free(prop
->enumarray_data
,TRUE
);
588 static EnumarrayProperty
*
589 enumarrayprop_copy(EnumarrayProperty
*src
)
592 EnumarrayProperty
*prop
=
593 (EnumarrayProperty
*)src
->common
.ops
->new_prop(src
->common
.descr
,
595 copy_init_property(&prop
->common
,&src
->common
);
596 g_array_set_size(prop
->enumarray_data
,src
->enumarray_data
->len
);
597 for (i
= 0 ; i
< src
->enumarray_data
->len
; i
++)
598 g_array_index(prop
->enumarray_data
,gint
,i
) =
599 g_array_index(src
->enumarray_data
,gint
,i
);
604 enumarrayprop_load(EnumarrayProperty
*prop
, AttributeNode attr
, DataNode data
)
606 guint nvals
= attribute_num_data(attr
);
608 g_array_set_size(prop
->enumarray_data
,nvals
);
610 for (i
=0; (i
< nvals
) && data
; i
++, data
= data_next(data
))
611 g_array_index(prop
->enumarray_data
,gint
,i
) = data_enum(data
);
613 g_warning("attribute_num_data() and actual data count mismatch "
614 "(shouldn't happen)");
618 enumarrayprop_save(EnumarrayProperty
*prop
, AttributeNode attr
)
621 for (i
= 0; i
< prop
->enumarray_data
->len
; i
++)
622 data_add_enum(attr
, g_array_index(prop
->enumarray_data
,gint
,i
));
626 enumarrayprop_get_from_offset(EnumarrayProperty
*prop
,
627 void *base
, guint offset
, guint offset2
)
629 guint nvals
= struct_member(base
,offset2
,guint
);
631 void *ofs_val
= struct_member(base
,offset
,void *);
632 g_array_set_size(prop
->enumarray_data
,nvals
);
633 for (i
= 0; i
< nvals
; i
++)
634 g_array_index(prop
->enumarray_data
,gint
,i
) =
635 struct_member(ofs_val
,i
* sizeof(gint
),gint
);
639 enumarrayprop_set_from_offset(EnumarrayProperty
*prop
,
640 void *base
, guint offset
, guint offset2
)
642 guint nvals
= prop
->enumarray_data
->len
;
643 gint
*vals
= g_memdup(&g_array_index(prop
->enumarray_data
,gint
,0),
644 sizeof(gint
) * nvals
);
645 g_free(struct_member(base
,offset
,gint
*));
646 struct_member(base
,offset
,gint
*) = vals
;
647 struct_member(base
,offset2
,guint
) = nvals
;
650 static const PropertyOps enumarrayprop_ops
= {
651 (PropertyType_New
) enumarrayprop_new
,
652 (PropertyType_Free
) enumarrayprop_free
,
653 (PropertyType_Copy
) enumarrayprop_copy
,
654 (PropertyType_Load
) enumarrayprop_load
,
655 (PropertyType_Save
) enumarrayprop_save
,
656 (PropertyType_GetWidget
) noopprop_get_widget
,
657 (PropertyType_ResetWidget
) noopprop_reset_widget
,
658 (PropertyType_SetFromWidget
) noopprop_set_from_widget
,
660 (PropertyType_CanMerge
) noopprop_can_merge
,
661 (PropertyType_GetFromOffset
) enumarrayprop_get_from_offset
,
662 (PropertyType_SetFromOffset
) enumarrayprop_set_from_offset
665 /* ************************************************************** */
668 prop_inttypes_register(void)
670 prop_type_register(PROP_TYPE_CHAR
,&charprop_ops
);
671 prop_type_register(PROP_TYPE_BOOL
,&boolprop_ops
);
672 prop_type_register(PROP_TYPE_INT
,&intprop_ops
);
673 prop_type_register(PROP_TYPE_INTARRAY
,&intarrayprop_ops
);
674 prop_type_register(PROP_TYPE_ENUM
,&enumprop_ops
);
675 prop_type_register(PROP_TYPE_ENUMARRAY
,&enumarrayprop_ops
);