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 charprop_get_data_size(CharProperty
*prop
)
127 return sizeof (prop
->char_data
);
131 static const PropertyOps charprop_ops
= {
132 (PropertyType_New
) charprop_new
,
133 (PropertyType_Free
) noopprop_free
,
134 (PropertyType_Copy
) charprop_copy
,
135 (PropertyType_Load
) charprop_load
,
136 (PropertyType_Save
) charprop_save
,
137 (PropertyType_GetWidget
) charprop_get_widget
,
138 (PropertyType_ResetWidget
) charprop_reset_widget
,
139 (PropertyType_SetFromWidget
) charprop_set_from_widget
,
141 (PropertyType_CanMerge
) noopprop_can_merge
,
142 (PropertyType_GetFromOffset
) charprop_get_from_offset
,
143 (PropertyType_SetFromOffset
) charprop_set_from_offset
,
144 (PropertyType_GetDataSize
) charprop_get_data_size
147 /* ************************************ */
150 /***************************/
151 /* The BOOL property type. */
152 /***************************/
155 bool_toggled(GtkWidget
*wid
)
157 if (GTK_TOGGLE_BUTTON(wid
)->active
)
158 gtk_label_set_text(GTK_LABEL(GTK_BIN(wid
)->child
), _("Yes"));
160 gtk_label_set_text(GTK_LABEL(GTK_BIN(wid
)->child
), _("No"));
164 boolprop_new(const PropDescription
*pdesc
, PropDescToPropPredicate reason
)
166 BoolProperty
*prop
= g_new0(BoolProperty
,1);
167 initialize_property(&prop
->common
, pdesc
, reason
);
168 prop
->bool_data
= FALSE
;
169 return &prop
->common
;
172 static BoolProperty
*
173 boolprop_copy(BoolProperty
*src
)
176 (BoolProperty
*)src
->common
.ops
->new_prop(src
->common
.descr
,
178 copy_init_property(&prop
->common
,&src
->common
);
179 prop
->bool_data
= src
->bool_data
;
184 boolprop_get_widget(BoolProperty
*prop
, PropDialog
*dialog
)
186 GtkWidget
*ret
= gtk_toggle_button_new_with_label(_("No"));
187 gtk_signal_connect(GTK_OBJECT(ret
), "toggled",
188 GTK_SIGNAL_FUNC(bool_toggled
), NULL
);
189 prophandler_connect(&prop
->common
,GTK_OBJECT(ret
),"toggled");
194 boolprop_reset_widget(BoolProperty
*prop
, WIDGET
*widget
)
196 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget
),prop
->bool_data
);
200 boolprop_set_from_widget(BoolProperty
*prop
, WIDGET
*widget
)
202 prop
->bool_data
= GTK_TOGGLE_BUTTON(widget
)->active
;
206 boolprop_load(BoolProperty
*prop
, AttributeNode attr
, DataNode data
)
208 prop
->bool_data
= data_boolean(data
);
212 boolprop_save(BoolProperty
*prop
, AttributeNode attr
)
214 data_add_boolean(attr
, prop
->bool_data
);
218 boolprop_get_from_offset(BoolProperty
*prop
,
219 void *base
, guint offset
, guint offset2
)
221 prop
->bool_data
= struct_member(base
,offset
,gboolean
);
225 boolprop_set_from_offset(BoolProperty
*prop
,
226 void *base
, guint offset
, guint offset2
)
228 struct_member(base
,offset
,gboolean
) = prop
->bool_data
;
232 boolprop_get_data_size(BoolProperty
*prop
)
234 return sizeof (prop
->bool_data
);
238 static const PropertyOps boolprop_ops
= {
239 (PropertyType_New
) boolprop_new
,
240 (PropertyType_Free
) noopprop_free
,
241 (PropertyType_Copy
) boolprop_copy
,
242 (PropertyType_Load
) boolprop_load
,
243 (PropertyType_Save
) boolprop_save
,
244 (PropertyType_GetWidget
) boolprop_get_widget
,
245 (PropertyType_ResetWidget
) boolprop_reset_widget
,
246 (PropertyType_SetFromWidget
) boolprop_set_from_widget
,
248 (PropertyType_CanMerge
) noopprop_can_merge
,
249 (PropertyType_GetFromOffset
) boolprop_get_from_offset
,
250 (PropertyType_SetFromOffset
) boolprop_set_from_offset
,
251 (PropertyType_GetDataSize
) boolprop_get_data_size
254 /***************************/
255 /* The INT property type. */
256 /***************************/
259 intprop_new(const PropDescription
*pdesc
, PropDescToPropPredicate reason
)
261 IntProperty
*prop
= g_new0(IntProperty
,1);
262 initialize_property(&prop
->common
, pdesc
, reason
);
268 intprop_copy(IntProperty
*src
)
271 (IntProperty
*)src
->common
.ops
->new_prop(src
->common
.descr
,
273 copy_init_property(&prop
->common
,&src
->common
);
274 prop
->int_data
= src
->int_data
;
279 intprop_get_widget(IntProperty
*prop
, PropDialog
*dialog
)
281 GtkAdjustment
*adj
= GTK_ADJUSTMENT(gtk_adjustment_new(prop
->int_data
,
284 GtkWidget
*ret
= gtk_spin_button_new(adj
, 1.0, 0);
285 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(ret
),TRUE
);
286 prophandler_connect(&prop
->common
,GTK_OBJECT(adj
),"value_changed");
292 intprop_reset_widget(IntProperty
*prop
, WIDGET
*widget
)
295 if (prop
->common
.extra_data
) {
296 PropNumData
*numdata
= prop
->common
.extra_data
;
297 adj
= GTK_ADJUSTMENT(gtk_adjustment_new(prop
->int_data
,
298 numdata
->min
, numdata
->max
,
299 numdata
->step
, 10.0 * numdata
->step
,
300 10.0 * numdata
->step
));
302 adj
= GTK_ADJUSTMENT(gtk_adjustment_new(prop
->int_data
,
306 gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(widget
), adj
);
307 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(widget
), TRUE
);
311 intprop_set_from_widget(IntProperty
*prop
, WIDGET
*widget
)
313 prop
->int_data
= gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget
));
317 intprop_load(IntProperty
*prop
, AttributeNode attr
, DataNode data
)
319 prop
->int_data
= data_int(data
);
323 intprop_save(IntProperty
*prop
, AttributeNode attr
)
325 data_add_int(attr
, prop
->int_data
);
329 intprop_get_from_offset(IntProperty
*prop
,
330 void *base
, guint offset
, guint offset2
)
332 prop
->int_data
= struct_member(base
,offset
,gint
);
336 intprop_set_from_offset(IntProperty
*prop
,
337 void *base
, guint offset
, guint offset2
)
339 struct_member(base
,offset
,gint
) = prop
->int_data
;
343 intprop_get_data_size(IntProperty
*prop
)
345 return sizeof (prop
->int_data
);
348 static const PropertyOps intprop_ops
= {
349 (PropertyType_New
) intprop_new
,
350 (PropertyType_Free
) noopprop_free
,
351 (PropertyType_Copy
) intprop_copy
,
352 (PropertyType_Load
) intprop_load
,
353 (PropertyType_Save
) intprop_save
,
354 (PropertyType_GetWidget
) intprop_get_widget
,
355 (PropertyType_ResetWidget
) intprop_reset_widget
,
356 (PropertyType_SetFromWidget
) intprop_set_from_widget
,
358 (PropertyType_CanMerge
) noopprop_can_merge
,
359 (PropertyType_GetFromOffset
) intprop_get_from_offset
,
360 (PropertyType_SetFromOffset
) intprop_set_from_offset
,
361 (PropertyType_GetDataSize
) intprop_get_data_size
364 /********************************/
365 /* The INTARRAY property type. */
366 /********************************/
368 static IntarrayProperty
*
369 intarrayprop_new(const PropDescription
*pdesc
,
370 PropDescToPropPredicate reason
)
372 IntarrayProperty
*prop
= g_new0(IntarrayProperty
,1);
373 initialize_property(&prop
->common
, pdesc
, reason
);
374 prop
->intarray_data
= g_array_new(FALSE
,TRUE
,sizeof(gint
));
379 intarrayprop_free(IntarrayProperty
*prop
)
381 g_array_free(prop
->intarray_data
,TRUE
);
385 static IntarrayProperty
*
386 intarrayprop_copy(IntarrayProperty
*src
)
389 IntarrayProperty
*prop
=
390 (IntarrayProperty
*)src
->common
.ops
->new_prop(src
->common
.descr
,
392 copy_init_property(&prop
->common
,&src
->common
);
393 g_array_set_size(prop
->intarray_data
,src
->intarray_data
->len
);
394 for (i
= 0 ; i
< src
->intarray_data
->len
; i
++)
395 g_array_index(prop
->intarray_data
,gint
,i
) =
396 g_array_index(src
->intarray_data
,gint
,i
);
401 intarrayprop_load(IntarrayProperty
*prop
, AttributeNode attr
, DataNode data
)
403 guint nvals
= attribute_num_data(attr
);
405 g_array_set_size(prop
->intarray_data
,nvals
);
406 for (i
=0; (i
< nvals
) && data
; i
++, data
= data_next(data
))
407 g_array_index(prop
->intarray_data
,gint
,i
) = data_int(data
);
409 g_warning("attribute_num_data() and actual data count mismatch "
410 "(shouldn't happen)");
414 intarrayprop_save(IntarrayProperty
*prop
, AttributeNode attr
)
417 for (i
= 0; i
< prop
->intarray_data
->len
; i
++)
418 data_add_int(attr
, g_array_index(prop
->intarray_data
,gint
,i
));
422 intarrayprop_get_from_offset(IntarrayProperty
*prop
,
423 void *base
, guint offset
, guint offset2
)
425 guint nvals
= struct_member(base
,offset2
,guint
);
427 void *ofs_val
= struct_member(base
,offset
,void *);
428 g_array_set_size(prop
->intarray_data
,nvals
);
429 for (i
= 0; i
< nvals
; i
++)
430 g_array_index(prop
->intarray_data
,gint
,i
) =
431 struct_member(ofs_val
,i
* sizeof(gint
),gint
);
435 intarrayprop_set_from_offset(IntarrayProperty
*prop
,
436 void *base
, guint offset
, guint offset2
)
438 guint nvals
= prop
->intarray_data
->len
;
439 gint
*vals
= g_memdup(&g_array_index(prop
->intarray_data
,gint
,0),
440 sizeof(gint
) * nvals
);
441 g_free(struct_member(base
,offset
,gint
*));
442 struct_member(base
,offset
,gint
*) = vals
;
443 struct_member(base
,offset2
,guint
) = nvals
;
446 static const PropertyOps intarrayprop_ops
= {
447 (PropertyType_New
) intarrayprop_new
,
448 (PropertyType_Free
) intarrayprop_free
,
449 (PropertyType_Copy
) intarrayprop_copy
,
450 (PropertyType_Load
) intarrayprop_load
,
451 (PropertyType_Save
) intarrayprop_save
,
452 (PropertyType_GetWidget
) noopprop_get_widget
,
453 (PropertyType_ResetWidget
) noopprop_reset_widget
,
454 (PropertyType_SetFromWidget
) noopprop_set_from_widget
,
456 (PropertyType_CanMerge
) noopprop_can_merge
,
457 (PropertyType_GetFromOffset
) intarrayprop_get_from_offset
,
458 (PropertyType_SetFromOffset
) intarrayprop_set_from_offset
461 /***************************/
462 /* The ENUM property type. */
463 /***************************/
465 static EnumProperty
*
466 enumprop_new(const PropDescription
*pdesc
, PropDescToPropPredicate reason
)
468 EnumProperty
*prop
= g_new0(EnumProperty
,1);
469 initialize_property(&prop
->common
, pdesc
, reason
);
474 static EnumProperty
*
475 enumprop_copy(EnumProperty
*src
)
478 (EnumProperty
*)src
->common
.ops
->new_prop(src
->common
.descr
,
480 copy_init_property(&prop
->common
,&src
->common
);
481 prop
->enum_data
= src
->enum_data
;
486 enumprop_get_widget(EnumProperty
*prop
, PropDialog
*dialog
)
490 if (prop
->common
.extra_data
) {
491 PropEnumData
*enumdata
= prop
->common
.extra_data
;
495 ret
= gtk_option_menu_new();
496 menu
= gtk_menu_new();
497 for (i
= 0; enumdata
[i
].name
!= NULL
; i
++) {
498 GtkWidget
*item
= gtk_menu_item_new_with_label(_(enumdata
[i
].name
));
500 gtk_object_set_user_data(GTK_OBJECT(item
),
501 GUINT_TO_POINTER(enumdata
[i
].enumv
));
502 gtk_container_add(GTK_CONTAINER(menu
), item
);
503 gtk_widget_show(item
);
504 prophandler_connect(&prop
->common
,GTK_OBJECT(item
),"activate");
506 gtk_option_menu_set_menu(GTK_OPTION_MENU(ret
), menu
);
508 ret
= gtk_entry_new(); /* should use spin button/option menu */
514 enumprop_reset_widget(EnumProperty
*prop
, WIDGET
*widget
)
516 if (prop
->common
.extra_data
) {
517 PropEnumData
*enumdata
= prop
->common
.extra_data
;
520 for (i
= 0; enumdata
[i
].name
!= NULL
; i
++) {
521 if (enumdata
[i
].enumv
== prop
->enum_data
) {
526 gtk_option_menu_set_history(GTK_OPTION_MENU(widget
), pos
);
529 g_snprintf(buf
, sizeof(buf
), "%d", prop
->enum_data
);
530 gtk_entry_set_text(GTK_ENTRY(widget
), buf
);
535 enumprop_set_from_widget(EnumProperty
*prop
, WIDGET
*widget
)
537 if (GTK_IS_OPTION_MENU(widget
)) {
539 GPOINTER_TO_UINT(gtk_object_get_user_data(
540 GTK_OBJECT(GTK_OPTION_MENU(widget
)->menu_item
)));
542 prop
->enum_data
= strtol(gtk_entry_get_text(GTK_ENTRY(widget
)),
548 enumprop_load(EnumProperty
*prop
, AttributeNode attr
, DataNode data
)
550 prop
->enum_data
= data_enum(data
);
554 enumprop_save(EnumProperty
*prop
, AttributeNode attr
)
556 data_add_enum(attr
, prop
->enum_data
);
560 enumprop_get_from_offset(EnumProperty
*prop
,
561 void *base
, guint offset
, guint offset2
)
563 prop
->enum_data
= struct_member(base
,offset
,gint
);
567 enumprop_set_from_offset(EnumProperty
*prop
,
568 void *base
, guint offset
, guint offset2
)
570 struct_member(base
,offset
,gint
) = prop
->enum_data
;
573 static const PropertyOps enumprop_ops
= {
574 (PropertyType_New
) enumprop_new
,
575 (PropertyType_Free
) noopprop_free
,
576 (PropertyType_Copy
) enumprop_copy
,
577 (PropertyType_Load
) enumprop_load
,
578 (PropertyType_Save
) enumprop_save
,
579 (PropertyType_GetWidget
) enumprop_get_widget
,
580 (PropertyType_ResetWidget
) enumprop_reset_widget
,
581 (PropertyType_SetFromWidget
) enumprop_set_from_widget
,
583 (PropertyType_CanMerge
) noopprop_can_merge
,
584 (PropertyType_GetFromOffset
) enumprop_get_from_offset
,
585 (PropertyType_SetFromOffset
) enumprop_set_from_offset
588 /********************************/
589 /* The ENUMARRAY property type. */
590 /********************************/
592 static EnumarrayProperty
*
593 enumarrayprop_new(const PropDescription
*pdesc
,
594 PropDescToPropPredicate reason
)
596 EnumarrayProperty
*prop
= g_new0(EnumarrayProperty
,1);
597 initialize_property(&prop
->common
, pdesc
, reason
);
598 prop
->enumarray_data
= g_array_new(FALSE
,TRUE
,sizeof(gint
));
603 enumarrayprop_free(EnumarrayProperty
*prop
)
605 g_array_free(prop
->enumarray_data
,TRUE
);
609 static EnumarrayProperty
*
610 enumarrayprop_copy(EnumarrayProperty
*src
)
613 EnumarrayProperty
*prop
=
614 (EnumarrayProperty
*)src
->common
.ops
->new_prop(src
->common
.descr
,
616 copy_init_property(&prop
->common
,&src
->common
);
617 g_array_set_size(prop
->enumarray_data
,src
->enumarray_data
->len
);
618 for (i
= 0 ; i
< src
->enumarray_data
->len
; i
++)
619 g_array_index(prop
->enumarray_data
,gint
,i
) =
620 g_array_index(src
->enumarray_data
,gint
,i
);
625 enumarrayprop_load(EnumarrayProperty
*prop
, AttributeNode attr
, DataNode data
)
627 guint nvals
= attribute_num_data(attr
);
629 g_array_set_size(prop
->enumarray_data
,nvals
);
631 for (i
=0; (i
< nvals
) && data
; i
++, data
= data_next(data
))
632 g_array_index(prop
->enumarray_data
,gint
,i
) = data_enum(data
);
634 g_warning("attribute_num_data() and actual data count mismatch "
635 "(shouldn't happen)");
639 enumarrayprop_save(EnumarrayProperty
*prop
, AttributeNode attr
)
642 for (i
= 0; i
< prop
->enumarray_data
->len
; i
++)
643 data_add_enum(attr
, g_array_index(prop
->enumarray_data
,gint
,i
));
647 enumarrayprop_get_from_offset(EnumarrayProperty
*prop
,
648 void *base
, guint offset
, guint offset2
)
650 guint nvals
= struct_member(base
,offset2
,guint
);
652 void *ofs_val
= struct_member(base
,offset
,void *);
653 g_array_set_size(prop
->enumarray_data
,nvals
);
654 for (i
= 0; i
< nvals
; i
++)
655 g_array_index(prop
->enumarray_data
,gint
,i
) =
656 struct_member(ofs_val
,i
* sizeof(gint
),gint
);
660 enumarrayprop_set_from_offset(EnumarrayProperty
*prop
,
661 void *base
, guint offset
, guint offset2
)
663 guint nvals
= prop
->enumarray_data
->len
;
664 gint
*vals
= g_memdup(&g_array_index(prop
->enumarray_data
,gint
,0),
665 sizeof(gint
) * nvals
);
666 g_free(struct_member(base
,offset
,gint
*));
667 struct_member(base
,offset
,gint
*) = vals
;
668 struct_member(base
,offset2
,guint
) = nvals
;
671 static const PropertyOps enumarrayprop_ops
= {
672 (PropertyType_New
) enumarrayprop_new
,
673 (PropertyType_Free
) enumarrayprop_free
,
674 (PropertyType_Copy
) enumarrayprop_copy
,
675 (PropertyType_Load
) enumarrayprop_load
,
676 (PropertyType_Save
) enumarrayprop_save
,
677 (PropertyType_GetWidget
) noopprop_get_widget
,
678 (PropertyType_ResetWidget
) noopprop_reset_widget
,
679 (PropertyType_SetFromWidget
) noopprop_set_from_widget
,
681 (PropertyType_CanMerge
) noopprop_can_merge
,
682 (PropertyType_GetFromOffset
) enumarrayprop_get_from_offset
,
683 (PropertyType_SetFromOffset
) enumarrayprop_set_from_offset
686 /* ************************************************************** */
689 prop_inttypes_register(void)
691 prop_type_register(PROP_TYPE_CHAR
,&charprop_ops
);
692 prop_type_register(PROP_TYPE_BOOL
,&boolprop_ops
);
693 prop_type_register(PROP_TYPE_INT
,&intprop_ops
);
694 prop_type_register(PROP_TYPE_INTARRAY
,&intarrayprop_ops
);
695 prop_type_register(PROP_TYPE_ENUM
,&enumprop_ops
);
696 prop_type_register(PROP_TYPE_ENUMARRAY
,&enumarrayprop_ops
);