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)
101 {
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 }
106 }
108 static void
109 options_store_transform_toggled (GtkToggleButton *button)
110 {
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 }
115 }
117 static void
118 options_clone_compensation_toggled (GtkToggleButton *button)
119 {
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 }
124 }
126 static void
127 options_clone_orphans_toggled (GtkToggleButton *button)
128 {
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 }
133 }
135 static void
136 options_selcue_toggled (GtkToggleButton *button)
137 {
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 }
142 }
144 static void
145 options_scale_origin_toggled (GtkToggleButton *button)
146 {
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 }
151 }
154 /**
155 * Small helper function to make options_selector a little less
156 * verbose.
157 *
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 )
180 {
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;
197 }
199 static GtkWidget *
200 options_selector ()
201 {
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;
292 }
295 static void
296 sp_display_dialog_set_oversample (GtkMenuItem *item, gpointer data)
297 {
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 );
312 }
315 static void
316 options_rotation_steps_changed (GtkMenuItem *item, gpointer data)
317 {
318 gint snaps_new = GPOINTER_TO_INT (data);
319 prefs_set_int_attribute ( "options.rotationsnapsperpi", "value", snaps_new );
320 }
322 static void
323 options_dialogs_ontop_changed (GtkMenuItem *item, gpointer data)
324 {
325 gint policy_new = GPOINTER_TO_INT (data);
326 prefs_set_int_attribute ( "options.transientpolicy", "value", policy_new );
327 }
329 void
330 options_rotation_steps (GtkWidget *vb, GtkTooltips *tt)
331 {
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 }
408 }
410 void
411 options_dialogs_ontop (GtkWidget *vb, GtkTooltips *tt)
412 {
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 }
476 }
479 static void
480 sp_display_dialog_cursor_tolerance_changed (GtkAdjustment *adj, gpointer data)
481 {
482 prefs_set_double_attribute ( "options.cursortolerance", "value",
483 adj->value );
484 }
486 static void
487 options_freehand_tolerance_changed (GtkAdjustment *adj, gpointer data)
488 {
489 prefs_set_double_attribute ("tools.freehand.pencil", "tolerance", adj->value);
490 }
492 static void
493 options_changed_double (GtkAdjustment *adj, gpointer data)
494 {
495 const gchar *prefs_path = (const gchar *) data;
496 prefs_set_double_attribute (prefs_path, "value", adj->value);
497 }
499 static void
500 options_changed_int (GtkAdjustment *adj, gpointer data)
501 {
502 const gchar *prefs_path = (const gchar *) data;
503 prefs_set_int_attribute (prefs_path, "value", (int) adj->value);
504 }
506 static void
507 options_changed_percent (GtkAdjustment *adj, gpointer data)
508 {
509 const gchar *prefs_path = (const gchar *) data;
510 prefs_set_double_attribute (prefs_path, "value", (adj->value)/100.0);
511 }
513 static void
514 options_changed_boolean (GtkToggleButton *tb, gpointer data)
515 {
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));
519 }
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)
531 )
532 {
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 }
586 }
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)
596 )
597 {
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 }
635 }
637 void
638 selcue_checkbox (GtkWidget *vb, GtkTooltips *tt, const gchar *path)
639 {
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 );
647 }
649 void
650 gradientdrag_checkbox (GtkWidget *vb, GtkTooltips *tt, const gchar *path)
651 {
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 );
659 }
662 /**
663 * Helper function for new_objects_style
664 *
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 )
686 {
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;
701 }
703 static void
704 style_from_selection_to_tool(GtkWidget *widget, gchar const *prefs_path)
705 {
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");
750 swatch->setStyle (css);
752 sp_repr_css_attr_unref(css);
753 }
754 }
755 }
757 static void
758 options_changed_radio (GtkToggleButton *tb, gpointer data)
759 {
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);
771 }
773 void
774 new_objects_style (GtkWidget *vb, GtkTooltips *tt, const gchar *path)
775 {
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 }
838 }
841 static GtkWidget *
842 options_dropper ()
843 {
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;
852 }
854 GtkWidget *
855 new_tab (GtkWidget *nb, const gchar *label)
856 {
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;
864 }
866 void
867 sp_display_dialog (void)
868 {
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"));
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);
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);
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 :