Code

5eacf74b41b07d56d178d7e6f58374e13b198994
[inkscape.git] / src / widgets / toolbox.cpp
1 #define __SP_MAINTOOLBOX_C__
3 /** \file
4  * Controls bars for some of Inkscape's tools 
5  * (for some tools, they are in their own files)
6  */
8 /*
9 *
10 * Authors:
11 *   MenTaLguY <mental@rydia.net>
12 *   Lauris Kaplinski <lauris@kaplinski.com>
13 *   bulia byak <buliabyak@users.sf.net>
14 *   Frank Felfe <innerspace@iname.com>
15 *   John Cliff <simarilius@yahoo.com>
16 *   David Turner <novalis@gnu.org>
17 *   Josh Andler <scislac@scislac.com>
18 *
19 * Copyright (C) 2004 David Turner
20 * Copyright (C) 2003 MenTaLguY
21 * Copyright (C) 1999-2005 authors
22 * Copyright (C) 2001-2002 Ximian, Inc.
23 *
24 * Released under GNU GPL, read the file 'COPYING' for more information
25 */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
31 #include <gtk/gtk.h>
33 #include "widgets/button.h"
34 #include "widgets/widget-sizes.h"
35 #include "widgets/spw-utilities.h"
36 #include "widgets/spinbutton-events.h"
38 #include "prefs-utils.h"
39 #include "verbs.h"
40 #include "sp-namedview.h"
41 #include "desktop.h"
42 #include "desktop-handles.h"
43 #include "nodepath.h"
44 #include "xml/repr.h"
45 #include "xml/node-event-vector.h"
46 #include <glibmm/i18n.h>
47 #include "helper/unit-menu.h"
48 #include "helper/units.h"
50 #include "inkscape.h"
51 #include "conn-avoid-ref.h"
54 #include "select-toolbar.h"
55 #include "gradient-toolbar.h"
57 #include "connector-context.h"
58 #include "sp-rect.h"
59 #include "sp-star.h"
60 #include "sp-spiral.h"
61 #include "sp-ellipse.h"
62 #include "selection.h"
63 #include "document-private.h"
65 #include "mod360.h"
67 #include "toolbox.h"
69 typedef void (*SetupFunction)(GtkWidget *toolbox, SPDesktop *desktop);
70 typedef void (*UpdateFunction)(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
72 static GtkWidget *sp_node_toolbox_new(SPDesktop *desktop);
73 static GtkWidget *sp_zoom_toolbox_new(SPDesktop *desktop);
74 static GtkWidget *sp_star_toolbox_new(SPDesktop *desktop);
75 static GtkWidget *sp_arc_toolbox_new(SPDesktop *desktop);
76 static GtkWidget *sp_rect_toolbox_new(SPDesktop *desktop);
77 static GtkWidget *sp_spiral_toolbox_new(SPDesktop *desktop);
78 static GtkWidget *sp_calligraphy_toolbox_new(SPDesktop *desktop);
79 static GtkWidget *sp_dropper_toolbox_new(SPDesktop *desktop);
80 static GtkWidget *sp_empty_toolbox_new(SPDesktop *desktop);
81 static GtkWidget *sp_text_toolbox_new(SPDesktop *desktop);
82 static GtkWidget *sp_connector_toolbox_new(SPDesktop *desktop);
85 static struct {
86     gchar const *type_name;
87     gchar const *data_name;
88     sp_verb_t verb;
89     sp_verb_t doubleclick_verb;
90 } const tools[] = {
91     { "SPSelectContext",   "select_tool",    SP_VERB_CONTEXT_SELECT,  SP_VERB_CONTEXT_SELECT_PREFS},
92     { "SPNodeContext",     "node_tool",      SP_VERB_CONTEXT_NODE, SP_VERB_CONTEXT_NODE_PREFS },
93     { "SPZoomContext",     "zoom_tool",      SP_VERB_CONTEXT_ZOOM, SP_VERB_CONTEXT_ZOOM_PREFS },
94     { "SPRectContext",     "rect_tool",      SP_VERB_CONTEXT_RECT, SP_VERB_CONTEXT_RECT_PREFS },
95     { "SPArcContext",      "arc_tool",       SP_VERB_CONTEXT_ARC, SP_VERB_CONTEXT_ARC_PREFS },
96     { "SPStarContext",     "star_tool",      SP_VERB_CONTEXT_STAR, SP_VERB_CONTEXT_STAR_PREFS },
97     { "SPSpiralContext",   "spiral_tool",    SP_VERB_CONTEXT_SPIRAL, SP_VERB_CONTEXT_SPIRAL_PREFS },
98     { "SPPencilContext",   "pencil_tool",    SP_VERB_CONTEXT_PENCIL, SP_VERB_CONTEXT_PENCIL_PREFS },
99     { "SPPenContext",      "pen_tool",       SP_VERB_CONTEXT_PEN, SP_VERB_CONTEXT_PEN_PREFS },
100     { "SPDynaDrawContext", "dyna_draw_tool", SP_VERB_CONTEXT_CALLIGRAPHIC, SP_VERB_CONTEXT_CALLIGRAPHIC_PREFS },
101     { "SPTextContext",     "text_tool",      SP_VERB_CONTEXT_TEXT, SP_VERB_CONTEXT_TEXT_PREFS },
102     { "SPConnectorContext","connector_tool", SP_VERB_CONTEXT_CONNECTOR, SP_VERB_CONTEXT_CONNECTOR_PREFS },
103     { "SPGradientContext", "gradient_tool",  SP_VERB_CONTEXT_GRADIENT, SP_VERB_CONTEXT_GRADIENT_PREFS },
104     { "SPDropperContext",  "dropper_tool",   SP_VERB_CONTEXT_DROPPER, SP_VERB_CONTEXT_DROPPER_PREFS },
105     { NULL, NULL, 0, 0 }
106 };
108 static struct {
109     gchar const *type_name;
110     gchar const *data_name;
111     GtkWidget *(*create_func)(SPDesktop *desktop);
112 } const aux_toolboxes[] = {
113     { "SPSelectContext", "select_toolbox", sp_select_toolbox_new },
114     { "SPNodeContext",   "node_toolbox",   sp_node_toolbox_new },
115     { "SPZoomContext",   "zoom_toolbox",   sp_zoom_toolbox_new },
116     { "SPStarContext",   "star_toolbox",   sp_star_toolbox_new },
117     { "SPRectContext",   "rect_toolbox",   sp_rect_toolbox_new },
118     { "SPArcContext",    "arc_toolbox",    sp_arc_toolbox_new },
119     { "SPSpiralContext", "spiral_toolbox", sp_spiral_toolbox_new },
120     { "SPPencilContext", "pencil_toolbox", NULL },
121     { "SPPenContext", "pen_toolbox", NULL },
122     { "SPDynaDrawContext", "calligraphy_toolbox", sp_calligraphy_toolbox_new },
123     { "SPTextContext",   "text_toolbox",   sp_text_toolbox_new },
124     { "SPDropperContext", "dropper_toolbox", sp_dropper_toolbox_new },
125     { "SPGradientContext", "gradient_toolbox", sp_gradient_toolbox_new },
126     { "SPConnectorContext", "connector_toolbox", sp_connector_toolbox_new },
127     { NULL, NULL, NULL }
128 };
130 static void toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop, SetupFunction setup_func, UpdateFunction update_func, sigc::connection*);
132 static void setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop);
133 static void update_tool_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
134 static void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop);
135 static void update_aux_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
136 static void setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop);
137 static void update_commands_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
139 /* Global text entry widgets necessary for update */
140 /* GtkWidget *dropper_rgb_entry, 
141           *dropper_opacity_entry ; */
142 // should be made a private member once this is converted to class
144 static void delete_connection(GObject *obj, sigc::connection *connection) {
145     connection->disconnect();
146     delete connection;
149 static GtkWidget *
150 sp_toolbox_button_new(GtkWidget *t, GtkIconSize size, gchar const *pxname, GtkSignalFunc handler,
151                       GtkTooltips *tt, gchar const *tip)
153     GtkWidget *b = sp_button_new_from_data(size, SP_BUTTON_TYPE_NORMAL, NULL, pxname, tip, tt);
154     gtk_widget_show(b);
155     if (handler) gtk_signal_connect(GTK_OBJECT(b), "clicked", handler, NULL);
156     gtk_box_pack_start(GTK_BOX(t), b, FALSE, FALSE, 0);
158     return b;
162 GtkWidget *
163 sp_toolbox_button_new_from_verb_with_doubleclick(GtkWidget *t, GtkIconSize size, SPButtonType type,
164                                                  Inkscape::Verb *verb, Inkscape::Verb *doubleclick_verb,
165                                                  Inkscape::UI::View::View *view, GtkTooltips *tt)
167     SPAction *action = verb->get_action(view);
168     if (!action) return NULL;
170     SPAction *doubleclick_action;
171     if (doubleclick_verb)
172         doubleclick_action = doubleclick_verb->get_action(view);
173     else
174         doubleclick_action = NULL;
176     /* fixme: Handle sensitive/unsensitive */
177     /* fixme: Implement sp_button_new_from_action */
178     GtkWidget *b = sp_button_new(size, type, action, doubleclick_action, tt);
179     gtk_widget_show(b);
180     gtk_box_pack_start(GTK_BOX(t), b, FALSE, FALSE, 0);
182     return b;
185 GtkWidget *sp_toolbox_button_new_from_verb(GtkWidget *t, GtkIconSize size, SPButtonType type, Inkscape::Verb *verb,
186                                            Inkscape::UI::View::View *view, GtkTooltips *tt)
188     return sp_toolbox_button_new_from_verb_with_doubleclick(t, size, type, verb, NULL, view, tt);
191 GtkWidget * sp_toolbox_button_normal_new_from_verb(GtkWidget *t, GtkIconSize size, Inkscape::Verb *verb,
192                                                    Inkscape::UI::View::View *view, GtkTooltips *tt)
194     return sp_toolbox_button_new_from_verb(t, size, SP_BUTTON_TYPE_NORMAL, verb, view, tt);
197 GtkWidget *
198 sp_tool_toolbox_new()
200     GtkTooltips *tt = gtk_tooltips_new();
201     GtkWidget *tb = gtk_vbox_new(FALSE, 0);
203     g_object_set_data(G_OBJECT(tb), "desktop", NULL);
204     g_object_set_data(G_OBJECT(tb), "tooltips", tt);
206     gtk_widget_set_sensitive(tb, FALSE);
208     GtkWidget *hb = gtk_handle_box_new();
209     gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), GTK_POS_TOP);
210     gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(hb), GTK_SHADOW_OUT);
211     gtk_handle_box_set_snap_edge(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
213     gtk_container_add(GTK_CONTAINER(hb), tb);
214     gtk_widget_show(GTK_WIDGET(tb));
216     sigc::connection* conn = new sigc::connection;
217     g_object_set_data(G_OBJECT(hb), "event_context_connection", conn);
219     return hb;
222 static void
223 aux_toolbox_attached(GtkHandleBox *toolbox, GtkWidget *child)
225     g_object_set_data(G_OBJECT(child), "is_detached", GINT_TO_POINTER(FALSE));
226     gtk_widget_queue_resize(child);
229 static void
230 aux_toolbox_detached(GtkHandleBox *toolbox, GtkWidget *child)
232     g_object_set_data(G_OBJECT(child), "is_detached", GINT_TO_POINTER(TRUE));
233     gtk_widget_queue_resize(child);
236 GtkWidget *
237 sp_aux_toolbox_new()
239     GtkWidget *tb = gtk_vbox_new(FALSE, 0);
241     GtkWidget *tb_s = gtk_vbox_new(FALSE, 0);
242     GtkWidget *tb_e = gtk_vbox_new(FALSE, 0);
243     gtk_box_set_spacing(GTK_BOX(tb), AUX_SPACING);
244     gtk_box_pack_start(GTK_BOX(tb), GTK_WIDGET(tb_s), FALSE, FALSE, 0);
245     gtk_box_pack_end(GTK_BOX(tb), GTK_WIDGET(tb_e), FALSE, FALSE, 0);
247     g_object_set_data(G_OBJECT(tb), "desktop", NULL);
248     g_object_set_data(G_OBJECT(tb), "top_spacer", tb_s);
250     gtk_widget_set_sensitive(tb, FALSE);
252     GtkWidget *hb = gtk_handle_box_new();
253     gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
254     gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(hb), GTK_SHADOW_OUT);
255     gtk_handle_box_set_snap_edge(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
257     g_signal_connect(G_OBJECT(hb), "child_attached", G_CALLBACK(aux_toolbox_attached), (gpointer)tb);
258     g_signal_connect(G_OBJECT(hb), "child_detached", G_CALLBACK(aux_toolbox_detached), (gpointer)tb);
260     gtk_container_add(GTK_CONTAINER(hb), tb);
261     gtk_widget_show(GTK_WIDGET(tb));
263     sigc::connection* conn = new sigc::connection;
264     g_object_set_data(G_OBJECT(hb), "event_context_connection", conn);
266     return hb;
269 //####################################
270 //# Commands Bar
271 //####################################
273 GtkWidget *
274 sp_commands_toolbox_new()
276     GtkWidget *tb = gtk_vbox_new(FALSE, 0);
278     GtkWidget *tb_s = gtk_vbox_new(FALSE, 0);
279     GtkWidget *tb_e = gtk_vbox_new(FALSE, 0);
280     gtk_box_set_spacing(GTK_BOX(tb), AUX_SPACING);
281     gtk_box_pack_start(GTK_BOX(tb), GTK_WIDGET(tb_s), FALSE, FALSE, 0);
282     gtk_box_pack_end(GTK_BOX(tb), GTK_WIDGET(tb_e), FALSE, FALSE, 0);
284     g_object_set_data(G_OBJECT(tb), "desktop", NULL);
285     gtk_widget_set_sensitive(tb, FALSE);
287     GtkWidget *hb = gtk_handle_box_new();
288     gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
289     gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(hb), GTK_SHADOW_OUT);
290     gtk_handle_box_set_snap_edge(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
292     g_signal_connect(G_OBJECT(hb), "child_attached", G_CALLBACK(aux_toolbox_attached), (gpointer)tb);
293     g_signal_connect(G_OBJECT(hb), "child_detached", G_CALLBACK(aux_toolbox_detached), (gpointer)tb);
295     gtk_container_add(GTK_CONTAINER(hb), tb);
296     gtk_widget_show(GTK_WIDGET(tb));
298     sigc::connection* conn = new sigc::connection;
299     g_object_set_data(G_OBJECT(hb), "event_context_connection", conn);
301     return hb;
305 //####################################
306 //# node editing callbacks
307 //####################################
309 void
310 sp_node_path_edit_add(void)
312     sp_node_selected_add_node();
315 void
316 sp_node_path_edit_delete(void)
318     sp_node_selected_delete();
321 void
322 sp_node_path_edit_delete_segment(void)
324     sp_node_selected_delete_segment();
327 void
328 sp_node_path_edit_break(void)
330     sp_node_selected_break();
333 void
334 sp_node_path_edit_join(void)
336     sp_node_selected_join();
339 void
340 sp_node_path_edit_join_segment(void)
342     sp_node_selected_join_segment();
345 void
346 sp_node_path_edit_toline(void)
348     sp_node_selected_set_line_type(NR_LINETO);
351 void
352 sp_node_path_edit_tocurve(void)
354     sp_node_selected_set_line_type(NR_CURVETO);
357 void
358 sp_node_path_edit_cusp(void)
360     sp_node_selected_set_type(Inkscape::NodePath::NODE_CUSP);
363 void
364 sp_node_path_edit_smooth(void)
366     sp_node_selected_set_type(Inkscape::NodePath::NODE_SMOOTH);
369 void
370 sp_node_path_edit_symmetrical(void)
372     sp_node_selected_set_type(Inkscape::NodePath::NODE_SYMM);
377 //################################
378 //##    Node Editing Toolbox    ##
379 //################################
381 static GtkWidget *
382 sp_node_toolbox_new(SPDesktop *desktop)
384     Inkscape::UI::View::View *view = desktop;
386     GtkTooltips *tt = gtk_tooltips_new();
387     GtkWidget *tb = gtk_hbox_new(FALSE, 0);
389     gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
391     sp_toolbox_button_new(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, "node_insert",
392         GTK_SIGNAL_FUNC(sp_node_path_edit_add), tt, _("Insert new nodes into selected segments"));
393     sp_toolbox_button_new(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, "node_delete",
394         GTK_SIGNAL_FUNC(sp_node_path_edit_delete), tt, _("Delete selected nodes"));
396     gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
398     sp_toolbox_button_new(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, "node_join",
399         GTK_SIGNAL_FUNC(sp_node_path_edit_join), tt, _("Join paths at selected nodes"));
400     sp_toolbox_button_new(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, "node_join_segment",
401         GTK_SIGNAL_FUNC(sp_node_path_edit_join_segment), tt, _("Join paths at selected nodes with new segment"));
403     sp_toolbox_button_new(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, "node_delete_segment",
404         GTK_SIGNAL_FUNC(sp_node_path_edit_delete_segment), tt, _("Split path between two non-endpoint nodes"));
406     sp_toolbox_button_new(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, "node_break",
407         GTK_SIGNAL_FUNC(sp_node_path_edit_break), tt, _("Break path at selected nodes"));
409     gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
411     sp_toolbox_button_new(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, "node_cusp",
412         GTK_SIGNAL_FUNC(sp_node_path_edit_cusp), tt, _("Make selected nodes corner"));
414     sp_toolbox_button_new(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, "node_smooth",
415         GTK_SIGNAL_FUNC(sp_node_path_edit_smooth), tt, _("Make selected nodes smooth"));
417     sp_toolbox_button_new(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, "node_symmetric",
418         GTK_SIGNAL_FUNC(sp_node_path_edit_symmetrical), tt, _("Make selected nodes symmetric"));
420     gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
422     sp_toolbox_button_new(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, "node_line",
423         GTK_SIGNAL_FUNC(sp_node_path_edit_toline), tt, _("Make selected segments lines"));
425     sp_toolbox_button_new(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, "node_curve",
426         GTK_SIGNAL_FUNC(sp_node_path_edit_tocurve), tt, _("Make selected segments curves"));
428     gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
430     sp_toolbox_button_normal_new_from_verb(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_OBJECT_TO_CURVE), view, tt);
432     sp_toolbox_button_normal_new_from_verb(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_SELECTION_OUTLINE), view, tt);
434     gtk_widget_show_all(tb);
436     return tb;
438 } // end of sp_node_toolbox_new()
441 //########################
442 //##    Zoom Toolbox    ##
443 //########################
445 static GtkWidget *
446 sp_zoom_toolbox_new(SPDesktop *desktop)
448     Inkscape::UI::View::View *view=desktop;
450     GtkTooltips *tt = gtk_tooltips_new();
451     GtkWidget *tb = gtk_hbox_new(FALSE, 0);
453     gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0),
454                        FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
456     sp_toolbox_button_new_from_verb(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_IN), view, tt);
458     sp_toolbox_button_new_from_verb(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_OUT), view, tt);
460     gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
462     sp_toolbox_button_new_from_verb(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_SELECTION), view, tt);
464     sp_toolbox_button_new_from_verb(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_DRAWING), view, tt);
466     sp_toolbox_button_new_from_verb(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_PAGE), view, tt);
468     sp_toolbox_button_new_from_verb(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_PAGE_WIDTH), view, tt);
470     gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
472     sp_toolbox_button_new_from_verb(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_PREV), view, tt);
474     sp_toolbox_button_new_from_verb(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_NEXT), view, tt);
476     gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
478     sp_toolbox_button_new_from_verb(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_1_1), view, tt);
480     sp_toolbox_button_new_from_verb(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_1_2), view, tt);
482     sp_toolbox_button_new_from_verb(tb, GTK_ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_2_1), view, tt);
484     gtk_widget_show_all(tb);
486     return tb;
488 } // end of sp_zoom_toolbox_new()
490 void
491 sp_tool_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
493     toolbox_set_desktop(gtk_bin_get_child(GTK_BIN(toolbox)), desktop, setup_tool_toolbox, update_tool_toolbox, static_cast<sigc::connection*>(g_object_get_data(G_OBJECT(toolbox), "event_context_connection")));
497 void
498 sp_aux_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
500     toolbox_set_desktop(gtk_bin_get_child(GTK_BIN(toolbox)), desktop, setup_aux_toolbox, update_aux_toolbox, static_cast<sigc::connection*>(g_object_get_data(G_OBJECT(toolbox), "event_context_connection")));
503 void
504 sp_commands_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
506     toolbox_set_desktop(gtk_bin_get_child(GTK_BIN(toolbox)), desktop, setup_commands_toolbox, update_commands_toolbox, static_cast<sigc::connection*>(g_object_get_data(G_OBJECT(toolbox), "event_context_connection")));
510 static void
511 toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop, SetupFunction setup_func, UpdateFunction update_func, sigc::connection *conn)
513     gpointer ptr = g_object_get_data(G_OBJECT(toolbox), "desktop");
514     SPDesktop *old_desktop = static_cast<SPDesktop*>(ptr);
516     if (old_desktop) {
517         GList *children, *iter;
519         children = gtk_container_get_children(GTK_CONTAINER(toolbox));
520         for ( iter = children ; iter ; iter = iter->next ) {
521             gtk_container_remove( GTK_CONTAINER(toolbox), GTK_WIDGET(iter->data) );
522         }
523         g_list_free(children);
524     }
526     g_object_set_data(G_OBJECT(toolbox), "desktop", (gpointer)desktop);
528     if (desktop) {
529         gtk_widget_set_sensitive(toolbox, TRUE);
530         setup_func(toolbox, desktop);
531         update_func(desktop, desktop->event_context, toolbox);
532         *conn = desktop->connectEventContextChanged 
533             (sigc::bind (sigc::ptr_fun(update_func), toolbox));
534     } else {
535         gtk_widget_set_sensitive(toolbox, FALSE);
536     }
538 } // end of toolbox_set_desktop()
541 static void
542 setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
544     GtkTooltips *tooltips=GTK_TOOLTIPS(g_object_get_data(G_OBJECT(toolbox), "tooltips"));
545     gint shrinkLeft = prefs_get_int_attribute_limited( "toolbox.left", "small", 0, 0, 1 );
546     GtkIconSize toolboxSize = shrinkLeft ? GTK_ICON_SIZE_SMALL_TOOLBAR : GTK_ICON_SIZE_LARGE_TOOLBAR;
548     for (int i = 0 ; tools[i].type_name ; i++ ) {
549         GtkWidget *button =
550             sp_toolbox_button_new_from_verb_with_doubleclick( toolbox, toolboxSize,
551                                                               SP_BUTTON_TYPE_TOGGLE,
552                                                               Inkscape::Verb::get(tools[i].verb),
553                                                               Inkscape::Verb::get(tools[i].doubleclick_verb),
554                                                               desktop,
555                                                               tooltips );
557         g_object_set_data( G_OBJECT(toolbox), tools[i].data_name,
558                            (gpointer)button );
559     }
563 static void
564 update_tool_toolbox( SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox )
566     gchar const *const tname = ( eventcontext
567                                  ? gtk_type_name(GTK_OBJECT_TYPE(eventcontext))
568                                  : NULL );
569     for (int i = 0 ; tools[i].type_name ; i++ ) {
570         SPButton *button = SP_BUTTON(g_object_get_data(G_OBJECT(toolbox), tools[i].data_name));
571         sp_button_toggle_set_down(button, tname && !strcmp(tname, tools[i].type_name));
572     }
575 static void
576 setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
578     GtkSizeGroup* grouper = gtk_size_group_new( GTK_SIZE_GROUP_BOTH );
580     for (int i = 0 ; aux_toolboxes[i].type_name ; i++ ) {
581         GtkWidget *sub_toolbox;
582         if (aux_toolboxes[i].create_func == NULL)
583             sub_toolbox = sp_empty_toolbox_new(desktop);
584         else
585             sub_toolbox = aux_toolboxes[i].create_func(desktop);
587         gtk_size_group_add_widget( grouper, sub_toolbox );
589         gtk_container_add(GTK_CONTAINER(toolbox), sub_toolbox);
590         g_object_set_data(G_OBJECT(toolbox), aux_toolboxes[i].data_name, sub_toolbox);
591     }
592     g_object_unref( G_OBJECT(grouper) );
595 static void
596 update_aux_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox)
598     gchar const *tname = ( eventcontext
599                            ? gtk_type_name(GTK_OBJECT_TYPE(eventcontext))
600                            : NULL );
601     for (int i = 0 ; aux_toolboxes[i].type_name ; i++ ) {
602         GtkWidget *sub_toolbox = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), aux_toolboxes[i].data_name));
603         if (tname && !strcmp(tname, aux_toolboxes[i].type_name)) {
604             gtk_widget_show_all(sub_toolbox);
605             g_object_set_data(G_OBJECT(toolbox), "shows", sub_toolbox);
606         } else {
607             gtk_widget_hide(sub_toolbox);
608         }
609     }
612 static void
613 setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
615     Inkscape::UI::View::View *view = desktop;
617     GtkTooltips *tt = gtk_tooltips_new();
618     GtkWidget *tb = gtk_hbox_new(FALSE, 0);
620     gint shrinkTop = prefs_get_int_attribute_limited( "toolbox", "small", 1, 0, 1 );
621     GtkIconSize toolboxSize = shrinkTop ? GTK_ICON_SIZE_SMALL_TOOLBAR : GTK_ICON_SIZE_LARGE_TOOLBAR;
623     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_NEW), view, tt);
624     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_OPEN), view, tt);
625     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_SAVE), view, tt);
626     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_PRINT), view, tt);
628     aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
630     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_IMPORT), view, tt);
631     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_EXPORT), view, tt);
633     aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
635     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_UNDO), view, tt);
636     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_REDO), view, tt);
638     aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
640     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_COPY), view, tt);
641     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_CUT), view, tt);
642     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_PASTE), view, tt);
644     aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
646     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_SELECTION), view, tt);
647     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_DRAWING), view, tt);
648     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_PAGE), view, tt);
650     aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
652     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_DUPLICATE), view, tt);
653     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_CLONE), view, tt);
654     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_UNLINK_CLONE), view, tt);
656     aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
658     sp_toolbox_button_normal_new_from_verb(tb, toolboxSize, Inkscape::Verb::get(SP_VERB_SELECTION_GROUP), view, tt);
659     sp_toolbox_button_normal_new_from_verb(tb, toolboxSize, Inkscape::Verb::get(SP_VERB_SELECTION_UNGROUP), view, tt);
661     // disabled until we have icons for them:
663     //find
665     //sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_TILE), view, tt);
666     //sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_UNTILE), view, tt);
668     aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
670     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_FILL_STROKE), view, tt);
671     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_TEXT), view, tt);
672     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_XML_EDITOR), view, tt);
673     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_ALIGN_DISTRIBUTE), view, tt);
675     aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
677     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_DISPLAY), view, tt);
678     sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_NAMEDVIEW), view, tt);
680     gtk_widget_show_all(tb);
682     gtk_container_add(GTK_CONTAINER(toolbox), tb);
685 static void
686 update_commands_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox)
690 void show_aux_toolbox(GtkWidget *toolbox_toplevel)
692     gtk_widget_show(toolbox_toplevel);
693     GtkWidget *toolbox = gtk_bin_get_child(GTK_BIN(toolbox_toplevel));
695     GtkWidget *shown_toolbox = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), "shows"));
696     if (!shown_toolbox) {
697         return;
698     }
699     gtk_widget_show(toolbox);
701     // need to show the spacer, or the padding will be off
702     GtkWidget *spacer = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), "top_spacer"));
703     gtk_widget_show(spacer);
705     gtk_widget_show_all(shown_toolbox);
708 void
709 aux_toolbox_space(GtkWidget *tb, gint space)
711     gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, space);
714 static GtkWidget *
715 sp_empty_toolbox_new(SPDesktop *desktop)
717     GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
718     gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
719     gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
721     gtk_widget_show_all(tbl);
722     sp_set_font_size_smaller (tbl);
724     return tbl;
727 // helper UI functions
729 GtkWidget *
730 sp_tb_spinbutton(
731     gchar *label, gchar const *tooltip,
732     gchar const *path, gchar const *data, gdouble def,
733     GtkWidget *us,
734     GtkWidget *tbl,
735     gboolean altx, gchar const *altx_mark,
736     gdouble lower, gdouble upper, gdouble step, gdouble page,
737     void (*callback)(GtkAdjustment *, GtkWidget *),
738     gdouble climb = 0.1, guint digits = 3)
740     GtkTooltips *tt = gtk_tooltips_new();
742     GtkWidget *hb = gtk_hbox_new(FALSE, 1);
744     GtkWidget *l = gtk_label_new(label);
745     gtk_widget_show(l);
746     gtk_misc_set_alignment(GTK_MISC(l), 1.0, 0.5);
747     gtk_container_add(GTK_CONTAINER(hb), l);
749     GtkObject *a = gtk_adjustment_new(prefs_get_double_attribute(path, data, def),
750                                       lower, upper, step, page, page);
751     gtk_object_set_data(GTK_OBJECT(tbl), data, a);
752     if (us)
753         sp_unit_selector_add_adjustment(SP_UNIT_SELECTOR(us), GTK_ADJUSTMENT(a));
755     GtkWidget *sb = gtk_spin_button_new(GTK_ADJUSTMENT(a), climb, digits);
756     gtk_tooltips_set_tip(tt, sb, tooltip, NULL);
757     if (altx)
758         gtk_object_set_data(GTK_OBJECT(sb), altx_mark, sb);
759     gtk_widget_set_size_request(sb, 
760                                 (upper <= 1.0 || digits == 0)? AUX_SPINBUTTON_WIDTH_SMALL - 10: AUX_SPINBUTTON_WIDTH_SMALL,
761                                 AUX_SPINBUTTON_HEIGHT);
762     gtk_widget_show(sb);
763     gtk_signal_connect(GTK_OBJECT(sb), "focus-in-event", GTK_SIGNAL_FUNC(spinbutton_focus_in), tbl);
764     gtk_signal_connect(GTK_OBJECT(sb), "key-press-event", GTK_SIGNAL_FUNC(spinbutton_keypress), tbl);
765     gtk_container_add(GTK_CONTAINER(hb), sb);
766     gtk_signal_connect(GTK_OBJECT(a), "value_changed", GTK_SIGNAL_FUNC(callback), tbl);
768     return hb;
771 #define MODE_LABEL_WIDTH 70
773 //########################
774 //##       Star         ##
775 //########################
777 static void
778 sp_stb_magnitude_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
780     SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
782     if (sp_document_get_undo_sensitive(SP_DT_DOCUMENT(desktop))) {
783         // do not remember prefs if this call is initiated by an undo change, because undoing object
784         // creation sets bogus values to its attributes before it is deleted
785         prefs_set_int_attribute("tools.shapes.star", "magnitude", (gint)adj->value);
786     }
788     // quit if run by the attr_changed listener
789     if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
790         return;
791     }
793     // in turn, prevent listener from responding
794     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
796     bool modmade = false;
798     Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
799     GSList const *items = selection->itemList();
800     for (; items != NULL; items = items->next) {
801         if (SP_IS_STAR((SPItem *) items->data)) {
802             Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
803             sp_repr_set_int(repr,"sodipodi:sides",(gint)adj->value);
804             sp_repr_set_svg_double(repr, "sodipodi:arg2",
805                                    (sp_repr_get_double_attribute(repr, "sodipodi:arg1", 0.5)
806                                     + M_PI / (gint)adj->value));
807             SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
808             modmade = true;
809         }
810     }
811     if (modmade)  sp_document_done(SP_DT_DOCUMENT(desktop));
813     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
815     spinbutton_defocus(GTK_OBJECT(tbl));
818 static void
819 sp_stb_proportion_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
821     SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
823     if (sp_document_get_undo_sensitive(SP_DT_DOCUMENT(desktop))) {
824         prefs_set_double_attribute("tools.shapes.star", "proportion", adj->value);
825     }
827     // quit if run by the attr_changed listener
828     if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
829         return;
830     }
832     // in turn, prevent listener from responding
833     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
835     bool modmade = false;
836     Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
837     GSList const *items = selection->itemList();
838     for (; items != NULL; items = items->next) {
839         if (SP_IS_STAR((SPItem *) items->data)) {
840             Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
842             gdouble r1 = sp_repr_get_double_attribute(repr, "sodipodi:r1", 1.0);
843             gdouble r2 = sp_repr_get_double_attribute(repr, "sodipodi:r2", 1.0);
844             if (r2 < r1) {
845                 sp_repr_set_svg_double(repr, "sodipodi:r2", r1*adj->value);
846             } else {
847                 sp_repr_set_svg_double(repr, "sodipodi:r1", r2*adj->value);
848             }
850             SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
851             modmade = true;
852         }
853     }
855     if (modmade) sp_document_done(SP_DT_DOCUMENT(desktop));
857     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
859     spinbutton_defocus(GTK_OBJECT(tbl));
862 static void
863 sp_stb_sides_flat_state_changed(GtkWidget *widget, GtkObject *tbl)
865     SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
867     if (sp_document_get_undo_sensitive(SP_DT_DOCUMENT(desktop))) {
868         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
869             prefs_set_string_attribute("tools.shapes.star", "isflatsided", "true");
870         } else {
871             prefs_set_string_attribute("tools.shapes.star", "isflatsided", "false");
872         }
873     }
875     // quit if run by the attr_changed listener
876     if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
877         return;
878     }
880     // in turn, prevent listener from responding
881     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
883     Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
884     GSList const *items = selection->itemList();
885     GtkWidget *prop_widget = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "prop_widget");
886     bool modmade = false;
887     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
888         gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), FALSE);
889         for (; items != NULL; items = items->next) {
890             if (SP_IS_STAR((SPItem *) items->data)) {
891                 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
892                 repr->setAttribute("inkscape:flatsided", "true");
893                 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
894                 modmade = true;
895             }
896         }
897     } else {
898         gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), TRUE);
899         for (; items != NULL; items = items->next) {
900             if (SP_IS_STAR((SPItem *) items->data)) {
901                 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
902                 repr->setAttribute("inkscape:flatsided", "false");
903                 SP_OBJECT(items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
904                 modmade = true;
905             }
906         }
907     }
908     if (modmade) sp_document_done(SP_DT_DOCUMENT(desktop));
910     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
912     spinbutton_defocus(GTK_OBJECT(tbl));
915 static void
916 sp_stb_rounded_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
918     SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
920     if (sp_document_get_undo_sensitive(SP_DT_DOCUMENT(desktop))) {
921         prefs_set_double_attribute("tools.shapes.star", "rounded", (gdouble) adj->value);
922     }
924     // quit if run by the attr_changed listener
925     if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
926         return;
927     }
929     // in turn, prevent listener from responding
930     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
932     bool modmade = false;
934     Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
935     GSList const *items = selection->itemList();
936     for (; items != NULL; items = items->next) {
937         if (SP_IS_STAR((SPItem *) items->data)) {
938             Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
939             sp_repr_set_svg_double(repr, "inkscape:rounded", (gdouble) adj->value);
940             SP_OBJECT(items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
941             modmade = true;
942         }
943     }
944     if (modmade)  sp_document_done(SP_DT_DOCUMENT(desktop));
946     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
948     spinbutton_defocus(GTK_OBJECT(tbl));
952 static void
953 sp_stb_randomized_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
955     SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
957     if (sp_document_get_undo_sensitive(SP_DT_DOCUMENT(desktop))) {
958         prefs_set_double_attribute("tools.shapes.star", "randomized", (gdouble) adj->value);
959     }
961     // quit if run by the attr_changed listener
962     if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
963         return;
964     }
966     // in turn, prevent listener from responding
967     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
969     bool modmade = false;
971     Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
972     GSList const *items = selection->itemList();
973     for (; items != NULL; items = items->next) {
974         if (SP_IS_STAR((SPItem *) items->data)) {
975             Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
976             sp_repr_set_svg_double(repr, "inkscape:randomized", (gdouble) adj->value);
977             SP_OBJECT(items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
978             modmade = true;
979         }
980     }
981     if (modmade)  sp_document_done(SP_DT_DOCUMENT(desktop));
983     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
985     spinbutton_defocus(GTK_OBJECT(tbl));
989 static void star_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
990                                        gchar const *old_value, gchar const *new_value,
991                                        bool is_interactive, gpointer data)
993     GtkWidget *tbl = GTK_WIDGET(data);
995     // quit if run by the _changed callbacks
996     if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
997         return;
998     }
1000     // in turn, prevent callbacks from responding
1001     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1003     GtkAdjustment *adj;
1005     if (!strcmp(name, "inkscape:randomized")) {
1006         adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "randomized");
1007         gtk_adjustment_set_value(adj, sp_repr_get_double_attribute(repr, "inkscape:randomized", 0.0));
1008     } else if (!strcmp(name, "inkscape:rounded")) {
1009         adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rounded");
1010         gtk_adjustment_set_value(adj, sp_repr_get_double_attribute(repr, "inkscape:rounded", 0.0));
1011     } else if (!strcmp(name, "inkscape:flatsided")) {
1012         GtkWidget *fscb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "flat_checkbox");
1013         GtkWidget *prop_widget = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "prop_widget");
1014         char const *flatsides = repr->attribute("inkscape:flatsided");
1015         if (flatsides && !strcmp(flatsides,"false" )) {
1016             gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb),  FALSE);
1017             gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), TRUE);
1018         } else {
1019             gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb),  TRUE);
1020             gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), FALSE);
1021         }
1022     } else if (!strcmp(name, "sodipodi:r1") || !strcmp(name, "sodipodi:r2")) {
1023         adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "proportion");
1024         gdouble r1 = sp_repr_get_double_attribute(repr, "sodipodi:r1", 1.0);
1025         gdouble r2 = sp_repr_get_double_attribute(repr, "sodipodi:r2", 1.0);
1026         if (r2 < r1) {
1027             gtk_adjustment_set_value(adj, r2/r1);
1028         } else {
1029             gtk_adjustment_set_value(adj, r1/r2);
1030         }
1031     } else if (!strcmp(name, "sodipodi:sides")) {
1032         adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "magnitude");
1033         gtk_adjustment_set_value(adj, sp_repr_get_int_attribute(repr, "sodipodi:sides", 0));
1034     }
1036     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1040 static Inkscape::XML::NodeEventVector star_tb_repr_events =
1042     NULL, /* child_added */
1043     NULL, /* child_removed */
1044     star_tb_event_attr_changed,
1045     NULL, /* content_changed */
1046     NULL  /* order_changed */
1047 };
1050 /**
1051  *  \param selection Should not be NULL.
1052  */
1053 static void
1054 sp_star_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1056     int n_selected = 0;
1057     Inkscape::XML::Node *repr = NULL;
1058     Inkscape::XML::Node *oldrepr = NULL;
1060     for (GSList const *items = selection->itemList();
1061          items != NULL;
1062          items = items->next)
1063     {
1064         if (SP_IS_STAR((SPItem *) items->data)) {
1065             n_selected++;
1066             repr = SP_OBJECT_REPR((SPItem *) items->data);
1067         }
1068     }
1070     GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
1072     if (n_selected == 0) {
1073         gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
1074     } else if (n_selected == 1) {
1075         gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1077         oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1078         if (oldrepr) { // remove old listener
1079             sp_repr_remove_listener_by_data(oldrepr, tbl);
1080             Inkscape::GC::release(oldrepr);
1081             oldrepr = 0;
1082             g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1083         }
1085         if (repr) {
1086             g_object_set_data(G_OBJECT(tbl), "repr", repr);
1087             Inkscape::GC::anchor(repr);
1088             sp_repr_add_listener(repr, &star_tb_repr_events, tbl);
1089         }
1090     } else {
1091         // FIXME: implement averaging of all parameters for multiple selected stars
1092         //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1093         gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1094     }
1098 static void
1099 sp_stb_defaults(GtkWidget *widget, GtkWidget *tbl)
1101     // FIXME: in this and all other _default functions, set some flag telling the value_changed
1102     // callbacks to lump all the changes for all selected objects in one undo step
1104     GtkAdjustment *adj;
1106     // fixme: make settable in prefs!
1107     gint mag = 5;
1108     gdouble prop = 0.5;
1109     gboolean flat = FALSE;
1110     gdouble randomized = 0;
1111     gdouble rounded = 0;
1113     GtkWidget *fscb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "flat_checkbox");
1114     gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb),  flat);
1115     GtkWidget *sb2 = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "prop_widget");
1116     gtk_widget_set_sensitive(GTK_WIDGET(sb2), !flat);
1118     adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "magnitude");
1119     gtk_adjustment_set_value(adj, mag);
1120     gtk_adjustment_value_changed(adj);
1122     adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "proportion");
1123     gtk_adjustment_set_value(adj, prop);
1124     gtk_adjustment_value_changed(adj);
1126     adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rounded");
1127     gtk_adjustment_set_value(adj, rounded);
1128     gtk_adjustment_value_changed(adj);
1130     adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "randomized");
1131     gtk_adjustment_set_value(adj, randomized);
1132     gtk_adjustment_value_changed(adj);
1134     spinbutton_defocus(GTK_OBJECT(tbl));
1138 void
1139 sp_toolbox_add_label(GtkWidget *tbl, gchar const *title, bool wide)
1141     GtkWidget *boxl = gtk_hbox_new(FALSE, 0);
1142     if (wide) gtk_widget_set_size_request(boxl, MODE_LABEL_WIDTH, -1);
1143     GtkWidget *l = gtk_label_new(NULL);
1144     gtk_label_set_markup(GTK_LABEL(l), title);
1145     gtk_box_pack_end(GTK_BOX(boxl), l, FALSE, FALSE, 0);
1146     gtk_box_pack_start(GTK_BOX(tbl), boxl, FALSE, FALSE, 0);
1147     gtk_object_set_data(GTK_OBJECT(tbl), "mode_label", l);
1151 static GtkWidget *
1152 sp_star_toolbox_new(SPDesktop *desktop)
1154     GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1156     gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1157     gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1159     GtkTooltips *tt = gtk_tooltips_new();
1161     sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1163     gchar const *flatsidedstr = NULL;
1165     /* Flatsided checkbox */
1166     {
1167         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1168         GtkWidget *fscb = gtk_check_button_new_with_label(_("Polygon"));
1169         gtk_widget_set_sensitive(GTK_WIDGET(fscb), TRUE);
1170         flatsidedstr = prefs_get_string_attribute("tools.shapes.star", "isflatsided");
1171         if (!flatsidedstr || (flatsidedstr && !strcmp(flatsidedstr, "false")))
1172             gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb),  FALSE);
1173         else
1174             gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb),  TRUE);
1175         gtk_tooltips_set_tip(tt, fscb, _("Regular polygon (with one handle) instead of a star"), NULL);
1176         gtk_widget_show(fscb);
1177         gtk_object_set_data(GTK_OBJECT(tbl), "flat_checkbox", fscb);
1178         gtk_container_add(GTK_CONTAINER(hb), fscb);
1179         g_signal_connect(G_OBJECT(fscb), "toggled", GTK_SIGNAL_FUNC(sp_stb_sides_flat_state_changed ), tbl);
1180         gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_SPACING);
1181     }
1183     aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
1185     /* Magnitude */
1186     {
1187         GtkWidget *hb = sp_tb_spinbutton(_("Corners:"), _("Number of corners of a polygon or star"),
1188                                          "tools.shapes.star", "magnitude", 3,
1189                                          NULL, tbl, TRUE, "altx-star",
1190                                          3, 1024, 1, 1,
1191                                          sp_stb_magnitude_value_changed, 1, 0);
1192         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1193     }
1195     /* Spoke ratio */
1196     {
1197         GtkWidget *hb = sp_tb_spinbutton(_("Spoke ratio:"),
1198                                          // TRANSLATORS: Tip radius of a star is the distance from the center to the farthest handle.
1199                                          // Base radius is the same for the closest handle.
1200                                          _("Base radius to tip radius ratio"),
1201                                          "tools.shapes.star", "proportion", 0.5,
1202                                          NULL, tbl, FALSE, NULL,
1203                                          0.01, 1.0, 0.01, 0.1,
1204                                          sp_stb_proportion_value_changed);
1205         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1206         g_object_set_data(G_OBJECT(tbl), "prop_widget", hb);
1207         if (!flatsidedstr || (flatsidedstr && !strcmp(flatsidedstr, "false")))
1208             gtk_widget_set_sensitive(GTK_WIDGET(hb), TRUE);
1209         else
1210             gtk_widget_set_sensitive(GTK_WIDGET(hb), FALSE);
1211     }
1213     /* Roundedness */
1214     {
1215         GtkWidget *hb = sp_tb_spinbutton(_("Rounded:"), _("How much rounded are the corners (0 for sharp)"),
1216                                          "tools.shapes.star", "rounded", 0.0,
1217                                          NULL, tbl, FALSE, NULL,
1218                                          -100.0, 100.0, 0.01, 0.1,
1219                                          sp_stb_rounded_value_changed);
1220         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1221     }
1223     /* Randomization */
1224     {
1225         GtkWidget *hb = sp_tb_spinbutton(_("Randomized:"), _("Scatter randomly the corners and angles"),
1226                                          "tools.shapes.star", "randomized", 0.0,
1227                                          NULL, tbl, FALSE, NULL,
1228                                          -10.0, 10.0, 0.001, 0.01,
1229                                          sp_stb_randomized_value_changed, 0.1, 3);
1230         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1231     }
1233     aux_toolbox_space(tbl, AUX_SPACING);
1235     /* Reset */
1236     {
1237         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1238         GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
1239         gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
1240         gtk_widget_show(b);
1241         gtk_container_add(GTK_CONTAINER(hb), b);
1242         gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_stb_defaults), tbl);
1243         gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_SPACING);
1244     }
1246     gtk_widget_show_all(tbl);
1247     sp_set_font_size_smaller (tbl);
1249     sigc::connection *connection = new sigc::connection(
1250         SP_DT_SELECTION(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_star_toolbox_selection_changed), (GtkObject *)tbl))
1251         );
1252     g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1254     return tbl;
1258 //########################
1259 //##       Rect         ##
1260 //########################
1262 static void 
1263 sp_rtb_sensitivize (GtkWidget *tbl)
1265     GtkAdjustment *adj1 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "rx"));
1266     GtkAdjustment *adj2 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "ry"));
1267     GtkWidget *not_rounded = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "not_rounded");
1269     if (adj1->value == 0 && adj2->value == 0 && gtk_object_get_data(GTK_OBJECT(tbl), "single")) { // only for a single selected rect (for now)
1270         gtk_widget_set_sensitive(GTK_WIDGET(not_rounded), FALSE);
1271     } else {
1272         gtk_widget_set_sensitive(GTK_WIDGET(not_rounded), TRUE);
1273     }
1277 static void
1278 sp_rtb_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name,
1279                           void (*setter)(SPRect *, gdouble))
1281     SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
1283     GtkWidget *us = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tbl), "units");
1284     SPUnit const *unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(us));
1286     if (sp_document_get_undo_sensitive(SP_DT_DOCUMENT(desktop))) {
1287         prefs_set_double_attribute("tools.shapes.rect", value_name, sp_units_get_pixels(adj->value, *unit));
1288     }
1290     // quit if run by the attr_changed listener
1291     if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1292         return;
1293     }
1295     // in turn, prevent listener from responding
1296     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1298     bool modmade = false;
1299     Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
1300     for (GSList const *items = selection->itemList(); items != NULL; items = items->next) {
1301         if (SP_IS_RECT(items->data)) {
1302             if (adj->value != 0) {
1303                 setter(SP_RECT(items->data), sp_units_get_pixels(adj->value, *unit));
1304             } else {
1305                 SP_OBJECT_REPR(items->data)->setAttribute(value_name, NULL);
1306             }
1307             modmade = true;
1308         }
1309     }
1311     sp_rtb_sensitivize (tbl);
1313     if (modmade) {
1314         sp_document_done(SP_DT_DOCUMENT(desktop));
1315     }
1317     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1319     // defocus spinbuttons by moving focus to the canvas, unless "stay" is on
1320     spinbutton_defocus(GTK_OBJECT(tbl));
1323 static void
1324 sp_rtb_rx_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1326     sp_rtb_value_changed(adj, tbl, "rx", sp_rect_set_visible_rx);
1329 static void
1330 sp_rtb_ry_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1332     sp_rtb_value_changed(adj, tbl, "ry", sp_rect_set_visible_ry);
1335 static void
1336 sp_rtb_width_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1338     sp_rtb_value_changed(adj, tbl, "width", sp_rect_set_visible_width);
1341 static void
1342 sp_rtb_height_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1344     sp_rtb_value_changed(adj, tbl, "height", sp_rect_set_visible_height);
1349 static void
1350 sp_rtb_defaults( GtkWidget *widget, GtkObject *obj)
1352     GtkWidget *tbl = GTK_WIDGET(obj);
1354     GtkAdjustment *adj;
1356     adj = (GtkAdjustment*)gtk_object_get_data(obj, "rx");
1357     gtk_adjustment_set_value(adj, 0.0);
1358     // this is necessary if the previous value was 0, but we still need to run the callback to change all selected objects
1359     gtk_adjustment_value_changed(adj);
1361     adj = (GtkAdjustment*)gtk_object_get_data(obj, "ry");
1362     gtk_adjustment_set_value(adj, 0.0);
1363     gtk_adjustment_value_changed(adj);
1365     sp_rtb_sensitivize (tbl);
1367     spinbutton_defocus(GTK_OBJECT(tbl));
1370 static void rect_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1371                                        gchar const *old_value, gchar const *new_value,
1372                                        bool is_interactive, gpointer data)
1374     GtkWidget *tbl = GTK_WIDGET(data);
1376     // quit if run by the _changed callbacks
1377     if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1378         return;
1379     }
1381     // in turn, prevent callbacks from responding
1382     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1384     GtkWidget *us = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tbl), "units");
1385     SPUnit const *unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(us));
1387     SPItem *item = SP_ITEM(g_object_get_data(G_OBJECT(tbl), "item"));
1388     if (SP_IS_RECT(item)) {
1389         {
1390             GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rx");
1391             gdouble rx = sp_rect_get_visible_rx(SP_RECT(item));
1392             gtk_adjustment_set_value(adj, sp_pixels_get_units(rx, *unit));
1393         }
1395         {
1396             GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "ry");
1397             gdouble ry = sp_rect_get_visible_ry(SP_RECT(item));
1398             gtk_adjustment_set_value(adj, sp_pixels_get_units(ry, *unit));
1399         }
1401         {
1402             GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "width");
1403             gdouble width = sp_rect_get_visible_width (SP_RECT(item));
1404             gtk_adjustment_set_value(adj, sp_pixels_get_units(width, *unit));
1405         }
1407         {
1408             GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "height");
1409             gdouble height = sp_rect_get_visible_height (SP_RECT(item));
1410             gtk_adjustment_set_value(adj, sp_pixels_get_units(height, *unit));
1411         }
1412     }
1414     sp_rtb_sensitivize (tbl);
1416     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1420 static Inkscape::XML::NodeEventVector rect_tb_repr_events = {
1421     NULL, /* child_added */
1422     NULL, /* child_removed */
1423     rect_tb_event_attr_changed,
1424     NULL, /* content_changed */
1425     NULL  /* order_changed */
1426 };
1428 /**
1429  *  \param selection should not be NULL.
1430  */
1431 static void
1432 sp_rect_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1434     int n_selected = 0;
1435     Inkscape::XML::Node *repr = NULL;
1436     SPItem *item = NULL;
1437     Inkscape::XML::Node *oldrepr = NULL;
1439     for (GSList const *items = selection->itemList();
1440          items != NULL;
1441          items = items->next) {
1442         if (SP_IS_RECT((SPItem *) items->data)) {
1443             n_selected++;
1444             item = (SPItem *) items->data;
1445             repr = SP_OBJECT_REPR(item);
1446         }
1447     }
1449     GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
1451     g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(FALSE));
1453     if (n_selected == 0) {
1454         gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
1456         GtkWidget *w = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "width_sb");
1457         gtk_widget_set_sensitive(w, FALSE);
1458         GtkWidget *h = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "height_sb");
1459         gtk_widget_set_sensitive(h, FALSE);
1461     } else if (n_selected == 1) {
1462         gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1463         g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
1465         GtkWidget *w = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "width_sb");
1466         gtk_widget_set_sensitive(w, TRUE);
1467         GtkWidget *h = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "height_sb");
1468         gtk_widget_set_sensitive(h, TRUE);
1470         oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1471         if (oldrepr) { // remove old listener
1472             sp_repr_remove_listener_by_data(oldrepr, tbl);
1473             Inkscape::GC::release(oldrepr);
1474             oldrepr = 0;
1475             g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1476         }
1477         if (repr) {
1478             g_object_set_data(G_OBJECT(tbl), "repr", repr);
1479             g_object_set_data(G_OBJECT(tbl), "item", item);
1480             Inkscape::GC::anchor(repr);
1481             sp_repr_add_listener(repr, &rect_tb_repr_events, tbl);
1482         }
1483     } else {
1484         // FIXME: implement averaging of all parameters for multiple selected
1485         //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1486         gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1487         sp_rtb_sensitivize (GTK_WIDGET(tbl));
1488     }
1492 static GtkWidget *
1493 sp_rect_toolbox_new(SPDesktop *desktop)
1495     GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1497     gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1498     gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1500     GtkTooltips *tt = gtk_tooltips_new();
1502     sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1504     // rx/ry units menu: create
1505     GtkWidget *us = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
1506     sp_unit_selector_setsize(us, AUX_OPTION_MENU_WIDTH, AUX_OPTION_MENU_HEIGHT);
1507     sp_unit_selector_set_unit(SP_UNIT_SELECTOR(us), desktop->namedview->doc_units);
1508     // fixme: add % meaning per cent of the width/height
1510     /* W */
1511     {
1512         GtkWidget *hb = sp_tb_spinbutton(_("W:"), _("Width of rectangle"),
1513                                          "tools.shapes.rect", "width", 0,
1514                                          us, tbl, TRUE, "altx-rect",
1515                                          0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1516                                          sp_rtb_width_value_changed);
1517         gtk_object_set_data(GTK_OBJECT(tbl), "width_sb", hb);
1518         gtk_widget_set_sensitive(hb, FALSE);
1519         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1520     }
1522     /* H */
1523     {
1524         GtkWidget *hb = sp_tb_spinbutton(_("H:"), _("Height of rectangle"),
1525                                          "tools.shapes.rect", "height", 0,
1526                                          us, tbl, FALSE, NULL,
1527                                          0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1528                                          sp_rtb_height_value_changed);
1529         gtk_object_set_data(GTK_OBJECT(tbl), "height_sb", hb);
1530         gtk_widget_set_sensitive(hb, FALSE);
1531         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1532     }
1534     /* rx */
1535     {
1536         GtkWidget *hb = sp_tb_spinbutton(_("Rx:"), _("Horizontal radius of rounded corners"),
1537                                          "tools.shapes.rect", "rx", 0,
1538                                          us, tbl, FALSE, NULL,
1539                                          0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1540                                          sp_rtb_rx_value_changed);
1541         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1542     }
1544     /* ry */
1545     {
1546         GtkWidget *hb = sp_tb_spinbutton(_("Ry:"), _("Vertical radius of rounded corners"),
1547                                          "tools.shapes.rect", "ry", 0,
1548                                          us, tbl, FALSE, NULL,
1549                                          0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1550                                          sp_rtb_ry_value_changed);
1551         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1552     }
1554     // add the units menu
1555     gtk_widget_show(us);
1556     gtk_box_pack_start(GTK_BOX(tbl), us, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1557     gtk_object_set_data(GTK_OBJECT(tbl), "units", us);
1559     /* Reset */
1560     {
1561         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1562         GtkWidget *b = gtk_button_new_with_label(_("Not rounded"));
1563         gtk_object_set_data(GTK_OBJECT(tbl), "not_rounded", b);
1564         gtk_tooltips_set_tip(tt, b, _("Make corners sharp"), NULL);
1565         gtk_widget_show(b);
1566         gtk_container_add(GTK_CONTAINER(hb), b);
1567         gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_rtb_defaults), tbl);
1568         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1569     }
1571     g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
1572     sp_rtb_sensitivize (tbl);
1574     gtk_widget_show_all(tbl);
1575     sp_set_font_size_smaller (tbl);
1577     sigc::connection *connection = new sigc::connection(
1578         SP_DT_SELECTION(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_rect_toolbox_selection_changed), (GtkObject *)tbl))
1579         );
1580     g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1582     return tbl;
1585 //########################
1586 //##       Spiral       ##
1587 //########################
1589 static void
1590 sp_spl_tb_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name)
1592     SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
1594     if (sp_document_get_undo_sensitive(SP_DT_DOCUMENT(desktop))) {
1595         prefs_set_double_attribute("tools.shapes.spiral", value_name, adj->value);
1596     }
1598     // quit if run by the attr_changed listener
1599     if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1600         return;
1601     }
1603     // in turn, prevent listener from responding
1604     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1606     gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
1608     bool modmade = false;
1609     for (GSList const *items = SP_DT_SELECTION(desktop)->itemList();
1610          items != NULL;
1611          items = items->next)
1612     {
1613         if (SP_IS_SPIRAL((SPItem *) items->data)) {
1614             Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
1615             sp_repr_set_svg_double( repr, namespaced_name, adj->value );
1616             SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
1617             modmade = true;
1618         }
1619     }
1621     g_free(namespaced_name);
1623     if (modmade) {
1624         sp_document_done(SP_DT_DOCUMENT(desktop));
1625     }
1627     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1629     spinbutton_defocus(GTK_OBJECT(tbl));
1632 static void
1633 sp_spl_tb_revolution_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1635     sp_spl_tb_value_changed(adj, tbl, "revolution");
1638 static void
1639 sp_spl_tb_expansion_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1641     sp_spl_tb_value_changed(adj, tbl, "expansion");
1644 static void
1645 sp_spl_tb_t0_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1647     sp_spl_tb_value_changed(adj, tbl, "t0");
1650 static void
1651 sp_spl_tb_defaults(GtkWidget *widget, GtkObject *obj)
1653     GtkWidget *tbl = GTK_WIDGET(obj);
1655     GtkAdjustment *adj;
1657     // fixme: make settable
1658     gdouble rev = 5;
1659     gdouble exp = 1.0;
1660     gdouble t0 = 0.0;
1662     adj = (GtkAdjustment*)gtk_object_get_data(obj, "revolution");
1663     gtk_adjustment_set_value(adj, rev);
1664     gtk_adjustment_value_changed(adj);
1666     adj = (GtkAdjustment*)gtk_object_get_data(obj, "expansion");
1667     gtk_adjustment_set_value(adj, exp);
1668     gtk_adjustment_value_changed(adj);
1670     adj = (GtkAdjustment*)gtk_object_get_data(obj, "t0");
1671     gtk_adjustment_set_value(adj, t0);
1672     gtk_adjustment_value_changed(adj);
1674     spinbutton_defocus(GTK_OBJECT(tbl));
1678 static void spiral_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1679                                          gchar const *old_value, gchar const *new_value,
1680                                          bool is_interactive, gpointer data)
1682     GtkWidget *tbl = GTK_WIDGET(data);
1684     // quit if run by the _changed callbacks
1685     if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1686         return;
1687     }
1689     // in turn, prevent callbacks from responding
1690     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1692     GtkAdjustment *adj;
1693     adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "revolution");
1694     gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:revolution", 3.0)));
1696     adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "expansion");
1697     gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:expansion", 1.0)));
1699     adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "t0");
1700     gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:t0", 0.0)));
1702     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1706 static Inkscape::XML::NodeEventVector spiral_tb_repr_events = {
1707     NULL, /* child_added */
1708     NULL, /* child_removed */
1709     spiral_tb_event_attr_changed,
1710     NULL, /* content_changed */
1711     NULL  /* order_changed */
1712 };
1714 static void
1715 sp_spiral_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1717     int n_selected = 0;
1718     Inkscape::XML::Node *repr = NULL;
1719     Inkscape::XML::Node *oldrepr = NULL;
1721     for (GSList const *items = selection->itemList();
1722          items != NULL;
1723          items = items->next)
1724     {
1725         if (SP_IS_SPIRAL((SPItem *) items->data)) {
1726             n_selected++;
1727             repr = SP_OBJECT_REPR((SPItem *) items->data);
1728         }
1729     }
1731     GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
1733     if (n_selected == 0) {
1734         gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
1735     } else if (n_selected == 1) {
1736         gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1738         oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1739         if (oldrepr) { // remove old listener
1740             sp_repr_remove_listener_by_data(oldrepr, tbl);
1741             Inkscape::GC::release(oldrepr);
1742             oldrepr = 0;
1743             g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1744         }
1746         if (repr) {
1747             g_object_set_data(G_OBJECT(tbl), "repr", repr);
1748             Inkscape::GC::anchor(repr);
1749             sp_repr_add_listener(repr, &spiral_tb_repr_events, tbl);
1750         }
1751     } else {
1752         // FIXME: implement averaging of all parameters for multiple selected
1753         //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1754         gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1755     }
1759 static GtkWidget *
1760 sp_spiral_toolbox_new(SPDesktop *desktop)
1762     GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1763     gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1764     gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1766     GtkTooltips *tt = gtk_tooltips_new();
1768     sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1770     /* Revolution */
1771     {
1772         GtkWidget *hb = sp_tb_spinbutton(_("Turns:"), _("Number of revolutions"),
1773                                          "tools.shapes.spiral", "revolution", 3.0,
1774                                          NULL, tbl, TRUE, "altx-spiral",
1775                                          0.01, 1024.0, 0.1, 1.0,
1776                                          sp_spl_tb_revolution_value_changed, 1, 2);
1777         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1778     }
1780     /* Expansion */
1781     {
1782         GtkWidget *hb = sp_tb_spinbutton(_("Divergence:"), _("How much denser/sparser are outer revolutions; 1 = uniform"),
1783                                          "tools.shapes.spiral", "expansion", 1.0,
1784                                          NULL, tbl, FALSE, NULL,
1785                                          0.0, 1000.0, 0.01, 1.0,
1786                                          sp_spl_tb_expansion_value_changed);
1787         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1788     }
1790     /* T0 */
1791     {
1792         GtkWidget *hb = sp_tb_spinbutton(_("Inner radius:"), _("Radius of the innermost revolution (relative to the spiral size)"),
1793                                          "tools.shapes.spiral", "t0", 0.0,
1794                                          NULL, tbl, FALSE, NULL,
1795                                          0.0, 0.999, 0.01, 1.0,
1796                                          sp_spl_tb_t0_value_changed);
1797         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1798     }
1800     aux_toolbox_space(tbl, AUX_SPACING);
1802     /* Reset */
1803     {
1804         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1805         GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
1806         gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
1807         gtk_widget_show(b);
1808         gtk_container_add(GTK_CONTAINER(hb), b);
1809         gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_spl_tb_defaults), tbl);
1810         gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1811     }
1813     gtk_widget_show_all(tbl);
1814     sp_set_font_size_smaller (tbl);
1816     sigc::connection *connection = new sigc::connection(
1817         SP_DT_SELECTION(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_spiral_toolbox_selection_changed), (GtkObject *)tbl))
1818         );
1819     g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1821     return tbl;
1825 //########################
1826 //##     Calligraphy    ##
1827 //########################
1829 static void
1830 sp_ddc_mass_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1832     prefs_set_double_attribute("tools.calligraphic", "mass", adj->value);
1833     spinbutton_defocus(GTK_OBJECT(tbl));
1836 static void
1837 sp_ddc_drag_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1839     prefs_set_double_attribute("tools.calligraphic", "drag", adj->value);
1840     spinbutton_defocus(GTK_OBJECT(tbl));
1843 static void
1844 sp_ddc_angle_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1846     prefs_set_double_attribute("tools.calligraphic", "angle", adj->value);
1847     spinbutton_defocus(GTK_OBJECT(tbl));
1850 static void
1851 sp_ddc_width_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1853     prefs_set_double_attribute("tools.calligraphic", "width", adj->value);
1854     spinbutton_defocus(GTK_OBJECT(tbl));
1857 static void
1858 sp_ddc_velthin_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1860     prefs_set_double_attribute("tools.calligraphic", "thinning", adj->value);
1861     spinbutton_defocus(GTK_OBJECT(tbl));
1864 static void
1865 sp_ddc_flatness_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1867     prefs_set_double_attribute("tools.calligraphic", "flatness", adj->value);
1868     spinbutton_defocus(GTK_OBJECT(tbl));
1871 static void
1872 sp_ddc_tremor_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1874     prefs_set_double_attribute("tools.calligraphic", "tremor", adj->value);
1875     spinbutton_defocus(GTK_OBJECT(tbl));
1878 static void
1879 sp_ddc_pressure_state_changed(GtkWidget *button, gpointer data)
1881     prefs_set_int_attribute ("tools.calligraphic", "usepressure", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0);
1884 static void
1885 sp_ddc_tilt_state_changed(GtkWidget *button, GtkWidget *calligraphy_angle)
1887     prefs_set_int_attribute ("tools.calligraphic", "usetilt", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0);
1889     gtk_widget_set_sensitive(GTK_WIDGET(calligraphy_angle), !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
1892 static void sp_ddc_defaults(GtkWidget *, GtkWidget *tbl)
1894     // FIXME: make defaults settable via Inkscape Options
1895     struct KeyValue {
1896         char const *key;
1897         double value;
1898     } const key_values[] = {
1899         {"mass", 0.02},
1900         {"drag", 1.0},
1901         {"angle", 30.0},
1902         {"width", 0.15},
1903         {"thinning", 0.1},
1904         {"tremor", 0.0},
1905         {"flatness", 0.9}
1906     };
1908     for (unsigned i = 0; i < G_N_ELEMENTS(key_values); ++i) {
1909         KeyValue const &kv = key_values[i];
1910         GtkAdjustment &adj = *static_cast<GtkAdjustment *>(gtk_object_get_data(GTK_OBJECT(tbl), kv.key));
1911         gtk_adjustment_set_value(&adj, kv.value);
1912     }
1914     spinbutton_defocus(GTK_OBJECT(tbl));
1917 static GtkWidget *
1918 sp_calligraphy_toolbox_new(SPDesktop *desktop)
1920     GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1921     gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1922     gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1924     GtkTooltips *tt = gtk_tooltips_new();
1925     GtkWidget *calligraphy_angle;
1927     //  interval
1928     gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1930     /* Width */
1931     {
1932         GtkWidget *hb = sp_tb_spinbutton(_("Width:"), _("The width of the calligraphic pen (relative to the visible canvas area)"),
1933                                          "tools.calligraphic", "width", 0.15,
1934                                          NULL, tbl, TRUE, "altx-calligraphy",
1935                                          0.01, 1.0, 0.01, 0.1,
1936                                          sp_ddc_width_value_changed,  0.01, 2);
1937         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1938     }
1940     /* Thinning */
1941     {
1942         GtkWidget *hb = sp_tb_spinbutton(_("Thinning:"), _("How much velocity thins the stroke (> 0 makes fast strokes thinner, < 0 makes them broader, 0 makes width independent of velocity)"),
1943                                          "tools.calligraphic", "thinning", 0.1,
1944                                          NULL, tbl, FALSE, NULL,
1945                                          -1.0, 1.0, 0.01, 0.1,
1946                                          sp_ddc_velthin_value_changed, 0.01, 2);
1947         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1948     }
1950     //  interval
1951     gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1953     /* Angle */
1954     {
1955         calligraphy_angle = sp_tb_spinbutton(_("Angle:"), _("The angle of the pen's nib (in degrees; 0 = horizontal; has no effect if fixation = 0)"),
1956                                              "tools.calligraphic", "angle", 30,
1957                                              NULL, tbl, TRUE, "calligraphy-angle",
1958                                              -90.0, 90.0, 1.0, 10.0,
1959                                              sp_ddc_angle_value_changed, 1, 0);
1960         gtk_box_pack_start(GTK_BOX(tbl), calligraphy_angle, FALSE, FALSE, AUX_SPACING);
1961     }
1963     /* Fixation */
1964     {
1965         GtkWidget *hb = sp_tb_spinbutton(_("Fixation:"), _("How fixed is the pen angle (0 = always perpendicular to stroke direction, 1 = fixed)"),
1966                                          "tools.calligraphic", "flatness", 0.9,
1967                                          NULL, tbl, FALSE, NULL,
1968                                          0.0, 1.0, 0.01, 0.1,
1969                                          sp_ddc_flatness_value_changed, 0.01, 2);
1970         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1971     }
1973     //  interval
1974     gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1976     /* Tremor */
1977     {
1978         GtkWidget *hb = sp_tb_spinbutton(_("Tremor:"), _("How uneven or trembling is the pen stroke"),
1979                                          "tools.calligraphic", "tremor", 0.0,
1980                                          NULL, tbl, FALSE, NULL,
1981                                          0.0, 1.0, 0.01, 0.1,
1982                                          sp_ddc_tremor_value_changed, 0.01, 2);
1983         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1984     }
1985     /* Mass */
1986     {
1987         GtkWidget *hb = sp_tb_spinbutton(_("Mass:"), _("How much inertia affects the movement of the pen"),
1988                                          "tools.calligraphic", "mass", 0.02,
1989                                          NULL, tbl, FALSE, NULL,
1990                                          0.0, 1.0, 0.01, 0.1,
1991                                          sp_ddc_mass_value_changed, 0.01, 2);
1992         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1993     }
1995     /* Drag */
1996     {
1997         // TRANSLATORS: "drag" means "resistance" here
1998         GtkWidget *hb = sp_tb_spinbutton(_("Drag:"), _("How much resistance affects the movement of the pen"),
1999                                          "tools.calligraphic", "drag", 1,
2000                                          NULL, tbl, FALSE, NULL,
2001                                          0.0, 1.0, 0.01, 0.1,
2002                                          sp_ddc_drag_value_changed, 0.01, 2);
2003         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2004     }
2006     //  interval
2007     gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2009     GtkWidget *cvbox = gtk_vbox_new (FALSE, 0);
2010     GtkWidget *cbox = gtk_hbox_new (FALSE, 0);
2012     /* Use Pressure button */
2013     {
2014     GtkWidget *button = sp_button_new_from_data( GTK_ICON_SIZE_SMALL_TOOLBAR,
2015                                                  SP_BUTTON_TYPE_TOGGLE,
2016                                                  NULL,
2017                                                  "use_pressure",
2018                                                  _("Use the pressure of the input device to alter the width of the pen"),
2019                                                  tt);
2020     g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (sp_ddc_pressure_state_changed), NULL);
2021     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.calligraphic", "usepressure", 1));
2022     gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
2023     }
2025     /* Use Tilt button */
2026     {
2027     GtkWidget *button = sp_button_new_from_data( GTK_ICON_SIZE_SMALL_TOOLBAR,
2028                                                  SP_BUTTON_TYPE_TOGGLE,
2029                                                  NULL,
2030                                                  "use_tilt",
2031                                                  _("Use the tilt of the input device to alter the angle of the pen's nib"),
2032                                                  tt);
2033     g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (sp_ddc_tilt_state_changed), calligraphy_angle);
2034     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.calligraphic", "usetilt", 1));
2035     gtk_widget_set_sensitive(GTK_WIDGET(calligraphy_angle), !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
2036     gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
2037     }
2039     gtk_box_pack_start(GTK_BOX(cvbox), cbox, TRUE, FALSE, 0);
2040     gtk_box_pack_start(GTK_BOX(tbl), cvbox, FALSE, FALSE, 0);
2042     /* Reset */
2043     {
2044         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2045         GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
2046         gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
2047         gtk_widget_show(b);
2048         gtk_container_add(GTK_CONTAINER(hb), b);
2049         gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_ddc_defaults), tbl);
2050         gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2051     }
2053 /*
2054      // Tablet features
2055     {
2056         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2057         GtkWidget *fscb = gtk_check_button_new_with_label(_("Tablet"));
2058         gtk_widget_set_sensitive(GTK_WIDGET(fscb), TRUE);
2063         gtk_tooltips_set_tip(tt, fscb, _("Enable/Disable drawing tablet features"), NULL);
2064         gtk_widget_show(fscb);
2065         gtk_object_set_data(GTK_OBJECT(tbl), "flat_checkbox", fscb);
2066         gtk_container_add(GTK_CONTAINER(hb), fscb);
2068         gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_SPACING);
2069     }
2070 */
2072     gtk_widget_show_all(tbl);
2073     sp_set_font_size_smaller (tbl);
2075     return tbl;
2079 //########################
2080 //##    Circle / Arc    ##
2081 //########################
2083 static void 
2084 sp_arctb_sensitivize (GtkWidget *tbl, double v1, double v2)
2086     GtkWidget *ocb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "open_checkbox");
2087     GtkWidget *make_whole = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "make_whole");
2089     if (v1 == 0 && v2 == 0) {
2090         if (gtk_object_get_data(GTK_OBJECT(tbl), "single")) { // only for a single selected ellipse (for now)
2091             gtk_widget_set_sensitive(GTK_WIDGET(ocb), FALSE);
2092             gtk_widget_set_sensitive(GTK_WIDGET(make_whole), FALSE);
2093         }
2094     } else {
2095         gtk_widget_set_sensitive(GTK_WIDGET(ocb), TRUE);
2096         gtk_widget_set_sensitive(GTK_WIDGET(make_whole), TRUE);
2097     }
2100 static void
2101 sp_arctb_startend_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name, gchar const *other_name)
2103     SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2105     if (sp_document_get_undo_sensitive(SP_DT_DOCUMENT(desktop))) {
2106         prefs_set_double_attribute("tools.shapes.arc", value_name, (adj->value * M_PI)/ 180);
2107     }
2109     // quit if run by the attr_changed listener
2110     if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2111         return;
2112     }
2114     // in turn, prevent listener from responding
2115     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2117     gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
2119     bool modmade = false;
2120     for (GSList const *items = SP_DT_SELECTION(desktop)->itemList();
2121          items != NULL;
2122          items = items->next)
2123     {
2124         SPItem *item = SP_ITEM(items->data);
2126         if (SP_IS_ARC(item) && SP_IS_GENERICELLIPSE(item)) {
2128             SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
2129             SPArc *arc = SP_ARC(item);
2131             if (!strcmp(value_name, "start"))
2132                 ge->start = (adj->value * M_PI)/ 180;
2133             else
2134                 ge->end = (adj->value * M_PI)/ 180;
2136             sp_genericellipse_normalize(ge);
2137             ((SPObject *)arc)->updateRepr();
2138             ((SPObject *)arc)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
2140             modmade = true;
2141         }
2142     }
2144     g_free(namespaced_name);
2146     GtkAdjustment *other = (GtkAdjustment *)gtk_object_get_data(GTK_OBJECT(tbl), other_name);
2148     sp_arctb_sensitivize (tbl, adj->value, other->value);
2150     if (modmade) {
2151         sp_document_maybe_done(SP_DT_DOCUMENT(desktop), value_name);
2152     }
2154     // defocus spinbuttons by moving focus to the canvas, unless "stay" is on
2155     spinbutton_defocus(GTK_OBJECT(tbl));
2157     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2161 static void
2162 sp_arctb_start_value_changed(GtkAdjustment *adj,  GtkWidget *tbl)
2164     sp_arctb_startend_value_changed(adj,  tbl, "start", "end");
2167 static void
2168 sp_arctb_end_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
2170     sp_arctb_startend_value_changed(adj,  tbl, "end", "start");
2173 static void
2174 sp_arctb_open_state_changed(GtkWidget *widget, GtkObject *tbl)
2176     SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2178     if (sp_document_get_undo_sensitive(SP_DT_DOCUMENT(desktop))) {
2179         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
2180             prefs_set_string_attribute("tools.shapes.arc", "open", "true");
2181         } else {
2182             prefs_set_string_attribute("tools.shapes.arc", "open", NULL);
2183         }
2184     }
2186     // quit if run by the attr_changed listener
2187     if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2188         return;
2189     }
2191     // in turn, prevent listener from responding
2192     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2194     bool modmade = false;
2196     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
2197         for (GSList const *items = SP_DT_SELECTION(desktop)->itemList();
2198              items != NULL;
2199              items = items->next)
2200         {
2201             if (SP_IS_ARC((SPItem *) items->data)) {
2202                 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2203                 repr->setAttribute("sodipodi:open", "true");
2204                 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
2205                 modmade = true;
2206             }
2207         }
2208     } else {
2209         for (GSList const *items = SP_DT_SELECTION(desktop)->itemList();
2210              items != NULL;
2211              items = items->next)
2212         {
2213             if (SP_IS_ARC((SPItem *) items->data))    {
2214                 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2215                 repr->setAttribute("sodipodi:open", NULL);
2216                 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
2217                 modmade = true;
2218             }
2219         }
2220     }
2222     if (modmade) {
2223         sp_document_done(SP_DT_DOCUMENT(desktop));
2224     }
2226     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2228     spinbutton_defocus(GTK_OBJECT(tbl));
2231 static void sp_arctb_defaults(GtkWidget *, GtkObject *obj)
2233     GtkWidget *tbl = GTK_WIDGET(obj);
2235     GtkAdjustment *adj;
2236     adj = (GtkAdjustment*)gtk_object_get_data(obj, "start");
2237     gtk_adjustment_set_value(adj, 0.0);
2238     gtk_adjustment_value_changed(adj);
2240     adj = (GtkAdjustment*)gtk_object_get_data(obj, "end");
2241     gtk_adjustment_set_value(adj, 0.0);
2242     gtk_adjustment_value_changed(adj);
2244     spinbutton_defocus(GTK_OBJECT(tbl));
2247 static void arc_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
2248                                       gchar const *old_value, gchar const *new_value,
2249                                       bool is_interactive, gpointer data)
2251     GtkWidget *tbl = GTK_WIDGET(data);
2253     // quit if run by the _changed callbacks
2254     if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2255         return;
2256     }
2258     // in turn, prevent callbacks from responding
2259     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2261     gdouble start = sp_repr_get_double_attribute(repr, "sodipodi:start", 0.0);
2262     gdouble end = sp_repr_get_double_attribute(repr, "sodipodi:end", 0.0);
2264     GtkAdjustment *adj1,*adj2;
2265     adj1 = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "start");
2266     gtk_adjustment_set_value(adj1, mod360((start * 180)/M_PI));
2267     adj2 = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "end");
2268     gtk_adjustment_set_value(adj2, mod360((end * 180)/M_PI));
2270     sp_arctb_sensitivize (tbl, adj1->value, adj2->value);
2272     char const *openstr = NULL;
2273     openstr = repr->attribute("sodipodi:open");
2274     GtkWidget *ocb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "open_checkbox");
2276     if (openstr) {
2277         gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ocb),  TRUE);
2278     } else {
2279         gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ocb),  FALSE);
2280     }
2282     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2285 static Inkscape::XML::NodeEventVector arc_tb_repr_events = {
2286     NULL, /* child_added */
2287     NULL, /* child_removed */
2288     arc_tb_event_attr_changed,
2289     NULL, /* content_changed */
2290     NULL  /* order_changed */
2291 };
2294 static void
2295 sp_arc_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
2297     int n_selected = 0;
2298     Inkscape::XML::Node *repr = NULL;
2299     Inkscape::XML::Node *oldrepr = NULL;
2301     for (GSList const *items = selection->itemList();
2302          items != NULL;
2303          items = items->next)
2304     {
2305         if (SP_IS_ARC((SPItem *) items->data)) {
2306             n_selected++;
2307             repr = SP_OBJECT_REPR((SPItem *) items->data);
2308         }
2309     }
2311     GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
2313     g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(FALSE));
2314     if (n_selected == 0) {
2315         gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
2316     } else if (n_selected == 1) {
2317         g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
2318         gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2320         oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
2322         if (oldrepr) { // remove old listener
2323             sp_repr_remove_listener_by_data(oldrepr, tbl);
2324             Inkscape::GC::release(oldrepr);
2325             oldrepr = 0;
2326             g_object_set_data(G_OBJECT(tbl), "repr", NULL);
2327         }
2329         if (repr) {
2330             g_object_set_data(G_OBJECT(tbl), "repr", repr);
2331             Inkscape::GC::anchor(repr);
2332             sp_repr_add_listener(repr, &arc_tb_repr_events, tbl);
2333         }
2334     } else {
2335         // FIXME: implement averaging of all parameters for multiple selected
2336         //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
2337         gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2338         sp_arctb_sensitivize (GTK_WIDGET(tbl), 1, 0);
2339     }
2343 static GtkWidget *
2344 sp_arc_toolbox_new(SPDesktop *desktop)
2346     GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2348     gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2349     gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2351     GtkTooltips *tt = gtk_tooltips_new();
2353     sp_toolbox_add_label(tbl, _("<b>New:</b>"));
2355     /* Start */
2356     {
2357         GtkWidget *hb = sp_tb_spinbutton(_("Start:"), _("The angle (in degrees) from the horizontal to the arc's start point"),
2358                                          "tools.shapes.arc", "start", 0.0,
2359                                          NULL, tbl, TRUE, "altx-arc",
2360                                          -360.0, 360.0, 1.0, 10.0,
2361                                          sp_arctb_start_value_changed);
2362         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2363     }
2365     /* End */
2366     {
2367         GtkWidget *hb = sp_tb_spinbutton(_("End:"), _("The angle (in degrees) from the horizontal to the arc's end point"),
2368                                          "tools.shapes.arc", "end", 0.0,
2369                                          NULL, tbl, FALSE, NULL,
2370                                          -360.0, 360.0, 1.0, 10.0,
2371                                          sp_arctb_end_value_changed);
2372         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2373     }
2375     /* Segments / Pie checkbox */
2376     {
2377         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2378         GtkWidget *fscb = gtk_check_button_new_with_label(_("Open arc"));
2379         gtk_tooltips_set_tip(tt, fscb, _("Switch between arc (unclosed shape) and segment (closed shape with two radii)"), NULL);
2381         gchar const *openstr = NULL;
2382         openstr = prefs_get_string_attribute("tools.shapes.arc", "open");
2383         if (!openstr || (openstr && !strcmp(openstr, "false")))
2384             gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb),  FALSE);
2385         else
2386             gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb),  TRUE);
2388         gtk_widget_show(fscb);
2389         gtk_object_set_data(GTK_OBJECT(tbl), "open_checkbox", fscb);
2390         gtk_container_add(GTK_CONTAINER(hb), fscb);
2391         g_signal_connect(G_OBJECT(fscb), "toggled", GTK_SIGNAL_FUNC(sp_arctb_open_state_changed ), tbl);
2392         gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2393     }
2395     /* Make Whole */
2396     {
2397         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2398         GtkWidget *b = gtk_button_new_with_label(_("Make whole"));
2399         gtk_object_set_data(GTK_OBJECT(tbl), "make_whole", b);
2400         gtk_tooltips_set_tip(tt, b, _("Make the shape a whole ellipse, not arc or segment"), NULL);
2401         gtk_widget_show(b);
2402         gtk_container_add(GTK_CONTAINER(hb), b);
2403         gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_arctb_defaults), tbl);
2404         gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2405     }
2407     g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
2408     // sensitivize make whole and open checkbox
2409     {
2410         GtkAdjustment *adj1 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "start"));
2411         GtkAdjustment *adj2 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "end"));
2412         sp_arctb_sensitivize (tbl, adj1->value, adj2->value);
2413     }
2415     sigc::connection *connection = new sigc::connection(
2416         SP_DT_SELECTION(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_arc_toolbox_selection_changed), (GtkObject *)tbl))
2417         );
2418     g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
2420     gtk_widget_show_all(tbl);
2421     sp_set_font_size_smaller (tbl);
2423     return tbl;
2429 // toggle button callbacks and updaters
2431 //########################
2432 //##      Dropper       ##
2433 //########################
2435 static void toggle_dropper_color_pick (GtkWidget *button, gpointer data) {
2436     prefs_set_int_attribute ("tools.dropper", "pick", 
2437         // 0 and 1 are backwards here because of pref
2438         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1);
2442 /**
2443  * Copy the current saved desktop color to the clipboard as full hex + alpha
2444  * color representation. This is useful for passing values between various 
2445  * input boxes, or directly to xml.
2446  */
2447 /* static void
2448 sp_dropper_copy( GtkWidget *widget, GtkObject *obj)
2450     GtkWidget *tbl = GTK_WIDGET(obj);
2451     
2452     SPDesktop *desktop = 
2453         (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2455    
2456     sp_dropper_c32_color_copy( sp_desktop_get_color(desktop, true) );
2457 }*/
2460 /**
2461  * Copies currently saved desktop color to the clipboard as a hex value. This 
2462  * is useful for editing webpages and needing a value quickly for web
2463  * colors.
2464  * 
2465  * TODO: When the toggle of the dropper is set to not mix color against 
2466  *       page background, this still just gets the color of the page and 
2467  *       doesn't get the actual mixed against background which is needed 
2468  *       for the hex value ppl. want for web pages, etc.
2469  */
2471 /* static void
2472 sp_dropper_copy_as_hex ( GtkWidget *widget, GtkObject *obj)
2474     GtkWidget *tbl = GTK_WIDGET(obj);
2475     
2476     SPDesktop *desktop = 
2477         (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2478     
2479     sp_dropper_c32_color_copy_hex( sp_desktop_get_color(desktop, true) );
2480 }*/
2483 /**
2484  * Sets the input boxes with the changed color and opacity. This is used as a 
2485  * callback for style changing.
2486  */
2487 /* static bool
2488 sp_style_changed (const SPCSSAttr *css, gpointer data)
2490     // GrDrag *drag = (GrDrag *) data;
2491     
2492     // set fill of text entry box
2493     if (css->attribute("fill"))
2494         gtk_entry_set_text((GtkEntry *)dropper_rgb_entry, 
2495             css->attribute("fill")); 
2497     // set opacity of text entry box
2498     if (css->attribute("fill-opacity"))
2499         gtk_entry_set_text((GtkEntry *)dropper_opacity_entry, 
2500             css->attribute("fill-opacity")); 
2501     
2502     // set fill of text entry box
2503     if (css->attribute("stroke"))
2504         gtk_entry_set_text((GtkEntry *)dropper_rgb_entry, 
2505             css->attribute("stroke")); 
2507     // set opacity of text entry box
2508     if (css->attribute("stroke-opacity"))
2509         gtk_entry_set_text((GtkEntry *)dropper_opacity_entry, 
2510             css->attribute("stroke-opacity"));
2511     return false;
2514 */
2517 /**
2518  * Dropper auxiliary toolbar construction and setup.
2519  *
2520  * TODO: Would like to add swatch of current color.
2521  * TODO: Add queue of last 5 or so colors selected with new swatches so that
2522  *       can drag and drop places. Will provide a nice mixing palette.
2523  */
2524 static GtkWidget *
2525 sp_dropper_toolbox_new(SPDesktop *desktop)
2527     GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2529     gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2530     gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2532     GtkTooltips *tt = gtk_tooltips_new();
2534     
2535     gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, 
2536                        AUX_BETWEEN_BUTTON_GROUPS);
2537     // sp_toolbox_add_label(tbl, _("<b>New:</b>"));
2540     
2541     /* RGB Input Field */
2542  /*   {
2543         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2544         GtkWidget *dropper_rgba_label = gtk_label_new ("Color:");
2545         gtk_widget_show (dropper_rgba_label);
2546         gtk_container_add(GTK_CONTAINER(hb), dropper_rgba_label);
2547         
2548         dropper_rgb_entry = gtk_entry_new ();
2549         sp_dialog_defocus_on_enter (dropper_rgb_entry);
2550         gtk_entry_set_max_length (GTK_ENTRY (dropper_rgb_entry), 7);
2551         gtk_entry_set_width_chars (GTK_ENTRY (dropper_rgb_entry), 7);
2552         gtk_tooltips_set_tip(tt, dropper_rgb_entry, 
2553                          _("Hexidecimal representation of last selected "
2554                            "color"), 
2555                          NULL);
2556         gtk_widget_show (dropper_rgb_entry);
2557         gtk_container_add(GTK_CONTAINER(hb), dropper_rgb_entry);
2558         
2559         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 
2560                            AUX_BETWEEN_BUTTON_GROUPS);
2561     } */
2562     
2563     /* Opacity Input Field */
2564 /*    {
2565         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2566         GtkWidget *dropper_opacity_label = gtk_label_new ( _("Opacity:") );
2567         gtk_widget_show (dropper_opacity_label);
2568         gtk_container_add(GTK_CONTAINER(hb), dropper_opacity_label);
2569         
2570         dropper_opacity_entry = gtk_entry_new ();
2571         sp_dialog_defocus_on_enter (dropper_opacity_entry);
2572         gtk_entry_set_max_length (GTK_ENTRY (dropper_opacity_entry), 11);
2573         gtk_entry_set_width_chars (GTK_ENTRY (dropper_opacity_entry), 11);
2574         gtk_tooltips_set_tip(tt, dropper_opacity_entry, 
2575                          _("Opacity of last selected color"), 
2576                          NULL);
2577         gtk_widget_show (dropper_opacity_entry);
2578         gtk_container_add(GTK_CONTAINER(hb), dropper_opacity_entry);
2579         
2580         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 
2581                            AUX_BETWEEN_BUTTON_GROUPS);
2582     } */
2583     
2584     
2585     /* Copy to Clipboard */
2586 /*    {
2587         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2588         GtkWidget *b = gtk_button_new_with_label(_("Copy as RGBA"));
2589         gtk_tooltips_set_tip(tt, b, _("Copy last saved color as hexidecimal "
2590                                       "RGB + Alpha (RGBA) to "
2591                                       "clipboard"), 
2592                              NULL);
2593         gtk_widget_show(b);
2594         gtk_container_add(GTK_CONTAINER(hb), b);
2595         gtk_signal_connect(GTK_OBJECT(b), "clicked", 
2596             GTK_SIGNAL_FUNC(sp_dropper_copy), tbl);
2597         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 
2598                            AUX_BETWEEN_BUTTON_GROUPS);
2599     } */
2602     /* Copy to Clipboard as HEX */
2603 /*    {
2604         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2605         GtkWidget *b = gtk_button_new_with_label(_("Copy as HEX"));
2606         gtk_tooltips_set_tip(tt, b, _("Copy last saved color as "
2607                                       "hexidecimal RGB without alpha " 
2608                                       "to clipboard"), NULL);
2609         gtk_widget_show(b);
2610         gtk_container_add(GTK_CONTAINER(hb), b);
2611         gtk_signal_connect(GTK_OBJECT(b), "clicked", 
2612             GTK_SIGNAL_FUNC(sp_dropper_copy_as_hex), tbl);
2613         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 
2614                            AUX_BETWEEN_BUTTON_GROUPS);
2615     } */
2616     
2617     // aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2618     
2619     {
2620         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2621         
2622         GtkWidget *button = 
2623             sp_button_new_from_data( GTK_ICON_SIZE_SMALL_TOOLBAR,
2624                                      SP_BUTTON_TYPE_TOGGLE,
2625                                      NULL,
2626                                      "pick_color",
2627                                      _("When pressed, picks visible color "
2628                                        "without alpha and when not pressed, "
2629                                        "picks color including its "
2630                                        "alpha"),
2631                                      tt);
2633         gtk_widget_show(button);
2634         gtk_container_add (GTK_CONTAINER (hb), button);
2636         g_signal_connect_after (G_OBJECT (button), "clicked", 
2637                                 G_CALLBACK (toggle_dropper_color_pick), NULL);
2638         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), 
2639                                       !prefs_get_int_attribute ("tools.dropper", 
2640                                                                "pick", 0));
2641         gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 
2642                    AUX_BETWEEN_BUTTON_GROUPS);
2643     }
2644    
2645     aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2646     
2648     // where new gtkmm stuff should go
2649     
2650     gtk_widget_show_all(tbl);
2651     sp_set_font_size_smaller (tbl);
2653     /*
2654     sigc::connection *connection = new sigc::connection(
2655         desktop->connectSetStyle(
2656             sigc::bind(sigc::ptr_fun(sp_style_changed), 
2657                        desktop)) ); 
2658     
2659     g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), 
2660                      connection); */
2661     
2662     return tbl;
2666 //########################
2667 //##    Text Toolbox    ##
2668 //########################
2669 /*
2670 static void
2671 sp_text_letter_changed(GtkAdjustment *adj, GtkWidget *tbl)
2673     //Call back for letter sizing spinbutton
2676 static void
2677 sp_text_line_changed(GtkAdjustment *adj, GtkWidget *tbl)
2679     //Call back for line height spinbutton
2682 static void
2683 sp_text_horiz_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
2685     //Call back for horizontal kerning spinbutton
2688 static void
2689 sp_text_vert_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
2691     //Call back for vertical kerning spinbutton
2694 static void
2695 sp_text_letter_rotation_changed(GtkAdjustment *adj, GtkWidget *tbl)
2697     //Call back for letter rotation spinbutton
2698 }*/
2699 static GtkWidget *
2700 sp_text_toolbox_new(SPDesktop *desktop)
2702     GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2703 /*    GtkWidget *us = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tbl), "units");
2704     GtkTooltips *tt = gtk_tooltips_new();
2705     GtkWidget *group;
2707         //Font Family
2708         {
2709         GtkWidget *c = gtk_combo_new ();
2710         gtk_combo_set_value_in_list ((GtkCombo *) c, FALSE, FALSE);
2711         gtk_combo_set_use_arrows ((GtkCombo *) c, TRUE);
2712         gtk_combo_set_use_arrows_always ((GtkCombo *) c, TRUE);
2713         gtk_widget_set_size_request (c, 144, -1);
2714         aux_toolbox_space(tbl, 1);
2715         gtk_box_pack_start (GTK_BOX (tbl), c, FALSE, FALSE, 0);
2716         }
2718         //Font Style
2719         {
2720         GtkWidget *c = gtk_combo_new ();
2721         gtk_combo_set_value_in_list ((GtkCombo *) c, FALSE, FALSE);
2722         gtk_combo_set_use_arrows ((GtkCombo *) c, TRUE);
2723         gtk_combo_set_use_arrows_always ((GtkCombo *) c, TRUE);
2724         gtk_widget_set_size_request (c, 88, -1);
2725         aux_toolbox_space(tbl, 1);
2726         gtk_box_pack_start (GTK_BOX (tbl), c, FALSE, FALSE, 0);
2727         }
2729         //Font Size
2730         {
2731         GtkWidget *c = gtk_combo_new ();
2732         gtk_combo_set_value_in_list ((GtkCombo *) c, FALSE, FALSE);
2733         gtk_combo_set_use_arrows ((GtkCombo *) c, TRUE);
2734         gtk_combo_set_use_arrows_always ((GtkCombo *) c, TRUE);
2735         gtk_widget_set_size_request (c, 64, -1);
2736         aux_toolbox_space(tbl, 1);
2737         gtk_box_pack_start (GTK_BOX (tbl), c, FALSE, FALSE, 0);
2738         }
2740         aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2741         //Bold
2742         {
2743         GtkWidget *px = gtk_image_new_from_stock(GTK_STOCK_BOLD, GTK_ICON_SIZE_SMALL_TOOLBAR);
2744         GtkWidget *button = gtk_toggle_button_new ();
2745         gtk_container_add (GTK_CONTAINER (button), px);
2746         gtk_widget_show(button);
2747         gtk_tooltips_set_tip (tt, button, _("Bold"), NULL);
2748         gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2749         gtk_widget_set_sensitive(button, TRUE);
2750         gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
2751         }
2754         //Italic
2755         {
2756         GtkWidget *px = gtk_image_new_from_stock(GTK_STOCK_ITALIC, GTK_ICON_SIZE_SMALL_TOOLBAR);
2757         GtkWidget *button = gtk_toggle_button_new ();
2758         gtk_container_add (GTK_CONTAINER (button), px);
2759         gtk_widget_show(button);
2760         gtk_tooltips_set_tip (tt, button, _("Italics"), NULL);
2761         gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2762         gtk_widget_set_sensitive(button, TRUE);
2763         gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
2764         }
2766         //Underline
2767         {
2768         GtkWidget *px = gtk_image_new_from_stock(GTK_STOCK_UNDERLINE, GTK_ICON_SIZE_SMALL_TOOLBAR);
2769         GtkWidget *button = gtk_toggle_button_new ();
2770         gtk_container_add (GTK_CONTAINER (button), px);
2771         gtk_widget_show(button);
2772         gtk_tooltips_set_tip (tt, button, _("Underline"), NULL);
2773         gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2774         gtk_widget_set_sensitive(button, FALSE);
2775         gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
2776         }
2778         aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2779         // align left
2780         {
2781         GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_LEFT, GTK_ICON_SIZE_SMALL_TOOLBAR);
2782         GtkWidget *b = group = gtk_radio_button_new (NULL);
2783                 gtk_container_add (GTK_CONTAINER (b), px);
2784         gtk_tooltips_set_tip (tt, b, _("Align lines left"), NULL);
2785         gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2786         gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2787         gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2788         }
2790         // align center
2791         {
2792         GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_CENTER, GTK_ICON_SIZE_SMALL_TOOLBAR);
2793         GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
2794                 gtk_container_add (GTK_CONTAINER (b), px);
2795         // TRANSLATORS: `Center' here is a verb.
2796         gtk_tooltips_set_tip (tt, b, _("Center lines"), NULL);
2797                 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2798         gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2799         gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2800         }
2802         // align right
2803         {
2804         GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_RIGHT, GTK_ICON_SIZE_SMALL_TOOLBAR);
2805         GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
2806                 gtk_container_add (GTK_CONTAINER (b), px);
2807         gtk_tooltips_set_tip (tt, b, _("Align lines right"), NULL);
2808         gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2809         gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2810         gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2811         }
2813         // full justification
2814         {
2815         GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_FILL, GTK_ICON_SIZE_SMALL_TOOLBAR);
2816         GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
2817                 gtk_container_add (GTK_CONTAINER (b), px);
2818         gtk_tooltips_set_tip (tt, b, _("Full justification"), NULL);
2819         gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2820         gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2821         gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2822         }
2823         
2824                 
2825         aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2826                 
2827         // horizontal
2828         {
2829         GtkWidget *px= sp_icon_new(GTK_ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_LR);
2830         GtkWidget *b = group = gtk_radio_button_new (NULL);
2831                 gtk_container_add (GTK_CONTAINER (b), px);
2832         gtk_tooltips_set_tip (tt, b, _("Horizontal text"), NULL);
2833         gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2834         gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2835         gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2836         }
2838         // vertical
2839         {
2840         GtkWidget *px = sp_icon_new (GTK_ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_TB);
2841         GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
2842                 gtk_container_add (GTK_CONTAINER (b), px);
2843         gtk_tooltips_set_tip (tt, b, _("Vertical text"), NULL);
2844         gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2845         gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2846         gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2847         }
2849         aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2851         // letter spacing
2852     {
2853         {
2854         GtkWidget *image = sp_icon_new (GTK_ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LETTER_SPACING);
2855         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2856         gtk_container_add (GTK_CONTAINER (hb), image);
2857         gtk_widget_show(image);
2858         gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
2859         }
2860     
2861         {
2862             GtkWidget *hb = sp_tb_spinbutton(_(""), _("Spacing between letters"),
2863                                              "tools.text", "letter_spacing", 0.0,
2864                                              us, tbl, FALSE, NULL,
2865                                              -1000.0, 1000.0, 0.1, 0.1,
2866                                              sp_text_letter_changed, 0.1, 1);
2867             gtk_widget_set_size_request (hb, 45, 6);
2868             gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
2869         }
2870     }
2872         // line spacing
2873     {
2874         {
2875         GtkWidget *image = sp_icon_new (GTK_ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LINE_SPACING);
2876         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2877         gtk_container_add (GTK_CONTAINER (hb), image);
2878         gtk_widget_show(image);
2879         gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
2880         }
2881     
2882         {
2883             GtkWidget *hb = sp_tb_spinbutton(_(""), _("Spacing between lines"),
2884                                              "tools.text", "line_spacing", 0,
2885                                              us, tbl, FALSE, NULL,
2886                                              -1000.0, 1000.0, 0.1, 0.1,
2887                                              sp_text_line_changed, 0.1, 1);
2888             gtk_widget_set_size_request (hb, 45, 0);
2889             gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 3);
2890         }
2891     }
2894     // horizontal kerning/vertical kerning units menu: create
2895     GtkWidget *us = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
2896     sp_unit_selector_setsize(us, AUX_OPTION_MENU_WIDTH, AUX_OPTION_MENU_HEIGHT);
2897     sp_unit_selector_set_unit(SP_UNIT_SELECTOR(us), desktop->namedview->doc_units);
2899     aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2901     // horizontal kerning
2902     {
2903         {
2904         GtkWidget *image = sp_icon_new (GTK_ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_HORZ_KERN);
2905         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2906         gtk_container_add (GTK_CONTAINER (hb), image);
2907         gtk_widget_show(image);
2908         gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
2909         }
2911         {
2912             GtkWidget *hb = sp_tb_spinbutton(_(""), _("Horizontal kerning"),
2913                                              "tools.text", "horizontal_kerning", 0,
2914                                              us, tbl, FALSE, NULL,
2915                                              -100.00, 100.00, 0.01, 0.1,
2916                                              sp_text_horiz_kern_changed);
2917             gtk_widget_set_size_request (hb, 45, 0);
2918             gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
2919         }
2920     }
2922     // vertical kerning
2923     {
2924         {
2925         GtkWidget *image = sp_icon_new (GTK_ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_VERT_KERN);
2926         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2927         gtk_container_add (GTK_CONTAINER (hb), image);
2928         gtk_widget_show(image);
2929         gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
2930         }
2931     
2932         {
2933             GtkWidget *hb = sp_tb_spinbutton(_(""), _("Vertical kerning"),
2934                                              "tools.text", "vertical_kerning", 0,
2935                                              us, tbl, FALSE, NULL,
2936                                              -100.00, 100.00, 0.01, 0.1,
2937                                              sp_text_vert_kern_changed);
2938             gtk_widget_set_size_request (hb, 45, 0);
2939             gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 5);
2940         }
2941     }
2943     // add the units menu
2944     gtk_widget_show(us);
2945     gtk_box_pack_start(GTK_BOX(tbl), us, FALSE, FALSE, 1);
2946     gtk_object_set_data(GTK_OBJECT(tbl), "units", us);
2947     }
2949         // letter rotation
2950     aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2951     {
2952         {
2953         GtkWidget *image = sp_icon_new (GTK_ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_ROTATION);
2954         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2955         gtk_container_add (GTK_CONTAINER (hb), image);
2956         gtk_widget_show(image);
2957         gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
2958         }
2959         {
2960             GtkWidget *hb = sp_tb_spinbutton(_(""), _("Letter rotation"),
2961                                              "tools.text", "letter_rotation", 0,
2962                                              us, tbl, FALSE, NULL,
2963                                              -180.0, 180.0, 0.1, 0.1,
2964                                              sp_text_letter_rotation_changed, 0.1, 1);
2965             gtk_widget_set_size_request (hb, 45, 0);
2966             gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
2967         }
2968         // rotation degree label
2969         {
2970         GtkWidget *label = gtk_widget_new (GTK_TYPE_LABEL, "label", "\302\260", "xalign", 0.0, NULL);
2971         gtk_box_pack_start(GTK_BOX(tbl), label, FALSE, FALSE, 0);
2972         }
2973     }
2974         
2975         // Remove Manual Kerns
2976         {
2977         GtkWidget *px = sp_icon_new (GTK_ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_REMOVE_KERNS);
2978         GtkWidget *button = gtk_button_new ();
2979         gtk_container_add (GTK_CONTAINER (button), px);
2980         gtk_widget_show(button);
2981         gtk_tooltips_set_tip (tt, button, _("Remove manual kerns"), NULL);
2982         gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2983         gtk_widget_set_sensitive(button, TRUE);
2984         gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2985         }
2987     gtk_widget_show_all(tbl);
2988     sp_set_font_size_smaller (tbl);
2990 */    return tbl;
2992 } // end of sp_text_toolbox_new()
2995 //#########################
2996 //##  Connector Toolbox  ##
2997 //#########################
2999 static void sp_connector_path_set_avoid(void)
3001     cc_selection_set_avoid(true);
3005 static void sp_connector_path_set_ignore(void)
3007     cc_selection_set_avoid(false);
3011 static void connector_spacing_changed(GtkAdjustment *adj, GtkWidget *tbl)
3013     // quit if run by the _changed callbacks
3014     if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
3015         return;
3016     }
3017         
3018     SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl),
3019             "desktop");
3020     SPDocument *doc = SP_DT_DOCUMENT(desktop);
3022     if (!sp_document_get_undo_sensitive(doc))
3023     {
3024         return;
3025     }
3027     // in turn, prevent callbacks from responding
3028     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
3029     
3030     Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
3031     
3032     sp_repr_set_css_double(repr, "inkscape:connector-spacing", adj->value);
3033     SP_OBJECT(desktop->namedview)->updateRepr();
3034     
3035     GSList *items = get_avoided_items(NULL, desktop->currentRoot(), desktop);
3036     for ( GSList const *iter = items ; iter != NULL ; iter = iter->next ) {
3037         SPItem *item = reinterpret_cast<SPItem *>(iter->data);
3038         NR::Matrix m = NR::identity();
3039         avoid_item_move(&m, item);
3040     }
3042     if (items) {
3043         g_slist_free(items);
3044     }
3045     
3046     sp_document_done(doc);
3048     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
3049     
3050     spinbutton_defocus(GTK_OBJECT(tbl));
3054 static void connector_tb_event_attr_changed(Inkscape::XML::Node *repr,
3055         gchar const *name, gchar const *old_value, gchar const *new_value,
3056         bool is_interactive, gpointer data)
3058     GtkWidget *tbl = GTK_WIDGET(data);
3060     if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
3061         return;
3062     }
3063     if (strcmp(name, "inkscape:connector-spacing") != 0) {
3064         return;
3065     }
3067     GtkAdjustment *adj = (GtkAdjustment*)
3068             gtk_object_get_data(GTK_OBJECT(tbl), "spacing");
3069     gdouble spacing = defaultConnSpacing;
3070     sp_repr_get_double(repr, "inkscape:connector-spacing", &spacing);
3071     
3072     gtk_adjustment_set_value(adj, spacing);
3076 static Inkscape::XML::NodeEventVector connector_tb_repr_events = {
3077     NULL, /* child_added */
3078     NULL, /* child_removed */
3079     connector_tb_event_attr_changed,
3080     NULL, /* content_changed */
3081     NULL  /* order_changed */
3082 };
3085 static GtkWidget *
3086 sp_connector_toolbox_new(SPDesktop *desktop)
3088     GtkTooltips *tt = gtk_tooltips_new();
3089     GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
3090     
3091     gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
3092     gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
3094     gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
3095             AUX_BETWEEN_BUTTON_GROUPS);
3097     sp_toolbox_button_new(tbl, GTK_ICON_SIZE_SMALL_TOOLBAR,
3098             "connector_avoid", GTK_SIGNAL_FUNC(sp_connector_path_set_avoid),
3099             tt, _("Make connectors avoid selected objects"));
3101     sp_toolbox_button_new(tbl, GTK_ICON_SIZE_SMALL_TOOLBAR,
3102             "connector_ignore", GTK_SIGNAL_FUNC(sp_connector_path_set_ignore),
3103             tt, _("Make connectors ignore selected objects"));
3105     //  interval
3106     gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
3107             AUX_BETWEEN_BUTTON_GROUPS);
3109     // Spacing spinbox
3110     {
3111         GtkWidget *object_spacing = sp_tb_spinbutton(_("Spacing:"),
3112                 _("The amount of space left around objects by auto-routing connectors"),
3113                 "tools.connector", "spacing", 10, NULL, tbl, TRUE,
3114                 "inkscape:connector-spacing", 0, 100, 1.0, 10.0,
3115                 connector_spacing_changed, 1, 0);
3117         gtk_box_pack_start(GTK_BOX(tbl), object_spacing, FALSE, FALSE,
3118                 AUX_SPACING);
3119     }
3121     gtk_widget_show_all(tbl);
3122     sp_set_font_size_smaller (tbl);
3123     
3124     // Code to watch for changes to the connector-spacing attribute in
3125     // the XML.
3126     Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
3127     g_assert(repr != NULL);
3128         
3129     Inkscape::XML::Node *oldrepr = (Inkscape::XML::Node *)
3130             gtk_object_get_data(GTK_OBJECT(tbl), "repr");
3131     
3132     if (oldrepr) { // remove old listener
3133         sp_repr_remove_listener_by_data(oldrepr, tbl);
3134         Inkscape::GC::release(oldrepr);
3135         oldrepr = NULL;
3136         g_object_set_data(G_OBJECT(tbl), "repr", NULL);
3137     }
3139     if (repr) {
3140         g_object_set_data(G_OBJECT(tbl), "repr", repr);
3141         Inkscape::GC::anchor(repr);
3142         sp_repr_add_listener(repr, &connector_tb_repr_events, tbl);
3143     }
3144     
3145     return tbl;
3147 } // end of sp_connector_toolbox_new()
3150 /*
3151   Local Variables:
3152   mode:c++
3153   c-file-style:"stroustrup"
3154   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
3155   indent-tabs-mode:nil
3156   fill-column:99
3157   End:
3158 */
3159 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :