3941ce6f0bb1cd73249eb0f64c139b760e707c09
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"
78 #include "mod360.h"
80 #include "toolbox.h"
82 typedef void (*SetupFunction)(GtkWidget *toolbox, SPDesktop *desktop);
83 typedef void (*UpdateFunction)(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
85 static GtkWidget *sp_node_toolbox_new(SPDesktop *desktop);
86 static GtkWidget *sp_zoom_toolbox_new(SPDesktop *desktop);
87 static GtkWidget *sp_star_toolbox_new(SPDesktop *desktop);
88 static GtkWidget *sp_arc_toolbox_new(SPDesktop *desktop);
89 static GtkWidget *sp_rect_toolbox_new(SPDesktop *desktop);
90 static GtkWidget *sp_spiral_toolbox_new(SPDesktop *desktop);
91 static GtkWidget *sp_pencil_toolbox_new(SPDesktop *desktop);
92 static GtkWidget *sp_pen_toolbox_new(SPDesktop *desktop);
93 static GtkWidget *sp_calligraphy_toolbox_new(SPDesktop *desktop);
94 static GtkWidget *sp_dropper_toolbox_new(SPDesktop *desktop);
95 static GtkWidget *sp_empty_toolbox_new(SPDesktop *desktop);
96 static GtkWidget *sp_connector_toolbox_new(SPDesktop *desktop);
98 namespace { GtkWidget *sp_text_toolbox_new (SPDesktop *desktop); }
101 static struct {
102 gchar const *type_name;
103 gchar const *data_name;
104 sp_verb_t verb;
105 sp_verb_t doubleclick_verb;
106 } const tools[] = {
107 { "SPSelectContext", "select_tool", SP_VERB_CONTEXT_SELECT, SP_VERB_CONTEXT_SELECT_PREFS},
108 { "SPNodeContext", "node_tool", SP_VERB_CONTEXT_NODE, SP_VERB_CONTEXT_NODE_PREFS },
109 { "SPZoomContext", "zoom_tool", SP_VERB_CONTEXT_ZOOM, SP_VERB_CONTEXT_ZOOM_PREFS },
110 { "SPRectContext", "rect_tool", SP_VERB_CONTEXT_RECT, SP_VERB_CONTEXT_RECT_PREFS },
111 { "SPArcContext", "arc_tool", SP_VERB_CONTEXT_ARC, SP_VERB_CONTEXT_ARC_PREFS },
112 { "SPStarContext", "star_tool", SP_VERB_CONTEXT_STAR, SP_VERB_CONTEXT_STAR_PREFS },
113 { "SPSpiralContext", "spiral_tool", SP_VERB_CONTEXT_SPIRAL, SP_VERB_CONTEXT_SPIRAL_PREFS },
114 { "SPPencilContext", "pencil_tool", SP_VERB_CONTEXT_PENCIL, SP_VERB_CONTEXT_PENCIL_PREFS },
115 { "SPPenContext", "pen_tool", SP_VERB_CONTEXT_PEN, SP_VERB_CONTEXT_PEN_PREFS },
116 { "SPDynaDrawContext", "dyna_draw_tool", SP_VERB_CONTEXT_CALLIGRAPHIC, SP_VERB_CONTEXT_CALLIGRAPHIC_PREFS },
117 { "SPTextContext", "text_tool", SP_VERB_CONTEXT_TEXT, SP_VERB_CONTEXT_TEXT_PREFS },
118 { "SPConnectorContext","connector_tool", SP_VERB_CONTEXT_CONNECTOR, SP_VERB_CONTEXT_CONNECTOR_PREFS },
119 { "SPGradientContext", "gradient_tool", SP_VERB_CONTEXT_GRADIENT, SP_VERB_CONTEXT_GRADIENT_PREFS },
120 { "SPDropperContext", "dropper_tool", SP_VERB_CONTEXT_DROPPER, SP_VERB_CONTEXT_DROPPER_PREFS },
121 { NULL, NULL, 0, 0 }
122 };
124 static struct {
125 gchar const *type_name;
126 gchar const *data_name;
127 GtkWidget *(*create_func)(SPDesktop *desktop);
128 } const aux_toolboxes[] = {
129 { "SPSelectContext", "select_toolbox", sp_select_toolbox_new },
130 { "SPNodeContext", "node_toolbox", sp_node_toolbox_new },
131 { "SPZoomContext", "zoom_toolbox", sp_zoom_toolbox_new },
132 { "SPStarContext", "star_toolbox", sp_star_toolbox_new },
133 { "SPRectContext", "rect_toolbox", sp_rect_toolbox_new },
134 { "SPArcContext", "arc_toolbox", sp_arc_toolbox_new },
135 { "SPSpiralContext", "spiral_toolbox", sp_spiral_toolbox_new },
136 { "SPPencilContext", "pencil_toolbox", sp_pencil_toolbox_new },
137 { "SPPenContext", "pen_toolbox", sp_pen_toolbox_new },
138 { "SPDynaDrawContext", "calligraphy_toolbox", sp_calligraphy_toolbox_new },
139 { "SPTextContext", "text_toolbox", sp_text_toolbox_new },
140 { "SPDropperContext", "dropper_toolbox", sp_dropper_toolbox_new },
141 { "SPGradientContext", "gradient_toolbox", sp_gradient_toolbox_new },
142 { "SPConnectorContext", "connector_toolbox", sp_connector_toolbox_new },
143 { NULL, NULL, NULL }
144 };
146 static void toolbox_set_desktop (GtkWidget *toolbox, SPDesktop *desktop, SetupFunction setup_func, UpdateFunction update_func, sigc::connection*);
148 static void setup_tool_toolbox (GtkWidget *toolbox, SPDesktop *desktop);
149 static void update_tool_toolbox (SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
151 static void setup_aux_toolbox (GtkWidget *toolbox, SPDesktop *desktop);
152 static void update_aux_toolbox (SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
154 static void setup_commands_toolbox (GtkWidget *toolbox, SPDesktop *desktop);
155 static void update_commands_toolbox (SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
157 /* Global text entry widgets necessary for update */
158 /* GtkWidget *dropper_rgb_entry,
159 *dropper_opacity_entry ; */
160 // should be made a private member once this is converted to class
162 static void delete_connection(GObject *obj, sigc::connection *connection) {
163 connection->disconnect();
164 delete connection;
165 }
167 static GtkWidget *
168 sp_toolbox_button_new(GtkWidget *t, Inkscape::IconSize size, gchar const *pxname, GtkSignalFunc handler,
169 GtkTooltips *tt, gchar const *tip)
170 {
171 GtkWidget *b = sp_button_new_from_data(size, SP_BUTTON_TYPE_NORMAL, NULL, pxname, tip, tt);
172 gtk_widget_show(b);
173 if (handler) gtk_signal_connect(GTK_OBJECT(b), "clicked", handler, NULL);
174 gtk_box_pack_start(GTK_BOX(t), b, FALSE, FALSE, 0);
176 return b;
177 }
179 GtkWidget *
180 sp_toolbox_button_new_from_verb_with_doubleclick(GtkWidget *t, Inkscape::IconSize size, SPButtonType type,
181 Inkscape::Verb *verb, Inkscape::Verb *doubleclick_verb,
182 Inkscape::UI::View::View *view, GtkTooltips *tt)
183 {
184 SPAction *action = verb->get_action(view);
185 if (!action) return NULL;
187 SPAction *doubleclick_action;
188 if (doubleclick_verb)
189 doubleclick_action = doubleclick_verb->get_action(view);
190 else
191 doubleclick_action = NULL;
193 /* fixme: Handle sensitive/unsensitive */
194 /* fixme: Implement sp_button_new_from_action */
195 GtkWidget *b = sp_button_new(size, type, action, doubleclick_action, tt);
196 gtk_widget_show(b);
197 gtk_box_pack_start(GTK_BOX(t), b, FALSE, FALSE, 0);
199 return b;
200 }
202 GtkWidget *sp_toolbox_button_new_from_verb(GtkWidget *t, Inkscape::IconSize size, SPButtonType type, Inkscape::Verb *verb,
203 Inkscape::UI::View::View *view, GtkTooltips *tt)
204 {
205 return sp_toolbox_button_new_from_verb_with_doubleclick(t, size, type, verb, NULL, view, tt);
206 }
208 GtkWidget * sp_toolbox_button_normal_new_from_verb(GtkWidget *t, Inkscape::IconSize size, Inkscape::Verb *verb,
209 Inkscape::UI::View::View *view, GtkTooltips *tt)
210 {
211 return sp_toolbox_button_new_from_verb(t, size, SP_BUTTON_TYPE_NORMAL, verb, view, tt);
212 }
214 GtkWidget *
215 sp_tool_toolbox_new()
216 {
217 GtkTooltips *tt = gtk_tooltips_new();
218 GtkWidget *tb = gtk_vbox_new(FALSE, 0);
220 g_object_set_data(G_OBJECT(tb), "desktop", NULL);
221 g_object_set_data(G_OBJECT(tb), "tooltips", tt);
223 gtk_widget_set_sensitive(tb, FALSE);
225 GtkWidget *hb = gtk_handle_box_new();
226 gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), GTK_POS_TOP);
227 gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(hb), GTK_SHADOW_OUT);
228 gtk_handle_box_set_snap_edge(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
230 gtk_container_add(GTK_CONTAINER(hb), tb);
231 gtk_widget_show(GTK_WIDGET(tb));
233 sigc::connection* conn = new sigc::connection;
234 g_object_set_data(G_OBJECT(hb), "event_context_connection", conn);
236 return hb;
237 }
239 static void
240 aux_toolbox_attached(GtkHandleBox *toolbox, GtkWidget *child)
241 {
242 g_object_set_data(G_OBJECT(child), "is_detached", GINT_TO_POINTER(FALSE));
243 gtk_widget_queue_resize(child);
244 }
246 static void
247 aux_toolbox_detached(GtkHandleBox *toolbox, GtkWidget *child)
248 {
249 g_object_set_data(G_OBJECT(child), "is_detached", GINT_TO_POINTER(TRUE));
250 gtk_widget_queue_resize(child);
251 }
253 GtkWidget *
254 sp_aux_toolbox_new()
255 {
256 GtkWidget *tb = gtk_vbox_new(FALSE, 0);
258 GtkWidget *tb_s = gtk_vbox_new(FALSE, 0);
259 GtkWidget *tb_e = gtk_vbox_new(FALSE, 0);
260 gtk_box_set_spacing(GTK_BOX(tb), AUX_SPACING);
261 gtk_box_pack_start(GTK_BOX(tb), GTK_WIDGET(tb_s), FALSE, FALSE, 0);
262 gtk_box_pack_end(GTK_BOX(tb), GTK_WIDGET(tb_e), FALSE, FALSE, 0);
264 g_object_set_data(G_OBJECT(tb), "desktop", NULL);
265 g_object_set_data(G_OBJECT(tb), "top_spacer", tb_s);
267 gtk_widget_set_sensitive(tb, FALSE);
269 GtkWidget *hb = gtk_handle_box_new();
270 gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
271 gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(hb), GTK_SHADOW_OUT);
272 gtk_handle_box_set_snap_edge(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
274 g_signal_connect(G_OBJECT(hb), "child_attached", G_CALLBACK(aux_toolbox_attached), (gpointer)tb);
275 g_signal_connect(G_OBJECT(hb), "child_detached", G_CALLBACK(aux_toolbox_detached), (gpointer)tb);
277 gtk_container_add(GTK_CONTAINER(hb), tb);
278 gtk_widget_show(GTK_WIDGET(tb));
280 sigc::connection* conn = new sigc::connection;
281 g_object_set_data(G_OBJECT(hb), "event_context_connection", conn);
283 return hb;
284 }
286 //####################################
287 //# Commands Bar
288 //####################################
290 GtkWidget *
291 sp_commands_toolbox_new()
292 {
293 GtkWidget *tb = gtk_vbox_new(FALSE, 0);
295 GtkWidget *tb_s = gtk_vbox_new(FALSE, 0);
296 GtkWidget *tb_e = gtk_vbox_new(FALSE, 0);
297 gtk_box_set_spacing(GTK_BOX(tb), AUX_SPACING);
298 gtk_box_pack_start(GTK_BOX(tb), GTK_WIDGET(tb_s), FALSE, FALSE, 0);
299 gtk_box_pack_end(GTK_BOX(tb), GTK_WIDGET(tb_e), FALSE, FALSE, 0);
301 g_object_set_data(G_OBJECT(tb), "desktop", NULL);
302 gtk_widget_set_sensitive(tb, FALSE);
304 GtkWidget *hb = gtk_handle_box_new();
305 gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
306 gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(hb), GTK_SHADOW_OUT);
307 gtk_handle_box_set_snap_edge(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
309 g_signal_connect(G_OBJECT(hb), "child_attached", G_CALLBACK(aux_toolbox_attached), (gpointer)tb);
310 g_signal_connect(G_OBJECT(hb), "child_detached", G_CALLBACK(aux_toolbox_detached), (gpointer)tb);
312 gtk_container_add(GTK_CONTAINER(hb), tb);
313 gtk_widget_show(GTK_WIDGET(tb));
315 sigc::connection* conn = new sigc::connection;
316 g_object_set_data(G_OBJECT(hb), "event_context_connection", conn);
318 return hb;
319 }
322 //####################################
323 //# node editing callbacks
324 //####################################
326 void
327 sp_node_path_edit_add(void)
328 {
329 sp_node_selected_add_node();
330 }
332 void
333 sp_node_path_edit_delete(void)
334 {
335 sp_node_selected_delete();
336 }
338 void
339 sp_node_path_edit_delete_segment(void)
340 {
341 sp_node_selected_delete_segment();
342 }
344 void
345 sp_node_path_edit_break(void)
346 {
347 sp_node_selected_break();
348 }
350 void
351 sp_node_path_edit_join(void)
352 {
353 sp_node_selected_join();
354 }
356 void
357 sp_node_path_edit_join_segment(void)
358 {
359 sp_node_selected_join_segment();
360 }
362 void
363 sp_node_path_edit_toline(void)
364 {
365 sp_node_selected_set_line_type(NR_LINETO);
366 }
368 void
369 sp_node_path_edit_tocurve(void)
370 {
371 sp_node_selected_set_line_type(NR_CURVETO);
372 }
374 void
375 sp_node_path_edit_cusp(void)
376 {
377 sp_node_selected_set_type(Inkscape::NodePath::NODE_CUSP);
378 }
380 void
381 sp_node_path_edit_smooth(void)
382 {
383 sp_node_selected_set_type(Inkscape::NodePath::NODE_SMOOTH);
384 }
386 void
387 sp_node_path_edit_symmetrical(void)
388 {
389 sp_node_selected_set_type(Inkscape::NodePath::NODE_SYMM);
390 }
392 static void toggle_show_handles (GtkWidget *button, gpointer data) {
393 bool show = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
394 prefs_set_int_attribute ("tools.nodes", "show_handles", show ? 1 : 0);
395 sp_nodepath_show_handles(show);
396 }
398 //################################
399 //## Node Editing Toolbox ##
400 //################################
402 static GtkWidget *
403 sp_node_toolbox_new(SPDesktop *desktop)
404 {
405 Inkscape::UI::View::View *view = desktop;
407 GtkTooltips *tt = gtk_tooltips_new();
408 GtkWidget *tb = gtk_hbox_new(FALSE, 0);
410 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
412 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_insert",
413 GTK_SIGNAL_FUNC(sp_node_path_edit_add), tt, _("Insert new nodes into selected segments"));
414 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_delete",
415 GTK_SIGNAL_FUNC(sp_node_path_edit_delete), tt, _("Delete selected nodes"));
417 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
419 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_join",
420 GTK_SIGNAL_FUNC(sp_node_path_edit_join), tt, _("Join selected endnodes"));
421 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_join_segment",
422 GTK_SIGNAL_FUNC(sp_node_path_edit_join_segment), tt, _("Join selected endnodes with a new segment"));
424 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_delete_segment",
425 GTK_SIGNAL_FUNC(sp_node_path_edit_delete_segment), tt, _("Split path between two non-endpoint nodes"));
427 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_break",
428 GTK_SIGNAL_FUNC(sp_node_path_edit_break), tt, _("Break path at selected nodes"));
430 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
432 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_cusp",
433 GTK_SIGNAL_FUNC(sp_node_path_edit_cusp), tt, _("Make selected nodes corner"));
435 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_smooth",
436 GTK_SIGNAL_FUNC(sp_node_path_edit_smooth), tt, _("Make selected nodes smooth"));
438 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_symmetric",
439 GTK_SIGNAL_FUNC(sp_node_path_edit_symmetrical), tt, _("Make selected nodes symmetric"));
441 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
443 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_line",
444 GTK_SIGNAL_FUNC(sp_node_path_edit_toline), tt, _("Make selected segments lines"));
446 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_curve",
447 GTK_SIGNAL_FUNC(sp_node_path_edit_tocurve), tt, _("Make selected segments curves"));
449 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
451 sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_OBJECT_TO_CURVE), view, tt);
453 sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_SELECTION_OUTLINE), view, tt);
455 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
457 GtkWidget *cvbox = gtk_vbox_new (FALSE, 0);
458 GtkWidget *cbox = gtk_hbox_new (FALSE, 0);
460 {
461 GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
462 SP_BUTTON_TYPE_TOGGLE,
463 NULL,
464 "nodes_show_handles",
465 _("Show the Bezier handles of selected nodes"),
466 tt);
467 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.nodes", "show_handles", 1));
468 g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (toggle_show_handles), desktop);
469 gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
470 }
472 gtk_box_pack_start(GTK_BOX(cvbox), cbox, TRUE, FALSE, 0);
473 gtk_box_pack_start(GTK_BOX(tb), cvbox, FALSE, FALSE, 0);
475 gtk_widget_show_all(tb);
477 return tb;
479 } // end of sp_node_toolbox_new()
482 //########################
483 //## Zoom Toolbox ##
484 //########################
486 static GtkWidget *
487 sp_zoom_toolbox_new(SPDesktop *desktop)
488 {
489 Inkscape::UI::View::View *view=desktop;
491 GtkTooltips *tt = gtk_tooltips_new();
492 GtkWidget *tb = gtk_hbox_new(FALSE, 0);
494 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0),
495 FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
497 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);
499 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);
501 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
503 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);
505 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);
507 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);
509 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);
511 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
513 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);
515 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);
517 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
519 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);
521 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);
523 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);
525 gtk_widget_show_all(tb);
527 return tb;
529 } // end of sp_zoom_toolbox_new()
531 void
532 sp_tool_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
533 {
534 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")));
535 }
538 void
539 sp_aux_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
540 {
541 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")));
542 }
544 void
545 sp_commands_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
546 {
547 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")));
548 }
550 static void
551 toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop, SetupFunction setup_func, UpdateFunction update_func, sigc::connection *conn)
552 {
553 gpointer ptr = g_object_get_data(G_OBJECT(toolbox), "desktop");
554 SPDesktop *old_desktop = static_cast<SPDesktop*>(ptr);
556 if (old_desktop) {
557 GList *children, *iter;
559 children = gtk_container_get_children(GTK_CONTAINER(toolbox));
560 for ( iter = children ; iter ; iter = iter->next ) {
561 gtk_container_remove( GTK_CONTAINER(toolbox), GTK_WIDGET(iter->data) );
562 }
563 g_list_free(children);
564 }
566 g_object_set_data(G_OBJECT(toolbox), "desktop", (gpointer)desktop);
568 if (desktop) {
569 gtk_widget_set_sensitive(toolbox, TRUE);
570 setup_func(toolbox, desktop);
571 update_func(desktop, desktop->event_context, toolbox);
572 *conn = desktop->connectEventContextChanged
573 (sigc::bind (sigc::ptr_fun(update_func), toolbox));
574 } else {
575 gtk_widget_set_sensitive(toolbox, FALSE);
576 }
578 } // end of toolbox_set_desktop()
581 static void
582 setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
583 {
584 GtkTooltips *tooltips=GTK_TOOLTIPS(g_object_get_data(G_OBJECT(toolbox), "tooltips"));
585 gint shrinkLeft = prefs_get_int_attribute_limited( "toolbox.left", "small", 0, 0, 1 );
586 Inkscape::IconSize toolboxSize = shrinkLeft ? Inkscape::ICON_SIZE_SMALL_TOOLBAR : Inkscape::ICON_SIZE_LARGE_TOOLBAR;
588 for (int i = 0 ; tools[i].type_name ; i++ ) {
589 GtkWidget *button =
590 sp_toolbox_button_new_from_verb_with_doubleclick( toolbox, toolboxSize,
591 SP_BUTTON_TYPE_TOGGLE,
592 Inkscape::Verb::get(tools[i].verb),
593 Inkscape::Verb::get(tools[i].doubleclick_verb),
594 desktop,
595 tooltips );
597 g_object_set_data( G_OBJECT(toolbox), tools[i].data_name,
598 (gpointer)button );
599 }
600 }
603 static void
604 update_tool_toolbox( SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox )
605 {
606 gchar const *const tname = ( eventcontext
607 ? gtk_type_name(GTK_OBJECT_TYPE(eventcontext))
608 : NULL );
609 for (int i = 0 ; tools[i].type_name ; i++ ) {
610 SPButton *button = SP_BUTTON(g_object_get_data(G_OBJECT(toolbox), tools[i].data_name));
611 sp_button_toggle_set_down(button, tname && !strcmp(tname, tools[i].type_name));
612 }
613 }
615 static void
616 setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
617 {
618 GtkSizeGroup* grouper = gtk_size_group_new( GTK_SIZE_GROUP_BOTH );
620 for (int i = 0 ; aux_toolboxes[i].type_name ; i++ ) {
621 GtkWidget *sub_toolbox;
622 if (aux_toolboxes[i].create_func == NULL)
623 sub_toolbox = sp_empty_toolbox_new(desktop);
624 else
625 sub_toolbox = aux_toolboxes[i].create_func(desktop);
627 gtk_size_group_add_widget( grouper, sub_toolbox );
629 gtk_container_add(GTK_CONTAINER(toolbox), sub_toolbox);
630 g_object_set_data(G_OBJECT(toolbox), aux_toolboxes[i].data_name, sub_toolbox);
631 }
632 g_object_unref( G_OBJECT(grouper) );
633 }
635 static void
636 update_aux_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox)
637 {
638 gchar const *tname = ( eventcontext
639 ? gtk_type_name(GTK_OBJECT_TYPE(eventcontext))
640 : NULL );
641 for (int i = 0 ; aux_toolboxes[i].type_name ; i++ ) {
642 GtkWidget *sub_toolbox = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), aux_toolboxes[i].data_name));
643 if (tname && !strcmp(tname, aux_toolboxes[i].type_name)) {
644 gtk_widget_show_all(sub_toolbox);
645 g_object_set_data(G_OBJECT(toolbox), "shows", sub_toolbox);
646 } else {
647 gtk_widget_hide(sub_toolbox);
648 }
649 }
650 }
652 static void
653 setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
654 {
655 Inkscape::UI::View::View *view = desktop;
657 GtkTooltips *tt = gtk_tooltips_new();
658 GtkWidget *tb = gtk_hbox_new(FALSE, 0);
660 gint shrinkTop = prefs_get_int_attribute_limited( "toolbox", "small", 1, 0, 1 );
661 Inkscape::IconSize toolboxSize = shrinkTop ? Inkscape::ICON_SIZE_SMALL_TOOLBAR : Inkscape::ICON_SIZE_LARGE_TOOLBAR;
663 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_NEW), view, tt);
664 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_OPEN), view, tt);
665 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_SAVE), view, tt);
666 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_PRINT), view, tt);
668 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
670 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_IMPORT), view, tt);
671 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_FILE_EXPORT), view, tt);
673 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
675 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_UNDO), view, tt);
676 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_REDO), view, tt);
678 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
680 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_COPY), view, tt);
681 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_CUT), view, tt);
682 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_PASTE), view, tt);
684 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
686 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_SELECTION), view, tt);
687 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_DRAWING), view, tt);
688 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_ZOOM_PAGE), view, tt);
690 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
692 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_DUPLICATE), view, tt);
693 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_CLONE), view, tt);
694 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_UNLINK_CLONE), view, tt);
696 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
698 sp_toolbox_button_normal_new_from_verb(tb, toolboxSize, Inkscape::Verb::get(SP_VERB_SELECTION_GROUP), view, tt);
699 sp_toolbox_button_normal_new_from_verb(tb, toolboxSize, Inkscape::Verb::get(SP_VERB_SELECTION_UNGROUP), view, tt);
701 // disabled until we have icons for them:
703 //find
705 //sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_TILE), view, tt);
706 //sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_EDIT_UNTILE), view, tt);
708 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
710 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_FILL_STROKE), view, tt);
711 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_TEXT), view, tt);
712 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_XML_EDITOR), view, tt);
713 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_ALIGN_DISTRIBUTE), view, tt);
715 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
717 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_DISPLAY), view, tt);
718 sp_toolbox_button_new_from_verb(tb, toolboxSize, SP_BUTTON_TYPE_NORMAL, Inkscape::Verb::get(SP_VERB_DIALOG_NAMEDVIEW), view, tt);
720 gtk_widget_show_all(tb);
722 gtk_container_add(GTK_CONTAINER(toolbox), tb);
723 }
725 static void
726 update_commands_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox)
727 {
728 }
730 void show_aux_toolbox(GtkWidget *toolbox_toplevel)
731 {
732 gtk_widget_show(toolbox_toplevel);
733 GtkWidget *toolbox = gtk_bin_get_child(GTK_BIN(toolbox_toplevel));
735 GtkWidget *shown_toolbox = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), "shows"));
736 if (!shown_toolbox) {
737 return;
738 }
739 gtk_widget_show(toolbox);
741 // need to show the spacer, or the padding will be off
742 GtkWidget *spacer = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), "top_spacer"));
743 gtk_widget_show(spacer);
745 gtk_widget_show_all(shown_toolbox);
746 }
748 void
749 aux_toolbox_space(GtkWidget *tb, gint space)
750 {
751 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, space);
752 }
754 static GtkWidget *
755 sp_empty_toolbox_new(SPDesktop *desktop)
756 {
757 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
758 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
759 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
761 gtk_widget_show_all(tbl);
762 sp_set_font_size_smaller (tbl);
764 return tbl;
765 }
767 // helper UI functions
769 GtkWidget *
770 sp_tb_spinbutton(
771 gchar *label, gchar const *tooltip,
772 gchar const *path, gchar const *data, gdouble def,
773 GtkWidget *us,
774 GtkWidget *tbl,
775 gboolean altx, gchar const *altx_mark,
776 gdouble lower, gdouble upper, gdouble step, gdouble page,
777 void (*callback)(GtkAdjustment *, GtkWidget *),
778 gdouble climb = 0.1, guint digits = 3, double factor = 1.0)
779 {
780 GtkTooltips *tt = gtk_tooltips_new();
782 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
784 GtkWidget *l = gtk_label_new(label);
785 gtk_widget_show(l);
786 gtk_misc_set_alignment(GTK_MISC(l), 1.0, 0.5);
787 gtk_container_add(GTK_CONTAINER(hb), l);
789 GtkObject *a = gtk_adjustment_new(prefs_get_double_attribute(path, data, def) * factor,
790 lower, upper, step, page, page);
791 gtk_object_set_data(GTK_OBJECT(tbl), data, a);
792 if (us)
793 sp_unit_selector_add_adjustment(SP_UNIT_SELECTOR(us), GTK_ADJUSTMENT(a));
795 GtkWidget *sb = gtk_spin_button_new(GTK_ADJUSTMENT(a), climb, digits);
796 gtk_tooltips_set_tip(tt, sb, tooltip, NULL);
797 if (altx)
798 gtk_object_set_data(GTK_OBJECT(sb), altx_mark, sb);
799 gtk_widget_set_size_request(sb,
800 (upper <= 1.0 || digits == 0)? AUX_SPINBUTTON_WIDTH_SMALL - 10: AUX_SPINBUTTON_WIDTH_SMALL,
801 AUX_SPINBUTTON_HEIGHT);
802 gtk_widget_show(sb);
803 gtk_signal_connect(GTK_OBJECT(sb), "focus-in-event", GTK_SIGNAL_FUNC(spinbutton_focus_in), tbl);
804 gtk_signal_connect(GTK_OBJECT(sb), "key-press-event", GTK_SIGNAL_FUNC(spinbutton_keypress), tbl);
805 gtk_container_add(GTK_CONTAINER(hb), sb);
806 gtk_signal_connect(GTK_OBJECT(a), "value_changed", GTK_SIGNAL_FUNC(callback), tbl);
808 return hb;
809 }
811 #define MODE_LABEL_WIDTH 70
813 //########################
814 //## Star ##
815 //########################
817 static void
818 sp_stb_magnitude_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
819 {
820 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
822 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
823 // do not remember prefs if this call is initiated by an undo change, because undoing object
824 // creation sets bogus values to its attributes before it is deleted
825 prefs_set_int_attribute("tools.shapes.star", "magnitude", (gint)adj->value);
826 }
828 // quit if run by the attr_changed listener
829 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
830 return;
831 }
833 // in turn, prevent listener from responding
834 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
836 bool modmade = false;
838 Inkscape::Selection *selection = sp_desktop_selection(desktop);
839 GSList const *items = selection->itemList();
840 for (; items != NULL; items = items->next) {
841 if (SP_IS_STAR((SPItem *) items->data)) {
842 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
843 sp_repr_set_int(repr,"sodipodi:sides",(gint)adj->value);
844 sp_repr_set_svg_double(repr, "sodipodi:arg2",
845 (sp_repr_get_double_attribute(repr, "sodipodi:arg1", 0.5)
846 + M_PI / (gint)adj->value));
847 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
848 modmade = true;
849 }
850 }
851 if (modmade) sp_document_done(sp_desktop_document(desktop));
853 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
855 spinbutton_defocus(GTK_OBJECT(tbl));
856 }
858 static void
859 sp_stb_proportion_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
860 {
861 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
863 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
864 prefs_set_double_attribute("tools.shapes.star", "proportion", adj->value);
865 }
867 // quit if run by the attr_changed listener
868 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
869 return;
870 }
872 // in turn, prevent listener from responding
873 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
875 bool modmade = false;
876 Inkscape::Selection *selection = sp_desktop_selection(desktop);
877 GSList const *items = selection->itemList();
878 for (; items != NULL; items = items->next) {
879 if (SP_IS_STAR((SPItem *) items->data)) {
880 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
882 gdouble r1 = sp_repr_get_double_attribute(repr, "sodipodi:r1", 1.0);
883 gdouble r2 = sp_repr_get_double_attribute(repr, "sodipodi:r2", 1.0);
884 if (r2 < r1) {
885 sp_repr_set_svg_double(repr, "sodipodi:r2", r1*adj->value);
886 } else {
887 sp_repr_set_svg_double(repr, "sodipodi:r1", r2*adj->value);
888 }
890 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
891 modmade = true;
892 }
893 }
895 if (modmade) sp_document_done(sp_desktop_document(desktop));
897 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
899 spinbutton_defocus(GTK_OBJECT(tbl));
900 }
902 static void
903 sp_stb_sides_flat_state_changed(GtkWidget *widget, GtkObject *tbl)
904 {
905 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
907 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
908 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
909 prefs_set_string_attribute("tools.shapes.star", "isflatsided", "true");
910 } else {
911 prefs_set_string_attribute("tools.shapes.star", "isflatsided", "false");
912 }
913 }
915 // quit if run by the attr_changed listener
916 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
917 return;
918 }
920 // in turn, prevent listener from responding
921 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
923 Inkscape::Selection *selection = sp_desktop_selection(desktop);
924 GSList const *items = selection->itemList();
925 GtkWidget *prop_widget = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "prop_widget");
926 bool modmade = false;
927 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
928 gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), FALSE);
929 for (; items != NULL; items = items->next) {
930 if (SP_IS_STAR((SPItem *) items->data)) {
931 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
932 repr->setAttribute("inkscape:flatsided", "true");
933 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
934 modmade = true;
935 }
936 }
937 } else {
938 gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), TRUE);
939 for (; items != NULL; items = items->next) {
940 if (SP_IS_STAR((SPItem *) items->data)) {
941 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
942 repr->setAttribute("inkscape:flatsided", "false");
943 SP_OBJECT(items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
944 modmade = true;
945 }
946 }
947 }
948 if (modmade) sp_document_done(sp_desktop_document(desktop));
950 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
952 spinbutton_defocus(GTK_OBJECT(tbl));
953 }
955 static void
956 sp_stb_rounded_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
957 {
958 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
960 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
961 prefs_set_double_attribute("tools.shapes.star", "rounded", (gdouble) adj->value);
962 }
964 // quit if run by the attr_changed listener
965 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
966 return;
967 }
969 // in turn, prevent listener from responding
970 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
972 bool modmade = false;
974 Inkscape::Selection *selection = sp_desktop_selection(desktop);
975 GSList const *items = selection->itemList();
976 for (; items != NULL; items = items->next) {
977 if (SP_IS_STAR((SPItem *) items->data)) {
978 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
979 sp_repr_set_svg_double(repr, "inkscape:rounded", (gdouble) adj->value);
980 SP_OBJECT(items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
981 modmade = true;
982 }
983 }
984 if (modmade) sp_document_done(sp_desktop_document(desktop));
986 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
988 spinbutton_defocus(GTK_OBJECT(tbl));
989 }
992 static void
993 sp_stb_randomized_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
994 {
995 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
997 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
998 prefs_set_double_attribute("tools.shapes.star", "randomized", (gdouble) adj->value);
999 }
1001 // quit if run by the attr_changed listener
1002 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1003 return;
1004 }
1006 // in turn, prevent listener from responding
1007 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1009 bool modmade = false;
1011 Inkscape::Selection *selection = sp_desktop_selection(desktop);
1012 GSList const *items = selection->itemList();
1013 for (; items != NULL; items = items->next) {
1014 if (SP_IS_STAR((SPItem *) items->data)) {
1015 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
1016 sp_repr_set_svg_double(repr, "inkscape:randomized", (gdouble) adj->value);
1017 SP_OBJECT(items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
1018 modmade = true;
1019 }
1020 }
1021 if (modmade) sp_document_done(sp_desktop_document(desktop));
1023 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1025 spinbutton_defocus(GTK_OBJECT(tbl));
1026 }
1029 static void star_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1030 gchar const *old_value, gchar const *new_value,
1031 bool is_interactive, gpointer data)
1032 {
1033 GtkWidget *tbl = GTK_WIDGET(data);
1035 // quit if run by the _changed callbacks
1036 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1037 return;
1038 }
1040 // in turn, prevent callbacks from responding
1041 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1043 GtkAdjustment *adj;
1045 if (!strcmp(name, "inkscape:randomized")) {
1046 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "randomized");
1047 gtk_adjustment_set_value(adj, sp_repr_get_double_attribute(repr, "inkscape:randomized", 0.0));
1048 } else if (!strcmp(name, "inkscape:rounded")) {
1049 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rounded");
1050 gtk_adjustment_set_value(adj, sp_repr_get_double_attribute(repr, "inkscape:rounded", 0.0));
1051 } else if (!strcmp(name, "inkscape:flatsided")) {
1052 GtkWidget *fscb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "flat_checkbox");
1053 GtkWidget *prop_widget = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "prop_widget");
1054 char const *flatsides = repr->attribute("inkscape:flatsided");
1055 if (flatsides && !strcmp(flatsides,"false" )) {
1056 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), FALSE);
1057 gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), TRUE);
1058 } else {
1059 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), TRUE);
1060 gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), FALSE);
1061 }
1062 } else if (!strcmp(name, "sodipodi:r1") || !strcmp(name, "sodipodi:r2")) {
1063 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "proportion");
1064 gdouble r1 = sp_repr_get_double_attribute(repr, "sodipodi:r1", 1.0);
1065 gdouble r2 = sp_repr_get_double_attribute(repr, "sodipodi:r2", 1.0);
1066 if (r2 < r1) {
1067 gtk_adjustment_set_value(adj, r2/r1);
1068 } else {
1069 gtk_adjustment_set_value(adj, r1/r2);
1070 }
1071 } else if (!strcmp(name, "sodipodi:sides")) {
1072 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "magnitude");
1073 gtk_adjustment_set_value(adj, sp_repr_get_int_attribute(repr, "sodipodi:sides", 0));
1074 }
1076 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1077 }
1080 static Inkscape::XML::NodeEventVector star_tb_repr_events =
1081 {
1082 NULL, /* child_added */
1083 NULL, /* child_removed */
1084 star_tb_event_attr_changed,
1085 NULL, /* content_changed */
1086 NULL /* order_changed */
1087 };
1090 /**
1091 * \param selection Should not be NULL.
1092 */
1093 static void
1094 sp_star_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1095 {
1096 int n_selected = 0;
1097 Inkscape::XML::Node *repr = NULL;
1098 Inkscape::XML::Node *oldrepr = NULL;
1100 for (GSList const *items = selection->itemList();
1101 items != NULL;
1102 items = items->next)
1103 {
1104 if (SP_IS_STAR((SPItem *) items->data)) {
1105 n_selected++;
1106 repr = SP_OBJECT_REPR((SPItem *) items->data);
1107 }
1108 }
1110 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
1112 if (n_selected == 0) {
1113 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
1114 } else if (n_selected == 1) {
1115 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1117 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1118 if (oldrepr) { // remove old listener
1119 sp_repr_remove_listener_by_data(oldrepr, tbl);
1120 Inkscape::GC::release(oldrepr);
1121 oldrepr = 0;
1122 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1123 }
1125 if (repr) {
1126 g_object_set_data(G_OBJECT(tbl), "repr", repr);
1127 Inkscape::GC::anchor(repr);
1128 sp_repr_add_listener(repr, &star_tb_repr_events, tbl);
1129 sp_repr_synthesize_events(repr, &star_tb_repr_events, tbl);
1130 }
1131 } else {
1132 // FIXME: implement averaging of all parameters for multiple selected stars
1133 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1134 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1135 }
1136 }
1139 static void
1140 sp_stb_defaults(GtkWidget *widget, GtkWidget *tbl)
1141 {
1142 // FIXME: in this and all other _default functions, set some flag telling the value_changed
1143 // callbacks to lump all the changes for all selected objects in one undo step
1145 GtkAdjustment *adj;
1147 // fixme: make settable in prefs!
1148 gint mag = 5;
1149 gdouble prop = 0.5;
1150 gboolean flat = FALSE;
1151 gdouble randomized = 0;
1152 gdouble rounded = 0;
1154 GtkWidget *fscb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "flat_checkbox");
1155 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), flat);
1156 GtkWidget *sb2 = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "prop_widget");
1157 gtk_widget_set_sensitive(GTK_WIDGET(sb2), !flat);
1159 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "magnitude");
1160 gtk_adjustment_set_value(adj, mag);
1161 gtk_adjustment_value_changed(adj);
1163 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "proportion");
1164 gtk_adjustment_set_value(adj, prop);
1165 gtk_adjustment_value_changed(adj);
1167 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rounded");
1168 gtk_adjustment_set_value(adj, rounded);
1169 gtk_adjustment_value_changed(adj);
1171 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "randomized");
1172 gtk_adjustment_set_value(adj, randomized);
1173 gtk_adjustment_value_changed(adj);
1175 spinbutton_defocus(GTK_OBJECT(tbl));
1176 }
1179 void
1180 sp_toolbox_add_label(GtkWidget *tbl, gchar const *title, bool wide)
1181 {
1182 GtkWidget *boxl = gtk_hbox_new(FALSE, 0);
1183 if (wide) gtk_widget_set_size_request(boxl, MODE_LABEL_WIDTH, -1);
1184 GtkWidget *l = gtk_label_new(NULL);
1185 gtk_label_set_markup(GTK_LABEL(l), title);
1186 gtk_box_pack_end(GTK_BOX(boxl), l, FALSE, FALSE, 0);
1187 gtk_box_pack_start(GTK_BOX(tbl), boxl, FALSE, FALSE, 0);
1188 gtk_object_set_data(GTK_OBJECT(tbl), "mode_label", l);
1189 }
1192 static GtkWidget *
1193 sp_star_toolbox_new(SPDesktop *desktop)
1194 {
1195 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1197 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1198 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1200 GtkTooltips *tt = gtk_tooltips_new();
1202 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1204 gchar const *flatsidedstr = NULL;
1206 /* Flatsided checkbox */
1207 {
1208 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1209 GtkWidget *fscb = gtk_check_button_new_with_label(_("Polygon"));
1210 gtk_widget_set_sensitive(GTK_WIDGET(fscb), TRUE);
1211 flatsidedstr = prefs_get_string_attribute("tools.shapes.star", "isflatsided");
1212 if (!flatsidedstr || (flatsidedstr && !strcmp(flatsidedstr, "false")))
1213 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), FALSE);
1214 else
1215 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), TRUE);
1216 gtk_tooltips_set_tip(tt, fscb, _("Regular polygon (with one handle) instead of a star"), NULL);
1217 gtk_widget_show(fscb);
1218 gtk_object_set_data(GTK_OBJECT(tbl), "flat_checkbox", fscb);
1219 gtk_container_add(GTK_CONTAINER(hb), fscb);
1220 g_signal_connect(G_OBJECT(fscb), "toggled", GTK_SIGNAL_FUNC(sp_stb_sides_flat_state_changed ), tbl);
1221 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_SPACING);
1222 }
1224 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
1226 /* Magnitude */
1227 {
1228 GtkWidget *hb = sp_tb_spinbutton(_("Corners:"), _("Number of corners of a polygon or star"),
1229 "tools.shapes.star", "magnitude", 3,
1230 NULL, tbl, TRUE, "altx-star",
1231 3, 1024, 1, 1,
1232 sp_stb_magnitude_value_changed, 1, 0);
1233 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1234 }
1236 /* Spoke ratio */
1237 {
1238 GtkWidget *hb = sp_tb_spinbutton(_("Spoke ratio:"),
1239 // TRANSLATORS: Tip radius of a star is the distance from the center to the farthest handle.
1240 // Base radius is the same for the closest handle.
1241 _("Base radius to tip radius ratio"),
1242 "tools.shapes.star", "proportion", 0.5,
1243 NULL, tbl, FALSE, NULL,
1244 0.01, 1.0, 0.01, 0.1,
1245 sp_stb_proportion_value_changed);
1246 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1247 g_object_set_data(G_OBJECT(tbl), "prop_widget", hb);
1248 if (!flatsidedstr || (flatsidedstr && !strcmp(flatsidedstr, "false")))
1249 gtk_widget_set_sensitive(GTK_WIDGET(hb), TRUE);
1250 else
1251 gtk_widget_set_sensitive(GTK_WIDGET(hb), FALSE);
1252 }
1254 /* Roundedness */
1255 {
1256 GtkWidget *hb = sp_tb_spinbutton(_("Rounded:"), _("How much rounded are the corners (0 for sharp)"),
1257 "tools.shapes.star", "rounded", 0.0,
1258 NULL, tbl, FALSE, NULL,
1259 -100.0, 100.0, 0.01, 0.1,
1260 sp_stb_rounded_value_changed);
1261 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1262 }
1264 /* Randomization */
1265 {
1266 GtkWidget *hb = sp_tb_spinbutton(_("Randomized:"), _("Scatter randomly the corners and angles"),
1267 "tools.shapes.star", "randomized", 0.0,
1268 NULL, tbl, FALSE, NULL,
1269 -10.0, 10.0, 0.001, 0.01,
1270 sp_stb_randomized_value_changed, 0.1, 3);
1271 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1272 }
1274 aux_toolbox_space(tbl, AUX_SPACING);
1276 /* Reset */
1277 {
1278 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1279 GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
1280 gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
1281 gtk_widget_show(b);
1282 gtk_container_add(GTK_CONTAINER(hb), b);
1283 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_stb_defaults), tbl);
1284 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_SPACING);
1285 }
1287 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1288 swatch->setWatchedTool ("tools.shapes.star", true);
1289 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1290 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1292 gtk_widget_show_all(tbl);
1293 sp_set_font_size_smaller (tbl);
1295 sigc::connection *connection = new sigc::connection(
1296 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_star_toolbox_selection_changed), (GtkObject *)tbl))
1297 );
1298 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1300 return tbl;
1301 }
1304 //########################
1305 //## Rect ##
1306 //########################
1308 static void
1309 sp_rtb_sensitivize (GtkWidget *tbl)
1310 {
1311 GtkAdjustment *adj1 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "rx"));
1312 GtkAdjustment *adj2 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "ry"));
1313 GtkWidget *not_rounded = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "not_rounded");
1315 if (adj1->value == 0 && adj2->value == 0 && gtk_object_get_data(GTK_OBJECT(tbl), "single")) { // only for a single selected rect (for now)
1316 gtk_widget_set_sensitive(GTK_WIDGET(not_rounded), FALSE);
1317 } else {
1318 gtk_widget_set_sensitive(GTK_WIDGET(not_rounded), TRUE);
1319 }
1320 }
1323 static void
1324 sp_rtb_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name,
1325 void (*setter)(SPRect *, gdouble))
1326 {
1327 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
1329 GtkWidget *us = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tbl), "units");
1330 SPUnit const *unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(us));
1332 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1333 prefs_set_double_attribute("tools.shapes.rect", value_name, sp_units_get_pixels(adj->value, *unit));
1334 }
1336 // quit if run by the attr_changed listener
1337 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1338 return;
1339 }
1341 // in turn, prevent listener from responding
1342 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1344 bool modmade = false;
1345 Inkscape::Selection *selection = sp_desktop_selection(desktop);
1346 for (GSList const *items = selection->itemList(); items != NULL; items = items->next) {
1347 if (SP_IS_RECT(items->data)) {
1348 if (adj->value != 0) {
1349 setter(SP_RECT(items->data), sp_units_get_pixels(adj->value, *unit));
1350 } else {
1351 SP_OBJECT_REPR(items->data)->setAttribute(value_name, NULL);
1352 }
1353 modmade = true;
1354 }
1355 }
1357 sp_rtb_sensitivize (tbl);
1359 if (modmade) {
1360 sp_document_done(sp_desktop_document(desktop));
1361 }
1363 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1365 // defocus spinbuttons by moving focus to the canvas, unless "stay" is on
1366 spinbutton_defocus(GTK_OBJECT(tbl));
1367 }
1369 static void
1370 sp_rtb_rx_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1371 {
1372 sp_rtb_value_changed(adj, tbl, "rx", sp_rect_set_visible_rx);
1373 }
1375 static void
1376 sp_rtb_ry_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1377 {
1378 sp_rtb_value_changed(adj, tbl, "ry", sp_rect_set_visible_ry);
1379 }
1381 static void
1382 sp_rtb_width_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1383 {
1384 sp_rtb_value_changed(adj, tbl, "width", sp_rect_set_visible_width);
1385 }
1387 static void
1388 sp_rtb_height_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1389 {
1390 sp_rtb_value_changed(adj, tbl, "height", sp_rect_set_visible_height);
1391 }
1395 static void
1396 sp_rtb_defaults( GtkWidget *widget, GtkObject *obj)
1397 {
1398 GtkWidget *tbl = GTK_WIDGET(obj);
1400 GtkAdjustment *adj;
1402 adj = (GtkAdjustment*)gtk_object_get_data(obj, "rx");
1403 gtk_adjustment_set_value(adj, 0.0);
1404 // this is necessary if the previous value was 0, but we still need to run the callback to change all selected objects
1405 gtk_adjustment_value_changed(adj);
1407 adj = (GtkAdjustment*)gtk_object_get_data(obj, "ry");
1408 gtk_adjustment_set_value(adj, 0.0);
1409 gtk_adjustment_value_changed(adj);
1411 sp_rtb_sensitivize (tbl);
1413 spinbutton_defocus(GTK_OBJECT(tbl));
1414 }
1416 static void rect_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1417 gchar const *old_value, gchar const *new_value,
1418 bool is_interactive, gpointer data)
1419 {
1420 GtkWidget *tbl = GTK_WIDGET(data);
1422 // quit if run by the _changed callbacks
1423 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1424 return;
1425 }
1427 // in turn, prevent callbacks from responding
1428 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1430 GtkWidget *us = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tbl), "units");
1431 SPUnit const *unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(us));
1433 SPItem *item = SP_ITEM(g_object_get_data(G_OBJECT(tbl), "item"));
1434 if (SP_IS_RECT(item)) {
1435 {
1436 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rx");
1437 gdouble rx = sp_rect_get_visible_rx(SP_RECT(item));
1438 gtk_adjustment_set_value(adj, sp_pixels_get_units(rx, *unit));
1439 }
1441 {
1442 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "ry");
1443 gdouble ry = sp_rect_get_visible_ry(SP_RECT(item));
1444 gtk_adjustment_set_value(adj, sp_pixels_get_units(ry, *unit));
1445 }
1447 {
1448 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "width");
1449 gdouble width = sp_rect_get_visible_width (SP_RECT(item));
1450 gtk_adjustment_set_value(adj, sp_pixels_get_units(width, *unit));
1451 }
1453 {
1454 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "height");
1455 gdouble height = sp_rect_get_visible_height (SP_RECT(item));
1456 gtk_adjustment_set_value(adj, sp_pixels_get_units(height, *unit));
1457 }
1458 }
1460 sp_rtb_sensitivize (tbl);
1462 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1463 }
1466 static Inkscape::XML::NodeEventVector rect_tb_repr_events = {
1467 NULL, /* child_added */
1468 NULL, /* child_removed */
1469 rect_tb_event_attr_changed,
1470 NULL, /* content_changed */
1471 NULL /* order_changed */
1472 };
1474 /**
1475 * \param selection should not be NULL.
1476 */
1477 static void
1478 sp_rect_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1479 {
1480 int n_selected = 0;
1481 Inkscape::XML::Node *repr = NULL;
1482 SPItem *item = NULL;
1483 Inkscape::XML::Node *oldrepr = NULL;
1485 for (GSList const *items = selection->itemList();
1486 items != NULL;
1487 items = items->next) {
1488 if (SP_IS_RECT((SPItem *) items->data)) {
1489 n_selected++;
1490 item = (SPItem *) items->data;
1491 repr = SP_OBJECT_REPR(item);
1492 }
1493 }
1495 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
1497 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(FALSE));
1499 if (n_selected == 0) {
1500 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
1502 GtkWidget *w = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "width_sb");
1503 gtk_widget_set_sensitive(w, FALSE);
1504 GtkWidget *h = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "height_sb");
1505 gtk_widget_set_sensitive(h, FALSE);
1507 } else if (n_selected == 1) {
1508 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1509 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
1511 GtkWidget *w = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "width_sb");
1512 gtk_widget_set_sensitive(w, TRUE);
1513 GtkWidget *h = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(tbl), "height_sb");
1514 gtk_widget_set_sensitive(h, TRUE);
1516 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1517 if (oldrepr) { // remove old listener
1518 sp_repr_remove_listener_by_data(oldrepr, tbl);
1519 Inkscape::GC::release(oldrepr);
1520 oldrepr = 0;
1521 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1522 }
1523 if (repr) {
1524 g_object_set_data(G_OBJECT(tbl), "repr", repr);
1525 g_object_set_data(G_OBJECT(tbl), "item", item);
1526 Inkscape::GC::anchor(repr);
1527 sp_repr_add_listener(repr, &rect_tb_repr_events, tbl);
1528 sp_repr_synthesize_events(repr, &rect_tb_repr_events, tbl);
1529 }
1530 } else {
1531 // FIXME: implement averaging of all parameters for multiple selected
1532 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1533 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1534 sp_rtb_sensitivize (GTK_WIDGET(tbl));
1535 }
1536 }
1539 static GtkWidget *
1540 sp_rect_toolbox_new(SPDesktop *desktop)
1541 {
1542 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1544 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1545 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1547 GtkTooltips *tt = gtk_tooltips_new();
1549 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1551 // rx/ry units menu: create
1552 GtkWidget *us = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
1553 sp_unit_selector_setsize(us, AUX_OPTION_MENU_WIDTH, AUX_OPTION_MENU_HEIGHT);
1554 sp_unit_selector_set_unit(SP_UNIT_SELECTOR(us), desktop->namedview->doc_units);
1555 // fixme: add % meaning per cent of the width/height
1557 /* W */
1558 {
1559 GtkWidget *hb = sp_tb_spinbutton(_("W:"), _("Width of rectangle"),
1560 "tools.shapes.rect", "width", 0,
1561 us, tbl, TRUE, "altx-rect",
1562 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1563 sp_rtb_width_value_changed);
1564 gtk_object_set_data(GTK_OBJECT(tbl), "width_sb", hb);
1565 gtk_widget_set_sensitive(hb, FALSE);
1566 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1567 }
1569 /* H */
1570 {
1571 GtkWidget *hb = sp_tb_spinbutton(_("H:"), _("Height of rectangle"),
1572 "tools.shapes.rect", "height", 0,
1573 us, tbl, FALSE, NULL,
1574 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1575 sp_rtb_height_value_changed);
1576 gtk_object_set_data(GTK_OBJECT(tbl), "height_sb", hb);
1577 gtk_widget_set_sensitive(hb, FALSE);
1578 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1579 }
1581 /* rx */
1582 {
1583 GtkWidget *hb = sp_tb_spinbutton(_("Rx:"), _("Horizontal radius of rounded corners"),
1584 "tools.shapes.rect", "rx", 0,
1585 us, tbl, FALSE, NULL,
1586 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1587 sp_rtb_rx_value_changed);
1588 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1589 }
1591 /* ry */
1592 {
1593 GtkWidget *hb = sp_tb_spinbutton(_("Ry:"), _("Vertical radius of rounded corners"),
1594 "tools.shapes.rect", "ry", 0,
1595 us, tbl, FALSE, NULL,
1596 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1597 sp_rtb_ry_value_changed);
1598 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1599 }
1601 // add the units menu
1602 gtk_widget_show(us);
1603 gtk_box_pack_start(GTK_BOX(tbl), us, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1604 gtk_object_set_data(GTK_OBJECT(tbl), "units", us);
1606 /* Reset */
1607 {
1608 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1609 GtkWidget *b = gtk_button_new_with_label(_("Not rounded"));
1610 gtk_object_set_data(GTK_OBJECT(tbl), "not_rounded", b);
1611 gtk_tooltips_set_tip(tt, b, _("Make corners sharp"), NULL);
1612 gtk_widget_show(b);
1613 gtk_container_add(GTK_CONTAINER(hb), b);
1614 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_rtb_defaults), tbl);
1615 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1616 }
1618 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1619 swatch->setWatchedTool ("tools.shapes.rect", true);
1620 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1621 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1623 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
1624 sp_rtb_sensitivize (tbl);
1626 gtk_widget_show_all(tbl);
1627 sp_set_font_size_smaller (tbl);
1629 sigc::connection *connection = new sigc::connection(
1630 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_rect_toolbox_selection_changed), (GtkObject *)tbl))
1631 );
1632 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1634 return tbl;
1635 }
1637 //########################
1638 //## Spiral ##
1639 //########################
1641 static void
1642 sp_spl_tb_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name)
1643 {
1644 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
1646 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1647 prefs_set_double_attribute("tools.shapes.spiral", value_name, adj->value);
1648 }
1650 // quit if run by the attr_changed listener
1651 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1652 return;
1653 }
1655 // in turn, prevent listener from responding
1656 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1658 gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
1660 bool modmade = false;
1661 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
1662 items != NULL;
1663 items = items->next)
1664 {
1665 if (SP_IS_SPIRAL((SPItem *) items->data)) {
1666 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
1667 sp_repr_set_svg_double( repr, namespaced_name, adj->value );
1668 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
1669 modmade = true;
1670 }
1671 }
1673 g_free(namespaced_name);
1675 if (modmade) {
1676 sp_document_done(sp_desktop_document(desktop));
1677 }
1679 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1681 spinbutton_defocus(GTK_OBJECT(tbl));
1682 }
1684 static void
1685 sp_spl_tb_revolution_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1686 {
1687 sp_spl_tb_value_changed(adj, tbl, "revolution");
1688 }
1690 static void
1691 sp_spl_tb_expansion_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1692 {
1693 sp_spl_tb_value_changed(adj, tbl, "expansion");
1694 }
1696 static void
1697 sp_spl_tb_t0_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1698 {
1699 sp_spl_tb_value_changed(adj, tbl, "t0");
1700 }
1702 static void
1703 sp_spl_tb_defaults(GtkWidget *widget, GtkObject *obj)
1704 {
1705 GtkWidget *tbl = GTK_WIDGET(obj);
1707 GtkAdjustment *adj;
1709 // fixme: make settable
1710 gdouble rev = 5;
1711 gdouble exp = 1.0;
1712 gdouble t0 = 0.0;
1714 adj = (GtkAdjustment*)gtk_object_get_data(obj, "revolution");
1715 gtk_adjustment_set_value(adj, rev);
1716 gtk_adjustment_value_changed(adj);
1718 adj = (GtkAdjustment*)gtk_object_get_data(obj, "expansion");
1719 gtk_adjustment_set_value(adj, exp);
1720 gtk_adjustment_value_changed(adj);
1722 adj = (GtkAdjustment*)gtk_object_get_data(obj, "t0");
1723 gtk_adjustment_set_value(adj, t0);
1724 gtk_adjustment_value_changed(adj);
1726 spinbutton_defocus(GTK_OBJECT(tbl));
1727 }
1730 static void spiral_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1731 gchar const *old_value, gchar const *new_value,
1732 bool is_interactive, gpointer data)
1733 {
1734 GtkWidget *tbl = GTK_WIDGET(data);
1736 // quit if run by the _changed callbacks
1737 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1738 return;
1739 }
1741 // in turn, prevent callbacks from responding
1742 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1744 GtkAdjustment *adj;
1745 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "revolution");
1746 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:revolution", 3.0)));
1748 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "expansion");
1749 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:expansion", 1.0)));
1751 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "t0");
1752 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:t0", 0.0)));
1754 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1755 }
1758 static Inkscape::XML::NodeEventVector spiral_tb_repr_events = {
1759 NULL, /* child_added */
1760 NULL, /* child_removed */
1761 spiral_tb_event_attr_changed,
1762 NULL, /* content_changed */
1763 NULL /* order_changed */
1764 };
1766 static void
1767 sp_spiral_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1768 {
1769 int n_selected = 0;
1770 Inkscape::XML::Node *repr = NULL;
1771 Inkscape::XML::Node *oldrepr = NULL;
1773 for (GSList const *items = selection->itemList();
1774 items != NULL;
1775 items = items->next)
1776 {
1777 if (SP_IS_SPIRAL((SPItem *) items->data)) {
1778 n_selected++;
1779 repr = SP_OBJECT_REPR((SPItem *) items->data);
1780 }
1781 }
1783 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
1785 if (n_selected == 0) {
1786 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
1787 } else if (n_selected == 1) {
1788 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1790 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1791 if (oldrepr) { // remove old listener
1792 sp_repr_remove_listener_by_data(oldrepr, tbl);
1793 Inkscape::GC::release(oldrepr);
1794 oldrepr = 0;
1795 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1796 }
1798 if (repr) {
1799 g_object_set_data(G_OBJECT(tbl), "repr", repr);
1800 Inkscape::GC::anchor(repr);
1801 sp_repr_add_listener(repr, &spiral_tb_repr_events, tbl);
1802 sp_repr_synthesize_events(repr, &spiral_tb_repr_events, tbl);
1803 }
1804 } else {
1805 // FIXME: implement averaging of all parameters for multiple selected
1806 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1807 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1808 }
1809 }
1812 static GtkWidget *
1813 sp_spiral_toolbox_new(SPDesktop *desktop)
1814 {
1815 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1816 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1817 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1819 GtkTooltips *tt = gtk_tooltips_new();
1821 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
1823 /* Revolution */
1824 {
1825 GtkWidget *hb = sp_tb_spinbutton(_("Turns:"), _("Number of revolutions"),
1826 "tools.shapes.spiral", "revolution", 3.0,
1827 NULL, tbl, TRUE, "altx-spiral",
1828 0.01, 1024.0, 0.1, 1.0,
1829 sp_spl_tb_revolution_value_changed, 1, 2);
1830 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1831 }
1833 /* Expansion */
1834 {
1835 GtkWidget *hb = sp_tb_spinbutton(_("Divergence:"), _("How much denser/sparser are outer revolutions; 1 = uniform"),
1836 "tools.shapes.spiral", "expansion", 1.0,
1837 NULL, tbl, FALSE, NULL,
1838 0.0, 1000.0, 0.01, 1.0,
1839 sp_spl_tb_expansion_value_changed);
1840 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1841 }
1843 /* T0 */
1844 {
1845 GtkWidget *hb = sp_tb_spinbutton(_("Inner radius:"), _("Radius of the innermost revolution (relative to the spiral size)"),
1846 "tools.shapes.spiral", "t0", 0.0,
1847 NULL, tbl, FALSE, NULL,
1848 0.0, 0.999, 0.01, 1.0,
1849 sp_spl_tb_t0_value_changed);
1850 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
1851 }
1853 aux_toolbox_space(tbl, AUX_SPACING);
1855 /* Reset */
1856 {
1857 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
1858 GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
1859 gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
1860 gtk_widget_show(b);
1861 gtk_container_add(GTK_CONTAINER(hb), b);
1862 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_spl_tb_defaults), tbl);
1863 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
1864 }
1866 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1867 swatch->setWatchedTool ("tools.shapes.spiral", true);
1868 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1869 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1871 gtk_widget_show_all(tbl);
1872 sp_set_font_size_smaller (tbl);
1874 sigc::connection *connection = new sigc::connection(
1875 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_spiral_toolbox_selection_changed), (GtkObject *)tbl))
1876 );
1877 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
1879 return tbl;
1880 }
1882 //########################
1883 //## Pen/Pencil ##
1884 //########################
1887 static GtkWidget *
1888 sp_pen_toolbox_new(SPDesktop *desktop)
1889 {
1890 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1891 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1892 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1894 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1895 swatch->setWatchedTool ("tools.freehand.pen", true);
1896 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1897 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1899 gtk_widget_show_all(tbl);
1900 sp_set_font_size_smaller (tbl);
1902 return tbl;
1903 }
1905 static GtkWidget *
1906 sp_pencil_toolbox_new(SPDesktop *desktop)
1907 {
1908 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
1909 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
1910 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
1912 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
1913 swatch->setWatchedTool ("tools.freehand.pencil", true);
1914 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1915 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
1917 gtk_widget_show_all(tbl);
1918 sp_set_font_size_smaller (tbl);
1920 return tbl;
1921 }
1924 //########################
1925 //## Calligraphy ##
1926 //########################
1928 static void
1929 sp_ddc_mass_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1930 {
1931 prefs_set_double_attribute("tools.calligraphic", "mass", adj->value);
1932 spinbutton_defocus(GTK_OBJECT(tbl));
1933 }
1935 static void
1936 sp_ddc_drag_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1937 {
1938 prefs_set_double_attribute("tools.calligraphic", "drag", adj->value);
1939 spinbutton_defocus(GTK_OBJECT(tbl));
1940 }
1942 static void
1943 sp_ddc_angle_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1944 {
1945 prefs_set_double_attribute("tools.calligraphic", "angle", adj->value);
1946 spinbutton_defocus(GTK_OBJECT(tbl));
1947 }
1949 static void
1950 sp_ddc_width_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1951 {
1952 prefs_set_double_attribute("tools.calligraphic", "width", adj->value * 0.01);
1953 spinbutton_defocus(GTK_OBJECT(tbl));
1954 }
1956 static void
1957 sp_ddc_velthin_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1958 {
1959 prefs_set_double_attribute("tools.calligraphic", "thinning", adj->value);
1960 spinbutton_defocus(GTK_OBJECT(tbl));
1961 }
1963 static void
1964 sp_ddc_flatness_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1965 {
1966 prefs_set_double_attribute("tools.calligraphic", "flatness", adj->value);
1967 spinbutton_defocus(GTK_OBJECT(tbl));
1968 }
1970 static void
1971 sp_ddc_tremor_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1972 {
1973 prefs_set_double_attribute("tools.calligraphic", "tremor", adj->value);
1974 spinbutton_defocus(GTK_OBJECT(tbl));
1975 }
1977 static void
1978 sp_ddc_pressure_state_changed(GtkWidget *button, gpointer data)
1979 {
1980 prefs_set_int_attribute ("tools.calligraphic", "usepressure", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0);
1981 }
1983 static void
1984 sp_ddc_tilt_state_changed(GtkWidget *button, GtkWidget *calligraphy_angle)
1985 {
1986 prefs_set_int_attribute ("tools.calligraphic", "usetilt", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0);
1988 gtk_widget_set_sensitive(GTK_WIDGET(calligraphy_angle), !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
1989 }
1991 static void sp_ddc_defaults(GtkWidget *, GtkWidget *tbl)
1992 {
1993 // FIXME: make defaults settable via Inkscape Options
1994 struct KeyValue {
1995 char const *key;
1996 double value;
1997 } const key_values[] = {
1998 {"mass", 0.02},
1999 {"drag", 1.0},
2000 {"angle", 30.0},
2001 {"width", 15},
2002 {"thinning", 0.1},
2003 {"tremor", 0.0},
2004 {"flatness", 0.9}
2005 };
2007 for (unsigned i = 0; i < G_N_ELEMENTS(key_values); ++i) {
2008 KeyValue const &kv = key_values[i];
2009 GtkAdjustment &adj = *static_cast<GtkAdjustment *>(gtk_object_get_data(GTK_OBJECT(tbl), kv.key));
2010 gtk_adjustment_set_value(&adj, kv.value);
2011 }
2013 spinbutton_defocus(GTK_OBJECT(tbl));
2014 }
2016 static GtkWidget *
2017 sp_calligraphy_toolbox_new(SPDesktop *desktop)
2018 {
2019 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2020 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2021 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2023 GtkTooltips *tt = gtk_tooltips_new();
2024 GtkWidget *calligraphy_angle;
2026 // interval
2027 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2029 /* Width */
2030 {
2031 GtkWidget *hb = sp_tb_spinbutton(_("Width:"), _("The width of the calligraphic pen (relative to the visible canvas area)"),
2032 "tools.calligraphic", "width", 15,
2033 NULL, tbl, TRUE, "altx-calligraphy",
2034 1, 100, 1.0, 10.0,
2035 sp_ddc_width_value_changed, 0.01, 0, 100);
2036 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2037 }
2039 /* Thinning */
2040 {
2041 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)"),
2042 "tools.calligraphic", "thinning", 0.1,
2043 NULL, tbl, FALSE, NULL,
2044 -1.0, 1.0, 0.01, 0.1,
2045 sp_ddc_velthin_value_changed, 0.01, 2);
2046 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2047 }
2049 // interval
2050 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2052 /* Angle */
2053 {
2054 calligraphy_angle = sp_tb_spinbutton(_("Angle:"), _("The angle of the pen's nib (in degrees; 0 = horizontal; has no effect if fixation = 0)"),
2055 "tools.calligraphic", "angle", 30,
2056 NULL, tbl, TRUE, "calligraphy-angle",
2057 -90.0, 90.0, 1.0, 10.0,
2058 sp_ddc_angle_value_changed, 1, 0);
2059 gtk_box_pack_start(GTK_BOX(tbl), calligraphy_angle, FALSE, FALSE, AUX_SPACING);
2060 }
2062 /* Fixation */
2063 {
2064 GtkWidget *hb = sp_tb_spinbutton(_("Fixation:"), _("How fixed is the pen angle (0 = always perpendicular to stroke direction, 1 = fixed)"),
2065 "tools.calligraphic", "flatness", 0.9,
2066 NULL, tbl, FALSE, NULL,
2067 0.0, 1.0, 0.01, 0.1,
2068 sp_ddc_flatness_value_changed, 0.01, 2);
2069 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2070 }
2072 // interval
2073 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2075 /* Tremor */
2076 {
2077 GtkWidget *hb = sp_tb_spinbutton(_("Tremor:"), _("How uneven or trembling is the pen stroke"),
2078 "tools.calligraphic", "tremor", 0.0,
2079 NULL, tbl, FALSE, NULL,
2080 0.0, 1.0, 0.01, 0.1,
2081 sp_ddc_tremor_value_changed, 0.01, 2);
2082 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2083 }
2084 /* Mass */
2085 {
2086 GtkWidget *hb = sp_tb_spinbutton(_("Mass:"), _("How much inertia affects the movement of the pen"),
2087 "tools.calligraphic", "mass", 0.02,
2088 NULL, tbl, FALSE, NULL,
2089 0.0, 1.0, 0.01, 0.1,
2090 sp_ddc_mass_value_changed, 0.01, 2);
2091 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2092 }
2094 /* Drag */
2095 {
2096 // TRANSLATORS: "drag" means "resistance" here
2097 GtkWidget *hb = sp_tb_spinbutton(_("Drag:"), _("How much resistance affects the movement of the pen"),
2098 "tools.calligraphic", "drag", 1,
2099 NULL, tbl, FALSE, NULL,
2100 0.0, 1.0, 0.01, 0.1,
2101 sp_ddc_drag_value_changed, 0.01, 2);
2102 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2103 }
2105 // interval
2106 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2108 GtkWidget *cvbox = gtk_vbox_new (FALSE, 0);
2109 GtkWidget *cbox = gtk_hbox_new (FALSE, 0);
2111 /* Use Pressure button */
2112 {
2113 GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
2114 SP_BUTTON_TYPE_TOGGLE,
2115 NULL,
2116 "use_pressure",
2117 _("Use the pressure of the input device to alter the width of the pen"),
2118 tt);
2119 g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (sp_ddc_pressure_state_changed), NULL);
2120 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.calligraphic", "usepressure", 1));
2121 gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
2122 }
2124 /* Use Tilt button */
2125 {
2126 GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
2127 SP_BUTTON_TYPE_TOGGLE,
2128 NULL,
2129 "use_tilt",
2130 _("Use the tilt of the input device to alter the angle of the pen's nib"),
2131 tt);
2132 g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (sp_ddc_tilt_state_changed), calligraphy_angle);
2133 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.calligraphic", "usetilt", 1));
2134 gtk_widget_set_sensitive(GTK_WIDGET(calligraphy_angle), !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
2135 gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
2136 }
2138 gtk_box_pack_start(GTK_BOX(cvbox), cbox, TRUE, FALSE, 0);
2139 gtk_box_pack_start(GTK_BOX(tbl), cvbox, FALSE, FALSE, 0);
2141 /* Reset */
2142 {
2143 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2144 GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
2145 gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
2146 gtk_widget_show(b);
2147 gtk_container_add(GTK_CONTAINER(hb), b);
2148 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_ddc_defaults), tbl);
2149 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2150 }
2153 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
2154 swatch->setWatchedTool ("tools.calligraphic", true);
2155 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
2156 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
2158 gtk_widget_show_all(tbl);
2159 sp_set_font_size_smaller (tbl);
2161 return tbl;
2162 }
2165 //########################
2166 //## Circle / Arc ##
2167 //########################
2169 static void
2170 sp_arctb_sensitivize (GtkWidget *tbl, double v1, double v2)
2171 {
2172 GtkWidget *ocb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "open_checkbox");
2173 GtkWidget *make_whole = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "make_whole");
2175 if (v1 == 0 && v2 == 0) {
2176 if (gtk_object_get_data(GTK_OBJECT(tbl), "single")) { // only for a single selected ellipse (for now)
2177 gtk_widget_set_sensitive(GTK_WIDGET(ocb), FALSE);
2178 gtk_widget_set_sensitive(GTK_WIDGET(make_whole), FALSE);
2179 }
2180 } else {
2181 gtk_widget_set_sensitive(GTK_WIDGET(ocb), TRUE);
2182 gtk_widget_set_sensitive(GTK_WIDGET(make_whole), TRUE);
2183 }
2184 }
2186 static void
2187 sp_arctb_startend_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name, gchar const *other_name)
2188 {
2189 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2191 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2192 prefs_set_double_attribute("tools.shapes.arc", value_name, (adj->value * M_PI)/ 180);
2193 }
2195 // quit if run by the attr_changed listener
2196 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2197 return;
2198 }
2200 // in turn, prevent listener from responding
2201 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2203 gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
2205 bool modmade = false;
2206 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2207 items != NULL;
2208 items = items->next)
2209 {
2210 SPItem *item = SP_ITEM(items->data);
2212 if (SP_IS_ARC(item) && SP_IS_GENERICELLIPSE(item)) {
2214 SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
2215 SPArc *arc = SP_ARC(item);
2217 if (!strcmp(value_name, "start"))
2218 ge->start = (adj->value * M_PI)/ 180;
2219 else
2220 ge->end = (adj->value * M_PI)/ 180;
2222 sp_genericellipse_normalize(ge);
2223 ((SPObject *)arc)->updateRepr();
2224 ((SPObject *)arc)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
2226 modmade = true;
2227 }
2228 }
2230 g_free(namespaced_name);
2232 GtkAdjustment *other = (GtkAdjustment *)gtk_object_get_data(GTK_OBJECT(tbl), other_name);
2234 sp_arctb_sensitivize (tbl, adj->value, other->value);
2236 if (modmade) {
2237 sp_document_maybe_done(sp_desktop_document(desktop), value_name);
2238 }
2240 // defocus spinbuttons by moving focus to the canvas, unless "stay" is on
2241 spinbutton_defocus(GTK_OBJECT(tbl));
2243 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2244 }
2247 static void
2248 sp_arctb_start_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
2249 {
2250 sp_arctb_startend_value_changed(adj, tbl, "start", "end");
2251 }
2253 static void
2254 sp_arctb_end_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
2255 {
2256 sp_arctb_startend_value_changed(adj, tbl, "end", "start");
2257 }
2259 static void
2260 sp_arctb_open_state_changed(GtkWidget *widget, GtkObject *tbl)
2261 {
2262 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2264 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2265 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
2266 prefs_set_string_attribute("tools.shapes.arc", "open", "true");
2267 } else {
2268 prefs_set_string_attribute("tools.shapes.arc", "open", NULL);
2269 }
2270 }
2272 // quit if run by the attr_changed listener
2273 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2274 return;
2275 }
2277 // in turn, prevent listener from responding
2278 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2280 bool modmade = false;
2282 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
2283 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2284 items != NULL;
2285 items = items->next)
2286 {
2287 if (SP_IS_ARC((SPItem *) items->data)) {
2288 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2289 repr->setAttribute("sodipodi:open", "true");
2290 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
2291 modmade = true;
2292 }
2293 }
2294 } else {
2295 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2296 items != NULL;
2297 items = items->next)
2298 {
2299 if (SP_IS_ARC((SPItem *) items->data)) {
2300 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2301 repr->setAttribute("sodipodi:open", NULL);
2302 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
2303 modmade = true;
2304 }
2305 }
2306 }
2308 if (modmade) {
2309 sp_document_done(sp_desktop_document(desktop));
2310 }
2312 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2314 spinbutton_defocus(GTK_OBJECT(tbl));
2315 }
2317 static void sp_arctb_defaults(GtkWidget *, GtkObject *obj)
2318 {
2319 GtkWidget *tbl = GTK_WIDGET(obj);
2321 GtkAdjustment *adj;
2322 adj = (GtkAdjustment*)gtk_object_get_data(obj, "start");
2323 gtk_adjustment_set_value(adj, 0.0);
2324 gtk_adjustment_value_changed(adj);
2326 adj = (GtkAdjustment*)gtk_object_get_data(obj, "end");
2327 gtk_adjustment_set_value(adj, 0.0);
2328 gtk_adjustment_value_changed(adj);
2330 spinbutton_defocus(GTK_OBJECT(tbl));
2331 }
2333 static void arc_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
2334 gchar const *old_value, gchar const *new_value,
2335 bool is_interactive, gpointer data)
2336 {
2337 GtkWidget *tbl = GTK_WIDGET(data);
2339 // quit if run by the _changed callbacks
2340 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2341 return;
2342 }
2344 // in turn, prevent callbacks from responding
2345 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2347 gdouble start = sp_repr_get_double_attribute(repr, "sodipodi:start", 0.0);
2348 gdouble end = sp_repr_get_double_attribute(repr, "sodipodi:end", 0.0);
2350 GtkAdjustment *adj1,*adj2;
2351 adj1 = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "start");
2352 gtk_adjustment_set_value(adj1, mod360((start * 180)/M_PI));
2353 adj2 = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "end");
2354 gtk_adjustment_set_value(adj2, mod360((end * 180)/M_PI));
2356 sp_arctb_sensitivize (tbl, adj1->value, adj2->value);
2358 char const *openstr = NULL;
2359 openstr = repr->attribute("sodipodi:open");
2360 GtkWidget *ocb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "open_checkbox");
2362 if (openstr) {
2363 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ocb), TRUE);
2364 } else {
2365 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ocb), FALSE);
2366 }
2368 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2369 }
2371 static Inkscape::XML::NodeEventVector arc_tb_repr_events = {
2372 NULL, /* child_added */
2373 NULL, /* child_removed */
2374 arc_tb_event_attr_changed,
2375 NULL, /* content_changed */
2376 NULL /* order_changed */
2377 };
2380 static void
2381 sp_arc_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
2382 {
2383 int n_selected = 0;
2384 Inkscape::XML::Node *repr = NULL;
2385 Inkscape::XML::Node *oldrepr = NULL;
2387 for (GSList const *items = selection->itemList();
2388 items != NULL;
2389 items = items->next)
2390 {
2391 if (SP_IS_ARC((SPItem *) items->data)) {
2392 n_selected++;
2393 repr = SP_OBJECT_REPR((SPItem *) items->data);
2394 }
2395 }
2397 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
2399 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(FALSE));
2400 if (n_selected == 0) {
2401 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
2402 } else if (n_selected == 1) {
2403 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
2404 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2406 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
2408 if (oldrepr) { // remove old listener
2409 sp_repr_remove_listener_by_data(oldrepr, tbl);
2410 Inkscape::GC::release(oldrepr);
2411 oldrepr = 0;
2412 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
2413 }
2415 if (repr) {
2416 g_object_set_data(G_OBJECT(tbl), "repr", repr);
2417 Inkscape::GC::anchor(repr);
2418 sp_repr_add_listener(repr, &arc_tb_repr_events, tbl);
2419 sp_repr_synthesize_events(repr, &arc_tb_repr_events, tbl);
2420 }
2421 } else {
2422 // FIXME: implement averaging of all parameters for multiple selected
2423 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
2424 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2425 sp_arctb_sensitivize (GTK_WIDGET(tbl), 1, 0);
2426 }
2427 }
2430 static GtkWidget *
2431 sp_arc_toolbox_new(SPDesktop *desktop)
2432 {
2433 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2435 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2436 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2438 GtkTooltips *tt = gtk_tooltips_new();
2440 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
2442 /* Start */
2443 {
2444 GtkWidget *hb = sp_tb_spinbutton(_("Start:"), _("The angle (in degrees) from the horizontal to the arc's start point"),
2445 "tools.shapes.arc", "start", 0.0,
2446 NULL, tbl, TRUE, "altx-arc",
2447 -360.0, 360.0, 1.0, 10.0,
2448 sp_arctb_start_value_changed);
2449 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2450 }
2452 /* End */
2453 {
2454 GtkWidget *hb = sp_tb_spinbutton(_("End:"), _("The angle (in degrees) from the horizontal to the arc's end point"),
2455 "tools.shapes.arc", "end", 0.0,
2456 NULL, tbl, FALSE, NULL,
2457 -360.0, 360.0, 1.0, 10.0,
2458 sp_arctb_end_value_changed);
2459 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2460 }
2462 /* Segments / Pie checkbox */
2463 {
2464 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2465 GtkWidget *fscb = gtk_check_button_new_with_label(_("Open arc"));
2466 gtk_tooltips_set_tip(tt, fscb, _("Switch between arc (unclosed shape) and segment (closed shape with two radii)"), NULL);
2468 gchar const *openstr = NULL;
2469 openstr = prefs_get_string_attribute("tools.shapes.arc", "open");
2470 if (!openstr || (openstr && !strcmp(openstr, "false")))
2471 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), FALSE);
2472 else
2473 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), TRUE);
2475 gtk_widget_show(fscb);
2476 gtk_object_set_data(GTK_OBJECT(tbl), "open_checkbox", fscb);
2477 gtk_container_add(GTK_CONTAINER(hb), fscb);
2478 g_signal_connect(G_OBJECT(fscb), "toggled", GTK_SIGNAL_FUNC(sp_arctb_open_state_changed ), tbl);
2479 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2480 }
2482 /* Make Whole */
2483 {
2484 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2485 GtkWidget *b = gtk_button_new_with_label(_("Make whole"));
2486 gtk_object_set_data(GTK_OBJECT(tbl), "make_whole", b);
2487 gtk_tooltips_set_tip(tt, b, _("Make the shape a whole ellipse, not arc or segment"), NULL);
2488 gtk_widget_show(b);
2489 gtk_container_add(GTK_CONTAINER(hb), b);
2490 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_arctb_defaults), tbl);
2491 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2492 }
2494 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
2495 // sensitivize make whole and open checkbox
2496 {
2497 GtkAdjustment *adj1 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "start"));
2498 GtkAdjustment *adj2 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "end"));
2499 sp_arctb_sensitivize (tbl, adj1->value, adj2->value);
2500 }
2502 sigc::connection *connection = new sigc::connection(
2503 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_arc_toolbox_selection_changed), (GtkObject *)tbl))
2504 );
2505 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
2507 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL);
2508 swatch->setWatchedTool ("tools.shapes.arc", true);
2509 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
2510 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
2512 gtk_widget_show_all(tbl);
2513 sp_set_font_size_smaller (tbl);
2515 return tbl;
2516 }
2521 // toggle button callbacks and updaters
2523 //########################
2524 //## Dropper ##
2525 //########################
2527 static void toggle_dropper_color_pick (GtkWidget *button, gpointer data) {
2528 prefs_set_int_attribute ("tools.dropper", "pick",
2529 // 0 and 1 are backwards here because of pref
2530 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1);
2531 }
2534 /**
2535 * Copy the current saved desktop color to the clipboard as full hex + alpha
2536 * color representation. This is useful for passing values between various
2537 * input boxes, or directly to xml.
2538 */
2539 /* static void
2540 sp_dropper_copy( GtkWidget *widget, GtkObject *obj)
2541 {
2542 GtkWidget *tbl = GTK_WIDGET(obj);
2544 SPDesktop *desktop =
2545 (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2548 sp_dropper_c32_color_copy( sp_desktop_get_color(desktop, true) );
2549 }*/
2552 /**
2553 * Copies currently saved desktop color to the clipboard as a hex value. This
2554 * is useful for editing webpages and needing a value quickly for web
2555 * colors.
2556 *
2557 * TODO: When the toggle of the dropper is set to not mix color against
2558 * page background, this still just gets the color of the page and
2559 * doesn't get the actual mixed against background which is needed
2560 * for the hex value ppl. want for web pages, etc.
2561 */
2563 /* static void
2564 sp_dropper_copy_as_hex ( GtkWidget *widget, GtkObject *obj)
2565 {
2566 GtkWidget *tbl = GTK_WIDGET(obj);
2568 SPDesktop *desktop =
2569 (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2571 sp_dropper_c32_color_copy_hex( sp_desktop_get_color(desktop, true) );
2572 }*/
2575 /**
2576 * Sets the input boxes with the changed color and opacity. This is used as a
2577 * callback for style changing.
2578 */
2579 /* static bool
2580 sp_style_changed (const SPCSSAttr *css, gpointer data)
2581 {
2582 // GrDrag *drag = (GrDrag *) data;
2584 // set fill of text entry box
2585 if (css->attribute("fill"))
2586 gtk_entry_set_text((GtkEntry *)dropper_rgb_entry,
2587 css->attribute("fill"));
2589 // set opacity of text entry box
2590 if (css->attribute("fill-opacity"))
2591 gtk_entry_set_text((GtkEntry *)dropper_opacity_entry,
2592 css->attribute("fill-opacity"));
2594 // set fill of text entry box
2595 if (css->attribute("stroke"))
2596 gtk_entry_set_text((GtkEntry *)dropper_rgb_entry,
2597 css->attribute("stroke"));
2599 // set opacity of text entry box
2600 if (css->attribute("stroke-opacity"))
2601 gtk_entry_set_text((GtkEntry *)dropper_opacity_entry,
2602 css->attribute("stroke-opacity"));
2603 return false;
2605 }
2606 */
2609 /**
2610 * Dropper auxiliary toolbar construction and setup.
2611 *
2612 * TODO: Would like to add swatch of current color.
2613 * TODO: Add queue of last 5 or so colors selected with new swatches so that
2614 * can drag and drop places. Will provide a nice mixing palette.
2615 */
2616 static GtkWidget *
2617 sp_dropper_toolbox_new(SPDesktop *desktop)
2618 {
2619 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2621 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2622 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2624 GtkTooltips *tt = gtk_tooltips_new();
2627 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
2628 AUX_BETWEEN_BUTTON_GROUPS);
2629 // sp_toolbox_add_label(tbl, _("<b>New:</b>"));
2633 /* RGB Input Field */
2634 /* {
2635 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2636 GtkWidget *dropper_rgba_label = gtk_label_new ("Color:");
2637 gtk_widget_show (dropper_rgba_label);
2638 gtk_container_add(GTK_CONTAINER(hb), dropper_rgba_label);
2640 dropper_rgb_entry = gtk_entry_new ();
2641 sp_dialog_defocus_on_enter (dropper_rgb_entry);
2642 gtk_entry_set_max_length (GTK_ENTRY (dropper_rgb_entry), 7);
2643 gtk_entry_set_width_chars (GTK_ENTRY (dropper_rgb_entry), 7);
2644 gtk_tooltips_set_tip(tt, dropper_rgb_entry,
2645 _("Hexidecimal representation of last selected "
2646 "color"),
2647 NULL);
2648 gtk_widget_show (dropper_rgb_entry);
2649 gtk_container_add(GTK_CONTAINER(hb), dropper_rgb_entry);
2651 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2652 AUX_BETWEEN_BUTTON_GROUPS);
2653 } */
2655 /* Opacity Input Field */
2656 /* {
2657 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2658 GtkWidget *dropper_opacity_label = gtk_label_new ( _("Opacity:") );
2659 gtk_widget_show (dropper_opacity_label);
2660 gtk_container_add(GTK_CONTAINER(hb), dropper_opacity_label);
2662 dropper_opacity_entry = gtk_entry_new ();
2663 sp_dialog_defocus_on_enter (dropper_opacity_entry);
2664 gtk_entry_set_max_length (GTK_ENTRY (dropper_opacity_entry), 11);
2665 gtk_entry_set_width_chars (GTK_ENTRY (dropper_opacity_entry), 11);
2666 gtk_tooltips_set_tip(tt, dropper_opacity_entry,
2667 _("Opacity of last selected color"),
2668 NULL);
2669 gtk_widget_show (dropper_opacity_entry);
2670 gtk_container_add(GTK_CONTAINER(hb), dropper_opacity_entry);
2672 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2673 AUX_BETWEEN_BUTTON_GROUPS);
2674 } */
2677 /* Copy to Clipboard */
2678 /* {
2679 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2680 GtkWidget *b = gtk_button_new_with_label(_("Copy as RGBA"));
2681 gtk_tooltips_set_tip(tt, b, _("Copy last saved color as hexidecimal "
2682 "RGB + Alpha (RGBA) to "
2683 "clipboard"),
2684 NULL);
2685 gtk_widget_show(b);
2686 gtk_container_add(GTK_CONTAINER(hb), b);
2687 gtk_signal_connect(GTK_OBJECT(b), "clicked",
2688 GTK_SIGNAL_FUNC(sp_dropper_copy), tbl);
2689 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2690 AUX_BETWEEN_BUTTON_GROUPS);
2691 } */
2694 /* Copy to Clipboard as HEX */
2695 /* {
2696 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2697 GtkWidget *b = gtk_button_new_with_label(_("Copy as HEX"));
2698 gtk_tooltips_set_tip(tt, b, _("Copy last saved color as "
2699 "hexidecimal RGB without alpha "
2700 "to clipboard"), NULL);
2701 gtk_widget_show(b);
2702 gtk_container_add(GTK_CONTAINER(hb), b);
2703 gtk_signal_connect(GTK_OBJECT(b), "clicked",
2704 GTK_SIGNAL_FUNC(sp_dropper_copy_as_hex), tbl);
2705 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2706 AUX_BETWEEN_BUTTON_GROUPS);
2707 } */
2709 // aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2711 {
2712 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2714 GtkWidget *button =
2715 sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
2716 SP_BUTTON_TYPE_TOGGLE,
2717 NULL,
2718 "pick_color",
2719 _("When pressed, picks visible color "
2720 "without alpha and when not pressed, "
2721 "picks color including its "
2722 "alpha"),
2723 tt);
2725 gtk_widget_show(button);
2726 gtk_container_add (GTK_CONTAINER (hb), button);
2728 g_signal_connect_after (G_OBJECT (button), "clicked",
2729 G_CALLBACK (toggle_dropper_color_pick), NULL);
2730 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
2731 !prefs_get_int_attribute ("tools.dropper",
2732 "pick", 0));
2733 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
2734 AUX_BETWEEN_BUTTON_GROUPS);
2735 }
2737 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
2740 // where new gtkmm stuff should go
2742 gtk_widget_show_all(tbl);
2743 sp_set_font_size_smaller (tbl);
2745 /*
2746 sigc::connection *connection = new sigc::connection(
2747 desktop->connectSetStyle(
2748 sigc::bind(sigc::ptr_fun(sp_style_changed),
2749 desktop)) );
2751 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection),
2752 connection); */
2754 return tbl;
2755 }
2758 //########################
2759 //## Text Toolbox ##
2760 //########################
2761 /*
2762 static void
2763 sp_text_letter_changed(GtkAdjustment *adj, GtkWidget *tbl)
2764 {
2765 //Call back for letter sizing spinbutton
2766 }
2768 static void
2769 sp_text_line_changed(GtkAdjustment *adj, GtkWidget *tbl)
2770 {
2771 //Call back for line height spinbutton
2772 }
2774 static void
2775 sp_text_horiz_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
2776 {
2777 //Call back for horizontal kerning spinbutton
2778 }
2780 static void
2781 sp_text_vert_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
2782 {
2783 //Call back for vertical kerning spinbutton
2784 }
2786 static void
2787 sp_text_letter_rotation_changed(GtkAdjustment *adj, GtkWidget *tbl)
2788 {
2789 //Call back for letter rotation spinbutton
2790 }*/
2792 namespace {
2794 bool visible = false;
2796 void
2797 sp_text_toolbox_selection_changed (Inkscape::Selection *selection, GObject *tbl)
2798 {
2799 SPStyle *query =
2800 sp_style_new ();
2802 int result_family =
2803 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
2805 int result_style =
2806 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
2808 int result_numbers =
2809 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
2811 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
2812 if (result_family == QUERY_STYLE_NOTHING || result_style == QUERY_STYLE_NOTHING || result_numbers == QUERY_STYLE_NOTHING)
2813 {
2814 Inkscape::XML::Node *repr = inkscape_get_repr (INKSCAPE, "tools.text");
2816 if (repr)
2817 {
2818 sp_style_read_from_repr (query, repr);
2819 }
2820 else
2821 {
2822 return;
2823 }
2824 }
2826 if (result_numbers == QUERY_STYLE_MULTIPLE_DIFFERENT)
2827 {
2828 GtkWidget *entry = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "family-entry"));
2829 gtk_entry_set_text (GTK_ENTRY (entry), "");
2830 gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
2831 return;
2832 }
2834 if (query->text)
2835 {
2836 if (query->text->font_family.value)
2837 {
2838 Gtk::TreePath path;
2839 try {
2840 path = Inkscape::FontLister::get_instance()->get_row_for_font (query->text->font_family.value);
2841 } catch (...) {
2842 return;
2843 }
2845 GtkTreeSelection *selection = GTK_TREE_SELECTION (g_object_get_data (G_OBJECT(tbl), "family-tree-selection"));
2846 GtkTreeView *treeview = GTK_TREE_VIEW (g_object_get_data (G_OBJECT(tbl), "family-tree-view"));
2848 g_object_set_data (G_OBJECT (selection), "block", gpointer(1));
2850 gtk_tree_selection_select_path (selection, path.gobj());
2851 gtk_tree_view_scroll_to_cell (treeview, path.gobj(), NULL, TRUE, 0.5, 0.0);
2853 g_object_set_data (G_OBJECT (selection), "block", gpointer(0));
2854 }
2856 //Size
2857 GtkWidget *cbox = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "combo-box-size"));
2858 char *str = g_strdup_printf ("%.5g", query->font_size.computed);
2859 g_object_set_data (tbl, "size-block", gpointer(1));
2860 gtk_entry_set_text (GTK_ENTRY(GTK_BIN (cbox)->child), str);
2861 g_object_set_data (tbl, "size-block", gpointer(0));
2862 free (str);
2864 //Anchor
2865 g_object_set_data (tbl, "anchor-block", gpointer(1));
2866 GtkWidget *button = 0;
2867 if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_START)
2868 {
2869 button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-anchor-start"));
2870 }
2871 else if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_MIDDLE)
2872 {
2873 button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-anchor-middle"));
2874 }
2875 else if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_END)
2876 {
2877 button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-anchor-end"));
2878 }
2879 if (button) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2880 g_object_set_data (tbl, "anchor-block", gpointer(0));
2883 #if 0
2884 //Style
2885 cbox = GTK_COMBO_BOX(g_object_get_data (G_OBJECT(tbl), "combo-box-style"));
2886 g_object_set_data (G_OBJECT (cbox), "block", GINT_TO_POINTER(1));
2887 gtk_combo_box_set_active (GTK_COMBO_BOX (cbox), gint(query->font_style.value));
2888 g_object_set_data (G_OBJECT (cbox), "block", GINT_TO_POINTER(0));
2889 #endif
2891 gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
2892 }
2893 }
2895 void
2896 sp_text_toolbox_selection_modified (Inkscape::Selection *selection, guint flags, GObject *tbl)
2897 {
2898 sp_text_toolbox_selection_changed (selection, tbl);
2899 }
2901 void
2902 sp_text_toolbox_subselection_changed (gpointer dragger, GObject *tbl)
2903 {
2904 sp_text_toolbox_selection_changed (NULL, tbl);
2905 }
2907 void
2908 sp_text_toolbox_family_changed (GtkTreeSelection *selection,
2909 GObject *tbl)
2910 {
2911 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
2912 GtkTreeModel *model;
2913 GtkWidget *popdown = GTK_WIDGET (g_object_get_data (tbl, "family-popdown-window"));
2914 GtkWidget *entry = GTK_WIDGET (g_object_get_data (tbl, "family-entry"));
2915 GtkTreeIter iter;
2916 char *family;
2918 gtk_tree_selection_get_selected (selection, &model, &iter);
2919 gtk_tree_model_get (model, &iter, 0, &family, -1);
2921 if (g_object_get_data (G_OBJECT (selection), "block"))
2922 {
2923 gtk_entry_set_text (GTK_ENTRY (entry), family);
2924 return;
2925 }
2927 gtk_widget_hide (popdown);
2928 visible = false;
2930 gtk_entry_set_text (GTK_ENTRY (entry), family);
2932 SPStyle *query =
2933 sp_style_new ();
2935 int result_numbers =
2936 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
2938 SPCSSAttr *css = sp_repr_css_attr_new ();
2939 sp_repr_css_set_property (css, "font-family", family);
2941 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
2942 if (result_numbers == QUERY_STYLE_NOTHING)
2943 {
2944 sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
2945 sp_text_edit_dialog_default_set_insensitive (); //FIXME: Replace trough a verb
2946 }
2947 else
2948 {
2949 sp_desktop_set_style (desktop, css, true, true);
2950 }
2952 sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP));
2953 sp_repr_css_attr_unref (css);
2956 free (family);
2958 gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
2959 }
2961 void
2962 sp_text_toolbox_family_entry_activate (GtkEntry *entry,
2963 GObject *tbl)
2964 {
2965 const char *family;
2967 family = gtk_entry_get_text (entry);
2969 try {
2970 Gtk::TreePath path = Inkscape::FontLister::get_instance()->get_row_for_font (family);
2972 GtkTreeSelection *selection = GTK_TREE_SELECTION (g_object_get_data (G_OBJECT(tbl), "family-tree-selection"));
2973 GtkTreeView *treeview = GTK_TREE_VIEW (g_object_get_data (G_OBJECT(tbl), "family-tree-view"));
2974 gtk_tree_selection_select_path (selection, path.gobj());
2975 gtk_tree_view_scroll_to_cell (treeview, path.gobj(), NULL, TRUE, 0.5, 0.0);
2976 gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
2977 } catch (...) {
2978 //XXX: Accept it anyway and show the warning
2979 if (family && strlen (family)) gtk_widget_show_all (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
2980 }
2981 }
2983 void
2984 sp_text_toolbox_anchoring_toggled (GtkRadioButton *button,
2985 gpointer data)
2986 {
2987 if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) return;
2988 int prop = GPOINTER_TO_INT(data);
2990 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
2991 SPCSSAttr *css = sp_repr_css_attr_new ();
2993 switch (prop)
2994 {
2995 case 0:
2996 {
2997 sp_repr_css_set_property (css, "text-anchor", "start");
2998 sp_repr_css_set_property (css, "text-align", "start");
2999 break;
3000 }
3001 case 1:
3002 {
3003 sp_repr_css_set_property (css, "text-anchor", "middle");
3004 sp_repr_css_set_property (css, "text-align", "center");
3005 break;
3006 }
3008 case 2:
3009 {
3010 sp_repr_css_set_property (css, "text-anchor", "end");
3011 sp_repr_css_set_property (css, "text-align", "end");
3012 break;
3013 }
3014 }
3016 sp_desktop_set_style (desktop, css, true, true);
3017 sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP));
3018 sp_repr_css_attr_unref (css);
3019 }
3021 void
3022 sp_text_toolbox_size_changed (GtkComboBox *cbox,
3023 GObject *tbl)
3024 {
3025 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3027 if (g_object_get_data (tbl, "size-block")) return;
3028 if (gtk_combo_box_get_active (cbox) < 0 ) return;
3030 SPCSSAttr *css = sp_repr_css_attr_new ();
3031 char *text = gtk_combo_box_get_active_text (cbox);
3032 sp_repr_css_set_property (css, "font-size", text);
3033 free (text);
3034 sp_desktop_set_style (desktop, css, true, true);
3035 sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP));
3036 sp_repr_css_attr_unref (css);
3037 }
3039 #if 0
3040 void
3041 sp_text_toolbox_style_changed (GtkComboBox *cbox,
3042 GtkWidget *tbl)
3043 {
3044 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3046 if (GPOINTER_TO_INT(g_object_get_data (G_OBJECT (cbox), "block")) != 0) return;
3048 static char* styles[] = { "normal", "italic" , "oblique" };
3050 SPCSSAttr *css = sp_repr_css_attr_new ();
3051 sp_repr_css_set_property (css, "font-style", styles[gtk_combo_box_get_active (cbox)]);
3052 sp_desktop_set_style (desktop, css, true, true);
3053 sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP));
3054 sp_repr_css_attr_unref (css);
3055 }
3056 #endif
3058 void
3059 sp_text_toolbox_text_popdown_clicked (GtkButton *button,
3060 GObject *tbl)
3061 {
3062 GtkWidget *popdown = GTK_WIDGET (g_object_get_data (tbl, "family-popdown-window"));
3063 GtkWidget *widget = GTK_WIDGET (g_object_get_data (tbl, "family-entry"));
3064 int x, y;
3066 if (!visible)
3067 {
3068 gdk_window_get_origin (widget->window, &x, &y);
3069 gtk_window_move (GTK_WINDOW (popdown), x, y + widget->allocation.height + 2); //2px of grace space
3070 gtk_widget_show_all (popdown);
3071 visible = true;
3072 }
3073 else
3074 {
3075 gtk_widget_hide (popdown);
3076 visible = false;
3077 }
3078 }
3080 gboolean
3081 sp_text_toolbox_entry_focus_in (GtkWidget *entry,
3082 GdkEventFocus *event,
3083 GObject *tbl)
3084 {
3085 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
3086 return FALSE;
3087 }
3089 gboolean
3090 sp_text_toolbox_popdown_focus_out (GtkWidget *popdown,
3091 GdkEventFocus *event,
3092 GObject *tbl)
3093 {
3094 gtk_widget_hide (popdown);
3095 visible = false;
3096 return FALSE;
3097 }
3099 void
3100 cell_data_func (GtkTreeViewColumn *column,
3101 GtkCellRenderer *cell,
3102 GtkTreeModel *tree_model,
3103 GtkTreeIter *iter,
3104 gpointer data)
3105 {
3106 char *family,
3107 *family_escaped,
3108 *sample_escaped;
3110 const char *sample;
3112 gtk_tree_model_get (tree_model, iter, 0, &family, -1);
3114 sample = prefs_get_string_attribute ("tools.text", "font_sample");
3116 family_escaped = g_markup_escape_text (family, -1);
3117 sample_escaped = g_markup_escape_text (sample, -1);
3119 std::stringstream markup;
3120 markup << family_escaped << " <span foreground='darkgray' font_family='" << family_escaped << "'>" << sample_escaped << "</span>";
3121 g_object_set (G_OBJECT (cell), "markup", markup.str().c_str(), NULL);
3123 free (family);
3124 free (family_escaped);
3125 free (sample_escaped);
3126 }
3128 GtkWidget*
3129 sp_text_toolbox_new (SPDesktop *desktop)
3130 {
3131 #if 0
3132 GtkWidget *us = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "units"));
3133 GtkTooltips *tt = gtk_tooltips_new();
3134 GtkWidget *group;
3135 #endif
3137 GtkWidget *tbl = gtk_hbox_new (FALSE, 0);
3138 Glib::RefPtr<Gtk::ListStore> store = Inkscape::FontLister::get_instance()->get_font_list();
3140 ////////////Family
3141 //Window
3142 GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3143 gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
3145 //Label
3146 GtkWidget *label = gtk_label_new (_("Family:"));
3147 aux_toolbox_space (tbl, 1);
3148 gtk_box_pack_start (GTK_BOX (tbl), label, FALSE, FALSE, 0);
3150 //Entry
3151 GtkWidget *entry = gtk_entry_new ();
3152 GtkEntryCompletion *completion = gtk_entry_completion_new ();
3153 gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (Glib::unwrap(store)));
3154 gtk_entry_completion_set_text_column (completion, 0);
3155 gtk_entry_completion_set_minimum_key_length (completion, 3); //3 characters minimum sounds reasonable
3156 g_object_set (G_OBJECT(completion), "inline-completion", TRUE, "popup-completion", TRUE, NULL);
3157 gtk_entry_set_completion (GTK_ENTRY(entry), completion);
3158 aux_toolbox_space (tbl, 1);
3159 gtk_box_pack_start (GTK_BOX (tbl), entry, FALSE, FALSE, 0);
3161 //Button
3162 GtkWidget *button = gtk_button_new ();
3163 gtk_container_add (GTK_CONTAINER (button), gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE));
3165 aux_toolbox_space (tbl, 1);
3166 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
3168 //Popdown
3169 GtkWidget *sw = gtk_scrolled_window_new (NULL, NULL);
3170 GtkWidget *treeview = gtk_tree_view_new ();
3171 GtkCellRenderer *cell = gtk_cell_renderer_text_new ();
3172 GtkTreeViewColumn *column = gtk_tree_view_column_new ();
3174 gtk_tree_view_column_pack_start (column, cell, FALSE);
3175 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
3176 gtk_tree_view_column_set_cell_data_func (column, cell, GtkTreeCellDataFunc (cell_data_func), tbl, NULL);
3177 g_object_set (G_OBJECT (column), "min-width", int (300), "max-width", int (300), NULL);
3179 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
3180 gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (Glib::unwrap(store)));
3181 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
3182 gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (treeview), TRUE);
3184 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
3185 gtk_container_add (GTK_CONTAINER (sw), treeview);
3187 gtk_container_add (GTK_CONTAINER (window), sw);
3188 gtk_widget_set_size_request (window, 300, 450);
3190 g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (sp_text_toolbox_family_entry_activate), tbl);
3191 g_signal_connect (G_OBJECT (entry), "focus-in-event", G_CALLBACK (sp_text_toolbox_entry_focus_in), tbl);
3193 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (sp_text_toolbox_text_popdown_clicked), tbl);
3195 g_signal_connect (G_OBJECT (window), "focus-out-event", G_CALLBACK (sp_text_toolbox_popdown_focus_out), tbl);
3197 GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
3198 g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (sp_text_toolbox_family_changed), tbl);
3200 g_object_set_data (G_OBJECT (tbl), "family-entry", entry);
3201 g_object_set_data (G_OBJECT (tbl), "family-popdown-button", button);
3202 g_object_set_data (G_OBJECT (tbl), "family-popdown-window", window);
3203 g_object_set_data (G_OBJECT (tbl), "family-tree-selection", selection);
3204 g_object_set_data (G_OBJECT (tbl), "family-tree-view", treeview);
3206 GtkWidget *image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
3207 aux_toolbox_space (tbl, 1);
3208 GtkWidget *box = gtk_event_box_new ();
3209 gtk_container_add (GTK_CONTAINER (box), image);
3210 gtk_box_pack_start (GTK_BOX (tbl), box, FALSE, FALSE, 4);
3211 g_object_set_data (G_OBJECT (tbl), "warning-image", box);
3212 GtkTooltips *tooltips = gtk_tooltips_new ();
3213 gtk_tooltips_set_tip (tooltips, box, _("This font is currently not installed on your system. Inkscape will use the default font instead."), "");
3214 gtk_widget_hide (GTK_WIDGET (box));
3216 ////////////Size
3218 //Label
3219 label = gtk_label_new (_("Size:"));
3220 aux_toolbox_space (tbl, 1);
3221 gtk_box_pack_start (GTK_BOX (tbl), label, FALSE, FALSE, 0);
3223 //Cbox
3224 const char *sizes[] = {
3225 "4", "6", "8", "9", "10", "11", "12", "13", "14",
3226 "16", "18", "20", "22", "24", "28",
3227 "32", "36", "40", "48", "56", "64", "72", "144"
3228 };
3230 GtkWidget *cbox = gtk_combo_box_entry_new_text ();
3231 for (unsigned int n = 0; n < G_N_ELEMENTS (sizes); gtk_combo_box_append_text (GTK_COMBO_BOX(cbox), sizes[n++]));
3232 gtk_widget_set_size_request (cbox, 80, -1);
3233 aux_toolbox_space (tbl, 1);
3234 gtk_box_pack_start (GTK_BOX (tbl), cbox, FALSE, FALSE, 0);
3235 g_object_set_data (G_OBJECT (tbl), "combo-box-size", cbox);
3236 g_signal_connect (G_OBJECT (cbox), "changed", G_CALLBACK (sp_text_toolbox_size_changed), tbl);
3238 ////////////Text anchor
3239 //Label
3240 label = gtk_label_new (_("Alignment:"));
3241 aux_toolbox_space (tbl, 2);
3242 gtk_box_pack_start (GTK_BOX (tbl), label, FALSE, FALSE, 0);
3243 aux_toolbox_space (tbl, 1);
3245 GtkWidget *group = gtk_radio_button_new (NULL);
3246 GtkWidget *row = gtk_hbox_new (FALSE, 4);
3247 g_object_set_data (G_OBJECT (tbl), "anchor-group", group);
3249 // align left
3250 GtkWidget *rbutton = group;
3251 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3252 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_LEFT, GTK_ICON_SIZE_SMALL_TOOLBAR));
3253 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3255 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3256 g_object_set_data (G_OBJECT (tbl), "text-anchor-start", rbutton);
3257 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer(0));
3260 // align center
3261 rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3262 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3263 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_CENTER, GTK_ICON_SIZE_SMALL_TOOLBAR));
3264 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3266 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3267 g_object_set_data (G_OBJECT (tbl), "text-anchor-middle", rbutton);
3268 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer (1));
3270 // align right
3271 rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3272 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3273 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_RIGHT, GTK_ICON_SIZE_SMALL_TOOLBAR));
3274 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3276 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3277 g_object_set_data (G_OBJECT (tbl), "text-anchor-end", rbutton);
3278 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer(2));
3280 aux_toolbox_space (tbl, 1);
3281 gtk_box_pack_start (GTK_BOX (tbl), row, FALSE, FALSE, 4);
3283 #if 0
3284 //Font Style
3285 cbox = gtk_combo_box_new_text ();
3286 gtk_combo_box_append_text (GTK_COMBO_BOX (cbox), _("Normal"));
3287 gtk_combo_box_append_text (GTK_COMBO_BOX (cbox), _("Italic"));
3288 gtk_combo_box_append_text (GTK_COMBO_BOX (cbox), _("Oblique"));
3289 gtk_widget_set_size_request (cbox, 144, -1);
3290 aux_toolbox_space (tbl, 1);
3291 gtk_box_pack_start (GTK_BOX (tbl), cbox, FALSE, FALSE, 0);
3292 g_object_set_data (G_OBJECT (tbl), "combo-box-style", cbox);
3293 g_signal_connect (G_OBJECT (cbox), "changed", G_CALLBACK (sp_text_toolbox_style_changed), tbl);
3294 #endif
3296 Inkscape::ConnectionPool* pool = Inkscape::ConnectionPool::new_connection_pool ("ISTextToolbox");
3298 sigc::connection *c_selection_changed =
3299 new sigc::connection (sp_desktop_selection (desktop)->connectChanged
3300 (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_changed), (GObject*)tbl)));
3301 pool->add_connection ("selection-changed", c_selection_changed);
3303 sigc::connection *c_selection_modified =
3304 new sigc::connection (sp_desktop_selection (desktop)->connectModified
3305 (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_modified), (GObject*)tbl)));
3306 pool->add_connection ("selection-modified", c_selection_modified);
3308 sigc::connection *c_subselection_changed =
3309 new sigc::connection (desktop->connectToolSubselectionChanged
3310 (sigc::bind (sigc::ptr_fun (sp_text_toolbox_subselection_changed), (GObject*)tbl)));
3311 pool->add_connection ("tool-subselection-changed", c_subselection_changed);
3313 Inkscape::ConnectionPool::connect_destroy (G_OBJECT (tbl), pool);
3316 #if 0
3317 //Font Size
3318 GtkWidget *cbox = gtk_combo_box_entry_new ();
3319 aux_toolbox_space(tbl, 1);
3320 gtk_box_pack_start (GTK_BOX (tbl), c, FALSE, FALSE, 0);
3322 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
3323 //Bold
3324 {
3325 GtkWidget *px = gtk_image_new_from_stock(GTK_STOCK_BOLD, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
3326 GtkWidget *button = gtk_toggle_button_new ();
3327 gtk_container_add (GTK_CONTAINER (button), px);
3328 gtk_widget_show(button);
3329 gtk_tooltips_set_tip (tt, button, _("Bold"), NULL);
3330 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
3331 gtk_widget_set_sensitive(button, TRUE);
3332 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
3333 }
3336 //Italic
3337 {
3338 GtkWidget *px = gtk_image_new_from_stock(GTK_STOCK_ITALIC, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
3339 GtkWidget *button = gtk_toggle_button_new ();
3340 gtk_container_add (GTK_CONTAINER (button), px);
3341 gtk_widget_show(button);
3342 gtk_tooltips_set_tip (tt, button, _("Italics"), NULL);
3343 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
3344 gtk_widget_set_sensitive(button, TRUE);
3345 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
3346 }
3348 //Underline
3349 {
3350 GtkWidget *px = gtk_image_new_from_stock(GTK_STOCK_UNDERLINE, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
3351 GtkWidget *button = gtk_toggle_button_new ();
3352 gtk_container_add (GTK_CONTAINER (button), px);
3353 gtk_widget_show(button);
3354 gtk_tooltips_set_tip (tt, button, _("Underline"), NULL);
3355 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
3356 gtk_widget_set_sensitive(button, FALSE);
3357 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
3358 }
3360 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
3361 // align left
3362 {
3363 GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_LEFT, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
3364 GtkWidget *b = group = gtk_radio_button_new (NULL);
3365 gtk_container_add (GTK_CONTAINER (b), px);
3366 gtk_tooltips_set_tip (tt, b, _("Align lines left"), NULL);
3367 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
3368 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
3369 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
3370 }
3372 // align center
3373 {
3374 GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_CENTER, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
3375 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3376 gtk_container_add (GTK_CONTAINER (b), px);
3377 // TRANSLATORS: `Center' here is a verb.
3378 gtk_tooltips_set_tip (tt, b, _("Center lines"), NULL);
3379 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
3380 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
3381 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
3382 }
3384 // align right
3385 {
3386 GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_RIGHT, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
3387 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3388 gtk_container_add (GTK_CONTAINER (b), px);
3389 gtk_tooltips_set_tip (tt, b, _("Align lines right"), NULL);
3390 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
3391 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
3392 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
3393 }
3395 // full justification
3396 {
3397 GtkWidget *px = gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_FILL, Inkscape::ICON_SIZE_SMALL_TOOLBAR);
3398 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3399 gtk_container_add (GTK_CONTAINER (b), px);
3400 gtk_tooltips_set_tip (tt, b, _("Full justification"), NULL);
3401 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
3402 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
3403 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
3404 }
3407 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
3409 // horizontal
3410 {
3411 GtkWidget *px= sp_icon_new(Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_LR);
3412 GtkWidget *b = group = gtk_radio_button_new (NULL);
3413 gtk_container_add (GTK_CONTAINER (b), px);
3414 gtk_tooltips_set_tip (tt, b, _("Horizontal text"), NULL);
3415 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
3416 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
3417 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
3418 }
3420 // vertical
3421 {
3422 GtkWidget *px = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_TB);
3423 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3424 gtk_container_add (GTK_CONTAINER (b), px);
3425 gtk_tooltips_set_tip (tt, b, _("Vertical text"), NULL);
3426 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
3427 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
3428 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
3429 }
3431 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
3433 // letter spacing
3434 {
3435 {
3436 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LETTER_SPACING);
3437 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3438 gtk_container_add (GTK_CONTAINER (hb), image);
3439 gtk_widget_show(image);
3440 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3441 }
3443 {
3444 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Spacing between letters"),
3445 "tools.text", "letter_spacing", 0.0,
3446 us, tbl, FALSE, NULL,
3447 -1000.0, 1000.0, 0.1, 0.1,
3448 sp_text_letter_changed, 0.1, 1);
3449 gtk_widget_set_size_request (hb, 45, 6);
3450 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
3451 }
3452 }
3454 // line spacing
3455 {
3456 {
3457 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LINE_SPACING);
3458 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3459 gtk_container_add (GTK_CONTAINER (hb), image);
3460 gtk_widget_show(image);
3461 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3462 }
3464 {
3465 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Spacing between lines"),
3466 "tools.text", "line_spacing", 0,
3467 us, tbl, FALSE, NULL,
3468 -1000.0, 1000.0, 0.1, 0.1,
3469 sp_text_line_changed, 0.1, 1);
3470 gtk_widget_set_size_request (hb, 45, 0);
3471 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 3);
3472 }
3473 }
3475 {
3476 // horizontal kerning/vertical kerning units menu: create
3477 GtkWidget *us = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
3478 sp_unit_selector_setsize(us, AUX_OPTION_MENU_WIDTH, AUX_OPTION_MENU_HEIGHT);
3479 sp_unit_selector_set_unit(SP_UNIT_SELECTOR(us), desktop->namedview->doc_units);
3481 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
3483 // horizontal kerning
3484 {
3485 {
3486 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_HORZ_KERN);
3487 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3488 gtk_container_add (GTK_CONTAINER (hb), image);
3489 gtk_widget_show(image);
3490 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3491 }
3493 {
3494 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Horizontal kerning"),
3495 "tools.text", "horizontal_kerning", 0,
3496 us, tbl, FALSE, NULL,
3497 -100.00, 100.00, 0.01, 0.1,
3498 sp_text_horiz_kern_changed);
3499 gtk_widget_set_size_request (hb, 45, 0);
3500 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
3501 }
3502 }
3504 // vertical kerning
3505 {
3506 {
3507 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_VERT_KERN);
3508 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3509 gtk_container_add (GTK_CONTAINER (hb), image);
3510 gtk_widget_show(image);
3511 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3512 }
3514 {
3515 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Vertical kerning"),
3516 "tools.text", "vertical_kerning", 0,
3517 us, tbl, FALSE, NULL,
3518 -100.00, 100.00, 0.01, 0.1,
3519 sp_text_vert_kern_changed);
3520 gtk_widget_set_size_request (hb, 45, 0);
3521 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 5);
3522 }
3523 }
3525 // add the units menu
3526 gtk_widget_show(us);
3527 gtk_box_pack_start(GTK_BOX(tbl), us, FALSE, FALSE, 1);
3528 gtk_object_set_data(GTK_OBJECT(tbl), "units", us);
3529 }
3531 // letter rotation
3532 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
3533 {
3534 {
3535 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_ROTATION);
3536 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3537 gtk_container_add (GTK_CONTAINER (hb), image);
3538 gtk_widget_show(image);
3539 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
3540 }
3541 {
3542 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Letter rotation"),
3543 "tools.text", "letter_rotation", 0,
3544 us, tbl, FALSE, NULL,
3545 -180.0, 180.0, 0.1, 0.1,
3546 sp_text_letter_rotation_changed, 0.1, 1);
3547 gtk_widget_set_size_request (hb, 45, 0);
3548 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
3549 }
3550 // rotation degree label
3551 {
3552 GtkWidget *label = gtk_widget_new (GTK_TYPE_LABEL, "label", "\302\260", "xalign", 0.0, NULL);
3553 gtk_box_pack_start(GTK_BOX(tbl), label, FALSE, FALSE, 0);
3554 }
3555 }
3557 // Remove Manual Kerns
3558 {
3559 GtkWidget *px = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_REMOVE_KERNS);
3560 GtkWidget *button = gtk_button_new ();
3561 gtk_container_add (GTK_CONTAINER (button), px);
3562 gtk_widget_show(button);
3563 gtk_tooltips_set_tip (tt, button, _("Remove manual kerns"), NULL);
3564 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
3565 gtk_widget_set_sensitive(button, TRUE);
3566 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
3567 }
3568 #endif
3570 gtk_widget_show_all (tbl);
3571 return tbl;
3573 } // end of sp_text_toolbox_new()
3575 }//<unnamed> namespace
3578 //#########################
3579 //## Connector Toolbox ##
3580 //#########################
3582 static void sp_connector_path_set_avoid(void)
3583 {
3584 cc_selection_set_avoid(true);
3585 }
3588 static void sp_connector_path_set_ignore(void)
3589 {
3590 cc_selection_set_avoid(false);
3591 }
3594 static void connector_spacing_changed(GtkAdjustment *adj, GtkWidget *tbl)
3595 {
3596 // quit if run by the _changed callbacks
3597 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
3598 return;
3599 }
3601 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl),
3602 "desktop");
3603 SPDocument *doc = sp_desktop_document(desktop);
3605 if (!sp_document_get_undo_sensitive(doc))
3606 {
3607 return;
3608 }
3610 // in turn, prevent callbacks from responding
3611 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
3613 Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
3615 sp_repr_set_css_double(repr, "inkscape:connector-spacing", adj->value);
3616 SP_OBJECT(desktop->namedview)->updateRepr();
3618 GSList *items = get_avoided_items(NULL, desktop->currentRoot(), desktop);
3619 for ( GSList const *iter = items ; iter != NULL ; iter = iter->next ) {
3620 SPItem *item = reinterpret_cast<SPItem *>(iter->data);
3621 NR::Matrix m = NR::identity();
3622 avoid_item_move(&m, item);
3623 }
3625 if (items) {
3626 g_slist_free(items);
3627 }
3629 sp_document_done(doc);
3631 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
3633 spinbutton_defocus(GTK_OBJECT(tbl));
3634 }
3637 static void connector_tb_event_attr_changed(Inkscape::XML::Node *repr,
3638 gchar const *name, gchar const *old_value, gchar const *new_value,
3639 bool is_interactive, gpointer data)
3640 {
3641 GtkWidget *tbl = GTK_WIDGET(data);
3643 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
3644 return;
3645 }
3646 if (strcmp(name, "inkscape:connector-spacing") != 0) {
3647 return;
3648 }
3650 GtkAdjustment *adj = (GtkAdjustment*)
3651 gtk_object_get_data(GTK_OBJECT(tbl), "spacing");
3652 gdouble spacing = defaultConnSpacing;
3653 sp_repr_get_double(repr, "inkscape:connector-spacing", &spacing);
3655 gtk_adjustment_set_value(adj, spacing);
3656 }
3659 static Inkscape::XML::NodeEventVector connector_tb_repr_events = {
3660 NULL, /* child_added */
3661 NULL, /* child_removed */
3662 connector_tb_event_attr_changed,
3663 NULL, /* content_changed */
3664 NULL /* order_changed */
3665 };
3668 static GtkWidget *
3669 sp_connector_toolbox_new(SPDesktop *desktop)
3670 {
3671 GtkTooltips *tt = gtk_tooltips_new();
3672 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
3674 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
3675 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
3677 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
3678 AUX_BETWEEN_BUTTON_GROUPS);
3680 sp_toolbox_button_new(tbl, Inkscape::ICON_SIZE_SMALL_TOOLBAR,
3681 "connector_avoid", GTK_SIGNAL_FUNC(sp_connector_path_set_avoid),
3682 tt, _("Make connectors avoid selected objects"));
3684 sp_toolbox_button_new(tbl, Inkscape::ICON_SIZE_SMALL_TOOLBAR,
3685 "connector_ignore", GTK_SIGNAL_FUNC(sp_connector_path_set_ignore),
3686 tt, _("Make connectors ignore selected objects"));
3688 // interval
3689 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
3690 AUX_BETWEEN_BUTTON_GROUPS);
3692 // Spacing spinbox
3693 {
3694 GtkWidget *object_spacing = sp_tb_spinbutton(_("Spacing:"),
3695 _("The amount of space left around objects by auto-routing connectors"),
3696 "tools.connector", "spacing", 10, NULL, tbl, TRUE,
3697 "inkscape:connector-spacing", 0, 100, 1.0, 10.0,
3698 connector_spacing_changed, 1, 0);
3700 gtk_box_pack_start(GTK_BOX(tbl), object_spacing, FALSE, FALSE,
3701 AUX_SPACING);
3702 }
3704 gtk_widget_show_all(tbl);
3705 sp_set_font_size_smaller (tbl);
3707 // Code to watch for changes to the connector-spacing attribute in
3708 // the XML.
3709 Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
3710 g_assert(repr != NULL);
3712 Inkscape::XML::Node *oldrepr = (Inkscape::XML::Node *)
3713 gtk_object_get_data(GTK_OBJECT(tbl), "repr");
3715 if (oldrepr) { // remove old listener
3716 sp_repr_remove_listener_by_data(oldrepr, tbl);
3717 Inkscape::GC::release(oldrepr);
3718 oldrepr = NULL;
3719 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
3720 }
3722 if (repr) {
3723 g_object_set_data(G_OBJECT(tbl), "repr", repr);
3724 Inkscape::GC::anchor(repr);
3725 sp_repr_add_listener(repr, &connector_tb_repr_events, tbl);
3726 sp_repr_synthesize_events(repr, &connector_tb_repr_events, tbl);
3727 }
3729 return tbl;
3731 } // end of sp_connector_toolbox_new()
3734 /*
3735 Local Variables:
3736 mode:c++
3737 c-file-style:"stroustrup"
3738 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
3739 indent-tabs-mode:nil
3740 fill-column:99
3741 End:
3742 */
3743 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :