Signal patch
[dia.git] / lib / prop_text.c
blob3dafe114894b56ff92c6eec922dc726052354ca3
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.
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
30 #include <gtk/gtk.h>
31 #include <gdk/gdkkeysyms.h>
32 #include "widgets.h"
33 #include "properties.h"
34 #include "propinternals.h"
35 #include "text.h"
36 #include "group.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;
48 prop->num_lines = 1;
49 return prop;
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);
60 return prop;
63 static StringProperty *
64 stringprop_copy(StringProperty *src)
66 StringProperty *prop =
67 (StringProperty *)src->common.ops->new_prop(src->common.descr,
68 src->common.reason);
69 copy_init_property(&prop->common,&src->common);
70 if (src->string_data)
71 prop->string_data = g_strdup(src->string_data);
72 else
73 prop->string_data = NULL;
74 prop->num_lines = src->num_lines;
75 return prop;
78 static void
79 stringprop_free(StringProperty *prop)
81 g_free(prop->string_data);
82 g_free(prop);
85 static GtkWidget *
86 stringprop_get_widget(StringProperty *prop, PropDialog *dialog)
88 GtkWidget *ret = gtk_entry_new();
89 prophandler_connect(&prop->common,GTK_OBJECT(ret),"changed");
90 return ret;
93 static void
94 stringprop_reset_widget(StringProperty *prop, GtkWidget *widget)
96 gtk_entry_set_text(GTK_ENTRY(widget),
97 prop->string_data ? prop->string_data : "");
100 static void
101 stringprop_set_from_widget(StringProperty *prop, GtkWidget *widget)
103 g_free(prop->string_data);
104 prop->string_data =
105 g_strdup (gtk_entry_get_text (GTK_ENTRY(widget)));
108 static gboolean
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)
116 return TRUE;
117 return FALSE;
120 static GtkWidget *
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");
131 return frame;
134 static void
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);
143 static void
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);
151 prop->string_data =
152 g_strdup (gtk_text_buffer_get_text (buffer, &start, &end, TRUE));
155 static GtkWidget *
156 fileprop_get_widget(StringProperty *prop, PropDialog *dialog)
158 GtkWidget *ret = dia_file_selector_new();
159 prophandler_connect(&prop->common,GTK_OBJECT(ret),"FIXME");
160 return ret;
163 static void
164 fileprop_reset_widget(StringProperty *prop, GtkWidget *widget)
166 dia_file_selector_set_file(DIAFILESELECTOR(widget),prop->string_data);
169 static void
170 fileprop_set_from_widget(StringProperty *prop, GtkWidget *widget)
172 g_free(prop->string_data);
173 prop->string_data =
174 g_strdup(dia_file_selector_get_file(DIAFILESELECTOR(widget)));
177 static void
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("");
187 static void
188 stringprop_save(StringProperty *prop, AttributeNode attr)
190 data_add_string(attr, prop->string_data);
193 static void
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 *));
201 static void
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);
209 static int
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;
221 return prop;
224 static void
225 stringlistprop_free(StringListProperty *prop)
227 g_list_foreach(prop->string_list, (GFunc)g_free, NULL);
228 g_list_free(prop->string_list);
229 g_free(prop);
232 static StringListProperty *
233 stringlistprop_copy(StringListProperty *src)
235 StringListProperty *prop =
236 (StringListProperty *)src->common.ops->new_prop(src->common.descr,
237 src->common.reason);
238 copy_init_property(&prop->common,&src->common);
239 if (src->string_list) {
240 GList *tmp;
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));
245 else
246 prop->string_list = NULL;
247 return prop;
250 static void
251 stringlistprop_load(StringListProperty *prop, AttributeNode attr, DataNode data)
253 g_warning("stringlistprop_load not implemented");
256 static void
257 stringlistprop_save(StringProperty *prop, AttributeNode attr)
259 g_warning("stringlistprop_save not implemented");
262 static void
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);
269 g_list_free(lst);
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;
275 static void
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);
282 g_list_free(lst);
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;
359 return prop;
362 static TextProperty *
363 textprop_copy(TextProperty *src)
365 TextProperty *prop =
366 (TextProperty *)src->common.ops->new_prop(src->common.descr,
367 src->common.reason);
368 copy_init_property(&prop->common,&src->common);
369 if (src->text_data)
370 prop->text_data = g_strdup(src->text_data);
371 else
372 prop->text_data = NULL;
373 return prop;
376 static void
377 textprop_free(TextProperty *prop)
379 g_free(prop->text_data);
380 g_free(prop);
383 static void
384 textprop_load(TextProperty *prop, AttributeNode attr, DataNode data)
386 Text *text;
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);
391 text_destroy(text);
394 static void
395 textprop_save(TextProperty *prop, AttributeNode attr)
397 Text *text = new_text(prop->text_data,
398 prop->attr.font,
399 prop->attr.height,
400 &prop->attr.position,
401 &prop->attr.color,
402 prop->attr.alignment);
403 data_add_text(attr,text);
404 text_destroy(text);
407 static void
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);
417 static void
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 /* ************************************************************** */
443 void
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
456 gchar *
457 object_get_displayname (DiaObject* object)
459 gchar *name = NULL;
460 Property *prop = NULL;
462 if (!object)
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);
472 if (!name)
473 name = g_strdup (object->type->name);
475 if (prop)
476 prop->ops->free(prop);
478 name = g_strdelimit (name, "\n", ' ');
480 return name;