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, Inkscape::IconSize 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, Inkscape::IconSize 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, Inkscape::IconSize 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, Inkscape::IconSize 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, Inkscape::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, Inkscape::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, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_join",
399 GTK_SIGNAL_FUNC(sp_node_path_edit_join), tt, _("Join selected endnodes"));
400 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_join_segment",
401 GTK_SIGNAL_FUNC(sp_node_path_edit_join_segment), tt, _("Join selected endnodes with a new segment"));
403 sp_toolbox_button_new(tb, Inkscape::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, Inkscape::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, Inkscape::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, Inkscape::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, Inkscape::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, Inkscape::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, Inkscape::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, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_OBJECT_TO_CURVE), view, tt);
432 sp_toolbox_button_normal_new_from_verb(tb, Inkscape::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, Inkscape::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, Inkscape::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, Inkscape::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, Inkscape::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, Inkscape::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, Inkscape::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, Inkscape::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, Inkscape::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, Inkscape::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, Inkscape::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, Inkscape::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 Inkscape::IconSize toolboxSize = shrinkLeft ? Inkscape::ICON_SIZE_SMALL_TOOLBAR : Inkscape::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 Inkscape::IconSize toolboxSize = shrinkTop ? Inkscape::ICON_SIZE_SMALL_TOOLBAR : Inkscape::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, double factor = 1.0)
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) * factor,
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_desktop_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_desktop_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_desktop_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_desktop_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_desktop_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_desktop_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_desktop_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_desktop_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_desktop_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_desktop_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_desktop_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_desktop_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_desktop_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_desktop_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_desktop_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 sp_repr_synthesize_events(repr, &star_tb_repr_events, tbl);
1090 }
1091 } else {
1092 // FIXME: implement averaging of all parameters for multiple selected stars
1093 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1094 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1095 }
1096 }
1099 static void
1100 sp_stb_defaults(GtkWidget *widget, GtkWidget *tbl)
1101 {
1102 // FIXME: in this and all other _default functions, set some flag telling the value_changed
1103 // callbacks to lump all the changes for all selected objects in one undo step
1105 GtkAdjustment *adj;
1107 // fixme: make settable in prefs!
1108 gint mag = 5;
1109 gdouble prop = 0.5;
1110 gboolean flat = FALSE;
1111 gdouble randomized = 0;
1112 gdouble rounded = 0;
1114 GtkWidget *fscb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "flat_checkbox");
1115 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), flat);
1116 GtkWidget *sb2 = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "prop_widget");
1117 gtk_widget_set_sensitive(GTK_WIDGET(sb2), !flat);
1119 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "magnitude");
1120 gtk_adjustment_set_value(adj, mag);
1121 gtk_adjustment_value_changed(adj);
1123 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "proportion");
1124 gtk_adjustment_set_value(adj, prop);
1125 gtk_adjustment_value_changed(adj);
1127 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rounded");
1128 gtk_adjustment_set_value(adj, rounded);
1129 gtk_adjustment_value_changed(adj);
1131 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "randomized");
1132 gtk_adjustment_set_value(adj, randomized);
1133 gtk_adjustment_value_changed(adj);
1135 spinbutton_defocus(GTK_OBJECT(tbl));
1136 }
1139 void
1140 sp_toolbox_add_label(GtkWidget *tbl, gchar const *title, bool wide)
1141 {
1142 GtkWidget *boxl = gtk_hbox_new(FALSE, 0);
1143 if (wide) gtk_widget_set_size_request(boxl, MODE_LABEL_WIDTH, -1);
1144 GtkWidget *l = gtk_label_new(NULL);
1145 gtk_label_set_markup(GTK_LABEL(l), title);
1146 gtk_box_pack_end(GTK_BOX(boxl), l, FALSE, FALSE, 0);
1147 gtk_box_pack_start(GTK_BOX(tbl), boxl, FALSE, FALSE, 0);
1148 gtk_object_set_data(GTK_OBJECT(tbl), "mode_label", l);
1149 }
1152 static GtkWidget *
1153 sp_star_toolbox_new(SPDesktop *desktop)
1154 {
1155 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1157 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1158 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1160 GtkTooltips *tt = gtk_tooltips_new();
1162 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1164 gchar const *flatsidedstr = NULL;
1166 /* Flatsided checkbox */
1167 {
1168 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1169 GtkWidget *fscb = gtk_check_button_new_with_label(_("Polygon"));
1170 gtk_widget_set_sensitive(GTK_WIDGET(fscb), TRUE);
1171 flatsidedstr = prefs_get_string_attribute("tools.shapes.star", "isflatsided");
1172 if (!flatsidedstr || (flatsidedstr && !strcmp(flatsidedstr, "false")))
1173 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), FALSE);
1174 else
1175 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), TRUE);
1176 gtk_tooltips_set_tip(tt, fscb, _("Regular polygon (with one handle) instead of a star"), NULL);
1177 gtk_widget_show(fscb);
1178 gtk_object_set_data(GTK_OBJECT(tbl), "flat_checkbox", fscb);
1179 gtk_container_add(GTK_CONTAINER(hb), fscb);
1180 g_signal_connect(G_OBJECT(fscb), "toggled", GTK_SIGNAL_FUNC(sp_stb_sides_flat_state_changed ), tbl);
1181 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_SPACING);
1182 }
1184 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
1186 /* Magnitude */
1187 {
1188 GtkWidget *hb = sp_tb_spinbutton(_("Corners:"), _("Number of corners of a polygon or star"),
1189 "tools.shapes.star", "magnitude", 3,
1190 NULL, tbl, TRUE, "altx-star",
1191 3, 1024, 1, 1,
1192 sp_stb_magnitude_value_changed, 1, 0);
1193 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1194 }
1196 /* Spoke ratio */
1197 {
1198 GtkWidget *hb = sp_tb_spinbutton(_("Spoke ratio:"),
1199 // TRANSLATORS: Tip radius of a star is the distance from the center to the farthest handle.
1200 // Base radius is the same for the closest handle.
1201 _("Base radius to tip radius ratio"),
1202 "tools.shapes.star", "proportion", 0.5,
1203 NULL, tbl, FALSE, NULL,
1204 0.01, 1.0, 0.01, 0.1,
1205 sp_stb_proportion_value_changed);
1206 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1207 g_object_set_data(G_OBJECT(tbl), "prop_widget", hb);
1208 if (!flatsidedstr || (flatsidedstr && !strcmp(flatsidedstr, "false")))
1209 gtk_widget_set_sensitive(GTK_WIDGET(hb), TRUE);
1210 else
1211 gtk_widget_set_sensitive(GTK_WIDGET(hb), FALSE);
1212 }
1214 /* Roundedness */
1215 {
1216 GtkWidget *hb = sp_tb_spinbutton(_("Rounded:"), _("How much rounded are the corners (0 for sharp)"),
1217 "tools.shapes.star", "rounded", 0.0,
1218 NULL, tbl, FALSE, NULL,
1219 -100.0, 100.0, 0.01, 0.1,
1220 sp_stb_rounded_value_changed);
1221 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1222 }
1224 /* Randomization */
1225 {
1226 GtkWidget *hb = sp_tb_spinbutton(_("Randomized:"), _("Scatter randomly the corners and angles"),
1227 "tools.shapes.star", "randomized", 0.0,
1228 NULL, tbl, FALSE, NULL,
1229 -10.0, 10.0, 0.001, 0.01,
1230 sp_stb_randomized_value_changed, 0.1, 3);
1231 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1232 }
1234 aux_toolbox_space(tbl, AUX_SPACING);
1236 /* Reset */
1237 {
1238 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1239 GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
1240 gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
1241 gtk_widget_show(b);
1242 gtk_container_add(GTK_CONTAINER(hb), b);
1243 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_stb_defaults), tbl);
1244 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_SPACING);
1245 }
1247 gtk_widget_show_all(tbl);
1248 sp_set_font_size_smaller (tbl);
1250 sigc::connection *connection = new sigc::connection(
1251 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_star_toolbox_selection_changed), (GtkObject *)tbl))
1252 );
1253 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1255 return tbl;
1256 }
1259 //########################
1260 //## Rect ##
1261 //########################
1263 static void
1264 sp_rtb_sensitivize (GtkWidget *tbl)
1265 {
1266 GtkAdjustment *adj1 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "rx"));
1267 GtkAdjustment *adj2 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "ry"));
1268 GtkWidget *not_rounded = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "not_rounded");
1270 if (adj1->value == 0 && adj2->value == 0 && gtk_object_get_data(GTK_OBJECT(tbl), "single")) { // only for a single selected rect (for now)
1271 gtk_widget_set_sensitive(GTK_WIDGET(not_rounded), FALSE);
1272 } else {
1273 gtk_widget_set_sensitive(GTK_WIDGET(not_rounded), TRUE);
1274 }
1275 }
1278 static void
1279 sp_rtb_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name,
1280 void (*setter)(SPRect *, gdouble))
1281 {
1282 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
1284 GtkWidget *us = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tbl), "units");
1285 SPUnit const *unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(us));
1287 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1288 prefs_set_double_attribute("tools.shapes.rect", value_name, sp_units_get_pixels(adj->value, *unit));
1289 }
1291 // quit if run by the attr_changed listener
1292 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1293 return;
1294 }
1296 // in turn, prevent listener from responding
1297 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1299 bool modmade = false;
1300 Inkscape::Selection *selection = sp_desktop_selection(desktop);
1301 for (GSList const *items = selection->itemList(); items != NULL; items = items->next) {
1302 if (SP_IS_RECT(items->data)) {
1303 if (adj->value != 0) {
1304 setter(SP_RECT(items->data), sp_units_get_pixels(adj->value, *unit));
1305 } else {
1306 SP_OBJECT_REPR(items->data)->setAttribute(value_name, NULL);
1307 }
1308 modmade = true;
1309 }
1310 }
1312 sp_rtb_sensitivize (tbl);
1314 if (modmade) {
1315 sp_document_done(sp_desktop_document(desktop));
1316 }
1318 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1320 // defocus spinbuttons by moving focus to the canvas, unless "stay" is on
1321 spinbutton_defocus(GTK_OBJECT(tbl));
1322 }
1324 static void
1325 sp_rtb_rx_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1326 {
1327 sp_rtb_value_changed(adj, tbl, "rx", sp_rect_set_visible_rx);
1328 }
1330 static void
1331 sp_rtb_ry_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1332 {
1333 sp_rtb_value_changed(adj, tbl, "ry", sp_rect_set_visible_ry);
1334 }
1336 static void
1337 sp_rtb_width_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1338 {
1339 sp_rtb_value_changed(adj, tbl, "width", sp_rect_set_visible_width);
1340 }
1342 static void
1343 sp_rtb_height_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1344 {
1345 sp_rtb_value_changed(adj, tbl, "height", sp_rect_set_visible_height);
1346 }
1350 static void
1351 sp_rtb_defaults( GtkWidget *widget, GtkObject *obj)
1352 {
1353 GtkWidget *tbl = GTK_WIDGET(obj);
1355 GtkAdjustment *adj;
1357 adj = (GtkAdjustment*)gtk_object_get_data(obj, "rx");
1358 gtk_adjustment_set_value(adj, 0.0);
1359 // this is necessary if the previous value was 0, but we still need to run the callback to change all selected objects
1360 gtk_adjustment_value_changed(adj);
1362 adj = (GtkAdjustment*)gtk_object_get_data(obj, "ry");
1363 gtk_adjustment_set_value(adj, 0.0);
1364 gtk_adjustment_value_changed(adj);
1366 sp_rtb_sensitivize (tbl);
1368 spinbutton_defocus(GTK_OBJECT(tbl));
1369 }
1371 static void rect_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1372 gchar const *old_value, gchar const *new_value,
1373 bool is_interactive, gpointer data)
1374 {
1375 GtkWidget *tbl = GTK_WIDGET(data);
1377 // quit if run by the _changed callbacks
1378 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1379 return;
1380 }
1382 // in turn, prevent callbacks from responding
1383 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1385 GtkWidget *us = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tbl), "units");
1386 SPUnit const *unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(us));
1388 SPItem *item = SP_ITEM(g_object_get_data(G_OBJECT(tbl), "item"));
1389 if (SP_IS_RECT(item)) {
1390 {
1391 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rx");
1392 gdouble rx = sp_rect_get_visible_rx(SP_RECT(item));
1393 gtk_adjustment_set_value(adj, sp_pixels_get_units(rx, *unit));
1394 }
1396 {
1397 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "ry");
1398 gdouble ry = sp_rect_get_visible_ry(SP_RECT(item));
1399 gtk_adjustment_set_value(adj, sp_pixels_get_units(ry, *unit));
1400 }
1402 {
1403 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "width");
1404 gdouble width = sp_rect_get_visible_width (SP_RECT(item));
1405 gtk_adjustment_set_value(adj, sp_pixels_get_units(width, *unit));
1406 }
1408 {
1409 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "height");
1410 gdouble height = sp_rect_get_visible_height (SP_RECT(item));
1411 gtk_adjustment_set_value(adj, sp_pixels_get_units(height, *unit));
1412 }
1413 }
1415 sp_rtb_sensitivize (tbl);
1417 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1418 }
1421 static Inkscape::XML::NodeEventVector rect_tb_repr_events = {
1422 NULL, /* child_added */
1423 NULL, /* child_removed */
1424 rect_tb_event_attr_changed,
1425 NULL, /* content_changed */
1426 NULL /* order_changed */
1427 };
1429 /**
1430 * \param selection should not be NULL.
1431 */
1432 static void
1433 sp_rect_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1434 {
1435 int n_selected = 0;
1436 Inkscape::XML::Node *repr = NULL;
1437 SPItem *item = NULL;
1438 Inkscape::XML::Node *oldrepr = NULL;
1440 for (GSList const *items = selection->itemList();
1441 items != NULL;
1442 items = items->next) {
1443 if (SP_IS_RECT((SPItem *) items->data)) {
1444 n_selected++;
1445 item = (SPItem *) items->data;
1446 repr = SP_OBJECT_REPR(item);
1447 }
1448 }
1450 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
1452 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(FALSE));
1454 if (n_selected == 0) {
1455 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
1457 GtkWidget *w = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "width_sb");
1458 gtk_widget_set_sensitive(w, FALSE);
1459 GtkWidget *h = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "height_sb");
1460 gtk_widget_set_sensitive(h, FALSE);
1462 } else if (n_selected == 1) {
1463 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1464 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
1466 GtkWidget *w = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "width_sb");
1467 gtk_widget_set_sensitive(w, TRUE);
1468 GtkWidget *h = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "height_sb");
1469 gtk_widget_set_sensitive(h, TRUE);
1471 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1472 if (oldrepr) { // remove old listener
1473 sp_repr_remove_listener_by_data(oldrepr, tbl);
1474 Inkscape::GC::release(oldrepr);
1475 oldrepr = 0;
1476 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1477 }
1478 if (repr) {
1479 g_object_set_data(G_OBJECT(tbl), "repr", repr);
1480 g_object_set_data(G_OBJECT(tbl), "item", item);
1481 Inkscape::GC::anchor(repr);
1482 sp_repr_add_listener(repr, &rect_tb_repr_events, tbl);
1483 sp_repr_synthesize_events(repr, &rect_tb_repr_events, tbl);
1484 }
1485 } else {
1486 // FIXME: implement averaging of all parameters for multiple selected
1487 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1488 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1489 sp_rtb_sensitivize (GTK_WIDGET(tbl));
1490 }
1491 }
1494 static GtkWidget *
1495 sp_rect_toolbox_new(SPDesktop *desktop)
1496 {
1497 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1499 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1500 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1502 GtkTooltips *tt = gtk_tooltips_new();
1504 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1506 // rx/ry units menu: create
1507 GtkWidget *us = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
1508 sp_unit_selector_setsize(us, AUX_OPTION_MENU_WIDTH, AUX_OPTION_MENU_HEIGHT);
1509 sp_unit_selector_set_unit(SP_UNIT_SELECTOR(us), desktop->namedview->doc_units);
1510 // fixme: add % meaning per cent of the width/height
1512 /* W */
1513 {
1514 GtkWidget *hb = sp_tb_spinbutton(_("W:"), _("Width of rectangle"),
1515 "tools.shapes.rect", "width", 0,
1516 us, tbl, TRUE, "altx-rect",
1517 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1518 sp_rtb_width_value_changed);
1519 gtk_object_set_data(GTK_OBJECT(tbl), "width_sb", hb);
1520 gtk_widget_set_sensitive(hb, FALSE);
1521 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1522 }
1524 /* H */
1525 {
1526 GtkWidget *hb = sp_tb_spinbutton(_("H:"), _("Height of rectangle"),
1527 "tools.shapes.rect", "height", 0,
1528 us, tbl, FALSE, NULL,
1529 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1530 sp_rtb_height_value_changed);
1531 gtk_object_set_data(GTK_OBJECT(tbl), "height_sb", hb);
1532 gtk_widget_set_sensitive(hb, FALSE);
1533 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1534 }
1536 /* rx */
1537 {
1538 GtkWidget *hb = sp_tb_spinbutton(_("Rx:"), _("Horizontal radius of rounded corners"),
1539 "tools.shapes.rect", "rx", 0,
1540 us, tbl, FALSE, NULL,
1541 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1542 sp_rtb_rx_value_changed);
1543 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1544 }
1546 /* ry */
1547 {
1548 GtkWidget *hb = sp_tb_spinbutton(_("Ry:"), _("Vertical radius of rounded corners"),
1549 "tools.shapes.rect", "ry", 0,
1550 us, tbl, FALSE, NULL,
1551 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1552 sp_rtb_ry_value_changed);
1553 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1554 }
1556 // add the units menu
1557 gtk_widget_show(us);
1558 gtk_box_pack_start(GTK_BOX(tbl), us, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1559 gtk_object_set_data(GTK_OBJECT(tbl), "units", us);
1561 /* Reset */
1562 {
1563 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1564 GtkWidget *b = gtk_button_new_with_label(_("Not rounded"));
1565 gtk_object_set_data(GTK_OBJECT(tbl), "not_rounded", b);
1566 gtk_tooltips_set_tip(tt, b, _("Make corners sharp"), NULL);
1567 gtk_widget_show(b);
1568 gtk_container_add(GTK_CONTAINER(hb), b);
1569 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_rtb_defaults), tbl);
1570 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1571 }
1573 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
1574 sp_rtb_sensitivize (tbl);
1576 gtk_widget_show_all(tbl);
1577 sp_set_font_size_smaller (tbl);
1579 sigc::connection *connection = new sigc::connection(
1580 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_rect_toolbox_selection_changed), (GtkObject *)tbl))
1581 );
1582 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1584 return tbl;
1585 }
1587 //########################
1588 //## Spiral ##
1589 //########################
1591 static void
1592 sp_spl_tb_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name)
1593 {
1594 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
1596 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1597 prefs_set_double_attribute("tools.shapes.spiral", value_name, adj->value);
1598 }
1600 // quit if run by the attr_changed listener
1601 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1602 return;
1603 }
1605 // in turn, prevent listener from responding
1606 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1608 gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
1610 bool modmade = false;
1611 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
1612 items != NULL;
1613 items = items->next)
1614 {
1615 if (SP_IS_SPIRAL((SPItem *) items->data)) {
1616 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
1617 sp_repr_set_svg_double( repr, namespaced_name, adj->value );
1618 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
1619 modmade = true;
1620 }
1621 }
1623 g_free(namespaced_name);
1625 if (modmade) {
1626 sp_document_done(sp_desktop_document(desktop));
1627 }
1629 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1631 spinbutton_defocus(GTK_OBJECT(tbl));
1632 }
1634 static void
1635 sp_spl_tb_revolution_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1636 {
1637 sp_spl_tb_value_changed(adj, tbl, "revolution");
1638 }
1640 static void
1641 sp_spl_tb_expansion_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1642 {
1643 sp_spl_tb_value_changed(adj, tbl, "expansion");
1644 }
1646 static void
1647 sp_spl_tb_t0_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1648 {
1649 sp_spl_tb_value_changed(adj, tbl, "t0");
1650 }
1652 static void
1653 sp_spl_tb_defaults(GtkWidget *widget, GtkObject *obj)
1654 {
1655 GtkWidget *tbl = GTK_WIDGET(obj);
1657 GtkAdjustment *adj;
1659 // fixme: make settable
1660 gdouble rev = 5;
1661 gdouble exp = 1.0;
1662 gdouble t0 = 0.0;
1664 adj = (GtkAdjustment*)gtk_object_get_data(obj, "revolution");
1665 gtk_adjustment_set_value(adj, rev);
1666 gtk_adjustment_value_changed(adj);
1668 adj = (GtkAdjustment*)gtk_object_get_data(obj, "expansion");
1669 gtk_adjustment_set_value(adj, exp);
1670 gtk_adjustment_value_changed(adj);
1672 adj = (GtkAdjustment*)gtk_object_get_data(obj, "t0");
1673 gtk_adjustment_set_value(adj, t0);
1674 gtk_adjustment_value_changed(adj);
1676 spinbutton_defocus(GTK_OBJECT(tbl));
1677 }
1680 static void spiral_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1681 gchar const *old_value, gchar const *new_value,
1682 bool is_interactive, gpointer data)
1683 {
1684 GtkWidget *tbl = GTK_WIDGET(data);
1686 // quit if run by the _changed callbacks
1687 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1688 return;
1689 }
1691 // in turn, prevent callbacks from responding
1692 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1694 GtkAdjustment *adj;
1695 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "revolution");
1696 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:revolution", 3.0)));
1698 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "expansion");
1699 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:expansion", 1.0)));
1701 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "t0");
1702 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:t0", 0.0)));
1704 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1705 }
1708 static Inkscape::XML::NodeEventVector spiral_tb_repr_events = {
1709 NULL, /* child_added */
1710 NULL, /* child_removed */
1711 spiral_tb_event_attr_changed,
1712 NULL, /* content_changed */
1713 NULL /* order_changed */
1714 };
1716 static void
1717 sp_spiral_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1718 {
1719 int n_selected = 0;
1720 Inkscape::XML::Node *repr = NULL;
1721 Inkscape::XML::Node *oldrepr = NULL;
1723 for (GSList const *items = selection->itemList();
1724 items != NULL;
1725 items = items->next)
1726 {
1727 if (SP_IS_SPIRAL((SPItem *) items->data)) {
1728 n_selected++;
1729 repr = SP_OBJECT_REPR((SPItem *) items->data);
1730 }
1731 }
1733 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
1735 if (n_selected == 0) {
1736 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
1737 } else if (n_selected == 1) {
1738 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1740 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1741 if (oldrepr) { // remove old listener
1742 sp_repr_remove_listener_by_data(oldrepr, tbl);
1743 Inkscape::GC::release(oldrepr);
1744 oldrepr = 0;
1745 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1746 }
1748 if (repr) {
1749 g_object_set_data(G_OBJECT(tbl), "repr", repr);
1750 Inkscape::GC::anchor(repr);
1751 sp_repr_add_listener(repr, &spiral_tb_repr_events, tbl);
1752 sp_repr_synthesize_events(repr, &spiral_tb_repr_events, tbl);
1753 }
1754 } else {
1755 // FIXME: implement averaging of all parameters for multiple selected
1756 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1757 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1758 }
1759 }
1762 static GtkWidget *
1763 sp_spiral_toolbox_new(SPDesktop *desktop)
1764 {
1765 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1766 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1767 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1769 GtkTooltips *tt = gtk_tooltips_new();
1771 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1773 /* Revolution */
1774 {
1775 GtkWidget *hb = sp_tb_spinbutton(_("Turns:"), _("Number of revolutions"),
1776 "tools.shapes.spiral", "revolution", 3.0,
1777 NULL, tbl, TRUE, "altx-spiral",
1778 0.01, 1024.0, 0.1, 1.0,
1779 sp_spl_tb_revolution_value_changed, 1, 2);
1780 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1781 }
1783 /* Expansion */
1784 {
1785 GtkWidget *hb = sp_tb_spinbutton(_("Divergence:"), _("How much denser/sparser are outer revolutions; 1 = uniform"),
1786 "tools.shapes.spiral", "expansion", 1.0,
1787 NULL, tbl, FALSE, NULL,
1788 0.0, 1000.0, 0.01, 1.0,
1789 sp_spl_tb_expansion_value_changed);
1790 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1791 }
1793 /* T0 */
1794 {
1795 GtkWidget *hb = sp_tb_spinbutton(_("Inner radius:"), _("Radius of the innermost revolution (relative to the spiral size)"),
1796 "tools.shapes.spiral", "t0", 0.0,
1797 NULL, tbl, FALSE, NULL,
1798 0.0, 0.999, 0.01, 1.0,
1799 sp_spl_tb_t0_value_changed);
1800 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1801 }
1803 aux_toolbox_space(tbl, AUX_SPACING);
1805 /* Reset */
1806 {
1807 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1808 GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
1809 gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
1810 gtk_widget_show(b);
1811 gtk_container_add(GTK_CONTAINER(hb), b);
1812 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_spl_tb_defaults), tbl);
1813 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1814 }
1816 gtk_widget_show_all(tbl);
1817 sp_set_font_size_smaller (tbl);
1819 sigc::connection *connection = new sigc::connection(
1820 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_spiral_toolbox_selection_changed), (GtkObject *)tbl))
1821 );
1822 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1824 return tbl;
1825 }
1828 //########################
1829 //## Calligraphy ##
1830 //########################
1832 static void
1833 sp_ddc_mass_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1834 {
1835 prefs_set_double_attribute("tools.calligraphic", "mass", adj->value);
1836 spinbutton_defocus(GTK_OBJECT(tbl));
1837 }
1839 static void
1840 sp_ddc_drag_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1841 {
1842 prefs_set_double_attribute("tools.calligraphic", "drag", adj->value);
1843 spinbutton_defocus(GTK_OBJECT(tbl));
1844 }
1846 static void
1847 sp_ddc_angle_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1848 {
1849 prefs_set_double_attribute("tools.calligraphic", "angle", adj->value);
1850 spinbutton_defocus(GTK_OBJECT(tbl));
1851 }
1853 static void
1854 sp_ddc_width_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1855 {
1856 prefs_set_double_attribute("tools.calligraphic", "width", adj->value * 0.01);
1857 spinbutton_defocus(GTK_OBJECT(tbl));
1858 }
1860 static void
1861 sp_ddc_velthin_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1862 {
1863 prefs_set_double_attribute("tools.calligraphic", "thinning", adj->value);
1864 spinbutton_defocus(GTK_OBJECT(tbl));
1865 }
1867 static void
1868 sp_ddc_flatness_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1869 {
1870 prefs_set_double_attribute("tools.calligraphic", "flatness", adj->value);
1871 spinbutton_defocus(GTK_OBJECT(tbl));
1872 }
1874 static void
1875 sp_ddc_tremor_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1876 {
1877 prefs_set_double_attribute("tools.calligraphic", "tremor", adj->value);
1878 spinbutton_defocus(GTK_OBJECT(tbl));
1879 }
1881 static void
1882 sp_ddc_pressure_state_changed(GtkWidget *button, gpointer data)
1883 {
1884 prefs_set_int_attribute ("tools.calligraphic", "usepressure", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0);
1885 }
1887 static void
1888 sp_ddc_tilt_state_changed(GtkWidget *button, GtkWidget *calligraphy_angle)
1889 {
1890 prefs_set_int_attribute ("tools.calligraphic", "usetilt", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0);
1892 gtk_widget_set_sensitive(GTK_WIDGET(calligraphy_angle), !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
1893 }
1895 static void sp_ddc_defaults(GtkWidget *, GtkWidget *tbl)
1896 {
1897 // FIXME: make defaults settable via Inkscape Options
1898 struct KeyValue {
1899 char const *key;
1900 double value;
1901 } const key_values[] = {
1902 {"mass", 0.02},
1903 {"drag", 1.0},
1904 {"angle", 30.0},
1905 {"width", 15},
1906 {"thinning", 0.1},
1907 {"tremor", 0.0},
1908 {"flatness", 0.9}
1909 };
1911 for (unsigned i = 0; i < G_N_ELEMENTS(key_values); ++i) {
1912 KeyValue const &kv = key_values[i];
1913 GtkAdjustment &adj = *static_cast<GtkAdjustment *>(gtk_object_get_data(GTK_OBJECT(tbl), kv.key));
1914 gtk_adjustment_set_value(&adj, kv.value);
1915 }
1917 spinbutton_defocus(GTK_OBJECT(tbl));
1918 }
1920 static GtkWidget *
1921 sp_calligraphy_toolbox_new(SPDesktop *desktop)
1922 {
1923 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1924 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1925 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1927 GtkTooltips *tt = gtk_tooltips_new();
1928 GtkWidget *calligraphy_angle;
1930 // interval
1931 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1933 /* Width */
1934 {
1935 GtkWidget *hb = sp_tb_spinbutton(_("Width:"), _("The width of the calligraphic pen (relative to the visible canvas area)"),
1936 "tools.calligraphic", "width", 15,
1937 NULL, tbl, TRUE, "altx-calligraphy",
1938 1, 100, 1.0, 10.0,
1939 sp_ddc_width_value_changed, 0.01, 0, 100);
1940 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1941 }
1943 /* Thinning */
1944 {
1945 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)"),
1946 "tools.calligraphic", "thinning", 0.1,
1947 NULL, tbl, FALSE, NULL,
1948 -1.0, 1.0, 0.01, 0.1,
1949 sp_ddc_velthin_value_changed, 0.01, 2);
1950 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1951 }
1953 // interval
1954 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1956 /* Angle */
1957 {
1958 calligraphy_angle = sp_tb_spinbutton(_("Angle:"), _("The angle of the pen's nib (in degrees; 0 = horizontal; has no effect if fixation = 0)"),
1959 "tools.calligraphic", "angle", 30,
1960 NULL, tbl, TRUE, "calligraphy-angle",
1961 -90.0, 90.0, 1.0, 10.0,
1962 sp_ddc_angle_value_changed, 1, 0);
1963 gtk_box_pack_start(GTK_BOX(tbl), calligraphy_angle, FALSE, FALSE, AUX_SPACING);
1964 }
1966 /* Fixation */
1967 {
1968 GtkWidget *hb = sp_tb_spinbutton(_("Fixation:"), _("How fixed is the pen angle (0 = always perpendicular to stroke direction, 1 = fixed)"),
1969 "tools.calligraphic", "flatness", 0.9,
1970 NULL, tbl, FALSE, NULL,
1971 0.0, 1.0, 0.01, 0.1,
1972 sp_ddc_flatness_value_changed, 0.01, 2);
1973 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1974 }
1976 // interval
1977 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1979 /* Tremor */
1980 {
1981 GtkWidget *hb = sp_tb_spinbutton(_("Tremor:"), _("How uneven or trembling is the pen stroke"),
1982 "tools.calligraphic", "tremor", 0.0,
1983 NULL, tbl, FALSE, NULL,
1984 0.0, 1.0, 0.01, 0.1,
1985 sp_ddc_tremor_value_changed, 0.01, 2);
1986 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1987 }
1988 /* Mass */
1989 {
1990 GtkWidget *hb = sp_tb_spinbutton(_("Mass:"), _("How much inertia affects the movement of the pen"),
1991 "tools.calligraphic", "mass", 0.02,
1992 NULL, tbl, FALSE, NULL,
1993 0.0, 1.0, 0.01, 0.1,
1994 sp_ddc_mass_value_changed, 0.01, 2);
1995 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1996 }
1998 /* Drag */
1999 {
2000 // TRANSLATORS: "drag" means "resistance" here
2001 GtkWidget *hb = sp_tb_spinbutton(_("Drag:"), _("How much resistance affects the movement of the pen"),
2002 "tools.calligraphic", "drag", 1,
2003 NULL, tbl, FALSE, NULL,
2004 0.0, 1.0, 0.01, 0.1,
2005 sp_ddc_drag_value_changed, 0.01, 2);
2006 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2007 }
2009 // interval
2010 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2012 GtkWidget *cvbox = gtk_vbox_new (FALSE, 0);
2013 GtkWidget *cbox = gtk_hbox_new (FALSE, 0);
2015 /* Use Pressure button */
2016 {
2017 GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
2018 SP_BUTTON_TYPE_TOGGLE,
2019 NULL,
2020 "use_pressure",
2021 _("Use the pressure of the input device to alter the width of the pen"),
2022 tt);
2023 g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (sp_ddc_pressure_state_changed), NULL);
2024 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.calligraphic", "usepressure", 1));
2025 gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
2026 }
2028 /* Use Tilt button */
2029 {
2030 GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
2031 SP_BUTTON_TYPE_TOGGLE,
2032 NULL,
2033 "use_tilt",
2034 _("Use the tilt of the input device to alter the angle of the pen's nib"),
2035 tt);
2036 g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (sp_ddc_tilt_state_changed), calligraphy_angle);
2037 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.calligraphic", "usetilt", 1));
2038 gtk_widget_set_sensitive(GTK_WIDGET(calligraphy_angle), !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
2039 gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
2040 }
2042 gtk_box_pack_start(GTK_BOX(cvbox), cbox, TRUE, FALSE, 0);
2043 gtk_box_pack_start(GTK_BOX(tbl), cvbox, FALSE, FALSE, 0);
2045 /* Reset */
2046 {
2047 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2048 GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
2049 gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
2050 gtk_widget_show(b);
2051 gtk_container_add(GTK_CONTAINER(hb), b);
2052 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_ddc_defaults), tbl);
2053 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2054 }
2056 /*
2057 // Tablet features
2058 {
2059 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2060 GtkWidget *fscb = gtk_check_button_new_with_label(_("Tablet"));
2061 gtk_widget_set_sensitive(GTK_WIDGET(fscb), TRUE);
2066 gtk_tooltips_set_tip(tt, fscb, _("Enable/Disable drawing tablet features"), NULL);
2067 gtk_widget_show(fscb);
2068 gtk_object_set_data(GTK_OBJECT(tbl), "flat_checkbox", fscb);
2069 gtk_container_add(GTK_CONTAINER(hb), fscb);
2071 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_SPACING);
2072 }
2073 */
2075 gtk_widget_show_all(tbl);
2076 sp_set_font_size_smaller (tbl);
2078 return tbl;
2079 }
2082 //########################
2083 //## Circle / Arc ##
2084 //########################
2086 static void
2087 sp_arctb_sensitivize (GtkWidget *tbl, double v1, double v2)
2088 {
2089 GtkWidget *ocb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "open_checkbox");
2090 GtkWidget *make_whole = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "make_whole");
2092 if (v1 == 0 && v2 == 0) {
2093 if (gtk_object_get_data(GTK_OBJECT(tbl), "single")) { // only for a single selected ellipse (for now)
2094 gtk_widget_set_sensitive(GTK_WIDGET(ocb), FALSE);
2095 gtk_widget_set_sensitive(GTK_WIDGET(make_whole), FALSE);
2096 }
2097 } else {
2098 gtk_widget_set_sensitive(GTK_WIDGET(ocb), TRUE);
2099 gtk_widget_set_sensitive(GTK_WIDGET(make_whole), TRUE);
2100 }
2101 }
2103 static void
2104 sp_arctb_startend_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name, gchar const *other_name)
2105 {
2106 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2108 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2109 prefs_set_double_attribute("tools.shapes.arc", value_name, (adj->value * M_PI)/ 180);
2110 }
2112 // quit if run by the attr_changed listener
2113 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2114 return;
2115 }
2117 // in turn, prevent listener from responding
2118 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2120 gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
2122 bool modmade = false;
2123 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2124 items != NULL;
2125 items = items->next)
2126 {
2127 SPItem *item = SP_ITEM(items->data);
2129 if (SP_IS_ARC(item) && SP_IS_GENERICELLIPSE(item)) {
2131 SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
2132 SPArc *arc = SP_ARC(item);
2134 if (!strcmp(value_name, "start"))
2135 ge->start = (adj->value * M_PI)/ 180;
2136 else
2137 ge->end = (adj->value * M_PI)/ 180;
2139 sp_genericellipse_normalize(ge);
2140 ((SPObject *)arc)->updateRepr();
2141 ((SPObject *)arc)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
2143 modmade = true;
2144 }
2145 }
2147 g_free(namespaced_name);
2149 GtkAdjustment *other = (GtkAdjustment *)gtk_object_get_data(GTK_OBJECT(tbl), other_name);
2151 sp_arctb_sensitivize (tbl, adj->value, other->value);
2153 if (modmade) {
2154 sp_document_maybe_done(sp_desktop_document(desktop), value_name);
2155 }
2157 // defocus spinbuttons by moving focus to the canvas, unless "stay" is on
2158 spinbutton_defocus(GTK_OBJECT(tbl));
2160 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2161 }
2164 static void
2165 sp_arctb_start_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
2166 {
2167 sp_arctb_startend_value_changed(adj, tbl, "start", "end");
2168 }
2170 static void
2171 sp_arctb_end_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
2172 {
2173 sp_arctb_startend_value_changed(adj, tbl, "end", "start");
2174 }
2176 static void
2177 sp_arctb_open_state_changed(GtkWidget *widget, GtkObject *tbl)
2178 {
2179 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2181 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2182 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
2183 prefs_set_string_attribute("tools.shapes.arc", "open", "true");
2184 } else {
2185 prefs_set_string_attribute("tools.shapes.arc", "open", NULL);
2186 }
2187 }
2189 // quit if run by the attr_changed listener
2190 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2191 return;
2192 }
2194 // in turn, prevent listener from responding
2195 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2197 bool modmade = false;
2199 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
2200 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2201 items != NULL;
2202 items = items->next)
2203 {
2204 if (SP_IS_ARC((SPItem *) items->data)) {
2205 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2206 repr->setAttribute("sodipodi:open", "true");
2207 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
2208 modmade = true;
2209 }
2210 }
2211 } else {
2212 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2213 items != NULL;
2214 items = items->next)
2215 {
2216 if (SP_IS_ARC((SPItem *) items->data)) {
2217 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2218 repr->setAttribute("sodipodi:open", NULL);
2219 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
2220 modmade = true;
2221 }
2222 }
2223 }
2225 if (modmade) {
2226 sp_document_done(sp_desktop_document(desktop));
2227 }
2229 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2231 spinbutton_defocus(GTK_OBJECT(tbl));
2232 }
2234 static void sp_arctb_defaults(GtkWidget *, GtkObject *obj)
2235 {
2236 GtkWidget *tbl = GTK_WIDGET(obj);
2238 GtkAdjustment *adj;
2239 adj = (GtkAdjustment*)gtk_object_get_data(obj, "start");
2240 gtk_adjustment_set_value(adj, 0.0);
2241 gtk_adjustment_value_changed(adj);
2243 adj = (GtkAdjustment*)gtk_object_get_data(obj, "end");
2244 gtk_adjustment_set_value(adj, 0.0);
2245 gtk_adjustment_value_changed(adj);
2247 spinbutton_defocus(GTK_OBJECT(tbl));
2248 }
2250 static void arc_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
2251 gchar const *old_value, gchar const *new_value,
2252 bool is_interactive, gpointer data)
2253 {
2254 GtkWidget *tbl = GTK_WIDGET(data);
2256 // quit if run by the _changed callbacks
2257 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2258 return;
2259 }
2261 // in turn, prevent callbacks from responding
2262 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2264 gdouble start = sp_repr_get_double_attribute(repr, "sodipodi:start", 0.0);
2265 gdouble end = sp_repr_get_double_attribute(repr, "sodipodi:end", 0.0);
2267 GtkAdjustment *adj1,*adj2;
2268 adj1 = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "start");
2269 gtk_adjustment_set_value(adj1, mod360((start * 180)/M_PI));
2270 adj2 = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "end");
2271 gtk_adjustment_set_value(adj2, mod360((end * 180)/M_PI));
2273 sp_arctb_sensitivize (tbl, adj1->value, adj2->value);
2275 char const *openstr = NULL;
2276 openstr = repr->attribute("sodipodi:open");
2277 GtkWidget *ocb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "open_checkbox");
2279 if (openstr) {
2280 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ocb), TRUE);
2281 } else {
2282 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ocb), FALSE);
2283 }
2285 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2286 }
2288 static Inkscape::XML::NodeEventVector arc_tb_repr_events = {
2289 NULL, /* child_added */
2290 NULL, /* child_removed */
2291 arc_tb_event_attr_changed,
2292 NULL, /* content_changed */
2293 NULL /* order_changed */
2294 };
2297 static void
2298 sp_arc_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
2299 {
2300 int n_selected = 0;
2301 Inkscape::XML::Node *repr = NULL;
2302 Inkscape::XML::Node *oldrepr = NULL;
2304 for (GSList const *items = selection->itemList();
2305 items != NULL;
2306 items = items->next)
2307 {
2308 if (SP_IS_ARC((SPItem *) items->data)) {
2309 n_selected++;
2310 repr = SP_OBJECT_REPR((SPItem *) items->data);
2311 }
2312 }
2314 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
2316 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(FALSE));
2317 if (n_selected == 0) {
2318 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
2319 } else if (n_selected == 1) {
2320 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
2321 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2323 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
2325 if (oldrepr) { // remove old listener
2326 sp_repr_remove_listener_by_data(oldrepr, tbl);
2327 Inkscape::GC::release(oldrepr);
2328 oldrepr = 0;
2329 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
2330 }
2332 if (repr) {
2333 g_object_set_data(G_OBJECT(tbl), "repr", repr);
2334 Inkscape::GC::anchor(repr);
2335 sp_repr_add_listener(repr, &arc_tb_repr_events, tbl);
2336 sp_repr_synthesize_events(repr, &arc_tb_repr_events, tbl);
2337 }
2338 } else {
2339 // FIXME: implement averaging of all parameters for multiple selected
2340 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
2341 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2342 sp_arctb_sensitivize (GTK_WIDGET(tbl), 1, 0);
2343 }
2344 }
2347 static GtkWidget *
2348 sp_arc_toolbox_new(SPDesktop *desktop)
2349 {
2350 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2352 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2353 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2355 GtkTooltips *tt = gtk_tooltips_new();
2357 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
2359 /* Start */
2360 {
2361 GtkWidget *hb = sp_tb_spinbutton(_("Start:"), _("The angle (in degrees) from the horizontal to the arc's start point"),
2362 "tools.shapes.arc", "start", 0.0,
2363 NULL, tbl, TRUE, "altx-arc",
2364 -360.0, 360.0, 1.0, 10.0,
2365 sp_arctb_start_value_changed);
2366 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2367 }
2369 /* End */
2370 {
2371 GtkWidget *hb = sp_tb_spinbutton(_("End:"), _("The angle (in degrees) from the horizontal to the arc's end point"),
2372 "tools.shapes.arc", "end", 0.0,
2373 NULL, tbl, FALSE, NULL,
2374 -360.0, 360.0, 1.0, 10.0,
2375 sp_arctb_end_value_changed);
2376 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2377 }
2379 /* Segments / Pie checkbox */
2380 {
2381 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2382 GtkWidget *fscb = gtk_check_button_new_with_label(_("Open arc"));
2383 gtk_tooltips_set_tip(tt, fscb, _("Switch between arc (unclosed shape) and segment (closed shape with two radii)"), NULL);
2385 gchar const *openstr = NULL;
2386 openstr = prefs_get_string_attribute("tools.shapes.arc", "open");
2387 if (!openstr || (openstr && !strcmp(openstr, "false")))
2388 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), FALSE);
2389 else
2390 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), TRUE);
2392 gtk_widget_show(fscb);
2393 gtk_object_set_data(GTK_OBJECT(tbl), "open_checkbox", fscb);
2394 gtk_container_add(GTK_CONTAINER(hb), fscb);
2395 g_signal_connect(G_OBJECT(fscb), "toggled", GTK_SIGNAL_FUNC(sp_arctb_open_state_changed ), tbl);
2396 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2397 }
2399 /* Make Whole */
2400 {
2401 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2402 GtkWidget *b = gtk_button_new_with_label(_("Make whole"));
2403 gtk_object_set_data(GTK_OBJECT(tbl), "make_whole", b);
2404 gtk_tooltips_set_tip(tt, b, _("Make the shape a whole ellipse, not arc or segment"), NULL);
2405 gtk_widget_show(b);
2406 gtk_container_add(GTK_CONTAINER(hb), b);
2407 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_arctb_defaults), tbl);
2408 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2409 }
2411 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
2412 // sensitivize make whole and open checkbox
2413 {
2414 GtkAdjustment *adj1 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "start"));
2415 GtkAdjustment *adj2 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "end"));
2416 sp_arctb_sensitivize (tbl, adj1->value, adj2->value);
2417 }
2419 sigc::connection *connection = new sigc::connection(
2420 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_arc_toolbox_selection_changed), (GtkObject *)tbl))
2421 );
2422 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
2424 gtk_widget_show_all(tbl);
2425 sp_set_font_size_smaller (tbl);
2427 return tbl;
2428 }
2433 // toggle button callbacks and updaters
2435 //########################
2436 //## Dropper ##
2437 //########################
2439 static void toggle_dropper_color_pick (GtkWidget *button, gpointer data) {
2440 prefs_set_int_attribute ("tools.dropper", "pick",
2441 // 0 and 1 are backwards here because of pref
2442 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1);
2443 }
2446 /**
2447 * Copy the current saved desktop color to the clipboard as full hex + alpha
2448 * color representation. This is useful for passing values between various
2449 * input boxes, or directly to xml.
2450 */
2451 /* static void
2452 sp_dropper_copy( GtkWidget *widget, GtkObject *obj)
2453 {
2454 GtkWidget *tbl = GTK_WIDGET(obj);
2456 SPDesktop *desktop =
2457 (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2460 sp_dropper_c32_color_copy( sp_desktop_get_color(desktop, true) );
2461 }*/
2464 /**
2465 * Copies currently saved desktop color to the clipboard as a hex value. This
2466 * is useful for editing webpages and needing a value quickly for web
2467 * colors.
2468 *
2469 * TODO: When the toggle of the dropper is set to not mix color against
2470 * page background, this still just gets the color of the page and
2471 * doesn't get the actual mixed against background which is needed
2472 * for the hex value ppl. want for web pages, etc.
2473 */
2475 /* static void
2476 sp_dropper_copy_as_hex ( GtkWidget *widget, GtkObject *obj)
2477 {
2478 GtkWidget *tbl = GTK_WIDGET(obj);
2480 SPDesktop *desktop =
2481 (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2483 sp_dropper_c32_color_copy_hex( sp_desktop_get_color(desktop, true) );
2484 }*/
2487 /**
2488 * Sets the input boxes with the changed color and opacity. This is used as a
2489 * callback for style changing.
2490 */
2491 /* static bool
2492 sp_style_changed (const SPCSSAttr *css, gpointer data)
2493 {
2494 // GrDrag *drag = (GrDrag *) data;
2496 // set fill of text entry box
2497 if (css->attribute("fill"))
2498 gtk_entry_set_text((GtkEntry *)dropper_rgb_entry,
2499 css->attribute("fill"));
2501 // set opacity of text entry box
2502 if (css->attribute("fill-opacity"))
2503 gtk_entry_set_text((GtkEntry *)dropper_opacity_entry,
2504 css->attribute("fill-opacity"));
2506 // set fill of text entry box
2507 if (css->attribute("stroke"))
2508 gtk_entry_set_text((GtkEntry *)dropper_rgb_entry,
2509 css->attribute("stroke"));
2511 // set opacity of text entry box
2512 if (css->attribute("stroke-opacity"))
2513 gtk_entry_set_text((GtkEntry *)dropper_opacity_entry,
2514 css->attribute("stroke-opacity"));
2515 return false;
2517 }
2518 */
2521 /**
2522 * Dropper auxiliary toolbar construction and setup.
2523 *
2524 * TODO: Would like to add swatch of current color.
2525 * TODO: Add queue of last 5 or so colors selected with new swatches so that
2526 * can drag and drop places. Will provide a nice mixing palette.
2527 */
2528 static GtkWidget *
2529 sp_dropper_toolbox_new(SPDesktop *desktop)
2530 {
2531 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2533 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2534 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2536 GtkTooltips *tt = gtk_tooltips_new();
2539 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
2540 AUX_BETWEEN_BUTTON_GROUPS);
2541 // sp_toolbox_add_label(tbl, _("<b>New:</b>"));
2545 /* RGB Input Field */
2546 /* {
2547 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2548 GtkWidget *dropper_rgba_label = gtk_label_new ("Color:");
2549 gtk_widget_show (dropper_rgba_label);
2550 gtk_container_add(GTK_CONTAINER(hb), dropper_rgba_label);
2552 dropper_rgb_entry = gtk_entry_new ();
2553 sp_dialog_defocus_on_enter (dropper_rgb_entry);
2554 gtk_entry_set_max_length (GTK_ENTRY (dropper_rgb_entry), 7);
2555 gtk_entry_set_width_chars (GTK_ENTRY (dropper_rgb_entry), 7);
2556 gtk_tooltips_set_tip(tt, dropper_rgb_entry,
2557 _("Hexidecimal representation of last selected "
2558 "color"),
2559 NULL);
2560 gtk_widget_show (dropper_rgb_entry);
2561 gtk_container_add(GTK_CONTAINER(hb), dropper_rgb_entry);
2563 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2564 AUX_BETWEEN_BUTTON_GROUPS);
2565 } */
2567 /* Opacity Input Field */
2568 /* {
2569 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2570 GtkWidget *dropper_opacity_label = gtk_label_new ( _("Opacity:") );
2571 gtk_widget_show (dropper_opacity_label);
2572 gtk_container_add(GTK_CONTAINER(hb), dropper_opacity_label);
2574 dropper_opacity_entry = gtk_entry_new ();
2575 sp_dialog_defocus_on_enter (dropper_opacity_entry);
2576 gtk_entry_set_max_length (GTK_ENTRY (dropper_opacity_entry), 11);
2577 gtk_entry_set_width_chars (GTK_ENTRY (dropper_opacity_entry), 11);
2578 gtk_tooltips_set_tip(tt, dropper_opacity_entry,
2579 _("Opacity of last selected color"),
2580 NULL);
2581 gtk_widget_show (dropper_opacity_entry);
2582 gtk_container_add(GTK_CONTAINER(hb), dropper_opacity_entry);
2584 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2585 AUX_BETWEEN_BUTTON_GROUPS);
2586 } */
2589 /* Copy to Clipboard */
2590 /* {
2591 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2592 GtkWidget *b = gtk_button_new_with_label(_("Copy as RGBA"));
2593 gtk_tooltips_set_tip(tt, b, _("Copy last saved color as hexidecimal "
2594 "RGB + Alpha (RGBA) to "
2595 "clipboard"),
2596 NULL);
2597 gtk_widget_show(b);
2598 gtk_container_add(GTK_CONTAINER(hb), b);
2599 gtk_signal_connect(GTK_OBJECT(b), "clicked",
2600 GTK_SIGNAL_FUNC(sp_dropper_copy), tbl);
2601 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2602 AUX_BETWEEN_BUTTON_GROUPS);
2603 } */
2606 /* Copy to Clipboard as HEX */
2607 /* {
2608 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2609 GtkWidget *b = gtk_button_new_with_label(_("Copy as HEX"));
2610 gtk_tooltips_set_tip(tt, b, _("Copy last saved color as "
2611 "hexidecimal RGB without alpha "
2612 "to clipboard"), NULL);
2613 gtk_widget_show(b);
2614 gtk_container_add(GTK_CONTAINER(hb), b);
2615 gtk_signal_connect(GTK_OBJECT(b), "clicked",
2616 GTK_SIGNAL_FUNC(sp_dropper_copy_as_hex), tbl);
2617 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2618 AUX_BETWEEN_BUTTON_GROUPS);
2619 } */
2621 // aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2623 {
2624 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2626 GtkWidget *button =
2627 sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
2628 SP_BUTTON_TYPE_TOGGLE,
2629 NULL,
2630 "pick_color",
2631 _("When pressed, picks visible color "
2632 "without alpha and when not pressed, "
2633 "picks color including its "
2634 "alpha"),
2635 tt);
2637 gtk_widget_show(button);
2638 gtk_container_add (GTK_CONTAINER (hb), button);
2640 g_signal_connect_after (G_OBJECT (button), "clicked",
2641 G_CALLBACK (toggle_dropper_color_pick), NULL);
2642 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
2643 !prefs_get_int_attribute ("tools.dropper",
2644 "pick", 0));
2645 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2646 AUX_BETWEEN_BUTTON_GROUPS);
2647 }
2649 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2652 // where new gtkmm stuff should go
2654 gtk_widget_show_all(tbl);
2655 sp_set_font_size_smaller (tbl);
2657 /*
2658 sigc::connection *connection = new sigc::connection(
2659 desktop->connectSetStyle(
2660 sigc::bind(sigc::ptr_fun(sp_style_changed),
2661 desktop)) );
2663 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection),
2664 connection); */
2666 return tbl;
2667 }
2670 //########################
2671 //## Text Toolbox ##
2672 //########################
2673 /*
2674 static void
2675 sp_text_letter_changed(GtkAdjustment *adj, GtkWidget *tbl)
2676 {
2677 //Call back for letter sizing spinbutton
2678 }
2680 static void
2681 sp_text_line_changed(GtkAdjustment *adj, GtkWidget *tbl)
2682 {
2683 //Call back for line height spinbutton
2684 }
2686 static void
2687 sp_text_horiz_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
2688 {
2689 //Call back for horizontal kerning spinbutton
2690 }
2692 static void
2693 sp_text_vert_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
2694 {
2695 //Call back for vertical kerning spinbutton
2696 }
2698 static void
2699 sp_text_letter_rotation_changed(GtkAdjustment *adj, GtkWidget *tbl)
2700 {
2701 //Call back for letter rotation spinbutton
2702 }*/
2703 static GtkWidget *
2704 sp_text_toolbox_new(SPDesktop *desktop)
2705 {
2706 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2707 /* GtkWidget *us = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tbl), "units");
2708 GtkTooltips *tt = gtk_tooltips_new();
2709 GtkWidget *group;
2711 //Font Family
2712 {
2713 GtkWidget *c = gtk_combo_new ();
2714 gtk_combo_set_value_in_list ((GtkCombo *) c, FALSE, FALSE);
2715 gtk_combo_set_use_arrows ((GtkCombo *) c, TRUE);
2716 gtk_combo_set_use_arrows_always ((GtkCombo *) c, TRUE);
2717 gtk_widget_set_size_request (c, 144, -1);
2718 aux_toolbox_space(tbl, 1);
2719 gtk_box_pack_start (GTK_BOX (tbl), c, FALSE, FALSE, 0);
2720 }
2722 //Font Style
2723 {
2724 GtkWidget *c = gtk_combo_new ();
2725 gtk_combo_set_value_in_list ((GtkCombo *) c, FALSE, FALSE);
2726 gtk_combo_set_use_arrows ((GtkCombo *) c, TRUE);
2727 gtk_combo_set_use_arrows_always ((GtkCombo *) c, TRUE);
2728 gtk_widget_set_size_request (c, 88, -1);
2729 aux_toolbox_space(tbl, 1);
2730 gtk_box_pack_start (GTK_BOX (tbl), c, FALSE, FALSE, 0);
2731 }
2733 //Font Size
2734 {
2735 GtkWidget *c = gtk_combo_new ();
2736 gtk_combo_set_value_in_list ((GtkCombo *) c, FALSE, FALSE);
2737 gtk_combo_set_use_arrows ((GtkCombo *) c, TRUE);
2738 gtk_combo_set_use_arrows_always ((GtkCombo *) c, TRUE);
2739 gtk_widget_set_size_request (c, 64, -1);
2740 aux_toolbox_space(tbl, 1);
2741 gtk_box_pack_start (GTK_BOX (tbl), c, FALSE, FALSE, 0);
2742 }
2744 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2745 //Bold
2746 {
2747 GtkWidget *px = gtk_image_new_from_stock(GTK_STOCK_BOLD, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2748 GtkWidget *button = gtk_toggle_button_new ();
2749 gtk_container_add (GTK_CONTAINER (button), px);
2750 gtk_widget_show(button);
2751 gtk_tooltips_set_tip (tt, button, _("Bold"), NULL);
2752 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2753 gtk_widget_set_sensitive(button, TRUE);
2754 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
2755 }
2758 //Italic
2759 {
2760 GtkWidget *px = gtk_image_new_from_stock(GTK_STOCK_ITALIC, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2761 GtkWidget *button = gtk_toggle_button_new ();
2762 gtk_container_add (GTK_CONTAINER (button), px);
2763 gtk_widget_show(button);
2764 gtk_tooltips_set_tip (tt, button, _("Italics"), NULL);
2765 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2766 gtk_widget_set_sensitive(button, TRUE);
2767 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
2768 }
2770 //Underline
2771 {
2772 GtkWidget *px = gtk_image_new_from_stock(GTK_STOCK_UNDERLINE, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2773 GtkWidget *button = gtk_toggle_button_new ();
2774 gtk_container_add (GTK_CONTAINER (button), px);
2775 gtk_widget_show(button);
2776 gtk_tooltips_set_tip (tt, button, _("Underline"), NULL);
2777 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2778 gtk_widget_set_sensitive(button, FALSE);
2779 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
2780 }
2782 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2783 // align left
2784 {
2785 GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_LEFT, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2786 GtkWidget *b = group = gtk_radio_button_new (NULL);
2787 gtk_container_add (GTK_CONTAINER (b), px);
2788 gtk_tooltips_set_tip (tt, b, _("Align lines left"), NULL);
2789 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2790 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2791 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2792 }
2794 // align center
2795 {
2796 GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_CENTER, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2797 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
2798 gtk_container_add (GTK_CONTAINER (b), px);
2799 // TRANSLATORS: `Center' here is a verb.
2800 gtk_tooltips_set_tip (tt, b, _("Center lines"), NULL);
2801 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2802 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2803 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2804 }
2806 // align right
2807 {
2808 GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_RIGHT, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2809 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
2810 gtk_container_add (GTK_CONTAINER (b), px);
2811 gtk_tooltips_set_tip (tt, b, _("Align lines right"), NULL);
2812 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2813 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2814 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2815 }
2817 // full justification
2818 {
2819 GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_FILL, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
2820 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
2821 gtk_container_add (GTK_CONTAINER (b), px);
2822 gtk_tooltips_set_tip (tt, b, _("Full justification"), NULL);
2823 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2824 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2825 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2826 }
2829 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2831 // horizontal
2832 {
2833 GtkWidget *px= sp_icon_new(Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_LR);
2834 GtkWidget *b = group = gtk_radio_button_new (NULL);
2835 gtk_container_add (GTK_CONTAINER (b), px);
2836 gtk_tooltips_set_tip (tt, b, _("Horizontal text"), NULL);
2837 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2838 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2839 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2840 }
2842 // vertical
2843 {
2844 GtkWidget *px = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_TB);
2845 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
2846 gtk_container_add (GTK_CONTAINER (b), px);
2847 gtk_tooltips_set_tip (tt, b, _("Vertical text"), NULL);
2848 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
2849 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
2850 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
2851 }
2853 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2855 // letter spacing
2856 {
2857 {
2858 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LETTER_SPACING);
2859 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2860 gtk_container_add (GTK_CONTAINER (hb), image);
2861 gtk_widget_show(image);
2862 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
2863 }
2865 {
2866 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Spacing between letters"),
2867 "tools.text", "letter_spacing", 0.0,
2868 us, tbl, FALSE, NULL,
2869 -1000.0, 1000.0, 0.1, 0.1,
2870 sp_text_letter_changed, 0.1, 1);
2871 gtk_widget_set_size_request (hb, 45, 6);
2872 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
2873 }
2874 }
2876 // line spacing
2877 {
2878 {
2879 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LINE_SPACING);
2880 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2881 gtk_container_add (GTK_CONTAINER (hb), image);
2882 gtk_widget_show(image);
2883 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
2884 }
2886 {
2887 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Spacing between lines"),
2888 "tools.text", "line_spacing", 0,
2889 us, tbl, FALSE, NULL,
2890 -1000.0, 1000.0, 0.1, 0.1,
2891 sp_text_line_changed, 0.1, 1);
2892 gtk_widget_set_size_request (hb, 45, 0);
2893 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 3);
2894 }
2895 }
2897 {
2898 // horizontal kerning/vertical kerning units menu: create
2899 GtkWidget *us = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
2900 sp_unit_selector_setsize(us, AUX_OPTION_MENU_WIDTH, AUX_OPTION_MENU_HEIGHT);
2901 sp_unit_selector_set_unit(SP_UNIT_SELECTOR(us), desktop->namedview->doc_units);
2903 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2905 // horizontal kerning
2906 {
2907 {
2908 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_HORZ_KERN);
2909 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2910 gtk_container_add (GTK_CONTAINER (hb), image);
2911 gtk_widget_show(image);
2912 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
2913 }
2915 {
2916 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Horizontal kerning"),
2917 "tools.text", "horizontal_kerning", 0,
2918 us, tbl, FALSE, NULL,
2919 -100.00, 100.00, 0.01, 0.1,
2920 sp_text_horiz_kern_changed);
2921 gtk_widget_set_size_request (hb, 45, 0);
2922 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
2923 }
2924 }
2926 // vertical kerning
2927 {
2928 {
2929 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_VERT_KERN);
2930 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2931 gtk_container_add (GTK_CONTAINER (hb), image);
2932 gtk_widget_show(image);
2933 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
2934 }
2936 {
2937 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Vertical kerning"),
2938 "tools.text", "vertical_kerning", 0,
2939 us, tbl, FALSE, NULL,
2940 -100.00, 100.00, 0.01, 0.1,
2941 sp_text_vert_kern_changed);
2942 gtk_widget_set_size_request (hb, 45, 0);
2943 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 5);
2944 }
2945 }
2947 // add the units menu
2948 gtk_widget_show(us);
2949 gtk_box_pack_start(GTK_BOX(tbl), us, FALSE, FALSE, 1);
2950 gtk_object_set_data(GTK_OBJECT(tbl), "units", us);
2951 }
2953 // letter rotation
2954 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2955 {
2956 {
2957 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_ROTATION);
2958 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2959 gtk_container_add (GTK_CONTAINER (hb), image);
2960 gtk_widget_show(image);
2961 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
2962 }
2963 {
2964 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Letter rotation"),
2965 "tools.text", "letter_rotation", 0,
2966 us, tbl, FALSE, NULL,
2967 -180.0, 180.0, 0.1, 0.1,
2968 sp_text_letter_rotation_changed, 0.1, 1);
2969 gtk_widget_set_size_request (hb, 45, 0);
2970 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
2971 }
2972 // rotation degree label
2973 {
2974 GtkWidget *label = gtk_widget_new (GTK_TYPE_LABEL, "label", "\302\260", "xalign", 0.0, NULL);
2975 gtk_box_pack_start(GTK_BOX(tbl), label, FALSE, FALSE, 0);
2976 }
2977 }
2979 // Remove Manual Kerns
2980 {
2981 GtkWidget *px = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_REMOVE_KERNS);
2982 GtkWidget *button = gtk_button_new ();
2983 gtk_container_add (GTK_CONTAINER (button), px);
2984 gtk_widget_show(button);
2985 gtk_tooltips_set_tip (tt, button, _("Remove manual kerns"), NULL);
2986 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2987 gtk_widget_set_sensitive(button, TRUE);
2988 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2989 }
2991 gtk_widget_show_all(tbl);
2992 sp_set_font_size_smaller (tbl);
2994 */ return tbl;
2996 } // end of sp_text_toolbox_new()
2999 //#########################
3000 //## Connector Toolbox ##
3001 //#########################
3003 static void sp_connector_path_set_avoid(void)
3004 {
3005 cc_selection_set_avoid(true);
3006 }
3009 static void sp_connector_path_set_ignore(void)
3010 {
3011 cc_selection_set_avoid(false);
3012 }
3015 static void connector_spacing_changed(GtkAdjustment *adj, GtkWidget *tbl)
3016 {
3017 // quit if run by the _changed callbacks
3018 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
3019 return;
3020 }
3022 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl),
3023 "desktop");
3024 SPDocument *doc = sp_desktop_document(desktop);
3026 if (!sp_document_get_undo_sensitive(doc))
3027 {
3028 return;
3029 }
3031 // in turn, prevent callbacks from responding
3032 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
3034 Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
3036 sp_repr_set_css_double(repr, "inkscape:connector-spacing", adj->value);
3037 SP_OBJECT(desktop->namedview)->updateRepr();
3039 GSList *items = get_avoided_items(NULL, desktop->currentRoot(), desktop);
3040 for ( GSList const *iter = items ; iter != NULL ; iter = iter->next ) {
3041 SPItem *item = reinterpret_cast<SPItem *>(iter->data);
3042 NR::Matrix m = NR::identity();
3043 avoid_item_move(&m, item);
3044 }
3046 if (items) {
3047 g_slist_free(items);
3048 }
3050 sp_document_done(doc);
3052 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
3054 spinbutton_defocus(GTK_OBJECT(tbl));
3055 }
3058 static void connector_tb_event_attr_changed(Inkscape::XML::Node *repr,
3059 gchar const *name, gchar const *old_value, gchar const *new_value,
3060 bool is_interactive, gpointer data)
3061 {
3062 GtkWidget *tbl = GTK_WIDGET(data);
3064 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
3065 return;
3066 }
3067 if (strcmp(name, "inkscape:connector-spacing") != 0) {
3068 return;
3069 }
3071 GtkAdjustment *adj = (GtkAdjustment*)
3072 gtk_object_get_data(GTK_OBJECT(tbl), "spacing");
3073 gdouble spacing = defaultConnSpacing;
3074 sp_repr_get_double(repr, "inkscape:connector-spacing", &spacing);
3076 gtk_adjustment_set_value(adj, spacing);
3077 }
3080 static Inkscape::XML::NodeEventVector connector_tb_repr_events = {
3081 NULL, /* child_added */
3082 NULL, /* child_removed */
3083 connector_tb_event_attr_changed,
3084 NULL, /* content_changed */
3085 NULL /* order_changed */
3086 };
3089 static GtkWidget *
3090 sp_connector_toolbox_new(SPDesktop *desktop)
3091 {
3092 GtkTooltips *tt = gtk_tooltips_new();
3093 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
3095 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
3096 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
3098 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
3099 AUX_BETWEEN_BUTTON_GROUPS);
3101 sp_toolbox_button_new(tbl, Inkscape::ICON_SIZE_DECORATION,
3102 "connector_avoid", GTK_SIGNAL_FUNC(sp_connector_path_set_avoid),
3103 tt, _("Make connectors avoid selected objects"));
3105 sp_toolbox_button_new(tbl, Inkscape::ICON_SIZE_DECORATION,
3106 "connector_ignore", GTK_SIGNAL_FUNC(sp_connector_path_set_ignore),
3107 tt, _("Make connectors ignore selected objects"));
3109 // interval
3110 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
3111 AUX_BETWEEN_BUTTON_GROUPS);
3113 // Spacing spinbox
3114 {
3115 GtkWidget *object_spacing = sp_tb_spinbutton(_("Spacing:"),
3116 _("The amount of space left around objects by auto-routing connectors"),
3117 "tools.connector", "spacing", 10, NULL, tbl, TRUE,
3118 "inkscape:connector-spacing", 0, 100, 1.0, 10.0,
3119 connector_spacing_changed, 1, 0);
3121 gtk_box_pack_start(GTK_BOX(tbl), object_spacing, FALSE, FALSE,
3122 AUX_SPACING);
3123 }
3125 gtk_widget_show_all(tbl);
3126 sp_set_font_size_smaller (tbl);
3128 // Code to watch for changes to the connector-spacing attribute in
3129 // the XML.
3130 Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
3131 g_assert(repr != NULL);
3133 Inkscape::XML::Node *oldrepr = (Inkscape::XML::Node *)
3134 gtk_object_get_data(GTK_OBJECT(tbl), "repr");
3136 if (oldrepr) { // remove old listener
3137 sp_repr_remove_listener_by_data(oldrepr, tbl);
3138 Inkscape::GC::release(oldrepr);
3139 oldrepr = NULL;
3140 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
3141 }
3143 if (repr) {
3144 g_object_set_data(G_OBJECT(tbl), "repr", repr);
3145 Inkscape::GC::anchor(repr);
3146 sp_repr_add_listener(repr, &connector_tb_repr_events, tbl);
3147 sp_repr_synthesize_events(repr, &connector_tb_repr_events, tbl);
3148 }
3150 return tbl;
3152 } // end of sp_connector_toolbox_new()
3155 /*
3156 Local Variables:
3157 mode:c++
3158 c-file-style:"stroustrup"
3159 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
3160 indent-tabs-mode:nil
3161 fill-column:99
3162 End:
3163 */
3164 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :