2006-12-03 Dimitris Glezos <dimitris@glezos.com>
[dia.git] / lib / prop_widgets.c
blobe217f6117c95cf95edc447cb2ca507bb5de6b6e8
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 "widget" types (static, buttons, notebooks, frames, etc.)
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.
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
29 #include <glib.h>
30 #undef GTK_DISABLE_DEPRECATED /* GtkList */
31 #include <gtk/gtk.h>
32 #define WIDGET GtkWidget
33 #include "widgets.h"
34 #include "properties.h"
35 #include "propinternals.h"
37 /******************************/
38 /* The STATIC property type. */
39 /******************************/
41 static WIDGET *
42 staticprop_get_widget(StaticProperty *prop, PropDialog *dialog)
44 GtkWidget *ret = NULL;
45 if (!prop->common.descr) return NULL;
47 ret = gtk_label_new(prop->common.descr->tooltip);
48 gtk_label_set_justify(GTK_LABEL(ret),GTK_JUSTIFY_LEFT);
49 return ret;
52 static const PropertyOps staticprop_ops = {
53 (PropertyType_New) noopprop_new,
54 (PropertyType_Free) noopprop_free,
55 (PropertyType_Copy) noopprop_copy,
56 (PropertyType_Load) invalidprop_load,
57 (PropertyType_Save) invalidprop_save,
58 (PropertyType_GetWidget) staticprop_get_widget,
59 (PropertyType_ResetWidget) noopprop_reset_widget,
60 (PropertyType_SetFromWidget) noopprop_set_from_widget,
62 (PropertyType_CanMerge) noopprop_can_merge,
63 (PropertyType_GetFromOffset) noopprop_get_from_offset,
64 (PropertyType_SetFromOffset) noopprop_set_from_offset
68 /******************************/
69 /* The BUTTON property type. */
70 /******************************/
72 static WIDGET *
73 buttonprop_get_widget(ButtonProperty *prop, PropDialog *dialog)
75 GtkWidget *ret = NULL;
76 if (!prop->common.descr) return NULL;
78 ret = gtk_button_new_with_label(_(prop->common.descr->tooltip));
79 prophandler_connect(&prop->common,GTK_OBJECT(ret),"clicked");
81 return ret;
84 static const PropertyOps buttonprop_ops = {
85 (PropertyType_New) noopprop_new,
86 (PropertyType_Free) noopprop_free,
87 (PropertyType_Copy) noopprop_copy,
88 (PropertyType_Load) invalidprop_load,
89 (PropertyType_Save) invalidprop_save,
90 (PropertyType_GetWidget) buttonprop_get_widget,
91 (PropertyType_ResetWidget) noopprop_reset_widget,
92 (PropertyType_SetFromWidget) noopprop_set_from_widget,
94 (PropertyType_CanMerge) noopprop_can_merge,
95 (PropertyType_GetFromOffset) noopprop_get_from_offset,
96 (PropertyType_SetFromOffset) noopprop_set_from_offset
99 /**************************************************/
100 /* The FRAME_BEGIN and FRAME_END property types. */
101 /**************************************************/
103 struct FoldButtonInfo {
104 GtkWidget *unfoldbutton;
105 GtkWidget *frame;
108 static void
109 frame_fold_unfold(GtkWidget *button1, gpointer userdata)
111 struct FoldButtonInfo *info = (struct FoldButtonInfo *)userdata;
113 if (button1 == info->unfoldbutton) {
114 gtk_widget_hide(info->unfoldbutton);
115 gtk_widget_show(info->frame);
116 } else {
117 gtk_widget_hide(info->frame);
118 gtk_widget_show(info->unfoldbutton);
122 static WIDGET *
123 frame_beginprop_get_widget(FrameProperty *prop, PropDialog *dialog)
125 gchar *foldstring = g_strdup_printf("%s <<<", prop->common.descr->description);
126 gchar *unfoldstring = g_strdup_printf("%s >>>", prop->common.descr->description);
127 GtkWidget *frame = gtk_frame_new(NULL);
128 GtkWidget *vbox = gtk_vbox_new(FALSE,2);
129 GtkWidget *foldbutton = gtk_button_new_with_label(foldstring);
130 GtkWidget *unfoldbutton = gtk_button_new_with_label(unfoldstring);
132 struct FoldButtonInfo *info = g_new(struct FoldButtonInfo, 1);
134 g_free(foldstring);
135 g_free(unfoldstring);
137 info->frame = frame;
138 info->unfoldbutton = unfoldbutton;
140 gtk_frame_set_label_widget(GTK_FRAME(frame), foldbutton);
142 gtk_container_set_border_width (GTK_CONTAINER(frame), 2);
143 gtk_container_add(GTK_CONTAINER(frame),vbox);
144 gtk_widget_show(foldbutton);
145 gtk_widget_show(frame);
146 gtk_widget_show(vbox);
148 prop_dialog_add_raw(dialog, frame);
150 prop_dialog_add_raw_with_flags(dialog, unfoldbutton, FALSE, FALSE);
152 gtk_signal_connect(GTK_OBJECT(foldbutton), "clicked",
153 GTK_SIGNAL_FUNC(frame_fold_unfold), info);
154 gtk_signal_connect(GTK_OBJECT(unfoldbutton), "clicked",
155 GTK_SIGNAL_FUNC(frame_fold_unfold), info);
157 prop_dialog_container_push(dialog,vbox);
159 return NULL; /* there is no single widget to add with a label next to it. */
162 static WIDGET *
163 frame_endprop_get_widget(FrameProperty *prop, PropDialog *dialog)
165 prop_dialog_container_pop(dialog);
166 return NULL;
169 static const PropertyOps frame_beginprop_ops = {
170 (PropertyType_New) noopprop_new,
171 (PropertyType_Free) noopprop_free,
172 (PropertyType_Copy) noopprop_copy,
173 (PropertyType_Load) invalidprop_load,
174 (PropertyType_Save) invalidprop_save,
175 (PropertyType_GetWidget) frame_beginprop_get_widget,
176 (PropertyType_ResetWidget) noopprop_reset_widget,
177 (PropertyType_SetFromWidget) noopprop_set_from_widget,
179 (PropertyType_CanMerge) noopprop_can_merge,
180 (PropertyType_GetFromOffset) noopprop_get_from_offset,
181 (PropertyType_SetFromOffset) noopprop_set_from_offset
184 static const PropertyOps frame_endprop_ops = {
185 (PropertyType_New) noopprop_new,
186 (PropertyType_Free) noopprop_free,
187 (PropertyType_Copy) noopprop_copy,
188 (PropertyType_Load) invalidprop_load,
189 (PropertyType_Save) invalidprop_save,
190 (PropertyType_GetWidget) frame_endprop_get_widget,
191 (PropertyType_ResetWidget) noopprop_reset_widget,
192 (PropertyType_SetFromWidget) noopprop_set_from_widget,
194 (PropertyType_CanMerge) noopprop_can_merge,
195 (PropertyType_GetFromOffset) noopprop_get_from_offset,
196 (PropertyType_SetFromOffset) noopprop_set_from_offset
199 /*********************************************************/
200 /* The MULTICOL_BEGIN, _COLUMN and _END property types. */
201 /*********************************************************/
203 static WIDGET *
204 multicol_beginprop_get_widget(MulticolProperty *prop, PropDialog *dialog)
206 GtkWidget *multicol = gtk_hbox_new(FALSE,1);
208 gtk_container_set_border_width (GTK_CONTAINER(multicol), 2);
209 gtk_widget_show(multicol);
211 prop_dialog_add_raw(dialog,multicol);
213 prop_dialog_container_push(dialog,multicol);
214 prop_dialog_container_push(dialog,NULL); /* there must be a _COLUMN soon */
216 return NULL; /* there is no single widget to add with a label next to it. */
219 static WIDGET *
220 multicol_columnprop_get_widget(MulticolProperty *prop, PropDialog *dialog)
222 GtkWidget *col = gtk_vbox_new(FALSE,1);
224 gtk_container_set_border_width (GTK_CONTAINER(col), 2);
225 gtk_widget_show(col);
227 prop_dialog_container_pop(dialog); /* NULL or the previous column */
229 gtk_box_pack_end_defaults(GTK_BOX(dialog->lastcont),col);
231 prop_dialog_add_raw(dialog,NULL); /* to reset the internal table system */
232 prop_dialog_container_push(dialog,col);
234 return NULL;
237 static WIDGET *
238 multicol_endprop_get_widget(MulticolProperty *prop, PropDialog *dialog)
240 prop_dialog_container_pop(dialog); /* the column */
241 prop_dialog_container_pop(dialog); /* the multicol */
242 return NULL;
245 static const PropertyOps multicol_beginprop_ops = {
246 (PropertyType_New) noopprop_new,
247 (PropertyType_Free) noopprop_free,
248 (PropertyType_Copy) noopprop_copy,
249 (PropertyType_Load) invalidprop_load,
250 (PropertyType_Save) invalidprop_save,
251 (PropertyType_GetWidget) multicol_beginprop_get_widget,
252 (PropertyType_ResetWidget) noopprop_reset_widget,
253 (PropertyType_SetFromWidget) noopprop_set_from_widget,
255 (PropertyType_CanMerge) noopprop_can_merge,
256 (PropertyType_GetFromOffset) noopprop_get_from_offset,
257 (PropertyType_SetFromOffset) noopprop_set_from_offset
260 static const PropertyOps multicol_columnprop_ops = {
261 (PropertyType_New) noopprop_new,
262 (PropertyType_Free) noopprop_free,
263 (PropertyType_Copy) noopprop_copy,
264 (PropertyType_Load) invalidprop_load,
265 (PropertyType_Save) invalidprop_save,
266 (PropertyType_GetWidget) multicol_columnprop_get_widget,
267 (PropertyType_ResetWidget) noopprop_reset_widget,
268 (PropertyType_SetFromWidget) noopprop_set_from_widget,
270 (PropertyType_CanMerge) noopprop_can_merge,
271 (PropertyType_GetFromOffset) noopprop_get_from_offset,
272 (PropertyType_SetFromOffset) noopprop_set_from_offset
275 static const PropertyOps multicol_endprop_ops = {
276 (PropertyType_New) noopprop_new,
277 (PropertyType_Free) noopprop_free,
278 (PropertyType_Copy) noopprop_copy,
279 (PropertyType_Load) invalidprop_load,
280 (PropertyType_Save) invalidprop_save,
281 (PropertyType_GetWidget) multicol_endprop_get_widget,
282 (PropertyType_ResetWidget) noopprop_reset_widget,
283 (PropertyType_SetFromWidget) noopprop_set_from_widget,
285 (PropertyType_CanMerge) noopprop_can_merge,
286 (PropertyType_GetFromOffset) noopprop_get_from_offset,
287 (PropertyType_SetFromOffset) noopprop_set_from_offset
290 /*********************************************************/
291 /* The NOTEBOOK_BEGIN, _PAGE and _END property types. */
292 /*********************************************************/
294 static WIDGET *
295 notebook_beginprop_get_widget(NotebookProperty *prop, PropDialog *dialog)
297 GtkWidget *notebook = gtk_notebook_new();
299 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook),GTK_POS_TOP);
300 gtk_container_set_border_width (GTK_CONTAINER(notebook), 1);
301 gtk_widget_show(notebook);
303 prop_dialog_add_raw(dialog,notebook);
305 prop_dialog_container_push(dialog,notebook);
306 prop_dialog_container_push(dialog,NULL); /* there must be a _PAGE soon */
308 return NULL; /* there is no single widget to add with a label next to it. */
311 static WIDGET *
312 notebook_pageprop_get_widget(NotebookProperty *prop, PropDialog *dialog)
314 GtkWidget *page = gtk_vbox_new(FALSE,1);
315 GtkWidget *label = gtk_label_new(_(prop->common.descr->description));
317 gtk_container_set_border_width (GTK_CONTAINER(page), 2);
318 gtk_widget_show(page);
319 gtk_widget_show(label);
321 prop_dialog_container_pop(dialog); /* NULL or the previous page */
323 gtk_notebook_append_page(GTK_NOTEBOOK(dialog->lastcont),page,label);
325 prop_dialog_add_raw(dialog,NULL); /* to reset the internal table system */
326 prop_dialog_container_push(dialog,page);
328 return NULL;
331 static WIDGET *
332 notebook_endprop_get_widget(NotebookProperty *prop, PropDialog *dialog)
334 prop_dialog_container_pop(dialog); /* the page */
335 prop_dialog_container_pop(dialog); /* the notebook */
336 return NULL;
339 static const PropertyOps notebook_beginprop_ops = {
340 (PropertyType_New) noopprop_new,
341 (PropertyType_Free) noopprop_free,
342 (PropertyType_Copy) noopprop_copy,
343 (PropertyType_Load) invalidprop_load,
344 (PropertyType_Save) invalidprop_save,
345 (PropertyType_GetWidget) notebook_beginprop_get_widget,
346 (PropertyType_ResetWidget) noopprop_reset_widget,
347 (PropertyType_SetFromWidget) noopprop_set_from_widget,
349 (PropertyType_CanMerge) noopprop_can_merge,
350 (PropertyType_GetFromOffset) noopprop_get_from_offset,
351 (PropertyType_SetFromOffset) noopprop_set_from_offset
354 static const PropertyOps notebook_pageprop_ops = {
355 (PropertyType_New) noopprop_new,
356 (PropertyType_Free) noopprop_free,
357 (PropertyType_Copy) noopprop_copy,
358 (PropertyType_Load) invalidprop_load,
359 (PropertyType_Save) invalidprop_save,
360 (PropertyType_GetWidget) notebook_pageprop_get_widget,
361 (PropertyType_ResetWidget) noopprop_reset_widget,
362 (PropertyType_SetFromWidget) noopprop_set_from_widget,
364 (PropertyType_CanMerge) noopprop_can_merge,
365 (PropertyType_GetFromOffset) noopprop_get_from_offset,
366 (PropertyType_SetFromOffset) noopprop_set_from_offset
369 static const PropertyOps notebook_endprop_ops = {
370 (PropertyType_New) noopprop_new,
371 (PropertyType_Free) noopprop_free,
372 (PropertyType_Copy) noopprop_copy,
373 (PropertyType_Load) invalidprop_load,
374 (PropertyType_Save) invalidprop_save,
375 (PropertyType_GetWidget) notebook_endprop_get_widget,
376 (PropertyType_ResetWidget) noopprop_reset_widget,
377 (PropertyType_SetFromWidget) noopprop_set_from_widget,
379 (PropertyType_CanMerge) noopprop_can_merge,
380 (PropertyType_GetFromOffset) noopprop_get_from_offset,
381 (PropertyType_SetFromOffset) noopprop_set_from_offset
384 /****************************/
385 /* The LIST property type. */
386 /****************************/
388 static void
389 listprop_emptylines_realloc(ListProperty *prop,guint new_size) {
390 guint i;
392 for (i = 0; i < prop->lines->len; i++)
393 g_free(g_ptr_array_index(prop->lines,i));
394 if (new_size >= 0)
395 g_ptr_array_set_size(prop->lines,new_size);
398 static void
399 listprop_copylines(ListProperty *prop, GPtrArray *src) {
400 guint i;
402 listprop_emptylines_realloc(prop,src->len);
404 for (i = 0; i < src->len; i++)
405 g_ptr_array_index(prop->lines,i) = g_strdup(g_ptr_array_index(src,i));
408 static ListProperty *
409 listprop_new(const PropDescription *pdesc, PropDescToPropPredicate reason)
411 ListProperty *prop = g_new0(ListProperty,1);
412 initialize_property(&prop->common,pdesc,reason);
413 prop->selected = -1;
414 prop->w_selected = -1;
415 prop->lines = g_ptr_array_new();
416 return prop;
419 static void
420 listprop_free(ListProperty *prop)
422 listprop_emptylines_realloc(prop,-1);
423 g_ptr_array_free(prop->lines,TRUE);
426 static ListProperty *
427 listprop_copy(ListProperty *src)
429 ListProperty *prop =
430 (ListProperty *)src->common.ops->new_prop(src->common.descr,
431 src->common.reason);
433 copy_init_property(&prop->common,&src->common);
434 prop->selected = src->selected;
435 prop->w_selected = src->w_selected;
436 listprop_copylines(prop,src->lines);
438 return prop;
441 static void
442 listprop_select_child_signal(GtkList *list,
443 GtkWidget *child,
444 ListProperty *prop)
446 prop->w_selected = gtk_list_child_position(list,child);
449 static WIDGET *
450 listprop_get_widget(ListProperty *prop, PropDialog *dialog)
452 GtkWidget *ret = gtk_list_new();
454 gtk_list_set_selection_mode(GTK_LIST(ret),GTK_SELECTION_BROWSE);
455 gtk_list_unselect_all(GTK_LIST(ret));
457 gtk_signal_connect(GTK_OBJECT(ret), "select-child",
458 GTK_SIGNAL_FUNC(listprop_select_child_signal), prop);
460 prophandler_connect(&prop->common,GTK_OBJECT(ret),"selection-changed");
461 return ret;
464 static GtkWidget *
465 make_item(const gchar *line) {
466 GtkWidget *item = gtk_list_item_new_with_label(line);
467 gtk_widget_show(item);
468 return item;
471 static void
472 listprop_reset_widget(ListProperty *prop, WIDGET *widget)
474 guint i;
475 GList *items = NULL;
476 gtk_list_clear_items(GTK_LIST(widget),0,-1);
478 for (i = 0; i < prop->lines->len; i++) {
479 items = g_list_append(items, make_item(g_ptr_array_index(prop->lines,i)));
481 gtk_list_append_items(GTK_LIST(widget),items);
482 prop->w_selected = prop->selected;
483 gtk_list_select_item(GTK_LIST(widget),prop->selected);
486 static void
487 listprop_set_from_widget(ListProperty *prop, WIDGET *widget)
489 prop->selected = prop->w_selected;
492 static void
493 listprop_get_from_offset(ListProperty *prop,
494 void *base, guint offset, guint offset2)
496 listprop_copylines(prop,struct_member(base,offset, GPtrArray *));
497 prop->selected = struct_member(base,offset2,gint);
500 static void
501 listprop_set_from_offset(ListProperty *prop,
502 void *base, guint offset, guint offset2)
504 struct_member(base,offset2,gint) = prop->selected;
507 static const PropertyOps listprop_ops = {
508 (PropertyType_New) listprop_new,
509 (PropertyType_Free) listprop_free,
510 (PropertyType_Copy) listprop_copy,
512 (PropertyType_Load) invalidprop_load,
513 (PropertyType_Save) invalidprop_save,
515 (PropertyType_GetWidget) listprop_get_widget,
516 (PropertyType_ResetWidget) listprop_reset_widget,
517 (PropertyType_SetFromWidget) listprop_set_from_widget,
519 (PropertyType_CanMerge) noopprop_can_merge,
520 (PropertyType_GetFromOffset) listprop_get_from_offset,
521 (PropertyType_SetFromOffset) listprop_set_from_offset
524 /* ************************************************************** */
526 void
527 prop_widgets_register(void)
529 prop_type_register(PROP_TYPE_STATIC,&staticprop_ops);
530 prop_type_register(PROP_TYPE_BUTTON,&buttonprop_ops);
531 prop_type_register(PROP_TYPE_FRAME_BEGIN,&frame_beginprop_ops);
532 prop_type_register(PROP_TYPE_FRAME_END,&frame_endprop_ops);
533 prop_type_register(PROP_TYPE_MULTICOL_BEGIN,&multicol_beginprop_ops);
534 prop_type_register(PROP_TYPE_MULTICOL_END,&multicol_endprop_ops);
535 prop_type_register(PROP_TYPE_MULTICOL_COLUMN,&multicol_columnprop_ops);
536 prop_type_register(PROP_TYPE_NOTEBOOK_BEGIN,&notebook_beginprop_ops);
537 prop_type_register(PROP_TYPE_NOTEBOOK_END,&notebook_endprop_ops);
538 prop_type_register(PROP_TYPE_NOTEBOOK_PAGE,&notebook_pageprop_ops);
539 prop_type_register(PROP_TYPE_LIST,&listprop_ops);