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