Code

moving trunk for module inkscape
[inkscape.git] / src / dialogs / display-settings.cpp
1 #define __SP_DISPLAY_SETTINGS_C__
3 /*
4 * Inkscape Preferences dialog
5 *
6 * Authors:
7 *   Lauris Kaplinski <lauris@ximian.com>
8 *   bulia byak
9 *
10 * Copyright (C) 2001 Ximian, Inc.
11 * Copyright (C) 2001-2004 Authors
12 *
13 */
15 #ifdef HAVE_CONFIG_H
16 # include "config.h"
17 #endif
18 #include <gtk/gtk.h>
20 #include "helper/window.h"
21 #include "../inkscape.h"
22 #include "../prefs-utils.h"
23 #include "dialog-events.h"
24 #include "../macros.h"
25 #include "../prefs-utils.h"
26 #include "../verbs.h"
27 #include "../interface.h"
28 #include "../message-stack.h"
29 #include "../enums.h"
30 #include "../selcue.h"
31 #include "../selection.h"
32 #include "../selection-chemistry.h"
33 #include "../style.h"
34 #include "../desktop-handles.h"
35 #include "../unit-constants.h"
36 #include "xml/repr.h"
37 #include "ui/widget/style-swatch.h"
42 static GtkWidget *dlg = NULL;
43 static win_data wd;
45 // impossible original values to make sure they are read from prefs
46 static gint x = -1000, y = -1000;
47 static gchar *prefs_path = "dialogs.preferences";
49 extern gint nr_arena_image_x_sample;
50 extern gint nr_arena_image_y_sample;
52 #define SB_WIDTH 90
53 #define SB_LONG_ADJUSTMENT 20
54 #define SB_MARGIN 1
55 #define SUFFIX_WIDTH 70
56 #define HB_MARGIN 4
57 #define VB_MARGIN 4
58 #define VB_SKIP 1
60 static void
61 sp_display_dialog_destroy (GtkObject *object, gpointer data)
62 {
64     sp_signal_disconnect_by_data (INKSCAPE, dlg);
65     wd.win = dlg = NULL;
66     wd.stop = 0;
68 } // edn of sp_display_dialog_destroy()
72 static gboolean
73 sp_display_dialog_delete (GtkObject *object, GdkEvent *event, gpointer data)
74 {
75     gtk_window_get_position ((GtkWindow *) dlg, &x, &y);
77     prefs_set_int_attribute (prefs_path, "x", x);
78     prefs_set_int_attribute (prefs_path, "y", y);
80     return FALSE; // which means, go ahead and destroy it
82 } // end of sp_display_dialog_delete()
84 static void
85 prefs_switch_page (GtkNotebook *notebook,
86                                                           GtkNotebookPage *page,
87                                                           guint page_num,
88                                                           gchar *attr)
89 {
90      prefs_set_int_attribute ("dialogs.preferences", attr, page_num);
91 }
93 static gint
94 get_int_value_data(GtkToggleButton *button)
95 {
96     return GPOINTER_TO_INT((gchar const*)gtk_object_get_data(GTK_OBJECT(button), "value"));
97 }
99 static void
100 options_selector_show_toggled (GtkToggleButton *button)
102         if (gtk_toggle_button_get_active (button)) {
103                 gchar const *val = (gchar const*)gtk_object_get_data(GTK_OBJECT(button), "value");
104                 prefs_set_string_attribute ("tools.select", "show", val);
105         }
108 static void
109 options_store_transform_toggled (GtkToggleButton *button)
111         if (gtk_toggle_button_get_active (button)) {
112                 guint const val = get_int_value_data(button);
113                 prefs_set_int_attribute ("options.preservetransform", "value", val);
114         }
117 static void
118 options_clone_compensation_toggled (GtkToggleButton *button)
120         if (gtk_toggle_button_get_active (button)) {
121                 guint const val = get_int_value_data(button);
122                 prefs_set_int_attribute ("options.clonecompensation", "value", val);
123         }
126 static void
127 options_clone_orphans_toggled (GtkToggleButton *button)
129         if (gtk_toggle_button_get_active (button)) {
130                 guint const val = get_int_value_data(button);
131                 prefs_set_int_attribute ("options.cloneorphans", "value", val);
132         }
135 static void
136 options_selcue_toggled (GtkToggleButton *button)
138         if (gtk_toggle_button_get_active (button)) {
139                 guint const val = get_int_value_data(button);
140                 prefs_set_int_attribute ("options.selcue", "value", val);
141         }
144 static void
145 options_scale_origin_toggled (GtkToggleButton *button)
147         if (gtk_toggle_button_get_active (button)) {
148                 gchar const *val = (gchar const *) gtk_object_get_data(GTK_OBJECT(button), "value");
149                 prefs_set_string_attribute ("tools.select", "scale_origin", val);
150         }
154 /**
155 * Small helper function to make options_selector a little less
156 * verbose.
158 * \param b Another radio button in the group, or NULL for the first.
159 * \param fb Box to add the button to.
160 * \param n Label for the button.
161 * \param tip Tooltip.
162 * \param v_string Key for the button's value, if it is a string.
163 * \param v_uint Key for the button's value, if it is a uint.
164 * \param isint Whether this is astring or uint.
165 * \param s Initial state of the button.
166 * \param h Toggled handler function.
167 */
168 static GtkWidget* sp_select_context_add_radio (
169     GtkWidget *b,
170     GtkWidget *fb,
171     GtkTooltips *tt,
172     gchar const *n,
173     gchar const *tip,
174     char const *v_string,
175     guint v_uint,
176     bool isint,
177     gboolean s,
178     void (*h)(GtkToggleButton*)
179     )
181         GtkWidget* r = gtk_radio_button_new_with_label (
182             b ? gtk_radio_button_group (GTK_RADIO_BUTTON (b)) : NULL, n
183             );
184         gtk_tooltips_set_tip (GTK_TOOLTIPS (tt), r, tip, NULL);
185         gtk_widget_show (r);
187   if (isint)
188         gtk_object_set_data (GTK_OBJECT (r), "value", GUINT_TO_POINTER (v_uint));
189   else
190         gtk_object_set_data (GTK_OBJECT (r), "value", (void*) v_string);
192         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (r), s);
193         gtk_box_pack_start (GTK_BOX (fb), r, FALSE, FALSE, 0);
194         gtk_signal_connect (GTK_OBJECT (r), "toggled", GTK_SIGNAL_FUNC (h), NULL);
196        return r;
199 static GtkWidget *
200 options_selector ()
202     GtkWidget *vb, *f, *fb, *b;
204     GtkTooltips *tt = gtk_tooltips_new();
206     vb = gtk_vbox_new (FALSE, VB_MARGIN);
208     f = gtk_frame_new (_("When transforming, show:"));
209     gtk_widget_show (f);
210     gtk_box_pack_start (GTK_BOX (vb), f, FALSE, FALSE, 0);
212     fb = gtk_hbox_new (FALSE, 10);
213     gtk_widget_show (fb);
214     gtk_container_add (GTK_CONTAINER (f), fb);
216     gchar const *show = prefs_get_string_attribute ("tools.select", "show");
218     b = sp_select_context_add_radio (
219         NULL, fb, tt, _("Objects"),
220         _("Show the actual objects when moving or transforming"),
221         "content", 0, false,
222         (show == NULL) || !strcmp (show, "content"),
223         options_selector_show_toggled
224         );
226     sp_select_context_add_radio(
227         b, fb, tt, _("Box outline"),
228         _("Show only a box outline of the objects when moving or transforming"),
229         "outline",  0, false,
230         show && !strcmp (show, "outline"),
231         options_selector_show_toggled
232         );
234     f = gtk_frame_new (_("Per-object selection cue:"));
235     gtk_widget_show (f);
236     gtk_box_pack_start (GTK_BOX (vb), f, FALSE, FALSE, 0);
238     fb = gtk_hbox_new (FALSE, 10);
239     gtk_widget_show (fb);
240     gtk_container_add (GTK_CONTAINER (f), fb);
242     gint cue = prefs_get_int_attribute ("options.selcue", "value", Inkscape::SelCue::MARK);
244     b = sp_select_context_add_radio (
245         NULL, fb, tt, _("None"),
246         _("No per-object selection indication"), NULL, Inkscape::SelCue::NONE, true,
247         cue == Inkscape::SelCue::NONE,
248         options_selcue_toggled
249         );
251     b = sp_select_context_add_radio (
252         b, fb, tt, _("Mark"),
253         _("Each selected object has a diamond mark in the top left corner"),
254         NULL, Inkscape::SelCue::MARK, true,
255         cue == Inkscape::SelCue::MARK,
256         options_selcue_toggled
257         );
259     sp_select_context_add_radio (
260         b, fb, tt, _("Box"),
261         _("Each selected object displays its bounding box"), NULL, Inkscape::SelCue::BBOX, true,
262         cue == Inkscape::SelCue::BBOX,
263         options_selcue_toggled
264         );
266     f = gtk_frame_new (_("Default scale origin:"));
267     gtk_widget_show (f);
268     gtk_box_pack_start (GTK_BOX (vb), f, FALSE, FALSE, 0);
270     fb = gtk_hbox_new (FALSE, 10);
271     gtk_widget_show (fb);
272     gtk_container_add (GTK_CONTAINER (f), fb);
274     gchar const *scale_orig = prefs_get_string_attribute ("tools.select", "scale_origin");
276     b = sp_select_context_add_radio (
277         NULL, fb, tt, _("Opposite bounding box edge"),
278         _("Default scale origin will be on the bounding box of the item"), "bbox", 0, false,
279         (scale_orig == NULL) || !strcmp (scale_orig, "bbox"),
280         options_scale_origin_toggled
281         );
283     sp_select_context_add_radio (
284         b, fb, tt, _("Farthest opposite node"),
285         _("Default scale origin will be on the bounding box of the item's points"),
286         "points", 0, false,
287         scale_orig && !strcmp (scale_orig, "points"),
288         options_scale_origin_toggled
289         );
291     return vb;
295 static void
296 sp_display_dialog_set_oversample (GtkMenuItem *item, gpointer data)
298     gint os;
300     os = GPOINTER_TO_INT (data);
302     g_return_if_fail (os >= 0);
303     g_return_if_fail (os <= 4);
305     nr_arena_image_x_sample = os;
306     nr_arena_image_y_sample = os;
308     inkscape_refresh_display (INKSCAPE);
310     prefs_set_int_attribute ( "options.bitmapoversample", "value", os );
315 static void
316 options_rotation_steps_changed (GtkMenuItem *item, gpointer data)
318     gint snaps_new = GPOINTER_TO_INT (data);
319     prefs_set_int_attribute ( "options.rotationsnapsperpi", "value", snaps_new );
322 static void
323 options_dialogs_ontop_changed (GtkMenuItem *item, gpointer data)
325     gint policy_new = GPOINTER_TO_INT (data);
326     prefs_set_int_attribute ( "options.transientpolicy", "value", policy_new );
329 void
330 options_rotation_steps (GtkWidget *vb, GtkTooltips *tt)
332     GtkWidget *hb = gtk_hbox_new (FALSE, HB_MARGIN);
333     gtk_widget_show (hb);
334     gtk_box_pack_start (GTK_BOX (vb), hb, FALSE, FALSE, 0);
336     {
337         GtkWidget *l = gtk_label_new (_("degrees"));
338         gtk_misc_set_alignment (GTK_MISC (l), 0.0, 0.5);
339         gtk_widget_set_size_request (l, SUFFIX_WIDTH, -1);
340         gtk_widget_show (l);
341         gtk_box_pack_end (GTK_BOX (hb), l, FALSE, FALSE, 0);
342     }
344     {
345         GtkWidget *om = gtk_option_menu_new ();
346         gtk_tooltips_set_tip (GTK_TOOLTIPS (tt), om, _("Rotating with Ctrl pressed snaps every that much degrees; also, pressing [ or ] rotates by this amount"), NULL);
347         gtk_widget_set_size_request (om, SB_WIDTH, -1);
348         gtk_widget_show (om);
349         gtk_box_pack_end (GTK_BOX (hb), om, FALSE, FALSE, SB_MARGIN);
351         GtkWidget *m = gtk_menu_new ();
352         gtk_widget_show (m);
354         int snaps_current = prefs_get_int_attribute ("options.rotationsnapsperpi", "value", 12);
355         int position_current = 0;
357         struct RotSteps {
358             double degrees;
359             int snaps;
360         } const rot_snaps[] = {
361             {90, 2},
362             {60, 3},
363             {45, 4},
364             {30, 6},
365             {15, 12},
366             {10, 18},
367             {7.5, 24},
368             {6, 30},
369             {5, 36},
370             {3, 60},
371             {2, 90},
372             {1, 180},
373             {1, 0},
374         };
376         for (unsigned j = 0; j < G_N_ELEMENTS(rot_snaps); ++j) {
377             RotSteps const &rs = rot_snaps[j];
379             gchar const *label = NULL;
380             if (rs.snaps == 0) {
381                 // sorationsnapsperpi == 0 means no snapping
382                 label = _("None");
383             } else {
384                 label = g_strdup_printf ("%.2g", rs.degrees);
385             }
387             if (rs.snaps == snaps_current)
388                 position_current = j;
390             GtkWidget *item = gtk_menu_item_new_with_label (label);
391             gtk_signal_connect ( GTK_OBJECT (item), "activate",
392                                  GTK_SIGNAL_FUNC (options_rotation_steps_changed),
393                                  GINT_TO_POINTER (rs.snaps) );
394             gtk_widget_show (item);
395             gtk_menu_append (GTK_MENU (m), item);
396         }
398         gtk_option_menu_set_menu (GTK_OPTION_MENU (om), m);
399         gtk_option_menu_set_history ( GTK_OPTION_MENU (om), position_current);
400     }
402     {
403         GtkWidget *l = gtk_label_new (_("Rotation snaps every:"));
404         gtk_misc_set_alignment (GTK_MISC (l), 1.0, 0.5);
405         gtk_widget_show (l);
406         gtk_box_pack_start (GTK_BOX (hb), l, TRUE, TRUE, 0);
407     }
410 void
411 options_dialogs_ontop (GtkWidget *vb, GtkTooltips *tt)
413     GtkWidget *hb = gtk_hbox_new (FALSE, HB_MARGIN);
414     gtk_widget_show (hb);
415     gtk_box_pack_start (GTK_BOX (vb), hb, FALSE, FALSE, 0);
417     { // empty label for alignment
418         GtkWidget *l = gtk_label_new ("");
419         gtk_widget_set_size_request (l, SUFFIX_WIDTH - SB_LONG_ADJUSTMENT, -1);
420         gtk_widget_show (l);
421         gtk_box_pack_end (GTK_BOX (hb), l, FALSE, FALSE, 0);
422     }
424     {
425         GtkWidget *om = gtk_option_menu_new ();
426         gtk_tooltips_set_tip (GTK_TOOLTIPS (tt), om, _("None: dialogs are treated as regular windows; Normal: dialogs stay on top of document windows; Aggressive: same as Normal but may work better with some window managers."), NULL);
427         gtk_widget_set_size_request (om, SB_WIDTH + SB_LONG_ADJUSTMENT, -1);
428         gtk_widget_show (om);
429         gtk_box_pack_end (GTK_BOX (hb), om, FALSE, FALSE, SB_MARGIN);
431         GtkWidget *m = gtk_menu_new ();
432         gtk_widget_show (m);
434         int current = prefs_get_int_attribute ("options.transientpolicy", "value", 1);
436         {
437         const gchar *label = _("None");
438         GtkWidget *item = gtk_menu_item_new_with_label (label);
439         gtk_signal_connect ( GTK_OBJECT (item), "activate",
440                                  GTK_SIGNAL_FUNC (options_dialogs_ontop_changed),
441                                  GINT_TO_POINTER (0) );
442         gtk_widget_show (item);
443         gtk_menu_append (GTK_MENU (m), item);
444         }
446         {
447         const gchar *label = _("Normal");
448         GtkWidget *item = gtk_menu_item_new_with_label (label);
449         gtk_signal_connect ( GTK_OBJECT (item), "activate",
450                                  GTK_SIGNAL_FUNC (options_dialogs_ontop_changed),
451                                  GINT_TO_POINTER (1) );
452         gtk_widget_show (item);
453         gtk_menu_append (GTK_MENU (m), item);
454         }
456         {
457         const gchar *label = _("Aggressive");
458         GtkWidget *item = gtk_menu_item_new_with_label (label);
459         gtk_signal_connect ( GTK_OBJECT (item), "activate",
460                                  GTK_SIGNAL_FUNC (options_dialogs_ontop_changed),
461                                  GINT_TO_POINTER (2) );
462         gtk_widget_show (item);
463         gtk_menu_append (GTK_MENU (m), item);
464         }
466         gtk_option_menu_set_menu (GTK_OPTION_MENU (om), m);
467         gtk_option_menu_set_history ( GTK_OPTION_MENU (om), current);
468     }
470     {
471         GtkWidget *l = gtk_label_new (_("Dialogs on top:"));
472         gtk_misc_set_alignment (GTK_MISC (l), 1.0, 0.5);
473         gtk_widget_show (l);
474         gtk_box_pack_start (GTK_BOX (hb), l, TRUE, TRUE, 0);
475     }
479 static void
480 sp_display_dialog_cursor_tolerance_changed (GtkAdjustment *adj, gpointer data)
482     prefs_set_double_attribute ( "options.cursortolerance", "value",
483                                  adj->value );
486 static void
487 options_freehand_tolerance_changed (GtkAdjustment *adj, gpointer data)
489     prefs_set_double_attribute ("tools.freehand.pencil", "tolerance",  adj->value);
492 static void
493 options_changed_double (GtkAdjustment *adj, gpointer data)
495     const gchar *prefs_path = (const gchar *) data;
496     prefs_set_double_attribute (prefs_path, "value",  adj->value);
499 static void
500 options_changed_int (GtkAdjustment *adj, gpointer data)
502     const gchar *prefs_path = (const gchar *) data;
503     prefs_set_int_attribute (prefs_path, "value",  (int) adj->value);
506 static void
507 options_changed_percent (GtkAdjustment *adj, gpointer data)
509     const gchar *prefs_path = (const gchar *) data;
510     prefs_set_double_attribute (prefs_path, "value",  (adj->value)/100.0);
513 static void
514 options_changed_boolean (GtkToggleButton *tb, gpointer data)
516     const gchar *prefs_path = (const gchar *) data;
517     const gchar *prefs_attr = (const gchar *) g_object_get_data (G_OBJECT(tb), "attr");
518     prefs_set_int_attribute (prefs_path, prefs_attr, gtk_toggle_button_get_active (tb));
521 void
522 options_sb (
523     gchar const *label,
524     gchar const *tooltip, GtkTooltips *tt,
525     gchar const *suffix,
526     GtkWidget *box,
527     gdouble lower, gdouble upper, gdouble step_increment, gdouble page_increment, gdouble page_size,
528     gchar const *prefs_path, gchar const *attr, gdouble def,
529     bool isint, bool ispercent,
530     void (*changed)(GtkAdjustment *, gpointer)
533     GtkWidget *hb = gtk_hbox_new (FALSE, HB_MARGIN);
534     gtk_widget_show (hb);
535     gtk_box_pack_start (GTK_BOX (box), hb, FALSE, FALSE, VB_SKIP);
537     {
538         GtkWidget *l = gtk_label_new (suffix);
539         gtk_misc_set_alignment (GTK_MISC (l), 0.0, 0.5);
540         gtk_widget_set_size_request (l, SUFFIX_WIDTH, -1);
541         gtk_widget_show (l);
542         gtk_box_pack_end (GTK_BOX (hb), l, FALSE, FALSE, 0);
543     }
545     {
546         GtkObject *a = gtk_adjustment_new(0.0, lower, upper, step_increment, page_increment, page_size);
548         gdouble value;
549         if (isint)
550             if (ispercent)
551                 value = 100 * (gdouble) prefs_get_double_attribute_limited (prefs_path, attr, def, lower/100.0, upper/100.0);
552             else
553                 value = (gdouble) prefs_get_int_attribute_limited (prefs_path, attr, (int) def, (int) lower, (int) upper);
554         else
555             value = prefs_get_double_attribute_limited (prefs_path, attr, def, lower, upper);
557         gtk_adjustment_set_value (GTK_ADJUSTMENT (a), value);
559         GtkWidget *sb;
560         if (isint) {
561             sb = gtk_spin_button_new (GTK_ADJUSTMENT (a), 1.0, 0);
562         } else {
563             if (step_increment < 0.1)
564                 sb = gtk_spin_button_new (GTK_ADJUSTMENT (a), 0.01, 3);
565             else
566                 sb = gtk_spin_button_new (GTK_ADJUSTMENT (a), 0.01, 2);
567         }
569         gtk_tooltips_set_tip (GTK_TOOLTIPS (tt), sb, tooltip, NULL);
570         gtk_entry_set_width_chars (GTK_ENTRY (sb), 6);
571         gtk_widget_set_size_request (sb, SB_WIDTH, -1);
572         gtk_widget_show (sb);
573         gtk_box_pack_end (GTK_BOX (hb), sb, FALSE, FALSE, SB_MARGIN);
575         gtk_signal_connect(GTK_OBJECT(a), "value_changed",
576                            GTK_SIGNAL_FUNC(changed), (gpointer) prefs_path);
577     }
579     {
580         GtkWidget *l = gtk_label_new (label);
581         gtk_misc_set_alignment (GTK_MISC (l), 1.0, 0.5);
582         gtk_widget_show (l);
583         gtk_box_pack_start (GTK_BOX (hb), l, TRUE, TRUE, 0);
584     }
589 void
590 options_checkbox (
591     gchar const *label,
592     gchar const *tooltip, GtkTooltips *tt,
593     GtkWidget *box,
594     gchar const *prefs_path, gchar const *attr, gint def,
595     void (*changed)(GtkToggleButton *, gpointer)
598     GtkWidget *hb = gtk_hbox_new (FALSE, HB_MARGIN);
599     gtk_widget_show (hb);
600     gtk_box_pack_start (GTK_BOX (box), hb, FALSE, FALSE, VB_SKIP);
602     { // empty label for alignment
603         GtkWidget *l = gtk_label_new ("");
604         gtk_widget_set_size_request (l, SUFFIX_WIDTH, -1);
605         gtk_widget_show (l);
606         gtk_box_pack_end (GTK_BOX (hb), l, FALSE, FALSE, 0);
607     }
609     {
611         GtkWidget *b  = gtk_check_button_new ();
613         gint value = prefs_get_int_attribute (prefs_path, attr, def);
615         gtk_toggle_button_set_active ((GtkToggleButton *) b, value != 0);
617         gtk_tooltips_set_tip (GTK_TOOLTIPS (tt), b, tooltip, NULL);
619         gtk_widget_set_size_request (b, SB_WIDTH, -1);
620         gtk_widget_show (b);
621         gtk_box_pack_end (GTK_BOX (hb), b, FALSE, FALSE, SB_MARGIN);
623         g_object_set_data (G_OBJECT(b), "attr", (void *) attr);
625         gtk_signal_connect(GTK_OBJECT(b), "toggled",
626                            GTK_SIGNAL_FUNC(changed), (gpointer) prefs_path);
627     }
629     {
630         GtkWidget *l = gtk_label_new (label);
631         gtk_misc_set_alignment (GTK_MISC (l), 1.0, 0.5);
632         gtk_widget_show (l);
633         gtk_box_pack_start (GTK_BOX (hb), l, TRUE, TRUE, 0);
634     }
637 void
638 selcue_checkbox (GtkWidget *vb, GtkTooltips *tt, const gchar *path)
640     options_checkbox (
641         _("Show selection cue"),
642         _("Whether selected objects display a selection cue (the same as in selector)"), tt,
643         vb,
644         path, "selcue", 1,
645         options_changed_boolean
646         );
649 void
650 gradientdrag_checkbox (GtkWidget *vb, GtkTooltips *tt, const gchar *path)
652     options_checkbox (
653         _("Enable gradient editing"),
654         _("Whether selected objects display gradient editing controls"), tt,
655         vb,
656         path, "gradientdrag", 1,
657         options_changed_boolean
658         );
662 /**
663 * Helper function for new_objects_style
665 * \param b Another radio button in the group, or NULL for the first.
666 * \param fb Box to add the button to.
667 * \param n Label for the button.
668 * \param tip Tooltip.
669 * \param v_uint Key for the button's value
670 * \param s Initial state of the button.
671 * \param h Toggled handler function.
672 */
673 static GtkWidget* new_objects_style_add_radio (
674     GtkWidget* b,
675     GtkWidget* fb,
676     GtkTooltips* tt,
677     const gchar* n,
678     const gchar* tip,
679     guint v_uint,
680     gboolean s,
681     void (*h)(GtkToggleButton*, gpointer),
682     gchar const *prefs_path,
683     gchar const *attr,
684     GtkWidget *button
685     )
687         GtkWidget* r = gtk_radio_button_new_with_label (
688             b ? gtk_radio_button_group (GTK_RADIO_BUTTON (b)) : NULL, n
689             );
690         gtk_tooltips_set_tip (GTK_TOOLTIPS (tt), r, tip, NULL);
691         gtk_widget_show (r);
693         gtk_object_set_data (GTK_OBJECT (r), "value", GUINT_TO_POINTER (v_uint));
694         gtk_object_set_data (GTK_OBJECT (r), "attr", (gpointer) attr);
695         gtk_object_set_data (GTK_OBJECT (r), "button_to_activate", (gpointer) button);
697         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (r), s);
698         gtk_signal_connect (GTK_OBJECT (r), "toggled", GTK_SIGNAL_FUNC (h), (gpointer) prefs_path);
700        return r;
703 static void
704 style_from_selection_to_tool(GtkWidget *widget, gchar const *prefs_path)
706     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
707     if (desktop == NULL)
708         return;
710     Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
712     if (selection->isEmpty()) {
713         SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE,
714                                        _("<b>No objects selected</b> to take the style from."));
715         return;
716     }
717     SPItem *item = selection->singleItem();
718     if (!item) {
719         /* TODO: If each item in the selection has the same style then don't consider it an error.
720          * Maybe we should try to handle multiple selections anyway, e.g. the intersection of the
721          * style attributes for the selected items. */
722         SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE,
723                                        _("<b>More than one object selected.</b>  Cannot take style from multiple objects."));
724         return;
725     }
727     SPCSSAttr *css = take_style_from_item (item);
729     if (!css) return;
731     // only store text style for the text tool
732     if (!g_strrstr ((const gchar *) prefs_path, "text")) {
733         css = sp_css_attr_unset_text (css);
734     }
736     // we cannot store properties with uris - they will be invalid in other documents
737     css = sp_css_attr_unset_uris (css);
739     sp_repr_css_change (inkscape_get_repr (INKSCAPE, prefs_path), css, "style");
740     sp_repr_css_attr_unref (css);
742     // update the swatch
743     Inkscape::UI::Widget::StyleSwatch *swatch = 
744         (Inkscape::UI::Widget::StyleSwatch *) gtk_object_get_data (GTK_OBJECT (widget), "swatch");
745     if (swatch) {
746         Inkscape::XML::Node *tool_repr = inkscape_get_repr(INKSCAPE, prefs_path);
747         if (tool_repr) {
748             SPCSSAttr *css = sp_repr_css_attr_inherited(tool_repr, "style");
749             
750             swatch->setStyle (css);
752             sp_repr_css_attr_unref(css);
753         }
754     }
757 static void
758 options_changed_radio (GtkToggleButton *tb, gpointer data)
760     const gchar *prefs_path = (const gchar *) data;
761     const gchar *prefs_attr = (const gchar *) g_object_get_data (G_OBJECT(tb), "attr");
762     const guint val = GPOINTER_TO_INT((const gchar*)gtk_object_get_data(GTK_OBJECT(tb), "value"));
764     if (prefs_path && prefs_attr && gtk_toggle_button_get_active (tb)) {
765         prefs_set_int_attribute (prefs_path, prefs_attr, val);
766     }
768     GtkWidget *button = (GtkWidget *) g_object_get_data (G_OBJECT(tb), "button_to_activate");
769     if (button)
770         gtk_widget_set_sensitive (button, !val);
773 void
774 new_objects_style (GtkWidget *vb, GtkTooltips *tt, const gchar *path)
776     GtkWidget *f = gtk_frame_new (_("Create new objects with:"));
777     gtk_widget_show (f);
778     gtk_box_pack_start (GTK_BOX (vb), f, FALSE, FALSE, 0);
780     GtkWidget *fb = gtk_vbox_new (FALSE, 0);
781     gtk_widget_show (fb);
782     gtk_container_add (GTK_CONTAINER (f), fb);
784     guint usecurrent = prefs_get_int_attribute (path, "usecurrent", 0);
786     GtkWidget *take = gtk_button_new_with_label (_("Take from selection"));
787     gtk_tooltips_set_tip (tt, take, _("Remember the style of the (first) selected object as this tool's style"), NULL);
788     gtk_widget_show (take);
790     GtkWidget *b;
791     {
792         b = new_objects_style_add_radio (
793             NULL, fb, tt, _("Last used style"), _("Apply the style you last set on an object"),
794             1,
795             usecurrent != 0,
796             options_changed_radio,
797             path, "usecurrent", take
798             );
800         GtkWidget *hb = gtk_hbox_new(FALSE, HB_MARGIN);
801         gtk_box_pack_start (GTK_BOX (hb), b, FALSE, FALSE, 0);
802         gtk_widget_show_all(hb);
804         gtk_box_pack_start (GTK_BOX (fb), hb, FALSE, FALSE, 0);
805     }
807     {
808         b = new_objects_style_add_radio (
809             b, fb, tt, _("This tool's own style:"), _("Each tool may store its own style to apply to the newly created objects. Use the button below to set it."),
810             0,
811             usecurrent == 0,
812             options_changed_radio,
813             path, "usecurrent", take
814             );
816         GtkWidget *hb = gtk_hbox_new(FALSE, HB_MARGIN);
817         gtk_box_pack_start (GTK_BOX (hb), b, FALSE, FALSE, 0);
819         // style swatch
820         Inkscape::XML::Node *tool_repr = inkscape_get_repr(INKSCAPE, path);
821         if (tool_repr) {
822             SPCSSAttr *css = sp_repr_css_attr_inherited(tool_repr, "style");
823             Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(css);
824             gtk_box_pack_start (GTK_BOX (hb), (GtkWidget *) swatch->gobj(), FALSE, FALSE, 0);
825             sp_repr_css_attr_unref(css);
826             gtk_object_set_data (GTK_OBJECT (take), "swatch", (gpointer) swatch);
827         }
829         // add "take from selection" button
830         gtk_widget_set_sensitive (take, (usecurrent == 0));
831         gtk_box_pack_start (GTK_BOX (hb), take, FALSE, FALSE, 0);
832         gtk_signal_connect (GTK_OBJECT (take), "clicked", GTK_SIGNAL_FUNC (style_from_selection_to_tool), (void *) path);
834         gtk_widget_show_all(hb);
836         gtk_box_pack_start (GTK_BOX (fb), hb, FALSE, FALSE, 0);
837     }
841 static GtkWidget *
842 options_dropper ()
844     GtkTooltips *tt = gtk_tooltips_new();
846     GtkWidget *vb = gtk_vbox_new (FALSE, VB_MARGIN);
848     selcue_checkbox (vb, tt, "tools.dropper");
849     gradientdrag_checkbox (vb, tt, "tools.dropper");
851     return vb;
854 GtkWidget *
855 new_tab (GtkWidget *nb, const gchar *label)
857      GtkWidget *l = gtk_label_new (label);
858      gtk_widget_show (l);
859      GtkWidget *vb = gtk_vbox_new (FALSE, VB_MARGIN);
860      gtk_widget_show (vb);
861      gtk_container_set_border_width (GTK_CONTAINER (vb), VB_MARGIN);
862      gtk_notebook_append_page (GTK_NOTEBOOK (nb), vb, l);
863      return vb;
866 void
867 sp_display_dialog (void)
870     GtkWidget *nb, *l, *vb, *vbvb, *hb, *om, *m, *i, *frame;
872     if (!dlg)
873     {
875         gchar title[500];
876         sp_ui_dialog_title_string (Inkscape::Verb::get(SP_VERB_DIALOG_DISPLAY), title);
878         dlg = sp_window_new (title, TRUE);
879         gtk_window_set_resizable ((GtkWindow *) dlg, FALSE);
880         if (x == -1000 || y == -1000) {
881             x = prefs_get_int_attribute (prefs_path, "x", 0);
882             y = prefs_get_int_attribute (prefs_path, "y", 0);
883         }
885         if (x != 0 || y != 0) {
886             gtk_window_move ((GtkWindow *) dlg, x, y);
887         } else {
888             gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
889         }
892         sp_transientize (dlg);
893         wd.win = dlg;
894         wd.stop = 0;
896         g_signal_connect   ( G_OBJECT (INKSCAPE), "activate_desktop",
897                              G_CALLBACK (sp_transientize_callback), &wd);
899         gtk_signal_connect ( GTK_OBJECT (dlg), "event", GTK_SIGNAL_FUNC (sp_dialog_event_handler), dlg);
901         gtk_signal_connect ( GTK_OBJECT (dlg), "destroy", G_CALLBACK (sp_display_dialog_destroy), dlg);
902         gtk_signal_connect ( GTK_OBJECT (dlg), "delete_event", G_CALLBACK (sp_display_dialog_delete), dlg);
903         g_signal_connect   ( G_OBJECT (INKSCAPE), "shut_down", G_CALLBACK (sp_display_dialog_delete), dlg);
905         g_signal_connect   ( G_OBJECT (INKSCAPE), "dialogs_hide", G_CALLBACK (sp_dialog_hide), dlg);
906         g_signal_connect   ( G_OBJECT (INKSCAPE), "dialogs_unhide", G_CALLBACK (sp_dialog_unhide), dlg);
908         GtkTooltips *tt = gtk_tooltips_new();
910         nb = gtk_notebook_new ();
911         gtk_widget_show (nb);
912         gtk_container_add (GTK_CONTAINER (dlg), nb);
914 // Mouse
915         vb = new_tab (nb, _("Mouse"));
917         options_sb (
918             /* TRANSLATORS: "Grab" is a noun here.  "Grab sensitivity" is intended to mean how
919              * close on the screen you need to be to an object to be able to grab it with mouse (in
920              * pixels). */
921             _("Grab sensitivity:"),
922             _("How close on the screen you need to be to an object to be able to grab it with mouse (in screen pixels)"), tt,
923             _("pixels"),
924             /* todo: allow real-world units. */
925             vb,
926             0.0, 30.0, 1.0, 1.0, 1.0,
927             "options.cursortolerance", "value", 8.0,
928             true, false,
929             sp_display_dialog_cursor_tolerance_changed
930             );
932         options_sb (
933             _("Click/drag threshold:"),
934             _("Maximum mouse drag (in screen pixels) which is considered a click, not a drag"), tt,
935             _("pixels"),
936             vb,
937             0.0, 20.0, 1.0, 1.0, 1.0,
938             "options.dragtolerance", "value", 4.0,
939             true, false,
940             options_changed_int
941             );
944 // Scrolling
945         vb = new_tab (nb, _("Scrolling"));
947         options_sb (
948             _("Mouse wheel scrolls by:"),
949             _("One mouse wheel notch scrolls by this distance in screen pixels (horizontally with Shift)"), tt,
950             _("pixels"),
951             vb,
952             0.0, 1000.0, 1.0, 1.0, 1.0,
953             "options.wheelscroll", "value", 40.0,
954             true, false,
955             options_changed_int
956             );
958         frame = gtk_frame_new (_("Ctrl+arrows"));
959         gtk_widget_show (frame);
960         gtk_box_pack_start (GTK_BOX (vb), frame, FALSE, FALSE, 0);
961         vbvb = gtk_vbox_new (FALSE, VB_MARGIN);
962         gtk_widget_show (vbvb);
963         gtk_container_add (GTK_CONTAINER (frame), vbvb);
965         options_sb (
966             _("Scroll by:"),
967             _("Pressing Ctrl+arrow key scrolls by this distance (in screen pixels)"), tt,
968             _("pixels"),
969             vbvb,
970             0.0, 1000.0, 1.0, 1.0, 1.0,
971             "options.keyscroll", "value", 10.0,
972             true, false,
973             options_changed_int
974             );
976         options_sb (
977             _("Acceleration:"),
978             _("Pressing and holding Ctrl+arrow will gradually speed up scrolling (0 for no acceleration)"), tt,
979             "",
980             vbvb,
981             0.0, 5.0, 0.01, 1.0, 1.0,
982             "options.scrollingacceleration", "value", 0.35,
983             false, false,
984             options_changed_double
985             );
987         frame = gtk_frame_new (_("Autoscrolling"));
988         gtk_widget_show (frame);
989         gtk_box_pack_start (GTK_BOX (vb), frame, FALSE, FALSE, 0);
990         vbvb = gtk_vbox_new (FALSE, VB_MARGIN);
991         gtk_widget_show (vbvb);
992         gtk_container_add (GTK_CONTAINER (frame), vbvb);
994         options_sb (
995             _("Speed:"),
996             _("How fast the canvas autoscrolls when you drag beyond canvas edge (0 to turn autoscroll off)"), tt,
997             "",
998             vbvb,
999             0.0, 5.0, 0.01, 1.0, 1.0,
1000             "options.autoscrollspeed", "value", 0.7,
1001             false, false,
1002             options_changed_double
1003             );
1005         options_sb (
1006             _("Threshold:"),
1007             _("How far (in screen pixels) you need to be from the canvas edge to trigger autoscroll; positive is outside the canvas, negative is within the canvas"), tt,
1008             _("pixels"),
1009             vbvb,
1010             -600.0, 600.0, 1.0, 1.0, 1.0,
1011             "options.autoscrolldistance", "value", -10.0,
1012             true, false,
1013             options_changed_int
1014             );
1016 // Steps
1017         vb = new_tab (nb, _("Steps"));
1019         options_sb (
1020             _("Arrow keys move by:"),
1021             _("Pressing an arrow key moves selected object(s) or node(s) by this distance (in px units)"), tt,
1022             _("px"),
1023             vb,
1024             0.0, 3000.0, 0.01, 1.0, 1.0,
1025             "options.nudgedistance", "value", 2.0,
1026             false, false,
1027             options_changed_double
1028             );
1030         options_sb (
1031             _("> and < scale by:"),
1032             _("Pressing > or < scales selection up or down by this increment (in px units)"), tt,
1033             _("px"),
1034             vb,
1035             0.0, 3000.0, 0.01, 1.0, 1.0,
1036             "options.defaultscale", "value", 2.0,
1037             false, false,
1038             options_changed_double
1039             );
1041         options_sb (
1042             _("Inset/Outset by:"),
1043             _("Inset and Outset commands displace the path by this distance (in px units)"), tt,
1044             _("px"),
1045             vb,
1046             0.0, 3000.0, 0.01, 1.0, 1.0,
1047             "options.defaultoffsetwidth", "value", 2.0,
1048             false, false,
1049             options_changed_double
1050             );
1052         options_rotation_steps (vb, tt);
1054 options_checkbox (
1055     _("Compass-like display of angles"),
1056     // TRANSLATORS: "positive clockwise" means "increasing in clockwise direction"
1057     _("When on, angles are displayed with 0 at north, 0 to 360 range, positive clockwise; otherwise with 0 at east, -180 to 180 range, positive counterclockwise"), tt,
1058     vb,
1059     "options.compassangledisplay", "value", 1,
1060     options_changed_boolean
1061     );
1063         options_sb (
1064             _("Zoom in/out by:"),
1065             _("Zoom tool click, +/- keys, and middle click zoom in and out by this multiplier"), tt,
1066             _("%"),
1067             vb,
1068             101.0, 500.0, 1.0, 1.0, 1.0,
1069             "options.zoomincrement", "value", 1.414213562,
1070             true, true,
1071             options_changed_percent
1072             );
1074 // Tools
1075         vb = new_tab (nb, _("Tools"));
1077         GtkWidget *nb_tools = gtk_notebook_new ();
1078         gtk_widget_show (nb_tools);
1079         gtk_container_add (GTK_CONTAINER (vb), nb_tools);
1081         // Selector
1082         {
1083             GtkWidget *vb_tool = new_tab (nb_tools, _("Selector"));
1085             GtkWidget *selector_page = options_selector ();
1086             gtk_widget_show (selector_page);
1087             gtk_container_add (GTK_CONTAINER (vb_tool), selector_page);
1089             gradientdrag_checkbox (vb_tool, tt, "tools.select");
1090         }
1092         // Node
1093         {
1094             GtkWidget *vb_tool = new_tab (nb_tools, _("Node"));
1096             selcue_checkbox (vb_tool, tt, "tools.nodes");
1097             gradientdrag_checkbox (vb_tool, tt, "tools.nodes");
1098         }
1100         // Zoom
1101         {
1102             GtkWidget *vb_tool = new_tab (nb_tools, _("Zoom"));
1104             selcue_checkbox (vb_tool, tt, "tools.zoom");
1105             gradientdrag_checkbox (vb_tool, tt, "tools.zoom");
1106         }
1108         { // The 4 shape tools
1109             GtkWidget *vb_shapes = new_tab (nb_tools, _("Shapes"));
1111             GtkWidget *nb_shapes = gtk_notebook_new ();
1112             gtk_widget_show (nb_shapes);
1113             gtk_container_add (GTK_CONTAINER (vb_shapes), nb_shapes);
1115             // Rect
1116             {
1117             GtkWidget *vb_tool = new_tab(nb_shapes, _("Rectangle"));
1118             new_objects_style (vb_tool, tt, "tools.shapes.rect");
1119             }
1121             // Ellipse
1122             {
1123             GtkWidget *vb_tool = new_tab(nb_shapes, _("Ellipse"));
1124             new_objects_style (vb_tool, tt, "tools.shapes.arc");
1125             }
1127             // Star
1128             {
1129             GtkWidget *vb_tool = new_tab(nb_shapes, _("Star"));
1130             new_objects_style (vb_tool, tt, "tools.shapes.star");
1131             }
1133             // Spiral
1134             {
1135             GtkWidget *vb_tool = new_tab(nb_shapes, _("Spiral"));
1136             new_objects_style (vb_tool, tt, "tools.shapes.spiral");
1137             }
1139             // common for all shapes
1140             selcue_checkbox (vb_shapes, tt, "tools.shapes");
1141             gradientdrag_checkbox (vb_shapes, tt, "tools.shapes");
1143             g_signal_connect(GTK_OBJECT (nb_shapes), "switch-page", GTK_SIGNAL_FUNC (prefs_switch_page), (void *) "page_shapes");
1144             gtk_notebook_set_current_page (GTK_NOTEBOOK (nb_shapes), prefs_get_int_attribute ("dialogs.preferences", "page_shapes", 0));
1145         }
1147         // Pencil
1148         {
1149             GtkWidget *vb_tool = new_tab (nb_tools, _("Pencil"));
1151             options_sb (
1152                 _("Tolerance:"),
1153                 _("This value affects the amount of smoothing applied to freehand lines; lower values produce more uneven paths with more nodes"), tt,
1154                 "",
1155                 vb_tool,
1156                 0.0, 100.0, 0.5, 1.0, 1.0,
1157                 "tools.freehand.pencil", "tolerance", 10.0,
1158                 false, false,
1159                 options_freehand_tolerance_changed
1160                 );
1162             new_objects_style (vb_tool, tt, "tools.freehand.pencil");
1164             selcue_checkbox (vb_tool, tt, "tools.freehand.pencil");
1165         }
1167         // Pen
1168         {
1169             GtkWidget *vb_tool = new_tab (nb_tools, _("Pen"));
1171             new_objects_style (vb_tool, tt, "tools.freehand.pen");
1173             selcue_checkbox (vb_tool, tt, "tools.freehand.pen");
1174         }
1176         // Calligraphy
1177         {
1178             GtkWidget *vb_tool = new_tab (nb_tools, _("Calligraphy"));
1180             new_objects_style (vb_tool, tt, "tools.calligraphic");
1181         }
1183         // Text
1184         {
1185             GtkWidget *vb_tool = new_tab (nb_tools, _("Text"));
1187             new_objects_style (vb_tool, tt, "tools.text");
1189             selcue_checkbox (vb_tool, tt, "tools.text");
1190             gradientdrag_checkbox (vb_tool, tt, "tools.text");
1191         }
1193         // Gradient
1194         {
1195             GtkWidget *vb_tool = new_tab (nb_tools, _("Gradient"));
1197             selcue_checkbox (vb_tool, tt, "tools.gradient");
1198         }
1200         // Connector
1201         {
1202             GtkWidget *vb_tool = new_tab (nb_tools, _("Connector"));
1203             
1204             selcue_checkbox (vb_tool, tt, "tools.connector");
1205         }
1207         // Dropper
1208         {
1209             GtkWidget *vb_tool = new_tab (nb_tools, _("Dropper"));
1211             GtkWidget *dropper_page = options_dropper ();
1212             gtk_widget_show (dropper_page);
1213             gtk_container_add (GTK_CONTAINER (vb_tool), dropper_page);
1214         }
1216         g_signal_connect(GTK_OBJECT (nb_tools), "switch-page", GTK_SIGNAL_FUNC (prefs_switch_page), (void *) "page_tools");
1217         gtk_notebook_set_current_page (GTK_NOTEBOOK (nb_tools), prefs_get_int_attribute ("dialogs.preferences", "page_tools", 0));
1220 // Windows
1221         vb = new_tab (nb, _("Windows"));
1223         options_dialogs_ontop (vb, tt);
1225 options_checkbox (
1226     _("Save window geometry"),
1227     _("Save the window size and position with each document (only for Inkscape SVG format)"), tt,
1228     vb,
1229     "options.savewindowgeometry", "value", 1,
1230     options_changed_boolean
1231     );
1233 options_checkbox (
1234     _("Dialogs are hidden in taskbar"),
1235     _("Whether dialog windows are to be hidden in the window manager taskbar"), tt,
1236     vb,
1237     "options.dialogsskiptaskbar", "value", 1,
1238     options_changed_boolean
1239     );
1241 options_checkbox (
1242     _("Zoom when window is resized"),
1243     _("Zoom drawing when document window is resized, to keep the same area visible (this is the default which can be changed in any window using the button above the right scrollbar)"), tt,
1244     vb,
1245     "options.stickyzoom", "value", 0,
1246     options_changed_boolean
1247     );
1250 // Clones
1251         vb = new_tab (nb, _("Clones"));
1253         // Clone compensation
1254         {
1255             GtkWidget *f = gtk_frame_new (_("When the original moves, its clones and linked offsets:"));
1256             gtk_widget_show (f);
1257             gtk_box_pack_start (GTK_BOX (vb), f, FALSE, FALSE, 0);
1259             GtkWidget *fb = gtk_vbox_new (FALSE, 0);
1260             gtk_widget_show (fb);
1261             gtk_container_add (GTK_CONTAINER (f), fb);
1263             gint compense = prefs_get_int_attribute ("options.clonecompensation", "value", SP_CLONE_COMPENSATION_PARALLEL);
1265             GtkWidget *b =
1266             sp_select_context_add_radio (
1267                 NULL, fb, tt, _("Move in parallel"),
1268                 _("Clones are translated by the same vector as their original."),
1269                 NULL, SP_CLONE_COMPENSATION_PARALLEL, true,
1270                 compense == SP_CLONE_COMPENSATION_PARALLEL,
1271                 options_clone_compensation_toggled
1272                 );
1274             sp_select_context_add_radio (
1275                 b, fb, tt, _("Stay unmoved"),
1276                 _("Clones preserve their positions when their original is moved."),
1277                 NULL, SP_CLONE_COMPENSATION_UNMOVED, true,
1278                 compense == SP_CLONE_COMPENSATION_UNMOVED,
1279                 options_clone_compensation_toggled
1280                 );
1282             sp_select_context_add_radio (
1283                 b, fb, tt, _("Move according to transform"),
1284                 _("Each clone moves according to the value of its transform= attribute. For example, a rotated clone will move in a different direction than its original."),
1285                 NULL, SP_CLONE_COMPENSATION_NONE, true,
1286                 compense == SP_CLONE_COMPENSATION_NONE,
1287                 options_clone_compensation_toggled
1288                 );
1289         }
1291         // Original deletion
1292         {
1293             GtkWidget *f = gtk_frame_new (_("When the original is deleted, its clones:"));
1294             gtk_widget_show (f);
1295             gtk_box_pack_start (GTK_BOX (vb), f, FALSE, FALSE, 0);
1297             GtkWidget *fb = gtk_vbox_new (FALSE, 0);
1298             gtk_widget_show (fb);
1299             gtk_container_add (GTK_CONTAINER (f), fb);
1301             gint orphans = prefs_get_int_attribute ("options.cloneorphans", "value", SP_CLONE_ORPHANS_UNLINK);
1303             GtkWidget *b =
1304             sp_select_context_add_radio (
1305                 NULL, fb, tt, _("Are unlinked"), _("Orphaned clones are converted to regular objects."), NULL, SP_CLONE_ORPHANS_UNLINK, true,
1306                 orphans == SP_CLONE_ORPHANS_UNLINK,
1307                 options_clone_orphans_toggled
1308                 );
1310             sp_select_context_add_radio (
1311                 b, fb, tt, _("Are deleted"), _("Orphaned clones are deleted along with their original."), NULL, SP_CLONE_ORPHANS_DELETE, true,
1312                 orphans == SP_CLONE_ORPHANS_DELETE,
1313                 options_clone_orphans_toggled
1314                 );
1316 /*
1317             sp_select_context_add_radio (
1318                 b, fb, tt, _("Ask me"), _("Ask me what to do with the clones when their originals are deleted."), NULL, SP_CLONE_ORPHANS_ASKME, true,
1319                 orphans == SP_CLONE_ORPHANS_ASKME,
1320                 options_clone_orphans_toggled
1321                 );
1322 */
1323         }
1325 // Transforms
1326         /* TRANSLATORS: Noun, i.e. transformations. */
1327         vb = new_tab (nb, _("Transforms"));
1329 options_checkbox (
1330     _("Scale stroke width"),
1331     _("When scaling objects, scale the stroke width by the same proportion"), tt,
1332     vb,
1333     "options.transform", "stroke", 1,
1334     options_changed_boolean
1335     );
1337 options_checkbox (
1338     _("Scale rounded corners in rectangles"),
1339     _("When scaling rectangles, scale the radii of rounded corners"), tt,
1340     vb,
1341     "options.transform", "rectcorners", 0,
1342     options_changed_boolean
1343     );
1345 options_checkbox (
1346     _("Transform gradients"),
1347     _("Transform gradients (in fill or stroke) along with the objects"), tt,
1348     vb,
1349     "options.transform", "gradient", 1,
1350     options_changed_boolean
1351     );
1353 options_checkbox (
1354     _("Transform patterns"),
1355     _("Transform patterns (in fill or stroke) along with the objects"), tt,
1356     vb,
1357     "options.transform", "pattern", 1,
1358     options_changed_boolean
1359     );
1362      // Store transformation (global)
1363         {
1364             /* TRANSLATORS: How to specify the affine transformation in the SVG file. */
1365             GtkWidget *f = gtk_frame_new (_("Store transformation:"));
1366             gtk_widget_show (f);
1367             gtk_box_pack_start (GTK_BOX (vb), f, FALSE, FALSE, 0);
1369             GtkWidget *fb = gtk_vbox_new (FALSE, 0);
1370             gtk_widget_show (fb);
1371             gtk_container_add (GTK_CONTAINER (f), fb);
1373             gint preserve = prefs_get_int_attribute ("options.preservetransform", "value", 0);
1375             GtkWidget *b = sp_select_context_add_radio (
1376                 NULL, fb, tt, _("Optimized"),
1377                 _("If possible, apply transformation to objects without adding a transform= attribute"),
1378                 NULL, 0, true,
1379                 preserve == 0,
1380                 options_store_transform_toggled
1381                 );
1383             sp_select_context_add_radio (
1384                 b, fb, tt, _("Preserved"),
1385                 _("Always store transformation as a transform= attribute on objects"),
1386                 NULL, 1, true,
1387                 preserve != 0,
1388                 options_store_transform_toggled
1389                 );
1390         }
1392 // Selecting
1393         vb = new_tab (nb, _("Selecting"));
1395             GtkWidget *f = gtk_frame_new (_("Ctrl+A, Tab, Shift+Tab:"));
1396             gtk_widget_show (f);
1397             gtk_box_pack_start (GTK_BOX (vb), f, FALSE, FALSE, 0);
1399             GtkWidget *fb = gtk_vbox_new (FALSE, 0);
1400             gtk_widget_show (fb);
1401             gtk_container_add (GTK_CONTAINER (f), fb);
1403 options_checkbox (
1404     _("Select only within current layer"),
1405     _("Uncheck this to make keyboard selection commands work on objects in all layers"), tt,
1406     fb,
1407     "options.kbselection", "inlayer", 1,
1408     options_changed_boolean
1409     );
1411 options_checkbox (
1412     _("Ignore hidden objects"),
1413     _("Uncheck this to be able to select objects that are hidden (either by themselves or by being in a hidden group or layer)"), tt,
1414     fb,
1415     "options.kbselection", "onlyvisible", 1,
1416     options_changed_boolean
1417     );
1419 options_checkbox (
1420     _("Ignore locked objects"),
1421     _("Uncheck this to be able to select objects that are locked (either by themselves or by being in a locked group or layer)"), tt,
1422     fb,
1423     "options.kbselection", "onlysensitive", 1,
1424     options_changed_boolean
1425     );
1428 // To be broken into: Display, Save, Export, SVG, Commands
1429         vb = new_tab (nb, _("Misc"));
1431         options_sb (
1432             _("Default export resolution:"),
1433             _("Default bitmap resolution (in dots per inch) in the Export dialog"), tt, // FIXME: add "Used for new exports; once exported, documents remember this value on per-object basis" when implemented
1434             _("dpi"),
1435             vb,
1436             0.0, 6000.0, 1.0, 1.0, 1.0,
1437             "dialogs.export.defaultxdpi", "value", PX_PER_IN,
1438             true, false,
1439             options_changed_int
1440             );
1442         options_checkbox (
1443     /* TRANSLATORS: When on, an imported bitmap creates an <image> element; otherwise it is a
1444      * rectangle with bitmap fill. */
1445     _("Import bitmap as <image>"),
1446     _("When on, an imported bitmap creates an <image> element; otherwise it is a rectangle with bitmap fill"), tt,
1447     vb,
1448     "options.importbitmapsasimages", "value", 1,
1449     options_changed_boolean
1450     );
1452         options_checkbox (
1453     /* TRANSLATORS: When on, the print out (currently Postscript) will have
1454      * a comment with the each object's label visible, marking the section
1455      * of the printing commands that represent the given object. */
1456     _("Add label comments to printing output"),
1457     _("When on, a comment will be added to the raw print output, marking the rendered output for an object with its label"), tt,
1458     vb,
1459     "printing.debug", "show-label-comments", 0,
1460     options_changed_boolean
1461     );
1463         options_checkbox (
1464     /* TRANSLATORS: When on, enable the effects menu, default is off */
1465     _("Enable script effects (requires restart) - EXPERIMENTAL"),
1466     _("When on, the effects menu is enabled, allowing external effect scripts to be called, requires restart before effective - EXPERIMENTAL"), tt,
1467     vb,
1468     "extensions", "show-effects-menu", 0,
1469     options_changed_boolean
1470     );
1472         options_sb (
1473             /* TRANSLATORS: The maximum length of the Open Recent list in the File menu. */
1474             _("Max recent documents:"),
1475             _("The maximum length of the Open Recent list in the File menu"), tt,
1476             "",
1477             vb,
1478             0.0, 1000.0, 1.0, 1.0, 1.0,
1479             "options.maxrecentdocuments", "value", 20.0,
1480             true, false,
1481             options_changed_int
1482             );
1484         options_sb (
1485             _("Simplification threshold:"),
1486             _("How strong is the Simplify command by default. If you invoke this command several times in quick succession, it will act more and more aggressively; invoking it again after a pause restores the default threshold."), tt,
1487             "",
1488             vb,
1489             0.0, 1.0, 0.001, 0.01, 0.01,
1490             "options.simplifythreshold", "value", 0.002,
1491             false, false,
1492             options_changed_double
1493             );
1496         /* Oversample */
1497         hb = gtk_hbox_new (FALSE, HB_MARGIN);
1498         gtk_widget_show (hb);
1499         gtk_box_pack_start (GTK_BOX (vb), hb, FALSE, FALSE, 0);
1501         // empty label for alignment
1502         l = gtk_label_new ("");
1503         gtk_widget_set_size_request (l, SUFFIX_WIDTH, -1);
1504         gtk_widget_show (l);
1505         gtk_box_pack_end (GTK_BOX (hb), l, FALSE, FALSE, 0);
1506     
1507         l = gtk_label_new (_("Oversample bitmaps:"));
1508         gtk_misc_set_alignment (GTK_MISC (l), 1.0, 0.5);
1509         gtk_widget_show (l);
1510         gtk_box_pack_start (GTK_BOX (hb), l, TRUE, TRUE, 0);
1512         om = gtk_option_menu_new ();
1513         gtk_widget_set_size_request (om, SB_WIDTH, -1);
1514         gtk_widget_show (om);
1515         gtk_box_pack_end (GTK_BOX (hb), om, FALSE, FALSE, SB_MARGIN);
1516         
1517         m = gtk_menu_new ();
1518         gtk_widget_show (m);
1520         i = gtk_menu_item_new_with_label (_("None"));
1521         gtk_signal_connect ( GTK_OBJECT (i), "activate",
1522                              GTK_SIGNAL_FUNC (sp_display_dialog_set_oversample),
1523                              GINT_TO_POINTER (0) );
1524         gtk_widget_show (i);
1525         gtk_menu_append (GTK_MENU (m), i);
1526         i = gtk_menu_item_new_with_label (_("2x2"));
1527         gtk_signal_connect ( GTK_OBJECT (i), "activate",
1528                              GTK_SIGNAL_FUNC (sp_display_dialog_set_oversample),
1529                              GINT_TO_POINTER (1) );
1530         gtk_widget_show (i);
1531         gtk_menu_append (GTK_MENU (m), i);
1532         i = gtk_menu_item_new_with_label (_("4x4"));
1533         gtk_signal_connect ( GTK_OBJECT (i), "activate",
1534                              GTK_SIGNAL_FUNC (sp_display_dialog_set_oversample),
1535                              GINT_TO_POINTER (2) );
1536         gtk_widget_show (i);
1537         gtk_menu_append (GTK_MENU (m), i);
1538         i = gtk_menu_item_new_with_label (_("8x8"));
1539         gtk_signal_connect ( GTK_OBJECT (i), "activate",
1540                              GTK_SIGNAL_FUNC (sp_display_dialog_set_oversample),
1541                              GINT_TO_POINTER (3));
1542         gtk_widget_show (i);
1543         gtk_menu_append (GTK_MENU (m), i);
1544         i = gtk_menu_item_new_with_label (_("16x16"));
1545         gtk_signal_connect ( GTK_OBJECT (i), "activate",
1546                              GTK_SIGNAL_FUNC (sp_display_dialog_set_oversample),
1547                              GINT_TO_POINTER (4) );
1548         gtk_widget_show (i);
1549         gtk_menu_append (GTK_MENU (m), i);
1551         gtk_option_menu_set_menu (GTK_OPTION_MENU (om), m);
1553         gtk_option_menu_set_history ( GTK_OPTION_MENU (om),
1554                                       nr_arena_image_x_sample);
1556         g_signal_connect(GTK_OBJECT (nb), "switch-page", GTK_SIGNAL_FUNC (prefs_switch_page), (void *) "page_top");
1557         gtk_notebook_set_current_page (GTK_NOTEBOOK (nb), prefs_get_int_attribute ("dialogs.preferences", "page_top", 0));
1559     } // end of if (!dlg)
1561     gtk_window_present ((GtkWindow *) dlg);
1563 } // end of sp_display_dialog()
1566 /*
1567   Local Variables:
1568   mode:c++
1569   c-file-style:"stroustrup"
1570   c-file-offsets:((innamespace . 0)(inline-open . 0))
1571   indent-tabs-mode:nil
1572   fill-column:99
1573   End:
1574 */
1575 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :