pre3 updates
[dia.git] / app / preferences.c
blobd1b3c4340fe86822303efacd648031c501c62d49
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1999 Alexander Larsson
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 #include <config.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 #ifdef HAVE_STDDEF_H
30 #include <stddef.h>
31 #endif
32 #include <locale.h>
34 #include <gtk/gtk.h>
36 #include "intl.h"
37 #include "widgets.h"
38 #include "diagram.h"
39 #include "message.h"
40 #include "preferences.h"
41 #include "dia_dirs.h"
42 #include "diagramdata.h"
43 #include "paper.h"
44 #include "interface.h"
46 #include "persistence.h"
48 #ifdef G_OS_WIN32
49 #include <io.h> /* open, close */
50 #endif
52 struct DiaPreferences prefs;
54 enum DiaPrefType {
55 PREF_NONE,
56 PREF_BOOLEAN,
57 PREF_INT,
58 PREF_UINT,
59 PREF_REAL,
60 PREF_UREAL,
61 PREF_COLOUR,
62 PREF_CHOICE,
63 PREF_STRING,
64 PREF_END_GROUP
67 typedef struct _DiaPrefData {
68 char *name;
69 enum DiaPrefType type;
70 int offset;
71 void *default_value;
72 int tab;
73 char *label_text;
74 GtkWidget *widget;
75 gboolean hidden;
76 GList *(*choice_list_function)();
77 /** A function to call after a preference item has been updated. */
78 void (*update_function)(struct _DiaPrefData *pref, char *ptr);
79 } DiaPrefData;
81 static void update_floating_toolbox(DiaPrefData *pref, char *ptr);
83 static int default_true = 1;
84 static int default_false = 0;
85 static int default_major_lines = 5;
86 static real default_real_one = 1.0;
87 static real default_real_zoom = 100.0;
88 static int default_int_w = 500;
89 static int default_int_h = 400;
90 static int default_undo_depth = 15;
91 static guint default_recent_documents = 5;
92 static Color default_colour = DEFAULT_GRID_COLOR;
93 static Color pbreak_colour = DEFAULT_PAGEBREAK_COLOR;
94 static guint default_dtree_dia_sort = DIA_TREE_SORT_INSERT;
95 static guint default_dtree_obj_sort = DIA_TREE_SORT_INSERT;
96 static const gchar *default_paper_name = NULL;
98 struct DiaPrefsTab {
99 char *title;
100 GtkTable *table;
101 int row;
104 struct DiaPrefsTab prefs_tabs[] =
106 {N_("User Interface"), NULL, 0},
107 {N_("Diagram Defaults"), NULL, 0},
108 {N_("View Defaults"), NULL, 0},
109 {N_("Grid Lines"), NULL, 0},
110 {N_("Diagram Tree"), NULL, 0},
113 #define NUM_PREFS_TABS (sizeof(prefs_tabs)/sizeof(struct DiaPrefsTab))
115 /* retrive a structure offset */
116 #ifdef offsetof
117 #define PREF_OFFSET(field) ((int) offsetof (struct DiaPreferences, field))
118 #else /* !offsetof */
119 #define PREF_OFFSET(field) ((int) ((char*) &((struct DiaPreferences *) 0)->field))
120 #endif /* !offsetof */
122 DiaPrefData prefs_data[] =
124 { "reset_tools_after_create", PREF_BOOLEAN, PREF_OFFSET(reset_tools_after_create), &default_true, 0, N_("Reset tools after create") },
125 { "compress_save", PREF_BOOLEAN, PREF_OFFSET(new_diagram.compress_save), &default_true, 0, N_("Compress saved files") },
126 { "undo_depth", PREF_UINT, PREF_OFFSET(undo_depth), &default_undo_depth, 0, N_("Number of undo levels:") },
127 { "reverse_rubberbanding_intersects", PREF_BOOLEAN, PREF_OFFSET(reverse_rubberbanding_intersects), &default_true, 0, N_("Reverse dragging selects\nintersecting objects") },
128 { "recent_documents_list_size", PREF_UINT, PREF_OFFSET(recent_documents_list_size), &default_recent_documents, 0, N_("Recent documents list size:") },
129 { "use_menu_bar", PREF_BOOLEAN, PREF_OFFSET(new_view.use_menu_bar), &default_true, 0, N_("Use menu bar") },
130 { "toolbox_on_top", PREF_BOOLEAN, PREF_OFFSET(toolbox_on_top),
131 &default_false, 0, N_("Keep tool box on top of diagram windows"),
132 NULL, FALSE, NULL, update_floating_toolbox},
134 { NULL, PREF_NONE, 0, NULL, 1, N_("New diagram:") },
135 { "is_portrait", PREF_BOOLEAN, PREF_OFFSET(new_diagram.is_portrait), &default_true, 1, N_("Portrait") },
136 { "new_diagram_papertype", PREF_CHOICE, PREF_OFFSET(new_diagram.papertype),
137 &default_paper_name, 1, N_("Paper type:"), NULL, FALSE,
138 get_paper_name_list },
139 { "new_diagram_bgcolour", PREF_COLOUR, PREF_OFFSET(new_diagram.bg_color),
140 &color_white, 1, N_("Background Color:") },
141 { NULL, PREF_END_GROUP, 0, NULL, 1, NULL },
143 { NULL, PREF_NONE, 0, NULL, 1, N_("New window:") },
144 { "new_view_width", PREF_UINT, PREF_OFFSET(new_view.width), &default_int_w, 1, N_("Width:") },
145 { "new_view_height", PREF_UINT, PREF_OFFSET(new_view.height), &default_int_h, 1, N_("Height:") },
146 { "new_view_zoom", PREF_UREAL, PREF_OFFSET(new_view.zoom), &default_real_zoom, 1, N_("Magnify:") },
147 { NULL, PREF_END_GROUP, 0, NULL, 1, NULL },
149 { NULL, PREF_NONE, 0, NULL, 1, N_("Connection Points:") },
150 { "show_cx_pts", PREF_BOOLEAN, PREF_OFFSET(show_cx_pts), &default_true, 1, N_("Visible") },
151 { NULL, PREF_END_GROUP, 0, NULL, 1, NULL },
153 { NULL, PREF_NONE, 0, NULL, 2, N_("Page breaks:") },
154 { "pagebreak_visible", PREF_BOOLEAN, PREF_OFFSET(pagebreak.visible), &default_true, 2, N_("Visible") },
155 { "pagebreak_colour", PREF_COLOUR, PREF_OFFSET(new_diagram.pagebreak_color), &pbreak_colour, 2, N_("Color:") },
156 { "pagebreak_solid", PREF_BOOLEAN, PREF_OFFSET(pagebreak.solid), &default_true, 2, N_("Solid lines") },
157 { NULL, PREF_END_GROUP, 0, NULL, 2, NULL },
159 /*{ NULL, PREF_NONE, 0, NULL, 3, N_("Grid:") }, */
160 { "grid_visible", PREF_BOOLEAN, PREF_OFFSET(grid.visible), &default_true, 3, N_("Visible") },
161 { "grid_snap", PREF_BOOLEAN, PREF_OFFSET(grid.snap), &default_false, 3, N_("Snap to") },
162 { "grid_dynamic", PREF_BOOLEAN, PREF_OFFSET(grid.dynamic), &default_true, 3, N_("Dynamic grid resizing") },
163 { "grid_x", PREF_UREAL, PREF_OFFSET(grid.x), &default_real_one, 3, N_("X Size:") },
164 { "grid_y", PREF_UREAL, PREF_OFFSET(grid.y), &default_real_one, 3, N_("Y Size:") },
165 { "grid_colour", PREF_COLOUR, PREF_OFFSET(new_diagram.grid_color), &default_colour, 3, N_("Color:") },
166 { "grid_major", PREF_UINT, PREF_OFFSET(grid.major_lines), &default_major_lines, 3, N_("Lines per major line") },
167 { "grid_hex", PREF_BOOLEAN, PREF_OFFSET(grid.hex), &default_false, 3, N_("Hex grid") },
168 { "grid_w", PREF_UREAL, PREF_OFFSET(grid.w), &default_real_one, 3, N_("Hex Size:")
170 /* { "grid_solid", PREF_BOOLEAN, PREF_OFFSET(grid.solid), &default_true, 3, N_("Solid lines:") }, */
172 { "render_bounding_boxes", PREF_BOOLEAN,PREF_OFFSET(render_bounding_boxes),
173 &default_false,0,"render bounding boxes",NULL, TRUE},
175 /* There's really no reason to not pertty format it, and allowing non-pretty
176 can lead to problems with long lines, CVS etc.
177 { "pretty_formated_xml", PREF_BOOLEAN,PREF_OFFSET(pretty_formated_xml),
178 &default_true,0,"pretty formated xml",NULL, TRUE},
181 { "prefer_psprint", PREF_BOOLEAN,PREF_OFFSET(prefer_psprint),
182 &default_false,0,"prefer psprint", NULL, TRUE},
184 { NULL, PREF_NONE, 0, NULL, 4, N_("Diagram tree window:") },
185 { "diagram_tree_save_hidden", PREF_BOOLEAN, PREF_OFFSET(dia_tree.save_hidden),
186 &default_false, 4, N_("Save hidden object types")},
187 { "diagram_tree_dia_sort", PREF_UINT, PREF_OFFSET(dia_tree.dia_sort),
188 &default_dtree_dia_sort, 4, "default diagram sort order", NULL, TRUE},
189 { "diagram_tree_obj_sort", PREF_UINT, PREF_OFFSET(dia_tree.obj_sort),
190 &default_dtree_obj_sort, 4, "default object sort order", NULL, TRUE},
191 { NULL, PREF_END_GROUP, 0, NULL, 4, NULL },
194 #define NUM_PREFS_DATA (sizeof(prefs_data)/sizeof(DiaPrefData))
196 static void prefs_create_dialog(void);
197 static void prefs_set_value_in_widget(GtkWidget * widget, DiaPrefData *data, char *ptr);
198 static void prefs_get_value_from_widget(GtkWidget * widget, DiaPrefData *data, char *ptr);
199 static void prefs_update_dialog_from_prefs(void);
200 static void prefs_update_prefs_from_dialog(void);
201 /* static gint prefs_apply(GtkWidget *widget, gpointer data); */
204 static GtkWidget *prefs_dialog = NULL;
206 void
207 prefs_show(void)
209 prefs_create_dialog();
210 gtk_widget_show(prefs_dialog);
212 prefs_update_dialog_from_prefs();
215 void
216 prefs_set_defaults(void)
218 int i;
219 char *ptr;
221 /* Since we can't call this in static initialization, we have to
222 * do it here.
224 if (default_paper_name == NULL)
225 default_paper_name = get_paper_name(get_default_paper());
227 for (i=0;i<NUM_PREFS_DATA;i++) {
228 ptr = (char *)&prefs + prefs_data[i].offset;
230 switch (prefs_data[i].type) {
231 case PREF_BOOLEAN:
232 *(int *)ptr = *(int *)prefs_data[i].default_value;
233 *(int *)ptr = persistence_register_boolean(prefs_data[i].name, *(int *)ptr);
234 break;
235 case PREF_INT:
236 case PREF_UINT:
237 *(int *)ptr = *(int *)prefs_data[i].default_value;
238 *(int *)ptr = persistence_register_integer(prefs_data[i].name, *(int *)ptr);
239 break;
240 case PREF_REAL:
241 case PREF_UREAL:
242 *(real *)ptr = *(real *)prefs_data[i].default_value;
243 *(real *)ptr = persistence_register_real(prefs_data[i].name, *(real *)ptr);
244 break;
245 case PREF_COLOUR:
246 *(Color *)ptr = *(Color *)prefs_data[i].default_value;
247 *(Color *)ptr = *persistence_register_color(prefs_data[i].name, (Color *)ptr);
248 break;
249 case PREF_CHOICE:
250 case PREF_STRING:
251 *(gchar **)ptr = *(gchar **)prefs_data[i].default_value;
252 *(gchar **)ptr = persistence_register_string(prefs_data[i].name, *(gchar **)ptr);
253 break;
254 case PREF_NONE:
255 case PREF_END_GROUP:
256 break;
261 void
262 prefs_save(void)
264 int i;
265 char *ptr;
266 for (i=0;i<NUM_PREFS_DATA;i++) {
267 if ((prefs_data[i].type == PREF_NONE) || (prefs_data[i].type == PREF_END_GROUP))
268 continue;
270 ptr = (char *)&prefs + prefs_data[i].offset;
272 switch (prefs_data[i].type) {
273 case PREF_BOOLEAN:
274 persistence_set_boolean(prefs_data[i].name, *(gint *)ptr);
275 break;
276 case PREF_INT:
277 case PREF_UINT:
278 persistence_set_integer(prefs_data[i].name, *(gint *)ptr);
279 break;
280 case PREF_REAL:
281 case PREF_UREAL:
283 persistence_set_real(prefs_data[i].name, *(real *)ptr);
284 break;
285 case PREF_COLOUR:
286 persistence_set_color(prefs_data[i].name, (Color *)ptr);
287 break;
288 case PREF_CHOICE:
289 case PREF_STRING:
290 persistence_set_string(prefs_data[i].name, *(gchar **)ptr);
291 break;
292 case PREF_NONE:
293 case PREF_END_GROUP:
294 break;
301 void
302 prefs_init(void)
304 prefs_set_defaults();
306 render_bounding_boxes = prefs.render_bounding_boxes;
309 static void
310 prefs_set_value_in_widget(GtkWidget * widget, DiaPrefData *data,
311 char *ptr)
313 switch(data->type) {
314 case PREF_BOOLEAN:
315 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), *((int *)ptr));
316 break;
317 case PREF_INT:
318 case PREF_UINT:
319 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget),
320 (gfloat) (*((int *)ptr)));
321 break;
322 case PREF_REAL:
323 case PREF_UREAL:
324 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget),
325 (gfloat) (*((real *)ptr)));
326 break;
327 case PREF_COLOUR:
328 dia_color_selector_set_color(widget, (Color *)ptr);
329 break;
330 case PREF_CHOICE: {
331 GList *names = (data->choice_list_function)();
332 int index;
333 for (index = 0; names != NULL; names = g_list_next(names), index++) {
334 if (!strcmp(*((gchar**)ptr), (gchar *)names->data))
335 break;
337 if (names == NULL) return;
338 gtk_option_menu_set_history(GTK_OPTION_MENU(widget), index);
339 gtk_menu_set_active(GTK_MENU(gtk_option_menu_get_menu(GTK_OPTION_MENU(widget))), index);
340 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(GTK_OPTION_MENU(widget))))), TRUE);
341 break;
343 case PREF_STRING:
344 gtk_entry_set_text(GTK_ENTRY(widget), (gchar *)(*((gchar **)ptr)));
345 break;
346 case PREF_NONE:
347 case PREF_END_GROUP:
348 break;
352 static void
353 prefs_get_value_from_widget(GtkWidget * widget, DiaPrefData *data,
354 char *ptr)
356 switch(data->type) {
357 case PREF_BOOLEAN:
358 *((int *)ptr) = GTK_TOGGLE_BUTTON(widget)->active;
359 break;
360 case PREF_INT:
361 case PREF_UINT:
362 *((int *)ptr) = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
363 break;
364 case PREF_REAL:
365 case PREF_UREAL:
366 *((real *)ptr) = (real)
367 gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(widget));
368 break;
369 case PREF_COLOUR:
370 dia_color_selector_get_color(widget, (Color *)ptr);
371 break;
372 case PREF_CHOICE: {
373 int index = gtk_option_menu_get_history(GTK_OPTION_MENU(widget));
374 GList *names = (data->choice_list_function)();
375 *((gchar **)ptr) = g_strdup((gchar *)g_list_nth_data(names, index));
376 break;
378 case PREF_STRING:
379 *((gchar **)ptr) = (gchar *)gtk_entry_get_text(GTK_ENTRY(widget));
380 break;
381 case PREF_NONE:
382 case PREF_END_GROUP:
383 break;
385 if (data->update_function != NULL) {
386 (data->update_function)(data, ptr);
390 static void
391 prefs_boolean_toggle(GtkWidget *widget, gpointer data)
393 guint active = GTK_TOGGLE_BUTTON(widget)->active;
394 gtk_button_set_label(GTK_BUTTON(widget), active ? _("Yes") : _("No"));
397 static GtkWidget *
398 prefs_get_property_widget(DiaPrefData *data)
400 GtkWidget *widget = NULL;
401 GtkAdjustment *adj;
403 switch(data->type) {
404 case PREF_BOOLEAN:
405 widget = gtk_toggle_button_new_with_label (_("No"));
406 g_signal_connect (GTK_OBJECT (widget), "toggled",
407 G_CALLBACK (prefs_boolean_toggle), NULL);
408 break;
409 case PREF_INT:
410 adj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0,
411 G_MININT, G_MAXINT,
412 1.0, 10.0, 10.0 ));
413 widget = gtk_spin_button_new (adj, 1.0, 0);
414 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(widget), TRUE);
415 gtk_widget_set_usize(widget, 80, -1);
416 break;
417 case PREF_UINT:
418 adj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0,
419 0.0, G_MAXINT,
420 1.0, 10.0, 10.0 ));
421 widget = gtk_spin_button_new (adj, 1.0, 0);
422 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(widget), TRUE);
423 gtk_widget_set_usize(widget, 80, -1);
424 break;
425 case PREF_REAL:
426 adj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0,
427 G_MINFLOAT, G_MAXFLOAT,
428 1.0, 10.0, 10.0 ));
429 widget = gtk_spin_button_new (adj, 1.0, 3);
430 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(widget), TRUE);
431 gtk_widget_set_usize(widget, 80, -1);
432 break;
433 case PREF_UREAL:
434 adj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0,
435 0.0, G_MAXFLOAT,
436 1.0, 10.0, 10.0 ));
437 widget = gtk_spin_button_new (adj, 1.0, 3);
438 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(widget), TRUE);
439 gtk_widget_set_usize(widget, 80, -1);
440 break;
441 case PREF_COLOUR:
442 widget = dia_color_selector_new();
443 break;
444 case PREF_STRING:
445 widget = gtk_entry_new();
446 break;
447 case PREF_CHOICE: {
448 GtkWidget *menu;
449 GList *names;
450 GSList *group = NULL;
451 widget = gtk_option_menu_new();
452 menu = gtk_menu_new();
453 for (names = (data->choice_list_function)(); names != NULL;
454 names = g_list_next(names)) {
455 GtkWidget *menuitem =
456 gtk_radio_menu_item_new_with_label(group, (gchar *)names->data);
457 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
458 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem));
460 gtk_option_menu_set_menu(GTK_OPTION_MENU(widget), menu);
461 gtk_widget_show_all(menu);
462 break;
464 case PREF_NONE:
465 case PREF_END_GROUP:
466 widget = NULL;
467 break;
469 if (widget != NULL)
470 gtk_widget_show(widget);
471 return widget;
474 static gint
475 prefs_respond(GtkWidget *widget,
476 gint response_id,
477 gpointer data)
479 if ( response_id == GTK_RESPONSE_APPLY
480 || response_id == GTK_RESPONSE_OK) {
481 prefs_update_prefs_from_dialog();
482 prefs_save();
483 diagram_redraw_all();
486 if (response_id != GTK_RESPONSE_APPLY)
487 gtk_widget_hide(widget);
489 return 0;
492 static void
493 prefs_create_dialog(void)
495 GtkWidget *label;
496 GtkWidget *dialog_vbox;
497 GtkWidget *notebook;
498 GtkTable *top_table = NULL; /* top level table for the tab */
499 GtkTable *current_table = NULL;
500 int i;
501 int tab_idx = -1;
503 if (prefs_dialog != NULL)
504 return;
506 prefs_dialog = gtk_dialog_new_with_buttons(
507 _("Preferences"),
508 GTK_WINDOW(interface_get_toolbox_shell()),
509 GTK_DIALOG_DESTROY_WITH_PARENT,
510 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
511 GTK_STOCK_APPLY, GTK_RESPONSE_APPLY,
512 GTK_STOCK_OK, GTK_RESPONSE_OK,
513 NULL);
514 gtk_dialog_set_default_response (GTK_DIALOG(prefs_dialog), GTK_RESPONSE_OK);
515 gtk_window_set_resizable (GTK_WINDOW (prefs_dialog), TRUE);
517 dialog_vbox = GTK_DIALOG (prefs_dialog)->vbox;
519 gtk_window_set_role (GTK_WINDOW (prefs_dialog), "preferences_window");
521 g_signal_connect(G_OBJECT (prefs_dialog), "response",
522 G_CALLBACK (prefs_respond), NULL);
524 g_signal_connect (GTK_OBJECT (prefs_dialog), "delete_event",
525 G_CALLBACK(gtk_widget_hide), NULL);
526 g_signal_connect (GTK_OBJECT (prefs_dialog), "destroy",
527 G_CALLBACK(gtk_widget_destroyed), &prefs_dialog);
529 notebook = gtk_notebook_new ();
530 gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
531 gtk_box_pack_start (GTK_BOX (dialog_vbox), notebook, TRUE, TRUE, 0);
532 gtk_container_set_border_width (GTK_CONTAINER (notebook), 2);
533 gtk_widget_show (notebook);
535 for (i=0;i<NUM_PREFS_TABS;i++) {
536 GtkWidget *table;
537 GtkWidget *notebook_page;
539 label = gtk_label_new(gettext(prefs_tabs[i].title));
540 gtk_widget_show(label);
542 table = gtk_table_new (9, 2, FALSE);
543 prefs_tabs[i].table = GTK_TABLE(table);
544 gtk_widget_set_size_request(table, -1, -1);
545 gtk_widget_show(table);
547 #ifdef SCROLLED_PAGES
548 notebook_page = gtk_scrolled_window_new (NULL, NULL);
549 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (notebook_page),
550 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
551 gtk_widget_show(notebook_page);
552 #else
553 notebook_page = table;
554 #endif/* SCROLLED_PAGES */
556 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), notebook_page, label);
558 #ifdef SCROLLED_PAGES
559 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(notebook_page),
560 table);
561 gtk_viewport_set_shadow_type(GTK_VIEWPORT(GTK_BIN(notebook_page)->child),
562 GTK_SHADOW_NONE);
563 #endif /* SCROLLED_PAGES */
567 tab_idx = -1;
568 for (i=0;i<NUM_PREFS_DATA;i++) {
569 GtkWidget *widget = NULL;
570 int row;
572 if (prefs_data[i].hidden)
573 continue;
575 if (tab_idx != prefs_data[i].tab) {
576 tab_idx = prefs_data[i].tab;
577 top_table = prefs_tabs[prefs_data[i].tab].table;
578 current_table = top_table;
580 row = prefs_tabs[tab_idx].row++;
581 switch(prefs_data[i].type) {
582 case PREF_NONE:
583 widget = gtk_frame_new(gettext(prefs_data[i].label_text));
584 gtk_widget_show (widget);
585 gtk_table_attach (current_table, widget, 0, 2,
586 row, row + 1,
587 GTK_FILL | GTK_EXPAND, GTK_FILL, 1, 1);
588 current_table = GTK_TABLE(gtk_table_new (9, 2, FALSE));
589 gtk_container_add(GTK_CONTAINER(widget), GTK_WIDGET(current_table));
590 gtk_widget_show(GTK_WIDGET(current_table));
591 break;
592 case PREF_END_GROUP:
593 current_table = top_table;
594 break;
595 case PREF_BOOLEAN:
596 widget = gtk_check_button_new_with_label (gettext(prefs_data[i].label_text));
597 gtk_widget_show (widget);
598 gtk_table_attach (current_table, widget, 0, 2,
599 row, row + 1,
600 GTK_FILL | GTK_EXPAND, GTK_FILL, 1, 1);
601 break;
602 default:
603 label = gtk_label_new (gettext(prefs_data[i].label_text));
604 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.3);
605 gtk_widget_show (label);
607 gtk_table_attach (current_table, label, 0, 1,
608 row, row + 1,
609 GTK_FILL | GTK_EXPAND, GTK_FILL, 1, 1);
611 widget = prefs_get_property_widget(&prefs_data[i]);
612 if (widget != NULL) {
613 gtk_table_attach (current_table, widget, 1, 2,
614 row, row + 1,
615 GTK_FILL, GTK_FILL, 1, 1);
617 break;
619 prefs_data[i].widget = widget;
623 gtk_widget_show (prefs_dialog);
626 static void
627 prefs_update_prefs_from_dialog(void)
629 GtkWidget *widget;
630 int i;
631 char *ptr;
633 for (i=0;i<NUM_PREFS_DATA;i++) {
634 if (prefs_data[i].hidden) continue;
635 widget = prefs_data[i].widget;
636 ptr = (char *)&prefs + prefs_data[i].offset;
638 prefs_get_value_from_widget(widget, &prefs_data[i], ptr);
642 static void
643 prefs_update_dialog_from_prefs(void)
645 GtkWidget *widget;
646 int i;
647 char *ptr;
649 for (i=0;i<NUM_PREFS_DATA;i++) {
650 if (prefs_data[i].hidden) continue;
651 widget = prefs_data[i].widget;
652 ptr = (char *)&prefs + prefs_data[i].offset;
654 prefs_set_value_in_widget(widget, &prefs_data[i], ptr);
658 static void
659 update_floating_toolbox(DiaPrefData *pref, char *ptr)
661 if (prefs.toolbox_on_top) {
662 /* Go through all diagrams and set toolbox transient for all displays */
663 GList *diagrams;
664 for (diagrams = dia_open_diagrams(); diagrams != NULL;
665 diagrams = g_list_next(diagrams)) {
666 Diagram *diagram = (Diagram *)diagrams->data;
667 GSList *displays;
668 for (displays = diagram->displays; displays != NULL;
669 displays = g_slist_next(displays)) {
670 DDisplay *ddisp = (DDisplay *)displays->data;
671 gtk_window_set_transient_for(GTK_WINDOW(interface_get_toolbox_shell()),
672 GTK_WINDOW(ddisp->shell));
675 } else {
676 /* Can't set non-transient, but don't want a message on every change.
677 * Maybe recreate toolbox?