44893b49b6c79a7e58693e7429d689a6b2f60c99
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 }
381 //################################
382 //## Node Editing Toolbox ##
383 //################################
385 static GtkWidget *
386 sp_node_toolbox_new(SPDesktop *desktop)
387 {
388 Inkscape::UI::View::View *view = desktop;
390 GtkTooltips *tt = gtk_tooltips_new();
391 GtkWidget *tb = gtk_hbox_new(FALSE, 0);
393 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
395 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_insert",
396 GTK_SIGNAL_FUNC(sp_node_path_edit_add), tt, _("Insert new nodes into selected segments"));
397 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_delete",
398 GTK_SIGNAL_FUNC(sp_node_path_edit_delete), tt, _("Delete selected nodes"));
400 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
402 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_join",
403 GTK_SIGNAL_FUNC(sp_node_path_edit_join), tt, _("Join selected endnodes"));
404 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_join_segment",
405 GTK_SIGNAL_FUNC(sp_node_path_edit_join_segment), tt, _("Join selected endnodes with a new segment"));
407 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_delete_segment",
408 GTK_SIGNAL_FUNC(sp_node_path_edit_delete_segment), tt, _("Split path between two non-endpoint nodes"));
410 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_break",
411 GTK_SIGNAL_FUNC(sp_node_path_edit_break), tt, _("Break path at selected nodes"));
413 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
415 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_cusp",
416 GTK_SIGNAL_FUNC(sp_node_path_edit_cusp), tt, _("Make selected nodes corner"));
418 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_smooth",
419 GTK_SIGNAL_FUNC(sp_node_path_edit_smooth), tt, _("Make selected nodes smooth"));
421 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_symmetric",
422 GTK_SIGNAL_FUNC(sp_node_path_edit_symmetrical), tt, _("Make selected nodes symmetric"));
424 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
426 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_line",
427 GTK_SIGNAL_FUNC(sp_node_path_edit_toline), tt, _("Make selected segments lines"));
429 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_curve",
430 GTK_SIGNAL_FUNC(sp_node_path_edit_tocurve), tt, _("Make selected segments curves"));
432 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
434 sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_OBJECT_TO_CURVE), view, tt);
436 sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_SELECTION_OUTLINE), view, tt);
438 gtk_widget_show_all(tb);
440 return tb;
442 } // end of sp_node_toolbox_new()
445 //########################
446 //## Zoom Toolbox ##
447 //########################
449 static GtkWidget *
450 sp_zoom_toolbox_new(SPDesktop *desktop)
451 {
452 Inkscape::UI::View::View *view=desktop;
454 GtkTooltips *tt = gtk_tooltips_new();
455 GtkWidget *tb = gtk_hbox_new(FALSE, 0);
457 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0),
458 FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
460 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);
462 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);
464 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
466 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);
468 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);
470 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);
472 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);
474 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
476 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);
478 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);
480 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
482 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);
484 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);
486 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);
488 gtk_widget_show_all(tb);
490 return tb;
492 } // end of sp_zoom_toolbox_new()
494 void
495 sp_tool_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
496 {
497 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")));
498 }
501 void
502 sp_aux_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
503 {
504 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")));
505 }
507 void
508 sp_commands_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
509 {
510 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")));
511 }
514 static void
515 toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop, SetupFunction setup_func, UpdateFunction update_func, sigc::connection *conn)
516 {
517 gpointer ptr = g_object_get_data(G_OBJECT(toolbox), "desktop");
518 SPDesktop *old_desktop = static_cast<SPDesktop*>(ptr);
520 if (old_desktop) {
521 GList *children, *iter;
523 children = gtk_container_get_children(GTK_CONTAINER(toolbox));
524 for ( iter = children ; iter ; iter = iter->next ) {
525 gtk_container_remove( GTK_CONTAINER(toolbox), GTK_WIDGET(iter->data) );
526 }
527 g_list_free(children);
528 }
530 g_object_set_data(G_OBJECT(toolbox), "desktop", (gpointer)desktop);
532 if (desktop) {
533 gtk_widget_set_sensitive(toolbox, TRUE);
534 setup_func(toolbox, desktop);
535 update_func(desktop, desktop->event_context, toolbox);
536 *conn = desktop->connectEventContextChanged
537 (sigc::bind (sigc::ptr_fun(update_func), toolbox));
538 } else {
539 gtk_widget_set_sensitive(toolbox, FALSE);
540 }
542 } // end of toolbox_set_desktop()
545 static void
546 setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
547 {
548 GtkTooltips *tooltips=GTK_TOOLTIPS(g_object_get_data(G_OBJECT(toolbox), "tooltips"));
549 gint shrinkLeft = prefs_get_int_attribute_limited( "toolbox.left", "small", 0, 0, 1 );
550 Inkscape::IconSize toolboxSize = shrinkLeft ? Inkscape::ICON_SIZE_SMALL_TOOLBAR : Inkscape::ICON_SIZE_LARGE_TOOLBAR;
552 for (int i = 0 ; tools[i].type_name ; i++ ) {
553 GtkWidget *button =
554 sp_toolbox_button_new_from_verb_with_doubleclick( toolbox, toolboxSize,
555 SP_BUTTON_TYPE_TOGGLE,
556 Inkscape::Verb::get(tools[i].verb),
557 Inkscape::Verb::get(tools[i].doubleclick_verb),
558 desktop,
559 tooltips );
561 g_object_set_data( G_OBJECT(toolbox), tools[i].data_name,
562 (gpointer)button );
563 }
564 }
567 static void
568 update_tool_toolbox( SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox )
569 {
570 gchar const *const tname = ( eventcontext
571 ? gtk_type_name(GTK_OBJECT_TYPE(eventcontext))
572 : NULL );
573 for (int i = 0 ; tools[i].type_name ; i++ ) {
574 SPButton *button = SP_BUTTON(g_object_get_data(G_OBJECT(toolbox), tools[i].data_name));
575 sp_button_toggle_set_down(button, tname && !strcmp(tname, tools[i].type_name));
576 }
577 }
579 static void
580 setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
581 {
582 GtkSizeGroup* grouper = gtk_size_group_new( GTK_SIZE_GROUP_BOTH );
584 for (int i = 0 ; aux_toolboxes[i].type_name ; i++ ) {
585 GtkWidget *sub_toolbox;
586 if (aux_toolboxes[i].create_func == NULL)
587 sub_toolbox = sp_empty_toolbox_new(desktop);
588 else
589 sub_toolbox = aux_toolboxes[i].create_func(desktop);
591 gtk_size_group_add_widget( grouper, sub_toolbox );
593 gtk_container_add(GTK_CONTAINER(toolbox), sub_toolbox);
594 g_object_set_data(G_OBJECT(toolbox), aux_toolboxes[i].data_name, sub_toolbox);
595 }
596 g_object_unref( G_OBJECT(grouper) );
597 }
599 static void
600 update_aux_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox)
601 {
602 gchar const *tname = ( eventcontext
603 ? gtk_type_name(GTK_OBJECT_TYPE(eventcontext))
604 : NULL );
605 for (int i = 0 ; aux_toolboxes[i].type_name ; i++ ) {
606 GtkWidget *sub_toolbox = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), aux_toolboxes[i].data_name));
607 if (tname && !strcmp(tname, aux_toolboxes[i].type_name)) {
608 gtk_widget_show_all(sub_toolbox);
609 g_object_set_data(G_OBJECT(toolbox), "shows", sub_toolbox);
610 } else {
611 gtk_widget_hide(sub_toolbox);
612 }
613 }
614 }
616 static void
617 setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
618 {
619 Inkscape::UI::View::View *view = desktop;
621 GtkTooltips *tt = gtk_tooltips_new();
622 GtkWidget *tb = gtk_hbox_new(FALSE, 0);
624 gint shrinkTop = prefs_get_int_attribute_limited( "toolbox", "small", 1, 0, 1 );
625 Inkscape::IconSize toolboxSize = shrinkTop ? Inkscape::ICON_SIZE_SMALL_TOOLBAR : Inkscape::ICON_SIZE_LARGE_TOOLBAR;
627 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_NEW), view, tt);
628 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_OPEN), view, tt);
629 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_SAVE), view, tt);
630 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_PRINT), view, tt);
632 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
634 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_IMPORT), view, tt);
635 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_EXPORT), view, tt);
637 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
639 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_UNDO), view, tt);
640 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_REDO), view, tt);
642 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
644 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_COPY), view, tt);
645 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_CUT), view, tt);
646 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_PASTE), view, tt);
648 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
650 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_SELECTION), view, tt);
651 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_DRAWING), view, tt);
652 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_PAGE), view, tt);
654 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
656 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_DUPLICATE), view, tt);
657 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_CLONE), view, tt);
658 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_UNLINK_CLONE), view, tt);
660 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
662 sp_toolbox_button_normal_new_from_verb(tb, toolboxSize, Inkscape::Verb::get(SP_VERB_SELECTION_GROUP), view, tt);
663 sp_toolbox_button_normal_new_from_verb(tb, toolboxSize, Inkscape::Verb::get(SP_VERB_SELECTION_UNGROUP), view, tt);
665 // disabled until we have icons for them:
667 //find
669 //sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_TILE), view, tt);
670 //sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_UNTILE), 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_DIALOG_FILL_STROKE), view, tt);
675 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_TEXT), view, tt);
676 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_XML_EDITOR), view, tt);
677 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_ALIGN_DISTRIBUTE), view, tt);
679 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
681 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_DISPLAY), view, tt);
682 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_NAMEDVIEW), view, tt);
684 gtk_widget_show_all(tb);
686 gtk_container_add(GTK_CONTAINER(toolbox), tb);
687 }
689 static void
690 update_commands_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox)
691 {
692 }
694 void show_aux_toolbox(GtkWidget *toolbox_toplevel)
695 {
696 gtk_widget_show(toolbox_toplevel);
697 GtkWidget *toolbox = gtk_bin_get_child(GTK_BIN(toolbox_toplevel));
699 GtkWidget *shown_toolbox = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), "shows"));
700 if (!shown_toolbox) {
701 return;
702 }
703 gtk_widget_show(toolbox);
705 // need to show the spacer, or the padding will be off
706 GtkWidget *spacer = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), "top_spacer"));
707 gtk_widget_show(spacer);
709 gtk_widget_show_all(shown_toolbox);
710 }
712 void
713 aux_toolbox_space(GtkWidget *tb, gint space)
714 {
715 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, space);
716 }
718 static GtkWidget *
719 sp_empty_toolbox_new(SPDesktop *desktop)
720 {
721 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
722 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
723 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
725 gtk_widget_show_all(tbl);
726 sp_set_font_size_smaller (tbl);
728 return tbl;
729 }
731 // helper UI functions
733 GtkWidget *
734 sp_tb_spinbutton(
735 gchar *label, gchar const *tooltip,
736 gchar const *path, gchar const *data, gdouble def,
737 GtkWidget *us,
738 GtkWidget *tbl,
739 gboolean altx, gchar const *altx_mark,
740 gdouble lower, gdouble upper, gdouble step, gdouble page,
741 void (*callback)(GtkAdjustment *, GtkWidget *),
742 gdouble climb = 0.1, guint digits = 3, double factor = 1.0)
743 {
744 GtkTooltips *tt = gtk_tooltips_new();
746 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
748 GtkWidget *l = gtk_label_new(label);
749 gtk_widget_show(l);
750 gtk_misc_set_alignment(GTK_MISC(l), 1.0, 0.5);
751 gtk_container_add(GTK_CONTAINER(hb), l);
753 GtkObject *a = gtk_adjustment_new(prefs_get_double_attribute(path, data, def) * factor,
754 lower, upper, step, page, page);
755 gtk_object_set_data(GTK_OBJECT(tbl), data, a);
756 if (us)
757 sp_unit_selector_add_adjustment(SP_UNIT_SELECTOR(us), GTK_ADJUSTMENT(a));
759 GtkWidget *sb = gtk_spin_button_new(GTK_ADJUSTMENT(a), climb, digits);
760 gtk_tooltips_set_tip(tt, sb, tooltip, NULL);
761 if (altx)
762 gtk_object_set_data(GTK_OBJECT(sb), altx_mark, sb);
763 gtk_widget_set_size_request(sb,
764 (upper <= 1.0 || digits == 0)? AUX_SPINBUTTON_WIDTH_SMALL - 10: AUX_SPINBUTTON_WIDTH_SMALL,
765 AUX_SPINBUTTON_HEIGHT);
766 gtk_widget_show(sb);
767 gtk_signal_connect(GTK_OBJECT(sb), "focus-in-event", GTK_SIGNAL_FUNC(spinbutton_focus_in), tbl);
768 gtk_signal_connect(GTK_OBJECT(sb), "key-press-event", GTK_SIGNAL_FUNC(spinbutton_keypress), tbl);
769 gtk_container_add(GTK_CONTAINER(hb), sb);
770 gtk_signal_connect(GTK_OBJECT(a), "value_changed", GTK_SIGNAL_FUNC(callback), tbl);
772 return hb;
773 }
775 #define MODE_LABEL_WIDTH 70
777 //########################
778 //## Star ##
779 //########################
781 static void
782 sp_stb_magnitude_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
783 {
784 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
786 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
787 // do not remember prefs if this call is initiated by an undo change, because undoing object
788 // creation sets bogus values to its attributes before it is deleted
789 prefs_set_int_attribute("tools.shapes.star", "magnitude", (gint)adj->value);
790 }
792 // quit if run by the attr_changed listener
793 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
794 return;
795 }
797 // in turn, prevent listener from responding
798 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
800 bool modmade = false;
802 Inkscape::Selection *selection = sp_desktop_selection(desktop);
803 GSList const *items = selection->itemList();
804 for (; items != NULL; items = items->next) {
805 if (SP_IS_STAR((SPItem *) items->data)) {
806 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
807 sp_repr_set_int(repr,"sodipodi:sides",(gint)adj->value);
808 sp_repr_set_svg_double(repr, "sodipodi:arg2",
809 (sp_repr_get_double_attribute(repr, "sodipodi:arg1", 0.5)
810 + M_PI / (gint)adj->value));
811 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
812 modmade = true;
813 }
814 }
815 if (modmade) sp_document_done(sp_desktop_document(desktop));
817 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
819 spinbutton_defocus(GTK_OBJECT(tbl));
820 }
822 static void
823 sp_stb_proportion_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
824 {
825 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
827 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
828 prefs_set_double_attribute("tools.shapes.star", "proportion", adj->value);
829 }
831 // quit if run by the attr_changed listener
832 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
833 return;
834 }
836 // in turn, prevent listener from responding
837 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
839 bool modmade = false;
840 Inkscape::Selection *selection = sp_desktop_selection(desktop);
841 GSList const *items = selection->itemList();
842 for (; items != NULL; items = items->next) {
843 if (SP_IS_STAR((SPItem *) items->data)) {
844 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
846 gdouble r1 = sp_repr_get_double_attribute(repr, "sodipodi:r1", 1.0);
847 gdouble r2 = sp_repr_get_double_attribute(repr, "sodipodi:r2", 1.0);
848 if (r2 < r1) {
849 sp_repr_set_svg_double(repr, "sodipodi:r2", r1*adj->value);
850 } else {
851 sp_repr_set_svg_double(repr, "sodipodi:r1", r2*adj->value);
852 }
854 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
855 modmade = true;
856 }
857 }
859 if (modmade) sp_document_done(sp_desktop_document(desktop));
861 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
863 spinbutton_defocus(GTK_OBJECT(tbl));
864 }
866 static void
867 sp_stb_sides_flat_state_changed(GtkWidget *widget, GtkObject *tbl)
868 {
869 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
871 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
872 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
873 prefs_set_string_attribute("tools.shapes.star", "isflatsided", "true");
874 } else {
875 prefs_set_string_attribute("tools.shapes.star", "isflatsided", "false");
876 }
877 }
879 // quit if run by the attr_changed listener
880 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
881 return;
882 }
884 // in turn, prevent listener from responding
885 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
887 Inkscape::Selection *selection = sp_desktop_selection(desktop);
888 GSList const *items = selection->itemList();
889 GtkWidget *prop_widget = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "prop_widget");
890 bool modmade = false;
891 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
892 gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), FALSE);
893 for (; items != NULL; items = items->next) {
894 if (SP_IS_STAR((SPItem *) items->data)) {
895 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
896 repr->setAttribute("inkscape:flatsided", "true");
897 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
898 modmade = true;
899 }
900 }
901 } else {
902 gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), TRUE);
903 for (; items != NULL; items = items->next) {
904 if (SP_IS_STAR((SPItem *) items->data)) {
905 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
906 repr->setAttribute("inkscape:flatsided", "false");
907 SP_OBJECT(items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
908 modmade = true;
909 }
910 }
911 }
912 if (modmade) sp_document_done(sp_desktop_document(desktop));
914 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
916 spinbutton_defocus(GTK_OBJECT(tbl));
917 }
919 static void
920 sp_stb_rounded_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
921 {
922 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
924 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
925 prefs_set_double_attribute("tools.shapes.star", "rounded", (gdouble) adj->value);
926 }
928 // quit if run by the attr_changed listener
929 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
930 return;
931 }
933 // in turn, prevent listener from responding
934 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
936 bool modmade = false;
938 Inkscape::Selection *selection = sp_desktop_selection(desktop);
939 GSList const *items = selection->itemList();
940 for (; items != NULL; items = items->next) {
941 if (SP_IS_STAR((SPItem *) items->data)) {
942 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
943 sp_repr_set_svg_double(repr, "inkscape:rounded", (gdouble) adj->value);
944 SP_OBJECT(items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
945 modmade = true;
946 }
947 }
948 if (modmade) sp_document_done(sp_desktop_document(desktop));
950 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
952 spinbutton_defocus(GTK_OBJECT(tbl));
953 }
956 static void
957 sp_stb_randomized_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
958 {
959 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
961 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
962 prefs_set_double_attribute("tools.shapes.star", "randomized", (gdouble) adj->value);
963 }
965 // quit if run by the attr_changed listener
966 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
967 return;
968 }
970 // in turn, prevent listener from responding
971 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
973 bool modmade = false;
975 Inkscape::Selection *selection = sp_desktop_selection(desktop);
976 GSList const *items = selection->itemList();
977 for (; items != NULL; items = items->next) {
978 if (SP_IS_STAR((SPItem *) items->data)) {
979 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
980 sp_repr_set_svg_double(repr, "inkscape:randomized", (gdouble) adj->value);
981 SP_OBJECT(items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
982 modmade = true;
983 }
984 }
985 if (modmade) sp_document_done(sp_desktop_document(desktop));
987 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
989 spinbutton_defocus(GTK_OBJECT(tbl));
990 }
993 static void star_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
994 gchar const *old_value, gchar const *new_value,
995 bool is_interactive, gpointer data)
996 {
997 GtkWidget *tbl = GTK_WIDGET(data);
999 // quit if run by the _changed callbacks
1000 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1001 return;
1002 }
1004 // in turn, prevent callbacks from responding
1005 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1007 GtkAdjustment *adj;
1009 if (!strcmp(name, "inkscape:randomized")) {
1010 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "randomized");
1011 gtk_adjustment_set_value(adj, sp_repr_get_double_attribute(repr, "inkscape:randomized", 0.0));
1012 } else if (!strcmp(name, "inkscape:rounded")) {
1013 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rounded");
1014 gtk_adjustment_set_value(adj, sp_repr_get_double_attribute(repr, "inkscape:rounded", 0.0));
1015 } else if (!strcmp(name, "inkscape:flatsided")) {
1016 GtkWidget *fscb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "flat_checkbox");
1017 GtkWidget *prop_widget = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "prop_widget");
1018 char const *flatsides = repr->attribute("inkscape:flatsided");
1019 if (flatsides && !strcmp(flatsides,"false" )) {
1020 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), FALSE);
1021 gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), TRUE);
1022 } else {
1023 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), TRUE);
1024 gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), FALSE);
1025 }
1026 } else if (!strcmp(name, "sodipodi:r1") || !strcmp(name, "sodipodi:r2")) {
1027 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "proportion");
1028 gdouble r1 = sp_repr_get_double_attribute(repr, "sodipodi:r1", 1.0);
1029 gdouble r2 = sp_repr_get_double_attribute(repr, "sodipodi:r2", 1.0);
1030 if (r2 < r1) {
1031 gtk_adjustment_set_value(adj, r2/r1);
1032 } else {
1033 gtk_adjustment_set_value(adj, r1/r2);
1034 }
1035 } else if (!strcmp(name, "sodipodi:sides")) {
1036 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "magnitude");
1037 gtk_adjustment_set_value(adj, sp_repr_get_int_attribute(repr, "sodipodi:sides", 0));
1038 }
1040 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1041 }
1044 static Inkscape::XML::NodeEventVector star_tb_repr_events =
1045 {
1046 NULL, /* child_added */
1047 NULL, /* child_removed */
1048 star_tb_event_attr_changed,
1049 NULL, /* content_changed */
1050 NULL /* order_changed */
1051 };
1054 /**
1055 * \param selection Should not be NULL.
1056 */
1057 static void
1058 sp_star_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1059 {
1060 int n_selected = 0;
1061 Inkscape::XML::Node *repr = NULL;
1062 Inkscape::XML::Node *oldrepr = NULL;
1064 for (GSList const *items = selection->itemList();
1065 items != NULL;
1066 items = items->next)
1067 {
1068 if (SP_IS_STAR((SPItem *) items->data)) {
1069 n_selected++;
1070 repr = SP_OBJECT_REPR((SPItem *) items->data);
1071 }
1072 }
1074 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
1076 if (n_selected == 0) {
1077 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
1078 } else if (n_selected == 1) {
1079 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1081 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1082 if (oldrepr) { // remove old listener
1083 sp_repr_remove_listener_by_data(oldrepr, tbl);
1084 Inkscape::GC::release(oldrepr);
1085 oldrepr = 0;
1086 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1087 }
1089 if (repr) {
1090 g_object_set_data(G_OBJECT(tbl), "repr", repr);
1091 Inkscape::GC::anchor(repr);
1092 sp_repr_add_listener(repr, &star_tb_repr_events, tbl);
1093 sp_repr_synthesize_events(repr, &star_tb_repr_events, tbl);
1094 }
1095 } else {
1096 // FIXME: implement averaging of all parameters for multiple selected stars
1097 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1098 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1099 }
1100 }
1103 static void
1104 sp_stb_defaults(GtkWidget *widget, GtkWidget *tbl)
1105 {
1106 // FIXME: in this and all other _default functions, set some flag telling the value_changed
1107 // callbacks to lump all the changes for all selected objects in one undo step
1109 GtkAdjustment *adj;
1111 // fixme: make settable in prefs!
1112 gint mag = 5;
1113 gdouble prop = 0.5;
1114 gboolean flat = FALSE;
1115 gdouble randomized = 0;
1116 gdouble rounded = 0;
1118 GtkWidget *fscb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "flat_checkbox");
1119 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), flat);
1120 GtkWidget *sb2 = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "prop_widget");
1121 gtk_widget_set_sensitive(GTK_WIDGET(sb2), !flat);
1123 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "magnitude");
1124 gtk_adjustment_set_value(adj, mag);
1125 gtk_adjustment_value_changed(adj);
1127 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "proportion");
1128 gtk_adjustment_set_value(adj, prop);
1129 gtk_adjustment_value_changed(adj);
1131 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rounded");
1132 gtk_adjustment_set_value(adj, rounded);
1133 gtk_adjustment_value_changed(adj);
1135 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "randomized");
1136 gtk_adjustment_set_value(adj, randomized);
1137 gtk_adjustment_value_changed(adj);
1139 spinbutton_defocus(GTK_OBJECT(tbl));
1140 }
1143 void
1144 sp_toolbox_add_label(GtkWidget *tbl, gchar const *title, bool wide)
1145 {
1146 GtkWidget *boxl = gtk_hbox_new(FALSE, 0);
1147 if (wide) gtk_widget_set_size_request(boxl, MODE_LABEL_WIDTH, -1);
1148 GtkWidget *l = gtk_label_new(NULL);
1149 gtk_label_set_markup(GTK_LABEL(l), title);
1150 gtk_box_pack_end(GTK_BOX(boxl), l, FALSE, FALSE, 0);
1151 gtk_box_pack_start(GTK_BOX(tbl), boxl, FALSE, FALSE, 0);
1152 gtk_object_set_data(GTK_OBJECT(tbl), "mode_label", l);
1153 }
1156 static GtkWidget *
1157 sp_star_toolbox_new(SPDesktop *desktop)
1158 {
1159 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1161 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1162 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1164 GtkTooltips *tt = gtk_tooltips_new();
1166 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1168 gchar const *flatsidedstr = NULL;
1170 /* Flatsided checkbox */
1171 {
1172 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1173 GtkWidget *fscb = gtk_check_button_new_with_label(_("Polygon"));
1174 gtk_widget_set_sensitive(GTK_WIDGET(fscb), TRUE);
1175 flatsidedstr = prefs_get_string_attribute("tools.shapes.star", "isflatsided");
1176 if (!flatsidedstr || (flatsidedstr && !strcmp(flatsidedstr, "false")))
1177 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), FALSE);
1178 else
1179 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), TRUE);
1180 gtk_tooltips_set_tip(tt, fscb, _("Regular polygon (with one handle) instead of a star"), NULL);
1181 gtk_widget_show(fscb);
1182 gtk_object_set_data(GTK_OBJECT(tbl), "flat_checkbox", fscb);
1183 gtk_container_add(GTK_CONTAINER(hb), fscb);
1184 g_signal_connect(G_OBJECT(fscb), "toggled", GTK_SIGNAL_FUNC(sp_stb_sides_flat_state_changed ), tbl);
1185 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_SPACING);
1186 }
1188 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
1190 /* Magnitude */
1191 {
1192 GtkWidget *hb = sp_tb_spinbutton(_("Corners:"), _("Number of corners of a polygon or star"),
1193 "tools.shapes.star", "magnitude", 3,
1194 NULL, tbl, TRUE, "altx-star",
1195 3, 1024, 1, 1,
1196 sp_stb_magnitude_value_changed, 1, 0);
1197 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1198 }
1200 /* Spoke ratio */
1201 {
1202 GtkWidget *hb = sp_tb_spinbutton(_("Spoke ratio:"),
1203 // TRANSLATORS: Tip radius of a star is the distance from the center to the farthest handle.
1204 // Base radius is the same for the closest handle.
1205 _("Base radius to tip radius ratio"),
1206 "tools.shapes.star", "proportion", 0.5,
1207 NULL, tbl, FALSE, NULL,
1208 0.01, 1.0, 0.01, 0.1,
1209 sp_stb_proportion_value_changed);
1210 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1211 g_object_set_data(G_OBJECT(tbl), "prop_widget", hb);
1212 if (!flatsidedstr || (flatsidedstr && !strcmp(flatsidedstr, "false")))
1213 gtk_widget_set_sensitive(GTK_WIDGET(hb), TRUE);
1214 else
1215 gtk_widget_set_sensitive(GTK_WIDGET(hb), FALSE);
1216 }
1218 /* Roundedness */
1219 {
1220 GtkWidget *hb = sp_tb_spinbutton(_("Rounded:"), _("How much rounded are the corners (0 for sharp)"),
1221 "tools.shapes.star", "rounded", 0.0,
1222 NULL, tbl, FALSE, NULL,
1223 -100.0, 100.0, 0.01, 0.1,
1224 sp_stb_rounded_value_changed);
1225 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1226 }
1228 /* Randomization */
1229 {
1230 GtkWidget *hb = sp_tb_spinbutton(_("Randomized:"), _("Scatter randomly the corners and angles"),
1231 "tools.shapes.star", "randomized", 0.0,
1232 NULL, tbl, FALSE, NULL,
1233 -10.0, 10.0, 0.001, 0.01,
1234 sp_stb_randomized_value_changed, 0.1, 3);
1235 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1236 }
1238 aux_toolbox_space(tbl, AUX_SPACING);
1240 /* Reset */
1241 {
1242 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1243 GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
1244 gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
1245 gtk_widget_show(b);
1246 gtk_container_add(GTK_CONTAINER(hb), b);
1247 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_stb_defaults), tbl);
1248 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_SPACING);
1249 }
1251 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1252 swatch->setWatchedTool ("tools.shapes.star", true);
1253 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1254 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1256 gtk_widget_show_all(tbl);
1257 sp_set_font_size_smaller (tbl);
1259 sigc::connection *connection = new sigc::connection(
1260 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_star_toolbox_selection_changed), (GtkObject *)tbl))
1261 );
1262 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1264 return tbl;
1265 }
1268 //########################
1269 //## Rect ##
1270 //########################
1272 static void
1273 sp_rtb_sensitivize (GtkWidget *tbl)
1274 {
1275 GtkAdjustment *adj1 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "rx"));
1276 GtkAdjustment *adj2 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "ry"));
1277 GtkWidget *not_rounded = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "not_rounded");
1279 if (adj1->value == 0 && adj2->value == 0 && gtk_object_get_data(GTK_OBJECT(tbl), "single")) { // only for a single selected rect (for now)
1280 gtk_widget_set_sensitive(GTK_WIDGET(not_rounded), FALSE);
1281 } else {
1282 gtk_widget_set_sensitive(GTK_WIDGET(not_rounded), TRUE);
1283 }
1284 }
1287 static void
1288 sp_rtb_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name,
1289 void (*setter)(SPRect *, gdouble))
1290 {
1291 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
1293 GtkWidget *us = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tbl), "units");
1294 SPUnit const *unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(us));
1296 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1297 prefs_set_double_attribute("tools.shapes.rect", value_name, sp_units_get_pixels(adj->value, *unit));
1298 }
1300 // quit if run by the attr_changed listener
1301 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1302 return;
1303 }
1305 // in turn, prevent listener from responding
1306 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1308 bool modmade = false;
1309 Inkscape::Selection *selection = sp_desktop_selection(desktop);
1310 for (GSList const *items = selection->itemList(); items != NULL; items = items->next) {
1311 if (SP_IS_RECT(items->data)) {
1312 if (adj->value != 0) {
1313 setter(SP_RECT(items->data), sp_units_get_pixels(adj->value, *unit));
1314 } else {
1315 SP_OBJECT_REPR(items->data)->setAttribute(value_name, NULL);
1316 }
1317 modmade = true;
1318 }
1319 }
1321 sp_rtb_sensitivize (tbl);
1323 if (modmade) {
1324 sp_document_done(sp_desktop_document(desktop));
1325 }
1327 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1329 // defocus spinbuttons by moving focus to the canvas, unless "stay" is on
1330 spinbutton_defocus(GTK_OBJECT(tbl));
1331 }
1333 static void
1334 sp_rtb_rx_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1335 {
1336 sp_rtb_value_changed(adj, tbl, "rx", sp_rect_set_visible_rx);
1337 }
1339 static void
1340 sp_rtb_ry_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1341 {
1342 sp_rtb_value_changed(adj, tbl, "ry", sp_rect_set_visible_ry);
1343 }
1345 static void
1346 sp_rtb_width_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1347 {
1348 sp_rtb_value_changed(adj, tbl, "width", sp_rect_set_visible_width);
1349 }
1351 static void
1352 sp_rtb_height_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1353 {
1354 sp_rtb_value_changed(adj, tbl, "height", sp_rect_set_visible_height);
1355 }
1359 static void
1360 sp_rtb_defaults( GtkWidget *widget, GtkObject *obj)
1361 {
1362 GtkWidget *tbl = GTK_WIDGET(obj);
1364 GtkAdjustment *adj;
1366 adj = (GtkAdjustment*)gtk_object_get_data(obj, "rx");
1367 gtk_adjustment_set_value(adj, 0.0);
1368 // this is necessary if the previous value was 0, but we still need to run the callback to change all selected objects
1369 gtk_adjustment_value_changed(adj);
1371 adj = (GtkAdjustment*)gtk_object_get_data(obj, "ry");
1372 gtk_adjustment_set_value(adj, 0.0);
1373 gtk_adjustment_value_changed(adj);
1375 sp_rtb_sensitivize (tbl);
1377 spinbutton_defocus(GTK_OBJECT(tbl));
1378 }
1380 static void rect_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1381 gchar const *old_value, gchar const *new_value,
1382 bool is_interactive, gpointer data)
1383 {
1384 GtkWidget *tbl = GTK_WIDGET(data);
1386 // quit if run by the _changed callbacks
1387 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1388 return;
1389 }
1391 // in turn, prevent callbacks from responding
1392 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1394 GtkWidget *us = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tbl), "units");
1395 SPUnit const *unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(us));
1397 SPItem *item = SP_ITEM(g_object_get_data(G_OBJECT(tbl), "item"));
1398 if (SP_IS_RECT(item)) {
1399 {
1400 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rx");
1401 gdouble rx = sp_rect_get_visible_rx(SP_RECT(item));
1402 gtk_adjustment_set_value(adj, sp_pixels_get_units(rx, *unit));
1403 }
1405 {
1406 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "ry");
1407 gdouble ry = sp_rect_get_visible_ry(SP_RECT(item));
1408 gtk_adjustment_set_value(adj, sp_pixels_get_units(ry, *unit));
1409 }
1411 {
1412 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "width");
1413 gdouble width = sp_rect_get_visible_width (SP_RECT(item));
1414 gtk_adjustment_set_value(adj, sp_pixels_get_units(width, *unit));
1415 }
1417 {
1418 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "height");
1419 gdouble height = sp_rect_get_visible_height (SP_RECT(item));
1420 gtk_adjustment_set_value(adj, sp_pixels_get_units(height, *unit));
1421 }
1422 }
1424 sp_rtb_sensitivize (tbl);
1426 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1427 }
1430 static Inkscape::XML::NodeEventVector rect_tb_repr_events = {
1431 NULL, /* child_added */
1432 NULL, /* child_removed */
1433 rect_tb_event_attr_changed,
1434 NULL, /* content_changed */
1435 NULL /* order_changed */
1436 };
1438 /**
1439 * \param selection should not be NULL.
1440 */
1441 static void
1442 sp_rect_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1443 {
1444 int n_selected = 0;
1445 Inkscape::XML::Node *repr = NULL;
1446 SPItem *item = NULL;
1447 Inkscape::XML::Node *oldrepr = NULL;
1449 for (GSList const *items = selection->itemList();
1450 items != NULL;
1451 items = items->next) {
1452 if (SP_IS_RECT((SPItem *) items->data)) {
1453 n_selected++;
1454 item = (SPItem *) items->data;
1455 repr = SP_OBJECT_REPR(item);
1456 }
1457 }
1459 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
1461 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(FALSE));
1463 if (n_selected == 0) {
1464 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
1466 GtkWidget *w = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "width_sb");
1467 gtk_widget_set_sensitive(w, FALSE);
1468 GtkWidget *h = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "height_sb");
1469 gtk_widget_set_sensitive(h, FALSE);
1471 } else if (n_selected == 1) {
1472 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1473 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
1475 GtkWidget *w = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "width_sb");
1476 gtk_widget_set_sensitive(w, TRUE);
1477 GtkWidget *h = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "height_sb");
1478 gtk_widget_set_sensitive(h, TRUE);
1480 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1481 if (oldrepr) { // remove old listener
1482 sp_repr_remove_listener_by_data(oldrepr, tbl);
1483 Inkscape::GC::release(oldrepr);
1484 oldrepr = 0;
1485 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1486 }
1487 if (repr) {
1488 g_object_set_data(G_OBJECT(tbl), "repr", repr);
1489 g_object_set_data(G_OBJECT(tbl), "item", item);
1490 Inkscape::GC::anchor(repr);
1491 sp_repr_add_listener(repr, &rect_tb_repr_events, tbl);
1492 sp_repr_synthesize_events(repr, &rect_tb_repr_events, tbl);
1493 }
1494 } else {
1495 // FIXME: implement averaging of all parameters for multiple selected
1496 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1497 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1498 sp_rtb_sensitivize (GTK_WIDGET(tbl));
1499 }
1500 }
1503 static GtkWidget *
1504 sp_rect_toolbox_new(SPDesktop *desktop)
1505 {
1506 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1508 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1509 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1511 GtkTooltips *tt = gtk_tooltips_new();
1513 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1515 // rx/ry units menu: create
1516 GtkWidget *us = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
1517 sp_unit_selector_setsize(us, AUX_OPTION_MENU_WIDTH, AUX_OPTION_MENU_HEIGHT);
1518 sp_unit_selector_set_unit(SP_UNIT_SELECTOR(us), desktop->namedview->doc_units);
1519 // fixme: add % meaning per cent of the width/height
1521 /* W */
1522 {
1523 GtkWidget *hb = sp_tb_spinbutton(_("W:"), _("Width of rectangle"),
1524 "tools.shapes.rect", "width", 0,
1525 us, tbl, TRUE, "altx-rect",
1526 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1527 sp_rtb_width_value_changed);
1528 gtk_object_set_data(GTK_OBJECT(tbl), "width_sb", hb);
1529 gtk_widget_set_sensitive(hb, FALSE);
1530 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1531 }
1533 /* H */
1534 {
1535 GtkWidget *hb = sp_tb_spinbutton(_("H:"), _("Height of rectangle"),
1536 "tools.shapes.rect", "height", 0,
1537 us, tbl, FALSE, NULL,
1538 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1539 sp_rtb_height_value_changed);
1540 gtk_object_set_data(GTK_OBJECT(tbl), "height_sb", hb);
1541 gtk_widget_set_sensitive(hb, FALSE);
1542 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1543 }
1545 /* rx */
1546 {
1547 GtkWidget *hb = sp_tb_spinbutton(_("Rx:"), _("Horizontal radius of rounded corners"),
1548 "tools.shapes.rect", "rx", 0,
1549 us, tbl, FALSE, NULL,
1550 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1551 sp_rtb_rx_value_changed);
1552 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1553 }
1555 /* ry */
1556 {
1557 GtkWidget *hb = sp_tb_spinbutton(_("Ry:"), _("Vertical radius of rounded corners"),
1558 "tools.shapes.rect", "ry", 0,
1559 us, tbl, FALSE, NULL,
1560 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1561 sp_rtb_ry_value_changed);
1562 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1563 }
1565 // add the units menu
1566 gtk_widget_show(us);
1567 gtk_box_pack_start(GTK_BOX(tbl), us, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1568 gtk_object_set_data(GTK_OBJECT(tbl), "units", us);
1570 /* Reset */
1571 {
1572 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1573 GtkWidget *b = gtk_button_new_with_label(_("Not rounded"));
1574 gtk_object_set_data(GTK_OBJECT(tbl), "not_rounded", b);
1575 gtk_tooltips_set_tip(tt, b, _("Make corners sharp"), NULL);
1576 gtk_widget_show(b);
1577 gtk_container_add(GTK_CONTAINER(hb), b);
1578 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_rtb_defaults), tbl);
1579 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1580 }
1582 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1583 swatch->setWatchedTool ("tools.shapes.rect", true);
1584 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1585 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1587 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
1588 sp_rtb_sensitivize (tbl);
1590 gtk_widget_show_all(tbl);
1591 sp_set_font_size_smaller (tbl);
1593 sigc::connection *connection = new sigc::connection(
1594 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_rect_toolbox_selection_changed), (GtkObject *)tbl))
1595 );
1596 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1598 return tbl;
1599 }
1601 //########################
1602 //## Spiral ##
1603 //########################
1605 static void
1606 sp_spl_tb_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name)
1607 {
1608 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
1610 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1611 prefs_set_double_attribute("tools.shapes.spiral", value_name, adj->value);
1612 }
1614 // quit if run by the attr_changed listener
1615 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1616 return;
1617 }
1619 // in turn, prevent listener from responding
1620 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1622 gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
1624 bool modmade = false;
1625 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
1626 items != NULL;
1627 items = items->next)
1628 {
1629 if (SP_IS_SPIRAL((SPItem *) items->data)) {
1630 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
1631 sp_repr_set_svg_double( repr, namespaced_name, adj->value );
1632 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
1633 modmade = true;
1634 }
1635 }
1637 g_free(namespaced_name);
1639 if (modmade) {
1640 sp_document_done(sp_desktop_document(desktop));
1641 }
1643 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1645 spinbutton_defocus(GTK_OBJECT(tbl));
1646 }
1648 static void
1649 sp_spl_tb_revolution_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1650 {
1651 sp_spl_tb_value_changed(adj, tbl, "revolution");
1652 }
1654 static void
1655 sp_spl_tb_expansion_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1656 {
1657 sp_spl_tb_value_changed(adj, tbl, "expansion");
1658 }
1660 static void
1661 sp_spl_tb_t0_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1662 {
1663 sp_spl_tb_value_changed(adj, tbl, "t0");
1664 }
1666 static void
1667 sp_spl_tb_defaults(GtkWidget *widget, GtkObject *obj)
1668 {
1669 GtkWidget *tbl = GTK_WIDGET(obj);
1671 GtkAdjustment *adj;
1673 // fixme: make settable
1674 gdouble rev = 5;
1675 gdouble exp = 1.0;
1676 gdouble t0 = 0.0;
1678 adj = (GtkAdjustment*)gtk_object_get_data(obj, "revolution");
1679 gtk_adjustment_set_value(adj, rev);
1680 gtk_adjustment_value_changed(adj);
1682 adj = (GtkAdjustment*)gtk_object_get_data(obj, "expansion");
1683 gtk_adjustment_set_value(adj, exp);
1684 gtk_adjustment_value_changed(adj);
1686 adj = (GtkAdjustment*)gtk_object_get_data(obj, "t0");
1687 gtk_adjustment_set_value(adj, t0);
1688 gtk_adjustment_value_changed(adj);
1690 spinbutton_defocus(GTK_OBJECT(tbl));
1691 }
1694 static void spiral_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1695 gchar const *old_value, gchar const *new_value,
1696 bool is_interactive, gpointer data)
1697 {
1698 GtkWidget *tbl = GTK_WIDGET(data);
1700 // quit if run by the _changed callbacks
1701 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1702 return;
1703 }
1705 // in turn, prevent callbacks from responding
1706 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1708 GtkAdjustment *adj;
1709 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "revolution");
1710 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:revolution", 3.0)));
1712 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "expansion");
1713 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:expansion", 1.0)));
1715 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "t0");
1716 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:t0", 0.0)));
1718 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1719 }
1722 static Inkscape::XML::NodeEventVector spiral_tb_repr_events = {
1723 NULL, /* child_added */
1724 NULL, /* child_removed */
1725 spiral_tb_event_attr_changed,
1726 NULL, /* content_changed */
1727 NULL /* order_changed */
1728 };
1730 static void
1731 sp_spiral_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1732 {
1733 int n_selected = 0;
1734 Inkscape::XML::Node *repr = NULL;
1735 Inkscape::XML::Node *oldrepr = NULL;
1737 for (GSList const *items = selection->itemList();
1738 items != NULL;
1739 items = items->next)
1740 {
1741 if (SP_IS_SPIRAL((SPItem *) items->data)) {
1742 n_selected++;
1743 repr = SP_OBJECT_REPR((SPItem *) items->data);
1744 }
1745 }
1747 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
1749 if (n_selected == 0) {
1750 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
1751 } else if (n_selected == 1) {
1752 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1754 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1755 if (oldrepr) { // remove old listener
1756 sp_repr_remove_listener_by_data(oldrepr, tbl);
1757 Inkscape::GC::release(oldrepr);
1758 oldrepr = 0;
1759 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1760 }
1762 if (repr) {
1763 g_object_set_data(G_OBJECT(tbl), "repr", repr);
1764 Inkscape::GC::anchor(repr);
1765 sp_repr_add_listener(repr, &spiral_tb_repr_events, tbl);
1766 sp_repr_synthesize_events(repr, &spiral_tb_repr_events, tbl);
1767 }
1768 } else {
1769 // FIXME: implement averaging of all parameters for multiple selected
1770 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1771 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1772 }
1773 }
1776 static GtkWidget *
1777 sp_spiral_toolbox_new(SPDesktop *desktop)
1778 {
1779 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1780 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1781 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1783 GtkTooltips *tt = gtk_tooltips_new();
1785 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1787 /* Revolution */
1788 {
1789 GtkWidget *hb = sp_tb_spinbutton(_("Turns:"), _("Number of revolutions"),
1790 "tools.shapes.spiral", "revolution", 3.0,
1791 NULL, tbl, TRUE, "altx-spiral",
1792 0.01, 1024.0, 0.1, 1.0,
1793 sp_spl_tb_revolution_value_changed, 1, 2);
1794 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1795 }
1797 /* Expansion */
1798 {
1799 GtkWidget *hb = sp_tb_spinbutton(_("Divergence:"), _("How much denser/sparser are outer revolutions; 1 = uniform"),
1800 "tools.shapes.spiral", "expansion", 1.0,
1801 NULL, tbl, FALSE, NULL,
1802 0.0, 1000.0, 0.01, 1.0,
1803 sp_spl_tb_expansion_value_changed);
1804 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1805 }
1807 /* T0 */
1808 {
1809 GtkWidget *hb = sp_tb_spinbutton(_("Inner radius:"), _("Radius of the innermost revolution (relative to the spiral size)"),
1810 "tools.shapes.spiral", "t0", 0.0,
1811 NULL, tbl, FALSE, NULL,
1812 0.0, 0.999, 0.01, 1.0,
1813 sp_spl_tb_t0_value_changed);
1814 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1815 }
1817 aux_toolbox_space(tbl, AUX_SPACING);
1819 /* Reset */
1820 {
1821 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1822 GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
1823 gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
1824 gtk_widget_show(b);
1825 gtk_container_add(GTK_CONTAINER(hb), b);
1826 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_spl_tb_defaults), tbl);
1827 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1828 }
1830 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1831 swatch->setWatchedTool ("tools.shapes.spiral", true);
1832 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1833 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1835 gtk_widget_show_all(tbl);
1836 sp_set_font_size_smaller (tbl);
1838 sigc::connection *connection = new sigc::connection(
1839 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_spiral_toolbox_selection_changed), (GtkObject *)tbl))
1840 );
1841 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1843 return tbl;
1844 }
1846 //########################
1847 //## Pen/Pencil ##
1848 //########################
1851 static GtkWidget *
1852 sp_pen_toolbox_new(SPDesktop *desktop)
1853 {
1854 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1855 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1856 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1858 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1859 swatch->setWatchedTool ("tools.freehand.pen", true);
1860 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1861 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1863 gtk_widget_show_all(tbl);
1864 sp_set_font_size_smaller (tbl);
1866 return tbl;
1867 }
1869 static GtkWidget *
1870 sp_pencil_toolbox_new(SPDesktop *desktop)
1871 {
1872 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1873 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1874 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1876 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1877 swatch->setWatchedTool ("tools.freehand.pencil", true);
1878 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1879 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1881 gtk_widget_show_all(tbl);
1882 sp_set_font_size_smaller (tbl);
1884 return tbl;
1885 }
1888 //########################
1889 //## Calligraphy ##
1890 //########################
1892 static void
1893 sp_ddc_mass_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1894 {
1895 prefs_set_double_attribute("tools.calligraphic", "mass", adj->value);
1896 spinbutton_defocus(GTK_OBJECT(tbl));
1897 }
1899 static void
1900 sp_ddc_drag_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1901 {
1902 prefs_set_double_attribute("tools.calligraphic", "drag", adj->value);
1903 spinbutton_defocus(GTK_OBJECT(tbl));
1904 }
1906 static void
1907 sp_ddc_angle_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1908 {
1909 prefs_set_double_attribute("tools.calligraphic", "angle", adj->value);
1910 spinbutton_defocus(GTK_OBJECT(tbl));
1911 }
1913 static void
1914 sp_ddc_width_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1915 {
1916 prefs_set_double_attribute("tools.calligraphic", "width", adj->value * 0.01);
1917 spinbutton_defocus(GTK_OBJECT(tbl));
1918 }
1920 static void
1921 sp_ddc_velthin_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1922 {
1923 prefs_set_double_attribute("tools.calligraphic", "thinning", adj->value);
1924 spinbutton_defocus(GTK_OBJECT(tbl));
1925 }
1927 static void
1928 sp_ddc_flatness_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1929 {
1930 prefs_set_double_attribute("tools.calligraphic", "flatness", adj->value);
1931 spinbutton_defocus(GTK_OBJECT(tbl));
1932 }
1934 static void
1935 sp_ddc_tremor_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1936 {
1937 prefs_set_double_attribute("tools.calligraphic", "tremor", adj->value);
1938 spinbutton_defocus(GTK_OBJECT(tbl));
1939 }
1941 static void
1942 sp_ddc_pressure_state_changed(GtkWidget *button, gpointer data)
1943 {
1944 prefs_set_int_attribute ("tools.calligraphic", "usepressure", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0);
1945 }
1947 static void
1948 sp_ddc_tilt_state_changed(GtkWidget *button, GtkWidget *calligraphy_angle)
1949 {
1950 prefs_set_int_attribute ("tools.calligraphic", "usetilt", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0);
1952 gtk_widget_set_sensitive(GTK_WIDGET(calligraphy_angle), !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
1953 }
1955 static void sp_ddc_defaults(GtkWidget *, GtkWidget *tbl)
1956 {
1957 // FIXME: make defaults settable via Inkscape Options
1958 struct KeyValue {
1959 char const *key;
1960 double value;
1961 } const key_values[] = {
1962 {"mass", 0.02},
1963 {"drag", 1.0},
1964 {"angle", 30.0},
1965 {"width", 15},
1966 {"thinning", 0.1},
1967 {"tremor", 0.0},
1968 {"flatness", 0.9}
1969 };
1971 for (unsigned i = 0; i < G_N_ELEMENTS(key_values); ++i) {
1972 KeyValue const &kv = key_values[i];
1973 GtkAdjustment &adj = *static_cast<GtkAdjustment *>(gtk_object_get_data(GTK_OBJECT(tbl), kv.key));
1974 gtk_adjustment_set_value(&adj, kv.value);
1975 }
1977 spinbutton_defocus(GTK_OBJECT(tbl));
1978 }
1980 static GtkWidget *
1981 sp_calligraphy_toolbox_new(SPDesktop *desktop)
1982 {
1983 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1984 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1985 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1987 GtkTooltips *tt = gtk_tooltips_new();
1988 GtkWidget *calligraphy_angle;
1990 // interval
1991 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1993 /* Width */
1994 {
1995 GtkWidget *hb = sp_tb_spinbutton(_("Width:"), _("The width of the calligraphic pen (relative to the visible canvas area)"),
1996 "tools.calligraphic", "width", 15,
1997 NULL, tbl, TRUE, "altx-calligraphy",
1998 1, 100, 1.0, 10.0,
1999 sp_ddc_width_value_changed, 0.01, 0, 100);
2000 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2001 }
2003 /* Thinning */
2004 {
2005 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)"),
2006 "tools.calligraphic", "thinning", 0.1,
2007 NULL, tbl, FALSE, NULL,
2008 -1.0, 1.0, 0.01, 0.1,
2009 sp_ddc_velthin_value_changed, 0.01, 2);
2010 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2011 }
2013 // interval
2014 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2016 /* Angle */
2017 {
2018 calligraphy_angle = sp_tb_spinbutton(_("Angle:"), _("The angle of the pen's nib (in degrees; 0 = horizontal; has no effect if fixation = 0)"),
2019 "tools.calligraphic", "angle", 30,
2020 NULL, tbl, TRUE, "calligraphy-angle",
2021 -90.0, 90.0, 1.0, 10.0,
2022 sp_ddc_angle_value_changed, 1, 0);
2023 gtk_box_pack_start(GTK_BOX(tbl), calligraphy_angle, FALSE, FALSE, AUX_SPACING);
2024 }
2026 /* Fixation */
2027 {
2028 GtkWidget *hb = sp_tb_spinbutton(_("Fixation:"), _("How fixed is the pen angle (0 = always perpendicular to stroke direction, 1 = fixed)"),
2029 "tools.calligraphic", "flatness", 0.9,
2030 NULL, tbl, FALSE, NULL,
2031 0.0, 1.0, 0.01, 0.1,
2032 sp_ddc_flatness_value_changed, 0.01, 2);
2033 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2034 }
2036 // interval
2037 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2039 /* Tremor */
2040 {
2041 GtkWidget *hb = sp_tb_spinbutton(_("Tremor:"), _("How uneven or trembling is the pen stroke"),
2042 "tools.calligraphic", "tremor", 0.0,
2043 NULL, tbl, FALSE, NULL,
2044 0.0, 1.0, 0.01, 0.1,
2045 sp_ddc_tremor_value_changed, 0.01, 2);
2046 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2047 }
2048 /* Mass */
2049 {
2050 GtkWidget *hb = sp_tb_spinbutton(_("Mass:"), _("How much inertia affects the movement of the pen"),
2051 "tools.calligraphic", "mass", 0.02,
2052 NULL, tbl, FALSE, NULL,
2053 0.0, 1.0, 0.01, 0.1,
2054 sp_ddc_mass_value_changed, 0.01, 2);
2055 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2056 }
2058 /* Drag */
2059 {
2060 // TRANSLATORS: "drag" means "resistance" here
2061 GtkWidget *hb = sp_tb_spinbutton(_("Drag:"), _("How much resistance affects the movement of the pen"),
2062 "tools.calligraphic", "drag", 1,
2063 NULL, tbl, FALSE, NULL,
2064 0.0, 1.0, 0.01, 0.1,
2065 sp_ddc_drag_value_changed, 0.01, 2);
2066 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2067 }
2069 // interval
2070 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2072 GtkWidget *cvbox = gtk_vbox_new (FALSE, 0);
2073 GtkWidget *cbox = gtk_hbox_new (FALSE, 0);
2075 /* Use Pressure button */
2076 {
2077 GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
2078 SP_BUTTON_TYPE_TOGGLE,
2079 NULL,
2080 "use_pressure",
2081 _("Use the pressure of the input device to alter the width of the pen"),
2082 tt);
2083 g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (sp_ddc_pressure_state_changed), NULL);
2084 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.calligraphic", "usepressure", 1));
2085 gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
2086 }
2088 /* Use Tilt button */
2089 {
2090 GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
2091 SP_BUTTON_TYPE_TOGGLE,
2092 NULL,
2093 "use_tilt",
2094 _("Use the tilt of the input device to alter the angle of the pen's nib"),
2095 tt);
2096 g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (sp_ddc_tilt_state_changed), calligraphy_angle);
2097 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.calligraphic", "usetilt", 1));
2098 gtk_widget_set_sensitive(GTK_WIDGET(calligraphy_angle), !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
2099 gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
2100 }
2102 gtk_box_pack_start(GTK_BOX(cvbox), cbox, TRUE, FALSE, 0);
2103 gtk_box_pack_start(GTK_BOX(tbl), cvbox, FALSE, FALSE, 0);
2105 /* Reset */
2106 {
2107 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2108 GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
2109 gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
2110 gtk_widget_show(b);
2111 gtk_container_add(GTK_CONTAINER(hb), b);
2112 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_ddc_defaults), tbl);
2113 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2114 }
2117 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
2118 swatch->setWatchedTool ("tools.calligraphic", true);
2119 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
2120 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
2122 gtk_widget_show_all(tbl);
2123 sp_set_font_size_smaller (tbl);
2125 return tbl;
2126 }
2129 //########################
2130 //## Circle / Arc ##
2131 //########################
2133 static void
2134 sp_arctb_sensitivize (GtkWidget *tbl, double v1, double v2)
2135 {
2136 GtkWidget *ocb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "open_checkbox");
2137 GtkWidget *make_whole = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "make_whole");
2139 if (v1 == 0 && v2 == 0) {
2140 if (gtk_object_get_data(GTK_OBJECT(tbl), "single")) { // only for a single selected ellipse (for now)
2141 gtk_widget_set_sensitive(GTK_WIDGET(ocb), FALSE);
2142 gtk_widget_set_sensitive(GTK_WIDGET(make_whole), FALSE);
2143 }
2144 } else {
2145 gtk_widget_set_sensitive(GTK_WIDGET(ocb), TRUE);
2146 gtk_widget_set_sensitive(GTK_WIDGET(make_whole), TRUE);
2147 }
2148 }
2150 static void
2151 sp_arctb_startend_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name, gchar const *other_name)
2152 {
2153 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2155 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2156 prefs_set_double_attribute("tools.shapes.arc", value_name, (adj->value * M_PI)/ 180);
2157 }
2159 // quit if run by the attr_changed listener
2160 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2161 return;
2162 }
2164 // in turn, prevent listener from responding
2165 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2167 gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
2169 bool modmade = false;
2170 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2171 items != NULL;
2172 items = items->next)
2173 {
2174 SPItem *item = SP_ITEM(items->data);
2176 if (SP_IS_ARC(item) && SP_IS_GENERICELLIPSE(item)) {
2178 SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
2179 SPArc *arc = SP_ARC(item);
2181 if (!strcmp(value_name, "start"))
2182 ge->start = (adj->value * M_PI)/ 180;
2183 else
2184 ge->end = (adj->value * M_PI)/ 180;
2186 sp_genericellipse_normalize(ge);
2187 ((SPObject *)arc)->updateRepr();
2188 ((SPObject *)arc)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
2190 modmade = true;
2191 }
2192 }
2194 g_free(namespaced_name);
2196 GtkAdjustment *other = (GtkAdjustment *)gtk_object_get_data(GTK_OBJECT(tbl), other_name);
2198 sp_arctb_sensitivize (tbl, adj->value, other->value);
2200 if (modmade) {
2201 sp_document_maybe_done(sp_desktop_document(desktop), value_name);
2202 }
2204 // defocus spinbuttons by moving focus to the canvas, unless "stay" is on
2205 spinbutton_defocus(GTK_OBJECT(tbl));
2207 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2208 }
2211 static void
2212 sp_arctb_start_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
2213 {
2214 sp_arctb_startend_value_changed(adj, tbl, "start", "end");
2215 }
2217 static void
2218 sp_arctb_end_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
2219 {
2220 sp_arctb_startend_value_changed(adj, tbl, "end", "start");
2221 }
2223 static void
2224 sp_arctb_open_state_changed(GtkWidget *widget, GtkObject *tbl)
2225 {
2226 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2228 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2229 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
2230 prefs_set_string_attribute("tools.shapes.arc", "open", "true");
2231 } else {
2232 prefs_set_string_attribute("tools.shapes.arc", "open", NULL);
2233 }
2234 }
2236 // quit if run by the attr_changed listener
2237 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2238 return;
2239 }
2241 // in turn, prevent listener from responding
2242 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2244 bool modmade = false;
2246 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
2247 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2248 items != NULL;
2249 items = items->next)
2250 {
2251 if (SP_IS_ARC((SPItem *) items->data)) {
2252 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2253 repr->setAttribute("sodipodi:open", "true");
2254 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
2255 modmade = true;
2256 }
2257 }
2258 } else {
2259 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2260 items != NULL;
2261 items = items->next)
2262 {
2263 if (SP_IS_ARC((SPItem *) items->data)) {
2264 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2265 repr->setAttribute("sodipodi:open", NULL);
2266 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
2267 modmade = true;
2268 }
2269 }
2270 }
2272 if (modmade) {
2273 sp_document_done(sp_desktop_document(desktop));
2274 }
2276 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2278 spinbutton_defocus(GTK_OBJECT(tbl));
2279 }
2281 static void sp_arctb_defaults(GtkWidget *, GtkObject *obj)
2282 {
2283 GtkWidget *tbl = GTK_WIDGET(obj);
2285 GtkAdjustment *adj;
2286 adj = (GtkAdjustment*)gtk_object_get_data(obj, "start");
2287 gtk_adjustment_set_value(adj, 0.0);
2288 gtk_adjustment_value_changed(adj);
2290 adj = (GtkAdjustment*)gtk_object_get_data(obj, "end");
2291 gtk_adjustment_set_value(adj, 0.0);
2292 gtk_adjustment_value_changed(adj);
2294 spinbutton_defocus(GTK_OBJECT(tbl));
2295 }
2297 static void arc_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
2298 gchar const *old_value, gchar const *new_value,
2299 bool is_interactive, gpointer data)
2300 {
2301 GtkWidget *tbl = GTK_WIDGET(data);
2303 // quit if run by the _changed callbacks
2304 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2305 return;
2306 }
2308 // in turn, prevent callbacks from responding
2309 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2311 gdouble start = sp_repr_get_double_attribute(repr, "sodipodi:start", 0.0);
2312 gdouble end = sp_repr_get_double_attribute(repr, "sodipodi:end", 0.0);
2314 GtkAdjustment *adj1,*adj2;
2315 adj1 = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "start");
2316 gtk_adjustment_set_value(adj1, mod360((start * 180)/M_PI));
2317 adj2 = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "end");
2318 gtk_adjustment_set_value(adj2, mod360((end * 180)/M_PI));
2320 sp_arctb_sensitivize (tbl, adj1->value, adj2->value);
2322 char const *openstr = NULL;
2323 openstr = repr->attribute("sodipodi:open");
2324 GtkWidget *ocb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "open_checkbox");
2326 if (openstr) {
2327 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ocb), TRUE);
2328 } else {
2329 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ocb), FALSE);
2330 }
2332 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2333 }
2335 static Inkscape::XML::NodeEventVector arc_tb_repr_events = {
2336 NULL, /* child_added */
2337 NULL, /* child_removed */
2338 arc_tb_event_attr_changed,
2339 NULL, /* content_changed */
2340 NULL /* order_changed */
2341 };
2344 static void
2345 sp_arc_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
2346 {
2347 int n_selected = 0;
2348 Inkscape::XML::Node *repr = NULL;
2349 Inkscape::XML::Node *oldrepr = NULL;
2351 for (GSList const *items = selection->itemList();
2352 items != NULL;
2353 items = items->next)
2354 {
2355 if (SP_IS_ARC((SPItem *) items->data)) {
2356 n_selected++;
2357 repr = SP_OBJECT_REPR((SPItem *) items->data);
2358 }
2359 }
2361 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
2363 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(FALSE));
2364 if (n_selected == 0) {
2365 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
2366 } else if (n_selected == 1) {
2367 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
2368 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2370 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
2372 if (oldrepr) { // remove old listener
2373 sp_repr_remove_listener_by_data(oldrepr, tbl);
2374 Inkscape::GC::release(oldrepr);
2375 oldrepr = 0;
2376 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
2377 }
2379 if (repr) {
2380 g_object_set_data(G_OBJECT(tbl), "repr", repr);
2381 Inkscape::GC::anchor(repr);
2382 sp_repr_add_listener(repr, &arc_tb_repr_events, tbl);
2383 sp_repr_synthesize_events(repr, &arc_tb_repr_events, tbl);
2384 }
2385 } else {
2386 // FIXME: implement averaging of all parameters for multiple selected
2387 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
2388 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2389 sp_arctb_sensitivize (GTK_WIDGET(tbl), 1, 0);
2390 }
2391 }
2394 static GtkWidget *
2395 sp_arc_toolbox_new(SPDesktop *desktop)
2396 {
2397 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2399 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2400 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2402 GtkTooltips *tt = gtk_tooltips_new();
2404 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
2406 /* Start */
2407 {
2408 GtkWidget *hb = sp_tb_spinbutton(_("Start:"), _("The angle (in degrees) from the horizontal to the arc's start point"),
2409 "tools.shapes.arc", "start", 0.0,
2410 NULL, tbl, TRUE, "altx-arc",
2411 -360.0, 360.0, 1.0, 10.0,
2412 sp_arctb_start_value_changed);
2413 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2414 }
2416 /* End */
2417 {
2418 GtkWidget *hb = sp_tb_spinbutton(_("End:"), _("The angle (in degrees) from the horizontal to the arc's end point"),
2419 "tools.shapes.arc", "end", 0.0,
2420 NULL, tbl, FALSE, NULL,
2421 -360.0, 360.0, 1.0, 10.0,
2422 sp_arctb_end_value_changed);
2423 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2424 }
2426 /* Segments / Pie checkbox */
2427 {
2428 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2429 GtkWidget *fscb = gtk_check_button_new_with_label(_("Open arc"));
2430 gtk_tooltips_set_tip(tt, fscb, _("Switch between arc (unclosed shape) and segment (closed shape with two radii)"), NULL);
2432 gchar const *openstr = NULL;
2433 openstr = prefs_get_string_attribute("tools.shapes.arc", "open");
2434 if (!openstr || (openstr && !strcmp(openstr, "false")))
2435 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), FALSE);
2436 else
2437 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), TRUE);
2439 gtk_widget_show(fscb);
2440 gtk_object_set_data(GTK_OBJECT(tbl), "open_checkbox", fscb);
2441 gtk_container_add(GTK_CONTAINER(hb), fscb);
2442 g_signal_connect(G_OBJECT(fscb), "toggled", GTK_SIGNAL_FUNC(sp_arctb_open_state_changed ), tbl);
2443 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2444 }
2446 /* Make Whole */
2447 {
2448 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2449 GtkWidget *b = gtk_button_new_with_label(_("Make whole"));
2450 gtk_object_set_data(GTK_OBJECT(tbl), "make_whole", b);
2451 gtk_tooltips_set_tip(tt, b, _("Make the shape a whole ellipse, not arc or segment"), NULL);
2452 gtk_widget_show(b);
2453 gtk_container_add(GTK_CONTAINER(hb), b);
2454 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_arctb_defaults), tbl);
2455 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2456 }
2458 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
2459 // sensitivize make whole and open checkbox
2460 {
2461 GtkAdjustment *adj1 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "start"));
2462 GtkAdjustment *adj2 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "end"));
2463 sp_arctb_sensitivize (tbl, adj1->value, adj2->value);
2464 }
2466 sigc::connection *connection = new sigc::connection(
2467 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_arc_toolbox_selection_changed), (GtkObject *)tbl))
2468 );
2469 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
2471 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
2472 swatch->setWatchedTool ("tools.shapes.arc", true);
2473 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
2474 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
2476 gtk_widget_show_all(tbl);
2477 sp_set_font_size_smaller (tbl);
2479 return tbl;
2480 }
2485 // toggle button callbacks and updaters
2487 //########################
2488 //## Dropper ##
2489 //########################
2491 static void toggle_dropper_color_pick (GtkWidget *button, gpointer data) {
2492 prefs_set_int_attribute ("tools.dropper", "pick",
2493 // 0 and 1 are backwards here because of pref
2494 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1);
2495 }
2498 /**
2499 * Copy the current saved desktop color to the clipboard as full hex + alpha
2500 * color representation. This is useful for passing values between various
2501 * input boxes, or directly to xml.
2502 */
2503 /* static void
2504 sp_dropper_copy( GtkWidget *widget, GtkObject *obj)
2505 {
2506 GtkWidget *tbl = GTK_WIDGET(obj);
2508 SPDesktop *desktop =
2509 (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2512 sp_dropper_c32_color_copy( sp_desktop_get_color(desktop, true) );
2513 }*/
2516 /**
2517 * Copies currently saved desktop color to the clipboard as a hex value. This
2518 * is useful for editing webpages and needing a value quickly for web
2519 * colors.
2520 *
2521 * TODO: When the toggle of the dropper is set to not mix color against
2522 * page background, this still just gets the color of the page and
2523 * doesn't get the actual mixed against background which is needed
2524 * for the hex value ppl. want for web pages, etc.
2525 */
2527 /* static void
2528 sp_dropper_copy_as_hex ( GtkWidget *widget, GtkObject *obj)
2529 {
2530 GtkWidget *tbl = GTK_WIDGET(obj);
2532 SPDesktop *desktop =
2533 (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2535 sp_dropper_c32_color_copy_hex( sp_desktop_get_color(desktop, true) );
2536 }*/
2539 /**
2540 * Sets the input boxes with the changed color and opacity. This is used as a
2541 * callback for style changing.
2542 */
2543 /* static bool
2544 sp_style_changed (const SPCSSAttr *css, gpointer data)
2545 {
2546 // GrDrag *drag = (GrDrag *) data;
2548 // set fill of text entry box
2549 if (css->attribute("fill"))
2550 gtk_entry_set_text((GtkEntry *)dropper_rgb_entry,
2551 css->attribute("fill"));
2553 // set opacity of text entry box
2554 if (css->attribute("fill-opacity"))
2555 gtk_entry_set_text((GtkEntry *)dropper_opacity_entry,
2556 css->attribute("fill-opacity"));
2558 // set fill of text entry box
2559 if (css->attribute("stroke"))
2560 gtk_entry_set_text((GtkEntry *)dropper_rgb_entry,
2561 css->attribute("stroke"));
2563 // set opacity of text entry box
2564 if (css->attribute("stroke-opacity"))
2565 gtk_entry_set_text((GtkEntry *)dropper_opacity_entry,
2566 css->attribute("stroke-opacity"));
2567 return false;
2569 }
2570 */
2573 /**
2574 * Dropper auxiliary toolbar construction and setup.
2575 *
2576 * TODO: Would like to add swatch of current color.
2577 * TODO: Add queue of last 5 or so colors selected with new swatches so that
2578 * can drag and drop places. Will provide a nice mixing palette.
2579 */
2580 static GtkWidget *
2581 sp_dropper_toolbox_new(SPDesktop *desktop)
2582 {
2583 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2585 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2586 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2588 GtkTooltips *tt = gtk_tooltips_new();
2591 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
2592 AUX_BETWEEN_BUTTON_GROUPS);
2593 // sp_toolbox_add_label(tbl, _("<b>New:</b>"));
2597 /* RGB Input Field */
2598 /* {
2599 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2600 GtkWidget *dropper_rgba_label = gtk_label_new ("Color:");
2601 gtk_widget_show (dropper_rgba_label);
2602 gtk_container_add(GTK_CONTAINER(hb), dropper_rgba_label);
2604 dropper_rgb_entry = gtk_entry_new ();
2605 sp_dialog_defocus_on_enter (dropper_rgb_entry);
2606 gtk_entry_set_max_length (GTK_ENTRY (dropper_rgb_entry), 7);
2607 gtk_entry_set_width_chars (GTK_ENTRY (dropper_rgb_entry), 7);
2608 gtk_tooltips_set_tip(tt, dropper_rgb_entry,
2609 _("Hexidecimal representation of last selected "
2610 "color"),
2611 NULL);
2612 gtk_widget_show (dropper_rgb_entry);
2613 gtk_container_add(GTK_CONTAINER(hb), dropper_rgb_entry);
2615 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2616 AUX_BETWEEN_BUTTON_GROUPS);
2617 } */
2619 /* Opacity Input Field */
2620 /* {
2621 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2622 GtkWidget *dropper_opacity_label = gtk_label_new ( _("Opacity:") );
2623 gtk_widget_show (dropper_opacity_label);
2624 gtk_container_add(GTK_CONTAINER(hb), dropper_opacity_label);
2626 dropper_opacity_entry = gtk_entry_new ();
2627 sp_dialog_defocus_on_enter (dropper_opacity_entry);
2628 gtk_entry_set_max_length (GTK_ENTRY (dropper_opacity_entry), 11);
2629 gtk_entry_set_width_chars (GTK_ENTRY (dropper_opacity_entry), 11);
2630 gtk_tooltips_set_tip(tt, dropper_opacity_entry,
2631 _("Opacity of last selected color"),
2632 NULL);
2633 gtk_widget_show (dropper_opacity_entry);
2634 gtk_container_add(GTK_CONTAINER(hb), dropper_opacity_entry);
2636 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2637 AUX_BETWEEN_BUTTON_GROUPS);
2638 } */
2641 /* Copy to Clipboard */
2642 /* {
2643 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2644 GtkWidget *b = gtk_button_new_with_label(_("Copy as RGBA"));
2645 gtk_tooltips_set_tip(tt, b, _("Copy last saved color as hexidecimal "
2646 "RGB + Alpha (RGBA) to "
2647 "clipboard"),
2648 NULL);
2649 gtk_widget_show(b);
2650 gtk_container_add(GTK_CONTAINER(hb), b);
2651 gtk_signal_connect(GTK_OBJECT(b), "clicked",
2652 GTK_SIGNAL_FUNC(sp_dropper_copy), tbl);
2653 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2654 AUX_BETWEEN_BUTTON_GROUPS);
2655 } */
2658 /* Copy to Clipboard as HEX */
2659 /* {
2660 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2661 GtkWidget *b = gtk_button_new_with_label(_("Copy as HEX"));
2662 gtk_tooltips_set_tip(tt, b, _("Copy last saved color as "
2663 "hexidecimal RGB without alpha "
2664 "to clipboard"), NULL);
2665 gtk_widget_show(b);
2666 gtk_container_add(GTK_CONTAINER(hb), b);
2667 gtk_signal_connect(GTK_OBJECT(b), "clicked",
2668 GTK_SIGNAL_FUNC(sp_dropper_copy_as_hex), tbl);
2669 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2670 AUX_BETWEEN_BUTTON_GROUPS);
2671 } */
2673 // aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2675 {
2676 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2678 GtkWidget *button =
2679 sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
2680 SP_BUTTON_TYPE_TOGGLE,
2681 NULL,
2682 "pick_color",
2683 _("When pressed, picks visible color "
2684 "without alpha and when not pressed, "
2685 "picks color including its "
2686 "alpha"),
2687 tt);
2689 gtk_widget_show(button);
2690 gtk_container_add (GTK_CONTAINER (hb), button);
2692 g_signal_connect_after (G_OBJECT (button), "clicked",
2693 G_CALLBACK (toggle_dropper_color_pick), NULL);
2694 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
2695 !prefs_get_int_attribute ("tools.dropper",
2696 "pick", 0));
2697 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2698 AUX_BETWEEN_BUTTON_GROUPS);
2699 }
2701 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2704 // where new gtkmm stuff should go
2706 gtk_widget_show_all(tbl);
2707 sp_set_font_size_smaller (tbl);
2709 /*
2710 sigc::connection *connection = new sigc::connection(
2711 desktop->connectSetStyle(
2712 sigc::bind(sigc::ptr_fun(sp_style_changed),
2713 desktop)) );
2715 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection),
2716 connection); */
2718 return tbl;
2719 }
2722 //########################
2723 //## Text Toolbox ##
2724 //########################
2725 /*
2726 static void
2727 sp_text_letter_changed(GtkAdjustment *adj, GtkWidget *tbl)
2728 {
2729 //Call back for letter sizing spinbutton
2730 }
2732 static void
2733 sp_text_line_changed(GtkAdjustment *adj, GtkWidget *tbl)
2734 {
2735 //Call back for line height spinbutton
2736 }
2738 static void
2739 sp_text_horiz_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
2740 {
2741 //Call back for horizontal kerning spinbutton
2742 }
2744 static void
2745 sp_text_vert_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
2746 {
2747 //Call back for vertical kerning spinbutton
2748 }
2750 static void
2751 sp_text_letter_rotation_changed(GtkAdjustment *adj, GtkWidget *tbl)
2752 {
2753 //Call back for letter rotation spinbutton
2754 }*/
2755 static GtkWidget *
2756 sp_text_toolbox_new(SPDesktop *desktop)
2757 {
2758 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2759 /* GtkWidget *us = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tbl), "units");
2760 GtkTooltips *tt = gtk_tooltips_new();
2761 GtkWidget *group;
2763 //Font Family
2764 {
2765 GtkWidget *c = gtk_combo_new ();
2766 gtk_combo_set_value_in_list ((GtkCombo *) c, FALSE, FALSE);
2767 gtk_combo_set_use_arrows ((GtkCombo *) c, TRUE);
2768 gtk_combo_set_use_arrows_always ((GtkCombo *) c, TRUE);
2769 gtk_widget_set_size_request (c, 144, -1);
2770 aux_toolbox_space(tbl, 1);
2771 gtk_box_pack_start (GTK_BOX (tbl), c, FALSE, FALSE, 0);
2772 }
2774 //Font Style
2775 {
2776 GtkWidget *c = gtk_combo_new ();
2777 gtk_combo_set_value_in_list ((GtkCombo *) c, FALSE, FALSE);
2778 gtk_combo_set_use_arrows ((GtkCombo *) c, TRUE);
2779 gtk_combo_set_use_arrows_always ((GtkCombo *) c, TRUE);
2780 gtk_widget_set_size_request (c, 88, -1);
2781 aux_toolbox_space(tbl, 1);
2782 gtk_box_pack_start (GTK_BOX (tbl), c, FALSE, FALSE, 0);
2783 }
2785 //Font Size
2786 {
2787 GtkWidget *c = gtk_combo_new ();
2788 gtk_combo_set_value_in_list ((GtkCombo *) c, FALSE, FALSE);
2789 gtk_combo_set_use_arrows ((GtkCombo *) c, TRUE);
2790 gtk_combo_set_use_arrows_always ((GtkCombo *) c, TRUE);
2791 gtk_widget_set_size_request (c, 64, -1);
2792 aux_toolbox_space(tbl, 1);
2793 gtk_box_pack_start (GTK_BOX (tbl), c, FALSE, FALSE, 0);
2794 }
2796 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2797 //Bold
2798 {
2799 GtkWidget *px = gtk_image_new_from_stock(GTK_STOCK_BOLD, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2800 GtkWidget *button = gtk_toggle_button_new ();
2801 gtk_container_add (GTK_CONTAINER (button), px);
2802 gtk_widget_show(button);
2803 gtk_tooltips_set_tip (tt, button, _("Bold"), NULL);
2804 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2805 gtk_widget_set_sensitive(button, TRUE);
2806 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
2807 }
2810 //Italic
2811 {
2812 GtkWidget *px = gtk_image_new_from_stock(GTK_STOCK_ITALIC, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2813 GtkWidget *button = gtk_toggle_button_new ();
2814 gtk_container_add (GTK_CONTAINER (button), px);
2815 gtk_widget_show(button);
2816 gtk_tooltips_set_tip (tt, button, _("Italics"), NULL);
2817 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2818 gtk_widget_set_sensitive(button, TRUE);
2819 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
2820 }
2822 //Underline
2823 {
2824 GtkWidget *px = gtk_image_new_from_stock(GTK_STOCK_UNDERLINE, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2825 GtkWidget *button = gtk_toggle_button_new ();
2826 gtk_container_add (GTK_CONTAINER (button), px);
2827 gtk_widget_show(button);
2828 gtk_tooltips_set_tip (tt, button, _("Underline"), NULL);
2829 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2830 gtk_widget_set_sensitive(button, FALSE);
2831 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
2832 }
2834 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2835 // align left
2836 {
2837 GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_LEFT, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2838 GtkWidget *b = group = gtk_radio_button_new (NULL);
2839 gtk_container_add (GTK_CONTAINER (b), px);
2840 gtk_tooltips_set_tip (tt, b, _("Align lines left"), NULL);
2841 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2842 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2843 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2844 }
2846 // align center
2847 {
2848 GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_CENTER, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2849 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
2850 gtk_container_add (GTK_CONTAINER (b), px);
2851 // TRANSLATORS: `Center' here is a verb.
2852 gtk_tooltips_set_tip (tt, b, _("Center lines"), NULL);
2853 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2854 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2855 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2856 }
2858 // align right
2859 {
2860 GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_RIGHT, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2861 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
2862 gtk_container_add (GTK_CONTAINER (b), px);
2863 gtk_tooltips_set_tip (tt, b, _("Align lines right"), NULL);
2864 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2865 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2866 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2867 }
2869 // full justification
2870 {
2871 GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_FILL, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2872 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
2873 gtk_container_add (GTK_CONTAINER (b), px);
2874 gtk_tooltips_set_tip (tt, b, _("Full justification"), NULL);
2875 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2876 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2877 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2878 }
2881 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2883 // horizontal
2884 {
2885 GtkWidget *px= sp_icon_new(Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_LR);
2886 GtkWidget *b = group = gtk_radio_button_new (NULL);
2887 gtk_container_add (GTK_CONTAINER (b), px);
2888 gtk_tooltips_set_tip (tt, b, _("Horizontal text"), NULL);
2889 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2890 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2891 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2892 }
2894 // vertical
2895 {
2896 GtkWidget *px = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_TB);
2897 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
2898 gtk_container_add (GTK_CONTAINER (b), px);
2899 gtk_tooltips_set_tip (tt, b, _("Vertical text"), NULL);
2900 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2901 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2902 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2903 }
2905 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2907 // letter spacing
2908 {
2909 {
2910 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LETTER_SPACING);
2911 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2912 gtk_container_add (GTK_CONTAINER (hb), image);
2913 gtk_widget_show(image);
2914 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
2915 }
2917 {
2918 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Spacing between letters"),
2919 "tools.text", "letter_spacing", 0.0,
2920 us, tbl, FALSE, NULL,
2921 -1000.0, 1000.0, 0.1, 0.1,
2922 sp_text_letter_changed, 0.1, 1);
2923 gtk_widget_set_size_request (hb, 45, 6);
2924 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
2925 }
2926 }
2928 // line spacing
2929 {
2930 {
2931 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LINE_SPACING);
2932 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2933 gtk_container_add (GTK_CONTAINER (hb), image);
2934 gtk_widget_show(image);
2935 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
2936 }
2938 {
2939 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Spacing between lines"),
2940 "tools.text", "line_spacing", 0,
2941 us, tbl, FALSE, NULL,
2942 -1000.0, 1000.0, 0.1, 0.1,
2943 sp_text_line_changed, 0.1, 1);
2944 gtk_widget_set_size_request (hb, 45, 0);
2945 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 3);
2946 }
2947 }
2949 {
2950 // horizontal kerning/vertical kerning units menu: create
2951 GtkWidget *us = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
2952 sp_unit_selector_setsize(us, AUX_OPTION_MENU_WIDTH, AUX_OPTION_MENU_HEIGHT);
2953 sp_unit_selector_set_unit(SP_UNIT_SELECTOR(us), desktop->namedview->doc_units);
2955 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2957 // horizontal kerning
2958 {
2959 {
2960 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_HORZ_KERN);
2961 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2962 gtk_container_add (GTK_CONTAINER (hb), image);
2963 gtk_widget_show(image);
2964 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
2965 }
2967 {
2968 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Horizontal kerning"),
2969 "tools.text", "horizontal_kerning", 0,
2970 us, tbl, FALSE, NULL,
2971 -100.00, 100.00, 0.01, 0.1,
2972 sp_text_horiz_kern_changed);
2973 gtk_widget_set_size_request (hb, 45, 0);
2974 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
2975 }
2976 }
2978 // vertical kerning
2979 {
2980 {
2981 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_VERT_KERN);
2982 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2983 gtk_container_add (GTK_CONTAINER (hb), image);
2984 gtk_widget_show(image);
2985 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
2986 }
2988 {
2989 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Vertical kerning"),
2990 "tools.text", "vertical_kerning", 0,
2991 us, tbl, FALSE, NULL,
2992 -100.00, 100.00, 0.01, 0.1,
2993 sp_text_vert_kern_changed);
2994 gtk_widget_set_size_request (hb, 45, 0);
2995 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 5);
2996 }
2997 }
2999 // add the units menu
3000 gtk_widget_show(us);
3001 gtk_box_pack_start(GTK_BOX(tbl), us, FALSE, FALSE, 1);
3002 gtk_object_set_data(GTK_OBJECT(tbl), "units", us);
3003 }
3005 // letter rotation
3006 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
3007 {
3008 {
3009 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_ROTATION);
3010 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3011 gtk_container_add (GTK_CONTAINER (hb), image);
3012 gtk_widget_show(image);
3013 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3014 }
3015 {
3016 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Letter rotation"),
3017 "tools.text", "letter_rotation", 0,
3018 us, tbl, FALSE, NULL,
3019 -180.0, 180.0, 0.1, 0.1,
3020 sp_text_letter_rotation_changed, 0.1, 1);
3021 gtk_widget_set_size_request (hb, 45, 0);
3022 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
3023 }
3024 // rotation degree label
3025 {
3026 GtkWidget *label = gtk_widget_new (GTK_TYPE_LABEL, "label", "\302\260", "xalign", 0.0, NULL);
3027 gtk_box_pack_start(GTK_BOX(tbl), label, FALSE, FALSE, 0);
3028 }
3029 }
3031 // Remove Manual Kerns
3032 {
3033 GtkWidget *px = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_REMOVE_KERNS);
3034 GtkWidget *button = gtk_button_new ();
3035 gtk_container_add (GTK_CONTAINER (button), px);
3036 gtk_widget_show(button);
3037 gtk_tooltips_set_tip (tt, button, _("Remove manual kerns"), NULL);
3038 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
3039 gtk_widget_set_sensitive(button, TRUE);
3040 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
3041 }
3043 */
3045 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
3046 swatch->setWatchedTool ("tools.text", true);
3047 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
3048 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
3050 gtk_widget_show_all(tbl);
3051 sp_set_font_size_smaller (tbl);
3053 return tbl;
3055 } // end of sp_text_toolbox_new()
3058 //#########################
3059 //## Connector Toolbox ##
3060 //#########################
3062 static void sp_connector_path_set_avoid(void)
3063 {
3064 cc_selection_set_avoid(true);
3065 }
3068 static void sp_connector_path_set_ignore(void)
3069 {
3070 cc_selection_set_avoid(false);
3071 }
3074 static void connector_spacing_changed(GtkAdjustment *adj, GtkWidget *tbl)
3075 {
3076 // quit if run by the _changed callbacks
3077 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
3078 return;
3079 }
3081 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl),
3082 "desktop");
3083 SPDocument *doc = sp_desktop_document(desktop);
3085 if (!sp_document_get_undo_sensitive(doc))
3086 {
3087 return;
3088 }
3090 // in turn, prevent callbacks from responding
3091 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
3093 Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
3095 sp_repr_set_css_double(repr, "inkscape:connector-spacing", adj->value);
3096 SP_OBJECT(desktop->namedview)->updateRepr();
3098 GSList *items = get_avoided_items(NULL, desktop->currentRoot(), desktop);
3099 for ( GSList const *iter = items ; iter != NULL ; iter = iter->next ) {
3100 SPItem *item = reinterpret_cast<SPItem *>(iter->data);
3101 NR::Matrix m = NR::identity();
3102 avoid_item_move(&m, item);
3103 }
3105 if (items) {
3106 g_slist_free(items);
3107 }
3109 sp_document_done(doc);
3111 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
3113 spinbutton_defocus(GTK_OBJECT(tbl));
3114 }
3117 static void connector_tb_event_attr_changed(Inkscape::XML::Node *repr,
3118 gchar const *name, gchar const *old_value, gchar const *new_value,
3119 bool is_interactive, gpointer data)
3120 {
3121 GtkWidget *tbl = GTK_WIDGET(data);
3123 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
3124 return;
3125 }
3126 if (strcmp(name, "inkscape:connector-spacing") != 0) {
3127 return;
3128 }
3130 GtkAdjustment *adj = (GtkAdjustment*)
3131 gtk_object_get_data(GTK_OBJECT(tbl), "spacing");
3132 gdouble spacing = defaultConnSpacing;
3133 sp_repr_get_double(repr, "inkscape:connector-spacing", &spacing);
3135 gtk_adjustment_set_value(adj, spacing);
3136 }
3139 static Inkscape::XML::NodeEventVector connector_tb_repr_events = {
3140 NULL, /* child_added */
3141 NULL, /* child_removed */
3142 connector_tb_event_attr_changed,
3143 NULL, /* content_changed */
3144 NULL /* order_changed */
3145 };
3148 static GtkWidget *
3149 sp_connector_toolbox_new(SPDesktop *desktop)
3150 {
3151 GtkTooltips *tt = gtk_tooltips_new();
3152 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
3154 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
3155 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
3157 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
3158 AUX_BETWEEN_BUTTON_GROUPS);
3160 sp_toolbox_button_new(tbl, Inkscape::ICON_SIZE_DECORATION,
3161 "connector_avoid", GTK_SIGNAL_FUNC(sp_connector_path_set_avoid),
3162 tt, _("Make connectors avoid selected objects"));
3164 sp_toolbox_button_new(tbl, Inkscape::ICON_SIZE_DECORATION,
3165 "connector_ignore", GTK_SIGNAL_FUNC(sp_connector_path_set_ignore),
3166 tt, _("Make connectors ignore selected objects"));
3168 // interval
3169 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
3170 AUX_BETWEEN_BUTTON_GROUPS);
3172 // Spacing spinbox
3173 {
3174 GtkWidget *object_spacing = sp_tb_spinbutton(_("Spacing:"),
3175 _("The amount of space left around objects by auto-routing connectors"),
3176 "tools.connector", "spacing", 10, NULL, tbl, TRUE,
3177 "inkscape:connector-spacing", 0, 100, 1.0, 10.0,
3178 connector_spacing_changed, 1, 0);
3180 gtk_box_pack_start(GTK_BOX(tbl), object_spacing, FALSE, FALSE,
3181 AUX_SPACING);
3182 }
3184 gtk_widget_show_all(tbl);
3185 sp_set_font_size_smaller (tbl);
3187 // Code to watch for changes to the connector-spacing attribute in
3188 // the XML.
3189 Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
3190 g_assert(repr != NULL);
3192 Inkscape::XML::Node *oldrepr = (Inkscape::XML::Node *)
3193 gtk_object_get_data(GTK_OBJECT(tbl), "repr");
3195 if (oldrepr) { // remove old listener
3196 sp_repr_remove_listener_by_data(oldrepr, tbl);
3197 Inkscape::GC::release(oldrepr);
3198 oldrepr = NULL;
3199 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
3200 }
3202 if (repr) {
3203 g_object_set_data(G_OBJECT(tbl), "repr", repr);
3204 Inkscape::GC::anchor(repr);
3205 sp_repr_add_listener(repr, &connector_tb_repr_events, tbl);
3206 sp_repr_synthesize_events(repr, &connector_tb_repr_events, tbl);
3207 }
3209 return tbl;
3211 } // end of sp_connector_toolbox_new()
3214 /*
3215 Local Variables:
3216 mode:c++
3217 c-file-style:"stroustrup"
3218 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
3219 indent-tabs-mode:nil
3220 fill-column:99
3221 End:
3222 */
3223 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :