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 "textual" types (strings, texts, whatever).
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.
31 #include <gdk/gdkkeysyms.h>
33 #include "properties.h"
34 #include "propinternals.h"
38 /*****************************************************/
39 /* The STRING, FILE and MULTISTRING property types. */
40 /*****************************************************/
42 static StringProperty
*
43 stringprop_new(const PropDescription
*pdesc
, PropDescToPropPredicate reason
)
45 StringProperty
*prop
= g_new0(StringProperty
,1);
46 initialize_property(&prop
->common
,pdesc
,reason
);
47 prop
->string_data
= NULL
;
52 static StringProperty
*
53 multistringprop_new(const PropDescription
*pdesc
,
54 PropDescToPropPredicate reason
)
56 StringProperty
*prop
= g_new0(StringProperty
,1);
57 initialize_property(&prop
->common
,pdesc
,reason
);
58 prop
->string_data
= NULL
;
59 prop
->num_lines
= GPOINTER_TO_INT(pdesc
->extra_data
);
63 static StringProperty
*
64 stringprop_copy(StringProperty
*src
)
66 StringProperty
*prop
=
67 (StringProperty
*)src
->common
.ops
->new_prop(src
->common
.descr
,
69 copy_init_property(&prop
->common
,&src
->common
);
71 prop
->string_data
= g_strdup(src
->string_data
);
73 prop
->string_data
= NULL
;
74 prop
->num_lines
= src
->num_lines
;
79 stringprop_free(StringProperty
*prop
)
81 g_free(prop
->string_data
);
86 stringprop_get_widget(StringProperty
*prop
, PropDialog
*dialog
)
88 GtkWidget
*ret
= gtk_entry_new();
89 prophandler_connect(&prop
->common
,GTK_OBJECT(ret
),"changed");
94 stringprop_reset_widget(StringProperty
*prop
, GtkWidget
*widget
)
96 gtk_entry_set_text(GTK_ENTRY(widget
),
97 prop
->string_data
? prop
->string_data
: "");
101 stringprop_set_from_widget(StringProperty
*prop
, GtkWidget
*widget
)
103 g_free(prop
->string_data
);
105 g_strdup (gtk_entry_get_text (GTK_ENTRY(widget
)));
109 multistringprop_handle_key(GtkWidget
*wid
, GdkEventKey
*event
)
111 /** Normal textview doesn't grab return, so to avoid closing the dialog...*/
112 /** Actually, this doesn't seem to work -- I guess the dialog closes
113 * becore this is called :(
115 if (event
->keyval
== GDK_Return
)
121 multistringprop_get_widget(StringProperty
*prop
, PropDialog
*dialog
)
123 GtkWidget
*ret
= gtk_text_view_new();
124 GtkWidget
*frame
= gtk_frame_new(NULL
);
125 gtk_frame_set_shadow_type(GTK_FRAME(frame
), GTK_SHADOW_IN
);
126 gtk_container_add(GTK_CONTAINER(frame
), ret
);
127 g_signal_connect(G_OBJECT(ret
), "key-release-event",
128 G_CALLBACK(multistringprop_handle_key
), NULL
);
129 gtk_widget_show(ret
);
130 prophandler_connect(&prop
->common
,GTK_OBJECT(ret
),"changed");
135 multistringprop_reset_widget(StringProperty
*prop
, GtkWidget
*widget
)
137 GtkWidget
*textview
= gtk_bin_get_child(GTK_BIN(widget
));
138 GtkTextBuffer
*buffer
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview
));
139 gtk_text_buffer_set_text(buffer
,
140 prop
->string_data
? prop
->string_data
: "", -1);
144 multistringprop_set_from_widget(StringProperty
*prop
, GtkWidget
*widget
) {
145 GtkWidget
*textview
= gtk_bin_get_child(GTK_BIN(widget
));
146 GtkTextBuffer
*buffer
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview
));
147 GtkTextIter start
, end
;
148 gtk_text_buffer_get_start_iter(buffer
, &start
);
149 gtk_text_buffer_get_end_iter(buffer
, &end
);
150 g_free(prop
->string_data
);
152 g_strdup (gtk_text_buffer_get_text (buffer
, &start
, &end
, TRUE
));
156 fileprop_get_widget(StringProperty
*prop
, PropDialog
*dialog
)
158 GtkWidget
*ret
= dia_file_selector_new();
159 prophandler_connect(&prop
->common
,GTK_OBJECT(ret
),"FIXME");
164 fileprop_reset_widget(StringProperty
*prop
, GtkWidget
*widget
)
166 dia_file_selector_set_file(DIAFILESELECTOR(widget
),prop
->string_data
);
170 fileprop_set_from_widget(StringProperty
*prop
, GtkWidget
*widget
)
172 g_free(prop
->string_data
);
174 g_strdup(dia_file_selector_get_file(DIAFILESELECTOR(widget
)));
178 stringprop_load(StringProperty
*prop
, AttributeNode attr
, DataNode data
)
180 g_free(prop
->string_data
);
181 prop
->string_data
= data_string(data
);
182 if (prop
->string_data
== NULL
) {
183 prop
->string_data
= g_strdup("");
188 stringprop_save(StringProperty
*prop
, AttributeNode attr
)
190 data_add_string(attr
, prop
->string_data
);
194 stringprop_get_from_offset(StringProperty
*prop
,
195 void *base
, guint offset
, guint offset2
)
197 g_free(prop
->string_data
);
198 prop
->string_data
= g_strdup(struct_member(base
,offset
,gchar
*));
202 stringprop_set_from_offset(StringProperty
*prop
,
203 void *base
, guint offset
, guint offset2
)
205 g_free(struct_member(base
,offset
,gchar
*));
206 struct_member(base
,offset
,gchar
*) = g_strdup(prop
->string_data
);
210 stringprop_get_data_size(StringProperty
*prop
)
212 return sizeof (prop
->string_data
); /* only the pointer */
215 static StringListProperty
*
216 stringlistprop_new(const PropDescription
*pdesc
, PropDescToPropPredicate reason
)
218 StringListProperty
*prop
= g_new0(StringListProperty
,1);
219 initialize_property(&prop
->common
,pdesc
,reason
);
220 prop
->string_list
= NULL
;
225 stringlistprop_free(StringListProperty
*prop
)
227 g_list_foreach(prop
->string_list
, (GFunc
)g_free
, NULL
);
228 g_list_free(prop
->string_list
);
232 static StringListProperty
*
233 stringlistprop_copy(StringListProperty
*src
)
235 StringListProperty
*prop
=
236 (StringListProperty
*)src
->common
.ops
->new_prop(src
->common
.descr
,
238 copy_init_property(&prop
->common
,&src
->common
);
239 if (src
->string_list
) {
242 for (tmp
= src
->string_list
; tmp
!= NULL
; tmp
= tmp
->next
)
243 prop
->string_list
= g_list_append(prop
->string_list
, g_strdup(tmp
->data
));
246 prop
->string_list
= NULL
;
251 stringlistprop_load(StringListProperty
*prop
, AttributeNode attr
, DataNode data
)
253 g_warning("stringlistprop_load not implemented");
257 stringlistprop_save(StringProperty
*prop
, AttributeNode attr
)
259 g_warning("stringlistprop_save not implemented");
263 stringlistprop_get_from_offset(StringListProperty
*prop
,
264 void *base
, guint offset
, guint offset2
)
266 GList
*tmp
, *lst
= prop
->string_list
;
268 g_list_foreach(lst
, (GFunc
)g_free
, NULL
);
270 for (tmp
= struct_member(base
,offset
,GList
*); tmp
!= NULL
; tmp
= tmp
->next
)
271 lst
= g_list_append(lst
, g_strdup(tmp
->data
));
272 prop
->string_list
= lst
;
276 stringlistprop_set_from_offset(StringListProperty
*prop
,
277 void *base
, guint offset
, guint offset2
)
279 GList
*tmp
, *lst
= struct_member(base
,offset
,GList
*);
281 g_list_foreach(lst
, (GFunc
)g_free
, NULL
);
283 for (tmp
= prop
->string_list
; tmp
!= NULL
; tmp
= tmp
->next
)
284 lst
= g_list_append(lst
, g_strdup(tmp
->data
));
285 struct_member(base
,offset
,GList
*) = lst
;
288 static const PropertyOps stringprop_ops
= {
289 (PropertyType_New
) stringprop_new
,
290 (PropertyType_Free
) stringprop_free
,
291 (PropertyType_Copy
) stringprop_copy
,
292 (PropertyType_Load
) stringprop_load
,
293 (PropertyType_Save
) stringprop_save
,
294 (PropertyType_GetWidget
) stringprop_get_widget
,
295 (PropertyType_ResetWidget
) stringprop_reset_widget
,
296 (PropertyType_SetFromWidget
) stringprop_set_from_widget
,
298 (PropertyType_CanMerge
) noopprop_can_merge
,
299 (PropertyType_GetFromOffset
) stringprop_get_from_offset
,
300 (PropertyType_SetFromOffset
) stringprop_set_from_offset
,
301 (PropertyType_GetDataSize
) stringprop_get_data_size
304 static const PropertyOps stringlistprop_ops
= {
305 (PropertyType_New
) stringlistprop_new
,
306 (PropertyType_Free
) stringlistprop_free
,
307 (PropertyType_Copy
) stringlistprop_copy
,
308 (PropertyType_Load
) stringlistprop_load
,
309 (PropertyType_Save
) stringlistprop_save
,
310 (PropertyType_GetWidget
) noopprop_get_widget
,
311 (PropertyType_ResetWidget
) noopprop_reset_widget
,
312 (PropertyType_SetFromWidget
) noopprop_set_from_widget
,
314 (PropertyType_CanMerge
) noopprop_can_merge
,
315 (PropertyType_GetFromOffset
) stringlistprop_get_from_offset
,
316 (PropertyType_SetFromOffset
) stringlistprop_set_from_offset
319 static const PropertyOps multistringprop_ops
= {
320 (PropertyType_New
) multistringprop_new
,
321 (PropertyType_Free
) stringprop_free
,
322 (PropertyType_Copy
) stringprop_copy
,
323 (PropertyType_Load
) stringprop_load
,
324 (PropertyType_Save
) stringprop_save
,
325 (PropertyType_GetWidget
) multistringprop_get_widget
,
326 (PropertyType_ResetWidget
) multistringprop_reset_widget
,
327 (PropertyType_SetFromWidget
) multistringprop_set_from_widget
,
329 (PropertyType_CanMerge
) noopprop_can_merge
,
330 (PropertyType_GetFromOffset
) stringprop_get_from_offset
,
331 (PropertyType_SetFromOffset
) stringprop_set_from_offset
334 static const PropertyOps fileprop_ops
= {
335 (PropertyType_New
) stringprop_new
,
336 (PropertyType_Free
) stringprop_free
,
337 (PropertyType_Copy
) stringprop_copy
,
338 (PropertyType_Load
) stringprop_load
,
339 (PropertyType_Save
) stringprop_save
,
340 (PropertyType_GetWidget
) fileprop_get_widget
,
341 (PropertyType_ResetWidget
) fileprop_reset_widget
,
342 (PropertyType_SetFromWidget
) fileprop_set_from_widget
,
344 (PropertyType_CanMerge
) noopprop_can_merge
,
345 (PropertyType_GetFromOffset
) stringprop_get_from_offset
,
346 (PropertyType_SetFromOffset
) stringprop_set_from_offset
349 /***************************/
350 /* The TEXT property type. */
351 /***************************/
353 static TextProperty
*
354 textprop_new(const PropDescription
*pdesc
, PropDescToPropPredicate reason
)
356 TextProperty
*prop
= g_new0(TextProperty
,1);
357 initialize_property(&prop
->common
,pdesc
,reason
);
358 prop
->text_data
= NULL
;
362 static TextProperty
*
363 textprop_copy(TextProperty
*src
)
366 (TextProperty
*)src
->common
.ops
->new_prop(src
->common
.descr
,
368 copy_init_property(&prop
->common
,&src
->common
);
370 prop
->text_data
= g_strdup(src
->text_data
);
372 prop
->text_data
= NULL
;
377 textprop_free(TextProperty
*prop
)
379 g_free(prop
->text_data
);
384 textprop_load(TextProperty
*prop
, AttributeNode attr
, DataNode data
)
387 g_free(prop
->text_data
);
388 text
= data_text(data
);
389 text_get_attributes(text
,&prop
->attr
);
390 prop
->text_data
= text_get_string_copy(text
);
395 textprop_save(TextProperty
*prop
, AttributeNode attr
)
397 Text
*text
= new_text(prop
->text_data
,
400 &prop
->attr
.position
,
402 prop
->attr
.alignment
);
403 data_add_text(attr
,text
);
408 textprop_get_from_offset(TextProperty
*prop
,
409 void *base
, guint offset
, guint offset2
)
411 Text
*text
= struct_member(base
,offset
,Text
*);
412 g_free(prop
->text_data
);
413 prop
->text_data
= text_get_string_copy(text
);
414 text_get_attributes(text
,&prop
->attr
);
418 textprop_set_from_offset(TextProperty
*prop
,
419 void *base
, guint offset
, guint offset2
)
421 Text
*text
= struct_member(base
,offset
,Text
*);
422 text_set_string(text
,prop
->text_data
);
423 text_set_attributes(text
,&prop
->attr
);
426 static const PropertyOps textprop_ops
= {
427 (PropertyType_New
) textprop_new
,
428 (PropertyType_Free
) textprop_free
,
429 (PropertyType_Copy
) textprop_copy
,
430 (PropertyType_Load
) textprop_load
,
431 (PropertyType_Save
) textprop_save
,
432 (PropertyType_GetWidget
) noopprop_get_widget
,
433 (PropertyType_ResetWidget
) noopprop_reset_widget
,
434 (PropertyType_SetFromWidget
) noopprop_set_from_widget
,
436 (PropertyType_CanMerge
) noopprop_can_merge
,
437 (PropertyType_GetFromOffset
) textprop_get_from_offset
,
438 (PropertyType_SetFromOffset
) textprop_set_from_offset
441 /* ************************************************************** */
444 prop_text_register(void)
446 prop_type_register(PROP_TYPE_STRING
,&stringprop_ops
);
447 prop_type_register(PROP_TYPE_STRINGLIST
,&stringlistprop_ops
);
448 prop_type_register(PROP_TYPE_MULTISTRING
,&multistringprop_ops
);
449 prop_type_register(PROP_TYPE_FILE
,&fileprop_ops
);
450 prop_type_register(PROP_TYPE_TEXT
,&textprop_ops
);
454 * Return a diplayable name for the object
457 object_get_displayname (DiaObject
* object
)
460 Property
*prop
= NULL
;
463 return g_strdup ("<null>"); /* should not happen */
465 if (IS_GROUP(object
))
466 name
= g_strdup_printf (_("Group with %d objects"), g_list_length(group_objects(object
)));
467 else if ((prop
= object_prop_by_name(object
, "name")) != NULL
)
468 name
= g_strdup (((StringProperty
*)prop
)->string_data
);
469 else if ((prop
= object_prop_by_name(object
, "text")) != NULL
)
470 name
= g_strdup (((TextProperty
*)prop
)->text_data
);
473 name
= g_strdup (object
->type
->name
);
476 prop
->ops
->free(prop
);
478 name
= g_strdelimit (name
, "\n", ' ');