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 <gtkmm.h>
32 #include <gtk/gtk.h>
33 #include <iostream>
34 #include <sstream>
36 #include "widgets/button.h"
37 #include "widgets/widget-sizes.h"
38 #include "widgets/spw-utilities.h"
39 #include "widgets/spinbutton-events.h"
40 #include "dialogs/text-edit.h"
42 #include "ui/widget/style-swatch.h"
44 #include "prefs-utils.h"
45 #include "verbs.h"
46 #include "sp-namedview.h"
47 #include "desktop.h"
48 #include "desktop-handles.h"
49 #include "nodepath.h"
50 #include "xml/repr.h"
51 #include "xml/node-event-vector.h"
52 #include <glibmm/i18n.h>
53 #include "helper/unit-menu.h"
54 #include "helper/units.h"
56 #include "inkscape.h"
57 #include "conn-avoid-ref.h"
60 #include "select-toolbar.h"
61 #include "gradient-toolbar.h"
63 #include "connector-context.h"
64 #include "sp-rect.h"
65 #include "sp-star.h"
66 #include "sp-spiral.h"
67 #include "sp-ellipse.h"
68 #include "sp-text.h"
69 #include "sp-flowtext.h"
70 #include "style.h"
71 #include "selection.h"
72 #include "document-private.h"
73 #include "desktop-style.h"
74 #include "../libnrtype/font-lister.h"
75 #include "../connection-pool.h"
76 #include "../prefs-utils.h"
77 #include "../inkscape-stock.h"
78 #include "icon.h"
79 #include "graphlayout/graphlayout.h"
81 #include "mod360.h"
83 #include "toolbox.h"
85 typedef void (*SetupFunction)(GtkWidget *toolbox, SPDesktop *desktop);
86 typedef void (*UpdateFunction)(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
88 static GtkWidget *sp_node_toolbox_new(SPDesktop *desktop);
89 static GtkWidget *sp_zoom_toolbox_new(SPDesktop *desktop);
90 static GtkWidget *sp_star_toolbox_new(SPDesktop *desktop);
91 static GtkWidget *sp_arc_toolbox_new(SPDesktop *desktop);
92 static GtkWidget *sp_rect_toolbox_new(SPDesktop *desktop);
93 static GtkWidget *sp_spiral_toolbox_new(SPDesktop *desktop);
94 static GtkWidget *sp_pencil_toolbox_new(SPDesktop *desktop);
95 static GtkWidget *sp_pen_toolbox_new(SPDesktop *desktop);
96 static GtkWidget *sp_calligraphy_toolbox_new(SPDesktop *desktop);
97 static GtkWidget *sp_dropper_toolbox_new(SPDesktop *desktop);
98 static GtkWidget *sp_empty_toolbox_new(SPDesktop *desktop);
99 static GtkWidget *sp_connector_toolbox_new(SPDesktop *desktop);
101 namespace { GtkWidget *sp_text_toolbox_new (SPDesktop *desktop); }
104 static struct {
105 gchar const *type_name;
106 gchar const *data_name;
107 sp_verb_t verb;
108 sp_verb_t doubleclick_verb;
109 } const tools[] = {
110 { "SPSelectContext", "select_tool", SP_VERB_CONTEXT_SELECT, SP_VERB_CONTEXT_SELECT_PREFS},
111 { "SPNodeContext", "node_tool", SP_VERB_CONTEXT_NODE, SP_VERB_CONTEXT_NODE_PREFS },
112 { "SPZoomContext", "zoom_tool", SP_VERB_CONTEXT_ZOOM, SP_VERB_CONTEXT_ZOOM_PREFS },
113 { "SPRectContext", "rect_tool", SP_VERB_CONTEXT_RECT, SP_VERB_CONTEXT_RECT_PREFS },
114 { "SPArcContext", "arc_tool", SP_VERB_CONTEXT_ARC, SP_VERB_CONTEXT_ARC_PREFS },
115 { "SPStarContext", "star_tool", SP_VERB_CONTEXT_STAR, SP_VERB_CONTEXT_STAR_PREFS },
116 { "SPSpiralContext", "spiral_tool", SP_VERB_CONTEXT_SPIRAL, SP_VERB_CONTEXT_SPIRAL_PREFS },
117 { "SPPencilContext", "pencil_tool", SP_VERB_CONTEXT_PENCIL, SP_VERB_CONTEXT_PENCIL_PREFS },
118 { "SPPenContext", "pen_tool", SP_VERB_CONTEXT_PEN, SP_VERB_CONTEXT_PEN_PREFS },
119 { "SPDynaDrawContext", "dyna_draw_tool", SP_VERB_CONTEXT_CALLIGRAPHIC, SP_VERB_CONTEXT_CALLIGRAPHIC_PREFS },
120 { "SPTextContext", "text_tool", SP_VERB_CONTEXT_TEXT, SP_VERB_CONTEXT_TEXT_PREFS },
121 { "SPConnectorContext","connector_tool", SP_VERB_CONTEXT_CONNECTOR, SP_VERB_CONTEXT_CONNECTOR_PREFS },
122 { "SPGradientContext", "gradient_tool", SP_VERB_CONTEXT_GRADIENT, SP_VERB_CONTEXT_GRADIENT_PREFS },
123 { "SPDropperContext", "dropper_tool", SP_VERB_CONTEXT_DROPPER, SP_VERB_CONTEXT_DROPPER_PREFS },
124 { NULL, NULL, 0, 0 }
125 };
127 static struct {
128 gchar const *type_name;
129 gchar const *data_name;
130 GtkWidget *(*create_func)(SPDesktop *desktop);
131 } const aux_toolboxes[] = {
132 { "SPSelectContext", "select_toolbox", sp_select_toolbox_new },
133 { "SPNodeContext", "node_toolbox", sp_node_toolbox_new },
134 { "SPZoomContext", "zoom_toolbox", sp_zoom_toolbox_new },
135 { "SPStarContext", "star_toolbox", sp_star_toolbox_new },
136 { "SPRectContext", "rect_toolbox", sp_rect_toolbox_new },
137 { "SPArcContext", "arc_toolbox", sp_arc_toolbox_new },
138 { "SPSpiralContext", "spiral_toolbox", sp_spiral_toolbox_new },
139 { "SPPencilContext", "pencil_toolbox", sp_pencil_toolbox_new },
140 { "SPPenContext", "pen_toolbox", sp_pen_toolbox_new },
141 { "SPDynaDrawContext", "calligraphy_toolbox", sp_calligraphy_toolbox_new },
142 { "SPTextContext", "text_toolbox", sp_text_toolbox_new },
143 { "SPDropperContext", "dropper_toolbox", sp_dropper_toolbox_new },
144 { "SPGradientContext", "gradient_toolbox", sp_gradient_toolbox_new },
145 { "SPConnectorContext", "connector_toolbox", sp_connector_toolbox_new },
146 { NULL, NULL, NULL }
147 };
149 static void toolbox_set_desktop (GtkWidget *toolbox, SPDesktop *desktop, SetupFunction setup_func, UpdateFunction update_func, sigc::connection*);
151 static void setup_tool_toolbox (GtkWidget *toolbox, SPDesktop *desktop);
152 static void update_tool_toolbox (SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
154 static void setup_aux_toolbox (GtkWidget *toolbox, SPDesktop *desktop);
155 static void update_aux_toolbox (SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
157 static void setup_commands_toolbox (GtkWidget *toolbox, SPDesktop *desktop);
158 static void update_commands_toolbox (SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
160 /* Global text entry widgets necessary for update */
161 /* GtkWidget *dropper_rgb_entry,
162 *dropper_opacity_entry ; */
163 // should be made a private member once this is converted to class
165 static void delete_connection(GObject *obj, sigc::connection *connection) {
166 connection->disconnect();
167 delete connection;
168 }
170 static GtkWidget *
171 sp_toolbox_button_new(GtkWidget *t, Inkscape::IconSize size, gchar const *pxname, GtkSignalFunc handler,
172 GtkTooltips *tt, gchar const *tip)
173 {
174 GtkWidget *b = sp_button_new_from_data(size, SP_BUTTON_TYPE_NORMAL, NULL, pxname, tip, tt);
175 gtk_widget_show(b);
176 if (handler) gtk_signal_connect(GTK_OBJECT(b), "clicked", handler, NULL);
177 gtk_box_pack_start(GTK_BOX(t), b, FALSE, FALSE, 0);
179 return b;
180 }
182 GtkWidget *
183 sp_toolbox_button_new_from_verb_with_doubleclick(GtkWidget *t, Inkscape::IconSize size, SPButtonType type,
184 Inkscape::Verb *verb, Inkscape::Verb *doubleclick_verb,
185 Inkscape::UI::View::View *view, GtkTooltips *tt)
186 {
187 SPAction *action = verb->get_action(view);
188 if (!action) return NULL;
190 SPAction *doubleclick_action;
191 if (doubleclick_verb)
192 doubleclick_action = doubleclick_verb->get_action(view);
193 else
194 doubleclick_action = NULL;
196 /* fixme: Handle sensitive/unsensitive */
197 /* fixme: Implement sp_button_new_from_action */
198 GtkWidget *b = sp_button_new(size, type, action, doubleclick_action, tt);
199 gtk_widget_show(b);
200 gtk_box_pack_start(GTK_BOX(t), b, FALSE, FALSE, 0);
202 return b;
203 }
205 GtkWidget *sp_toolbox_button_new_from_verb(GtkWidget *t, Inkscape::IconSize size, SPButtonType type, Inkscape::Verb *verb,
206 Inkscape::UI::View::View *view, GtkTooltips *tt)
207 {
208 return sp_toolbox_button_new_from_verb_with_doubleclick(t, size, type, verb, NULL, view, tt);
209 }
211 GtkWidget * sp_toolbox_button_normal_new_from_verb(GtkWidget *t, Inkscape::IconSize size, Inkscape::Verb *verb,
212 Inkscape::UI::View::View *view, GtkTooltips *tt)
213 {
214 return sp_toolbox_button_new_from_verb(t, size, SP_BUTTON_TYPE_NORMAL, verb, view, tt);
215 }
217 GtkWidget *
218 sp_tool_toolbox_new()
219 {
220 GtkTooltips *tt = gtk_tooltips_new();
221 GtkWidget *tb = gtk_vbox_new(FALSE, 0);
223 g_object_set_data(G_OBJECT(tb), "desktop", NULL);
224 g_object_set_data(G_OBJECT(tb), "tooltips", tt);
226 gtk_widget_set_sensitive(tb, FALSE);
228 GtkWidget *hb = gtk_handle_box_new();
229 gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), GTK_POS_TOP);
230 gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(hb), GTK_SHADOW_OUT);
231 gtk_handle_box_set_snap_edge(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
233 gtk_container_add(GTK_CONTAINER(hb), tb);
234 gtk_widget_show(GTK_WIDGET(tb));
236 sigc::connection* conn = new sigc::connection;
237 g_object_set_data(G_OBJECT(hb), "event_context_connection", conn);
239 return hb;
240 }
242 static void
243 aux_toolbox_attached(GtkHandleBox *toolbox, GtkWidget *child)
244 {
245 g_object_set_data(G_OBJECT(child), "is_detached", GINT_TO_POINTER(FALSE));
246 gtk_widget_queue_resize(child);
247 }
249 static void
250 aux_toolbox_detached(GtkHandleBox *toolbox, GtkWidget *child)
251 {
252 g_object_set_data(G_OBJECT(child), "is_detached", GINT_TO_POINTER(TRUE));
253 gtk_widget_queue_resize(child);
254 }
256 GtkWidget *
257 sp_aux_toolbox_new()
258 {
259 GtkWidget *tb = gtk_vbox_new(FALSE, 0);
261 GtkWidget *tb_s = gtk_vbox_new(FALSE, 0);
262 GtkWidget *tb_e = gtk_vbox_new(FALSE, 0);
263 gtk_box_set_spacing(GTK_BOX(tb), AUX_SPACING);
264 gtk_box_pack_start(GTK_BOX(tb), GTK_WIDGET(tb_s), FALSE, FALSE, 0);
265 gtk_box_pack_end(GTK_BOX(tb), GTK_WIDGET(tb_e), FALSE, FALSE, 0);
267 g_object_set_data(G_OBJECT(tb), "desktop", NULL);
268 g_object_set_data(G_OBJECT(tb), "top_spacer", tb_s);
270 gtk_widget_set_sensitive(tb, FALSE);
272 GtkWidget *hb = gtk_handle_box_new();
273 gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
274 gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(hb), GTK_SHADOW_OUT);
275 gtk_handle_box_set_snap_edge(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
277 g_signal_connect(G_OBJECT(hb), "child_attached", G_CALLBACK(aux_toolbox_attached), (gpointer)tb);
278 g_signal_connect(G_OBJECT(hb), "child_detached", G_CALLBACK(aux_toolbox_detached), (gpointer)tb);
280 gtk_container_add(GTK_CONTAINER(hb), tb);
281 gtk_widget_show(GTK_WIDGET(tb));
283 sigc::connection* conn = new sigc::connection;
284 g_object_set_data(G_OBJECT(hb), "event_context_connection", conn);
286 return hb;
287 }
289 //####################################
290 //# Commands Bar
291 //####################################
293 GtkWidget *
294 sp_commands_toolbox_new()
295 {
296 GtkWidget *tb = gtk_vbox_new(FALSE, 0);
298 GtkWidget *tb_s = gtk_vbox_new(FALSE, 0);
299 GtkWidget *tb_e = gtk_vbox_new(FALSE, 0);
300 gtk_box_set_spacing(GTK_BOX(tb), AUX_SPACING);
301 gtk_box_pack_start(GTK_BOX(tb), GTK_WIDGET(tb_s), FALSE, FALSE, 0);
302 gtk_box_pack_end(GTK_BOX(tb), GTK_WIDGET(tb_e), FALSE, FALSE, 0);
304 g_object_set_data(G_OBJECT(tb), "desktop", NULL);
305 gtk_widget_set_sensitive(tb, FALSE);
307 GtkWidget *hb = gtk_handle_box_new();
308 gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
309 gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(hb), GTK_SHADOW_OUT);
310 gtk_handle_box_set_snap_edge(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
312 g_signal_connect(G_OBJECT(hb), "child_attached", G_CALLBACK(aux_toolbox_attached), (gpointer)tb);
313 g_signal_connect(G_OBJECT(hb), "child_detached", G_CALLBACK(aux_toolbox_detached), (gpointer)tb);
315 gtk_container_add(GTK_CONTAINER(hb), tb);
316 gtk_widget_show(GTK_WIDGET(tb));
318 sigc::connection* conn = new sigc::connection;
319 g_object_set_data(G_OBJECT(hb), "event_context_connection", conn);
321 return hb;
322 }
325 //####################################
326 //# node editing callbacks
327 //####################################
329 void
330 sp_node_path_edit_add(void)
331 {
332 sp_node_selected_add_node();
333 }
335 void
336 sp_node_path_edit_delete(void)
337 {
338 sp_node_selected_delete();
339 }
341 void
342 sp_node_path_edit_delete_segment(void)
343 {
344 sp_node_selected_delete_segment();
345 }
347 void
348 sp_node_path_edit_break(void)
349 {
350 sp_node_selected_break();
351 }
353 void
354 sp_node_path_edit_join(void)
355 {
356 sp_node_selected_join();
357 }
359 void
360 sp_node_path_edit_join_segment(void)
361 {
362 sp_node_selected_join_segment();
363 }
365 void
366 sp_node_path_edit_toline(void)
367 {
368 sp_node_selected_set_line_type(NR_LINETO);
369 }
371 void
372 sp_node_path_edit_tocurve(void)
373 {
374 sp_node_selected_set_line_type(NR_CURVETO);
375 }
377 void
378 sp_node_path_edit_cusp(void)
379 {
380 sp_node_selected_set_type(Inkscape::NodePath::NODE_CUSP);
381 }
383 void
384 sp_node_path_edit_smooth(void)
385 {
386 sp_node_selected_set_type(Inkscape::NodePath::NODE_SMOOTH);
387 }
389 void
390 sp_node_path_edit_symmetrical(void)
391 {
392 sp_node_selected_set_type(Inkscape::NodePath::NODE_SYMM);
393 }
395 static void toggle_show_handles (GtkWidget *button, gpointer data) {
396 bool show = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
397 prefs_set_int_attribute ("tools.nodes", "show_handles", show ? 1 : 0);
398 sp_nodepath_show_handles(show);
399 }
401 //################################
402 //## Node Editing Toolbox ##
403 //################################
405 static GtkWidget *
406 sp_node_toolbox_new(SPDesktop *desktop)
407 {
408 Inkscape::UI::View::View *view = desktop;
410 GtkTooltips *tt = gtk_tooltips_new();
411 GtkWidget *tb = gtk_hbox_new(FALSE, 0);
413 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
415 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_insert",
416 GTK_SIGNAL_FUNC(sp_node_path_edit_add), tt, _("Insert new nodes into selected segments"));
417 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_delete",
418 GTK_SIGNAL_FUNC(sp_node_path_edit_delete), tt, _("Delete selected nodes"));
420 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
422 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_join",
423 GTK_SIGNAL_FUNC(sp_node_path_edit_join), tt, _("Join selected endnodes"));
424 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_join_segment",
425 GTK_SIGNAL_FUNC(sp_node_path_edit_join_segment), tt, _("Join selected endnodes with a new segment"));
427 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_delete_segment",
428 GTK_SIGNAL_FUNC(sp_node_path_edit_delete_segment), tt, _("Split path between two non-endpoint nodes"));
430 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_break",
431 GTK_SIGNAL_FUNC(sp_node_path_edit_break), tt, _("Break path at selected nodes"));
433 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
435 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_cusp",
436 GTK_SIGNAL_FUNC(sp_node_path_edit_cusp), tt, _("Make selected nodes corner"));
438 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_smooth",
439 GTK_SIGNAL_FUNC(sp_node_path_edit_smooth), tt, _("Make selected nodes smooth"));
441 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_symmetric",
442 GTK_SIGNAL_FUNC(sp_node_path_edit_symmetrical), tt, _("Make selected nodes symmetric"));
444 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
446 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_line",
447 GTK_SIGNAL_FUNC(sp_node_path_edit_toline), tt, _("Make selected segments lines"));
449 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_curve",
450 GTK_SIGNAL_FUNC(sp_node_path_edit_tocurve), tt, _("Make selected segments curves"));
452 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
454 sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_OBJECT_TO_CURVE), view, tt);
456 sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_SELECTION_OUTLINE), view, tt);
458 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
460 GtkWidget *cvbox = gtk_vbox_new (FALSE, 0);
461 GtkWidget *cbox = gtk_hbox_new (FALSE, 0);
463 {
464 GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
465 SP_BUTTON_TYPE_TOGGLE,
466 NULL,
467 "nodes_show_handles",
468 _("Show the Bezier handles of selected nodes"),
469 tt);
470 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.nodes", "show_handles", 1));
471 g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (toggle_show_handles), desktop);
472 gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
473 }
475 gtk_box_pack_start(GTK_BOX(cvbox), cbox, TRUE, FALSE, 0);
476 gtk_box_pack_start(GTK_BOX(tb), cvbox, FALSE, FALSE, 0);
478 gtk_widget_show_all(tb);
480 return tb;
482 } // end of sp_node_toolbox_new()
485 //########################
486 //## Zoom Toolbox ##
487 //########################
489 static GtkWidget *
490 sp_zoom_toolbox_new(SPDesktop *desktop)
491 {
492 Inkscape::UI::View::View *view=desktop;
494 GtkTooltips *tt = gtk_tooltips_new();
495 GtkWidget *tb = gtk_hbox_new(FALSE, 0);
497 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0),
498 FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
500 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_IN), view, tt);
502 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_OUT), view, tt);
504 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
506 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_SELECTION), view, tt);
508 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_DRAWING), view, tt);
510 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_PAGE), view, tt);
512 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_PAGE_WIDTH), view, tt);
514 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
516 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_PREV), view, tt);
518 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_NEXT), view, tt);
520 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
522 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_1_1), view, tt);
524 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_1_2), view, tt);
526 sp_toolbox_button_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_2_1), view, tt);
528 gtk_widget_show_all(tb);
530 return tb;
532 } // end of sp_zoom_toolbox_new()
534 void
535 sp_tool_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
536 {
537 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")));
538 }
541 void
542 sp_aux_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
543 {
544 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")));
545 }
547 void
548 sp_commands_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
549 {
550 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")));
551 }
553 static void
554 toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop, SetupFunction setup_func, UpdateFunction update_func, sigc::connection *conn)
555 {
556 gpointer ptr = g_object_get_data(G_OBJECT(toolbox), "desktop");
557 SPDesktop *old_desktop = static_cast<SPDesktop*>(ptr);
559 if (old_desktop) {
560 GList *children, *iter;
562 children = gtk_container_get_children(GTK_CONTAINER(toolbox));
563 for ( iter = children ; iter ; iter = iter->next ) {
564 gtk_container_remove( GTK_CONTAINER(toolbox), GTK_WIDGET(iter->data) );
565 }
566 g_list_free(children);
567 }
569 g_object_set_data(G_OBJECT(toolbox), "desktop", (gpointer)desktop);
571 if (desktop) {
572 gtk_widget_set_sensitive(toolbox, TRUE);
573 setup_func(toolbox, desktop);
574 update_func(desktop, desktop->event_context, toolbox);
575 *conn = desktop->connectEventContextChanged
576 (sigc::bind (sigc::ptr_fun(update_func), toolbox));
577 } else {
578 gtk_widget_set_sensitive(toolbox, FALSE);
579 }
581 } // end of toolbox_set_desktop()
584 static void
585 setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
586 {
587 GtkTooltips *tooltips=GTK_TOOLTIPS(g_object_get_data(G_OBJECT(toolbox), "tooltips"));
588 gint shrinkLeft = prefs_get_int_attribute_limited( "toolbox.left", "small", 0, 0, 1 );
589 Inkscape::IconSize toolboxSize = shrinkLeft ? Inkscape::ICON_SIZE_SMALL_TOOLBAR : Inkscape::ICON_SIZE_LARGE_TOOLBAR;
591 for (int i = 0 ; tools[i].type_name ; i++ ) {
592 GtkWidget *button =
593 sp_toolbox_button_new_from_verb_with_doubleclick( toolbox, toolboxSize,
594 SP_BUTTON_TYPE_TOGGLE,
595 Inkscape::Verb::get(tools[i].verb),
596 Inkscape::Verb::get(tools[i].doubleclick_verb),
597 desktop,
598 tooltips );
600 g_object_set_data( G_OBJECT(toolbox), tools[i].data_name,
601 (gpointer)button );
602 }
603 }
606 static void
607 update_tool_toolbox( SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox )
608 {
609 gchar const *const tname = ( eventcontext
610 ? gtk_type_name(GTK_OBJECT_TYPE(eventcontext))
611 : NULL );
612 for (int i = 0 ; tools[i].type_name ; i++ ) {
613 SPButton *button = SP_BUTTON(g_object_get_data(G_OBJECT(toolbox), tools[i].data_name));
614 sp_button_toggle_set_down(button, tname && !strcmp(tname, tools[i].type_name));
615 }
616 }
618 static void
619 setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
620 {
621 GtkSizeGroup* grouper = gtk_size_group_new( GTK_SIZE_GROUP_BOTH );
623 for (int i = 0 ; aux_toolboxes[i].type_name ; i++ ) {
624 GtkWidget *sub_toolbox;
625 if (aux_toolboxes[i].create_func == NULL)
626 sub_toolbox = sp_empty_toolbox_new(desktop);
627 else
628 sub_toolbox = aux_toolboxes[i].create_func(desktop);
630 gtk_size_group_add_widget( grouper, sub_toolbox );
632 gtk_container_add(GTK_CONTAINER(toolbox), sub_toolbox);
633 g_object_set_data(G_OBJECT(toolbox), aux_toolboxes[i].data_name, sub_toolbox);
634 }
635 g_object_unref( G_OBJECT(grouper) );
636 }
638 static void
639 update_aux_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox)
640 {
641 gchar const *tname = ( eventcontext
642 ? gtk_type_name(GTK_OBJECT_TYPE(eventcontext))
643 : NULL );
644 for (int i = 0 ; aux_toolboxes[i].type_name ; i++ ) {
645 GtkWidget *sub_toolbox = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), aux_toolboxes[i].data_name));
646 if (tname && !strcmp(tname, aux_toolboxes[i].type_name)) {
647 gtk_widget_show_all(sub_toolbox);
648 g_object_set_data(G_OBJECT(toolbox), "shows", sub_toolbox);
649 } else {
650 gtk_widget_hide(sub_toolbox);
651 }
652 }
653 }
655 static void
656 setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
657 {
658 Inkscape::UI::View::View *view = desktop;
660 GtkTooltips *tt = gtk_tooltips_new();
661 GtkWidget *tb = gtk_hbox_new(FALSE, 0);
663 gint shrinkTop = prefs_get_int_attribute_limited( "toolbox", "small", 1, 0, 1 );
664 Inkscape::IconSize toolboxSize = shrinkTop ? Inkscape::ICON_SIZE_SMALL_TOOLBAR : Inkscape::ICON_SIZE_LARGE_TOOLBAR;
666 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_NEW), view, tt);
667 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_OPEN), view, tt);
668 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_SAVE), view, tt);
669 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_PRINT), view, tt);
671 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
673 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_IMPORT), view, tt);
674 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_EXPORT), view, tt);
676 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
678 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_UNDO), view, tt);
679 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_REDO), view, tt);
681 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
683 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_COPY), view, tt);
684 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_CUT), view, tt);
685 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_PASTE), view, tt);
687 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
689 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_SELECTION), view, tt);
690 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_DRAWING), view, tt);
691 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_PAGE), view, tt);
693 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
695 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_DUPLICATE), view, tt);
696 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_CLONE), view, tt);
697 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_UNLINK_CLONE), view, tt);
699 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
701 sp_toolbox_button_normal_new_from_verb(tb, toolboxSize, Inkscape::Verb::get(SP_VERB_SELECTION_GROUP), view, tt);
702 sp_toolbox_button_normal_new_from_verb(tb, toolboxSize, Inkscape::Verb::get(SP_VERB_SELECTION_UNGROUP), view, tt);
704 // disabled until we have icons for them:
706 //find
708 //sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_TILE), view, tt);
709 //sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_UNTILE), view, tt);
711 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
713 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_FILL_STROKE), view, tt);
714 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_TEXT), view, tt);
715 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_XML_EDITOR), view, tt);
716 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_ALIGN_DISTRIBUTE), view, tt);
718 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
720 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_DISPLAY), view, tt);
721 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_NAMEDVIEW), view, tt);
723 gtk_widget_show_all(tb);
725 gtk_container_add(GTK_CONTAINER(toolbox), tb);
726 }
728 static void
729 update_commands_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox)
730 {
731 }
733 void show_aux_toolbox(GtkWidget *toolbox_toplevel)
734 {
735 gtk_widget_show(toolbox_toplevel);
736 GtkWidget *toolbox = gtk_bin_get_child(GTK_BIN(toolbox_toplevel));
738 GtkWidget *shown_toolbox = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), "shows"));
739 if (!shown_toolbox) {
740 return;
741 }
742 gtk_widget_show(toolbox);
744 // need to show the spacer, or the padding will be off
745 GtkWidget *spacer = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), "top_spacer"));
746 gtk_widget_show(spacer);
748 gtk_widget_show_all(shown_toolbox);
749 }
751 void
752 aux_toolbox_space(GtkWidget *tb, gint space)
753 {
754 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, space);
755 }
757 static GtkWidget *
758 sp_empty_toolbox_new(SPDesktop *desktop)
759 {
760 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
761 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
762 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
764 gtk_widget_show_all(tbl);
765 sp_set_font_size_smaller (tbl);
767 return tbl;
768 }
770 // helper UI functions
772 GtkWidget *
773 sp_tb_spinbutton(
774 gchar *label, gchar const *tooltip,
775 gchar const *path, gchar const *data, gdouble def,
776 GtkWidget *us,
777 GtkWidget *tbl,
778 gboolean altx, gchar const *altx_mark,
779 gdouble lower, gdouble upper, gdouble step, gdouble page,
780 void (*callback)(GtkAdjustment *, GtkWidget *),
781 gdouble climb = 0.1, guint digits = 3, double factor = 1.0)
782 {
783 GtkTooltips *tt = gtk_tooltips_new();
785 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
787 GtkWidget *l = gtk_label_new(label);
788 gtk_widget_show(l);
789 gtk_misc_set_alignment(GTK_MISC(l), 1.0, 0.5);
790 gtk_container_add(GTK_CONTAINER(hb), l);
792 GtkObject *a = gtk_adjustment_new(prefs_get_double_attribute(path, data, def) * factor,
793 lower, upper, step, page, page);
794 gtk_object_set_data(GTK_OBJECT(tbl), data, a);
795 if (us)
796 sp_unit_selector_add_adjustment(SP_UNIT_SELECTOR(us), GTK_ADJUSTMENT(a));
798 GtkWidget *sb = gtk_spin_button_new(GTK_ADJUSTMENT(a), climb, digits);
799 gtk_tooltips_set_tip(tt, sb, tooltip, NULL);
800 if (altx)
801 gtk_object_set_data(GTK_OBJECT(sb), altx_mark, sb);
802 gtk_widget_set_size_request(sb,
803 (upper <= 1.0 || digits == 0)? AUX_SPINBUTTON_WIDTH_SMALL - 10: AUX_SPINBUTTON_WIDTH_SMALL,
804 AUX_SPINBUTTON_HEIGHT);
805 gtk_widget_show(sb);
806 gtk_signal_connect(GTK_OBJECT(sb), "focus-in-event", GTK_SIGNAL_FUNC(spinbutton_focus_in), tbl);
807 gtk_signal_connect(GTK_OBJECT(sb), "key-press-event", GTK_SIGNAL_FUNC(spinbutton_keypress), tbl);
808 gtk_container_add(GTK_CONTAINER(hb), sb);
809 gtk_signal_connect(GTK_OBJECT(a), "value_changed", GTK_SIGNAL_FUNC(callback), tbl);
811 return hb;
812 }
814 #define MODE_LABEL_WIDTH 70
816 //########################
817 //## Star ##
818 //########################
820 static void
821 sp_stb_magnitude_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
822 {
823 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
825 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
826 // do not remember prefs if this call is initiated by an undo change, because undoing object
827 // creation sets bogus values to its attributes before it is deleted
828 prefs_set_int_attribute("tools.shapes.star", "magnitude", (gint)adj->value);
829 }
831 // quit if run by the attr_changed listener
832 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
833 return;
834 }
836 // in turn, prevent listener from responding
837 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
839 bool modmade = false;
841 Inkscape::Selection *selection = sp_desktop_selection(desktop);
842 GSList const *items = selection->itemList();
843 for (; items != NULL; items = items->next) {
844 if (SP_IS_STAR((SPItem *) items->data)) {
845 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
846 sp_repr_set_int(repr,"sodipodi:sides",(gint)adj->value);
847 sp_repr_set_svg_double(repr, "sodipodi:arg2",
848 (sp_repr_get_double_attribute(repr, "sodipodi:arg1", 0.5)
849 + M_PI / (gint)adj->value));
850 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
851 modmade = true;
852 }
853 }
854 if (modmade) sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
855 /* TODO: annotate */ "toolbox.cpp:854");
857 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
859 spinbutton_defocus(GTK_OBJECT(tbl));
860 }
862 static void
863 sp_stb_proportion_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
864 {
865 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
867 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
868 prefs_set_double_attribute("tools.shapes.star", "proportion", adj->value);
869 }
871 // quit if run by the attr_changed listener
872 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
873 return;
874 }
876 // in turn, prevent listener from responding
877 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
879 bool modmade = false;
880 Inkscape::Selection *selection = sp_desktop_selection(desktop);
881 GSList const *items = selection->itemList();
882 for (; items != NULL; items = items->next) {
883 if (SP_IS_STAR((SPItem *) items->data)) {
884 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
886 gdouble r1 = sp_repr_get_double_attribute(repr, "sodipodi:r1", 1.0);
887 gdouble r2 = sp_repr_get_double_attribute(repr, "sodipodi:r2", 1.0);
888 if (r2 < r1) {
889 sp_repr_set_svg_double(repr, "sodipodi:r2", r1*adj->value);
890 } else {
891 sp_repr_set_svg_double(repr, "sodipodi:r1", r2*adj->value);
892 }
894 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
895 modmade = true;
896 }
897 }
899 if (modmade) sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
900 /* TODO: annotate */ "toolbox.cpp:899");
902 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
904 spinbutton_defocus(GTK_OBJECT(tbl));
905 }
907 static void
908 sp_stb_sides_flat_state_changed(GtkWidget *widget, GtkObject *tbl)
909 {
910 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
912 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
913 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
914 prefs_set_string_attribute("tools.shapes.star", "isflatsided", "true");
915 } else {
916 prefs_set_string_attribute("tools.shapes.star", "isflatsided", "false");
917 }
918 }
920 // quit if run by the attr_changed listener
921 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
922 return;
923 }
925 // in turn, prevent listener from responding
926 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
928 Inkscape::Selection *selection = sp_desktop_selection(desktop);
929 GSList const *items = selection->itemList();
930 GtkWidget *prop_widget = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "prop_widget");
931 bool modmade = false;
932 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
933 gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), FALSE);
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 repr->setAttribute("inkscape:flatsided", "true");
938 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
939 modmade = true;
940 }
941 }
942 } else {
943 gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), TRUE);
944 for (; items != NULL; items = items->next) {
945 if (SP_IS_STAR((SPItem *) items->data)) {
946 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
947 repr->setAttribute("inkscape:flatsided", "false");
948 SP_OBJECT(items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
949 modmade = true;
950 }
951 }
952 }
953 if (modmade) sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
954 /* TODO: annotate */ "toolbox.cpp:953");
956 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
958 spinbutton_defocus(GTK_OBJECT(tbl));
959 }
961 static void
962 sp_stb_rounded_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
963 {
964 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
966 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
967 prefs_set_double_attribute("tools.shapes.star", "rounded", (gdouble) adj->value);
968 }
970 // quit if run by the attr_changed listener
971 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
972 return;
973 }
975 // in turn, prevent listener from responding
976 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
978 bool modmade = false;
980 Inkscape::Selection *selection = sp_desktop_selection(desktop);
981 GSList const *items = selection->itemList();
982 for (; items != NULL; items = items->next) {
983 if (SP_IS_STAR((SPItem *) items->data)) {
984 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
985 sp_repr_set_svg_double(repr, "inkscape:rounded", (gdouble) adj->value);
986 SP_OBJECT(items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
987 modmade = true;
988 }
989 }
990 if (modmade) sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
991 /* TODO: annotate */ "toolbox.cpp:990");
993 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
995 spinbutton_defocus(GTK_OBJECT(tbl));
996 }
999 static void
1000 sp_stb_randomized_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1001 {
1002 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
1004 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1005 prefs_set_double_attribute("tools.shapes.star", "randomized", (gdouble) adj->value);
1006 }
1008 // quit if run by the attr_changed listener
1009 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1010 return;
1011 }
1013 // in turn, prevent listener from responding
1014 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1016 bool modmade = false;
1018 Inkscape::Selection *selection = sp_desktop_selection(desktop);
1019 GSList const *items = selection->itemList();
1020 for (; items != NULL; items = items->next) {
1021 if (SP_IS_STAR((SPItem *) items->data)) {
1022 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
1023 sp_repr_set_svg_double(repr, "inkscape:randomized", (gdouble) adj->value);
1024 SP_OBJECT(items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
1025 modmade = true;
1026 }
1027 }
1028 if (modmade) sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
1029 /* TODO: annotate */ "toolbox.cpp:1028");
1031 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1033 spinbutton_defocus(GTK_OBJECT(tbl));
1034 }
1037 static void star_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1038 gchar const *old_value, gchar const *new_value,
1039 bool is_interactive, gpointer data)
1040 {
1041 GtkWidget *tbl = GTK_WIDGET(data);
1043 // quit if run by the _changed callbacks
1044 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1045 return;
1046 }
1048 // in turn, prevent callbacks from responding
1049 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1051 GtkAdjustment *adj;
1053 if (!strcmp(name, "inkscape:randomized")) {
1054 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "randomized");
1055 gtk_adjustment_set_value(adj, sp_repr_get_double_attribute(repr, "inkscape:randomized", 0.0));
1056 } else if (!strcmp(name, "inkscape:rounded")) {
1057 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rounded");
1058 gtk_adjustment_set_value(adj, sp_repr_get_double_attribute(repr, "inkscape:rounded", 0.0));
1059 } else if (!strcmp(name, "inkscape:flatsided")) {
1060 GtkWidget *fscb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "flat_checkbox");
1061 GtkWidget *prop_widget = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "prop_widget");
1062 char const *flatsides = repr->attribute("inkscape:flatsided");
1063 if (flatsides && !strcmp(flatsides,"false" )) {
1064 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), FALSE);
1065 gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), TRUE);
1066 } else {
1067 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), TRUE);
1068 gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), FALSE);
1069 }
1070 } else if (!strcmp(name, "sodipodi:r1") || !strcmp(name, "sodipodi:r2")) {
1071 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "proportion");
1072 gdouble r1 = sp_repr_get_double_attribute(repr, "sodipodi:r1", 1.0);
1073 gdouble r2 = sp_repr_get_double_attribute(repr, "sodipodi:r2", 1.0);
1074 if (r2 < r1) {
1075 gtk_adjustment_set_value(adj, r2/r1);
1076 } else {
1077 gtk_adjustment_set_value(adj, r1/r2);
1078 }
1079 } else if (!strcmp(name, "sodipodi:sides")) {
1080 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "magnitude");
1081 gtk_adjustment_set_value(adj, sp_repr_get_int_attribute(repr, "sodipodi:sides", 0));
1082 }
1084 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1085 }
1088 static Inkscape::XML::NodeEventVector star_tb_repr_events =
1089 {
1090 NULL, /* child_added */
1091 NULL, /* child_removed */
1092 star_tb_event_attr_changed,
1093 NULL, /* content_changed */
1094 NULL /* order_changed */
1095 };
1098 /**
1099 * \param selection Should not be NULL.
1100 */
1101 static void
1102 sp_star_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1103 {
1104 int n_selected = 0;
1105 Inkscape::XML::Node *repr = NULL;
1106 Inkscape::XML::Node *oldrepr = NULL;
1108 for (GSList const *items = selection->itemList();
1109 items != NULL;
1110 items = items->next)
1111 {
1112 if (SP_IS_STAR((SPItem *) items->data)) {
1113 n_selected++;
1114 repr = SP_OBJECT_REPR((SPItem *) items->data);
1115 }
1116 }
1118 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
1120 if (n_selected == 0) {
1121 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
1122 } else if (n_selected == 1) {
1123 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1125 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1126 if (oldrepr) { // remove old listener
1127 sp_repr_remove_listener_by_data(oldrepr, tbl);
1128 Inkscape::GC::release(oldrepr);
1129 oldrepr = 0;
1130 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1131 }
1133 if (repr) {
1134 g_object_set_data(G_OBJECT(tbl), "repr", repr);
1135 Inkscape::GC::anchor(repr);
1136 sp_repr_add_listener(repr, &star_tb_repr_events, tbl);
1137 sp_repr_synthesize_events(repr, &star_tb_repr_events, tbl);
1138 }
1139 } else {
1140 // FIXME: implement averaging of all parameters for multiple selected stars
1141 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1142 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1143 }
1144 }
1147 static void
1148 sp_stb_defaults(GtkWidget *widget, GtkWidget *tbl)
1149 {
1150 // FIXME: in this and all other _default functions, set some flag telling the value_changed
1151 // callbacks to lump all the changes for all selected objects in one undo step
1153 GtkAdjustment *adj;
1155 // fixme: make settable in prefs!
1156 gint mag = 5;
1157 gdouble prop = 0.5;
1158 gboolean flat = FALSE;
1159 gdouble randomized = 0;
1160 gdouble rounded = 0;
1162 GtkWidget *fscb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "flat_checkbox");
1163 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), flat);
1164 GtkWidget *sb2 = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "prop_widget");
1165 gtk_widget_set_sensitive(GTK_WIDGET(sb2), !flat);
1167 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "magnitude");
1168 gtk_adjustment_set_value(adj, mag);
1169 gtk_adjustment_value_changed(adj);
1171 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "proportion");
1172 gtk_adjustment_set_value(adj, prop);
1173 gtk_adjustment_value_changed(adj);
1175 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rounded");
1176 gtk_adjustment_set_value(adj, rounded);
1177 gtk_adjustment_value_changed(adj);
1179 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "randomized");
1180 gtk_adjustment_set_value(adj, randomized);
1181 gtk_adjustment_value_changed(adj);
1183 spinbutton_defocus(GTK_OBJECT(tbl));
1184 }
1187 void
1188 sp_toolbox_add_label(GtkWidget *tbl, gchar const *title, bool wide)
1189 {
1190 GtkWidget *boxl = gtk_hbox_new(FALSE, 0);
1191 if (wide) gtk_widget_set_size_request(boxl, MODE_LABEL_WIDTH, -1);
1192 GtkWidget *l = gtk_label_new(NULL);
1193 gtk_label_set_markup(GTK_LABEL(l), title);
1194 gtk_box_pack_end(GTK_BOX(boxl), l, FALSE, FALSE, 0);
1195 gtk_box_pack_start(GTK_BOX(tbl), boxl, FALSE, FALSE, 0);
1196 gtk_object_set_data(GTK_OBJECT(tbl), "mode_label", l);
1197 }
1200 static GtkWidget *
1201 sp_star_toolbox_new(SPDesktop *desktop)
1202 {
1203 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1205 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1206 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1208 GtkTooltips *tt = gtk_tooltips_new();
1210 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1212 gchar const *flatsidedstr = NULL;
1214 /* Flatsided checkbox */
1215 {
1216 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1217 GtkWidget *fscb = gtk_check_button_new_with_label(_("Polygon"));
1218 gtk_widget_set_sensitive(GTK_WIDGET(fscb), TRUE);
1219 flatsidedstr = prefs_get_string_attribute("tools.shapes.star", "isflatsided");
1220 if (!flatsidedstr || (flatsidedstr && !strcmp(flatsidedstr, "false")))
1221 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), FALSE);
1222 else
1223 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), TRUE);
1224 gtk_tooltips_set_tip(tt, fscb, _("Regular polygon (with one handle) instead of a star"), NULL);
1225 gtk_widget_show(fscb);
1226 gtk_object_set_data(GTK_OBJECT(tbl), "flat_checkbox", fscb);
1227 gtk_container_add(GTK_CONTAINER(hb), fscb);
1228 g_signal_connect(G_OBJECT(fscb), "toggled", GTK_SIGNAL_FUNC(sp_stb_sides_flat_state_changed ), tbl);
1229 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_SPACING);
1230 }
1232 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
1234 /* Magnitude */
1235 {
1236 GtkWidget *hb = sp_tb_spinbutton(_("Corners:"), _("Number of corners of a polygon or star"),
1237 "tools.shapes.star", "magnitude", 3,
1238 NULL, tbl, TRUE, "altx-star",
1239 3, 1024, 1, 1,
1240 sp_stb_magnitude_value_changed, 1, 0);
1241 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1242 }
1244 /* Spoke ratio */
1245 {
1246 GtkWidget *hb = sp_tb_spinbutton(_("Spoke ratio:"),
1247 // TRANSLATORS: Tip radius of a star is the distance from the center to the farthest handle.
1248 // Base radius is the same for the closest handle.
1249 _("Base radius to tip radius ratio"),
1250 "tools.shapes.star", "proportion", 0.5,
1251 NULL, tbl, FALSE, NULL,
1252 0.01, 1.0, 0.01, 0.1,
1253 sp_stb_proportion_value_changed);
1254 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1255 g_object_set_data(G_OBJECT(tbl), "prop_widget", hb);
1256 if (!flatsidedstr || (flatsidedstr && !strcmp(flatsidedstr, "false")))
1257 gtk_widget_set_sensitive(GTK_WIDGET(hb), TRUE);
1258 else
1259 gtk_widget_set_sensitive(GTK_WIDGET(hb), FALSE);
1260 }
1262 /* Roundedness */
1263 {
1264 GtkWidget *hb = sp_tb_spinbutton(_("Rounded:"), _("How much rounded are the corners (0 for sharp)"),
1265 "tools.shapes.star", "rounded", 0.0,
1266 NULL, tbl, FALSE, NULL,
1267 -100.0, 100.0, 0.01, 0.1,
1268 sp_stb_rounded_value_changed);
1269 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1270 }
1272 /* Randomization */
1273 {
1274 GtkWidget *hb = sp_tb_spinbutton(_("Randomized:"), _("Scatter randomly the corners and angles"),
1275 "tools.shapes.star", "randomized", 0.0,
1276 NULL, tbl, FALSE, NULL,
1277 -10.0, 10.0, 0.001, 0.01,
1278 sp_stb_randomized_value_changed, 0.1, 3);
1279 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1280 }
1282 aux_toolbox_space(tbl, AUX_SPACING);
1284 /* Reset */
1285 {
1286 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1287 GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
1288 gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
1289 gtk_widget_show(b);
1290 gtk_container_add(GTK_CONTAINER(hb), b);
1291 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_stb_defaults), tbl);
1292 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_SPACING);
1293 }
1295 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1296 swatch->setWatchedTool ("tools.shapes.star", true);
1297 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1298 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1300 gtk_widget_show_all(tbl);
1301 sp_set_font_size_smaller (tbl);
1303 sigc::connection *connection = new sigc::connection(
1304 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_star_toolbox_selection_changed), (GtkObject *)tbl))
1305 );
1306 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1308 return tbl;
1309 }
1312 //########################
1313 //## Rect ##
1314 //########################
1316 static void
1317 sp_rtb_sensitivize (GtkWidget *tbl)
1318 {
1319 GtkAdjustment *adj1 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "rx"));
1320 GtkAdjustment *adj2 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "ry"));
1321 GtkWidget *not_rounded = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "not_rounded");
1323 if (adj1->value == 0 && adj2->value == 0 && gtk_object_get_data(GTK_OBJECT(tbl), "single")) { // only for a single selected rect (for now)
1324 gtk_widget_set_sensitive(GTK_WIDGET(not_rounded), FALSE);
1325 } else {
1326 gtk_widget_set_sensitive(GTK_WIDGET(not_rounded), TRUE);
1327 }
1328 }
1331 static void
1332 sp_rtb_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name,
1333 void (*setter)(SPRect *, gdouble))
1334 {
1335 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
1337 GtkWidget *us = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tbl), "units");
1338 SPUnit const *unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(us));
1340 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1341 prefs_set_double_attribute("tools.shapes.rect", value_name, sp_units_get_pixels(adj->value, *unit));
1342 }
1344 // quit if run by the attr_changed listener
1345 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1346 return;
1347 }
1349 // in turn, prevent listener from responding
1350 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1352 bool modmade = false;
1353 Inkscape::Selection *selection = sp_desktop_selection(desktop);
1354 for (GSList const *items = selection->itemList(); items != NULL; items = items->next) {
1355 if (SP_IS_RECT(items->data)) {
1356 if (adj->value != 0) {
1357 setter(SP_RECT(items->data), sp_units_get_pixels(adj->value, *unit));
1358 } else {
1359 SP_OBJECT_REPR(items->data)->setAttribute(value_name, NULL);
1360 }
1361 modmade = true;
1362 }
1363 }
1365 sp_rtb_sensitivize (tbl);
1367 if (modmade) {
1368 sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_RECT,
1369 /* TODO: annotate */ "toolbox.cpp:1368");
1370 }
1372 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1374 // defocus spinbuttons by moving focus to the canvas, unless "stay" is on
1375 spinbutton_defocus(GTK_OBJECT(tbl));
1376 }
1378 static void
1379 sp_rtb_rx_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1380 {
1381 sp_rtb_value_changed(adj, tbl, "rx", sp_rect_set_visible_rx);
1382 }
1384 static void
1385 sp_rtb_ry_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1386 {
1387 sp_rtb_value_changed(adj, tbl, "ry", sp_rect_set_visible_ry);
1388 }
1390 static void
1391 sp_rtb_width_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1392 {
1393 sp_rtb_value_changed(adj, tbl, "width", sp_rect_set_visible_width);
1394 }
1396 static void
1397 sp_rtb_height_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1398 {
1399 sp_rtb_value_changed(adj, tbl, "height", sp_rect_set_visible_height);
1400 }
1404 static void
1405 sp_rtb_defaults( GtkWidget *widget, GtkObject *obj)
1406 {
1407 GtkWidget *tbl = GTK_WIDGET(obj);
1409 GtkAdjustment *adj;
1411 adj = (GtkAdjustment*)gtk_object_get_data(obj, "rx");
1412 gtk_adjustment_set_value(adj, 0.0);
1413 // this is necessary if the previous value was 0, but we still need to run the callback to change all selected objects
1414 gtk_adjustment_value_changed(adj);
1416 adj = (GtkAdjustment*)gtk_object_get_data(obj, "ry");
1417 gtk_adjustment_set_value(adj, 0.0);
1418 gtk_adjustment_value_changed(adj);
1420 sp_rtb_sensitivize (tbl);
1422 spinbutton_defocus(GTK_OBJECT(tbl));
1423 }
1425 static void rect_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1426 gchar const *old_value, gchar const *new_value,
1427 bool is_interactive, gpointer data)
1428 {
1429 GtkWidget *tbl = GTK_WIDGET(data);
1431 // quit if run by the _changed callbacks
1432 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1433 return;
1434 }
1436 // in turn, prevent callbacks from responding
1437 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1439 GtkWidget *us = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tbl), "units");
1440 SPUnit const *unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(us));
1442 SPItem *item = SP_ITEM(g_object_get_data(G_OBJECT(tbl), "item"));
1443 if (SP_IS_RECT(item)) {
1444 {
1445 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rx");
1446 gdouble rx = sp_rect_get_visible_rx(SP_RECT(item));
1447 gtk_adjustment_set_value(adj, sp_pixels_get_units(rx, *unit));
1448 }
1450 {
1451 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "ry");
1452 gdouble ry = sp_rect_get_visible_ry(SP_RECT(item));
1453 gtk_adjustment_set_value(adj, sp_pixels_get_units(ry, *unit));
1454 }
1456 {
1457 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "width");
1458 gdouble width = sp_rect_get_visible_width (SP_RECT(item));
1459 gtk_adjustment_set_value(adj, sp_pixels_get_units(width, *unit));
1460 }
1462 {
1463 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "height");
1464 gdouble height = sp_rect_get_visible_height (SP_RECT(item));
1465 gtk_adjustment_set_value(adj, sp_pixels_get_units(height, *unit));
1466 }
1467 }
1469 sp_rtb_sensitivize (tbl);
1471 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1472 }
1475 static Inkscape::XML::NodeEventVector rect_tb_repr_events = {
1476 NULL, /* child_added */
1477 NULL, /* child_removed */
1478 rect_tb_event_attr_changed,
1479 NULL, /* content_changed */
1480 NULL /* order_changed */
1481 };
1483 /**
1484 * \param selection should not be NULL.
1485 */
1486 static void
1487 sp_rect_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1488 {
1489 int n_selected = 0;
1490 Inkscape::XML::Node *repr = NULL;
1491 SPItem *item = NULL;
1492 Inkscape::XML::Node *oldrepr = NULL;
1494 for (GSList const *items = selection->itemList();
1495 items != NULL;
1496 items = items->next) {
1497 if (SP_IS_RECT((SPItem *) items->data)) {
1498 n_selected++;
1499 item = (SPItem *) items->data;
1500 repr = SP_OBJECT_REPR(item);
1501 }
1502 }
1504 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
1506 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(FALSE));
1508 if (n_selected == 0) {
1509 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
1511 GtkWidget *w = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "width_sb");
1512 gtk_widget_set_sensitive(w, FALSE);
1513 GtkWidget *h = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "height_sb");
1514 gtk_widget_set_sensitive(h, FALSE);
1516 } else if (n_selected == 1) {
1517 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1518 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
1520 GtkWidget *w = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "width_sb");
1521 gtk_widget_set_sensitive(w, TRUE);
1522 GtkWidget *h = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "height_sb");
1523 gtk_widget_set_sensitive(h, TRUE);
1525 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1526 if (oldrepr) { // remove old listener
1527 sp_repr_remove_listener_by_data(oldrepr, tbl);
1528 Inkscape::GC::release(oldrepr);
1529 oldrepr = 0;
1530 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1531 }
1532 if (repr) {
1533 g_object_set_data(G_OBJECT(tbl), "repr", repr);
1534 g_object_set_data(G_OBJECT(tbl), "item", item);
1535 Inkscape::GC::anchor(repr);
1536 sp_repr_add_listener(repr, &rect_tb_repr_events, tbl);
1537 sp_repr_synthesize_events(repr, &rect_tb_repr_events, tbl);
1538 }
1539 } else {
1540 // FIXME: implement averaging of all parameters for multiple selected
1541 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1542 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1543 sp_rtb_sensitivize (GTK_WIDGET(tbl));
1544 }
1545 }
1548 static GtkWidget *
1549 sp_rect_toolbox_new(SPDesktop *desktop)
1550 {
1551 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1553 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1554 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1556 GtkTooltips *tt = gtk_tooltips_new();
1558 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1560 // rx/ry units menu: create
1561 GtkWidget *us = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
1562 sp_unit_selector_setsize(us, AUX_OPTION_MENU_WIDTH, AUX_OPTION_MENU_HEIGHT);
1563 sp_unit_selector_set_unit(SP_UNIT_SELECTOR(us), desktop->namedview->doc_units);
1564 // fixme: add % meaning per cent of the width/height
1566 /* W */
1567 {
1568 GtkWidget *hb = sp_tb_spinbutton(_("W:"), _("Width of rectangle"),
1569 "tools.shapes.rect", "width", 0,
1570 us, tbl, TRUE, "altx-rect",
1571 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1572 sp_rtb_width_value_changed);
1573 gtk_object_set_data(GTK_OBJECT(tbl), "width_sb", hb);
1574 gtk_widget_set_sensitive(hb, FALSE);
1575 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1576 }
1578 /* H */
1579 {
1580 GtkWidget *hb = sp_tb_spinbutton(_("H:"), _("Height of rectangle"),
1581 "tools.shapes.rect", "height", 0,
1582 us, tbl, FALSE, NULL,
1583 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1584 sp_rtb_height_value_changed);
1585 gtk_object_set_data(GTK_OBJECT(tbl), "height_sb", hb);
1586 gtk_widget_set_sensitive(hb, FALSE);
1587 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1588 }
1590 /* rx */
1591 {
1592 GtkWidget *hb = sp_tb_spinbutton(_("Rx:"), _("Horizontal radius of rounded corners"),
1593 "tools.shapes.rect", "rx", 0,
1594 us, tbl, FALSE, NULL,
1595 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1596 sp_rtb_rx_value_changed);
1597 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1598 }
1600 /* ry */
1601 {
1602 GtkWidget *hb = sp_tb_spinbutton(_("Ry:"), _("Vertical radius of rounded corners"),
1603 "tools.shapes.rect", "ry", 0,
1604 us, tbl, FALSE, NULL,
1605 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1606 sp_rtb_ry_value_changed);
1607 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1608 }
1610 // add the units menu
1611 gtk_widget_show(us);
1612 gtk_box_pack_start(GTK_BOX(tbl), us, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1613 gtk_object_set_data(GTK_OBJECT(tbl), "units", us);
1615 /* Reset */
1616 {
1617 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1618 GtkWidget *b = gtk_button_new_with_label(_("Not rounded"));
1619 gtk_object_set_data(GTK_OBJECT(tbl), "not_rounded", b);
1620 gtk_tooltips_set_tip(tt, b, _("Make corners sharp"), NULL);
1621 gtk_widget_show(b);
1622 gtk_container_add(GTK_CONTAINER(hb), b);
1623 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_rtb_defaults), tbl);
1624 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1625 }
1627 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1628 swatch->setWatchedTool ("tools.shapes.rect", true);
1629 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1630 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1632 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
1633 sp_rtb_sensitivize (tbl);
1635 gtk_widget_show_all(tbl);
1636 sp_set_font_size_smaller (tbl);
1638 sigc::connection *connection = new sigc::connection(
1639 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_rect_toolbox_selection_changed), (GtkObject *)tbl))
1640 );
1641 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1643 return tbl;
1644 }
1646 //########################
1647 //## Spiral ##
1648 //########################
1650 static void
1651 sp_spl_tb_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name)
1652 {
1653 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
1655 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1656 prefs_set_double_attribute("tools.shapes.spiral", value_name, adj->value);
1657 }
1659 // quit if run by the attr_changed listener
1660 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1661 return;
1662 }
1664 // in turn, prevent listener from responding
1665 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1667 gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
1669 bool modmade = false;
1670 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
1671 items != NULL;
1672 items = items->next)
1673 {
1674 if (SP_IS_SPIRAL((SPItem *) items->data)) {
1675 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
1676 sp_repr_set_svg_double( repr, namespaced_name, adj->value );
1677 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
1678 modmade = true;
1679 }
1680 }
1682 g_free(namespaced_name);
1684 if (modmade) {
1685 sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_SPIRAL,
1686 /* TODO: annotate */ "toolbox.cpp:1685");
1687 }
1689 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1691 spinbutton_defocus(GTK_OBJECT(tbl));
1692 }
1694 static void
1695 sp_spl_tb_revolution_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1696 {
1697 sp_spl_tb_value_changed(adj, tbl, "revolution");
1698 }
1700 static void
1701 sp_spl_tb_expansion_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1702 {
1703 sp_spl_tb_value_changed(adj, tbl, "expansion");
1704 }
1706 static void
1707 sp_spl_tb_t0_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1708 {
1709 sp_spl_tb_value_changed(adj, tbl, "t0");
1710 }
1712 static void
1713 sp_spl_tb_defaults(GtkWidget *widget, GtkObject *obj)
1714 {
1715 GtkWidget *tbl = GTK_WIDGET(obj);
1717 GtkAdjustment *adj;
1719 // fixme: make settable
1720 gdouble rev = 5;
1721 gdouble exp = 1.0;
1722 gdouble t0 = 0.0;
1724 adj = (GtkAdjustment*)gtk_object_get_data(obj, "revolution");
1725 gtk_adjustment_set_value(adj, rev);
1726 gtk_adjustment_value_changed(adj);
1728 adj = (GtkAdjustment*)gtk_object_get_data(obj, "expansion");
1729 gtk_adjustment_set_value(adj, exp);
1730 gtk_adjustment_value_changed(adj);
1732 adj = (GtkAdjustment*)gtk_object_get_data(obj, "t0");
1733 gtk_adjustment_set_value(adj, t0);
1734 gtk_adjustment_value_changed(adj);
1736 spinbutton_defocus(GTK_OBJECT(tbl));
1737 }
1740 static void spiral_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1741 gchar const *old_value, gchar const *new_value,
1742 bool is_interactive, gpointer data)
1743 {
1744 GtkWidget *tbl = GTK_WIDGET(data);
1746 // quit if run by the _changed callbacks
1747 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1748 return;
1749 }
1751 // in turn, prevent callbacks from responding
1752 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1754 GtkAdjustment *adj;
1755 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "revolution");
1756 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:revolution", 3.0)));
1758 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "expansion");
1759 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:expansion", 1.0)));
1761 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "t0");
1762 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:t0", 0.0)));
1764 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1765 }
1768 static Inkscape::XML::NodeEventVector spiral_tb_repr_events = {
1769 NULL, /* child_added */
1770 NULL, /* child_removed */
1771 spiral_tb_event_attr_changed,
1772 NULL, /* content_changed */
1773 NULL /* order_changed */
1774 };
1776 static void
1777 sp_spiral_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1778 {
1779 int n_selected = 0;
1780 Inkscape::XML::Node *repr = NULL;
1781 Inkscape::XML::Node *oldrepr = NULL;
1783 for (GSList const *items = selection->itemList();
1784 items != NULL;
1785 items = items->next)
1786 {
1787 if (SP_IS_SPIRAL((SPItem *) items->data)) {
1788 n_selected++;
1789 repr = SP_OBJECT_REPR((SPItem *) items->data);
1790 }
1791 }
1793 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
1795 if (n_selected == 0) {
1796 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
1797 } else if (n_selected == 1) {
1798 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1800 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1801 if (oldrepr) { // remove old listener
1802 sp_repr_remove_listener_by_data(oldrepr, tbl);
1803 Inkscape::GC::release(oldrepr);
1804 oldrepr = 0;
1805 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1806 }
1808 if (repr) {
1809 g_object_set_data(G_OBJECT(tbl), "repr", repr);
1810 Inkscape::GC::anchor(repr);
1811 sp_repr_add_listener(repr, &spiral_tb_repr_events, tbl);
1812 sp_repr_synthesize_events(repr, &spiral_tb_repr_events, tbl);
1813 }
1814 } else {
1815 // FIXME: implement averaging of all parameters for multiple selected
1816 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1817 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1818 }
1819 }
1822 static GtkWidget *
1823 sp_spiral_toolbox_new(SPDesktop *desktop)
1824 {
1825 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1826 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1827 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1829 GtkTooltips *tt = gtk_tooltips_new();
1831 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1833 /* Revolution */
1834 {
1835 GtkWidget *hb = sp_tb_spinbutton(_("Turns:"), _("Number of revolutions"),
1836 "tools.shapes.spiral", "revolution", 3.0,
1837 NULL, tbl, TRUE, "altx-spiral",
1838 0.01, 1024.0, 0.1, 1.0,
1839 sp_spl_tb_revolution_value_changed, 1, 2);
1840 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1841 }
1843 /* Expansion */
1844 {
1845 GtkWidget *hb = sp_tb_spinbutton(_("Divergence:"), _("How much denser/sparser are outer revolutions; 1 = uniform"),
1846 "tools.shapes.spiral", "expansion", 1.0,
1847 NULL, tbl, FALSE, NULL,
1848 0.0, 1000.0, 0.01, 1.0,
1849 sp_spl_tb_expansion_value_changed);
1850 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1851 }
1853 /* T0 */
1854 {
1855 GtkWidget *hb = sp_tb_spinbutton(_("Inner radius:"), _("Radius of the innermost revolution (relative to the spiral size)"),
1856 "tools.shapes.spiral", "t0", 0.0,
1857 NULL, tbl, FALSE, NULL,
1858 0.0, 0.999, 0.01, 1.0,
1859 sp_spl_tb_t0_value_changed);
1860 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1861 }
1863 aux_toolbox_space(tbl, AUX_SPACING);
1865 /* Reset */
1866 {
1867 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1868 GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
1869 gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
1870 gtk_widget_show(b);
1871 gtk_container_add(GTK_CONTAINER(hb), b);
1872 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_spl_tb_defaults), tbl);
1873 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1874 }
1876 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1877 swatch->setWatchedTool ("tools.shapes.spiral", true);
1878 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1879 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1881 gtk_widget_show_all(tbl);
1882 sp_set_font_size_smaller (tbl);
1884 sigc::connection *connection = new sigc::connection(
1885 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_spiral_toolbox_selection_changed), (GtkObject *)tbl))
1886 );
1887 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1889 return tbl;
1890 }
1892 //########################
1893 //## Pen/Pencil ##
1894 //########################
1897 static GtkWidget *
1898 sp_pen_toolbox_new(SPDesktop *desktop)
1899 {
1900 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1901 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1902 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1904 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1905 swatch->setWatchedTool ("tools.freehand.pen", true);
1906 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1907 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1909 gtk_widget_show_all(tbl);
1910 sp_set_font_size_smaller (tbl);
1912 return tbl;
1913 }
1915 static GtkWidget *
1916 sp_pencil_toolbox_new(SPDesktop *desktop)
1917 {
1918 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1919 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1920 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1922 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1923 swatch->setWatchedTool ("tools.freehand.pencil", true);
1924 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1925 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1927 gtk_widget_show_all(tbl);
1928 sp_set_font_size_smaller (tbl);
1930 return tbl;
1931 }
1934 //########################
1935 //## Calligraphy ##
1936 //########################
1938 static void
1939 sp_ddc_mass_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1940 {
1941 prefs_set_double_attribute("tools.calligraphic", "mass", adj->value);
1942 spinbutton_defocus(GTK_OBJECT(tbl));
1943 }
1945 static void
1946 sp_ddc_drag_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1947 {
1948 prefs_set_double_attribute("tools.calligraphic", "drag", adj->value);
1949 spinbutton_defocus(GTK_OBJECT(tbl));
1950 }
1952 static void
1953 sp_ddc_angle_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1954 {
1955 prefs_set_double_attribute("tools.calligraphic", "angle", adj->value);
1956 spinbutton_defocus(GTK_OBJECT(tbl));
1957 }
1959 static void
1960 sp_ddc_width_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1961 {
1962 prefs_set_double_attribute("tools.calligraphic", "width", adj->value * 0.01);
1963 spinbutton_defocus(GTK_OBJECT(tbl));
1964 }
1966 static void
1967 sp_ddc_velthin_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1968 {
1969 prefs_set_double_attribute("tools.calligraphic", "thinning", adj->value);
1970 spinbutton_defocus(GTK_OBJECT(tbl));
1971 }
1973 static void
1974 sp_ddc_flatness_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1975 {
1976 prefs_set_double_attribute("tools.calligraphic", "flatness", adj->value);
1977 spinbutton_defocus(GTK_OBJECT(tbl));
1978 }
1980 static void
1981 sp_ddc_tremor_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1982 {
1983 prefs_set_double_attribute("tools.calligraphic", "tremor", adj->value);
1984 spinbutton_defocus(GTK_OBJECT(tbl));
1985 }
1987 static void
1988 sp_ddc_pressure_state_changed(GtkWidget *button, gpointer data)
1989 {
1990 prefs_set_int_attribute ("tools.calligraphic", "usepressure", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0);
1991 }
1993 static void
1994 sp_ddc_tilt_state_changed(GtkWidget *button, GtkWidget *calligraphy_angle)
1995 {
1996 prefs_set_int_attribute ("tools.calligraphic", "usetilt", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0);
1998 gtk_widget_set_sensitive(GTK_WIDGET(calligraphy_angle), !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
1999 }
2001 static void sp_ddc_defaults(GtkWidget *, GtkWidget *tbl)
2002 {
2003 // FIXME: make defaults settable via Inkscape Options
2004 struct KeyValue {
2005 char const *key;
2006 double value;
2007 } const key_values[] = {
2008 {"mass", 0.02},
2009 {"drag", 1.0},
2010 {"angle", 30.0},
2011 {"width", 15},
2012 {"thinning", 0.1},
2013 {"tremor", 0.0},
2014 {"flatness", 0.9}
2015 };
2017 for (unsigned i = 0; i < G_N_ELEMENTS(key_values); ++i) {
2018 KeyValue const &kv = key_values[i];
2019 GtkAdjustment &adj = *static_cast<GtkAdjustment *>(gtk_object_get_data(GTK_OBJECT(tbl), kv.key));
2020 gtk_adjustment_set_value(&adj, kv.value);
2021 }
2023 spinbutton_defocus(GTK_OBJECT(tbl));
2024 }
2026 static GtkWidget *
2027 sp_calligraphy_toolbox_new(SPDesktop *desktop)
2028 {
2029 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2030 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2031 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2033 GtkTooltips *tt = gtk_tooltips_new();
2034 GtkWidget *calligraphy_angle;
2036 // interval
2037 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2039 /* Width */
2040 {
2041 GtkWidget *hb = sp_tb_spinbutton(_("Width:"), _("The width of the calligraphic pen (relative to the visible canvas area)"),
2042 "tools.calligraphic", "width", 15,
2043 NULL, tbl, TRUE, "altx-calligraphy",
2044 1, 100, 1.0, 10.0,
2045 sp_ddc_width_value_changed, 0.01, 0, 100);
2046 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2047 }
2049 /* Thinning */
2050 {
2051 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)"),
2052 "tools.calligraphic", "thinning", 0.1,
2053 NULL, tbl, FALSE, NULL,
2054 -1.0, 1.0, 0.01, 0.1,
2055 sp_ddc_velthin_value_changed, 0.01, 2);
2056 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2057 }
2059 // interval
2060 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2062 /* Angle */
2063 {
2064 calligraphy_angle = sp_tb_spinbutton(_("Angle:"), _("The angle of the pen's nib (in degrees; 0 = horizontal; has no effect if fixation = 0)"),
2065 "tools.calligraphic", "angle", 30,
2066 NULL, tbl, TRUE, "calligraphy-angle",
2067 -90.0, 90.0, 1.0, 10.0,
2068 sp_ddc_angle_value_changed, 1, 0);
2069 gtk_box_pack_start(GTK_BOX(tbl), calligraphy_angle, FALSE, FALSE, AUX_SPACING);
2070 }
2072 /* Fixation */
2073 {
2074 GtkWidget *hb = sp_tb_spinbutton(_("Fixation:"), _("How fixed is the pen angle (0 = always perpendicular to stroke direction, 1 = fixed)"),
2075 "tools.calligraphic", "flatness", 0.9,
2076 NULL, tbl, FALSE, NULL,
2077 0.0, 1.0, 0.01, 0.1,
2078 sp_ddc_flatness_value_changed, 0.01, 2);
2079 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2080 }
2082 // interval
2083 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2085 /* Tremor */
2086 {
2087 GtkWidget *hb = sp_tb_spinbutton(_("Tremor:"), _("How uneven or trembling is the pen stroke"),
2088 "tools.calligraphic", "tremor", 0.0,
2089 NULL, tbl, FALSE, NULL,
2090 0.0, 1.0, 0.01, 0.1,
2091 sp_ddc_tremor_value_changed, 0.01, 2);
2092 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2093 }
2094 /* Mass */
2095 {
2096 GtkWidget *hb = sp_tb_spinbutton(_("Mass:"), _("How much inertia affects the movement of the pen"),
2097 "tools.calligraphic", "mass", 0.02,
2098 NULL, tbl, FALSE, NULL,
2099 0.0, 1.0, 0.01, 0.1,
2100 sp_ddc_mass_value_changed, 0.01, 2);
2101 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2102 }
2104 /* Drag */
2105 {
2106 // TRANSLATORS: "drag" means "resistance" here
2107 GtkWidget *hb = sp_tb_spinbutton(_("Drag:"), _("How much resistance affects the movement of the pen"),
2108 "tools.calligraphic", "drag", 1,
2109 NULL, tbl, FALSE, NULL,
2110 0.0, 1.0, 0.01, 0.1,
2111 sp_ddc_drag_value_changed, 0.01, 2);
2112 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2113 }
2115 // interval
2116 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2118 GtkWidget *cvbox = gtk_vbox_new (FALSE, 0);
2119 GtkWidget *cbox = gtk_hbox_new (FALSE, 0);
2121 /* Use Pressure button */
2122 {
2123 GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
2124 SP_BUTTON_TYPE_TOGGLE,
2125 NULL,
2126 "use_pressure",
2127 _("Use the pressure of the input device to alter the width of the pen"),
2128 tt);
2129 g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (sp_ddc_pressure_state_changed), NULL);
2130 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.calligraphic", "usepressure", 1));
2131 gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
2132 }
2134 /* Use Tilt button */
2135 {
2136 GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
2137 SP_BUTTON_TYPE_TOGGLE,
2138 NULL,
2139 "use_tilt",
2140 _("Use the tilt of the input device to alter the angle of the pen's nib"),
2141 tt);
2142 g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (sp_ddc_tilt_state_changed), calligraphy_angle);
2143 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.calligraphic", "usetilt", 1));
2144 gtk_widget_set_sensitive(GTK_WIDGET(calligraphy_angle), !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
2145 gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
2146 }
2148 gtk_box_pack_start(GTK_BOX(cvbox), cbox, TRUE, FALSE, 0);
2149 gtk_box_pack_start(GTK_BOX(tbl), cvbox, FALSE, FALSE, 0);
2151 /* Reset */
2152 {
2153 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2154 GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
2155 gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
2156 gtk_widget_show(b);
2157 gtk_container_add(GTK_CONTAINER(hb), b);
2158 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_ddc_defaults), tbl);
2159 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2160 }
2163 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
2164 swatch->setWatchedTool ("tools.calligraphic", true);
2165 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
2166 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
2168 gtk_widget_show_all(tbl);
2169 sp_set_font_size_smaller (tbl);
2171 return tbl;
2172 }
2175 //########################
2176 //## Circle / Arc ##
2177 //########################
2179 static void
2180 sp_arctb_sensitivize (GtkWidget *tbl, double v1, double v2)
2181 {
2182 GtkWidget *ocb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "open_checkbox");
2183 GtkWidget *make_whole = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "make_whole");
2185 if (v1 == 0 && v2 == 0) {
2186 if (gtk_object_get_data(GTK_OBJECT(tbl), "single")) { // only for a single selected ellipse (for now)
2187 gtk_widget_set_sensitive(GTK_WIDGET(ocb), FALSE);
2188 gtk_widget_set_sensitive(GTK_WIDGET(make_whole), FALSE);
2189 }
2190 } else {
2191 gtk_widget_set_sensitive(GTK_WIDGET(ocb), TRUE);
2192 gtk_widget_set_sensitive(GTK_WIDGET(make_whole), TRUE);
2193 }
2194 }
2196 static void
2197 sp_arctb_startend_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name, gchar const *other_name)
2198 {
2199 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2201 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2202 prefs_set_double_attribute("tools.shapes.arc", value_name, (adj->value * M_PI)/ 180);
2203 }
2205 // quit if run by the attr_changed listener
2206 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2207 return;
2208 }
2210 // in turn, prevent listener from responding
2211 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2213 gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
2215 bool modmade = false;
2216 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2217 items != NULL;
2218 items = items->next)
2219 {
2220 SPItem *item = SP_ITEM(items->data);
2222 if (SP_IS_ARC(item) && SP_IS_GENERICELLIPSE(item)) {
2224 SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
2225 SPArc *arc = SP_ARC(item);
2227 if (!strcmp(value_name, "start"))
2228 ge->start = (adj->value * M_PI)/ 180;
2229 else
2230 ge->end = (adj->value * M_PI)/ 180;
2232 sp_genericellipse_normalize(ge);
2233 ((SPObject *)arc)->updateRepr();
2234 ((SPObject *)arc)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
2236 modmade = true;
2237 }
2238 }
2240 g_free(namespaced_name);
2242 GtkAdjustment *other = (GtkAdjustment *)gtk_object_get_data(GTK_OBJECT(tbl), other_name);
2244 sp_arctb_sensitivize (tbl, adj->value, other->value);
2246 if (modmade) {
2247 sp_document_maybe_done(sp_desktop_document(desktop), value_name, SP_VERB_CONTEXT_ARC,
2248 /* TODO: annotate */ "toolbox.cpp:2247");
2249 }
2251 // defocus spinbuttons by moving focus to the canvas, unless "stay" is on
2252 spinbutton_defocus(GTK_OBJECT(tbl));
2254 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2255 }
2258 static void
2259 sp_arctb_start_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
2260 {
2261 sp_arctb_startend_value_changed(adj, tbl, "start", "end");
2262 }
2264 static void
2265 sp_arctb_end_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
2266 {
2267 sp_arctb_startend_value_changed(adj, tbl, "end", "start");
2268 }
2270 static void
2271 sp_arctb_open_state_changed(GtkWidget *widget, GtkObject *tbl)
2272 {
2273 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2275 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2276 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
2277 prefs_set_string_attribute("tools.shapes.arc", "open", "true");
2278 } else {
2279 prefs_set_string_attribute("tools.shapes.arc", "open", NULL);
2280 }
2281 }
2283 // quit if run by the attr_changed listener
2284 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2285 return;
2286 }
2288 // in turn, prevent listener from responding
2289 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2291 bool modmade = false;
2293 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
2294 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2295 items != NULL;
2296 items = items->next)
2297 {
2298 if (SP_IS_ARC((SPItem *) items->data)) {
2299 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2300 repr->setAttribute("sodipodi:open", "true");
2301 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
2302 modmade = true;
2303 }
2304 }
2305 } else {
2306 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2307 items != NULL;
2308 items = items->next)
2309 {
2310 if (SP_IS_ARC((SPItem *) items->data)) {
2311 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2312 repr->setAttribute("sodipodi:open", NULL);
2313 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
2314 modmade = true;
2315 }
2316 }
2317 }
2319 if (modmade) {
2320 sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_ARC,
2321 /* TODO: annotate */ "toolbox.cpp:2320");
2322 }
2324 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2326 spinbutton_defocus(GTK_OBJECT(tbl));
2327 }
2329 static void sp_arctb_defaults(GtkWidget *, GtkObject *obj)
2330 {
2331 GtkWidget *tbl = GTK_WIDGET(obj);
2333 GtkAdjustment *adj;
2334 adj = (GtkAdjustment*)gtk_object_get_data(obj, "start");
2335 gtk_adjustment_set_value(adj, 0.0);
2336 gtk_adjustment_value_changed(adj);
2338 adj = (GtkAdjustment*)gtk_object_get_data(obj, "end");
2339 gtk_adjustment_set_value(adj, 0.0);
2340 gtk_adjustment_value_changed(adj);
2342 spinbutton_defocus(GTK_OBJECT(tbl));
2343 }
2345 static void arc_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
2346 gchar const *old_value, gchar const *new_value,
2347 bool is_interactive, gpointer data)
2348 {
2349 GtkWidget *tbl = GTK_WIDGET(data);
2351 // quit if run by the _changed callbacks
2352 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2353 return;
2354 }
2356 // in turn, prevent callbacks from responding
2357 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2359 gdouble start = sp_repr_get_double_attribute(repr, "sodipodi:start", 0.0);
2360 gdouble end = sp_repr_get_double_attribute(repr, "sodipodi:end", 0.0);
2362 GtkAdjustment *adj1,*adj2;
2363 adj1 = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "start");
2364 gtk_adjustment_set_value(adj1, mod360((start * 180)/M_PI));
2365 adj2 = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "end");
2366 gtk_adjustment_set_value(adj2, mod360((end * 180)/M_PI));
2368 sp_arctb_sensitivize (tbl, adj1->value, adj2->value);
2370 char const *openstr = NULL;
2371 openstr = repr->attribute("sodipodi:open");
2372 GtkWidget *ocb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "open_checkbox");
2374 if (openstr) {
2375 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ocb), TRUE);
2376 } else {
2377 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ocb), FALSE);
2378 }
2380 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2381 }
2383 static Inkscape::XML::NodeEventVector arc_tb_repr_events = {
2384 NULL, /* child_added */
2385 NULL, /* child_removed */
2386 arc_tb_event_attr_changed,
2387 NULL, /* content_changed */
2388 NULL /* order_changed */
2389 };
2392 static void
2393 sp_arc_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
2394 {
2395 int n_selected = 0;
2396 Inkscape::XML::Node *repr = NULL;
2397 Inkscape::XML::Node *oldrepr = NULL;
2399 for (GSList const *items = selection->itemList();
2400 items != NULL;
2401 items = items->next)
2402 {
2403 if (SP_IS_ARC((SPItem *) items->data)) {
2404 n_selected++;
2405 repr = SP_OBJECT_REPR((SPItem *) items->data);
2406 }
2407 }
2409 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
2411 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(FALSE));
2412 if (n_selected == 0) {
2413 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
2414 } else if (n_selected == 1) {
2415 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
2416 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2418 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
2420 if (oldrepr) { // remove old listener
2421 sp_repr_remove_listener_by_data(oldrepr, tbl);
2422 Inkscape::GC::release(oldrepr);
2423 oldrepr = 0;
2424 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
2425 }
2427 if (repr) {
2428 g_object_set_data(G_OBJECT(tbl), "repr", repr);
2429 Inkscape::GC::anchor(repr);
2430 sp_repr_add_listener(repr, &arc_tb_repr_events, tbl);
2431 sp_repr_synthesize_events(repr, &arc_tb_repr_events, tbl);
2432 }
2433 } else {
2434 // FIXME: implement averaging of all parameters for multiple selected
2435 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
2436 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2437 sp_arctb_sensitivize (GTK_WIDGET(tbl), 1, 0);
2438 }
2439 }
2442 static GtkWidget *
2443 sp_arc_toolbox_new(SPDesktop *desktop)
2444 {
2445 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2447 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2448 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2450 GtkTooltips *tt = gtk_tooltips_new();
2452 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
2454 /* Start */
2455 {
2456 GtkWidget *hb = sp_tb_spinbutton(_("Start:"), _("The angle (in degrees) from the horizontal to the arc's start point"),
2457 "tools.shapes.arc", "start", 0.0,
2458 NULL, tbl, TRUE, "altx-arc",
2459 -360.0, 360.0, 1.0, 10.0,
2460 sp_arctb_start_value_changed);
2461 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2462 }
2464 /* End */
2465 {
2466 GtkWidget *hb = sp_tb_spinbutton(_("End:"), _("The angle (in degrees) from the horizontal to the arc's end point"),
2467 "tools.shapes.arc", "end", 0.0,
2468 NULL, tbl, FALSE, NULL,
2469 -360.0, 360.0, 1.0, 10.0,
2470 sp_arctb_end_value_changed);
2471 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2472 }
2474 /* Segments / Pie checkbox */
2475 {
2476 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2477 GtkWidget *fscb = gtk_check_button_new_with_label(_("Open arc"));
2478 gtk_tooltips_set_tip(tt, fscb, _("Switch between arc (unclosed shape) and segment (closed shape with two radii)"), NULL);
2480 gchar const *openstr = NULL;
2481 openstr = prefs_get_string_attribute("tools.shapes.arc", "open");
2482 if (!openstr || (openstr && !strcmp(openstr, "false")))
2483 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), FALSE);
2484 else
2485 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), TRUE);
2487 gtk_widget_show(fscb);
2488 gtk_object_set_data(GTK_OBJECT(tbl), "open_checkbox", fscb);
2489 gtk_container_add(GTK_CONTAINER(hb), fscb);
2490 g_signal_connect(G_OBJECT(fscb), "toggled", GTK_SIGNAL_FUNC(sp_arctb_open_state_changed ), tbl);
2491 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2492 }
2494 /* Make Whole */
2495 {
2496 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2497 GtkWidget *b = gtk_button_new_with_label(_("Make whole"));
2498 gtk_object_set_data(GTK_OBJECT(tbl), "make_whole", b);
2499 gtk_tooltips_set_tip(tt, b, _("Make the shape a whole ellipse, not arc or segment"), NULL);
2500 gtk_widget_show(b);
2501 gtk_container_add(GTK_CONTAINER(hb), b);
2502 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_arctb_defaults), tbl);
2503 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2504 }
2506 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
2507 // sensitivize make whole and open checkbox
2508 {
2509 GtkAdjustment *adj1 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "start"));
2510 GtkAdjustment *adj2 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "end"));
2511 sp_arctb_sensitivize (tbl, adj1->value, adj2->value);
2512 }
2514 sigc::connection *connection = new sigc::connection(
2515 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_arc_toolbox_selection_changed), (GtkObject *)tbl))
2516 );
2517 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
2519 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
2520 swatch->setWatchedTool ("tools.shapes.arc", true);
2521 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
2522 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
2524 gtk_widget_show_all(tbl);
2525 sp_set_font_size_smaller (tbl);
2527 return tbl;
2528 }
2533 // toggle button callbacks and updaters
2535 //########################
2536 //## Dropper ##
2537 //########################
2539 static void toggle_dropper_pick_alpha (GtkWidget *button, gpointer tbl) {
2540 prefs_set_int_attribute ("tools.dropper", "pick",
2541 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)));
2542 GtkWidget *set_checkbox = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "set_checkbox");
2543 if (set_checkbox) {
2544 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) {
2545 gtk_widget_set_sensitive (GTK_WIDGET (set_checkbox), TRUE);
2546 } else {
2547 gtk_widget_set_sensitive (GTK_WIDGET (set_checkbox), FALSE);
2548 }
2549 }
2550 }
2552 static void toggle_dropper_set_alpha (GtkWidget *button, gpointer data) {
2553 prefs_set_int_attribute ("tools.dropper", "setalpha",
2554 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0);
2555 }
2558 /**
2559 * Copy the current saved desktop color to the clipboard as full hex + alpha
2560 * color representation. This is useful for passing values between various
2561 * input boxes, or directly to xml.
2562 */
2563 /* static void
2564 sp_dropper_copy( GtkWidget *widget, GtkObject *obj)
2565 {
2566 GtkWidget *tbl = GTK_WIDGET(obj);
2568 SPDesktop *desktop =
2569 (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2572 sp_dropper_c32_color_copy( sp_desktop_get_color(desktop, true) );
2573 }*/
2576 /**
2577 * Copies currently saved desktop color to the clipboard as a hex value. This
2578 * is useful for editing webpages and needing a value quickly for web
2579 * colors.
2580 *
2581 * TODO: When the toggle of the dropper is set to not mix color against
2582 * page background, this still just gets the color of the page and
2583 * doesn't get the actual mixed against background which is needed
2584 * for the hex value ppl. want for web pages, etc.
2585 */
2587 /* static void
2588 sp_dropper_copy_as_hex ( GtkWidget *widget, GtkObject *obj)
2589 {
2590 GtkWidget *tbl = GTK_WIDGET(obj);
2592 SPDesktop *desktop =
2593 (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2595 sp_dropper_c32_color_copy_hex( sp_desktop_get_color(desktop, true) );
2596 }*/
2599 /**
2600 * Sets the input boxes with the changed color and opacity. This is used as a
2601 * callback for style changing.
2602 */
2603 /* static bool
2604 sp_style_changed (const SPCSSAttr *css, gpointer data)
2605 {
2606 // GrDrag *drag = (GrDrag *) data;
2608 // set fill of text entry box
2609 if (css->attribute("fill"))
2610 gtk_entry_set_text((GtkEntry *)dropper_rgb_entry,
2611 css->attribute("fill"));
2613 // set opacity of text entry box
2614 if (css->attribute("fill-opacity"))
2615 gtk_entry_set_text((GtkEntry *)dropper_opacity_entry,
2616 css->attribute("fill-opacity"));
2618 // set fill of text entry box
2619 if (css->attribute("stroke"))
2620 gtk_entry_set_text((GtkEntry *)dropper_rgb_entry,
2621 css->attribute("stroke"));
2623 // set opacity of text entry box
2624 if (css->attribute("stroke-opacity"))
2625 gtk_entry_set_text((GtkEntry *)dropper_opacity_entry,
2626 css->attribute("stroke-opacity"));
2627 return false;
2629 }
2630 */
2633 /**
2634 * Dropper auxiliary toolbar construction and setup.
2635 *
2636 * TODO: Would like to add swatch of current color.
2637 * TODO: Add queue of last 5 or so colors selected with new swatches so that
2638 * can drag and drop places. Will provide a nice mixing palette.
2639 */
2640 static GtkWidget *
2641 sp_dropper_toolbox_new(SPDesktop *desktop)
2642 {
2643 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2645 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2646 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2648 GtkTooltips *tt = gtk_tooltips_new();
2651 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
2652 AUX_BETWEEN_BUTTON_GROUPS);
2653 // sp_toolbox_add_label(tbl, _("<b>New:</b>"));
2657 /* RGB Input Field */
2658 /* {
2659 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2660 GtkWidget *dropper_rgba_label = gtk_label_new ("Color:");
2661 gtk_widget_show (dropper_rgba_label);
2662 gtk_container_add(GTK_CONTAINER(hb), dropper_rgba_label);
2664 dropper_rgb_entry = gtk_entry_new ();
2665 sp_dialog_defocus_on_enter (dropper_rgb_entry);
2666 gtk_entry_set_max_length (GTK_ENTRY (dropper_rgb_entry), 7);
2667 gtk_entry_set_width_chars (GTK_ENTRY (dropper_rgb_entry), 7);
2668 gtk_tooltips_set_tip(tt, dropper_rgb_entry,
2669 _("Hexidecimal representation of last selected "
2670 "color"),
2671 NULL);
2672 gtk_widget_show (dropper_rgb_entry);
2673 gtk_container_add(GTK_CONTAINER(hb), dropper_rgb_entry);
2675 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2676 AUX_BETWEEN_BUTTON_GROUPS);
2677 } */
2679 /* Opacity Input Field */
2680 /* {
2681 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2682 GtkWidget *dropper_opacity_label = gtk_label_new ( _("Opacity:") );
2683 gtk_widget_show (dropper_opacity_label);
2684 gtk_container_add(GTK_CONTAINER(hb), dropper_opacity_label);
2686 dropper_opacity_entry = gtk_entry_new ();
2687 sp_dialog_defocus_on_enter (dropper_opacity_entry);
2688 gtk_entry_set_max_length (GTK_ENTRY (dropper_opacity_entry), 11);
2689 gtk_entry_set_width_chars (GTK_ENTRY (dropper_opacity_entry), 11);
2690 gtk_tooltips_set_tip(tt, dropper_opacity_entry,
2691 _("Opacity of last selected color"),
2692 NULL);
2693 gtk_widget_show (dropper_opacity_entry);
2694 gtk_container_add(GTK_CONTAINER(hb), dropper_opacity_entry);
2696 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2697 AUX_BETWEEN_BUTTON_GROUPS);
2698 } */
2701 /* Copy to Clipboard */
2702 /* {
2703 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2704 GtkWidget *b = gtk_button_new_with_label(_("Copy as RGBA"));
2705 gtk_tooltips_set_tip(tt, b, _("Copy last saved color as hexidecimal "
2706 "RGB + Alpha (RGBA) to "
2707 "clipboard"),
2708 NULL);
2709 gtk_widget_show(b);
2710 gtk_container_add(GTK_CONTAINER(hb), b);
2711 gtk_signal_connect(GTK_OBJECT(b), "clicked",
2712 GTK_SIGNAL_FUNC(sp_dropper_copy), tbl);
2713 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2714 AUX_BETWEEN_BUTTON_GROUPS);
2715 } */
2718 /* Copy to Clipboard as HEX */
2719 /* {
2720 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2721 GtkWidget *b = gtk_button_new_with_label(_("Copy as HEX"));
2722 gtk_tooltips_set_tip(tt, b, _("Copy last saved color as "
2723 "hexidecimal RGB without alpha "
2724 "to clipboard"), NULL);
2725 gtk_widget_show(b);
2726 gtk_container_add(GTK_CONTAINER(hb), b);
2727 gtk_signal_connect(GTK_OBJECT(b), "clicked",
2728 GTK_SIGNAL_FUNC(sp_dropper_copy_as_hex), tbl);
2729 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2730 AUX_BETWEEN_BUTTON_GROUPS);
2731 } */
2733 // aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2735 {
2736 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2738 GtkWidget *button = gtk_check_button_new_with_label(_("Pick alpha"));
2739 gtk_tooltips_set_tip(tt, button, _("Pick both the color and the alpha (transparency) under cursor; otherwise, pick only the visible color premultiplied by alpha"), NULL);
2740 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
2741 prefs_get_int_attribute ("tools.dropper",
2742 "pick", 1));
2743 gtk_widget_show(button);
2744 gtk_container_add (GTK_CONTAINER (hb), button);
2745 gtk_object_set_data(GTK_OBJECT(tbl), "pick_checkbox", button);
2746 g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK (toggle_dropper_pick_alpha), tbl);
2747 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2748 AUX_BETWEEN_BUTTON_GROUPS);
2749 }
2751 {
2752 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2754 GtkWidget *button = gtk_check_button_new_with_label(_("Set alpha"));
2755 gtk_tooltips_set_tip(tt, button, _("If alpha was picked, assign it to selection as fill or stroke transparency"), NULL);
2756 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
2757 prefs_get_int_attribute ("tools.dropper",
2758 "setalpha", 1));
2759 gtk_widget_show(button);
2760 gtk_container_add (GTK_CONTAINER (hb), button);
2761 gtk_object_set_data(GTK_OBJECT(tbl), "set_checkbox", button);
2762 g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK (toggle_dropper_set_alpha), tbl);
2764 // make sure it's disabled if we're not picking alpha
2765 GtkWidget *pick_checkbox = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "pick_checkbox");
2766 if (pick_checkbox) {
2767 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pick_checkbox))) {
2768 gtk_widget_set_sensitive (GTK_WIDGET (button), TRUE);
2769 } else {
2770 gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
2771 }
2772 }
2774 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2775 AUX_BETWEEN_BUTTON_GROUPS);
2776 }
2778 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2781 // where new gtkmm stuff should go
2783 gtk_widget_show_all(tbl);
2784 sp_set_font_size_smaller (tbl);
2786 /*
2787 sigc::connection *connection = new sigc::connection(
2788 desktop->connectSetStyle(
2789 sigc::bind(sigc::ptr_fun(sp_style_changed),
2790 desktop)) );
2792 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection),
2793 connection); */
2795 return tbl;
2796 }
2799 //########################
2800 //## Text Toolbox ##
2801 //########################
2802 /*
2803 static void
2804 sp_text_letter_changed(GtkAdjustment *adj, GtkWidget *tbl)
2805 {
2806 //Call back for letter sizing spinbutton
2807 }
2809 static void
2810 sp_text_line_changed(GtkAdjustment *adj, GtkWidget *tbl)
2811 {
2812 //Call back for line height spinbutton
2813 }
2815 static void
2816 sp_text_horiz_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
2817 {
2818 //Call back for horizontal kerning spinbutton
2819 }
2821 static void
2822 sp_text_vert_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
2823 {
2824 //Call back for vertical kerning spinbutton
2825 }
2827 static void
2828 sp_text_letter_rotation_changed(GtkAdjustment *adj, GtkWidget *tbl)
2829 {
2830 //Call back for letter rotation spinbutton
2831 }*/
2833 namespace {
2835 bool visible = false;
2837 void
2838 sp_text_toolbox_selection_changed (Inkscape::Selection *selection, GObject *tbl)
2839 {
2841 SPStyle *query =
2842 sp_style_new ();
2844 int result_family =
2845 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
2847 int result_style =
2848 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
2850 int result_numbers =
2851 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
2853 gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
2855 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
2856 if (result_family == QUERY_STYLE_NOTHING || result_style == QUERY_STYLE_NOTHING || result_numbers == QUERY_STYLE_NOTHING)
2857 {
2858 Inkscape::XML::Node *repr = inkscape_get_repr (INKSCAPE, "tools.text");
2860 if (repr)
2861 {
2862 sp_style_read_from_repr (query, repr);
2863 }
2864 else
2865 {
2866 return;
2867 }
2868 }
2870 if (query->text)
2871 {
2872 if (result_family == QUERY_STYLE_MULTIPLE_DIFFERENT) {
2873 GtkWidget *entry = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "family-entry"));
2874 gtk_entry_set_text (GTK_ENTRY (entry), "");
2876 } else if (query->text->font_family.value) {
2878 GtkWidget *entry = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "family-entry"));
2879 gtk_entry_set_text (GTK_ENTRY (entry), query->text->font_family.value);
2881 Gtk::TreePath path;
2882 try {
2883 path = Inkscape::FontLister::get_instance()->get_row_for_font (query->text->font_family.value);
2884 } catch (...) {
2885 return;
2886 }
2888 GtkTreeSelection *tselection = GTK_TREE_SELECTION (g_object_get_data (G_OBJECT(tbl), "family-tree-selection"));
2889 GtkTreeView *treeview = GTK_TREE_VIEW (g_object_get_data (G_OBJECT(tbl), "family-tree-view"));
2891 g_object_set_data (G_OBJECT (tselection), "block", gpointer(1));
2893 gtk_tree_selection_select_path (tselection, path.gobj());
2894 gtk_tree_view_scroll_to_cell (treeview, path.gobj(), NULL, TRUE, 0.5, 0.0);
2896 g_object_set_data (G_OBJECT (tselection), "block", gpointer(0));
2897 }
2899 //Size
2900 GtkWidget *cbox = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "combo-box-size"));
2901 char *str = g_strdup_printf ("%.5g", query->font_size.computed);
2902 g_object_set_data (tbl, "size-block", gpointer(1));
2903 gtk_entry_set_text (GTK_ENTRY(GTK_BIN (cbox)->child), str);
2904 g_object_set_data (tbl, "size-block", gpointer(0));
2905 free (str);
2907 //Anchor
2908 if (query->text_align.computed == SP_CSS_TEXT_ALIGN_JUSTIFY)
2909 {
2910 GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-fill"));
2911 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
2912 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2913 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
2914 }
2915 else
2916 {
2917 if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_START)
2918 {
2919 GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-start"));
2920 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
2921 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2922 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
2923 }
2924 else if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_MIDDLE)
2925 {
2926 GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-middle"));
2927 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
2928 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2929 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
2930 }
2931 else if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_END)
2932 {
2933 GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-end"));
2934 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
2935 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2936 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
2937 }
2938 }
2940 //Style
2941 {
2942 GtkToggleButton *button = GTK_TOGGLE_BUTTON (g_object_get_data (G_OBJECT (tbl), "style-bold"));
2944 gboolean active = gtk_toggle_button_get_active (button);
2945 gboolean check = (query->font_weight.computed >= SP_CSS_FONT_WEIGHT_700);
2947 if (active != check)
2948 {
2949 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
2950 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), check);
2951 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
2952 }
2953 }
2955 {
2956 GtkToggleButton *button = GTK_TOGGLE_BUTTON (g_object_get_data (G_OBJECT (tbl), "style-italic"));
2958 gboolean active = gtk_toggle_button_get_active (button);
2959 gboolean check = (query->font_style.computed != SP_CSS_FONT_STYLE_NORMAL);
2961 if (active != check)
2962 {
2963 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
2964 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), check);
2965 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
2966 }
2967 }
2969 //Orientation
2970 //locking both buttons, changing one affect all group (both)
2971 GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "orientation-horizontal"));
2972 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
2974 GtkWidget *button1 = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "orientation-vertical"));
2975 g_object_set_data (G_OBJECT (button1), "block", gpointer(1));
2977 if (query->writing_mode.computed == SP_CSS_WRITING_MODE_LR_TB)
2978 {
2979 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2980 }
2981 else
2982 {
2983 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button1), TRUE);
2984 }
2985 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
2986 g_object_set_data (G_OBJECT (button1), "block", gpointer(0));
2987 }
2988 }
2990 void
2991 sp_text_toolbox_selection_modified (Inkscape::Selection *selection, guint flags, GObject *tbl)
2992 {
2993 sp_text_toolbox_selection_changed (selection, tbl);
2994 }
2996 void
2997 sp_text_toolbox_subselection_changed (gpointer dragger, GObject *tbl)
2998 {
2999 sp_text_toolbox_selection_changed (NULL, tbl);
3000 }
3002 void
3003 sp_text_toolbox_family_changed (GtkTreeSelection *selection,
3004 GObject *tbl)
3005 {
3006 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3007 GtkTreeModel *model = 0;
3008 GtkWidget *popdown = GTK_WIDGET (g_object_get_data (tbl, "family-popdown-window"));
3009 GtkWidget *entry = GTK_WIDGET (g_object_get_data (tbl, "family-entry"));
3010 GtkTreeIter iter;
3011 char *family = 0;
3013 gdk_pointer_ungrab (GDK_CURRENT_TIME);
3014 gdk_keyboard_ungrab (GDK_CURRENT_TIME);
3016 if ( !gtk_tree_selection_get_selected( selection, &model, &iter ) ) {
3017 return;
3018 }
3020 gtk_tree_model_get (model, &iter, 0, &family, -1);
3022 if (g_object_get_data (G_OBJECT (selection), "block"))
3023 {
3024 gtk_entry_set_text (GTK_ENTRY (entry), family);
3025 return;
3026 }
3028 gtk_widget_hide (popdown);
3029 visible = false;
3031 gtk_entry_set_text (GTK_ENTRY (entry), family);
3033 SPStyle *query =
3034 sp_style_new ();
3036 int result_numbers =
3037 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
3039 SPCSSAttr *css = sp_repr_css_attr_new ();
3040 sp_repr_css_set_property (css, "font-family", family);
3042 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
3043 if (result_numbers == QUERY_STYLE_NOTHING)
3044 {
3045 sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
3046 sp_text_edit_dialog_default_set_insensitive (); //FIXME: Replace trough a verb
3047 }
3048 else
3049 {
3050 sp_desktop_set_style (desktop, css, true, true);
3051 }
3053 sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
3054 /* TODO: annotate */ "toolbox.cpp:3024");
3055 sp_repr_css_attr_unref (css);
3056 free (family);
3057 gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
3059 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3060 }
3062 void
3063 sp_text_toolbox_family_entry_activate (GtkEntry *entry,
3064 GObject *tbl)
3065 {
3066 const char *family = gtk_entry_get_text (entry);
3068 try {
3069 Gtk::TreePath path = Inkscape::FontLister::get_instance()->get_row_for_font (family);
3070 GtkTreeSelection *selection = GTK_TREE_SELECTION (g_object_get_data (G_OBJECT(tbl), "family-tree-selection"));
3071 GtkTreeView *treeview = GTK_TREE_VIEW (g_object_get_data (G_OBJECT(tbl), "family-tree-view"));
3072 gtk_tree_selection_select_path (selection, path.gobj());
3073 gtk_tree_view_scroll_to_cell (treeview, path.gobj(), NULL, TRUE, 0.5, 0.0);
3074 gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
3075 } catch (...) {
3076 if (family && strlen (family))
3077 {
3078 gtk_widget_show_all (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
3079 }
3080 }
3081 }
3083 void
3084 sp_text_toolbox_anchoring_toggled (GtkRadioButton *button,
3085 gpointer data)
3086 {
3087 if (g_object_get_data (G_OBJECT (button), "block")) return;
3088 if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) return;
3089 int prop = GPOINTER_TO_INT(data);
3091 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3092 SPCSSAttr *css = sp_repr_css_attr_new ();
3094 switch (prop)
3095 {
3096 case 0:
3097 {
3098 sp_repr_css_set_property (css, "text-anchor", "start");
3099 sp_repr_css_set_property (css, "text-align", "start");
3100 break;
3101 }
3102 case 1:
3103 {
3104 sp_repr_css_set_property (css, "text-anchor", "middle");
3105 sp_repr_css_set_property (css, "text-align", "center");
3106 break;
3107 }
3109 case 2:
3110 {
3111 sp_repr_css_set_property (css, "text-anchor", "end");
3112 sp_repr_css_set_property (css, "text-align", "end");
3113 break;
3114 }
3116 case 3:
3117 {
3118 sp_repr_css_set_property (css, "text-anchor", "start");
3119 sp_repr_css_set_property (css, "text-align", "justify");
3120 break;
3121 }
3122 }
3124 SPStyle *query =
3125 sp_style_new ();
3126 int result_numbers =
3127 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
3129 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
3130 if (result_numbers == QUERY_STYLE_NOTHING)
3131 {
3132 sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
3133 }
3135 sp_desktop_set_style (desktop, css, true, true);
3136 sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
3137 /* TODO: annotate */ "toolbox.cpp:3107");
3138 sp_repr_css_attr_unref (css);
3140 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3141 }
3143 void
3144 sp_text_toolbox_style_toggled (GtkToggleButton *button,
3145 gpointer data)
3146 {
3147 if (g_object_get_data (G_OBJECT (button), "block")) return;
3149 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3150 SPCSSAttr *css = sp_repr_css_attr_new ();
3151 int prop = GPOINTER_TO_INT(data);
3152 bool active = gtk_toggle_button_get_active (button);
3155 switch (prop)
3156 {
3157 case 0:
3158 {
3159 sp_repr_css_set_property (css, "font-weight", active ? "bold" : "normal" );
3160 break;
3161 }
3163 case 1:
3164 {
3165 sp_repr_css_set_property (css, "font-style", active ? "italic" : "normal");
3166 break;
3167 }
3168 }
3170 SPStyle *query =
3171 sp_style_new ();
3172 int result_numbers =
3173 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
3175 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
3176 if (result_numbers == QUERY_STYLE_NOTHING)
3177 {
3178 sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
3179 }
3181 sp_desktop_set_style (desktop, css, true, true);
3182 sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
3183 /* TODO: annotate */ "toolbox.cpp:3153");
3184 sp_repr_css_attr_unref (css);
3186 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3187 }
3189 void
3190 sp_text_toolbox_orientation_toggled (GtkRadioButton *button,
3191 gpointer data)
3192 {
3193 if (g_object_get_data (G_OBJECT (button), "block")) {
3194 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
3195 return;
3196 }
3198 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3199 SPCSSAttr *css = sp_repr_css_attr_new ();
3200 int prop = GPOINTER_TO_INT(data);
3202 switch (prop)
3203 {
3204 case 0:
3205 {
3206 sp_repr_css_set_property (css, "writing-mode", "lr");
3207 break;
3208 }
3210 case 1:
3211 {
3212 sp_repr_css_set_property (css, "writing-mode", "tb");
3213 break;
3214 }
3215 }
3217 SPStyle *query =
3218 sp_style_new ();
3219 int result_numbers =
3220 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
3222 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
3223 if (result_numbers == QUERY_STYLE_NOTHING)
3224 {
3225 sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
3226 }
3228 sp_desktop_set_style (desktop, css, true, true);
3229 sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
3230 /* TODO: annotate */ "toolbox.cpp:3200");
3231 sp_repr_css_attr_unref (css);
3233 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3234 }
3236 gboolean
3237 sp_text_toolbox_size_keypress (GtkWidget *w, GdkEventKey *event, gpointer data)
3238 {
3239 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3240 if (!desktop) return FALSE;
3242 switch (get_group0_keyval (event)) {
3243 case GDK_Escape: // defocus
3244 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3245 return TRUE; // I consumed the event
3246 break;
3247 case GDK_Return: // defocus
3248 case GDK_KP_Enter:
3249 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3250 return TRUE; // I consumed the event
3251 break;
3252 }
3253 return FALSE;
3254 }
3256 gboolean
3257 sp_text_toolbox_family_keypress (GtkWidget *w, GdkEventKey *event, GObject *tbl)
3258 {
3259 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3260 if (!desktop) return FALSE;
3262 switch (get_group0_keyval (event)) {
3263 case GDK_Escape: // defocus
3264 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3265 sp_text_toolbox_selection_changed (NULL, tbl); // update
3266 return TRUE; // I consumed the event
3267 break;
3268 }
3269 return FALSE;
3270 }
3272 gboolean
3273 sp_text_toolbox_family_list_keypress (GtkWidget *w, GdkEventKey *event, GObject *tbl)
3274 {
3275 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3276 if (!desktop) return FALSE;
3278 switch (get_group0_keyval (event)) {
3279 case GDK_Escape: // defocus
3280 gtk_widget_hide (w);
3281 visible = false;
3282 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3283 return TRUE; // I consumed the event
3284 break;
3285 }
3286 return FALSE;
3287 }
3290 void
3291 sp_text_toolbox_size_changed (GtkComboBox *cbox,
3292 GObject *tbl)
3293 {
3294 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3296 if (g_object_get_data (tbl, "size-block")) return;
3298 #if GTK_CHECK_VERSION(2,6,0)
3299 char *text = gtk_combo_box_get_active_text (cbox);
3300 #else // GTK_CHECK_VERSION(2,6,0)
3301 GtkTreeModel *model = gtk_combo_box_get_model (cbox);
3302 GtkTreeIter iter;
3303 char *text = NULL;
3305 if (gtk_combo_box_get_active_iter (cbox, &iter) && model)
3306 gtk_tree_model_get (model, &iter, 0, &text, -1);
3307 #endif // GTK_CHECK_VERSION(2,6,0)
3309 SPCSSAttr *css = sp_repr_css_attr_new ();
3310 sp_repr_css_set_property (css, "font-size", text);
3311 free (text);
3313 SPStyle *query =
3314 sp_style_new ();
3315 int result_numbers =
3316 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
3318 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
3319 if (result_numbers == QUERY_STYLE_NOTHING)
3320 {
3321 sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
3322 }
3324 sp_desktop_set_style (desktop, css, true, true);
3325 sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:size", SP_VERB_NONE,
3326 /* TODO: annotate */ "toolbox.cpp:3296");
3327 sp_repr_css_attr_unref (css);
3330 if (gtk_combo_box_get_active (cbox) > 0) // if this was from drop-down (as opposed to type-in), defocus
3331 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3332 }
3334 void
3335 sp_text_toolbox_text_popdown_clicked (GtkButton *button,
3336 GObject *tbl)
3337 {
3338 GtkWidget *popdown = GTK_WIDGET (g_object_get_data (tbl, "family-popdown-window"));
3339 GtkWidget *widget = GTK_WIDGET (g_object_get_data (tbl, "family-entry"));
3340 int x, y;
3342 if (!visible)
3343 {
3344 gdk_window_get_origin (widget->window, &x, &y);
3345 gtk_window_move (GTK_WINDOW (popdown), x, y + widget->allocation.height + 2); //2px of grace space
3346 gtk_widget_show_all (popdown);
3348 gdk_pointer_grab (widget->window, TRUE,
3349 GdkEventMask (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
3350 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
3351 GDK_POINTER_MOTION_MASK),
3352 NULL, NULL, GDK_CURRENT_TIME);
3354 gdk_keyboard_grab (widget->window, TRUE, GDK_CURRENT_TIME);
3356 visible = true;
3357 }
3358 else
3359 {
3360 gdk_pointer_ungrab (GDK_CURRENT_TIME);
3361 gdk_keyboard_ungrab (GDK_CURRENT_TIME);
3362 gtk_widget_hide (popdown);
3363 visible = false;
3364 }
3365 }
3367 gboolean
3368 sp_text_toolbox_entry_focus_in (GtkWidget *entry,
3369 GdkEventFocus *event,
3370 GObject *tbl)
3371 {
3372 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
3373 return FALSE;
3374 }
3376 gboolean
3377 sp_text_toolbox_popdown_focus_out (GtkWidget *popdown,
3378 GdkEventFocus *event,
3379 GObject *tbl)
3380 {
3381 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3383 gtk_widget_hide (popdown);
3384 visible = false;
3385 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3386 return TRUE;
3387 }
3389 void
3390 cell_data_func (GtkTreeViewColumn *column,
3391 GtkCellRenderer *cell,
3392 GtkTreeModel *tree_model,
3393 GtkTreeIter *iter,
3394 gpointer data)
3395 {
3396 char *family,
3397 *family_escaped,
3398 *sample_escaped;
3400 static const char *sample = _("AaBbCcIiPpQq12369$\342\202\254\302\242?.;/()");
3402 gtk_tree_model_get (tree_model, iter, 0, &family, -1);
3404 family_escaped = g_markup_escape_text (family, -1);
3405 sample_escaped = g_markup_escape_text (sample, -1);
3407 std::stringstream markup;
3408 markup << family_escaped << " <span foreground='darkgray' font_family='" << family_escaped << "'>" << sample_escaped << "</span>";
3409 g_object_set (G_OBJECT (cell), "markup", markup.str().c_str(), NULL);
3411 free (family);
3412 free (family_escaped);
3413 free (sample_escaped);
3414 }
3416 GtkWidget*
3417 sp_text_toolbox_new (SPDesktop *desktop)
3418 {
3419 GtkWidget *tbl = gtk_hbox_new (FALSE, 0);
3421 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
3422 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
3424 GtkTooltips *tt = gtk_tooltips_new();
3425 Glib::RefPtr<Gtk::ListStore> store = Inkscape::FontLister::get_instance()->get_font_list();
3427 ////////////Family
3428 //Window
3429 GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3430 gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
3432 //Entry
3433 GtkWidget *entry = gtk_entry_new ();
3434 gtk_object_set_data(GTK_OBJECT(entry), "altx-text", entry);
3435 GtkEntryCompletion *completion = gtk_entry_completion_new ();
3436 gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (Glib::unwrap(store)));
3437 gtk_entry_completion_set_text_column (completion, 0);
3438 gtk_entry_completion_set_minimum_key_length (completion, 1);
3439 g_object_set (G_OBJECT(completion), "inline-completion", TRUE, "popup-completion", TRUE, NULL);
3440 gtk_entry_set_completion (GTK_ENTRY(entry), completion);
3441 aux_toolbox_space (tbl, 1);
3442 gtk_box_pack_start (GTK_BOX (tbl), entry, FALSE, FALSE, 0);
3444 //Button
3445 GtkWidget *button = gtk_button_new ();
3446 gtk_container_add (GTK_CONTAINER (button), gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE));
3447 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
3449 //Popdown
3450 GtkWidget *sw = gtk_scrolled_window_new (NULL, NULL);
3451 GtkWidget *treeview = gtk_tree_view_new ();
3453 GtkCellRenderer *cell = gtk_cell_renderer_text_new ();
3454 GtkTreeViewColumn *column = gtk_tree_view_column_new ();
3455 gtk_tree_view_column_pack_start (column, cell, FALSE);
3456 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
3457 gtk_tree_view_column_set_cell_data_func (column, cell, GtkTreeCellDataFunc (cell_data_func), NULL, NULL);
3458 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
3460 gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (Glib::unwrap(store)));
3461 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
3462 #if GTK_CHECK_VERSION(2,6,0)
3463 gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (treeview), TRUE);
3464 #endif // GTK_CHECK_VERSION(2,6,0)
3466 //gtk_tree_view_set_enable_search (GTK_TREE_VIEW (treeview), TRUE);
3468 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
3469 gtk_container_add (GTK_CONTAINER (sw), treeview);
3471 gtk_container_add (GTK_CONTAINER (window), sw);
3472 gtk_widget_set_size_request (window, 300, 450);
3474 g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (sp_text_toolbox_family_entry_activate), tbl);
3475 g_signal_connect (G_OBJECT (entry), "focus-in-event", G_CALLBACK (sp_text_toolbox_entry_focus_in), tbl);
3476 g_signal_connect (G_OBJECT (entry), "key-press-event", G_CALLBACK(sp_text_toolbox_family_keypress), tbl);
3478 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (sp_text_toolbox_text_popdown_clicked), tbl);
3480 g_signal_connect (G_OBJECT (window), "focus-out-event", G_CALLBACK (sp_text_toolbox_popdown_focus_out), tbl);
3481 g_signal_connect (G_OBJECT (window), "key-press-event", G_CALLBACK(sp_text_toolbox_family_list_keypress), tbl);
3483 GtkTreeSelection *tselection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
3484 g_signal_connect (G_OBJECT (tselection), "changed", G_CALLBACK (sp_text_toolbox_family_changed), tbl);
3486 g_object_set_data (G_OBJECT (tbl), "family-entry", entry);
3487 g_object_set_data (G_OBJECT (tbl), "family-popdown-button", button);
3488 g_object_set_data (G_OBJECT (tbl), "family-popdown-window", window);
3489 g_object_set_data (G_OBJECT (tbl), "family-tree-selection", tselection);
3490 g_object_set_data (G_OBJECT (tbl), "family-tree-view", treeview);
3492 GtkWidget *image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
3493 aux_toolbox_space (tbl, 1);
3494 GtkWidget *box = gtk_event_box_new ();
3495 gtk_container_add (GTK_CONTAINER (box), image);
3496 gtk_box_pack_start (GTK_BOX (tbl), box, FALSE, FALSE, 4);
3497 g_object_set_data (G_OBJECT (tbl), "warning-image", box);
3498 GtkTooltips *tooltips = gtk_tooltips_new ();
3499 gtk_tooltips_set_tip (tooltips, box, _("This font is currently not installed on your system. Inkscape will use the default font instead."), "");
3500 gtk_widget_hide (GTK_WIDGET (box));
3501 g_signal_connect_swapped (G_OBJECT (tbl), "show", G_CALLBACK (gtk_widget_hide), box);
3503 ////////////Size
3504 const char *sizes[] = {
3505 "4", "6", "8", "9", "10", "11", "12", "13", "14",
3506 "16", "18", "20", "22", "24", "28",
3507 "32", "36", "40", "48", "56", "64", "72", "144"
3508 };
3510 GtkWidget *cbox = gtk_combo_box_entry_new_text ();
3511 for (unsigned int n = 0; n < G_N_ELEMENTS (sizes); gtk_combo_box_append_text (GTK_COMBO_BOX(cbox), sizes[n++]));
3512 gtk_widget_set_size_request (cbox, 80, -1);
3513 aux_toolbox_space (tbl, 1);
3514 gtk_box_pack_start (GTK_BOX (tbl), cbox, FALSE, FALSE, 0);
3515 g_object_set_data (G_OBJECT (tbl), "combo-box-size", cbox);
3516 g_signal_connect (G_OBJECT (cbox), "changed", G_CALLBACK (sp_text_toolbox_size_changed), tbl);
3517 gtk_signal_connect(GTK_OBJECT(cbox), "key-press-event", GTK_SIGNAL_FUNC(sp_text_toolbox_size_keypress), NULL);
3519 //spacer
3520 aux_toolbox_space (tbl, 4);
3521 gtk_box_pack_start (GTK_BOX (tbl), gtk_vseparator_new (), FALSE, FALSE, 4);
3523 ////////////Text anchor
3524 GtkWidget *group = gtk_radio_button_new (NULL);
3525 GtkWidget *row = gtk_hbox_new (FALSE, 4);
3526 g_object_set_data (G_OBJECT (tbl), "anchor-group", group);
3528 // left
3529 GtkWidget *rbutton = group;
3530 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3531 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_LEFT, GTK_ICON_SIZE_SMALL_TOOLBAR));
3532 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3534 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3535 g_object_set_data (G_OBJECT (tbl), "text-start", rbutton);
3536 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer(0));
3537 gtk_tooltips_set_tip(tt, rbutton, _("Align left"), NULL);
3539 // center
3540 rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3541 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3542 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_CENTER, GTK_ICON_SIZE_SMALL_TOOLBAR));
3543 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3545 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3546 g_object_set_data (G_OBJECT (tbl), "text-middle", rbutton);
3547 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer (1));
3548 gtk_tooltips_set_tip(tt, rbutton, _("Center"), NULL);
3550 // right
3551 rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3552 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3553 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_RIGHT, GTK_ICON_SIZE_SMALL_TOOLBAR));
3554 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3556 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3557 g_object_set_data (G_OBJECT (tbl), "text-end", rbutton);
3558 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer(2));
3559 gtk_tooltips_set_tip(tt, rbutton, _("Align right"), NULL);
3561 // fill
3562 rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3563 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3564 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_FILL, GTK_ICON_SIZE_SMALL_TOOLBAR));
3565 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3567 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3568 g_object_set_data (G_OBJECT (tbl), "text-fill", rbutton);
3569 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer(3));
3570 gtk_tooltips_set_tip(tt, rbutton, _("Justify"), NULL);
3572 aux_toolbox_space (tbl, 1);
3573 gtk_box_pack_start (GTK_BOX (tbl), row, FALSE, FALSE, 4);
3575 //spacer
3576 gtk_box_pack_start (GTK_BOX (tbl), gtk_vseparator_new (), FALSE, FALSE, 4);
3578 ////////////Text style
3579 row = gtk_hbox_new (FALSE, 4);
3581 // bold
3582 rbutton = gtk_toggle_button_new ();
3583 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3584 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_BOLD, GTK_ICON_SIZE_SMALL_TOOLBAR));
3585 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3586 gtk_tooltips_set_tip(tt, rbutton, _("Bold"), NULL);
3588 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3589 g_object_set_data (G_OBJECT (tbl), "style-bold", rbutton);
3590 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_style_toggled), gpointer(0));
3592 // italic
3593 rbutton = gtk_toggle_button_new ();
3594 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3595 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_ITALIC, GTK_ICON_SIZE_SMALL_TOOLBAR));
3596 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3597 gtk_tooltips_set_tip(tt, rbutton, _("Italic"), NULL);
3599 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3600 g_object_set_data (G_OBJECT (tbl), "style-italic", rbutton);
3601 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_style_toggled), gpointer (1));
3603 aux_toolbox_space (tbl, 1);
3604 gtk_box_pack_start (GTK_BOX (tbl), row, FALSE, FALSE, 4);
3606 //spacer
3607 gtk_box_pack_start (GTK_BOX (tbl), gtk_vseparator_new (), FALSE, FALSE, 4);
3609 ////////////Text orientation
3610 group = gtk_radio_button_new (NULL);
3611 row = gtk_hbox_new (FALSE, 4);
3612 g_object_set_data (G_OBJECT (tbl), "orientation-group", group);
3614 // horizontal
3615 rbutton = group;
3616 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3617 gtk_container_add (GTK_CONTAINER (rbutton), sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_LR));
3618 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3619 gtk_tooltips_set_tip(tt, rbutton, _("Horizontal text"), NULL);
3621 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3622 g_object_set_data (G_OBJECT (tbl), "orientation-horizontal", rbutton);
3623 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_orientation_toggled), gpointer(0));
3625 // vertical
3626 rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3627 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3628 gtk_container_add (GTK_CONTAINER (rbutton), sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_TB));
3629 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3630 gtk_tooltips_set_tip(tt, rbutton, _("Vertical text"), NULL);
3632 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3633 g_object_set_data (G_OBJECT (tbl), "orientation-vertical", rbutton);
3634 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_orientation_toggled), gpointer (1));
3635 gtk_box_pack_start (GTK_BOX (tbl), row, FALSE, FALSE, 4);
3638 //watch selection
3639 Inkscape::ConnectionPool* pool = Inkscape::ConnectionPool::new_connection_pool ("ISTextToolbox");
3641 sigc::connection *c_selection_changed =
3642 new sigc::connection (sp_desktop_selection (desktop)->connectChanged
3643 (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_changed), (GObject*)tbl)));
3644 pool->add_connection ("selection-changed", c_selection_changed);
3646 sigc::connection *c_selection_modified =
3647 new sigc::connection (sp_desktop_selection (desktop)->connectModified
3648 (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_modified), (GObject*)tbl)));
3649 pool->add_connection ("selection-modified", c_selection_modified);
3651 sigc::connection *c_subselection_changed =
3652 new sigc::connection (desktop->connectToolSubselectionChanged
3653 (sigc::bind (sigc::ptr_fun (sp_text_toolbox_subselection_changed), (GObject*)tbl)));
3654 pool->add_connection ("tool-subselection-changed", c_subselection_changed);
3656 Inkscape::ConnectionPool::connect_destroy (G_OBJECT (tbl), pool);
3659 #if 0
3660 // horizontal
3661 {
3662 GtkWidget *px= sp_icon_new(Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_LR);
3663 GtkWidget *b = group = gtk_radio_button_new (NULL);
3664 gtk_container_add (GTK_CONTAINER (b), px);
3665 gtk_tooltips_set_tip (tt, b, _("Horizontal text"), NULL);
3666 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
3667 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
3668 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
3669 }
3671 // vertical
3672 {
3673 GtkWidget *px = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_TB);
3674 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3675 gtk_container_add (GTK_CONTAINER (b), px);
3676 gtk_tooltips_set_tip (tt, b, _("Vertical text"), NULL);
3677 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
3678 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
3679 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
3680 }
3682 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
3684 // letter spacing
3685 {
3686 {
3687 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LETTER_SPACING);
3688 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3689 gtk_container_add (GTK_CONTAINER (hb), image);
3690 gtk_widget_show(image);
3691 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3692 }
3694 {
3695 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Spacing between letters"),
3696 "tools.text", "letter_spacing", 0.0,
3697 us, tbl, FALSE, NULL,
3698 -1000.0, 1000.0, 0.1, 0.1,
3699 sp_text_letter_changed, 0.1, 1);
3700 gtk_widget_set_size_request (hb, 45, 6);
3701 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
3702 }
3703 }
3705 // line spacing
3706 {
3707 {
3708 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LINE_SPACING);
3709 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3710 gtk_container_add (GTK_CONTAINER (hb), image);
3711 gtk_widget_show(image);
3712 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3713 }
3715 {
3716 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Spacing between lines"),
3717 "tools.text", "line_spacing", 0,
3718 us, tbl, FALSE, NULL,
3719 -1000.0, 1000.0, 0.1, 0.1,
3720 sp_text_line_changed, 0.1, 1);
3721 gtk_widget_set_size_request (hb, 45, 0);
3722 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 3);
3723 }
3724 }
3726 {
3727 // horizontal kerning/vertical kerning units menu: create
3728 GtkWidget *us = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
3729 sp_unit_selector_setsize(us, AUX_OPTION_MENU_WIDTH, AUX_OPTION_MENU_HEIGHT);
3730 sp_unit_selector_set_unit(SP_UNIT_SELECTOR(us), desktop->namedview->doc_units);
3732 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
3734 // horizontal kerning
3735 {
3736 {
3737 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_HORZ_KERN);
3738 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3739 gtk_container_add (GTK_CONTAINER (hb), image);
3740 gtk_widget_show(image);
3741 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3742 }
3744 {
3745 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Horizontal kerning"),
3746 "tools.text", "horizontal_kerning", 0,
3747 us, tbl, FALSE, NULL,
3748 -100.00, 100.00, 0.01, 0.1,
3749 sp_text_horiz_kern_changed);
3750 gtk_widget_set_size_request (hb, 45, 0);
3751 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
3752 }
3753 }
3755 // vertical kerning
3756 {
3757 {
3758 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_VERT_KERN);
3759 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3760 gtk_container_add (GTK_CONTAINER (hb), image);
3761 gtk_widget_show(image);
3762 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3763 }
3765 {
3766 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Vertical kerning"),
3767 "tools.text", "vertical_kerning", 0,
3768 us, tbl, FALSE, NULL,
3769 -100.00, 100.00, 0.01, 0.1,
3770 sp_text_vert_kern_changed);
3771 gtk_widget_set_size_request (hb, 45, 0);
3772 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 5);
3773 }
3774 }
3776 // add the units menu
3777 gtk_widget_show(us);
3778 gtk_box_pack_start(GTK_BOX(tbl), us, FALSE, FALSE, 1);
3779 gtk_object_set_data(GTK_OBJECT(tbl), "units", us);
3780 }
3782 // letter rotation
3783 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
3784 {
3785 {
3786 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_ROTATION);
3787 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3788 gtk_container_add (GTK_CONTAINER (hb), image);
3789 gtk_widget_show(image);
3790 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3791 }
3792 {
3793 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Letter rotation"),
3794 "tools.text", "letter_rotation", 0,
3795 us, tbl, FALSE, NULL,
3796 -180.0, 180.0, 0.1, 0.1,
3797 sp_text_letter_rotation_changed, 0.1, 1);
3798 gtk_widget_set_size_request (hb, 45, 0);
3799 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
3800 }
3801 // rotation degree label
3802 {
3803 GtkWidget *label = gtk_widget_new (GTK_TYPE_LABEL, "label", "\302\260", "xalign", 0.0, NULL);
3804 gtk_box_pack_start(GTK_BOX(tbl), label, FALSE, FALSE, 0);
3805 }
3806 }
3808 // Remove Manual Kerns
3809 {
3810 GtkWidget *px = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_REMOVE_KERNS);
3811 GtkWidget *button = gtk_button_new ();
3812 gtk_container_add (GTK_CONTAINER (button), px);
3813 gtk_widget_show(button);
3814 gtk_tooltips_set_tip (tt, button, _("Remove manual kerns"), NULL);
3815 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
3816 gtk_widget_set_sensitive(button, TRUE);
3817 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
3818 }
3819 #endif
3821 gtk_widget_show_all (tbl);
3822 return tbl;
3824 } // end of sp_text_toolbox_new()
3826 }//<unnamed> namespace
3829 //#########################
3830 //## Connector Toolbox ##
3831 //#########################
3833 static void sp_connector_path_set_avoid(void)
3834 {
3835 cc_selection_set_avoid(true);
3836 }
3839 static void sp_connector_path_set_ignore(void)
3840 {
3841 cc_selection_set_avoid(false);
3842 }
3846 static void connector_spacing_changed(GtkAdjustment *adj, GtkWidget *tbl)
3847 {
3848 // quit if run by the _changed callbacks
3849 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
3850 return;
3851 }
3853 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl),
3854 "desktop");
3855 SPDocument *doc = sp_desktop_document(desktop);
3857 if (!sp_document_get_undo_sensitive(doc))
3858 {
3859 return;
3860 }
3862 // in turn, prevent callbacks from responding
3863 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
3865 Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
3867 sp_repr_set_css_double(repr, "inkscape:connector-spacing", adj->value);
3868 SP_OBJECT(desktop->namedview)->updateRepr();
3870 GSList *items = get_avoided_items(NULL, desktop->currentRoot(), desktop);
3871 for ( GSList const *iter = items ; iter != NULL ; iter = iter->next ) {
3872 SPItem *item = reinterpret_cast<SPItem *>(iter->data);
3873 NR::Matrix m = NR::identity();
3874 avoid_item_move(&m, item);
3875 }
3877 if (items) {
3878 g_slist_free(items);
3879 }
3881 sp_document_done(doc, SP_VERB_CONTEXT_CONNECTOR,
3882 _("Change connector spacing distance"));
3884 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
3886 spinbutton_defocus(GTK_OBJECT(tbl));
3887 }
3889 static void sp_connector_graph_layout(void)
3890 {
3891 if (!SP_ACTIVE_DESKTOP) return;
3893 // hack for clones, see comment in align-and-distribute.cpp
3894 int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
3895 prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
3897 graphlayout(sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList());
3899 prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
3901 sp_document_done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_DIALOG_ALIGN_DISTRIBUTE, /* TODO: annotate */ "toolbox.cpp:129");
3902 }
3904 static void
3905 sp_directed_graph_layout_toggled(GtkWidget *widget, GtkObject *tbl)
3906 {
3907 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
3908 prefs_set_string_attribute("tools.connector", "directedlayout",
3909 "true");
3910 } else {
3911 prefs_set_string_attribute("tools.connector", "directedlayout",
3912 "false");
3913 }
3914 }
3915 static void
3916 sp_nooverlaps_graph_layout_toggled(GtkWidget *widget, GtkObject *tbl)
3917 {
3918 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
3919 prefs_set_string_attribute("tools.connector", "avoidoverlaplayout",
3920 "true");
3921 } else {
3922 prefs_set_string_attribute("tools.connector", "avoidoverlaplayout",
3923 "false");
3924 }
3925 }
3928 static void connector_length_changed(GtkAdjustment *adj, GtkWidget *tbl)
3929 {
3930 prefs_set_double_attribute("tools.connector", "length", adj->value);
3931 spinbutton_defocus(GTK_OBJECT(tbl));
3932 }
3934 static void connector_tb_event_attr_changed(Inkscape::XML::Node *repr,
3935 gchar const *name, gchar const *old_value, gchar const *new_value,
3936 bool is_interactive, gpointer data)
3937 {
3938 GtkWidget *tbl = GTK_WIDGET(data);
3940 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
3941 return;
3942 }
3943 if (strcmp(name, "inkscape:connector-spacing") != 0) {
3944 return;
3945 }
3947 GtkAdjustment *adj = (GtkAdjustment*)
3948 gtk_object_get_data(GTK_OBJECT(tbl), "spacing");
3949 gdouble spacing = defaultConnSpacing;
3950 sp_repr_get_double(repr, "inkscape:connector-spacing", &spacing);
3952 gtk_adjustment_set_value(adj, spacing);
3953 }
3956 static Inkscape::XML::NodeEventVector connector_tb_repr_events = {
3957 NULL, /* child_added */
3958 NULL, /* child_removed */
3959 connector_tb_event_attr_changed,
3960 NULL, /* content_changed */
3961 NULL /* order_changed */
3962 };
3965 static GtkWidget *
3966 sp_connector_toolbox_new(SPDesktop *desktop)
3967 {
3968 GtkTooltips *tt = gtk_tooltips_new();
3969 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
3971 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
3972 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
3974 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
3975 AUX_BETWEEN_BUTTON_GROUPS);
3977 sp_toolbox_button_new(tbl, Inkscape::ICON_SIZE_SMALL_TOOLBAR,
3978 "connector_avoid", GTK_SIGNAL_FUNC(sp_connector_path_set_avoid),
3979 tt, _("Make connectors avoid selected objects"));
3981 sp_toolbox_button_new(tbl, Inkscape::ICON_SIZE_SMALL_TOOLBAR,
3982 "connector_ignore", GTK_SIGNAL_FUNC(sp_connector_path_set_ignore),
3983 tt, _("Make connectors ignore selected objects"));
3985 // interval
3986 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
3987 AUX_BETWEEN_BUTTON_GROUPS);
3989 // Spacing spinbox
3990 {
3991 GtkWidget *object_spacing = sp_tb_spinbutton(_("Spacing:"),
3992 _("The amount of space left around objects by auto-routing connectors"),
3993 "tools.connector", "spacing", 10, NULL, tbl, TRUE,
3994 "inkscape:connector-spacing", 0, 100, 1.0, 10.0,
3995 connector_spacing_changed, 1, 0);
3997 gtk_box_pack_start(GTK_BOX(tbl), object_spacing, FALSE, FALSE,
3998 AUX_SPACING);
3999 }
4000 // Graph (connector network) layout
4001 sp_toolbox_button_new(tbl, Inkscape::ICON_SIZE_SMALL_TOOLBAR,
4002 "graph_layout", GTK_SIGNAL_FUNC(sp_connector_graph_layout),
4003 tt, _("Nicely arrange selected connector network"));
4004 // Default connector length spinbox
4005 {
4006 GtkWidget *connector_length = sp_tb_spinbutton(_("Length:"),
4007 _("Ideal length for connectors when layout is applied"),
4008 "tools.connector", "length", 100, NULL, tbl, TRUE,
4009 "inkscape:connector-length", 10, 1000, 10.0, 100.0,
4010 connector_length_changed, 1, 0);
4012 gtk_box_pack_start(GTK_BOX(tbl), connector_length, FALSE, FALSE,
4013 AUX_SPACING);
4014 }
4015 gchar const *tbuttonstate;
4016 // Directed edges toggle button
4017 {
4018 GtkWidget *tbutton = gtk_toggle_button_new ();
4019 gtk_button_set_relief (GTK_BUTTON (tbutton), GTK_RELIEF_NONE);
4020 gtk_container_add (GTK_CONTAINER (tbutton), sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, "directed_graph"));
4021 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (tbutton), FALSE);
4022 gtk_tooltips_set_tip(tt, tbutton, _("Make connectors with end-markers (arrows) point downwards"), NULL);
4024 gtk_box_pack_start (GTK_BOX (tbl), tbutton, FALSE, FALSE, 0);
4025 g_signal_connect(G_OBJECT(tbutton), "toggled", GTK_SIGNAL_FUNC(sp_directed_graph_layout_toggled), tbl);
4026 tbuttonstate = prefs_get_string_attribute("tools.connector", "directedlayout");
4027 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(tbutton),
4028 (tbuttonstate && !strcmp(tbuttonstate, "true"))?TRUE:FALSE );
4029 }
4030 // Avoid overlaps toggle button
4031 {
4032 GtkWidget *tbutton = gtk_toggle_button_new ();
4033 gtk_button_set_relief (GTK_BUTTON (tbutton), GTK_RELIEF_NONE);
4034 gtk_container_add (GTK_CONTAINER (tbutton), sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, "remove_overlaps"));
4035 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (tbutton), FALSE);
4036 gtk_tooltips_set_tip(tt, tbutton, _("Do not allow overlapping shapes"), NULL);
4038 gtk_box_pack_start (GTK_BOX (tbl), tbutton, FALSE, FALSE, 0);
4039 g_signal_connect(G_OBJECT(tbutton), "toggled", GTK_SIGNAL_FUNC(sp_nooverlaps_graph_layout_toggled), tbl);
4040 tbuttonstate = prefs_get_string_attribute("tools.connector", "avoidoverlaplayout");
4041 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(tbutton),
4042 (tbuttonstate && !strcmp(tbuttonstate, "true"))?TRUE:FALSE );
4043 }
4045 gtk_widget_show_all(tbl);
4046 sp_set_font_size_smaller (tbl);
4048 // Code to watch for changes to the connector-spacing attribute in
4049 // the XML.
4050 Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
4051 g_assert(repr != NULL);
4053 Inkscape::XML::Node *oldrepr = (Inkscape::XML::Node *)
4054 gtk_object_get_data(GTK_OBJECT(tbl), "repr");
4056 if (oldrepr) { // remove old listener
4057 sp_repr_remove_listener_by_data(oldrepr, tbl);
4058 Inkscape::GC::release(oldrepr);
4059 oldrepr = NULL;
4060 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
4061 }
4063 if (repr) {
4064 g_object_set_data(G_OBJECT(tbl), "repr", repr);
4065 Inkscape::GC::anchor(repr);
4066 sp_repr_add_listener(repr, &connector_tb_repr_events, tbl);
4067 sp_repr_synthesize_events(repr, &connector_tb_repr_events, tbl);
4068 }
4070 return tbl;
4072 } // end of sp_connector_toolbox_new()
4075 /*
4076 Local Variables:
4077 mode:c++
4078 c-file-style:"stroustrup"
4079 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
4080 indent-tabs-mode:nil
4081 fill-column:99
4082 End:
4083 */
4084 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :