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