3d6434bf2f6de97f031e3da4fcc0d3e46564f6a8
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 "ui/widget/style-swatch.h"
40 #include "prefs-utils.h"
41 #include "verbs.h"
42 #include "sp-namedview.h"
43 #include "desktop.h"
44 #include "desktop-handles.h"
45 #include "nodepath.h"
46 #include "xml/repr.h"
47 #include "xml/node-event-vector.h"
48 #include <glibmm/i18n.h>
49 #include "helper/unit-menu.h"
50 #include "helper/units.h"
52 #include "inkscape.h"
53 #include "conn-avoid-ref.h"
56 #include "select-toolbar.h"
57 #include "gradient-toolbar.h"
59 #include "connector-context.h"
60 #include "sp-rect.h"
61 #include "sp-star.h"
62 #include "sp-spiral.h"
63 #include "sp-ellipse.h"
64 #include "selection.h"
65 #include "document-private.h"
67 #include "mod360.h"
69 #include "toolbox.h"
71 typedef void (*SetupFunction)(GtkWidget *toolbox, SPDesktop *desktop);
72 typedef void (*UpdateFunction)(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
74 static GtkWidget *sp_node_toolbox_new(SPDesktop *desktop);
75 static GtkWidget *sp_zoom_toolbox_new(SPDesktop *desktop);
76 static GtkWidget *sp_star_toolbox_new(SPDesktop *desktop);
77 static GtkWidget *sp_arc_toolbox_new(SPDesktop *desktop);
78 static GtkWidget *sp_rect_toolbox_new(SPDesktop *desktop);
79 static GtkWidget *sp_spiral_toolbox_new(SPDesktop *desktop);
80 static GtkWidget *sp_pencil_toolbox_new(SPDesktop *desktop);
81 static GtkWidget *sp_pen_toolbox_new(SPDesktop *desktop);
82 static GtkWidget *sp_calligraphy_toolbox_new(SPDesktop *desktop);
83 static GtkWidget *sp_dropper_toolbox_new(SPDesktop *desktop);
84 static GtkWidget *sp_empty_toolbox_new(SPDesktop *desktop);
85 static GtkWidget *sp_text_toolbox_new(SPDesktop *desktop);
86 static GtkWidget *sp_connector_toolbox_new(SPDesktop *desktop);
89 static struct {
90 gchar const *type_name;
91 gchar const *data_name;
92 sp_verb_t verb;
93 sp_verb_t doubleclick_verb;
94 } const tools[] = {
95 { "SPSelectContext", "select_tool", SP_VERB_CONTEXT_SELECT, SP_VERB_CONTEXT_SELECT_PREFS},
96 { "SPNodeContext", "node_tool", SP_VERB_CONTEXT_NODE, SP_VERB_CONTEXT_NODE_PREFS },
97 { "SPZoomContext", "zoom_tool", SP_VERB_CONTEXT_ZOOM, SP_VERB_CONTEXT_ZOOM_PREFS },
98 { "SPRectContext", "rect_tool", SP_VERB_CONTEXT_RECT, SP_VERB_CONTEXT_RECT_PREFS },
99 { "SPArcContext", "arc_tool", SP_VERB_CONTEXT_ARC, SP_VERB_CONTEXT_ARC_PREFS },
100 { "SPStarContext", "star_tool", SP_VERB_CONTEXT_STAR, SP_VERB_CONTEXT_STAR_PREFS },
101 { "SPSpiralContext", "spiral_tool", SP_VERB_CONTEXT_SPIRAL, SP_VERB_CONTEXT_SPIRAL_PREFS },
102 { "SPPencilContext", "pencil_tool", SP_VERB_CONTEXT_PENCIL, SP_VERB_CONTEXT_PENCIL_PREFS },
103 { "SPPenContext", "pen_tool", SP_VERB_CONTEXT_PEN, SP_VERB_CONTEXT_PEN_PREFS },
104 { "SPDynaDrawContext", "dyna_draw_tool", SP_VERB_CONTEXT_CALLIGRAPHIC, SP_VERB_CONTEXT_CALLIGRAPHIC_PREFS },
105 { "SPTextContext", "text_tool", SP_VERB_CONTEXT_TEXT, SP_VERB_CONTEXT_TEXT_PREFS },
106 { "SPConnectorContext","connector_tool", SP_VERB_CONTEXT_CONNECTOR, SP_VERB_CONTEXT_CONNECTOR_PREFS },
107 { "SPGradientContext", "gradient_tool", SP_VERB_CONTEXT_GRADIENT, SP_VERB_CONTEXT_GRADIENT_PREFS },
108 { "SPDropperContext", "dropper_tool", SP_VERB_CONTEXT_DROPPER, SP_VERB_CONTEXT_DROPPER_PREFS },
109 { NULL, NULL, 0, 0 }
110 };
112 static struct {
113 gchar const *type_name;
114 gchar const *data_name;
115 GtkWidget *(*create_func)(SPDesktop *desktop);
116 } const aux_toolboxes[] = {
117 { "SPSelectContext", "select_toolbox", sp_select_toolbox_new },
118 { "SPNodeContext", "node_toolbox", sp_node_toolbox_new },
119 { "SPZoomContext", "zoom_toolbox", sp_zoom_toolbox_new },
120 { "SPStarContext", "star_toolbox", sp_star_toolbox_new },
121 { "SPRectContext", "rect_toolbox", sp_rect_toolbox_new },
122 { "SPArcContext", "arc_toolbox", sp_arc_toolbox_new },
123 { "SPSpiralContext", "spiral_toolbox", sp_spiral_toolbox_new },
124 { "SPPencilContext", "pencil_toolbox", sp_pencil_toolbox_new },
125 { "SPPenContext", "pen_toolbox", sp_pen_toolbox_new },
126 { "SPDynaDrawContext", "calligraphy_toolbox", sp_calligraphy_toolbox_new },
127 { "SPTextContext", "text_toolbox", sp_text_toolbox_new },
128 { "SPDropperContext", "dropper_toolbox", sp_dropper_toolbox_new },
129 { "SPGradientContext", "gradient_toolbox", sp_gradient_toolbox_new },
130 { "SPConnectorContext", "connector_toolbox", sp_connector_toolbox_new },
131 { NULL, NULL, NULL }
132 };
134 static void toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop, SetupFunction setup_func, UpdateFunction update_func, sigc::connection*);
136 static void setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop);
137 static void update_tool_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
138 static void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop);
139 static void update_aux_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
140 static void setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop);
141 static void update_commands_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
143 /* Global text entry widgets necessary for update */
144 /* GtkWidget *dropper_rgb_entry,
145 *dropper_opacity_entry ; */
146 // should be made a private member once this is converted to class
148 static void delete_connection(GObject *obj, sigc::connection *connection) {
149 connection->disconnect();
150 delete connection;
151 }
153 static GtkWidget *
154 sp_toolbox_button_new(GtkWidget *t, Inkscape::IconSize size, gchar const *pxname, GtkSignalFunc handler,
155 GtkTooltips *tt, gchar const *tip)
156 {
157 GtkWidget *b = sp_button_new_from_data(size, SP_BUTTON_TYPE_NORMAL, NULL, pxname, tip, tt);
158 gtk_widget_show(b);
159 if (handler) gtk_signal_connect(GTK_OBJECT(b), "clicked", handler, NULL);
160 gtk_box_pack_start(GTK_BOX(t), b, FALSE, FALSE, 0);
162 return b;
163 }
166 GtkWidget *
167 sp_toolbox_button_new_from_verb_with_doubleclick(GtkWidget *t, Inkscape::IconSize size, SPButtonType type,
168 Inkscape::Verb *verb, Inkscape::Verb *doubleclick_verb,
169 Inkscape::UI::View::View *view, GtkTooltips *tt)
170 {
171 SPAction *action = verb->get_action(view);
172 if (!action) return NULL;
174 SPAction *doubleclick_action;
175 if (doubleclick_verb)
176 doubleclick_action = doubleclick_verb->get_action(view);
177 else
178 doubleclick_action = NULL;
180 /* fixme: Handle sensitive/unsensitive */
181 /* fixme: Implement sp_button_new_from_action */
182 GtkWidget *b = sp_button_new(size, type, action, doubleclick_action, tt);
183 gtk_widget_show(b);
184 gtk_box_pack_start(GTK_BOX(t), b, FALSE, FALSE, 0);
186 return b;
187 }
189 GtkWidget *sp_toolbox_button_new_from_verb(GtkWidget *t, Inkscape::IconSize size, SPButtonType type, Inkscape::Verb *verb,
190 Inkscape::UI::View::View *view, GtkTooltips *tt)
191 {
192 return sp_toolbox_button_new_from_verb_with_doubleclick(t, size, type, verb, NULL, view, tt);
193 }
195 GtkWidget * sp_toolbox_button_normal_new_from_verb(GtkWidget *t, Inkscape::IconSize size, Inkscape::Verb *verb,
196 Inkscape::UI::View::View *view, GtkTooltips *tt)
197 {
198 return sp_toolbox_button_new_from_verb(t, size, SP_BUTTON_TYPE_NORMAL, verb, view, tt);
199 }
201 GtkWidget *
202 sp_tool_toolbox_new()
203 {
204 GtkTooltips *tt = gtk_tooltips_new();
205 GtkWidget *tb = gtk_vbox_new(FALSE, 0);
207 g_object_set_data(G_OBJECT(tb), "desktop", NULL);
208 g_object_set_data(G_OBJECT(tb), "tooltips", tt);
210 gtk_widget_set_sensitive(tb, FALSE);
212 GtkWidget *hb = gtk_handle_box_new();
213 gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), GTK_POS_TOP);
214 gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(hb), GTK_SHADOW_OUT);
215 gtk_handle_box_set_snap_edge(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
217 gtk_container_add(GTK_CONTAINER(hb), tb);
218 gtk_widget_show(GTK_WIDGET(tb));
220 sigc::connection* conn = new sigc::connection;
221 g_object_set_data(G_OBJECT(hb), "event_context_connection", conn);
223 return hb;
224 }
226 static void
227 aux_toolbox_attached(GtkHandleBox *toolbox, GtkWidget *child)
228 {
229 g_object_set_data(G_OBJECT(child), "is_detached", GINT_TO_POINTER(FALSE));
230 gtk_widget_queue_resize(child);
231 }
233 static void
234 aux_toolbox_detached(GtkHandleBox *toolbox, GtkWidget *child)
235 {
236 g_object_set_data(G_OBJECT(child), "is_detached", GINT_TO_POINTER(TRUE));
237 gtk_widget_queue_resize(child);
238 }
240 GtkWidget *
241 sp_aux_toolbox_new()
242 {
243 GtkWidget *tb = gtk_vbox_new(FALSE, 0);
245 GtkWidget *tb_s = gtk_vbox_new(FALSE, 0);
246 GtkWidget *tb_e = gtk_vbox_new(FALSE, 0);
247 gtk_box_set_spacing(GTK_BOX(tb), AUX_SPACING);
248 gtk_box_pack_start(GTK_BOX(tb), GTK_WIDGET(tb_s), FALSE, FALSE, 0);
249 gtk_box_pack_end(GTK_BOX(tb), GTK_WIDGET(tb_e), FALSE, FALSE, 0);
251 g_object_set_data(G_OBJECT(tb), "desktop", NULL);
252 g_object_set_data(G_OBJECT(tb), "top_spacer", tb_s);
254 gtk_widget_set_sensitive(tb, FALSE);
256 GtkWidget *hb = gtk_handle_box_new();
257 gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
258 gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(hb), GTK_SHADOW_OUT);
259 gtk_handle_box_set_snap_edge(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
261 g_signal_connect(G_OBJECT(hb), "child_attached", G_CALLBACK(aux_toolbox_attached), (gpointer)tb);
262 g_signal_connect(G_OBJECT(hb), "child_detached", G_CALLBACK(aux_toolbox_detached), (gpointer)tb);
264 gtk_container_add(GTK_CONTAINER(hb), tb);
265 gtk_widget_show(GTK_WIDGET(tb));
267 sigc::connection* conn = new sigc::connection;
268 g_object_set_data(G_OBJECT(hb), "event_context_connection", conn);
270 return hb;
271 }
273 //####################################
274 //# Commands Bar
275 //####################################
277 GtkWidget *
278 sp_commands_toolbox_new()
279 {
280 GtkWidget *tb = gtk_vbox_new(FALSE, 0);
282 GtkWidget *tb_s = gtk_vbox_new(FALSE, 0);
283 GtkWidget *tb_e = gtk_vbox_new(FALSE, 0);
284 gtk_box_set_spacing(GTK_BOX(tb), AUX_SPACING);
285 gtk_box_pack_start(GTK_BOX(tb), GTK_WIDGET(tb_s), FALSE, FALSE, 0);
286 gtk_box_pack_end(GTK_BOX(tb), GTK_WIDGET(tb_e), FALSE, FALSE, 0);
288 g_object_set_data(G_OBJECT(tb), "desktop", NULL);
289 gtk_widget_set_sensitive(tb, FALSE);
291 GtkWidget *hb = gtk_handle_box_new();
292 gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
293 gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(hb), GTK_SHADOW_OUT);
294 gtk_handle_box_set_snap_edge(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
296 g_signal_connect(G_OBJECT(hb), "child_attached", G_CALLBACK(aux_toolbox_attached), (gpointer)tb);
297 g_signal_connect(G_OBJECT(hb), "child_detached", G_CALLBACK(aux_toolbox_detached), (gpointer)tb);
299 gtk_container_add(GTK_CONTAINER(hb), tb);
300 gtk_widget_show(GTK_WIDGET(tb));
302 sigc::connection* conn = new sigc::connection;
303 g_object_set_data(G_OBJECT(hb), "event_context_connection", conn);
305 return hb;
306 }
309 //####################################
310 //# node editing callbacks
311 //####################################
313 void
314 sp_node_path_edit_add(void)
315 {
316 sp_node_selected_add_node();
317 }
319 void
320 sp_node_path_edit_delete(void)
321 {
322 sp_node_selected_delete();
323 }
325 void
326 sp_node_path_edit_delete_segment(void)
327 {
328 sp_node_selected_delete_segment();
329 }
331 void
332 sp_node_path_edit_break(void)
333 {
334 sp_node_selected_break();
335 }
337 void
338 sp_node_path_edit_join(void)
339 {
340 sp_node_selected_join();
341 }
343 void
344 sp_node_path_edit_join_segment(void)
345 {
346 sp_node_selected_join_segment();
347 }
349 void
350 sp_node_path_edit_toline(void)
351 {
352 sp_node_selected_set_line_type(NR_LINETO);
353 }
355 void
356 sp_node_path_edit_tocurve(void)
357 {
358 sp_node_selected_set_line_type(NR_CURVETO);
359 }
361 void
362 sp_node_path_edit_cusp(void)
363 {
364 sp_node_selected_set_type(Inkscape::NodePath::NODE_CUSP);
365 }
367 void
368 sp_node_path_edit_smooth(void)
369 {
370 sp_node_selected_set_type(Inkscape::NodePath::NODE_SMOOTH);
371 }
373 void
374 sp_node_path_edit_symmetrical(void)
375 {
376 sp_node_selected_set_type(Inkscape::NodePath::NODE_SYMM);
377 }
379 static void toggle_show_handles (GtkWidget *button, gpointer data) {
380 bool show = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
381 prefs_set_int_attribute ("tools.nodes", "show_handles", show ? 1 : 0);
382 sp_nodepath_show_handles(show);
383 }
385 //################################
386 //## Node Editing Toolbox ##
387 //################################
389 static GtkWidget *
390 sp_node_toolbox_new(SPDesktop *desktop)
391 {
392 Inkscape::UI::View::View *view = desktop;
394 GtkTooltips *tt = gtk_tooltips_new();
395 GtkWidget *tb = gtk_hbox_new(FALSE, 0);
397 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
399 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_insert",
400 GTK_SIGNAL_FUNC(sp_node_path_edit_add), tt, _("Insert new nodes into selected segments"));
401 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_delete",
402 GTK_SIGNAL_FUNC(sp_node_path_edit_delete), tt, _("Delete selected nodes"));
404 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
406 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_join",
407 GTK_SIGNAL_FUNC(sp_node_path_edit_join), tt, _("Join selected endnodes"));
408 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_join_segment",
409 GTK_SIGNAL_FUNC(sp_node_path_edit_join_segment), tt, _("Join selected endnodes with a new segment"));
411 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_delete_segment",
412 GTK_SIGNAL_FUNC(sp_node_path_edit_delete_segment), tt, _("Split path between two non-endpoint nodes"));
414 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_break",
415 GTK_SIGNAL_FUNC(sp_node_path_edit_break), tt, _("Break path at selected nodes"));
417 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
419 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_cusp",
420 GTK_SIGNAL_FUNC(sp_node_path_edit_cusp), tt, _("Make selected nodes corner"));
422 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_smooth",
423 GTK_SIGNAL_FUNC(sp_node_path_edit_smooth), tt, _("Make selected nodes smooth"));
425 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_symmetric",
426 GTK_SIGNAL_FUNC(sp_node_path_edit_symmetrical), tt, _("Make selected nodes symmetric"));
428 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
430 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_line",
431 GTK_SIGNAL_FUNC(sp_node_path_edit_toline), tt, _("Make selected segments lines"));
433 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_curve",
434 GTK_SIGNAL_FUNC(sp_node_path_edit_tocurve), tt, _("Make selected segments curves"));
436 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
438 sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_OBJECT_TO_CURVE), view, tt);
440 sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_SELECTION_OUTLINE), view, tt);
442 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
444 GtkWidget *cvbox = gtk_vbox_new (FALSE, 0);
445 GtkWidget *cbox = gtk_hbox_new (FALSE, 0);
447 {
448 GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
449 SP_BUTTON_TYPE_TOGGLE,
450 NULL,
451 "nodes_show_handles",
452 _("Show the Bezier handles of selected nodes"),
453 tt);
454 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.nodes", "show_handles", 1));
455 g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (toggle_show_handles), desktop);
456 gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
457 }
459 gtk_box_pack_start(GTK_BOX(cvbox), cbox, TRUE, FALSE, 0);
460 gtk_box_pack_start(GTK_BOX(tb), cvbox, FALSE, FALSE, 0);
462 gtk_widget_show_all(tb);
464 return tb;
466 } // end of sp_node_toolbox_new()
469 //########################
470 //## Zoom Toolbox ##
471 //########################
473 static GtkWidget *
474 sp_zoom_toolbox_new(SPDesktop *desktop)
475 {
476 Inkscape::UI::View::View *view=desktop;
478 GtkTooltips *tt = gtk_tooltips_new();
479 GtkWidget *tb = gtk_hbox_new(FALSE, 0);
481 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0),
482 FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
484 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_IN), view, tt);
486 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_OUT), view, tt);
488 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
490 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_SELECTION), view, tt);
492 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_DRAWING), view, tt);
494 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_PAGE), view, tt);
496 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_PAGE_WIDTH), view, tt);
498 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
500 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_PREV), view, tt);
502 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_NEXT), view, tt);
504 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
506 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_1_1), view, tt);
508 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_1_2), view, tt);
510 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_2_1), view, tt);
512 gtk_widget_show_all(tb);
514 return tb;
516 } // end of sp_zoom_toolbox_new()
518 void
519 sp_tool_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
520 {
521 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")));
522 }
525 void
526 sp_aux_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
527 {
528 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")));
529 }
531 void
532 sp_commands_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
533 {
534 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")));
535 }
538 static void
539 toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop, SetupFunction setup_func, UpdateFunction update_func, sigc::connection *conn)
540 {
541 gpointer ptr = g_object_get_data(G_OBJECT(toolbox), "desktop");
542 SPDesktop *old_desktop = static_cast<SPDesktop*>(ptr);
544 if (old_desktop) {
545 GList *children, *iter;
547 children = gtk_container_get_children(GTK_CONTAINER(toolbox));
548 for ( iter = children ; iter ; iter = iter->next ) {
549 gtk_container_remove( GTK_CONTAINER(toolbox), GTK_WIDGET(iter->data) );
550 }
551 g_list_free(children);
552 }
554 g_object_set_data(G_OBJECT(toolbox), "desktop", (gpointer)desktop);
556 if (desktop) {
557 gtk_widget_set_sensitive(toolbox, TRUE);
558 setup_func(toolbox, desktop);
559 update_func(desktop, desktop->event_context, toolbox);
560 *conn = desktop->connectEventContextChanged
561 (sigc::bind (sigc::ptr_fun(update_func), toolbox));
562 } else {
563 gtk_widget_set_sensitive(toolbox, FALSE);
564 }
566 } // end of toolbox_set_desktop()
569 static void
570 setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
571 {
572 GtkTooltips *tooltips=GTK_TOOLTIPS(g_object_get_data(G_OBJECT(toolbox), "tooltips"));
573 gint shrinkLeft = prefs_get_int_attribute_limited( "toolbox.left", "small", 0, 0, 1 );
574 Inkscape::IconSize toolboxSize = shrinkLeft ? Inkscape::ICON_SIZE_SMALL_TOOLBAR : Inkscape::ICON_SIZE_LARGE_TOOLBAR;
576 for (int i = 0 ; tools[i].type_name ; i++ ) {
577 GtkWidget *button =
578 sp_toolbox_button_new_from_verb_with_doubleclick( toolbox, toolboxSize,
579 SP_BUTTON_TYPE_TOGGLE,
580 Inkscape::Verb::get(tools[i].verb),
581 Inkscape::Verb::get(tools[i].doubleclick_verb),
582 desktop,
583 tooltips );
585 g_object_set_data( G_OBJECT(toolbox), tools[i].data_name,
586 (gpointer)button );
587 }
588 }
591 static void
592 update_tool_toolbox( SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox )
593 {
594 gchar const *const tname = ( eventcontext
595 ? gtk_type_name(GTK_OBJECT_TYPE(eventcontext))
596 : NULL );
597 for (int i = 0 ; tools[i].type_name ; i++ ) {
598 SPButton *button = SP_BUTTON(g_object_get_data(G_OBJECT(toolbox), tools[i].data_name));
599 sp_button_toggle_set_down(button, tname && !strcmp(tname, tools[i].type_name));
600 }
601 }
603 static void
604 setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
605 {
606 GtkSizeGroup* grouper = gtk_size_group_new( GTK_SIZE_GROUP_BOTH );
608 for (int i = 0 ; aux_toolboxes[i].type_name ; i++ ) {
609 GtkWidget *sub_toolbox;
610 if (aux_toolboxes[i].create_func == NULL)
611 sub_toolbox = sp_empty_toolbox_new(desktop);
612 else
613 sub_toolbox = aux_toolboxes[i].create_func(desktop);
615 gtk_size_group_add_widget( grouper, sub_toolbox );
617 gtk_container_add(GTK_CONTAINER(toolbox), sub_toolbox);
618 g_object_set_data(G_OBJECT(toolbox), aux_toolboxes[i].data_name, sub_toolbox);
619 }
620 g_object_unref( G_OBJECT(grouper) );
621 }
623 static void
624 update_aux_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox)
625 {
626 gchar const *tname = ( eventcontext
627 ? gtk_type_name(GTK_OBJECT_TYPE(eventcontext))
628 : NULL );
629 for (int i = 0 ; aux_toolboxes[i].type_name ; i++ ) {
630 GtkWidget *sub_toolbox = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), aux_toolboxes[i].data_name));
631 if (tname && !strcmp(tname, aux_toolboxes[i].type_name)) {
632 gtk_widget_show_all(sub_toolbox);
633 g_object_set_data(G_OBJECT(toolbox), "shows", sub_toolbox);
634 } else {
635 gtk_widget_hide(sub_toolbox);
636 }
637 }
638 }
640 static void
641 setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
642 {
643 Inkscape::UI::View::View *view = desktop;
645 GtkTooltips *tt = gtk_tooltips_new();
646 GtkWidget *tb = gtk_hbox_new(FALSE, 0);
648 gint shrinkTop = prefs_get_int_attribute_limited( "toolbox", "small", 1, 0, 1 );
649 Inkscape::IconSize toolboxSize = shrinkTop ? Inkscape::ICON_SIZE_SMALL_TOOLBAR : Inkscape::ICON_SIZE_LARGE_TOOLBAR;
651 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_NEW), view, tt);
652 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_OPEN), view, tt);
653 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_SAVE), view, tt);
654 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_PRINT), view, tt);
656 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
658 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_IMPORT), view, tt);
659 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_EXPORT), view, tt);
661 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
663 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_UNDO), view, tt);
664 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_REDO), view, tt);
666 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
668 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_COPY), view, tt);
669 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_CUT), view, tt);
670 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_PASTE), view, tt);
672 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
674 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_SELECTION), view, tt);
675 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_DRAWING), view, tt);
676 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_PAGE), view, tt);
678 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
680 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_DUPLICATE), view, tt);
681 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_CLONE), view, tt);
682 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_UNLINK_CLONE), view, tt);
684 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
686 sp_toolbox_button_normal_new_from_verb(tb, toolboxSize, Inkscape::Verb::get(SP_VERB_SELECTION_GROUP), view, tt);
687 sp_toolbox_button_normal_new_from_verb(tb, toolboxSize, Inkscape::Verb::get(SP_VERB_SELECTION_UNGROUP), view, tt);
689 // disabled until we have icons for them:
691 //find
693 //sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_TILE), view, tt);
694 //sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_UNTILE), view, tt);
696 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
698 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_FILL_STROKE), view, tt);
699 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_TEXT), view, tt);
700 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_XML_EDITOR), view, tt);
701 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_ALIGN_DISTRIBUTE), view, tt);
703 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
705 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_DISPLAY), view, tt);
706 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_NAMEDVIEW), view, tt);
708 gtk_widget_show_all(tb);
710 gtk_container_add(GTK_CONTAINER(toolbox), tb);
711 }
713 static void
714 update_commands_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox)
715 {
716 }
718 void show_aux_toolbox(GtkWidget *toolbox_toplevel)
719 {
720 gtk_widget_show(toolbox_toplevel);
721 GtkWidget *toolbox = gtk_bin_get_child(GTK_BIN(toolbox_toplevel));
723 GtkWidget *shown_toolbox = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), "shows"));
724 if (!shown_toolbox) {
725 return;
726 }
727 gtk_widget_show(toolbox);
729 // need to show the spacer, or the padding will be off
730 GtkWidget *spacer = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), "top_spacer"));
731 gtk_widget_show(spacer);
733 gtk_widget_show_all(shown_toolbox);
734 }
736 void
737 aux_toolbox_space(GtkWidget *tb, gint space)
738 {
739 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, space);
740 }
742 static GtkWidget *
743 sp_empty_toolbox_new(SPDesktop *desktop)
744 {
745 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
746 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
747 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
749 gtk_widget_show_all(tbl);
750 sp_set_font_size_smaller (tbl);
752 return tbl;
753 }
755 // helper UI functions
757 GtkWidget *
758 sp_tb_spinbutton(
759 gchar *label, gchar const *tooltip,
760 gchar const *path, gchar const *data, gdouble def,
761 GtkWidget *us,
762 GtkWidget *tbl,
763 gboolean altx, gchar const *altx_mark,
764 gdouble lower, gdouble upper, gdouble step, gdouble page,
765 void (*callback)(GtkAdjustment *, GtkWidget *),
766 gdouble climb = 0.1, guint digits = 3, double factor = 1.0)
767 {
768 GtkTooltips *tt = gtk_tooltips_new();
770 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
772 GtkWidget *l = gtk_label_new(label);
773 gtk_widget_show(l);
774 gtk_misc_set_alignment(GTK_MISC(l), 1.0, 0.5);
775 gtk_container_add(GTK_CONTAINER(hb), l);
777 GtkObject *a = gtk_adjustment_new(prefs_get_double_attribute(path, data, def) * factor,
778 lower, upper, step, page, page);
779 gtk_object_set_data(GTK_OBJECT(tbl), data, a);
780 if (us)
781 sp_unit_selector_add_adjustment(SP_UNIT_SELECTOR(us), GTK_ADJUSTMENT(a));
783 GtkWidget *sb = gtk_spin_button_new(GTK_ADJUSTMENT(a), climb, digits);
784 gtk_tooltips_set_tip(tt, sb, tooltip, NULL);
785 if (altx)
786 gtk_object_set_data(GTK_OBJECT(sb), altx_mark, sb);
787 gtk_widget_set_size_request(sb,
788 (upper <= 1.0 || digits == 0)? AUX_SPINBUTTON_WIDTH_SMALL - 10: AUX_SPINBUTTON_WIDTH_SMALL,
789 AUX_SPINBUTTON_HEIGHT);
790 gtk_widget_show(sb);
791 gtk_signal_connect(GTK_OBJECT(sb), "focus-in-event", GTK_SIGNAL_FUNC(spinbutton_focus_in), tbl);
792 gtk_signal_connect(GTK_OBJECT(sb), "key-press-event", GTK_SIGNAL_FUNC(spinbutton_keypress), tbl);
793 gtk_container_add(GTK_CONTAINER(hb), sb);
794 gtk_signal_connect(GTK_OBJECT(a), "value_changed", GTK_SIGNAL_FUNC(callback), tbl);
796 return hb;
797 }
799 #define MODE_LABEL_WIDTH 70
801 //########################
802 //## Star ##
803 //########################
805 static void
806 sp_stb_magnitude_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
807 {
808 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
810 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
811 // do not remember prefs if this call is initiated by an undo change, because undoing object
812 // creation sets bogus values to its attributes before it is deleted
813 prefs_set_int_attribute("tools.shapes.star", "magnitude", (gint)adj->value);
814 }
816 // quit if run by the attr_changed listener
817 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
818 return;
819 }
821 // in turn, prevent listener from responding
822 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
824 bool modmade = false;
826 Inkscape::Selection *selection = sp_desktop_selection(desktop);
827 GSList const *items = selection->itemList();
828 for (; items != NULL; items = items->next) {
829 if (SP_IS_STAR((SPItem *) items->data)) {
830 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
831 sp_repr_set_int(repr,"sodipodi:sides",(gint)adj->value);
832 sp_repr_set_svg_double(repr, "sodipodi:arg2",
833 (sp_repr_get_double_attribute(repr, "sodipodi:arg1", 0.5)
834 + M_PI / (gint)adj->value));
835 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
836 modmade = true;
837 }
838 }
839 if (modmade) sp_document_done(sp_desktop_document(desktop));
841 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
843 spinbutton_defocus(GTK_OBJECT(tbl));
844 }
846 static void
847 sp_stb_proportion_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
848 {
849 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
851 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
852 prefs_set_double_attribute("tools.shapes.star", "proportion", adj->value);
853 }
855 // quit if run by the attr_changed listener
856 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
857 return;
858 }
860 // in turn, prevent listener from responding
861 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
863 bool modmade = false;
864 Inkscape::Selection *selection = sp_desktop_selection(desktop);
865 GSList const *items = selection->itemList();
866 for (; items != NULL; items = items->next) {
867 if (SP_IS_STAR((SPItem *) items->data)) {
868 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
870 gdouble r1 = sp_repr_get_double_attribute(repr, "sodipodi:r1", 1.0);
871 gdouble r2 = sp_repr_get_double_attribute(repr, "sodipodi:r2", 1.0);
872 if (r2 < r1) {
873 sp_repr_set_svg_double(repr, "sodipodi:r2", r1*adj->value);
874 } else {
875 sp_repr_set_svg_double(repr, "sodipodi:r1", r2*adj->value);
876 }
878 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
879 modmade = true;
880 }
881 }
883 if (modmade) sp_document_done(sp_desktop_document(desktop));
885 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
887 spinbutton_defocus(GTK_OBJECT(tbl));
888 }
890 static void
891 sp_stb_sides_flat_state_changed(GtkWidget *widget, GtkObject *tbl)
892 {
893 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
895 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
896 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
897 prefs_set_string_attribute("tools.shapes.star", "isflatsided", "true");
898 } else {
899 prefs_set_string_attribute("tools.shapes.star", "isflatsided", "false");
900 }
901 }
903 // quit if run by the attr_changed listener
904 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
905 return;
906 }
908 // in turn, prevent listener from responding
909 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
911 Inkscape::Selection *selection = sp_desktop_selection(desktop);
912 GSList const *items = selection->itemList();
913 GtkWidget *prop_widget = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "prop_widget");
914 bool modmade = false;
915 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
916 gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), FALSE);
917 for (; items != NULL; items = items->next) {
918 if (SP_IS_STAR((SPItem *) items->data)) {
919 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
920 repr->setAttribute("inkscape:flatsided", "true");
921 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
922 modmade = true;
923 }
924 }
925 } else {
926 gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), TRUE);
927 for (; items != NULL; items = items->next) {
928 if (SP_IS_STAR((SPItem *) items->data)) {
929 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
930 repr->setAttribute("inkscape:flatsided", "false");
931 SP_OBJECT(items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
932 modmade = true;
933 }
934 }
935 }
936 if (modmade) sp_document_done(sp_desktop_document(desktop));
938 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
940 spinbutton_defocus(GTK_OBJECT(tbl));
941 }
943 static void
944 sp_stb_rounded_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
945 {
946 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
948 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
949 prefs_set_double_attribute("tools.shapes.star", "rounded", (gdouble) adj->value);
950 }
952 // quit if run by the attr_changed listener
953 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
954 return;
955 }
957 // in turn, prevent listener from responding
958 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
960 bool modmade = false;
962 Inkscape::Selection *selection = sp_desktop_selection(desktop);
963 GSList const *items = selection->itemList();
964 for (; items != NULL; items = items->next) {
965 if (SP_IS_STAR((SPItem *) items->data)) {
966 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
967 sp_repr_set_svg_double(repr, "inkscape:rounded", (gdouble) adj->value);
968 SP_OBJECT(items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
969 modmade = true;
970 }
971 }
972 if (modmade) sp_document_done(sp_desktop_document(desktop));
974 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
976 spinbutton_defocus(GTK_OBJECT(tbl));
977 }
980 static void
981 sp_stb_randomized_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
982 {
983 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
985 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
986 prefs_set_double_attribute("tools.shapes.star", "randomized", (gdouble) adj->value);
987 }
989 // quit if run by the attr_changed listener
990 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
991 return;
992 }
994 // in turn, prevent listener from responding
995 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
997 bool modmade = false;
999 Inkscape::Selection *selection = sp_desktop_selection(desktop);
1000 GSList const *items = selection->itemList();
1001 for (; items != NULL; items = items->next) {
1002 if (SP_IS_STAR((SPItem *) items->data)) {
1003 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
1004 sp_repr_set_svg_double(repr, "inkscape:randomized", (gdouble) adj->value);
1005 SP_OBJECT(items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
1006 modmade = true;
1007 }
1008 }
1009 if (modmade) sp_document_done(sp_desktop_document(desktop));
1011 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1013 spinbutton_defocus(GTK_OBJECT(tbl));
1014 }
1017 static void star_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1018 gchar const *old_value, gchar const *new_value,
1019 bool is_interactive, gpointer data)
1020 {
1021 GtkWidget *tbl = GTK_WIDGET(data);
1023 // quit if run by the _changed callbacks
1024 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1025 return;
1026 }
1028 // in turn, prevent callbacks from responding
1029 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1031 GtkAdjustment *adj;
1033 if (!strcmp(name, "inkscape:randomized")) {
1034 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "randomized");
1035 gtk_adjustment_set_value(adj, sp_repr_get_double_attribute(repr, "inkscape:randomized", 0.0));
1036 } else if (!strcmp(name, "inkscape:rounded")) {
1037 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rounded");
1038 gtk_adjustment_set_value(adj, sp_repr_get_double_attribute(repr, "inkscape:rounded", 0.0));
1039 } else if (!strcmp(name, "inkscape:flatsided")) {
1040 GtkWidget *fscb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "flat_checkbox");
1041 GtkWidget *prop_widget = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "prop_widget");
1042 char const *flatsides = repr->attribute("inkscape:flatsided");
1043 if (flatsides && !strcmp(flatsides,"false" )) {
1044 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), FALSE);
1045 gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), TRUE);
1046 } else {
1047 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), TRUE);
1048 gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), FALSE);
1049 }
1050 } else if (!strcmp(name, "sodipodi:r1") || !strcmp(name, "sodipodi:r2")) {
1051 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "proportion");
1052 gdouble r1 = sp_repr_get_double_attribute(repr, "sodipodi:r1", 1.0);
1053 gdouble r2 = sp_repr_get_double_attribute(repr, "sodipodi:r2", 1.0);
1054 if (r2 < r1) {
1055 gtk_adjustment_set_value(adj, r2/r1);
1056 } else {
1057 gtk_adjustment_set_value(adj, r1/r2);
1058 }
1059 } else if (!strcmp(name, "sodipodi:sides")) {
1060 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "magnitude");
1061 gtk_adjustment_set_value(adj, sp_repr_get_int_attribute(repr, "sodipodi:sides", 0));
1062 }
1064 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1065 }
1068 static Inkscape::XML::NodeEventVector star_tb_repr_events =
1069 {
1070 NULL, /* child_added */
1071 NULL, /* child_removed */
1072 star_tb_event_attr_changed,
1073 NULL, /* content_changed */
1074 NULL /* order_changed */
1075 };
1078 /**
1079 * \param selection Should not be NULL.
1080 */
1081 static void
1082 sp_star_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1083 {
1084 int n_selected = 0;
1085 Inkscape::XML::Node *repr = NULL;
1086 Inkscape::XML::Node *oldrepr = NULL;
1088 for (GSList const *items = selection->itemList();
1089 items != NULL;
1090 items = items->next)
1091 {
1092 if (SP_IS_STAR((SPItem *) items->data)) {
1093 n_selected++;
1094 repr = SP_OBJECT_REPR((SPItem *) items->data);
1095 }
1096 }
1098 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
1100 if (n_selected == 0) {
1101 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
1102 } else if (n_selected == 1) {
1103 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1105 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1106 if (oldrepr) { // remove old listener
1107 sp_repr_remove_listener_by_data(oldrepr, tbl);
1108 Inkscape::GC::release(oldrepr);
1109 oldrepr = 0;
1110 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1111 }
1113 if (repr) {
1114 g_object_set_data(G_OBJECT(tbl), "repr", repr);
1115 Inkscape::GC::anchor(repr);
1116 sp_repr_add_listener(repr, &star_tb_repr_events, tbl);
1117 sp_repr_synthesize_events(repr, &star_tb_repr_events, tbl);
1118 }
1119 } else {
1120 // FIXME: implement averaging of all parameters for multiple selected stars
1121 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1122 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1123 }
1124 }
1127 static void
1128 sp_stb_defaults(GtkWidget *widget, GtkWidget *tbl)
1129 {
1130 // FIXME: in this and all other _default functions, set some flag telling the value_changed
1131 // callbacks to lump all the changes for all selected objects in one undo step
1133 GtkAdjustment *adj;
1135 // fixme: make settable in prefs!
1136 gint mag = 5;
1137 gdouble prop = 0.5;
1138 gboolean flat = FALSE;
1139 gdouble randomized = 0;
1140 gdouble rounded = 0;
1142 GtkWidget *fscb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "flat_checkbox");
1143 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), flat);
1144 GtkWidget *sb2 = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "prop_widget");
1145 gtk_widget_set_sensitive(GTK_WIDGET(sb2), !flat);
1147 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "magnitude");
1148 gtk_adjustment_set_value(adj, mag);
1149 gtk_adjustment_value_changed(adj);
1151 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "proportion");
1152 gtk_adjustment_set_value(adj, prop);
1153 gtk_adjustment_value_changed(adj);
1155 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rounded");
1156 gtk_adjustment_set_value(adj, rounded);
1157 gtk_adjustment_value_changed(adj);
1159 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "randomized");
1160 gtk_adjustment_set_value(adj, randomized);
1161 gtk_adjustment_value_changed(adj);
1163 spinbutton_defocus(GTK_OBJECT(tbl));
1164 }
1167 void
1168 sp_toolbox_add_label(GtkWidget *tbl, gchar const *title, bool wide)
1169 {
1170 GtkWidget *boxl = gtk_hbox_new(FALSE, 0);
1171 if (wide) gtk_widget_set_size_request(boxl, MODE_LABEL_WIDTH, -1);
1172 GtkWidget *l = gtk_label_new(NULL);
1173 gtk_label_set_markup(GTK_LABEL(l), title);
1174 gtk_box_pack_end(GTK_BOX(boxl), l, FALSE, FALSE, 0);
1175 gtk_box_pack_start(GTK_BOX(tbl), boxl, FALSE, FALSE, 0);
1176 gtk_object_set_data(GTK_OBJECT(tbl), "mode_label", l);
1177 }
1180 static GtkWidget *
1181 sp_star_toolbox_new(SPDesktop *desktop)
1182 {
1183 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1185 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1186 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1188 GtkTooltips *tt = gtk_tooltips_new();
1190 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1192 gchar const *flatsidedstr = NULL;
1194 /* Flatsided checkbox */
1195 {
1196 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1197 GtkWidget *fscb = gtk_check_button_new_with_label(_("Polygon"));
1198 gtk_widget_set_sensitive(GTK_WIDGET(fscb), TRUE);
1199 flatsidedstr = prefs_get_string_attribute("tools.shapes.star", "isflatsided");
1200 if (!flatsidedstr || (flatsidedstr && !strcmp(flatsidedstr, "false")))
1201 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), FALSE);
1202 else
1203 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), TRUE);
1204 gtk_tooltips_set_tip(tt, fscb, _("Regular polygon (with one handle) instead of a star"), NULL);
1205 gtk_widget_show(fscb);
1206 gtk_object_set_data(GTK_OBJECT(tbl), "flat_checkbox", fscb);
1207 gtk_container_add(GTK_CONTAINER(hb), fscb);
1208 g_signal_connect(G_OBJECT(fscb), "toggled", GTK_SIGNAL_FUNC(sp_stb_sides_flat_state_changed ), tbl);
1209 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_SPACING);
1210 }
1212 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
1214 /* Magnitude */
1215 {
1216 GtkWidget *hb = sp_tb_spinbutton(_("Corners:"), _("Number of corners of a polygon or star"),
1217 "tools.shapes.star", "magnitude", 3,
1218 NULL, tbl, TRUE, "altx-star",
1219 3, 1024, 1, 1,
1220 sp_stb_magnitude_value_changed, 1, 0);
1221 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1222 }
1224 /* Spoke ratio */
1225 {
1226 GtkWidget *hb = sp_tb_spinbutton(_("Spoke ratio:"),
1227 // TRANSLATORS: Tip radius of a star is the distance from the center to the farthest handle.
1228 // Base radius is the same for the closest handle.
1229 _("Base radius to tip radius ratio"),
1230 "tools.shapes.star", "proportion", 0.5,
1231 NULL, tbl, FALSE, NULL,
1232 0.01, 1.0, 0.01, 0.1,
1233 sp_stb_proportion_value_changed);
1234 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1235 g_object_set_data(G_OBJECT(tbl), "prop_widget", hb);
1236 if (!flatsidedstr || (flatsidedstr && !strcmp(flatsidedstr, "false")))
1237 gtk_widget_set_sensitive(GTK_WIDGET(hb), TRUE);
1238 else
1239 gtk_widget_set_sensitive(GTK_WIDGET(hb), FALSE);
1240 }
1242 /* Roundedness */
1243 {
1244 GtkWidget *hb = sp_tb_spinbutton(_("Rounded:"), _("How much rounded are the corners (0 for sharp)"),
1245 "tools.shapes.star", "rounded", 0.0,
1246 NULL, tbl, FALSE, NULL,
1247 -100.0, 100.0, 0.01, 0.1,
1248 sp_stb_rounded_value_changed);
1249 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1250 }
1252 /* Randomization */
1253 {
1254 GtkWidget *hb = sp_tb_spinbutton(_("Randomized:"), _("Scatter randomly the corners and angles"),
1255 "tools.shapes.star", "randomized", 0.0,
1256 NULL, tbl, FALSE, NULL,
1257 -10.0, 10.0, 0.001, 0.01,
1258 sp_stb_randomized_value_changed, 0.1, 3);
1259 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1260 }
1262 aux_toolbox_space(tbl, AUX_SPACING);
1264 /* Reset */
1265 {
1266 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1267 GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
1268 gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
1269 gtk_widget_show(b);
1270 gtk_container_add(GTK_CONTAINER(hb), b);
1271 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_stb_defaults), tbl);
1272 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_SPACING);
1273 }
1275 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1276 swatch->setWatchedTool ("tools.shapes.star", true);
1277 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1278 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1280 gtk_widget_show_all(tbl);
1281 sp_set_font_size_smaller (tbl);
1283 sigc::connection *connection = new sigc::connection(
1284 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_star_toolbox_selection_changed), (GtkObject *)tbl))
1285 );
1286 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1288 return tbl;
1289 }
1292 //########################
1293 //## Rect ##
1294 //########################
1296 static void
1297 sp_rtb_sensitivize (GtkWidget *tbl)
1298 {
1299 GtkAdjustment *adj1 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "rx"));
1300 GtkAdjustment *adj2 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "ry"));
1301 GtkWidget *not_rounded = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "not_rounded");
1303 if (adj1->value == 0 && adj2->value == 0 && gtk_object_get_data(GTK_OBJECT(tbl), "single")) { // only for a single selected rect (for now)
1304 gtk_widget_set_sensitive(GTK_WIDGET(not_rounded), FALSE);
1305 } else {
1306 gtk_widget_set_sensitive(GTK_WIDGET(not_rounded), TRUE);
1307 }
1308 }
1311 static void
1312 sp_rtb_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name,
1313 void (*setter)(SPRect *, gdouble))
1314 {
1315 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
1317 GtkWidget *us = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tbl), "units");
1318 SPUnit const *unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(us));
1320 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1321 prefs_set_double_attribute("tools.shapes.rect", value_name, sp_units_get_pixels(adj->value, *unit));
1322 }
1324 // quit if run by the attr_changed listener
1325 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1326 return;
1327 }
1329 // in turn, prevent listener from responding
1330 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1332 bool modmade = false;
1333 Inkscape::Selection *selection = sp_desktop_selection(desktop);
1334 for (GSList const *items = selection->itemList(); items != NULL; items = items->next) {
1335 if (SP_IS_RECT(items->data)) {
1336 if (adj->value != 0) {
1337 setter(SP_RECT(items->data), sp_units_get_pixels(adj->value, *unit));
1338 } else {
1339 SP_OBJECT_REPR(items->data)->setAttribute(value_name, NULL);
1340 }
1341 modmade = true;
1342 }
1343 }
1345 sp_rtb_sensitivize (tbl);
1347 if (modmade) {
1348 sp_document_done(sp_desktop_document(desktop));
1349 }
1351 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1353 // defocus spinbuttons by moving focus to the canvas, unless "stay" is on
1354 spinbutton_defocus(GTK_OBJECT(tbl));
1355 }
1357 static void
1358 sp_rtb_rx_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1359 {
1360 sp_rtb_value_changed(adj, tbl, "rx", sp_rect_set_visible_rx);
1361 }
1363 static void
1364 sp_rtb_ry_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1365 {
1366 sp_rtb_value_changed(adj, tbl, "ry", sp_rect_set_visible_ry);
1367 }
1369 static void
1370 sp_rtb_width_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1371 {
1372 sp_rtb_value_changed(adj, tbl, "width", sp_rect_set_visible_width);
1373 }
1375 static void
1376 sp_rtb_height_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1377 {
1378 sp_rtb_value_changed(adj, tbl, "height", sp_rect_set_visible_height);
1379 }
1383 static void
1384 sp_rtb_defaults( GtkWidget *widget, GtkObject *obj)
1385 {
1386 GtkWidget *tbl = GTK_WIDGET(obj);
1388 GtkAdjustment *adj;
1390 adj = (GtkAdjustment*)gtk_object_get_data(obj, "rx");
1391 gtk_adjustment_set_value(adj, 0.0);
1392 // this is necessary if the previous value was 0, but we still need to run the callback to change all selected objects
1393 gtk_adjustment_value_changed(adj);
1395 adj = (GtkAdjustment*)gtk_object_get_data(obj, "ry");
1396 gtk_adjustment_set_value(adj, 0.0);
1397 gtk_adjustment_value_changed(adj);
1399 sp_rtb_sensitivize (tbl);
1401 spinbutton_defocus(GTK_OBJECT(tbl));
1402 }
1404 static void rect_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1405 gchar const *old_value, gchar const *new_value,
1406 bool is_interactive, gpointer data)
1407 {
1408 GtkWidget *tbl = GTK_WIDGET(data);
1410 // quit if run by the _changed callbacks
1411 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1412 return;
1413 }
1415 // in turn, prevent callbacks from responding
1416 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1418 GtkWidget *us = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tbl), "units");
1419 SPUnit const *unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(us));
1421 SPItem *item = SP_ITEM(g_object_get_data(G_OBJECT(tbl), "item"));
1422 if (SP_IS_RECT(item)) {
1423 {
1424 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rx");
1425 gdouble rx = sp_rect_get_visible_rx(SP_RECT(item));
1426 gtk_adjustment_set_value(adj, sp_pixels_get_units(rx, *unit));
1427 }
1429 {
1430 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "ry");
1431 gdouble ry = sp_rect_get_visible_ry(SP_RECT(item));
1432 gtk_adjustment_set_value(adj, sp_pixels_get_units(ry, *unit));
1433 }
1435 {
1436 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "width");
1437 gdouble width = sp_rect_get_visible_width (SP_RECT(item));
1438 gtk_adjustment_set_value(adj, sp_pixels_get_units(width, *unit));
1439 }
1441 {
1442 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "height");
1443 gdouble height = sp_rect_get_visible_height (SP_RECT(item));
1444 gtk_adjustment_set_value(adj, sp_pixels_get_units(height, *unit));
1445 }
1446 }
1448 sp_rtb_sensitivize (tbl);
1450 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1451 }
1454 static Inkscape::XML::NodeEventVector rect_tb_repr_events = {
1455 NULL, /* child_added */
1456 NULL, /* child_removed */
1457 rect_tb_event_attr_changed,
1458 NULL, /* content_changed */
1459 NULL /* order_changed */
1460 };
1462 /**
1463 * \param selection should not be NULL.
1464 */
1465 static void
1466 sp_rect_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1467 {
1468 int n_selected = 0;
1469 Inkscape::XML::Node *repr = NULL;
1470 SPItem *item = NULL;
1471 Inkscape::XML::Node *oldrepr = NULL;
1473 for (GSList const *items = selection->itemList();
1474 items != NULL;
1475 items = items->next) {
1476 if (SP_IS_RECT((SPItem *) items->data)) {
1477 n_selected++;
1478 item = (SPItem *) items->data;
1479 repr = SP_OBJECT_REPR(item);
1480 }
1481 }
1483 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
1485 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(FALSE));
1487 if (n_selected == 0) {
1488 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
1490 GtkWidget *w = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "width_sb");
1491 gtk_widget_set_sensitive(w, FALSE);
1492 GtkWidget *h = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "height_sb");
1493 gtk_widget_set_sensitive(h, FALSE);
1495 } else if (n_selected == 1) {
1496 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1497 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
1499 GtkWidget *w = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "width_sb");
1500 gtk_widget_set_sensitive(w, TRUE);
1501 GtkWidget *h = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "height_sb");
1502 gtk_widget_set_sensitive(h, TRUE);
1504 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1505 if (oldrepr) { // remove old listener
1506 sp_repr_remove_listener_by_data(oldrepr, tbl);
1507 Inkscape::GC::release(oldrepr);
1508 oldrepr = 0;
1509 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1510 }
1511 if (repr) {
1512 g_object_set_data(G_OBJECT(tbl), "repr", repr);
1513 g_object_set_data(G_OBJECT(tbl), "item", item);
1514 Inkscape::GC::anchor(repr);
1515 sp_repr_add_listener(repr, &rect_tb_repr_events, tbl);
1516 sp_repr_synthesize_events(repr, &rect_tb_repr_events, tbl);
1517 }
1518 } else {
1519 // FIXME: implement averaging of all parameters for multiple selected
1520 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1521 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1522 sp_rtb_sensitivize (GTK_WIDGET(tbl));
1523 }
1524 }
1527 static GtkWidget *
1528 sp_rect_toolbox_new(SPDesktop *desktop)
1529 {
1530 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1532 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1533 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1535 GtkTooltips *tt = gtk_tooltips_new();
1537 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1539 // rx/ry units menu: create
1540 GtkWidget *us = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
1541 sp_unit_selector_setsize(us, AUX_OPTION_MENU_WIDTH, AUX_OPTION_MENU_HEIGHT);
1542 sp_unit_selector_set_unit(SP_UNIT_SELECTOR(us), desktop->namedview->doc_units);
1543 // fixme: add % meaning per cent of the width/height
1545 /* W */
1546 {
1547 GtkWidget *hb = sp_tb_spinbutton(_("W:"), _("Width of rectangle"),
1548 "tools.shapes.rect", "width", 0,
1549 us, tbl, TRUE, "altx-rect",
1550 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1551 sp_rtb_width_value_changed);
1552 gtk_object_set_data(GTK_OBJECT(tbl), "width_sb", hb);
1553 gtk_widget_set_sensitive(hb, FALSE);
1554 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1555 }
1557 /* H */
1558 {
1559 GtkWidget *hb = sp_tb_spinbutton(_("H:"), _("Height of rectangle"),
1560 "tools.shapes.rect", "height", 0,
1561 us, tbl, FALSE, NULL,
1562 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1563 sp_rtb_height_value_changed);
1564 gtk_object_set_data(GTK_OBJECT(tbl), "height_sb", hb);
1565 gtk_widget_set_sensitive(hb, FALSE);
1566 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1567 }
1569 /* rx */
1570 {
1571 GtkWidget *hb = sp_tb_spinbutton(_("Rx:"), _("Horizontal radius of rounded corners"),
1572 "tools.shapes.rect", "rx", 0,
1573 us, tbl, FALSE, NULL,
1574 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1575 sp_rtb_rx_value_changed);
1576 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1577 }
1579 /* ry */
1580 {
1581 GtkWidget *hb = sp_tb_spinbutton(_("Ry:"), _("Vertical radius of rounded corners"),
1582 "tools.shapes.rect", "ry", 0,
1583 us, tbl, FALSE, NULL,
1584 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1585 sp_rtb_ry_value_changed);
1586 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1587 }
1589 // add the units menu
1590 gtk_widget_show(us);
1591 gtk_box_pack_start(GTK_BOX(tbl), us, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1592 gtk_object_set_data(GTK_OBJECT(tbl), "units", us);
1594 /* Reset */
1595 {
1596 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1597 GtkWidget *b = gtk_button_new_with_label(_("Not rounded"));
1598 gtk_object_set_data(GTK_OBJECT(tbl), "not_rounded", b);
1599 gtk_tooltips_set_tip(tt, b, _("Make corners sharp"), NULL);
1600 gtk_widget_show(b);
1601 gtk_container_add(GTK_CONTAINER(hb), b);
1602 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_rtb_defaults), tbl);
1603 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1604 }
1606 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1607 swatch->setWatchedTool ("tools.shapes.rect", true);
1608 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1609 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1611 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
1612 sp_rtb_sensitivize (tbl);
1614 gtk_widget_show_all(tbl);
1615 sp_set_font_size_smaller (tbl);
1617 sigc::connection *connection = new sigc::connection(
1618 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_rect_toolbox_selection_changed), (GtkObject *)tbl))
1619 );
1620 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1622 return tbl;
1623 }
1625 //########################
1626 //## Spiral ##
1627 //########################
1629 static void
1630 sp_spl_tb_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name)
1631 {
1632 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
1634 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1635 prefs_set_double_attribute("tools.shapes.spiral", value_name, adj->value);
1636 }
1638 // quit if run by the attr_changed listener
1639 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1640 return;
1641 }
1643 // in turn, prevent listener from responding
1644 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1646 gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
1648 bool modmade = false;
1649 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
1650 items != NULL;
1651 items = items->next)
1652 {
1653 if (SP_IS_SPIRAL((SPItem *) items->data)) {
1654 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
1655 sp_repr_set_svg_double( repr, namespaced_name, adj->value );
1656 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
1657 modmade = true;
1658 }
1659 }
1661 g_free(namespaced_name);
1663 if (modmade) {
1664 sp_document_done(sp_desktop_document(desktop));
1665 }
1667 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1669 spinbutton_defocus(GTK_OBJECT(tbl));
1670 }
1672 static void
1673 sp_spl_tb_revolution_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1674 {
1675 sp_spl_tb_value_changed(adj, tbl, "revolution");
1676 }
1678 static void
1679 sp_spl_tb_expansion_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1680 {
1681 sp_spl_tb_value_changed(adj, tbl, "expansion");
1682 }
1684 static void
1685 sp_spl_tb_t0_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1686 {
1687 sp_spl_tb_value_changed(adj, tbl, "t0");
1688 }
1690 static void
1691 sp_spl_tb_defaults(GtkWidget *widget, GtkObject *obj)
1692 {
1693 GtkWidget *tbl = GTK_WIDGET(obj);
1695 GtkAdjustment *adj;
1697 // fixme: make settable
1698 gdouble rev = 5;
1699 gdouble exp = 1.0;
1700 gdouble t0 = 0.0;
1702 adj = (GtkAdjustment*)gtk_object_get_data(obj, "revolution");
1703 gtk_adjustment_set_value(adj, rev);
1704 gtk_adjustment_value_changed(adj);
1706 adj = (GtkAdjustment*)gtk_object_get_data(obj, "expansion");
1707 gtk_adjustment_set_value(adj, exp);
1708 gtk_adjustment_value_changed(adj);
1710 adj = (GtkAdjustment*)gtk_object_get_data(obj, "t0");
1711 gtk_adjustment_set_value(adj, t0);
1712 gtk_adjustment_value_changed(adj);
1714 spinbutton_defocus(GTK_OBJECT(tbl));
1715 }
1718 static void spiral_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1719 gchar const *old_value, gchar const *new_value,
1720 bool is_interactive, gpointer data)
1721 {
1722 GtkWidget *tbl = GTK_WIDGET(data);
1724 // quit if run by the _changed callbacks
1725 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1726 return;
1727 }
1729 // in turn, prevent callbacks from responding
1730 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1732 GtkAdjustment *adj;
1733 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "revolution");
1734 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:revolution", 3.0)));
1736 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "expansion");
1737 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:expansion", 1.0)));
1739 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "t0");
1740 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:t0", 0.0)));
1742 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1743 }
1746 static Inkscape::XML::NodeEventVector spiral_tb_repr_events = {
1747 NULL, /* child_added */
1748 NULL, /* child_removed */
1749 spiral_tb_event_attr_changed,
1750 NULL, /* content_changed */
1751 NULL /* order_changed */
1752 };
1754 static void
1755 sp_spiral_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1756 {
1757 int n_selected = 0;
1758 Inkscape::XML::Node *repr = NULL;
1759 Inkscape::XML::Node *oldrepr = NULL;
1761 for (GSList const *items = selection->itemList();
1762 items != NULL;
1763 items = items->next)
1764 {
1765 if (SP_IS_SPIRAL((SPItem *) items->data)) {
1766 n_selected++;
1767 repr = SP_OBJECT_REPR((SPItem *) items->data);
1768 }
1769 }
1771 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
1773 if (n_selected == 0) {
1774 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
1775 } else if (n_selected == 1) {
1776 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1778 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1779 if (oldrepr) { // remove old listener
1780 sp_repr_remove_listener_by_data(oldrepr, tbl);
1781 Inkscape::GC::release(oldrepr);
1782 oldrepr = 0;
1783 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1784 }
1786 if (repr) {
1787 g_object_set_data(G_OBJECT(tbl), "repr", repr);
1788 Inkscape::GC::anchor(repr);
1789 sp_repr_add_listener(repr, &spiral_tb_repr_events, tbl);
1790 sp_repr_synthesize_events(repr, &spiral_tb_repr_events, tbl);
1791 }
1792 } else {
1793 // FIXME: implement averaging of all parameters for multiple selected
1794 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1795 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1796 }
1797 }
1800 static GtkWidget *
1801 sp_spiral_toolbox_new(SPDesktop *desktop)
1802 {
1803 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1804 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1805 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1807 GtkTooltips *tt = gtk_tooltips_new();
1809 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1811 /* Revolution */
1812 {
1813 GtkWidget *hb = sp_tb_spinbutton(_("Turns:"), _("Number of revolutions"),
1814 "tools.shapes.spiral", "revolution", 3.0,
1815 NULL, tbl, TRUE, "altx-spiral",
1816 0.01, 1024.0, 0.1, 1.0,
1817 sp_spl_tb_revolution_value_changed, 1, 2);
1818 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1819 }
1821 /* Expansion */
1822 {
1823 GtkWidget *hb = sp_tb_spinbutton(_("Divergence:"), _("How much denser/sparser are outer revolutions; 1 = uniform"),
1824 "tools.shapes.spiral", "expansion", 1.0,
1825 NULL, tbl, FALSE, NULL,
1826 0.0, 1000.0, 0.01, 1.0,
1827 sp_spl_tb_expansion_value_changed);
1828 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1829 }
1831 /* T0 */
1832 {
1833 GtkWidget *hb = sp_tb_spinbutton(_("Inner radius:"), _("Radius of the innermost revolution (relative to the spiral size)"),
1834 "tools.shapes.spiral", "t0", 0.0,
1835 NULL, tbl, FALSE, NULL,
1836 0.0, 0.999, 0.01, 1.0,
1837 sp_spl_tb_t0_value_changed);
1838 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1839 }
1841 aux_toolbox_space(tbl, AUX_SPACING);
1843 /* Reset */
1844 {
1845 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1846 GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
1847 gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
1848 gtk_widget_show(b);
1849 gtk_container_add(GTK_CONTAINER(hb), b);
1850 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_spl_tb_defaults), tbl);
1851 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1852 }
1854 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1855 swatch->setWatchedTool ("tools.shapes.spiral", true);
1856 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1857 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1859 gtk_widget_show_all(tbl);
1860 sp_set_font_size_smaller (tbl);
1862 sigc::connection *connection = new sigc::connection(
1863 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_spiral_toolbox_selection_changed), (GtkObject *)tbl))
1864 );
1865 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1867 return tbl;
1868 }
1870 //########################
1871 //## Pen/Pencil ##
1872 //########################
1875 static GtkWidget *
1876 sp_pen_toolbox_new(SPDesktop *desktop)
1877 {
1878 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1879 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1880 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1882 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1883 swatch->setWatchedTool ("tools.freehand.pen", true);
1884 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1885 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1887 gtk_widget_show_all(tbl);
1888 sp_set_font_size_smaller (tbl);
1890 return tbl;
1891 }
1893 static GtkWidget *
1894 sp_pencil_toolbox_new(SPDesktop *desktop)
1895 {
1896 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1897 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1898 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1900 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1901 swatch->setWatchedTool ("tools.freehand.pencil", true);
1902 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1903 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1905 gtk_widget_show_all(tbl);
1906 sp_set_font_size_smaller (tbl);
1908 return tbl;
1909 }
1912 //########################
1913 //## Calligraphy ##
1914 //########################
1916 static void
1917 sp_ddc_mass_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1918 {
1919 prefs_set_double_attribute("tools.calligraphic", "mass", adj->value);
1920 spinbutton_defocus(GTK_OBJECT(tbl));
1921 }
1923 static void
1924 sp_ddc_drag_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1925 {
1926 prefs_set_double_attribute("tools.calligraphic", "drag", adj->value);
1927 spinbutton_defocus(GTK_OBJECT(tbl));
1928 }
1930 static void
1931 sp_ddc_angle_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1932 {
1933 prefs_set_double_attribute("tools.calligraphic", "angle", adj->value);
1934 spinbutton_defocus(GTK_OBJECT(tbl));
1935 }
1937 static void
1938 sp_ddc_width_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1939 {
1940 prefs_set_double_attribute("tools.calligraphic", "width", adj->value * 0.01);
1941 spinbutton_defocus(GTK_OBJECT(tbl));
1942 }
1944 static void
1945 sp_ddc_velthin_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1946 {
1947 prefs_set_double_attribute("tools.calligraphic", "thinning", adj->value);
1948 spinbutton_defocus(GTK_OBJECT(tbl));
1949 }
1951 static void
1952 sp_ddc_flatness_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1953 {
1954 prefs_set_double_attribute("tools.calligraphic", "flatness", adj->value);
1955 spinbutton_defocus(GTK_OBJECT(tbl));
1956 }
1958 static void
1959 sp_ddc_tremor_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1960 {
1961 prefs_set_double_attribute("tools.calligraphic", "tremor", adj->value);
1962 spinbutton_defocus(GTK_OBJECT(tbl));
1963 }
1965 static void
1966 sp_ddc_pressure_state_changed(GtkWidget *button, gpointer data)
1967 {
1968 prefs_set_int_attribute ("tools.calligraphic", "usepressure", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0);
1969 }
1971 static void
1972 sp_ddc_tilt_state_changed(GtkWidget *button, GtkWidget *calligraphy_angle)
1973 {
1974 prefs_set_int_attribute ("tools.calligraphic", "usetilt", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0);
1976 gtk_widget_set_sensitive(GTK_WIDGET(calligraphy_angle), !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
1977 }
1979 static void sp_ddc_defaults(GtkWidget *, GtkWidget *tbl)
1980 {
1981 // FIXME: make defaults settable via Inkscape Options
1982 struct KeyValue {
1983 char const *key;
1984 double value;
1985 } const key_values[] = {
1986 {"mass", 0.02},
1987 {"drag", 1.0},
1988 {"angle", 30.0},
1989 {"width", 15},
1990 {"thinning", 0.1},
1991 {"tremor", 0.0},
1992 {"flatness", 0.9}
1993 };
1995 for (unsigned i = 0; i < G_N_ELEMENTS(key_values); ++i) {
1996 KeyValue const &kv = key_values[i];
1997 GtkAdjustment &adj = *static_cast<GtkAdjustment *>(gtk_object_get_data(GTK_OBJECT(tbl), kv.key));
1998 gtk_adjustment_set_value(&adj, kv.value);
1999 }
2001 spinbutton_defocus(GTK_OBJECT(tbl));
2002 }
2004 static GtkWidget *
2005 sp_calligraphy_toolbox_new(SPDesktop *desktop)
2006 {
2007 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2008 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2009 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2011 GtkTooltips *tt = gtk_tooltips_new();
2012 GtkWidget *calligraphy_angle;
2014 // interval
2015 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2017 /* Width */
2018 {
2019 GtkWidget *hb = sp_tb_spinbutton(_("Width:"), _("The width of the calligraphic pen (relative to the visible canvas area)"),
2020 "tools.calligraphic", "width", 15,
2021 NULL, tbl, TRUE, "altx-calligraphy",
2022 1, 100, 1.0, 10.0,
2023 sp_ddc_width_value_changed, 0.01, 0, 100);
2024 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2025 }
2027 /* Thinning */
2028 {
2029 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)"),
2030 "tools.calligraphic", "thinning", 0.1,
2031 NULL, tbl, FALSE, NULL,
2032 -1.0, 1.0, 0.01, 0.1,
2033 sp_ddc_velthin_value_changed, 0.01, 2);
2034 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2035 }
2037 // interval
2038 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2040 /* Angle */
2041 {
2042 calligraphy_angle = sp_tb_spinbutton(_("Angle:"), _("The angle of the pen's nib (in degrees; 0 = horizontal; has no effect if fixation = 0)"),
2043 "tools.calligraphic", "angle", 30,
2044 NULL, tbl, TRUE, "calligraphy-angle",
2045 -90.0, 90.0, 1.0, 10.0,
2046 sp_ddc_angle_value_changed, 1, 0);
2047 gtk_box_pack_start(GTK_BOX(tbl), calligraphy_angle, FALSE, FALSE, AUX_SPACING);
2048 }
2050 /* Fixation */
2051 {
2052 GtkWidget *hb = sp_tb_spinbutton(_("Fixation:"), _("How fixed is the pen angle (0 = always perpendicular to stroke direction, 1 = fixed)"),
2053 "tools.calligraphic", "flatness", 0.9,
2054 NULL, tbl, FALSE, NULL,
2055 0.0, 1.0, 0.01, 0.1,
2056 sp_ddc_flatness_value_changed, 0.01, 2);
2057 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2058 }
2060 // interval
2061 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2063 /* Tremor */
2064 {
2065 GtkWidget *hb = sp_tb_spinbutton(_("Tremor:"), _("How uneven or trembling is the pen stroke"),
2066 "tools.calligraphic", "tremor", 0.0,
2067 NULL, tbl, FALSE, NULL,
2068 0.0, 1.0, 0.01, 0.1,
2069 sp_ddc_tremor_value_changed, 0.01, 2);
2070 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2071 }
2072 /* Mass */
2073 {
2074 GtkWidget *hb = sp_tb_spinbutton(_("Mass:"), _("How much inertia affects the movement of the pen"),
2075 "tools.calligraphic", "mass", 0.02,
2076 NULL, tbl, FALSE, NULL,
2077 0.0, 1.0, 0.01, 0.1,
2078 sp_ddc_mass_value_changed, 0.01, 2);
2079 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2080 }
2082 /* Drag */
2083 {
2084 // TRANSLATORS: "drag" means "resistance" here
2085 GtkWidget *hb = sp_tb_spinbutton(_("Drag:"), _("How much resistance affects the movement of the pen"),
2086 "tools.calligraphic", "drag", 1,
2087 NULL, tbl, FALSE, NULL,
2088 0.0, 1.0, 0.01, 0.1,
2089 sp_ddc_drag_value_changed, 0.01, 2);
2090 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2091 }
2093 // interval
2094 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2096 GtkWidget *cvbox = gtk_vbox_new (FALSE, 0);
2097 GtkWidget *cbox = gtk_hbox_new (FALSE, 0);
2099 /* Use Pressure button */
2100 {
2101 GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
2102 SP_BUTTON_TYPE_TOGGLE,
2103 NULL,
2104 "use_pressure",
2105 _("Use the pressure of the input device to alter the width of the pen"),
2106 tt);
2107 g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (sp_ddc_pressure_state_changed), NULL);
2108 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.calligraphic", "usepressure", 1));
2109 gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
2110 }
2112 /* Use Tilt button */
2113 {
2114 GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
2115 SP_BUTTON_TYPE_TOGGLE,
2116 NULL,
2117 "use_tilt",
2118 _("Use the tilt of the input device to alter the angle of the pen's nib"),
2119 tt);
2120 g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (sp_ddc_tilt_state_changed), calligraphy_angle);
2121 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.calligraphic", "usetilt", 1));
2122 gtk_widget_set_sensitive(GTK_WIDGET(calligraphy_angle), !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
2123 gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
2124 }
2126 gtk_box_pack_start(GTK_BOX(cvbox), cbox, TRUE, FALSE, 0);
2127 gtk_box_pack_start(GTK_BOX(tbl), cvbox, FALSE, FALSE, 0);
2129 /* Reset */
2130 {
2131 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2132 GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
2133 gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
2134 gtk_widget_show(b);
2135 gtk_container_add(GTK_CONTAINER(hb), b);
2136 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_ddc_defaults), tbl);
2137 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2138 }
2141 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
2142 swatch->setWatchedTool ("tools.calligraphic", true);
2143 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
2144 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
2146 gtk_widget_show_all(tbl);
2147 sp_set_font_size_smaller (tbl);
2149 return tbl;
2150 }
2153 //########################
2154 //## Circle / Arc ##
2155 //########################
2157 static void
2158 sp_arctb_sensitivize (GtkWidget *tbl, double v1, double v2)
2159 {
2160 GtkWidget *ocb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "open_checkbox");
2161 GtkWidget *make_whole = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "make_whole");
2163 if (v1 == 0 && v2 == 0) {
2164 if (gtk_object_get_data(GTK_OBJECT(tbl), "single")) { // only for a single selected ellipse (for now)
2165 gtk_widget_set_sensitive(GTK_WIDGET(ocb), FALSE);
2166 gtk_widget_set_sensitive(GTK_WIDGET(make_whole), FALSE);
2167 }
2168 } else {
2169 gtk_widget_set_sensitive(GTK_WIDGET(ocb), TRUE);
2170 gtk_widget_set_sensitive(GTK_WIDGET(make_whole), TRUE);
2171 }
2172 }
2174 static void
2175 sp_arctb_startend_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name, gchar const *other_name)
2176 {
2177 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2179 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2180 prefs_set_double_attribute("tools.shapes.arc", value_name, (adj->value * M_PI)/ 180);
2181 }
2183 // quit if run by the attr_changed listener
2184 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2185 return;
2186 }
2188 // in turn, prevent listener from responding
2189 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2191 gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
2193 bool modmade = false;
2194 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2195 items != NULL;
2196 items = items->next)
2197 {
2198 SPItem *item = SP_ITEM(items->data);
2200 if (SP_IS_ARC(item) && SP_IS_GENERICELLIPSE(item)) {
2202 SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
2203 SPArc *arc = SP_ARC(item);
2205 if (!strcmp(value_name, "start"))
2206 ge->start = (adj->value * M_PI)/ 180;
2207 else
2208 ge->end = (adj->value * M_PI)/ 180;
2210 sp_genericellipse_normalize(ge);
2211 ((SPObject *)arc)->updateRepr();
2212 ((SPObject *)arc)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
2214 modmade = true;
2215 }
2216 }
2218 g_free(namespaced_name);
2220 GtkAdjustment *other = (GtkAdjustment *)gtk_object_get_data(GTK_OBJECT(tbl), other_name);
2222 sp_arctb_sensitivize (tbl, adj->value, other->value);
2224 if (modmade) {
2225 sp_document_maybe_done(sp_desktop_document(desktop), value_name);
2226 }
2228 // defocus spinbuttons by moving focus to the canvas, unless "stay" is on
2229 spinbutton_defocus(GTK_OBJECT(tbl));
2231 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2232 }
2235 static void
2236 sp_arctb_start_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
2237 {
2238 sp_arctb_startend_value_changed(adj, tbl, "start", "end");
2239 }
2241 static void
2242 sp_arctb_end_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
2243 {
2244 sp_arctb_startend_value_changed(adj, tbl, "end", "start");
2245 }
2247 static void
2248 sp_arctb_open_state_changed(GtkWidget *widget, GtkObject *tbl)
2249 {
2250 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2252 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2253 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
2254 prefs_set_string_attribute("tools.shapes.arc", "open", "true");
2255 } else {
2256 prefs_set_string_attribute("tools.shapes.arc", "open", NULL);
2257 }
2258 }
2260 // quit if run by the attr_changed listener
2261 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2262 return;
2263 }
2265 // in turn, prevent listener from responding
2266 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2268 bool modmade = false;
2270 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
2271 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2272 items != NULL;
2273 items = items->next)
2274 {
2275 if (SP_IS_ARC((SPItem *) items->data)) {
2276 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2277 repr->setAttribute("sodipodi:open", "true");
2278 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
2279 modmade = true;
2280 }
2281 }
2282 } else {
2283 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2284 items != NULL;
2285 items = items->next)
2286 {
2287 if (SP_IS_ARC((SPItem *) items->data)) {
2288 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2289 repr->setAttribute("sodipodi:open", NULL);
2290 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
2291 modmade = true;
2292 }
2293 }
2294 }
2296 if (modmade) {
2297 sp_document_done(sp_desktop_document(desktop));
2298 }
2300 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2302 spinbutton_defocus(GTK_OBJECT(tbl));
2303 }
2305 static void sp_arctb_defaults(GtkWidget *, GtkObject *obj)
2306 {
2307 GtkWidget *tbl = GTK_WIDGET(obj);
2309 GtkAdjustment *adj;
2310 adj = (GtkAdjustment*)gtk_object_get_data(obj, "start");
2311 gtk_adjustment_set_value(adj, 0.0);
2312 gtk_adjustment_value_changed(adj);
2314 adj = (GtkAdjustment*)gtk_object_get_data(obj, "end");
2315 gtk_adjustment_set_value(adj, 0.0);
2316 gtk_adjustment_value_changed(adj);
2318 spinbutton_defocus(GTK_OBJECT(tbl));
2319 }
2321 static void arc_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
2322 gchar const *old_value, gchar const *new_value,
2323 bool is_interactive, gpointer data)
2324 {
2325 GtkWidget *tbl = GTK_WIDGET(data);
2327 // quit if run by the _changed callbacks
2328 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2329 return;
2330 }
2332 // in turn, prevent callbacks from responding
2333 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2335 gdouble start = sp_repr_get_double_attribute(repr, "sodipodi:start", 0.0);
2336 gdouble end = sp_repr_get_double_attribute(repr, "sodipodi:end", 0.0);
2338 GtkAdjustment *adj1,*adj2;
2339 adj1 = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "start");
2340 gtk_adjustment_set_value(adj1, mod360((start * 180)/M_PI));
2341 adj2 = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "end");
2342 gtk_adjustment_set_value(adj2, mod360((end * 180)/M_PI));
2344 sp_arctb_sensitivize (tbl, adj1->value, adj2->value);
2346 char const *openstr = NULL;
2347 openstr = repr->attribute("sodipodi:open");
2348 GtkWidget *ocb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "open_checkbox");
2350 if (openstr) {
2351 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ocb), TRUE);
2352 } else {
2353 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ocb), FALSE);
2354 }
2356 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2357 }
2359 static Inkscape::XML::NodeEventVector arc_tb_repr_events = {
2360 NULL, /* child_added */
2361 NULL, /* child_removed */
2362 arc_tb_event_attr_changed,
2363 NULL, /* content_changed */
2364 NULL /* order_changed */
2365 };
2368 static void
2369 sp_arc_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
2370 {
2371 int n_selected = 0;
2372 Inkscape::XML::Node *repr = NULL;
2373 Inkscape::XML::Node *oldrepr = NULL;
2375 for (GSList const *items = selection->itemList();
2376 items != NULL;
2377 items = items->next)
2378 {
2379 if (SP_IS_ARC((SPItem *) items->data)) {
2380 n_selected++;
2381 repr = SP_OBJECT_REPR((SPItem *) items->data);
2382 }
2383 }
2385 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
2387 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(FALSE));
2388 if (n_selected == 0) {
2389 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
2390 } else if (n_selected == 1) {
2391 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
2392 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2394 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
2396 if (oldrepr) { // remove old listener
2397 sp_repr_remove_listener_by_data(oldrepr, tbl);
2398 Inkscape::GC::release(oldrepr);
2399 oldrepr = 0;
2400 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
2401 }
2403 if (repr) {
2404 g_object_set_data(G_OBJECT(tbl), "repr", repr);
2405 Inkscape::GC::anchor(repr);
2406 sp_repr_add_listener(repr, &arc_tb_repr_events, tbl);
2407 sp_repr_synthesize_events(repr, &arc_tb_repr_events, tbl);
2408 }
2409 } else {
2410 // FIXME: implement averaging of all parameters for multiple selected
2411 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
2412 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2413 sp_arctb_sensitivize (GTK_WIDGET(tbl), 1, 0);
2414 }
2415 }
2418 static GtkWidget *
2419 sp_arc_toolbox_new(SPDesktop *desktop)
2420 {
2421 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2423 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2424 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2426 GtkTooltips *tt = gtk_tooltips_new();
2428 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
2430 /* Start */
2431 {
2432 GtkWidget *hb = sp_tb_spinbutton(_("Start:"), _("The angle (in degrees) from the horizontal to the arc's start point"),
2433 "tools.shapes.arc", "start", 0.0,
2434 NULL, tbl, TRUE, "altx-arc",
2435 -360.0, 360.0, 1.0, 10.0,
2436 sp_arctb_start_value_changed);
2437 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2438 }
2440 /* End */
2441 {
2442 GtkWidget *hb = sp_tb_spinbutton(_("End:"), _("The angle (in degrees) from the horizontal to the arc's end point"),
2443 "tools.shapes.arc", "end", 0.0,
2444 NULL, tbl, FALSE, NULL,
2445 -360.0, 360.0, 1.0, 10.0,
2446 sp_arctb_end_value_changed);
2447 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2448 }
2450 /* Segments / Pie checkbox */
2451 {
2452 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2453 GtkWidget *fscb = gtk_check_button_new_with_label(_("Open arc"));
2454 gtk_tooltips_set_tip(tt, fscb, _("Switch between arc (unclosed shape) and segment (closed shape with two radii)"), NULL);
2456 gchar const *openstr = NULL;
2457 openstr = prefs_get_string_attribute("tools.shapes.arc", "open");
2458 if (!openstr || (openstr && !strcmp(openstr, "false")))
2459 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), FALSE);
2460 else
2461 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), TRUE);
2463 gtk_widget_show(fscb);
2464 gtk_object_set_data(GTK_OBJECT(tbl), "open_checkbox", fscb);
2465 gtk_container_add(GTK_CONTAINER(hb), fscb);
2466 g_signal_connect(G_OBJECT(fscb), "toggled", GTK_SIGNAL_FUNC(sp_arctb_open_state_changed ), tbl);
2467 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2468 }
2470 /* Make Whole */
2471 {
2472 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2473 GtkWidget *b = gtk_button_new_with_label(_("Make whole"));
2474 gtk_object_set_data(GTK_OBJECT(tbl), "make_whole", b);
2475 gtk_tooltips_set_tip(tt, b, _("Make the shape a whole ellipse, not arc or segment"), NULL);
2476 gtk_widget_show(b);
2477 gtk_container_add(GTK_CONTAINER(hb), b);
2478 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_arctb_defaults), tbl);
2479 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2480 }
2482 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
2483 // sensitivize make whole and open checkbox
2484 {
2485 GtkAdjustment *adj1 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "start"));
2486 GtkAdjustment *adj2 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "end"));
2487 sp_arctb_sensitivize (tbl, adj1->value, adj2->value);
2488 }
2490 sigc::connection *connection = new sigc::connection(
2491 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_arc_toolbox_selection_changed), (GtkObject *)tbl))
2492 );
2493 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
2495 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
2496 swatch->setWatchedTool ("tools.shapes.arc", true);
2497 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
2498 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
2500 gtk_widget_show_all(tbl);
2501 sp_set_font_size_smaller (tbl);
2503 return tbl;
2504 }
2509 // toggle button callbacks and updaters
2511 //########################
2512 //## Dropper ##
2513 //########################
2515 static void toggle_dropper_color_pick (GtkWidget *button, gpointer data) {
2516 prefs_set_int_attribute ("tools.dropper", "pick",
2517 // 0 and 1 are backwards here because of pref
2518 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1);
2519 }
2522 /**
2523 * Copy the current saved desktop color to the clipboard as full hex + alpha
2524 * color representation. This is useful for passing values between various
2525 * input boxes, or directly to xml.
2526 */
2527 /* static void
2528 sp_dropper_copy( GtkWidget *widget, GtkObject *obj)
2529 {
2530 GtkWidget *tbl = GTK_WIDGET(obj);
2532 SPDesktop *desktop =
2533 (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2536 sp_dropper_c32_color_copy( sp_desktop_get_color(desktop, true) );
2537 }*/
2540 /**
2541 * Copies currently saved desktop color to the clipboard as a hex value. This
2542 * is useful for editing webpages and needing a value quickly for web
2543 * colors.
2544 *
2545 * TODO: When the toggle of the dropper is set to not mix color against
2546 * page background, this still just gets the color of the page and
2547 * doesn't get the actual mixed against background which is needed
2548 * for the hex value ppl. want for web pages, etc.
2549 */
2551 /* static void
2552 sp_dropper_copy_as_hex ( GtkWidget *widget, GtkObject *obj)
2553 {
2554 GtkWidget *tbl = GTK_WIDGET(obj);
2556 SPDesktop *desktop =
2557 (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2559 sp_dropper_c32_color_copy_hex( sp_desktop_get_color(desktop, true) );
2560 }*/
2563 /**
2564 * Sets the input boxes with the changed color and opacity. This is used as a
2565 * callback for style changing.
2566 */
2567 /* static bool
2568 sp_style_changed (const SPCSSAttr *css, gpointer data)
2569 {
2570 // GrDrag *drag = (GrDrag *) data;
2572 // set fill of text entry box
2573 if (css->attribute("fill"))
2574 gtk_entry_set_text((GtkEntry *)dropper_rgb_entry,
2575 css->attribute("fill"));
2577 // set opacity of text entry box
2578 if (css->attribute("fill-opacity"))
2579 gtk_entry_set_text((GtkEntry *)dropper_opacity_entry,
2580 css->attribute("fill-opacity"));
2582 // set fill of text entry box
2583 if (css->attribute("stroke"))
2584 gtk_entry_set_text((GtkEntry *)dropper_rgb_entry,
2585 css->attribute("stroke"));
2587 // set opacity of text entry box
2588 if (css->attribute("stroke-opacity"))
2589 gtk_entry_set_text((GtkEntry *)dropper_opacity_entry,
2590 css->attribute("stroke-opacity"));
2591 return false;
2593 }
2594 */
2597 /**
2598 * Dropper auxiliary toolbar construction and setup.
2599 *
2600 * TODO: Would like to add swatch of current color.
2601 * TODO: Add queue of last 5 or so colors selected with new swatches so that
2602 * can drag and drop places. Will provide a nice mixing palette.
2603 */
2604 static GtkWidget *
2605 sp_dropper_toolbox_new(SPDesktop *desktop)
2606 {
2607 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2609 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2610 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2612 GtkTooltips *tt = gtk_tooltips_new();
2615 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
2616 AUX_BETWEEN_BUTTON_GROUPS);
2617 // sp_toolbox_add_label(tbl, _("<b>New:</b>"));
2621 /* RGB Input Field */
2622 /* {
2623 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2624 GtkWidget *dropper_rgba_label = gtk_label_new ("Color:");
2625 gtk_widget_show (dropper_rgba_label);
2626 gtk_container_add(GTK_CONTAINER(hb), dropper_rgba_label);
2628 dropper_rgb_entry = gtk_entry_new ();
2629 sp_dialog_defocus_on_enter (dropper_rgb_entry);
2630 gtk_entry_set_max_length (GTK_ENTRY (dropper_rgb_entry), 7);
2631 gtk_entry_set_width_chars (GTK_ENTRY (dropper_rgb_entry), 7);
2632 gtk_tooltips_set_tip(tt, dropper_rgb_entry,
2633 _("Hexidecimal representation of last selected "
2634 "color"),
2635 NULL);
2636 gtk_widget_show (dropper_rgb_entry);
2637 gtk_container_add(GTK_CONTAINER(hb), dropper_rgb_entry);
2639 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2640 AUX_BETWEEN_BUTTON_GROUPS);
2641 } */
2643 /* Opacity Input Field */
2644 /* {
2645 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2646 GtkWidget *dropper_opacity_label = gtk_label_new ( _("Opacity:") );
2647 gtk_widget_show (dropper_opacity_label);
2648 gtk_container_add(GTK_CONTAINER(hb), dropper_opacity_label);
2650 dropper_opacity_entry = gtk_entry_new ();
2651 sp_dialog_defocus_on_enter (dropper_opacity_entry);
2652 gtk_entry_set_max_length (GTK_ENTRY (dropper_opacity_entry), 11);
2653 gtk_entry_set_width_chars (GTK_ENTRY (dropper_opacity_entry), 11);
2654 gtk_tooltips_set_tip(tt, dropper_opacity_entry,
2655 _("Opacity of last selected color"),
2656 NULL);
2657 gtk_widget_show (dropper_opacity_entry);
2658 gtk_container_add(GTK_CONTAINER(hb), dropper_opacity_entry);
2660 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2661 AUX_BETWEEN_BUTTON_GROUPS);
2662 } */
2665 /* Copy to Clipboard */
2666 /* {
2667 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2668 GtkWidget *b = gtk_button_new_with_label(_("Copy as RGBA"));
2669 gtk_tooltips_set_tip(tt, b, _("Copy last saved color as hexidecimal "
2670 "RGB + Alpha (RGBA) to "
2671 "clipboard"),
2672 NULL);
2673 gtk_widget_show(b);
2674 gtk_container_add(GTK_CONTAINER(hb), b);
2675 gtk_signal_connect(GTK_OBJECT(b), "clicked",
2676 GTK_SIGNAL_FUNC(sp_dropper_copy), tbl);
2677 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2678 AUX_BETWEEN_BUTTON_GROUPS);
2679 } */
2682 /* Copy to Clipboard as HEX */
2683 /* {
2684 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2685 GtkWidget *b = gtk_button_new_with_label(_("Copy as HEX"));
2686 gtk_tooltips_set_tip(tt, b, _("Copy last saved color as "
2687 "hexidecimal RGB without alpha "
2688 "to clipboard"), NULL);
2689 gtk_widget_show(b);
2690 gtk_container_add(GTK_CONTAINER(hb), b);
2691 gtk_signal_connect(GTK_OBJECT(b), "clicked",
2692 GTK_SIGNAL_FUNC(sp_dropper_copy_as_hex), tbl);
2693 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2694 AUX_BETWEEN_BUTTON_GROUPS);
2695 } */
2697 // aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2699 {
2700 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2702 GtkWidget *button =
2703 sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
2704 SP_BUTTON_TYPE_TOGGLE,
2705 NULL,
2706 "pick_color",
2707 _("When pressed, picks visible color "
2708 "without alpha and when not pressed, "
2709 "picks color including its "
2710 "alpha"),
2711 tt);
2713 gtk_widget_show(button);
2714 gtk_container_add (GTK_CONTAINER (hb), button);
2716 g_signal_connect_after (G_OBJECT (button), "clicked",
2717 G_CALLBACK (toggle_dropper_color_pick), NULL);
2718 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
2719 !prefs_get_int_attribute ("tools.dropper",
2720 "pick", 0));
2721 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2722 AUX_BETWEEN_BUTTON_GROUPS);
2723 }
2725 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2728 // where new gtkmm stuff should go
2730 gtk_widget_show_all(tbl);
2731 sp_set_font_size_smaller (tbl);
2733 /*
2734 sigc::connection *connection = new sigc::connection(
2735 desktop->connectSetStyle(
2736 sigc::bind(sigc::ptr_fun(sp_style_changed),
2737 desktop)) );
2739 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection),
2740 connection); */
2742 return tbl;
2743 }
2746 //########################
2747 //## Text Toolbox ##
2748 //########################
2749 /*
2750 static void
2751 sp_text_letter_changed(GtkAdjustment *adj, GtkWidget *tbl)
2752 {
2753 //Call back for letter sizing spinbutton
2754 }
2756 static void
2757 sp_text_line_changed(GtkAdjustment *adj, GtkWidget *tbl)
2758 {
2759 //Call back for line height spinbutton
2760 }
2762 static void
2763 sp_text_horiz_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
2764 {
2765 //Call back for horizontal kerning spinbutton
2766 }
2768 static void
2769 sp_text_vert_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
2770 {
2771 //Call back for vertical kerning spinbutton
2772 }
2774 static void
2775 sp_text_letter_rotation_changed(GtkAdjustment *adj, GtkWidget *tbl)
2776 {
2777 //Call back for letter rotation spinbutton
2778 }*/
2779 static GtkWidget *
2780 sp_text_toolbox_new(SPDesktop *desktop)
2781 {
2782 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2783 /* GtkWidget *us = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tbl), "units");
2784 GtkTooltips *tt = gtk_tooltips_new();
2785 GtkWidget *group;
2787 //Font Family
2788 {
2789 GtkWidget *c = gtk_combo_new ();
2790 gtk_combo_set_value_in_list ((GtkCombo *) c, FALSE, FALSE);
2791 gtk_combo_set_use_arrows ((GtkCombo *) c, TRUE);
2792 gtk_combo_set_use_arrows_always ((GtkCombo *) c, TRUE);
2793 gtk_widget_set_size_request (c, 144, -1);
2794 aux_toolbox_space(tbl, 1);
2795 gtk_box_pack_start (GTK_BOX (tbl), c, FALSE, FALSE, 0);
2796 }
2798 //Font Style
2799 {
2800 GtkWidget *c = gtk_combo_new ();
2801 gtk_combo_set_value_in_list ((GtkCombo *) c, FALSE, FALSE);
2802 gtk_combo_set_use_arrows ((GtkCombo *) c, TRUE);
2803 gtk_combo_set_use_arrows_always ((GtkCombo *) c, TRUE);
2804 gtk_widget_set_size_request (c, 88, -1);
2805 aux_toolbox_space(tbl, 1);
2806 gtk_box_pack_start (GTK_BOX (tbl), c, FALSE, FALSE, 0);
2807 }
2809 //Font Size
2810 {
2811 GtkWidget *c = gtk_combo_new ();
2812 gtk_combo_set_value_in_list ((GtkCombo *) c, FALSE, FALSE);
2813 gtk_combo_set_use_arrows ((GtkCombo *) c, TRUE);
2814 gtk_combo_set_use_arrows_always ((GtkCombo *) c, TRUE);
2815 gtk_widget_set_size_request (c, 64, -1);
2816 aux_toolbox_space(tbl, 1);
2817 gtk_box_pack_start (GTK_BOX (tbl), c, FALSE, FALSE, 0);
2818 }
2820 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2821 //Bold
2822 {
2823 GtkWidget *px = gtk_image_new_from_stock(GTK_STOCK_BOLD, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2824 GtkWidget *button = gtk_toggle_button_new ();
2825 gtk_container_add (GTK_CONTAINER (button), px);
2826 gtk_widget_show(button);
2827 gtk_tooltips_set_tip (tt, button, _("Bold"), NULL);
2828 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2829 gtk_widget_set_sensitive(button, TRUE);
2830 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
2831 }
2834 //Italic
2835 {
2836 GtkWidget *px = gtk_image_new_from_stock(GTK_STOCK_ITALIC, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2837 GtkWidget *button = gtk_toggle_button_new ();
2838 gtk_container_add (GTK_CONTAINER (button), px);
2839 gtk_widget_show(button);
2840 gtk_tooltips_set_tip (tt, button, _("Italics"), NULL);
2841 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2842 gtk_widget_set_sensitive(button, TRUE);
2843 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
2844 }
2846 //Underline
2847 {
2848 GtkWidget *px = gtk_image_new_from_stock(GTK_STOCK_UNDERLINE, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2849 GtkWidget *button = gtk_toggle_button_new ();
2850 gtk_container_add (GTK_CONTAINER (button), px);
2851 gtk_widget_show(button);
2852 gtk_tooltips_set_tip (tt, button, _("Underline"), NULL);
2853 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2854 gtk_widget_set_sensitive(button, FALSE);
2855 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
2856 }
2858 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2859 // align left
2860 {
2861 GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_LEFT, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2862 GtkWidget *b = group = gtk_radio_button_new (NULL);
2863 gtk_container_add (GTK_CONTAINER (b), px);
2864 gtk_tooltips_set_tip (tt, b, _("Align lines left"), NULL);
2865 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2866 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2867 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2868 }
2870 // align center
2871 {
2872 GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_CENTER, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2873 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
2874 gtk_container_add (GTK_CONTAINER (b), px);
2875 // TRANSLATORS: `Center' here is a verb.
2876 gtk_tooltips_set_tip (tt, b, _("Center lines"), NULL);
2877 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2878 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2879 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2880 }
2882 // align right
2883 {
2884 GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_RIGHT, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2885 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
2886 gtk_container_add (GTK_CONTAINER (b), px);
2887 gtk_tooltips_set_tip (tt, b, _("Align lines right"), NULL);
2888 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2889 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2890 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2891 }
2893 // full justification
2894 {
2895 GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_FILL, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2896 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
2897 gtk_container_add (GTK_CONTAINER (b), px);
2898 gtk_tooltips_set_tip (tt, b, _("Full justification"), NULL);
2899 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2900 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2901 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2902 }
2905 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2907 // horizontal
2908 {
2909 GtkWidget *px= sp_icon_new(Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_LR);
2910 GtkWidget *b = group = gtk_radio_button_new (NULL);
2911 gtk_container_add (GTK_CONTAINER (b), px);
2912 gtk_tooltips_set_tip (tt, b, _("Horizontal text"), NULL);
2913 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2914 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2915 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2916 }
2918 // vertical
2919 {
2920 GtkWidget *px = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_TB);
2921 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
2922 gtk_container_add (GTK_CONTAINER (b), px);
2923 gtk_tooltips_set_tip (tt, b, _("Vertical text"), NULL);
2924 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2925 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2926 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2927 }
2929 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2931 // letter spacing
2932 {
2933 {
2934 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LETTER_SPACING);
2935 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2936 gtk_container_add (GTK_CONTAINER (hb), image);
2937 gtk_widget_show(image);
2938 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
2939 }
2941 {
2942 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Spacing between letters"),
2943 "tools.text", "letter_spacing", 0.0,
2944 us, tbl, FALSE, NULL,
2945 -1000.0, 1000.0, 0.1, 0.1,
2946 sp_text_letter_changed, 0.1, 1);
2947 gtk_widget_set_size_request (hb, 45, 6);
2948 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
2949 }
2950 }
2952 // line spacing
2953 {
2954 {
2955 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LINE_SPACING);
2956 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2957 gtk_container_add (GTK_CONTAINER (hb), image);
2958 gtk_widget_show(image);
2959 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
2960 }
2962 {
2963 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Spacing between lines"),
2964 "tools.text", "line_spacing", 0,
2965 us, tbl, FALSE, NULL,
2966 -1000.0, 1000.0, 0.1, 0.1,
2967 sp_text_line_changed, 0.1, 1);
2968 gtk_widget_set_size_request (hb, 45, 0);
2969 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 3);
2970 }
2971 }
2973 {
2974 // horizontal kerning/vertical kerning units menu: create
2975 GtkWidget *us = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
2976 sp_unit_selector_setsize(us, AUX_OPTION_MENU_WIDTH, AUX_OPTION_MENU_HEIGHT);
2977 sp_unit_selector_set_unit(SP_UNIT_SELECTOR(us), desktop->namedview->doc_units);
2979 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2981 // horizontal kerning
2982 {
2983 {
2984 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_HORZ_KERN);
2985 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2986 gtk_container_add (GTK_CONTAINER (hb), image);
2987 gtk_widget_show(image);
2988 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
2989 }
2991 {
2992 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Horizontal kerning"),
2993 "tools.text", "horizontal_kerning", 0,
2994 us, tbl, FALSE, NULL,
2995 -100.00, 100.00, 0.01, 0.1,
2996 sp_text_horiz_kern_changed);
2997 gtk_widget_set_size_request (hb, 45, 0);
2998 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
2999 }
3000 }
3002 // vertical kerning
3003 {
3004 {
3005 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_VERT_KERN);
3006 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3007 gtk_container_add (GTK_CONTAINER (hb), image);
3008 gtk_widget_show(image);
3009 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3010 }
3012 {
3013 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Vertical kerning"),
3014 "tools.text", "vertical_kerning", 0,
3015 us, tbl, FALSE, NULL,
3016 -100.00, 100.00, 0.01, 0.1,
3017 sp_text_vert_kern_changed);
3018 gtk_widget_set_size_request (hb, 45, 0);
3019 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 5);
3020 }
3021 }
3023 // add the units menu
3024 gtk_widget_show(us);
3025 gtk_box_pack_start(GTK_BOX(tbl), us, FALSE, FALSE, 1);
3026 gtk_object_set_data(GTK_OBJECT(tbl), "units", us);
3027 }
3029 // letter rotation
3030 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
3031 {
3032 {
3033 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_ROTATION);
3034 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3035 gtk_container_add (GTK_CONTAINER (hb), image);
3036 gtk_widget_show(image);
3037 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3038 }
3039 {
3040 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Letter rotation"),
3041 "tools.text", "letter_rotation", 0,
3042 us, tbl, FALSE, NULL,
3043 -180.0, 180.0, 0.1, 0.1,
3044 sp_text_letter_rotation_changed, 0.1, 1);
3045 gtk_widget_set_size_request (hb, 45, 0);
3046 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
3047 }
3048 // rotation degree label
3049 {
3050 GtkWidget *label = gtk_widget_new (GTK_TYPE_LABEL, "label", "\302\260", "xalign", 0.0, NULL);
3051 gtk_box_pack_start(GTK_BOX(tbl), label, FALSE, FALSE, 0);
3052 }
3053 }
3055 // Remove Manual Kerns
3056 {
3057 GtkWidget *px = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_REMOVE_KERNS);
3058 GtkWidget *button = gtk_button_new ();
3059 gtk_container_add (GTK_CONTAINER (button), px);
3060 gtk_widget_show(button);
3061 gtk_tooltips_set_tip (tt, button, _("Remove manual kerns"), NULL);
3062 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
3063 gtk_widget_set_sensitive(button, TRUE);
3064 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
3065 }
3067 */
3069 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
3070 swatch->setWatchedTool ("tools.text", true);
3071 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
3072 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
3074 gtk_widget_show_all(tbl);
3075 sp_set_font_size_smaller (tbl);
3077 return tbl;
3079 } // end of sp_text_toolbox_new()
3082 //#########################
3083 //## Connector Toolbox ##
3084 //#########################
3086 static void sp_connector_path_set_avoid(void)
3087 {
3088 cc_selection_set_avoid(true);
3089 }
3092 static void sp_connector_path_set_ignore(void)
3093 {
3094 cc_selection_set_avoid(false);
3095 }
3098 static void connector_spacing_changed(GtkAdjustment *adj, GtkWidget *tbl)
3099 {
3100 // quit if run by the _changed callbacks
3101 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
3102 return;
3103 }
3105 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl),
3106 "desktop");
3107 SPDocument *doc = sp_desktop_document(desktop);
3109 if (!sp_document_get_undo_sensitive(doc))
3110 {
3111 return;
3112 }
3114 // in turn, prevent callbacks from responding
3115 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
3117 Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
3119 sp_repr_set_css_double(repr, "inkscape:connector-spacing", adj->value);
3120 SP_OBJECT(desktop->namedview)->updateRepr();
3122 GSList *items = get_avoided_items(NULL, desktop->currentRoot(), desktop);
3123 for ( GSList const *iter = items ; iter != NULL ; iter = iter->next ) {
3124 SPItem *item = reinterpret_cast<SPItem *>(iter->data);
3125 NR::Matrix m = NR::identity();
3126 avoid_item_move(&m, item);
3127 }
3129 if (items) {
3130 g_slist_free(items);
3131 }
3133 sp_document_done(doc);
3135 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
3137 spinbutton_defocus(GTK_OBJECT(tbl));
3138 }
3141 static void connector_tb_event_attr_changed(Inkscape::XML::Node *repr,
3142 gchar const *name, gchar const *old_value, gchar const *new_value,
3143 bool is_interactive, gpointer data)
3144 {
3145 GtkWidget *tbl = GTK_WIDGET(data);
3147 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
3148 return;
3149 }
3150 if (strcmp(name, "inkscape:connector-spacing") != 0) {
3151 return;
3152 }
3154 GtkAdjustment *adj = (GtkAdjustment*)
3155 gtk_object_get_data(GTK_OBJECT(tbl), "spacing");
3156 gdouble spacing = defaultConnSpacing;
3157 sp_repr_get_double(repr, "inkscape:connector-spacing", &spacing);
3159 gtk_adjustment_set_value(adj, spacing);
3160 }
3163 static Inkscape::XML::NodeEventVector connector_tb_repr_events = {
3164 NULL, /* child_added */
3165 NULL, /* child_removed */
3166 connector_tb_event_attr_changed,
3167 NULL, /* content_changed */
3168 NULL /* order_changed */
3169 };
3172 static GtkWidget *
3173 sp_connector_toolbox_new(SPDesktop *desktop)
3174 {
3175 GtkTooltips *tt = gtk_tooltips_new();
3176 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
3178 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
3179 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
3181 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
3182 AUX_BETWEEN_BUTTON_GROUPS);
3184 sp_toolbox_button_new(tbl, Inkscape::ICON_SIZE_SMALL_TOOLBAR,
3185 "connector_avoid", GTK_SIGNAL_FUNC(sp_connector_path_set_avoid),
3186 tt, _("Make connectors avoid selected objects"));
3188 sp_toolbox_button_new(tbl, Inkscape::ICON_SIZE_SMALL_TOOLBAR,
3189 "connector_ignore", GTK_SIGNAL_FUNC(sp_connector_path_set_ignore),
3190 tt, _("Make connectors ignore selected objects"));
3192 // interval
3193 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
3194 AUX_BETWEEN_BUTTON_GROUPS);
3196 // Spacing spinbox
3197 {
3198 GtkWidget *object_spacing = sp_tb_spinbutton(_("Spacing:"),
3199 _("The amount of space left around objects by auto-routing connectors"),
3200 "tools.connector", "spacing", 10, NULL, tbl, TRUE,
3201 "inkscape:connector-spacing", 0, 100, 1.0, 10.0,
3202 connector_spacing_changed, 1, 0);
3204 gtk_box_pack_start(GTK_BOX(tbl), object_spacing, FALSE, FALSE,
3205 AUX_SPACING);
3206 }
3208 gtk_widget_show_all(tbl);
3209 sp_set_font_size_smaller (tbl);
3211 // Code to watch for changes to the connector-spacing attribute in
3212 // the XML.
3213 Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
3214 g_assert(repr != NULL);
3216 Inkscape::XML::Node *oldrepr = (Inkscape::XML::Node *)
3217 gtk_object_get_data(GTK_OBJECT(tbl), "repr");
3219 if (oldrepr) { // remove old listener
3220 sp_repr_remove_listener_by_data(oldrepr, tbl);
3221 Inkscape::GC::release(oldrepr);
3222 oldrepr = NULL;
3223 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
3224 }
3226 if (repr) {
3227 g_object_set_data(G_OBJECT(tbl), "repr", repr);
3228 Inkscape::GC::anchor(repr);
3229 sp_repr_add_listener(repr, &connector_tb_repr_events, tbl);
3230 sp_repr_synthesize_events(repr, &connector_tb_repr_events, tbl);
3231 }
3233 return tbl;
3235 } // end of sp_connector_toolbox_new()
3238 /*
3239 Local Variables:
3240 mode:c++
3241 c-file-style:"stroustrup"
3242 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
3243 indent-tabs-mode:nil
3244 fill-column:99
3245 End:
3246 */
3247 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :