* added GDK_PIXBUF_LIBS in order to create pixbuf.dll
[dia.git] / lib / prop_widgets.c
blobfda398f069aaff0d282715df98d79b81f4afc2f6
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 info->frame = frame;
135 info->unfoldbutton = unfoldbutton;
137 gtk_frame_set_label_widget(GTK_FRAME(frame), foldbutton);
139 gtk_container_set_border_width (GTK_CONTAINER(frame), 2);
140 gtk_container_add(GTK_CONTAINER(frame),vbox);
141 gtk_widget_show(foldbutton);
142 gtk_widget_show(frame);
143 gtk_widget_show(vbox);
145 prop_dialog_add_raw(dialog, frame);
147 prop_dialog_add_raw_with_flags(dialog, unfoldbutton, FALSE, FALSE);
149 gtk_signal_connect(GTK_OBJECT(foldbutton), "clicked",
150 GTK_SIGNAL_FUNC(frame_fold_unfold), info);
151 gtk_signal_connect(GTK_OBJECT(unfoldbutton), "clicked",
152 GTK_SIGNAL_FUNC(frame_fold_unfold), info);
154 prop_dialog_container_push(dialog,vbox);
156 return NULL; /* there is no single widget to add with a label next to it. */
159 static WIDGET *
160 frame_endprop_get_widget(FrameProperty *prop, PropDialog *dialog)
162 prop_dialog_container_pop(dialog);
163 return NULL;
166 static const PropertyOps frame_beginprop_ops = {
167 (PropertyType_New) noopprop_new,
168 (PropertyType_Free) noopprop_free,
169 (PropertyType_Copy) noopprop_copy,
170 (PropertyType_Load) invalidprop_load,
171 (PropertyType_Save) invalidprop_save,
172 (PropertyType_GetWidget) frame_beginprop_get_widget,
173 (PropertyType_ResetWidget) noopprop_reset_widget,
174 (PropertyType_SetFromWidget) noopprop_set_from_widget,
176 (PropertyType_CanMerge) noopprop_can_merge,
177 (PropertyType_GetFromOffset) noopprop_get_from_offset,
178 (PropertyType_SetFromOffset) noopprop_set_from_offset
181 static const PropertyOps frame_endprop_ops = {
182 (PropertyType_New) noopprop_new,
183 (PropertyType_Free) noopprop_free,
184 (PropertyType_Copy) noopprop_copy,
185 (PropertyType_Load) invalidprop_load,
186 (PropertyType_Save) invalidprop_save,
187 (PropertyType_GetWidget) frame_endprop_get_widget,
188 (PropertyType_ResetWidget) noopprop_reset_widget,
189 (PropertyType_SetFromWidget) noopprop_set_from_widget,
191 (PropertyType_CanMerge) noopprop_can_merge,
192 (PropertyType_GetFromOffset) noopprop_get_from_offset,
193 (PropertyType_SetFromOffset) noopprop_set_from_offset
196 /*********************************************************/
197 /* The MULTICOL_BEGIN, _COLUMN and _END property types. */
198 /*********************************************************/
200 static WIDGET *
201 multicol_beginprop_get_widget(MulticolProperty *prop, PropDialog *dialog)
203 GtkWidget *multicol = gtk_hbox_new(FALSE,1);
205 gtk_container_set_border_width (GTK_CONTAINER(multicol), 2);
206 gtk_widget_show(multicol);
208 prop_dialog_add_raw(dialog,multicol);
210 prop_dialog_container_push(dialog,multicol);
211 prop_dialog_container_push(dialog,NULL); /* there must be a _COLUMN soon */
213 return NULL; /* there is no single widget to add with a label next to it. */
216 static WIDGET *
217 multicol_columnprop_get_widget(MulticolProperty *prop, PropDialog *dialog)
219 GtkWidget *col = gtk_vbox_new(FALSE,1);
221 gtk_container_set_border_width (GTK_CONTAINER(col), 2);
222 gtk_widget_show(col);
224 prop_dialog_container_pop(dialog); /* NULL or the previous column */
226 gtk_box_pack_end_defaults(GTK_BOX(dialog->lastcont),col);
228 prop_dialog_add_raw(dialog,NULL); /* to reset the internal table system */
229 prop_dialog_container_push(dialog,col);
231 return NULL;
234 static WIDGET *
235 multicol_endprop_get_widget(MulticolProperty *prop, PropDialog *dialog)
237 prop_dialog_container_pop(dialog); /* the column */
238 prop_dialog_container_pop(dialog); /* the multicol */
239 return NULL;
242 static const PropertyOps multicol_beginprop_ops = {
243 (PropertyType_New) noopprop_new,
244 (PropertyType_Free) noopprop_free,
245 (PropertyType_Copy) noopprop_copy,
246 (PropertyType_Load) invalidprop_load,
247 (PropertyType_Save) invalidprop_save,
248 (PropertyType_GetWidget) multicol_beginprop_get_widget,
249 (PropertyType_ResetWidget) noopprop_reset_widget,
250 (PropertyType_SetFromWidget) noopprop_set_from_widget,
252 (PropertyType_CanMerge) noopprop_can_merge,
253 (PropertyType_GetFromOffset) noopprop_get_from_offset,
254 (PropertyType_SetFromOffset) noopprop_set_from_offset
257 static const PropertyOps multicol_columnprop_ops = {
258 (PropertyType_New) noopprop_new,
259 (PropertyType_Free) noopprop_free,
260 (PropertyType_Copy) noopprop_copy,
261 (PropertyType_Load) invalidprop_load,
262 (PropertyType_Save) invalidprop_save,
263 (PropertyType_GetWidget) multicol_columnprop_get_widget,
264 (PropertyType_ResetWidget) noopprop_reset_widget,
265 (PropertyType_SetFromWidget) noopprop_set_from_widget,
267 (PropertyType_CanMerge) noopprop_can_merge,
268 (PropertyType_GetFromOffset) noopprop_get_from_offset,
269 (PropertyType_SetFromOffset) noopprop_set_from_offset
272 static const PropertyOps multicol_endprop_ops = {
273 (PropertyType_New) noopprop_new,
274 (PropertyType_Free) noopprop_free,
275 (PropertyType_Copy) noopprop_copy,
276 (PropertyType_Load) invalidprop_load,
277 (PropertyType_Save) invalidprop_save,
278 (PropertyType_GetWidget) multicol_endprop_get_widget,
279 (PropertyType_ResetWidget) noopprop_reset_widget,
280 (PropertyType_SetFromWidget) noopprop_set_from_widget,
282 (PropertyType_CanMerge) noopprop_can_merge,
283 (PropertyType_GetFromOffset) noopprop_get_from_offset,
284 (PropertyType_SetFromOffset) noopprop_set_from_offset
287 /*********************************************************/
288 /* The NOTEBOOK_BEGIN, _PAGE and _END property types. */
289 /*********************************************************/
291 static WIDGET *
292 notebook_beginprop_get_widget(NotebookProperty *prop, PropDialog *dialog)
294 GtkWidget *notebook = gtk_notebook_new();
296 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook),GTK_POS_TOP);
297 gtk_container_set_border_width (GTK_CONTAINER(notebook), 1);
298 gtk_widget_show(notebook);
300 prop_dialog_add_raw(dialog,notebook);
302 prop_dialog_container_push(dialog,notebook);
303 prop_dialog_container_push(dialog,NULL); /* there must be a _PAGE soon */
305 return NULL; /* there is no single widget to add with a label next to it. */
308 static WIDGET *
309 notebook_pageprop_get_widget(NotebookProperty *prop, PropDialog *dialog)
311 GtkWidget *page = gtk_vbox_new(FALSE,1);
312 GtkWidget *label = gtk_label_new(_(prop->common.descr->description));
314 gtk_container_set_border_width (GTK_CONTAINER(page), 2);
315 gtk_widget_show(page);
316 gtk_widget_show(label);
318 prop_dialog_container_pop(dialog); /* NULL or the previous page */
320 gtk_notebook_append_page(GTK_NOTEBOOK(dialog->lastcont),page,label);
322 prop_dialog_add_raw(dialog,NULL); /* to reset the internal table system */
323 prop_dialog_container_push(dialog,page);
325 return NULL;
328 static WIDGET *
329 notebook_endprop_get_widget(NotebookProperty *prop, PropDialog *dialog)
331 prop_dialog_container_pop(dialog); /* the page */
332 prop_dialog_container_pop(dialog); /* the notebook */
333 return NULL;
336 static const PropertyOps notebook_beginprop_ops = {
337 (PropertyType_New) noopprop_new,
338 (PropertyType_Free) noopprop_free,
339 (PropertyType_Copy) noopprop_copy,
340 (PropertyType_Load) invalidprop_load,
341 (PropertyType_Save) invalidprop_save,
342 (PropertyType_GetWidget) notebook_beginprop_get_widget,
343 (PropertyType_ResetWidget) noopprop_reset_widget,
344 (PropertyType_SetFromWidget) noopprop_set_from_widget,
346 (PropertyType_CanMerge) noopprop_can_merge,
347 (PropertyType_GetFromOffset) noopprop_get_from_offset,
348 (PropertyType_SetFromOffset) noopprop_set_from_offset
351 static const PropertyOps notebook_pageprop_ops = {
352 (PropertyType_New) noopprop_new,
353 (PropertyType_Free) noopprop_free,
354 (PropertyType_Copy) noopprop_copy,
355 (PropertyType_Load) invalidprop_load,
356 (PropertyType_Save) invalidprop_save,
357 (PropertyType_GetWidget) notebook_pageprop_get_widget,
358 (PropertyType_ResetWidget) noopprop_reset_widget,
359 (PropertyType_SetFromWidget) noopprop_set_from_widget,
361 (PropertyType_CanMerge) noopprop_can_merge,
362 (PropertyType_GetFromOffset) noopprop_get_from_offset,
363 (PropertyType_SetFromOffset) noopprop_set_from_offset
366 static const PropertyOps notebook_endprop_ops = {
367 (PropertyType_New) noopprop_new,
368 (PropertyType_Free) noopprop_free,
369 (PropertyType_Copy) noopprop_copy,
370 (PropertyType_Load) invalidprop_load,
371 (PropertyType_Save) invalidprop_save,
372 (PropertyType_GetWidget) notebook_endprop_get_widget,
373 (PropertyType_ResetWidget) noopprop_reset_widget,
374 (PropertyType_SetFromWidget) noopprop_set_from_widget,
376 (PropertyType_CanMerge) noopprop_can_merge,
377 (PropertyType_GetFromOffset) noopprop_get_from_offset,
378 (PropertyType_SetFromOffset) noopprop_set_from_offset
381 /****************************/
382 /* The LIST property type. */
383 /****************************/
385 static void
386 listprop_emptylines_realloc(ListProperty *prop,guint new_size) {
387 guint i;
389 for (i = 0; i < prop->lines->len; i++)
390 g_free(g_ptr_array_index(prop->lines,i));
391 if (new_size >= 0)
392 g_ptr_array_set_size(prop->lines,new_size);
395 static void
396 listprop_copylines(ListProperty *prop, GPtrArray *src) {
397 guint i;
399 listprop_emptylines_realloc(prop,src->len);
401 for (i = 0; i < src->len; i++)
402 g_ptr_array_index(prop->lines,i) = g_strdup(g_ptr_array_index(src,i));
405 static ListProperty *
406 listprop_new(const PropDescription *pdesc, PropDescToPropPredicate reason)
408 ListProperty *prop = g_new0(ListProperty,1);
409 initialize_property(&prop->common,pdesc,reason);
410 prop->selected = -1;
411 prop->w_selected = -1;
412 prop->lines = g_ptr_array_new();
413 return prop;
416 static void
417 listprop_free(ListProperty *prop)
419 listprop_emptylines_realloc(prop,-1);
420 g_ptr_array_free(prop->lines,TRUE);
423 static ListProperty *
424 listprop_copy(ListProperty *src)
426 ListProperty *prop =
427 (ListProperty *)src->common.ops->new_prop(src->common.descr,
428 src->common.reason);
430 copy_init_property(&prop->common,&src->common);
431 prop->selected = src->selected;
432 prop->w_selected = src->w_selected;
433 listprop_copylines(prop,src->lines);
435 return prop;
438 static void
439 listprop_select_child_signal(GtkList *list,
440 GtkWidget *child,
441 ListProperty *prop)
443 prop->w_selected = gtk_list_child_position(list,child);
446 static WIDGET *
447 listprop_get_widget(ListProperty *prop, PropDialog *dialog)
449 GtkWidget *ret = gtk_list_new();
451 gtk_list_set_selection_mode(GTK_LIST(ret),GTK_SELECTION_BROWSE);
452 gtk_list_unselect_all(GTK_LIST(ret));
454 gtk_signal_connect(GTK_OBJECT(ret), "select-child",
455 GTK_SIGNAL_FUNC(listprop_select_child_signal), prop);
457 prophandler_connect(&prop->common,GTK_OBJECT(ret),"selection-changed");
458 return ret;
461 static GtkWidget *
462 make_item(const gchar *line) {
463 return gtk_list_item_new_with_label(line);
466 static void
467 listprop_reset_widget(ListProperty *prop, WIDGET *widget)
469 guint i;
470 GList *items = NULL;
471 gtk_list_clear_items(GTK_LIST(widget),0,-1);
473 for (i = 0; i < prop->lines->len; i++) {
474 items = g_list_append(items, make_item(g_ptr_array_index(prop->lines,i)));
476 gtk_list_append_items(GTK_LIST(widget),items);
477 prop->w_selected = prop->selected;
478 gtk_list_select_item(GTK_LIST(widget),prop->selected);
481 static void
482 listprop_set_from_widget(ListProperty *prop, WIDGET *widget)
484 prop->selected = prop->w_selected;
487 static void
488 listprop_get_from_offset(ListProperty *prop,
489 void *base, guint offset, guint offset2)
491 listprop_copylines(prop,struct_member(base,offset, GPtrArray *));
492 prop->selected = struct_member(base,offset2,gint);
495 static void
496 listprop_set_from_offset(ListProperty *prop,
497 void *base, guint offset, guint offset2)
499 struct_member(base,offset2,gint) = prop->selected;
502 static const PropertyOps listprop_ops = {
503 (PropertyType_New) listprop_new,
504 (PropertyType_Free) listprop_free,
505 (PropertyType_Copy) listprop_copy,
507 (PropertyType_Load) invalidprop_load,
508 (PropertyType_Save) invalidprop_save,
510 (PropertyType_GetWidget) listprop_get_widget,
511 (PropertyType_ResetWidget) listprop_reset_widget,
512 (PropertyType_SetFromWidget) listprop_set_from_widget,
514 (PropertyType_CanMerge) noopprop_can_merge,
515 (PropertyType_GetFromOffset) listprop_get_from_offset,
516 (PropertyType_SetFromOffset) listprop_set_from_offset
519 /* ************************************************************** */
521 void
522 prop_widgets_register(void)
524 prop_type_register(PROP_TYPE_STATIC,&staticprop_ops);
525 prop_type_register(PROP_TYPE_BUTTON,&buttonprop_ops);
526 prop_type_register(PROP_TYPE_FRAME_BEGIN,&frame_beginprop_ops);
527 prop_type_register(PROP_TYPE_FRAME_END,&frame_endprop_ops);
528 prop_type_register(PROP_TYPE_MULTICOL_BEGIN,&multicol_beginprop_ops);
529 prop_type_register(PROP_TYPE_MULTICOL_END,&multicol_endprop_ops);
530 prop_type_register(PROP_TYPE_MULTICOL_COLUMN,&multicol_columnprop_ops);
531 prop_type_register(PROP_TYPE_NOTEBOOK_BEGIN,&notebook_beginprop_ops);
532 prop_type_register(PROP_TYPE_NOTEBOOK_END,&notebook_endprop_ops);
533 prop_type_register(PROP_TYPE_NOTEBOOK_PAGE,&notebook_pageprop_ops);
534 prop_type_register(PROP_TYPE_LIST,&listprop_ops);