13b731c79eb571d6f9a172187c9135cfe072f95a
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_cap_rounding_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1989 {
1990 prefs_set_double_attribute("tools.calligraphic", "cap_rounding", adj->value);
1991 spinbutton_defocus(GTK_OBJECT(tbl));
1992 }
1994 static void
1995 sp_ddc_pressure_state_changed(GtkWidget *button, gpointer data)
1996 {
1997 prefs_set_int_attribute ("tools.calligraphic", "usepressure", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0);
1998 }
2000 static void
2001 sp_ddc_tilt_state_changed(GtkWidget *button, GtkWidget *calligraphy_angle)
2002 {
2003 prefs_set_int_attribute ("tools.calligraphic", "usetilt", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0);
2005 gtk_widget_set_sensitive(GTK_WIDGET(calligraphy_angle), !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
2006 }
2008 static void sp_ddc_defaults(GtkWidget *, GtkWidget *tbl)
2009 {
2010 // FIXME: make defaults settable via Inkscape Options
2011 struct KeyValue {
2012 char const *key;
2013 double value;
2014 } const key_values[] = {
2015 {"mass", 0.02},
2016 {"drag", 1.0},
2017 {"angle", 30.0},
2018 {"width", 15},
2019 {"thinning", 0.1},
2020 {"tremor", 0.0},
2021 {"flatness", 0.9},
2022 {"cap_rounding", 0.0}
2023 };
2025 for (unsigned i = 0; i < G_N_ELEMENTS(key_values); ++i) {
2026 KeyValue const &kv = key_values[i];
2027 GtkAdjustment &adj = *static_cast<GtkAdjustment *>(gtk_object_get_data(GTK_OBJECT(tbl), kv.key));
2028 gtk_adjustment_set_value(&adj, kv.value);
2029 }
2031 spinbutton_defocus(GTK_OBJECT(tbl));
2032 }
2034 static GtkWidget *
2035 sp_calligraphy_toolbox_new(SPDesktop *desktop)
2036 {
2037 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2038 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2039 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2041 GtkTooltips *tt = gtk_tooltips_new();
2042 GtkWidget *calligraphy_angle;
2044 // interval
2045 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2047 /* Width */
2048 {
2049 GtkWidget *hb = sp_tb_spinbutton(_("Width:"), _("The width of the calligraphic pen (relative to the visible canvas area)"),
2050 "tools.calligraphic", "width", 15,
2051 NULL, tbl, TRUE, "altx-calligraphy",
2052 1, 100, 1.0, 10.0,
2053 sp_ddc_width_value_changed, 0.01, 0, 100);
2054 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2055 }
2057 /* Thinning */
2058 {
2059 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)"),
2060 "tools.calligraphic", "thinning", 0.1,
2061 NULL, tbl, FALSE, NULL,
2062 -1.0, 1.0, 0.01, 0.1,
2063 sp_ddc_velthin_value_changed, 0.01, 2);
2064 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2065 }
2067 // interval
2068 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2070 /* Angle */
2071 {
2072 calligraphy_angle = sp_tb_spinbutton(_("Angle:"), _("The angle of the pen's nib (in degrees; 0 = horizontal; has no effect if fixation = 0)"),
2073 "tools.calligraphic", "angle", 30,
2074 NULL, tbl, TRUE, "calligraphy-angle",
2075 -90.0, 90.0, 1.0, 10.0,
2076 sp_ddc_angle_value_changed, 1, 0);
2077 gtk_box_pack_start(GTK_BOX(tbl), calligraphy_angle, FALSE, FALSE, AUX_SPACING);
2078 }
2080 /* Fixation */
2081 {
2082 GtkWidget *hb = sp_tb_spinbutton(_("Fixation:"), _("How fixed is the pen angle (0 = always perpendicular to stroke direction, 1 = fixed)"),
2083 "tools.calligraphic", "flatness", 0.9,
2084 NULL, tbl, FALSE, NULL,
2085 0.0, 1.0, 0.01, 0.1,
2086 sp_ddc_flatness_value_changed, 0.01, 2);
2087 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2088 }
2090 // interval
2091 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2093 /* Tremor */
2094 {
2095 GtkWidget *hb = sp_tb_spinbutton(_("Tremor:"), _("How uneven or trembling is the pen stroke"),
2096 "tools.calligraphic", "tremor", 0.0,
2097 NULL, tbl, FALSE, NULL,
2098 0.0, 1.0, 0.01, 0.1,
2099 sp_ddc_tremor_value_changed, 0.01, 2);
2100 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2101 }
2103 /* Mass */
2104 {
2105 GtkWidget *hb = sp_tb_spinbutton(_("Mass:"), _("How much inertia affects the movement of the pen"),
2106 "tools.calligraphic", "mass", 0.02,
2107 NULL, tbl, FALSE, NULL,
2108 0.0, 1.0, 0.01, 0.1,
2109 sp_ddc_mass_value_changed, 0.01, 2);
2110 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2111 }
2113 /* Drag */
2114 {
2115 // TRANSLATORS: "drag" means "resistance" here
2116 GtkWidget *hb = sp_tb_spinbutton(_("Drag:"), _("How much resistance affects the movement of the pen"),
2117 "tools.calligraphic", "drag", 1,
2118 NULL, tbl, FALSE, NULL,
2119 0.0, 1.0, 0.01, 0.1,
2120 sp_ddc_drag_value_changed, 0.01, 2);
2121 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2122 }
2124 /* Cap Rounding */
2125 {
2126 // TRANSLATORS: "cap" means "end" (both start and finish) here
2127 GtkWidget *hb = sp_tb_spinbutton(_("Round:"), _("How much the ends of a stroke are rounded"),
2128 "tools.calligraphic", "cap_rounding", 1,
2129 NULL, tbl, FALSE, NULL,
2130 0.0, 1.0, 0.01, 0.1,
2131 sp_ddc_cap_rounding_value_changed, 0.01, 2);
2132 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2133 }
2135 // interval
2136 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2138 GtkWidget *cvbox = gtk_vbox_new (FALSE, 0);
2139 GtkWidget *cbox = gtk_hbox_new (FALSE, 0);
2141 /* Use Pressure button */
2142 {
2143 GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
2144 SP_BUTTON_TYPE_TOGGLE,
2145 NULL,
2146 "use_pressure",
2147 _("Use the pressure of the input device to alter the width of the pen"),
2148 tt);
2149 g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (sp_ddc_pressure_state_changed), NULL);
2150 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.calligraphic", "usepressure", 1));
2151 gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
2152 }
2154 /* Use Tilt button */
2155 {
2156 GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
2157 SP_BUTTON_TYPE_TOGGLE,
2158 NULL,
2159 "use_tilt",
2160 _("Use the tilt of the input device to alter the angle of the pen's nib"),
2161 tt);
2162 g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (sp_ddc_tilt_state_changed), calligraphy_angle);
2163 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.calligraphic", "usetilt", 1));
2164 gtk_widget_set_sensitive(GTK_WIDGET(calligraphy_angle), !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
2165 gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
2166 }
2168 gtk_box_pack_start(GTK_BOX(cvbox), cbox, TRUE, FALSE, 0);
2169 gtk_box_pack_start(GTK_BOX(tbl), cvbox, FALSE, FALSE, 0);
2171 /* Reset */
2172 {
2173 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2174 GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
2175 gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
2176 gtk_widget_show(b);
2177 gtk_container_add(GTK_CONTAINER(hb), b);
2178 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_ddc_defaults), tbl);
2179 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2180 }
2183 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
2184 swatch->setWatchedTool ("tools.calligraphic", true);
2185 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
2186 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
2188 gtk_widget_show_all(tbl);
2189 sp_set_font_size_smaller (tbl);
2191 return tbl;
2192 }
2195 //########################
2196 //## Circle / Arc ##
2197 //########################
2199 static void
2200 sp_arctb_sensitivize (GtkWidget *tbl, double v1, double v2)
2201 {
2202 GtkWidget *ocb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "open_checkbox");
2203 GtkWidget *make_whole = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "make_whole");
2205 if (v1 == 0 && v2 == 0) {
2206 if (gtk_object_get_data(GTK_OBJECT(tbl), "single")) { // only for a single selected ellipse (for now)
2207 gtk_widget_set_sensitive(GTK_WIDGET(ocb), FALSE);
2208 gtk_widget_set_sensitive(GTK_WIDGET(make_whole), FALSE);
2209 }
2210 } else {
2211 gtk_widget_set_sensitive(GTK_WIDGET(ocb), TRUE);
2212 gtk_widget_set_sensitive(GTK_WIDGET(make_whole), TRUE);
2213 }
2214 }
2216 static void
2217 sp_arctb_startend_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name, gchar const *other_name)
2218 {
2219 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2221 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2222 prefs_set_double_attribute("tools.shapes.arc", value_name, (adj->value * M_PI)/ 180);
2223 }
2225 // quit if run by the attr_changed listener
2226 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2227 return;
2228 }
2230 // in turn, prevent listener from responding
2231 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2233 gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
2235 bool modmade = false;
2236 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2237 items != NULL;
2238 items = items->next)
2239 {
2240 SPItem *item = SP_ITEM(items->data);
2242 if (SP_IS_ARC(item) && SP_IS_GENERICELLIPSE(item)) {
2244 SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
2245 SPArc *arc = SP_ARC(item);
2247 if (!strcmp(value_name, "start"))
2248 ge->start = (adj->value * M_PI)/ 180;
2249 else
2250 ge->end = (adj->value * M_PI)/ 180;
2252 sp_genericellipse_normalize(ge);
2253 ((SPObject *)arc)->updateRepr();
2254 ((SPObject *)arc)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
2256 modmade = true;
2257 }
2258 }
2260 g_free(namespaced_name);
2262 GtkAdjustment *other = (GtkAdjustment *)gtk_object_get_data(GTK_OBJECT(tbl), other_name);
2264 sp_arctb_sensitivize (tbl, adj->value, other->value);
2266 if (modmade) {
2267 sp_document_maybe_done(sp_desktop_document(desktop), value_name, SP_VERB_CONTEXT_ARC,
2268 /* TODO: annotate */ "toolbox.cpp:2247");
2269 }
2271 // defocus spinbuttons by moving focus to the canvas, unless "stay" is on
2272 spinbutton_defocus(GTK_OBJECT(tbl));
2274 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2275 }
2278 static void
2279 sp_arctb_start_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
2280 {
2281 sp_arctb_startend_value_changed(adj, tbl, "start", "end");
2282 }
2284 static void
2285 sp_arctb_end_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
2286 {
2287 sp_arctb_startend_value_changed(adj, tbl, "end", "start");
2288 }
2290 static void
2291 sp_arctb_open_state_changed(GtkWidget *widget, GtkObject *tbl)
2292 {
2293 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2295 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2296 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
2297 prefs_set_string_attribute("tools.shapes.arc", "open", "true");
2298 } else {
2299 prefs_set_string_attribute("tools.shapes.arc", "open", NULL);
2300 }
2301 }
2303 // quit if run by the attr_changed listener
2304 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2305 return;
2306 }
2308 // in turn, prevent listener from responding
2309 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2311 bool modmade = false;
2313 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
2314 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2315 items != NULL;
2316 items = items->next)
2317 {
2318 if (SP_IS_ARC((SPItem *) items->data)) {
2319 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2320 repr->setAttribute("sodipodi:open", "true");
2321 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
2322 modmade = true;
2323 }
2324 }
2325 } else {
2326 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2327 items != NULL;
2328 items = items->next)
2329 {
2330 if (SP_IS_ARC((SPItem *) items->data)) {
2331 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2332 repr->setAttribute("sodipodi:open", NULL);
2333 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
2334 modmade = true;
2335 }
2336 }
2337 }
2339 if (modmade) {
2340 sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_ARC,
2341 /* TODO: annotate */ "toolbox.cpp:2320");
2342 }
2344 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2346 spinbutton_defocus(GTK_OBJECT(tbl));
2347 }
2349 static void sp_arctb_defaults(GtkWidget *, GtkObject *obj)
2350 {
2351 GtkWidget *tbl = GTK_WIDGET(obj);
2353 GtkAdjustment *adj;
2354 adj = (GtkAdjustment*)gtk_object_get_data(obj, "start");
2355 gtk_adjustment_set_value(adj, 0.0);
2356 gtk_adjustment_value_changed(adj);
2358 adj = (GtkAdjustment*)gtk_object_get_data(obj, "end");
2359 gtk_adjustment_set_value(adj, 0.0);
2360 gtk_adjustment_value_changed(adj);
2362 spinbutton_defocus(GTK_OBJECT(tbl));
2363 }
2365 static void arc_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
2366 gchar const *old_value, gchar const *new_value,
2367 bool is_interactive, gpointer data)
2368 {
2369 GtkWidget *tbl = GTK_WIDGET(data);
2371 // quit if run by the _changed callbacks
2372 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2373 return;
2374 }
2376 // in turn, prevent callbacks from responding
2377 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2379 gdouble start = sp_repr_get_double_attribute(repr, "sodipodi:start", 0.0);
2380 gdouble end = sp_repr_get_double_attribute(repr, "sodipodi:end", 0.0);
2382 GtkAdjustment *adj1,*adj2;
2383 adj1 = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "start");
2384 gtk_adjustment_set_value(adj1, mod360((start * 180)/M_PI));
2385 adj2 = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "end");
2386 gtk_adjustment_set_value(adj2, mod360((end * 180)/M_PI));
2388 sp_arctb_sensitivize (tbl, adj1->value, adj2->value);
2390 char const *openstr = NULL;
2391 openstr = repr->attribute("sodipodi:open");
2392 GtkWidget *ocb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "open_checkbox");
2394 if (openstr) {
2395 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ocb), TRUE);
2396 } else {
2397 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ocb), FALSE);
2398 }
2400 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2401 }
2403 static Inkscape::XML::NodeEventVector arc_tb_repr_events = {
2404 NULL, /* child_added */
2405 NULL, /* child_removed */
2406 arc_tb_event_attr_changed,
2407 NULL, /* content_changed */
2408 NULL /* order_changed */
2409 };
2412 static void
2413 sp_arc_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
2414 {
2415 int n_selected = 0;
2416 Inkscape::XML::Node *repr = NULL;
2417 Inkscape::XML::Node *oldrepr = NULL;
2419 for (GSList const *items = selection->itemList();
2420 items != NULL;
2421 items = items->next)
2422 {
2423 if (SP_IS_ARC((SPItem *) items->data)) {
2424 n_selected++;
2425 repr = SP_OBJECT_REPR((SPItem *) items->data);
2426 }
2427 }
2429 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
2431 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(FALSE));
2432 if (n_selected == 0) {
2433 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
2434 } else if (n_selected == 1) {
2435 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
2436 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2438 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
2440 if (oldrepr) { // remove old listener
2441 sp_repr_remove_listener_by_data(oldrepr, tbl);
2442 Inkscape::GC::release(oldrepr);
2443 oldrepr = 0;
2444 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
2445 }
2447 if (repr) {
2448 g_object_set_data(G_OBJECT(tbl), "repr", repr);
2449 Inkscape::GC::anchor(repr);
2450 sp_repr_add_listener(repr, &arc_tb_repr_events, tbl);
2451 sp_repr_synthesize_events(repr, &arc_tb_repr_events, tbl);
2452 }
2453 } else {
2454 // FIXME: implement averaging of all parameters for multiple selected
2455 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
2456 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2457 sp_arctb_sensitivize (GTK_WIDGET(tbl), 1, 0);
2458 }
2459 }
2462 static GtkWidget *
2463 sp_arc_toolbox_new(SPDesktop *desktop)
2464 {
2465 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2467 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2468 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2470 GtkTooltips *tt = gtk_tooltips_new();
2472 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
2474 /* Start */
2475 {
2476 GtkWidget *hb = sp_tb_spinbutton(_("Start:"), _("The angle (in degrees) from the horizontal to the arc's start point"),
2477 "tools.shapes.arc", "start", 0.0,
2478 NULL, tbl, TRUE, "altx-arc",
2479 -360.0, 360.0, 1.0, 10.0,
2480 sp_arctb_start_value_changed);
2481 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2482 }
2484 /* End */
2485 {
2486 GtkWidget *hb = sp_tb_spinbutton(_("End:"), _("The angle (in degrees) from the horizontal to the arc's end point"),
2487 "tools.shapes.arc", "end", 0.0,
2488 NULL, tbl, FALSE, NULL,
2489 -360.0, 360.0, 1.0, 10.0,
2490 sp_arctb_end_value_changed);
2491 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2492 }
2494 /* Segments / Pie checkbox */
2495 {
2496 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2497 GtkWidget *fscb = gtk_check_button_new_with_label(_("Open arc"));
2498 gtk_tooltips_set_tip(tt, fscb, _("Switch between arc (unclosed shape) and segment (closed shape with two radii)"), NULL);
2500 gchar const *openstr = NULL;
2501 openstr = prefs_get_string_attribute("tools.shapes.arc", "open");
2502 if (!openstr || (openstr && !strcmp(openstr, "false")))
2503 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), FALSE);
2504 else
2505 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), TRUE);
2507 gtk_widget_show(fscb);
2508 gtk_object_set_data(GTK_OBJECT(tbl), "open_checkbox", fscb);
2509 gtk_container_add(GTK_CONTAINER(hb), fscb);
2510 g_signal_connect(G_OBJECT(fscb), "toggled", GTK_SIGNAL_FUNC(sp_arctb_open_state_changed ), tbl);
2511 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2512 }
2514 /* Make Whole */
2515 {
2516 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2517 GtkWidget *b = gtk_button_new_with_label(_("Make whole"));
2518 gtk_object_set_data(GTK_OBJECT(tbl), "make_whole", b);
2519 gtk_tooltips_set_tip(tt, b, _("Make the shape a whole ellipse, not arc or segment"), NULL);
2520 gtk_widget_show(b);
2521 gtk_container_add(GTK_CONTAINER(hb), b);
2522 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_arctb_defaults), tbl);
2523 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2524 }
2526 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
2527 // sensitivize make whole and open checkbox
2528 {
2529 GtkAdjustment *adj1 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "start"));
2530 GtkAdjustment *adj2 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "end"));
2531 sp_arctb_sensitivize (tbl, adj1->value, adj2->value);
2532 }
2534 sigc::connection *connection = new sigc::connection(
2535 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_arc_toolbox_selection_changed), (GtkObject *)tbl))
2536 );
2537 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
2539 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
2540 swatch->setWatchedTool ("tools.shapes.arc", true);
2541 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
2542 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
2544 gtk_widget_show_all(tbl);
2545 sp_set_font_size_smaller (tbl);
2547 return tbl;
2548 }
2553 // toggle button callbacks and updaters
2555 //########################
2556 //## Dropper ##
2557 //########################
2559 static void toggle_dropper_pick_alpha (GtkWidget *button, gpointer tbl) {
2560 prefs_set_int_attribute ("tools.dropper", "pick",
2561 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)));
2562 GtkWidget *set_checkbox = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "set_checkbox");
2563 if (set_checkbox) {
2564 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) {
2565 gtk_widget_set_sensitive (GTK_WIDGET (set_checkbox), TRUE);
2566 } else {
2567 gtk_widget_set_sensitive (GTK_WIDGET (set_checkbox), FALSE);
2568 }
2569 }
2570 }
2572 static void toggle_dropper_set_alpha (GtkWidget *button, gpointer data) {
2573 prefs_set_int_attribute ("tools.dropper", "setalpha",
2574 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0);
2575 }
2578 /**
2579 * Copy the current saved desktop color to the clipboard as full hex + alpha
2580 * color representation. This is useful for passing values between various
2581 * input boxes, or directly to xml.
2582 */
2583 /* static void
2584 sp_dropper_copy( GtkWidget *widget, GtkObject *obj)
2585 {
2586 GtkWidget *tbl = GTK_WIDGET(obj);
2588 SPDesktop *desktop =
2589 (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2592 sp_dropper_c32_color_copy( sp_desktop_get_color(desktop, true) );
2593 }*/
2596 /**
2597 * Copies currently saved desktop color to the clipboard as a hex value. This
2598 * is useful for editing webpages and needing a value quickly for web
2599 * colors.
2600 *
2601 * TODO: When the toggle of the dropper is set to not mix color against
2602 * page background, this still just gets the color of the page and
2603 * doesn't get the actual mixed against background which is needed
2604 * for the hex value ppl. want for web pages, etc.
2605 */
2607 /* static void
2608 sp_dropper_copy_as_hex ( GtkWidget *widget, GtkObject *obj)
2609 {
2610 GtkWidget *tbl = GTK_WIDGET(obj);
2612 SPDesktop *desktop =
2613 (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2615 sp_dropper_c32_color_copy_hex( sp_desktop_get_color(desktop, true) );
2616 }*/
2619 /**
2620 * Sets the input boxes with the changed color and opacity. This is used as a
2621 * callback for style changing.
2622 */
2623 /* static bool
2624 sp_style_changed (const SPCSSAttr *css, gpointer data)
2625 {
2626 // GrDrag *drag = (GrDrag *) data;
2628 // set fill of text entry box
2629 if (css->attribute("fill"))
2630 gtk_entry_set_text((GtkEntry *)dropper_rgb_entry,
2631 css->attribute("fill"));
2633 // set opacity of text entry box
2634 if (css->attribute("fill-opacity"))
2635 gtk_entry_set_text((GtkEntry *)dropper_opacity_entry,
2636 css->attribute("fill-opacity"));
2638 // set fill of text entry box
2639 if (css->attribute("stroke"))
2640 gtk_entry_set_text((GtkEntry *)dropper_rgb_entry,
2641 css->attribute("stroke"));
2643 // set opacity of text entry box
2644 if (css->attribute("stroke-opacity"))
2645 gtk_entry_set_text((GtkEntry *)dropper_opacity_entry,
2646 css->attribute("stroke-opacity"));
2647 return false;
2649 }
2650 */
2653 /**
2654 * Dropper auxiliary toolbar construction and setup.
2655 *
2656 * TODO: Would like to add swatch of current color.
2657 * TODO: Add queue of last 5 or so colors selected with new swatches so that
2658 * can drag and drop places. Will provide a nice mixing palette.
2659 */
2660 static GtkWidget *
2661 sp_dropper_toolbox_new(SPDesktop *desktop)
2662 {
2663 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2665 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2666 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2668 GtkTooltips *tt = gtk_tooltips_new();
2671 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
2672 AUX_BETWEEN_BUTTON_GROUPS);
2673 // sp_toolbox_add_label(tbl, _("<b>New:</b>"));
2677 /* RGB Input Field */
2678 /* {
2679 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2680 GtkWidget *dropper_rgba_label = gtk_label_new ("Color:");
2681 gtk_widget_show (dropper_rgba_label);
2682 gtk_container_add(GTK_CONTAINER(hb), dropper_rgba_label);
2684 dropper_rgb_entry = gtk_entry_new ();
2685 sp_dialog_defocus_on_enter (dropper_rgb_entry);
2686 gtk_entry_set_max_length (GTK_ENTRY (dropper_rgb_entry), 7);
2687 gtk_entry_set_width_chars (GTK_ENTRY (dropper_rgb_entry), 7);
2688 gtk_tooltips_set_tip(tt, dropper_rgb_entry,
2689 _("Hexidecimal representation of last selected "
2690 "color"),
2691 NULL);
2692 gtk_widget_show (dropper_rgb_entry);
2693 gtk_container_add(GTK_CONTAINER(hb), dropper_rgb_entry);
2695 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2696 AUX_BETWEEN_BUTTON_GROUPS);
2697 } */
2699 /* Opacity Input Field */
2700 /* {
2701 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2702 GtkWidget *dropper_opacity_label = gtk_label_new ( _("Opacity:") );
2703 gtk_widget_show (dropper_opacity_label);
2704 gtk_container_add(GTK_CONTAINER(hb), dropper_opacity_label);
2706 dropper_opacity_entry = gtk_entry_new ();
2707 sp_dialog_defocus_on_enter (dropper_opacity_entry);
2708 gtk_entry_set_max_length (GTK_ENTRY (dropper_opacity_entry), 11);
2709 gtk_entry_set_width_chars (GTK_ENTRY (dropper_opacity_entry), 11);
2710 gtk_tooltips_set_tip(tt, dropper_opacity_entry,
2711 _("Opacity of last selected color"),
2712 NULL);
2713 gtk_widget_show (dropper_opacity_entry);
2714 gtk_container_add(GTK_CONTAINER(hb), dropper_opacity_entry);
2716 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2717 AUX_BETWEEN_BUTTON_GROUPS);
2718 } */
2721 /* Copy to Clipboard */
2722 /* {
2723 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2724 GtkWidget *b = gtk_button_new_with_label(_("Copy as RGBA"));
2725 gtk_tooltips_set_tip(tt, b, _("Copy last saved color as hexidecimal "
2726 "RGB + Alpha (RGBA) to "
2727 "clipboard"),
2728 NULL);
2729 gtk_widget_show(b);
2730 gtk_container_add(GTK_CONTAINER(hb), b);
2731 gtk_signal_connect(GTK_OBJECT(b), "clicked",
2732 GTK_SIGNAL_FUNC(sp_dropper_copy), tbl);
2733 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2734 AUX_BETWEEN_BUTTON_GROUPS);
2735 } */
2738 /* Copy to Clipboard as HEX */
2739 /* {
2740 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2741 GtkWidget *b = gtk_button_new_with_label(_("Copy as HEX"));
2742 gtk_tooltips_set_tip(tt, b, _("Copy last saved color as "
2743 "hexidecimal RGB without alpha "
2744 "to clipboard"), NULL);
2745 gtk_widget_show(b);
2746 gtk_container_add(GTK_CONTAINER(hb), b);
2747 gtk_signal_connect(GTK_OBJECT(b), "clicked",
2748 GTK_SIGNAL_FUNC(sp_dropper_copy_as_hex), tbl);
2749 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2750 AUX_BETWEEN_BUTTON_GROUPS);
2751 } */
2753 // aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2755 {
2756 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2758 GtkWidget *button = gtk_check_button_new_with_label(_("Pick alpha"));
2759 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);
2760 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
2761 prefs_get_int_attribute ("tools.dropper",
2762 "pick", 1));
2763 gtk_widget_show(button);
2764 gtk_container_add (GTK_CONTAINER (hb), button);
2765 gtk_object_set_data(GTK_OBJECT(tbl), "pick_checkbox", button);
2766 g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK (toggle_dropper_pick_alpha), tbl);
2767 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2768 AUX_BETWEEN_BUTTON_GROUPS);
2769 }
2771 {
2772 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2774 GtkWidget *button = gtk_check_button_new_with_label(_("Set alpha"));
2775 gtk_tooltips_set_tip(tt, button, _("If alpha was picked, assign it to selection as fill or stroke transparency"), NULL);
2776 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
2777 prefs_get_int_attribute ("tools.dropper",
2778 "setalpha", 1));
2779 gtk_widget_show(button);
2780 gtk_container_add (GTK_CONTAINER (hb), button);
2781 gtk_object_set_data(GTK_OBJECT(tbl), "set_checkbox", button);
2782 g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK (toggle_dropper_set_alpha), tbl);
2784 // make sure it's disabled if we're not picking alpha
2785 GtkWidget *pick_checkbox = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "pick_checkbox");
2786 if (pick_checkbox) {
2787 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pick_checkbox))) {
2788 gtk_widget_set_sensitive (GTK_WIDGET (button), TRUE);
2789 } else {
2790 gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
2791 }
2792 }
2794 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2795 AUX_BETWEEN_BUTTON_GROUPS);
2796 }
2798 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2801 // where new gtkmm stuff should go
2803 gtk_widget_show_all(tbl);
2804 sp_set_font_size_smaller (tbl);
2806 /*
2807 sigc::connection *connection = new sigc::connection(
2808 desktop->connectSetStyle(
2809 sigc::bind(sigc::ptr_fun(sp_style_changed),
2810 desktop)) );
2812 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection),
2813 connection); */
2815 return tbl;
2816 }
2819 //########################
2820 //## Text Toolbox ##
2821 //########################
2822 /*
2823 static void
2824 sp_text_letter_changed(GtkAdjustment *adj, GtkWidget *tbl)
2825 {
2826 //Call back for letter sizing spinbutton
2827 }
2829 static void
2830 sp_text_line_changed(GtkAdjustment *adj, GtkWidget *tbl)
2831 {
2832 //Call back for line height spinbutton
2833 }
2835 static void
2836 sp_text_horiz_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
2837 {
2838 //Call back for horizontal kerning spinbutton
2839 }
2841 static void
2842 sp_text_vert_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
2843 {
2844 //Call back for vertical kerning spinbutton
2845 }
2847 static void
2848 sp_text_letter_rotation_changed(GtkAdjustment *adj, GtkWidget *tbl)
2849 {
2850 //Call back for letter rotation spinbutton
2851 }*/
2853 namespace {
2855 bool visible = false;
2857 void
2858 sp_text_toolbox_selection_changed (Inkscape::Selection *selection, GObject *tbl)
2859 {
2861 SPStyle *query =
2862 sp_style_new ();
2864 int result_family =
2865 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
2867 int result_style =
2868 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
2870 int result_numbers =
2871 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
2873 gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
2875 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
2876 if (result_family == QUERY_STYLE_NOTHING || result_style == QUERY_STYLE_NOTHING || result_numbers == QUERY_STYLE_NOTHING)
2877 {
2878 Inkscape::XML::Node *repr = inkscape_get_repr (INKSCAPE, "tools.text");
2880 if (repr)
2881 {
2882 sp_style_read_from_repr (query, repr);
2883 }
2884 else
2885 {
2886 return;
2887 }
2888 }
2890 if (query->text)
2891 {
2892 if (result_family == QUERY_STYLE_MULTIPLE_DIFFERENT) {
2893 GtkWidget *entry = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "family-entry"));
2894 gtk_entry_set_text (GTK_ENTRY (entry), "");
2896 } else if (query->text->font_family.value) {
2898 GtkWidget *entry = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "family-entry"));
2899 gtk_entry_set_text (GTK_ENTRY (entry), query->text->font_family.value);
2901 Gtk::TreePath path;
2902 try {
2903 path = Inkscape::FontLister::get_instance()->get_row_for_font (query->text->font_family.value);
2904 } catch (...) {
2905 return;
2906 }
2908 GtkTreeSelection *tselection = GTK_TREE_SELECTION (g_object_get_data (G_OBJECT(tbl), "family-tree-selection"));
2909 GtkTreeView *treeview = GTK_TREE_VIEW (g_object_get_data (G_OBJECT(tbl), "family-tree-view"));
2911 g_object_set_data (G_OBJECT (tselection), "block", gpointer(1));
2913 gtk_tree_selection_select_path (tselection, path.gobj());
2914 gtk_tree_view_scroll_to_cell (treeview, path.gobj(), NULL, TRUE, 0.5, 0.0);
2916 g_object_set_data (G_OBJECT (tselection), "block", gpointer(0));
2917 }
2919 //Size
2920 GtkWidget *cbox = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "combo-box-size"));
2921 char *str = g_strdup_printf ("%.5g", query->font_size.computed);
2922 g_object_set_data (tbl, "size-block", gpointer(1));
2923 gtk_entry_set_text (GTK_ENTRY(GTK_BIN (cbox)->child), str);
2924 g_object_set_data (tbl, "size-block", gpointer(0));
2925 free (str);
2927 //Anchor
2928 if (query->text_align.computed == SP_CSS_TEXT_ALIGN_JUSTIFY)
2929 {
2930 GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-fill"));
2931 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
2932 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2933 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
2934 }
2935 else
2936 {
2937 if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_START)
2938 {
2939 GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-start"));
2940 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
2941 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2942 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
2943 }
2944 else if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_MIDDLE)
2945 {
2946 GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-middle"));
2947 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
2948 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2949 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
2950 }
2951 else if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_END)
2952 {
2953 GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-end"));
2954 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
2955 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2956 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
2957 }
2958 }
2960 //Style
2961 {
2962 GtkToggleButton *button = GTK_TOGGLE_BUTTON (g_object_get_data (G_OBJECT (tbl), "style-bold"));
2964 gboolean active = gtk_toggle_button_get_active (button);
2965 gboolean check = (query->font_weight.computed >= SP_CSS_FONT_WEIGHT_700);
2967 if (active != check)
2968 {
2969 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
2970 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), check);
2971 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
2972 }
2973 }
2975 {
2976 GtkToggleButton *button = GTK_TOGGLE_BUTTON (g_object_get_data (G_OBJECT (tbl), "style-italic"));
2978 gboolean active = gtk_toggle_button_get_active (button);
2979 gboolean check = (query->font_style.computed != SP_CSS_FONT_STYLE_NORMAL);
2981 if (active != check)
2982 {
2983 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
2984 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), check);
2985 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
2986 }
2987 }
2989 //Orientation
2990 //locking both buttons, changing one affect all group (both)
2991 GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "orientation-horizontal"));
2992 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
2994 GtkWidget *button1 = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "orientation-vertical"));
2995 g_object_set_data (G_OBJECT (button1), "block", gpointer(1));
2997 if (query->writing_mode.computed == SP_CSS_WRITING_MODE_LR_TB)
2998 {
2999 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
3000 }
3001 else
3002 {
3003 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button1), TRUE);
3004 }
3005 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
3006 g_object_set_data (G_OBJECT (button1), "block", gpointer(0));
3007 }
3008 }
3010 void
3011 sp_text_toolbox_selection_modified (Inkscape::Selection *selection, guint flags, GObject *tbl)
3012 {
3013 sp_text_toolbox_selection_changed (selection, tbl);
3014 }
3016 void
3017 sp_text_toolbox_subselection_changed (gpointer dragger, GObject *tbl)
3018 {
3019 sp_text_toolbox_selection_changed (NULL, tbl);
3020 }
3022 void
3023 sp_text_toolbox_family_changed (GtkTreeSelection *selection,
3024 GObject *tbl)
3025 {
3026 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3027 GtkTreeModel *model = 0;
3028 GtkWidget *popdown = GTK_WIDGET (g_object_get_data (tbl, "family-popdown-window"));
3029 GtkWidget *entry = GTK_WIDGET (g_object_get_data (tbl, "family-entry"));
3030 GtkTreeIter iter;
3031 char *family = 0;
3033 gdk_pointer_ungrab (GDK_CURRENT_TIME);
3034 gdk_keyboard_ungrab (GDK_CURRENT_TIME);
3036 if ( !gtk_tree_selection_get_selected( selection, &model, &iter ) ) {
3037 return;
3038 }
3040 gtk_tree_model_get (model, &iter, 0, &family, -1);
3042 if (g_object_get_data (G_OBJECT (selection), "block"))
3043 {
3044 gtk_entry_set_text (GTK_ENTRY (entry), family);
3045 return;
3046 }
3048 gtk_widget_hide (popdown);
3049 visible = false;
3051 gtk_entry_set_text (GTK_ENTRY (entry), family);
3053 SPStyle *query =
3054 sp_style_new ();
3056 int result_numbers =
3057 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
3059 SPCSSAttr *css = sp_repr_css_attr_new ();
3060 sp_repr_css_set_property (css, "font-family", family);
3062 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
3063 if (result_numbers == QUERY_STYLE_NOTHING)
3064 {
3065 sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
3066 sp_text_edit_dialog_default_set_insensitive (); //FIXME: Replace trough a verb
3067 }
3068 else
3069 {
3070 sp_desktop_set_style (desktop, css, true, true);
3071 }
3073 sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
3074 /* TODO: annotate */ "toolbox.cpp:3024");
3075 sp_repr_css_attr_unref (css);
3076 free (family);
3077 gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
3079 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3080 }
3082 void
3083 sp_text_toolbox_family_entry_activate (GtkEntry *entry,
3084 GObject *tbl)
3085 {
3086 const char *family = gtk_entry_get_text (entry);
3088 try {
3089 Gtk::TreePath path = Inkscape::FontLister::get_instance()->get_row_for_font (family);
3090 GtkTreeSelection *selection = GTK_TREE_SELECTION (g_object_get_data (G_OBJECT(tbl), "family-tree-selection"));
3091 GtkTreeView *treeview = GTK_TREE_VIEW (g_object_get_data (G_OBJECT(tbl), "family-tree-view"));
3092 gtk_tree_selection_select_path (selection, path.gobj());
3093 gtk_tree_view_scroll_to_cell (treeview, path.gobj(), NULL, TRUE, 0.5, 0.0);
3094 gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
3095 } catch (...) {
3096 if (family && strlen (family))
3097 {
3098 gtk_widget_show_all (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
3099 }
3100 }
3101 }
3103 void
3104 sp_text_toolbox_anchoring_toggled (GtkRadioButton *button,
3105 gpointer data)
3106 {
3107 if (g_object_get_data (G_OBJECT (button), "block")) return;
3108 if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) return;
3109 int prop = GPOINTER_TO_INT(data);
3111 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3112 SPCSSAttr *css = sp_repr_css_attr_new ();
3114 switch (prop)
3115 {
3116 case 0:
3117 {
3118 sp_repr_css_set_property (css, "text-anchor", "start");
3119 sp_repr_css_set_property (css, "text-align", "start");
3120 break;
3121 }
3122 case 1:
3123 {
3124 sp_repr_css_set_property (css, "text-anchor", "middle");
3125 sp_repr_css_set_property (css, "text-align", "center");
3126 break;
3127 }
3129 case 2:
3130 {
3131 sp_repr_css_set_property (css, "text-anchor", "end");
3132 sp_repr_css_set_property (css, "text-align", "end");
3133 break;
3134 }
3136 case 3:
3137 {
3138 sp_repr_css_set_property (css, "text-anchor", "start");
3139 sp_repr_css_set_property (css, "text-align", "justify");
3140 break;
3141 }
3142 }
3144 SPStyle *query =
3145 sp_style_new ();
3146 int result_numbers =
3147 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
3149 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
3150 if (result_numbers == QUERY_STYLE_NOTHING)
3151 {
3152 sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
3153 }
3155 sp_desktop_set_style (desktop, css, true, true);
3156 sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
3157 /* TODO: annotate */ "toolbox.cpp:3107");
3158 sp_repr_css_attr_unref (css);
3160 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3161 }
3163 void
3164 sp_text_toolbox_style_toggled (GtkToggleButton *button,
3165 gpointer data)
3166 {
3167 if (g_object_get_data (G_OBJECT (button), "block")) return;
3169 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3170 SPCSSAttr *css = sp_repr_css_attr_new ();
3171 int prop = GPOINTER_TO_INT(data);
3172 bool active = gtk_toggle_button_get_active (button);
3175 switch (prop)
3176 {
3177 case 0:
3178 {
3179 sp_repr_css_set_property (css, "font-weight", active ? "bold" : "normal" );
3180 break;
3181 }
3183 case 1:
3184 {
3185 sp_repr_css_set_property (css, "font-style", active ? "italic" : "normal");
3186 break;
3187 }
3188 }
3190 SPStyle *query =
3191 sp_style_new ();
3192 int result_numbers =
3193 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
3195 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
3196 if (result_numbers == QUERY_STYLE_NOTHING)
3197 {
3198 sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
3199 }
3201 sp_desktop_set_style (desktop, css, true, true);
3202 sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
3203 /* TODO: annotate */ "toolbox.cpp:3153");
3204 sp_repr_css_attr_unref (css);
3206 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3207 }
3209 void
3210 sp_text_toolbox_orientation_toggled (GtkRadioButton *button,
3211 gpointer data)
3212 {
3213 if (g_object_get_data (G_OBJECT (button), "block")) {
3214 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
3215 return;
3216 }
3218 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3219 SPCSSAttr *css = sp_repr_css_attr_new ();
3220 int prop = GPOINTER_TO_INT(data);
3222 switch (prop)
3223 {
3224 case 0:
3225 {
3226 sp_repr_css_set_property (css, "writing-mode", "lr");
3227 break;
3228 }
3230 case 1:
3231 {
3232 sp_repr_css_set_property (css, "writing-mode", "tb");
3233 break;
3234 }
3235 }
3237 SPStyle *query =
3238 sp_style_new ();
3239 int result_numbers =
3240 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
3242 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
3243 if (result_numbers == QUERY_STYLE_NOTHING)
3244 {
3245 sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
3246 }
3248 sp_desktop_set_style (desktop, css, true, true);
3249 sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
3250 /* TODO: annotate */ "toolbox.cpp:3200");
3251 sp_repr_css_attr_unref (css);
3253 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3254 }
3256 gboolean
3257 sp_text_toolbox_size_keypress (GtkWidget *w, GdkEventKey *event, gpointer data)
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 return TRUE; // I consumed the event
3266 break;
3267 case GDK_Return: // defocus
3268 case GDK_KP_Enter:
3269 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3270 return TRUE; // I consumed the event
3271 break;
3272 }
3273 return FALSE;
3274 }
3276 gboolean
3277 sp_text_toolbox_family_keypress (GtkWidget *w, GdkEventKey *event, GObject *tbl)
3278 {
3279 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3280 if (!desktop) return FALSE;
3282 switch (get_group0_keyval (event)) {
3283 case GDK_Escape: // defocus
3284 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3285 sp_text_toolbox_selection_changed (NULL, tbl); // update
3286 return TRUE; // I consumed the event
3287 break;
3288 }
3289 return FALSE;
3290 }
3292 gboolean
3293 sp_text_toolbox_family_list_keypress (GtkWidget *w, GdkEventKey *event, GObject *tbl)
3294 {
3295 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3296 if (!desktop) return FALSE;
3298 switch (get_group0_keyval (event)) {
3299 case GDK_Escape: // defocus
3300 gtk_widget_hide (w);
3301 visible = false;
3302 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3303 return TRUE; // I consumed the event
3304 break;
3305 }
3306 return FALSE;
3307 }
3310 void
3311 sp_text_toolbox_size_changed (GtkComboBox *cbox,
3312 GObject *tbl)
3313 {
3314 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3316 if (g_object_get_data (tbl, "size-block")) return;
3318 #if GTK_CHECK_VERSION(2,6,0)
3319 char *text = gtk_combo_box_get_active_text (cbox);
3320 #else // GTK_CHECK_VERSION(2,6,0)
3321 GtkTreeModel *model = gtk_combo_box_get_model (cbox);
3322 GtkTreeIter iter;
3323 char *text = NULL;
3325 if (gtk_combo_box_get_active_iter (cbox, &iter) && model)
3326 gtk_tree_model_get (model, &iter, 0, &text, -1);
3327 #endif // GTK_CHECK_VERSION(2,6,0)
3329 SPCSSAttr *css = sp_repr_css_attr_new ();
3330 sp_repr_css_set_property (css, "font-size", text);
3331 free (text);
3333 SPStyle *query =
3334 sp_style_new ();
3335 int result_numbers =
3336 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
3338 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
3339 if (result_numbers == QUERY_STYLE_NOTHING)
3340 {
3341 sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
3342 }
3344 sp_desktop_set_style (desktop, css, true, true);
3345 sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:size", SP_VERB_NONE,
3346 /* TODO: annotate */ "toolbox.cpp:3296");
3347 sp_repr_css_attr_unref (css);
3350 if (gtk_combo_box_get_active (cbox) > 0) // if this was from drop-down (as opposed to type-in), defocus
3351 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3352 }
3354 void
3355 sp_text_toolbox_text_popdown_clicked (GtkButton *button,
3356 GObject *tbl)
3357 {
3358 GtkWidget *popdown = GTK_WIDGET (g_object_get_data (tbl, "family-popdown-window"));
3359 GtkWidget *widget = GTK_WIDGET (g_object_get_data (tbl, "family-entry"));
3360 int x, y;
3362 if (!visible)
3363 {
3364 gdk_window_get_origin (widget->window, &x, &y);
3365 gtk_window_move (GTK_WINDOW (popdown), x, y + widget->allocation.height + 2); //2px of grace space
3366 gtk_widget_show_all (popdown);
3368 gdk_pointer_grab (widget->window, TRUE,
3369 GdkEventMask (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
3370 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
3371 GDK_POINTER_MOTION_MASK),
3372 NULL, NULL, GDK_CURRENT_TIME);
3374 gdk_keyboard_grab (widget->window, TRUE, GDK_CURRENT_TIME);
3376 visible = true;
3377 }
3378 else
3379 {
3380 gdk_pointer_ungrab (GDK_CURRENT_TIME);
3381 gdk_keyboard_ungrab (GDK_CURRENT_TIME);
3382 gtk_widget_hide (popdown);
3383 visible = false;
3384 }
3385 }
3387 gboolean
3388 sp_text_toolbox_entry_focus_in (GtkWidget *entry,
3389 GdkEventFocus *event,
3390 GObject *tbl)
3391 {
3392 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
3393 return FALSE;
3394 }
3396 gboolean
3397 sp_text_toolbox_popdown_focus_out (GtkWidget *popdown,
3398 GdkEventFocus *event,
3399 GObject *tbl)
3400 {
3401 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3403 gtk_widget_hide (popdown);
3404 visible = false;
3405 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3406 return TRUE;
3407 }
3409 void
3410 cell_data_func (GtkTreeViewColumn *column,
3411 GtkCellRenderer *cell,
3412 GtkTreeModel *tree_model,
3413 GtkTreeIter *iter,
3414 gpointer data)
3415 {
3416 char *family,
3417 *family_escaped,
3418 *sample_escaped;
3420 static const char *sample = _("AaBbCcIiPpQq12369$\342\202\254\302\242?.;/()");
3422 gtk_tree_model_get (tree_model, iter, 0, &family, -1);
3424 family_escaped = g_markup_escape_text (family, -1);
3425 sample_escaped = g_markup_escape_text (sample, -1);
3427 std::stringstream markup;
3428 markup << family_escaped << " <span foreground='darkgray' font_family='" << family_escaped << "'>" << sample_escaped << "</span>";
3429 g_object_set (G_OBJECT (cell), "markup", markup.str().c_str(), NULL);
3431 free (family);
3432 free (family_escaped);
3433 free (sample_escaped);
3434 }
3436 static void delete_completion(GObject *obj, GtkWidget *entry) {
3437 GObject *completion = (GObject *) gtk_object_get_data(GTK_OBJECT(entry), "completion");
3438 if (completion) {
3439 gtk_entry_set_completion (GTK_ENTRY(entry), NULL);
3440 g_object_unref (completion);
3441 }
3442 }
3444 GtkWidget*
3445 sp_text_toolbox_new (SPDesktop *desktop)
3446 {
3447 GtkWidget *tbl = gtk_hbox_new (FALSE, 0);
3449 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
3450 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
3452 GtkTooltips *tt = gtk_tooltips_new();
3453 Glib::RefPtr<Gtk::ListStore> store = Inkscape::FontLister::get_instance()->get_font_list();
3455 ////////////Family
3456 //Window
3457 GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3458 gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
3460 //Entry
3461 GtkWidget *entry = gtk_entry_new ();
3462 gtk_object_set_data(GTK_OBJECT(entry), "altx-text", entry);
3463 GtkEntryCompletion *completion = gtk_entry_completion_new ();
3464 gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (Glib::unwrap(store)));
3465 gtk_entry_completion_set_text_column (completion, 0);
3466 gtk_entry_completion_set_minimum_key_length (completion, 1);
3467 g_object_set (G_OBJECT(completion), "inline-completion", TRUE, "popup-completion", TRUE, NULL);
3468 gtk_entry_set_completion (GTK_ENTRY(entry), completion);
3469 gtk_object_set_data(GTK_OBJECT(entry), "completion", completion);
3470 aux_toolbox_space (tbl, 1);
3471 gtk_box_pack_start (GTK_BOX (tbl), entry, FALSE, FALSE, 0);
3472 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_completion), entry);
3474 //Button
3475 GtkWidget *button = gtk_button_new ();
3476 gtk_container_add (GTK_CONTAINER (button), gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE));
3477 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
3479 //Popdown
3480 GtkWidget *sw = gtk_scrolled_window_new (NULL, NULL);
3481 GtkWidget *treeview = gtk_tree_view_new ();
3483 GtkCellRenderer *cell = gtk_cell_renderer_text_new ();
3484 GtkTreeViewColumn *column = gtk_tree_view_column_new ();
3485 gtk_tree_view_column_pack_start (column, cell, FALSE);
3486 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
3487 gtk_tree_view_column_set_cell_data_func (column, cell, GtkTreeCellDataFunc (cell_data_func), NULL, NULL);
3488 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
3490 gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (Glib::unwrap(store)));
3491 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
3492 #if GTK_CHECK_VERSION(2,6,0)
3493 gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (treeview), TRUE);
3494 #endif // GTK_CHECK_VERSION(2,6,0)
3496 //gtk_tree_view_set_enable_search (GTK_TREE_VIEW (treeview), TRUE);
3498 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
3499 gtk_container_add (GTK_CONTAINER (sw), treeview);
3501 gtk_container_add (GTK_CONTAINER (window), sw);
3502 gtk_widget_set_size_request (window, 300, 450);
3504 g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (sp_text_toolbox_family_entry_activate), tbl);
3505 g_signal_connect (G_OBJECT (entry), "focus-in-event", G_CALLBACK (sp_text_toolbox_entry_focus_in), tbl);
3506 g_signal_connect (G_OBJECT (entry), "key-press-event", G_CALLBACK(sp_text_toolbox_family_keypress), tbl);
3508 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (sp_text_toolbox_text_popdown_clicked), tbl);
3510 g_signal_connect (G_OBJECT (window), "focus-out-event", G_CALLBACK (sp_text_toolbox_popdown_focus_out), tbl);
3511 g_signal_connect (G_OBJECT (window), "key-press-event", G_CALLBACK(sp_text_toolbox_family_list_keypress), tbl);
3513 GtkTreeSelection *tselection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
3514 g_signal_connect (G_OBJECT (tselection), "changed", G_CALLBACK (sp_text_toolbox_family_changed), tbl);
3516 g_object_set_data (G_OBJECT (tbl), "family-entry", entry);
3517 g_object_set_data (G_OBJECT (tbl), "family-popdown-button", button);
3518 g_object_set_data (G_OBJECT (tbl), "family-popdown-window", window);
3519 g_object_set_data (G_OBJECT (tbl), "family-tree-selection", tselection);
3520 g_object_set_data (G_OBJECT (tbl), "family-tree-view", treeview);
3522 GtkWidget *image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
3523 aux_toolbox_space (tbl, 1);
3524 GtkWidget *box = gtk_event_box_new ();
3525 gtk_container_add (GTK_CONTAINER (box), image);
3526 gtk_box_pack_start (GTK_BOX (tbl), box, FALSE, FALSE, 4);
3527 g_object_set_data (G_OBJECT (tbl), "warning-image", box);
3528 GtkTooltips *tooltips = gtk_tooltips_new ();
3529 gtk_tooltips_set_tip (tooltips, box, _("This font is currently not installed on your system. Inkscape will use the default font instead."), "");
3530 gtk_widget_hide (GTK_WIDGET (box));
3531 g_signal_connect_swapped (G_OBJECT (tbl), "show", G_CALLBACK (gtk_widget_hide), box);
3533 ////////////Size
3534 const char *sizes[] = {
3535 "4", "6", "8", "9", "10", "11", "12", "13", "14",
3536 "16", "18", "20", "22", "24", "28",
3537 "32", "36", "40", "48", "56", "64", "72", "144"
3538 };
3540 GtkWidget *cbox = gtk_combo_box_entry_new_text ();
3541 for (unsigned int n = 0; n < G_N_ELEMENTS (sizes); gtk_combo_box_append_text (GTK_COMBO_BOX(cbox), sizes[n++]));
3542 gtk_widget_set_size_request (cbox, 80, -1);
3543 aux_toolbox_space (tbl, 1);
3544 gtk_box_pack_start (GTK_BOX (tbl), cbox, FALSE, FALSE, 0);
3545 g_object_set_data (G_OBJECT (tbl), "combo-box-size", cbox);
3546 g_signal_connect (G_OBJECT (cbox), "changed", G_CALLBACK (sp_text_toolbox_size_changed), tbl);
3547 gtk_signal_connect(GTK_OBJECT(cbox), "key-press-event", GTK_SIGNAL_FUNC(sp_text_toolbox_size_keypress), NULL);
3549 //spacer
3550 aux_toolbox_space (tbl, 4);
3551 gtk_box_pack_start (GTK_BOX (tbl), gtk_vseparator_new (), FALSE, FALSE, 4);
3553 ////////////Text anchor
3554 GtkWidget *group = gtk_radio_button_new (NULL);
3555 GtkWidget *row = gtk_hbox_new (FALSE, 4);
3556 g_object_set_data (G_OBJECT (tbl), "anchor-group", group);
3558 // left
3559 GtkWidget *rbutton = group;
3560 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3561 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_LEFT, GTK_ICON_SIZE_SMALL_TOOLBAR));
3562 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3564 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3565 g_object_set_data (G_OBJECT (tbl), "text-start", rbutton);
3566 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer(0));
3567 gtk_tooltips_set_tip(tt, rbutton, _("Align left"), NULL);
3569 // center
3570 rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3571 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3572 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_CENTER, GTK_ICON_SIZE_SMALL_TOOLBAR));
3573 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3575 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3576 g_object_set_data (G_OBJECT (tbl), "text-middle", rbutton);
3577 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer (1));
3578 gtk_tooltips_set_tip(tt, rbutton, _("Center"), NULL);
3580 // right
3581 rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3582 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3583 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_RIGHT, GTK_ICON_SIZE_SMALL_TOOLBAR));
3584 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3586 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3587 g_object_set_data (G_OBJECT (tbl), "text-end", rbutton);
3588 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer(2));
3589 gtk_tooltips_set_tip(tt, rbutton, _("Align right"), NULL);
3591 // fill
3592 rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3593 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3594 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_FILL, GTK_ICON_SIZE_SMALL_TOOLBAR));
3595 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3597 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3598 g_object_set_data (G_OBJECT (tbl), "text-fill", rbutton);
3599 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer(3));
3600 gtk_tooltips_set_tip(tt, rbutton, _("Justify"), NULL);
3602 aux_toolbox_space (tbl, 1);
3603 gtk_box_pack_start (GTK_BOX (tbl), row, FALSE, FALSE, 4);
3605 //spacer
3606 gtk_box_pack_start (GTK_BOX (tbl), gtk_vseparator_new (), FALSE, FALSE, 4);
3608 ////////////Text style
3609 row = gtk_hbox_new (FALSE, 4);
3611 // bold
3612 rbutton = gtk_toggle_button_new ();
3613 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3614 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_BOLD, GTK_ICON_SIZE_SMALL_TOOLBAR));
3615 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3616 gtk_tooltips_set_tip(tt, rbutton, _("Bold"), NULL);
3618 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3619 g_object_set_data (G_OBJECT (tbl), "style-bold", rbutton);
3620 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_style_toggled), gpointer(0));
3622 // italic
3623 rbutton = gtk_toggle_button_new ();
3624 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3625 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_ITALIC, GTK_ICON_SIZE_SMALL_TOOLBAR));
3626 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3627 gtk_tooltips_set_tip(tt, rbutton, _("Italic"), NULL);
3629 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3630 g_object_set_data (G_OBJECT (tbl), "style-italic", rbutton);
3631 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_style_toggled), gpointer (1));
3633 aux_toolbox_space (tbl, 1);
3634 gtk_box_pack_start (GTK_BOX (tbl), row, FALSE, FALSE, 4);
3636 //spacer
3637 gtk_box_pack_start (GTK_BOX (tbl), gtk_vseparator_new (), FALSE, FALSE, 4);
3639 ////////////Text orientation
3640 group = gtk_radio_button_new (NULL);
3641 row = gtk_hbox_new (FALSE, 4);
3642 g_object_set_data (G_OBJECT (tbl), "orientation-group", group);
3644 // horizontal
3645 rbutton = group;
3646 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3647 gtk_container_add (GTK_CONTAINER (rbutton), sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_LR));
3648 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3649 gtk_tooltips_set_tip(tt, rbutton, _("Horizontal text"), NULL);
3651 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3652 g_object_set_data (G_OBJECT (tbl), "orientation-horizontal", rbutton);
3653 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_orientation_toggled), gpointer(0));
3655 // vertical
3656 rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3657 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3658 gtk_container_add (GTK_CONTAINER (rbutton), sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_TB));
3659 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3660 gtk_tooltips_set_tip(tt, rbutton, _("Vertical text"), NULL);
3662 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3663 g_object_set_data (G_OBJECT (tbl), "orientation-vertical", rbutton);
3664 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_orientation_toggled), gpointer (1));
3665 gtk_box_pack_start (GTK_BOX (tbl), row, FALSE, FALSE, 4);
3668 //watch selection
3669 Inkscape::ConnectionPool* pool = Inkscape::ConnectionPool::new_connection_pool ("ISTextToolbox");
3671 sigc::connection *c_selection_changed =
3672 new sigc::connection (sp_desktop_selection (desktop)->connectChanged
3673 (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_changed), (GObject*)tbl)));
3674 pool->add_connection ("selection-changed", c_selection_changed);
3676 sigc::connection *c_selection_modified =
3677 new sigc::connection (sp_desktop_selection (desktop)->connectModified
3678 (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_modified), (GObject*)tbl)));
3679 pool->add_connection ("selection-modified", c_selection_modified);
3681 sigc::connection *c_subselection_changed =
3682 new sigc::connection (desktop->connectToolSubselectionChanged
3683 (sigc::bind (sigc::ptr_fun (sp_text_toolbox_subselection_changed), (GObject*)tbl)));
3684 pool->add_connection ("tool-subselection-changed", c_subselection_changed);
3686 Inkscape::ConnectionPool::connect_destroy (G_OBJECT (tbl), pool);
3689 #if 0
3690 // horizontal
3691 {
3692 GtkWidget *px= sp_icon_new(Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_LR);
3693 GtkWidget *b = group = gtk_radio_button_new (NULL);
3694 gtk_container_add (GTK_CONTAINER (b), px);
3695 gtk_tooltips_set_tip (tt, b, _("Horizontal text"), NULL);
3696 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
3697 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
3698 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
3699 }
3701 // vertical
3702 {
3703 GtkWidget *px = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_TB);
3704 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3705 gtk_container_add (GTK_CONTAINER (b), px);
3706 gtk_tooltips_set_tip (tt, b, _("Vertical text"), NULL);
3707 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
3708 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
3709 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
3710 }
3712 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
3714 // letter spacing
3715 {
3716 {
3717 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LETTER_SPACING);
3718 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3719 gtk_container_add (GTK_CONTAINER (hb), image);
3720 gtk_widget_show(image);
3721 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3722 }
3724 {
3725 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Spacing between letters"),
3726 "tools.text", "letter_spacing", 0.0,
3727 us, tbl, FALSE, NULL,
3728 -1000.0, 1000.0, 0.1, 0.1,
3729 sp_text_letter_changed, 0.1, 1);
3730 gtk_widget_set_size_request (hb, 45, 6);
3731 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
3732 }
3733 }
3735 // line spacing
3736 {
3737 {
3738 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LINE_SPACING);
3739 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3740 gtk_container_add (GTK_CONTAINER (hb), image);
3741 gtk_widget_show(image);
3742 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3743 }
3745 {
3746 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Spacing between lines"),
3747 "tools.text", "line_spacing", 0,
3748 us, tbl, FALSE, NULL,
3749 -1000.0, 1000.0, 0.1, 0.1,
3750 sp_text_line_changed, 0.1, 1);
3751 gtk_widget_set_size_request (hb, 45, 0);
3752 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 3);
3753 }
3754 }
3756 {
3757 // horizontal kerning/vertical kerning units menu: create
3758 GtkWidget *us = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
3759 sp_unit_selector_setsize(us, AUX_OPTION_MENU_WIDTH, AUX_OPTION_MENU_HEIGHT);
3760 sp_unit_selector_set_unit(SP_UNIT_SELECTOR(us), desktop->namedview->doc_units);
3762 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
3764 // horizontal kerning
3765 {
3766 {
3767 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_HORZ_KERN);
3768 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3769 gtk_container_add (GTK_CONTAINER (hb), image);
3770 gtk_widget_show(image);
3771 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3772 }
3774 {
3775 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Horizontal kerning"),
3776 "tools.text", "horizontal_kerning", 0,
3777 us, tbl, FALSE, NULL,
3778 -100.00, 100.00, 0.01, 0.1,
3779 sp_text_horiz_kern_changed);
3780 gtk_widget_set_size_request (hb, 45, 0);
3781 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
3782 }
3783 }
3785 // vertical kerning
3786 {
3787 {
3788 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_VERT_KERN);
3789 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3790 gtk_container_add (GTK_CONTAINER (hb), image);
3791 gtk_widget_show(image);
3792 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3793 }
3795 {
3796 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Vertical kerning"),
3797 "tools.text", "vertical_kerning", 0,
3798 us, tbl, FALSE, NULL,
3799 -100.00, 100.00, 0.01, 0.1,
3800 sp_text_vert_kern_changed);
3801 gtk_widget_set_size_request (hb, 45, 0);
3802 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 5);
3803 }
3804 }
3806 // add the units menu
3807 gtk_widget_show(us);
3808 gtk_box_pack_start(GTK_BOX(tbl), us, FALSE, FALSE, 1);
3809 gtk_object_set_data(GTK_OBJECT(tbl), "units", us);
3810 }
3812 // letter rotation
3813 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
3814 {
3815 {
3816 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_ROTATION);
3817 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3818 gtk_container_add (GTK_CONTAINER (hb), image);
3819 gtk_widget_show(image);
3820 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3821 }
3822 {
3823 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Letter rotation"),
3824 "tools.text", "letter_rotation", 0,
3825 us, tbl, FALSE, NULL,
3826 -180.0, 180.0, 0.1, 0.1,
3827 sp_text_letter_rotation_changed, 0.1, 1);
3828 gtk_widget_set_size_request (hb, 45, 0);
3829 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
3830 }
3831 // rotation degree label
3832 {
3833 GtkWidget *label = gtk_widget_new (GTK_TYPE_LABEL, "label", "\302\260", "xalign", 0.0, NULL);
3834 gtk_box_pack_start(GTK_BOX(tbl), label, FALSE, FALSE, 0);
3835 }
3836 }
3838 // Remove Manual Kerns
3839 {
3840 GtkWidget *px = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_REMOVE_KERNS);
3841 GtkWidget *button = gtk_button_new ();
3842 gtk_container_add (GTK_CONTAINER (button), px);
3843 gtk_widget_show(button);
3844 gtk_tooltips_set_tip (tt, button, _("Remove manual kerns"), NULL);
3845 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
3846 gtk_widget_set_sensitive(button, TRUE);
3847 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
3848 }
3849 #endif
3851 gtk_widget_show_all (tbl);
3852 return tbl;
3854 } // end of sp_text_toolbox_new()
3856 }//<unnamed> namespace
3859 //#########################
3860 //## Connector Toolbox ##
3861 //#########################
3863 static void sp_connector_path_set_avoid(void)
3864 {
3865 cc_selection_set_avoid(true);
3866 }
3869 static void sp_connector_path_set_ignore(void)
3870 {
3871 cc_selection_set_avoid(false);
3872 }
3876 static void connector_spacing_changed(GtkAdjustment *adj, GtkWidget *tbl)
3877 {
3878 // quit if run by the _changed callbacks
3879 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
3880 return;
3881 }
3883 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl),
3884 "desktop");
3885 SPDocument *doc = sp_desktop_document(desktop);
3887 if (!sp_document_get_undo_sensitive(doc))
3888 {
3889 return;
3890 }
3892 // in turn, prevent callbacks from responding
3893 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
3895 Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
3897 sp_repr_set_css_double(repr, "inkscape:connector-spacing", adj->value);
3898 SP_OBJECT(desktop->namedview)->updateRepr();
3900 GSList *items = get_avoided_items(NULL, desktop->currentRoot(), desktop);
3901 for ( GSList const *iter = items ; iter != NULL ; iter = iter->next ) {
3902 SPItem *item = reinterpret_cast<SPItem *>(iter->data);
3903 NR::Matrix m = NR::identity();
3904 avoid_item_move(&m, item);
3905 }
3907 if (items) {
3908 g_slist_free(items);
3909 }
3911 sp_document_done(doc, SP_VERB_CONTEXT_CONNECTOR,
3912 _("Change connector spacing distance"));
3914 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
3916 spinbutton_defocus(GTK_OBJECT(tbl));
3917 }
3919 static void sp_connector_graph_layout(void)
3920 {
3921 if (!SP_ACTIVE_DESKTOP) return;
3923 // hack for clones, see comment in align-and-distribute.cpp
3924 int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
3925 prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
3927 graphlayout(sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList());
3929 prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
3931 sp_document_done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_DIALOG_ALIGN_DISTRIBUTE, /* TODO: annotate */ "toolbox.cpp:129");
3932 }
3934 static void
3935 sp_directed_graph_layout_toggled(GtkWidget *widget, GtkObject *tbl)
3936 {
3937 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
3938 prefs_set_string_attribute("tools.connector", "directedlayout",
3939 "true");
3940 } else {
3941 prefs_set_string_attribute("tools.connector", "directedlayout",
3942 "false");
3943 }
3944 }
3945 static void
3946 sp_nooverlaps_graph_layout_toggled(GtkWidget *widget, GtkObject *tbl)
3947 {
3948 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
3949 prefs_set_string_attribute("tools.connector", "avoidoverlaplayout",
3950 "true");
3951 } else {
3952 prefs_set_string_attribute("tools.connector", "avoidoverlaplayout",
3953 "false");
3954 }
3955 }
3958 static void connector_length_changed(GtkAdjustment *adj, GtkWidget *tbl)
3959 {
3960 prefs_set_double_attribute("tools.connector", "length", adj->value);
3961 spinbutton_defocus(GTK_OBJECT(tbl));
3962 }
3964 static void connector_tb_event_attr_changed(Inkscape::XML::Node *repr,
3965 gchar const *name, gchar const *old_value, gchar const *new_value,
3966 bool is_interactive, gpointer data)
3967 {
3968 GtkWidget *tbl = GTK_WIDGET(data);
3970 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
3971 return;
3972 }
3973 if (strcmp(name, "inkscape:connector-spacing") != 0) {
3974 return;
3975 }
3977 GtkAdjustment *adj = (GtkAdjustment*)
3978 gtk_object_get_data(GTK_OBJECT(tbl), "spacing");
3979 gdouble spacing = defaultConnSpacing;
3980 sp_repr_get_double(repr, "inkscape:connector-spacing", &spacing);
3982 gtk_adjustment_set_value(adj, spacing);
3983 }
3986 static Inkscape::XML::NodeEventVector connector_tb_repr_events = {
3987 NULL, /* child_added */
3988 NULL, /* child_removed */
3989 connector_tb_event_attr_changed,
3990 NULL, /* content_changed */
3991 NULL /* order_changed */
3992 };
3995 static GtkWidget *
3996 sp_connector_toolbox_new(SPDesktop *desktop)
3997 {
3998 GtkTooltips *tt = gtk_tooltips_new();
3999 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
4001 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
4002 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
4004 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
4005 AUX_BETWEEN_BUTTON_GROUPS);
4007 sp_toolbox_button_new(tbl, Inkscape::ICON_SIZE_SMALL_TOOLBAR,
4008 "connector_avoid", GTK_SIGNAL_FUNC(sp_connector_path_set_avoid),
4009 tt, _("Make connectors avoid selected objects"));
4011 sp_toolbox_button_new(tbl, Inkscape::ICON_SIZE_SMALL_TOOLBAR,
4012 "connector_ignore", GTK_SIGNAL_FUNC(sp_connector_path_set_ignore),
4013 tt, _("Make connectors ignore selected objects"));
4015 // interval
4016 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
4017 AUX_BETWEEN_BUTTON_GROUPS);
4019 // Spacing spinbox
4020 {
4021 GtkWidget *object_spacing = sp_tb_spinbutton(_("Spacing:"),
4022 _("The amount of space left around objects by auto-routing connectors"),
4023 "tools.connector", "spacing", 10, NULL, tbl, TRUE,
4024 "inkscape:connector-spacing", 0, 100, 1.0, 10.0,
4025 connector_spacing_changed, 1, 0);
4027 gtk_box_pack_start(GTK_BOX(tbl), object_spacing, FALSE, FALSE,
4028 AUX_SPACING);
4029 }
4030 // Graph (connector network) layout
4031 sp_toolbox_button_new(tbl, Inkscape::ICON_SIZE_SMALL_TOOLBAR,
4032 "graph_layout", GTK_SIGNAL_FUNC(sp_connector_graph_layout),
4033 tt, _("Nicely arrange selected connector network"));
4034 // Default connector length spinbox
4035 {
4036 GtkWidget *connector_length = sp_tb_spinbutton(_("Length:"),
4037 _("Ideal length for connectors when layout is applied"),
4038 "tools.connector", "length", 100, NULL, tbl, TRUE,
4039 "inkscape:connector-length", 10, 1000, 10.0, 100.0,
4040 connector_length_changed, 1, 0);
4042 gtk_box_pack_start(GTK_BOX(tbl), connector_length, FALSE, FALSE,
4043 AUX_SPACING);
4044 }
4045 gchar const *tbuttonstate;
4046 // Directed edges toggle button
4047 {
4048 GtkWidget *tbutton = gtk_toggle_button_new ();
4049 gtk_button_set_relief (GTK_BUTTON (tbutton), GTK_RELIEF_NONE);
4050 gtk_container_add (GTK_CONTAINER (tbutton), sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, "directed_graph"));
4051 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (tbutton), FALSE);
4052 gtk_tooltips_set_tip(tt, tbutton, _("Make connectors with end-markers (arrows) point downwards"), NULL);
4054 gtk_box_pack_start (GTK_BOX (tbl), tbutton, FALSE, FALSE, 0);
4055 g_signal_connect(G_OBJECT(tbutton), "toggled", GTK_SIGNAL_FUNC(sp_directed_graph_layout_toggled), tbl);
4056 tbuttonstate = prefs_get_string_attribute("tools.connector", "directedlayout");
4057 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(tbutton),
4058 (tbuttonstate && !strcmp(tbuttonstate, "true"))?TRUE:FALSE );
4059 }
4060 // Avoid overlaps toggle button
4061 {
4062 GtkWidget *tbutton = gtk_toggle_button_new ();
4063 gtk_button_set_relief (GTK_BUTTON (tbutton), GTK_RELIEF_NONE);
4064 gtk_container_add (GTK_CONTAINER (tbutton), sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, "remove_overlaps"));
4065 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (tbutton), FALSE);
4066 gtk_tooltips_set_tip(tt, tbutton, _("Do not allow overlapping shapes"), NULL);
4068 gtk_box_pack_start (GTK_BOX (tbl), tbutton, FALSE, FALSE, 0);
4069 g_signal_connect(G_OBJECT(tbutton), "toggled", GTK_SIGNAL_FUNC(sp_nooverlaps_graph_layout_toggled), tbl);
4070 tbuttonstate = prefs_get_string_attribute("tools.connector", "avoidoverlaplayout");
4071 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(tbutton),
4072 (tbuttonstate && !strcmp(tbuttonstate, "true"))?TRUE:FALSE );
4073 }
4075 gtk_widget_show_all(tbl);
4076 sp_set_font_size_smaller (tbl);
4078 // Code to watch for changes to the connector-spacing attribute in
4079 // the XML.
4080 Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
4081 g_assert(repr != NULL);
4083 Inkscape::XML::Node *oldrepr = (Inkscape::XML::Node *)
4084 gtk_object_get_data(GTK_OBJECT(tbl), "repr");
4086 if (oldrepr) { // remove old listener
4087 sp_repr_remove_listener_by_data(oldrepr, tbl);
4088 Inkscape::GC::release(oldrepr);
4089 oldrepr = NULL;
4090 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
4091 }
4093 if (repr) {
4094 g_object_set_data(G_OBJECT(tbl), "repr", repr);
4095 Inkscape::GC::anchor(repr);
4096 sp_repr_add_listener(repr, &connector_tb_repr_events, tbl);
4097 sp_repr_synthesize_events(repr, &connector_tb_repr_events, tbl);
4098 }
4100 return tbl;
4102 } // end of sp_connector_toolbox_new()
4105 /*
4106 Local Variables:
4107 mode:c++
4108 c-file-style:"stroustrup"
4109 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
4110 indent-tabs-mode:nil
4111 fill-column:99
4112 End:
4113 */
4114 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :