3c5d2e4a0486ca6ff04c544f961112d7ab9943e1
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 * Jon A. Cruz <jon@joncruz.org>
19 *
20 * Copyright (C) 2004 David Turner
21 * Copyright (C) 2003 MenTaLguY
22 * Copyright (C) 1999-2006 authors
23 * Copyright (C) 2001-2002 Ximian, Inc.
24 *
25 * Released under GNU GPL, read the file 'COPYING' for more information
26 */
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
32 #include <gtkmm.h>
33 #include <gtk/gtk.h>
34 #include <iostream>
35 #include <sstream>
37 #include "widgets/button.h"
38 #include "widgets/widget-sizes.h"
39 #include "widgets/spw-utilities.h"
40 #include "widgets/spinbutton-events.h"
41 #include "dialogs/text-edit.h"
43 #include "ui/widget/style-swatch.h"
45 #include "prefs-utils.h"
46 #include "verbs.h"
47 #include "sp-namedview.h"
48 #include "desktop.h"
49 #include "desktop-handles.h"
50 #include "nodepath.h"
51 #include "xml/repr.h"
52 #include "xml/node-event-vector.h"
53 #include <glibmm/i18n.h>
54 #include "helper/unit-menu.h"
55 #include "helper/units.h"
57 #include "inkscape.h"
58 #include "conn-avoid-ref.h"
61 #include "select-toolbar.h"
62 #include "gradient-toolbar.h"
64 #include "connector-context.h"
65 #include "sp-rect.h"
66 #include "sp-star.h"
67 #include "sp-spiral.h"
68 #include "sp-ellipse.h"
69 #include "sp-text.h"
70 #include "sp-flowtext.h"
71 #include "style.h"
72 #include "selection.h"
73 #include "document-private.h"
74 #include "desktop-style.h"
75 #include "../libnrtype/font-lister.h"
76 #include "../connection-pool.h"
77 #include "../prefs-utils.h"
78 #include "../inkscape-stock.h"
79 #include "icon.h"
80 #include "graphlayout/graphlayout.h"
82 #include "mod360.h"
84 #include "toolbox.h"
86 #include "flood-context.h"
88 #include "ink-action.h"
89 #include "ege-adjustment-action.h"
90 #include "ege-output-action.h"
91 #include "ege-select-one-action.h"
92 #include "helper/unit-tracker.h"
94 using Inkscape::UnitTracker;
96 typedef void (*SetupFunction)(GtkWidget *toolbox, SPDesktop *desktop);
97 typedef void (*UpdateFunction)(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
99 static GtkWidget *sp_node_toolbox_new(SPDesktop *desktop);
100 static GtkWidget *sp_zoom_toolbox_new(SPDesktop *desktop);
101 static GtkWidget *sp_star_toolbox_new(SPDesktop *desktop);
102 static GtkWidget *sp_arc_toolbox_new(SPDesktop *desktop);
103 static GtkWidget *sp_rect_toolbox_new(SPDesktop *desktop);
104 static GtkWidget *sp_spiral_toolbox_new(SPDesktop *desktop);
105 static GtkWidget *sp_pencil_toolbox_new(SPDesktop *desktop);
106 static GtkWidget *sp_pen_toolbox_new(SPDesktop *desktop);
107 static GtkWidget *sp_calligraphy_toolbox_new(SPDesktop *desktop);
108 static GtkWidget *sp_dropper_toolbox_new(SPDesktop *desktop);
109 static GtkWidget *sp_empty_toolbox_new(SPDesktop *desktop);
110 static GtkWidget *sp_connector_toolbox_new(SPDesktop *desktop);
111 static GtkWidget *sp_paintbucket_toolbox_new(SPDesktop *desktop);
113 namespace { GtkWidget *sp_text_toolbox_new (SPDesktop *desktop); }
116 static struct {
117 gchar const *type_name;
118 gchar const *data_name;
119 sp_verb_t verb;
120 sp_verb_t doubleclick_verb;
121 } const tools[] = {
122 { "SPSelectContext", "select_tool", SP_VERB_CONTEXT_SELECT, SP_VERB_CONTEXT_SELECT_PREFS},
123 { "SPNodeContext", "node_tool", SP_VERB_CONTEXT_NODE, SP_VERB_CONTEXT_NODE_PREFS },
124 { "SPZoomContext", "zoom_tool", SP_VERB_CONTEXT_ZOOM, SP_VERB_CONTEXT_ZOOM_PREFS },
125 { "SPRectContext", "rect_tool", SP_VERB_CONTEXT_RECT, SP_VERB_CONTEXT_RECT_PREFS },
126 { "SPArcContext", "arc_tool", SP_VERB_CONTEXT_ARC, SP_VERB_CONTEXT_ARC_PREFS },
127 { "SPStarContext", "star_tool", SP_VERB_CONTEXT_STAR, SP_VERB_CONTEXT_STAR_PREFS },
128 { "SPSpiralContext", "spiral_tool", SP_VERB_CONTEXT_SPIRAL, SP_VERB_CONTEXT_SPIRAL_PREFS },
129 { "SPPencilContext", "pencil_tool", SP_VERB_CONTEXT_PENCIL, SP_VERB_CONTEXT_PENCIL_PREFS },
130 { "SPPenContext", "pen_tool", SP_VERB_CONTEXT_PEN, SP_VERB_CONTEXT_PEN_PREFS },
131 { "SPDynaDrawContext", "dyna_draw_tool", SP_VERB_CONTEXT_CALLIGRAPHIC, SP_VERB_CONTEXT_CALLIGRAPHIC_PREFS },
132 { "SPFloodContext", "paintbucket_tool", SP_VERB_CONTEXT_PAINTBUCKET, SP_VERB_CONTEXT_PAINTBUCKET_PREFS },
133 { "SPTextContext", "text_tool", SP_VERB_CONTEXT_TEXT, SP_VERB_CONTEXT_TEXT_PREFS },
134 { "SPConnectorContext","connector_tool", SP_VERB_CONTEXT_CONNECTOR, SP_VERB_CONTEXT_CONNECTOR_PREFS },
135 { "SPGradientContext", "gradient_tool", SP_VERB_CONTEXT_GRADIENT, SP_VERB_CONTEXT_GRADIENT_PREFS },
136 { "SPDropperContext", "dropper_tool", SP_VERB_CONTEXT_DROPPER, SP_VERB_CONTEXT_DROPPER_PREFS },
137 { NULL, NULL, 0, 0 }
138 };
140 static struct {
141 gchar const *type_name;
142 gchar const *data_name;
143 GtkWidget *(*create_func)(SPDesktop *desktop);
144 } const aux_toolboxes[] = {
145 { "SPSelectContext", "select_toolbox", sp_select_toolbox_new },
146 { "SPNodeContext", "node_toolbox", sp_node_toolbox_new },
147 { "SPZoomContext", "zoom_toolbox", sp_zoom_toolbox_new },
148 { "SPStarContext", "star_toolbox", sp_star_toolbox_new },
149 { "SPRectContext", "rect_toolbox", sp_rect_toolbox_new },
150 { "SPArcContext", "arc_toolbox", sp_arc_toolbox_new },
151 { "SPSpiralContext", "spiral_toolbox", sp_spiral_toolbox_new },
152 { "SPPencilContext", "pencil_toolbox", sp_pencil_toolbox_new },
153 { "SPPenContext", "pen_toolbox", sp_pen_toolbox_new },
154 { "SPDynaDrawContext", "calligraphy_toolbox", sp_calligraphy_toolbox_new },
155 { "SPTextContext", "text_toolbox", sp_text_toolbox_new },
156 { "SPDropperContext", "dropper_toolbox", sp_dropper_toolbox_new },
157 { "SPGradientContext", "gradient_toolbox", sp_gradient_toolbox_new },
158 { "SPConnectorContext", "connector_toolbox", sp_connector_toolbox_new },
159 { "SPFloodContext", "paintbucket_toolbox", sp_paintbucket_toolbox_new },
160 { NULL, NULL, NULL }
161 };
163 static GtkActionGroup* create_or_fetch_actions( SPDesktop* desktop );
165 static void toolbox_set_desktop (GtkWidget *toolbox, SPDesktop *desktop, SetupFunction setup_func, UpdateFunction update_func, sigc::connection*);
167 static void setup_tool_toolbox (GtkWidget *toolbox, SPDesktop *desktop);
168 static void update_tool_toolbox (SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
170 static void setup_aux_toolbox (GtkWidget *toolbox, SPDesktop *desktop);
171 static void update_aux_toolbox (SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
173 static void setup_commands_toolbox (GtkWidget *toolbox, SPDesktop *desktop);
174 static void update_commands_toolbox (SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
176 /* Global text entry widgets necessary for update */
177 /* GtkWidget *dropper_rgb_entry,
178 *dropper_opacity_entry ; */
179 // should be made a private member once this is converted to class
181 static void delete_connection(GObject *obj, sigc::connection *connection) {
182 connection->disconnect();
183 delete connection;
184 }
186 static GtkWidget *
187 sp_toolbox_button_new(GtkWidget *t, Inkscape::IconSize size, gchar const *pxname, GtkSignalFunc handler,
188 GtkTooltips *tt, gchar const *tip)
189 {
190 GtkWidget *b = sp_button_new_from_data(size, SP_BUTTON_TYPE_NORMAL, NULL, pxname, tip, tt);
191 gtk_widget_show(b);
192 if (handler) gtk_signal_connect(GTK_OBJECT(b), "clicked", handler, NULL);
193 gtk_box_pack_start(GTK_BOX(t), b, FALSE, FALSE, 0);
195 return b;
196 }
198 GtkWidget *
199 sp_toolbox_button_new_from_verb_with_doubleclick(GtkWidget *t, Inkscape::IconSize size, SPButtonType type,
200 Inkscape::Verb *verb, Inkscape::Verb *doubleclick_verb,
201 Inkscape::UI::View::View *view, GtkTooltips *tt)
202 {
203 SPAction *action = verb->get_action(view);
204 if (!action) return NULL;
206 SPAction *doubleclick_action;
207 if (doubleclick_verb)
208 doubleclick_action = doubleclick_verb->get_action(view);
209 else
210 doubleclick_action = NULL;
212 /* fixme: Handle sensitive/unsensitive */
213 /* fixme: Implement sp_button_new_from_action */
214 GtkWidget *b = sp_button_new(size, type, action, doubleclick_action, tt);
215 gtk_widget_show(b);
216 gtk_box_pack_start(GTK_BOX(t), b, FALSE, FALSE, 0);
218 return b;
219 }
221 GtkWidget *sp_toolbox_button_new_from_verb(GtkWidget *t, Inkscape::IconSize size, SPButtonType type, Inkscape::Verb *verb,
222 Inkscape::UI::View::View *view, GtkTooltips *tt)
223 {
224 return sp_toolbox_button_new_from_verb_with_doubleclick(t, size, type, verb, NULL, view, tt);
225 }
227 GtkWidget * sp_toolbox_button_normal_new_from_verb(GtkWidget *t, Inkscape::IconSize size, Inkscape::Verb *verb,
228 Inkscape::UI::View::View *view, GtkTooltips *tt)
229 {
230 return sp_toolbox_button_new_from_verb(t, size, SP_BUTTON_TYPE_NORMAL, verb, view, tt);
231 }
234 static void trigger_sp_action( GtkAction* act, gpointer user_data )
235 {
236 SPAction* targetAction = SP_ACTION(user_data);
237 if ( targetAction ) {
238 sp_action_perform( targetAction, NULL );
239 }
240 }
242 static void sp_action_action_set_sensitive (SPAction *action, unsigned int sensitive, void *data)
243 {
244 if ( data ) {
245 GtkAction* act = GTK_ACTION(data);
246 gtk_action_set_sensitive( act, sensitive );
247 }
248 }
250 static SPActionEventVector action_event_vector = {
251 {NULL},
252 NULL,
253 NULL,
254 sp_action_action_set_sensitive,
255 NULL,
256 NULL
257 };
259 static GtkAction* create_action_for_verb( Inkscape::Verb* verb, Inkscape::UI::View::View* view, Inkscape::IconSize size )
260 {
261 GtkAction* act = 0;
263 SPAction* targetAction = verb->get_action(view);
264 InkAction* inky = ink_action_new( verb->get_id(), verb->get_name(), verb->get_tip(), verb->get_image(), size );
265 act = GTK_ACTION(inky);
266 gtk_action_set_sensitive( act, targetAction->sensitive );
268 g_signal_connect( G_OBJECT(inky), "activate", GTK_SIGNAL_FUNC(trigger_sp_action), targetAction );
270 SPAction*rebound = dynamic_cast<SPAction *>( nr_object_ref( dynamic_cast<NRObject *>(targetAction) ) );
271 nr_active_object_add_listener( (NRActiveObject *)rebound, (NRObjectEventVector *)&action_event_vector, sizeof(SPActionEventVector), inky );
273 return act;
274 }
276 GtkActionGroup* create_or_fetch_actions( SPDesktop* desktop )
277 {
278 Inkscape::UI::View::View *view = desktop;
279 gint verbsToUse[] = {
280 // disabled until we have icons for them:
281 //find
282 //SP_VERB_EDIT_TILE,
283 //SP_VERB_EDIT_UNTILE,
284 SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
285 SP_VERB_DIALOG_DISPLAY,
286 SP_VERB_DIALOG_FILL_STROKE,
287 SP_VERB_DIALOG_NAMEDVIEW,
288 SP_VERB_DIALOG_TEXT,
289 SP_VERB_DIALOG_XML_EDITOR,
290 SP_VERB_EDIT_CLONE,
291 SP_VERB_EDIT_COPY,
292 SP_VERB_EDIT_CUT,
293 SP_VERB_EDIT_DUPLICATE,
294 SP_VERB_EDIT_PASTE,
295 SP_VERB_EDIT_REDO,
296 SP_VERB_EDIT_UNDO,
297 SP_VERB_EDIT_UNLINK_CLONE,
298 SP_VERB_FILE_EXPORT,
299 SP_VERB_FILE_IMPORT,
300 SP_VERB_FILE_NEW,
301 SP_VERB_FILE_OPEN,
302 SP_VERB_FILE_PRINT,
303 SP_VERB_FILE_SAVE,
304 SP_VERB_SELECTION_GROUP,
305 SP_VERB_SELECTION_UNGROUP,
306 SP_VERB_ZOOM_DRAWING,
307 SP_VERB_ZOOM_PAGE,
308 SP_VERB_ZOOM_SELECTION
309 };
311 gint shrinkTop = prefs_get_int_attribute_limited( "toolbox", "small", 1, 0, 1 );
312 Inkscape::IconSize toolboxSize = shrinkTop ? Inkscape::ICON_SIZE_SMALL_TOOLBAR : Inkscape::ICON_SIZE_LARGE_TOOLBAR;
314 static std::map<SPDesktop*, GtkActionGroup*> groups;
315 GtkActionGroup* mainActions = 0;
316 if ( groups.find(desktop) != groups.end() ) {
317 mainActions = groups[desktop];
318 }
320 if ( !mainActions ) {
321 mainActions = gtk_action_group_new("main");
322 groups[desktop] = mainActions;
323 }
325 for ( guint i = 0; i < G_N_ELEMENTS(verbsToUse); i++ ) {
326 Inkscape::Verb* verb = Inkscape::Verb::get(verbsToUse[i]);
327 if ( verb ) {
328 if ( !gtk_action_group_get_action( mainActions, verb->get_id() ) ) {
329 GtkAction* act = create_action_for_verb( verb, view, toolboxSize );
330 gtk_action_group_add_action( mainActions, act );
331 }
332 }
333 }
335 return mainActions;
336 }
339 GtkWidget *
340 sp_tool_toolbox_new()
341 {
342 GtkTooltips *tt = gtk_tooltips_new();
343 GtkWidget *tb = gtk_vbox_new(FALSE, 0);
345 g_object_set_data(G_OBJECT(tb), "desktop", NULL);
346 g_object_set_data(G_OBJECT(tb), "tooltips", tt);
348 gtk_widget_set_sensitive(tb, FALSE);
350 GtkWidget *hb = gtk_handle_box_new();
351 gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), GTK_POS_TOP);
352 gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(hb), GTK_SHADOW_OUT);
353 gtk_handle_box_set_snap_edge(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
355 gtk_container_add(GTK_CONTAINER(hb), tb);
356 gtk_widget_show(GTK_WIDGET(tb));
358 sigc::connection* conn = new sigc::connection;
359 g_object_set_data(G_OBJECT(hb), "event_context_connection", conn);
361 return hb;
362 }
364 static void
365 aux_toolbox_attached(GtkHandleBox *toolbox, GtkWidget *child)
366 {
367 g_object_set_data(G_OBJECT(child), "is_detached", GINT_TO_POINTER(FALSE));
368 gtk_widget_queue_resize(child);
369 }
371 static void
372 aux_toolbox_detached(GtkHandleBox *toolbox, GtkWidget *child)
373 {
374 g_object_set_data(G_OBJECT(child), "is_detached", GINT_TO_POINTER(TRUE));
375 gtk_widget_queue_resize(child);
376 }
378 GtkWidget *
379 sp_aux_toolbox_new()
380 {
381 GtkWidget *tb = gtk_vbox_new(FALSE, 0);
383 GtkWidget *tb_s = gtk_vbox_new(FALSE, 0);
384 GtkWidget *tb_e = gtk_vbox_new(FALSE, 0);
385 gtk_box_set_spacing(GTK_BOX(tb), AUX_SPACING);
386 gtk_box_pack_start(GTK_BOX(tb), GTK_WIDGET(tb_s), FALSE, FALSE, 0);
387 gtk_box_pack_end(GTK_BOX(tb), GTK_WIDGET(tb_e), FALSE, FALSE, 0);
389 g_object_set_data(G_OBJECT(tb), "desktop", NULL);
390 g_object_set_data(G_OBJECT(tb), "top_spacer", tb_s);
392 gtk_widget_set_sensitive(tb, FALSE);
394 GtkWidget *hb = gtk_handle_box_new();
395 gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
396 gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(hb), GTK_SHADOW_OUT);
397 gtk_handle_box_set_snap_edge(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
399 g_signal_connect(G_OBJECT(hb), "child_attached", G_CALLBACK(aux_toolbox_attached), (gpointer)tb);
400 g_signal_connect(G_OBJECT(hb), "child_detached", G_CALLBACK(aux_toolbox_detached), (gpointer)tb);
402 gtk_container_add(GTK_CONTAINER(hb), tb);
403 gtk_widget_show(GTK_WIDGET(tb));
405 sigc::connection* conn = new sigc::connection;
406 g_object_set_data(G_OBJECT(hb), "event_context_connection", conn);
408 return hb;
409 }
411 //####################################
412 //# Commands Bar
413 //####################################
415 GtkWidget *
416 sp_commands_toolbox_new()
417 {
418 GtkWidget *tb = gtk_vbox_new(FALSE, 0);
420 GtkWidget *tb_s = gtk_vbox_new(FALSE, 0);
421 GtkWidget *tb_e = gtk_vbox_new(FALSE, 0);
422 gtk_box_set_spacing(GTK_BOX(tb), AUX_SPACING);
423 gtk_box_pack_start(GTK_BOX(tb), GTK_WIDGET(tb_s), FALSE, FALSE, 0);
424 gtk_box_pack_end(GTK_BOX(tb), GTK_WIDGET(tb_e), FALSE, FALSE, 0);
426 g_object_set_data(G_OBJECT(tb), "desktop", NULL);
427 gtk_widget_set_sensitive(tb, FALSE);
429 GtkWidget *hb = gtk_handle_box_new();
430 gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
431 gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(hb), GTK_SHADOW_OUT);
432 gtk_handle_box_set_snap_edge(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
434 g_signal_connect(G_OBJECT(hb), "child_attached", G_CALLBACK(aux_toolbox_attached), (gpointer)tb);
435 g_signal_connect(G_OBJECT(hb), "child_detached", G_CALLBACK(aux_toolbox_detached), (gpointer)tb);
437 gtk_container_add(GTK_CONTAINER(hb), tb);
438 gtk_widget_show(GTK_WIDGET(tb));
440 sigc::connection* conn = new sigc::connection;
441 g_object_set_data(G_OBJECT(hb), "event_context_connection", conn);
443 return hb;
444 }
447 //####################################
448 //# node editing callbacks
449 //####################################
451 void
452 sp_node_path_edit_add(void)
453 {
454 sp_node_selected_add_node();
455 }
457 void
458 sp_node_path_edit_delete(void)
459 {
460 sp_node_selected_delete();
461 }
463 void
464 sp_node_path_edit_delete_segment(void)
465 {
466 sp_node_selected_delete_segment();
467 }
469 void
470 sp_node_path_edit_break(void)
471 {
472 sp_node_selected_break();
473 }
475 void
476 sp_node_path_edit_join(void)
477 {
478 sp_node_selected_join();
479 }
481 void
482 sp_node_path_edit_join_segment(void)
483 {
484 sp_node_selected_join_segment();
485 }
487 void
488 sp_node_path_edit_toline(void)
489 {
490 sp_node_selected_set_line_type(NR_LINETO);
491 }
493 void
494 sp_node_path_edit_tocurve(void)
495 {
496 sp_node_selected_set_line_type(NR_CURVETO);
497 }
499 void
500 sp_node_path_edit_cusp(void)
501 {
502 sp_node_selected_set_type(Inkscape::NodePath::NODE_CUSP);
503 }
505 void
506 sp_node_path_edit_smooth(void)
507 {
508 sp_node_selected_set_type(Inkscape::NodePath::NODE_SMOOTH);
509 }
511 void
512 sp_node_path_edit_symmetrical(void)
513 {
514 sp_node_selected_set_type(Inkscape::NodePath::NODE_SYMM);
515 }
517 static void toggle_show_handles (GtkWidget *button, gpointer data) {
518 bool show = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
519 prefs_set_int_attribute ("tools.nodes", "show_handles", show ? 1 : 0);
520 sp_nodepath_show_handles(show);
521 }
523 //################################
524 //## Node Editing Toolbox ##
525 //################################
527 static GtkWidget *
528 sp_node_toolbox_new(SPDesktop *desktop)
529 {
530 Inkscape::UI::View::View *view = desktop;
532 GtkTooltips *tt = gtk_tooltips_new();
533 GtkWidget *tb = gtk_hbox_new(FALSE, 0);
535 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
537 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_insert",
538 GTK_SIGNAL_FUNC(sp_node_path_edit_add), tt, _("Insert new nodes into selected segments"));
539 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_delete",
540 GTK_SIGNAL_FUNC(sp_node_path_edit_delete), tt, _("Delete selected nodes"));
542 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
544 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_join",
545 GTK_SIGNAL_FUNC(sp_node_path_edit_join), tt, _("Join selected endnodes"));
546 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_join_segment",
547 GTK_SIGNAL_FUNC(sp_node_path_edit_join_segment), tt, _("Join selected endnodes with a new segment"));
549 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_delete_segment",
550 GTK_SIGNAL_FUNC(sp_node_path_edit_delete_segment), tt, _("Split path between two non-endpoint nodes"));
552 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_break",
553 GTK_SIGNAL_FUNC(sp_node_path_edit_break), tt, _("Break path at selected nodes"));
555 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
557 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_cusp",
558 GTK_SIGNAL_FUNC(sp_node_path_edit_cusp), tt, _("Make selected nodes corner"));
560 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_smooth",
561 GTK_SIGNAL_FUNC(sp_node_path_edit_smooth), tt, _("Make selected nodes smooth"));
563 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_symmetric",
564 GTK_SIGNAL_FUNC(sp_node_path_edit_symmetrical), tt, _("Make selected nodes symmetric"));
566 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
568 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_line",
569 GTK_SIGNAL_FUNC(sp_node_path_edit_toline), tt, _("Make selected segments lines"));
571 sp_toolbox_button_new(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, "node_curve",
572 GTK_SIGNAL_FUNC(sp_node_path_edit_tocurve), tt, _("Make selected segments curves"));
574 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
576 sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_OBJECT_TO_CURVE), view, tt);
578 sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_SELECTION_OUTLINE), view, tt);
580 aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS);
582 GtkWidget *cvbox = gtk_vbox_new (FALSE, 0);
583 GtkWidget *cbox = gtk_hbox_new (FALSE, 0);
585 {
586 GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
587 SP_BUTTON_TYPE_TOGGLE,
588 NULL,
589 "nodes_show_handles",
590 _("Show the Bezier handles of selected nodes"),
591 tt);
592 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("tools.nodes", "show_handles", 1));
593 g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (toggle_show_handles), desktop);
594 gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
595 }
597 gtk_box_pack_start(GTK_BOX(cvbox), cbox, TRUE, FALSE, 0);
598 gtk_box_pack_start(GTK_BOX(tb), cvbox, FALSE, FALSE, 0);
600 gtk_widget_show_all(tb);
602 return tb;
604 } // end of sp_node_toolbox_new()
607 //########################
608 //## Zoom Toolbox ##
609 //########################
611 static GtkWidget *
612 sp_zoom_toolbox_new(SPDesktop *desktop)
613 {
614 Inkscape::UI::View::View *view=desktop;
616 GtkTooltips *tt = gtk_tooltips_new();
617 GtkWidget *tb = gtk_hbox_new(FALSE, 0);
619 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0),
620 FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
622 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);
624 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);
626 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
628 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);
630 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);
632 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);
634 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);
636 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
638 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);
640 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);
642 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
644 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);
646 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);
648 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);
650 gtk_widget_show_all(tb);
652 return tb;
654 } // end of sp_zoom_toolbox_new()
656 void
657 sp_tool_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
658 {
659 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")));
660 }
663 void
664 sp_aux_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
665 {
666 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")));
667 }
669 void
670 sp_commands_toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop)
671 {
672 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")));
673 }
675 static void
676 toolbox_set_desktop(GtkWidget *toolbox, SPDesktop *desktop, SetupFunction setup_func, UpdateFunction update_func, sigc::connection *conn)
677 {
678 gpointer ptr = g_object_get_data(G_OBJECT(toolbox), "desktop");
679 SPDesktop *old_desktop = static_cast<SPDesktop*>(ptr);
681 if (old_desktop) {
682 GList *children, *iter;
684 children = gtk_container_get_children(GTK_CONTAINER(toolbox));
685 for ( iter = children ; iter ; iter = iter->next ) {
686 gtk_container_remove( GTK_CONTAINER(toolbox), GTK_WIDGET(iter->data) );
687 }
688 g_list_free(children);
689 }
691 g_object_set_data(G_OBJECT(toolbox), "desktop", (gpointer)desktop);
693 if (desktop) {
694 gtk_widget_set_sensitive(toolbox, TRUE);
695 setup_func(toolbox, desktop);
696 update_func(desktop, desktop->event_context, toolbox);
697 *conn = desktop->connectEventContextChanged
698 (sigc::bind (sigc::ptr_fun(update_func), toolbox));
699 } else {
700 gtk_widget_set_sensitive(toolbox, FALSE);
701 }
703 } // end of toolbox_set_desktop()
706 static void
707 setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
708 {
709 GtkTooltips *tooltips=GTK_TOOLTIPS(g_object_get_data(G_OBJECT(toolbox), "tooltips"));
710 gint shrinkLeft = prefs_get_int_attribute_limited( "toolbox.left", "small", 0, 0, 1 );
711 Inkscape::IconSize toolboxSize = shrinkLeft ? Inkscape::ICON_SIZE_SMALL_TOOLBAR : Inkscape::ICON_SIZE_LARGE_TOOLBAR;
713 for (int i = 0 ; tools[i].type_name ; i++ ) {
714 GtkWidget *button =
715 sp_toolbox_button_new_from_verb_with_doubleclick( toolbox, toolboxSize,
716 SP_BUTTON_TYPE_TOGGLE,
717 Inkscape::Verb::get(tools[i].verb),
718 Inkscape::Verb::get(tools[i].doubleclick_verb),
719 desktop,
720 tooltips );
722 g_object_set_data( G_OBJECT(toolbox), tools[i].data_name,
723 (gpointer)button );
724 }
725 }
728 static void
729 update_tool_toolbox( SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox )
730 {
731 gchar const *const tname = ( eventcontext
732 ? gtk_type_name(GTK_OBJECT_TYPE(eventcontext))
733 : NULL );
734 for (int i = 0 ; tools[i].type_name ; i++ ) {
735 SPButton *button = SP_BUTTON(g_object_get_data(G_OBJECT(toolbox), tools[i].data_name));
736 sp_button_toggle_set_down(button, tname && !strcmp(tname, tools[i].type_name));
737 }
738 }
740 static void
741 setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
742 {
743 GtkSizeGroup* grouper = gtk_size_group_new( GTK_SIZE_GROUP_BOTH );
745 for (int i = 0 ; aux_toolboxes[i].type_name ; i++ ) {
746 GtkWidget *sub_toolbox;
747 if (aux_toolboxes[i].create_func == NULL)
748 sub_toolbox = sp_empty_toolbox_new(desktop);
749 else
750 sub_toolbox = aux_toolboxes[i].create_func(desktop);
752 gtk_size_group_add_widget( grouper, sub_toolbox );
754 gtk_container_add(GTK_CONTAINER(toolbox), sub_toolbox);
755 g_object_set_data(G_OBJECT(toolbox), aux_toolboxes[i].data_name, sub_toolbox);
756 }
757 g_object_unref( G_OBJECT(grouper) );
758 }
760 static void
761 update_aux_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox)
762 {
763 gchar const *tname = ( eventcontext
764 ? gtk_type_name(GTK_OBJECT_TYPE(eventcontext))
765 : NULL );
766 for (int i = 0 ; aux_toolboxes[i].type_name ; i++ ) {
767 GtkWidget *sub_toolbox = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), aux_toolboxes[i].data_name));
768 if (tname && !strcmp(tname, aux_toolboxes[i].type_name)) {
769 gtk_widget_show_all(sub_toolbox);
770 g_object_set_data(G_OBJECT(toolbox), "shows", sub_toolbox);
771 } else {
772 gtk_widget_hide(sub_toolbox);
773 }
774 }
775 }
777 static void
778 setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
779 {
780 gchar const * descr =
781 "<ui>"
782 " <toolbar name='CommandsToolbar'>"
783 " <toolitem action='FileNew' />"
784 " <toolitem action='FileOpen' />"
785 " <toolitem action='FileSave' />"
786 " <toolitem action='FilePrint' />"
787 " <separator />"
788 " <toolitem action='FileImport' />"
789 " <toolitem action='FileExport' />"
790 " <separator />"
791 " <toolitem action='EditUndo' />"
792 " <toolitem action='EditRedo' />"
793 " <separator />"
794 " <toolitem action='EditCopy' />"
795 " <toolitem action='EditCut' />"
796 " <toolitem action='EditPaste' />"
797 " <separator />"
798 " <toolitem action='ZoomSelection' />"
799 " <toolitem action='ZoomDrawing' />"
800 " <toolitem action='ZoomPage' />"
801 " <separator />"
802 " <toolitem action='EditDuplicate' />"
803 " <toolitem action='EditClone' />"
804 " <toolitem action='EditUnlinkClone' />"
805 " <separator />"
806 " <toolitem action='SelectionGroup' />"
807 " <toolitem action='SelectionUnGroup' />"
808 " <separator />"
809 " <toolitem action='DialogFillStroke' />"
810 " <toolitem action='DialogText' />"
811 " <toolitem action='DialogXMLEditor' />"
812 " <toolitem action='DialogAlignDistribute' />"
813 " <separator />"
814 " <toolitem action='DialogPreferences' />"
815 " <toolitem action='DialogDocumentProperties' />"
816 " </toolbar>"
817 "</ui>";
818 GtkActionGroup* mainActions = create_or_fetch_actions( desktop );
821 GtkUIManager* mgr = gtk_ui_manager_new();
822 GError* errVal = 0;
824 gtk_ui_manager_insert_action_group( mgr, mainActions, 0 );
825 gtk_ui_manager_add_ui_from_string( mgr, descr, -1, &errVal );
827 GtkWidget* toolBar = gtk_ui_manager_get_widget( mgr, "/ui/CommandsToolbar" );
828 gtk_toolbar_set_style( GTK_TOOLBAR(toolBar), GTK_TOOLBAR_ICONS );
829 gint shrinkTop = prefs_get_int_attribute_limited( "toolbox", "small", 1, 0, 1 );
830 Inkscape::IconSize toolboxSize = shrinkTop ? Inkscape::ICON_SIZE_SMALL_TOOLBAR : Inkscape::ICON_SIZE_LARGE_TOOLBAR;
831 gtk_toolbar_set_icon_size( GTK_TOOLBAR(toolBar), (GtkIconSize)toolboxSize );
834 gtk_container_add( GTK_CONTAINER(toolbox), toolBar );
835 }
837 static void
838 update_commands_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox)
839 {
840 }
842 void show_aux_toolbox(GtkWidget *toolbox_toplevel)
843 {
844 gtk_widget_show(toolbox_toplevel);
845 GtkWidget *toolbox = gtk_bin_get_child(GTK_BIN(toolbox_toplevel));
847 GtkWidget *shown_toolbox = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), "shows"));
848 if (!shown_toolbox) {
849 return;
850 }
851 gtk_widget_show(toolbox);
853 // need to show the spacer, or the padding will be off
854 GtkWidget *spacer = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), "top_spacer"));
855 gtk_widget_show(spacer);
857 gtk_widget_show_all(shown_toolbox);
858 }
860 void
861 aux_toolbox_space(GtkWidget *tb, gint space)
862 {
863 gtk_box_pack_start(GTK_BOX(tb), gtk_hbox_new(FALSE, 0), FALSE, FALSE, space);
864 }
866 static GtkWidget *
867 sp_empty_toolbox_new(SPDesktop *desktop)
868 {
869 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
870 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
871 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
873 gtk_widget_show_all(tbl);
874 sp_set_font_size_smaller (tbl);
876 return tbl;
877 }
879 // helper UI functions
881 GtkWidget *
882 sp_tb_spinbutton(
883 gchar *label, gchar const *tooltip,
884 gchar const *path, gchar const *data, gdouble def,
885 GtkWidget *us,
886 GtkWidget *tbl,
887 gboolean altx, gchar const *altx_mark,
888 gdouble lower, gdouble upper, gdouble step, gdouble page,
889 void (*callback)(GtkAdjustment *, GtkWidget *),
890 gdouble climb = 0.1, guint digits = 3, double factor = 1.0)
891 {
892 GtkTooltips *tt = gtk_tooltips_new();
894 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
896 GtkWidget *l = gtk_label_new(label);
897 gtk_widget_show(l);
898 gtk_misc_set_alignment(GTK_MISC(l), 1.0, 0.5);
899 gtk_container_add(GTK_CONTAINER(hb), l);
901 GtkObject *a = gtk_adjustment_new(prefs_get_double_attribute(path, data, def) * factor,
902 lower, upper, step, page, page);
903 gtk_object_set_data(GTK_OBJECT(tbl), data, a);
904 if (us)
905 sp_unit_selector_add_adjustment(SP_UNIT_SELECTOR(us), GTK_ADJUSTMENT(a));
907 GtkWidget *sb = gtk_spin_button_new(GTK_ADJUSTMENT(a), climb, digits);
908 gtk_tooltips_set_tip(tt, sb, tooltip, NULL);
909 if (altx)
910 gtk_object_set_data(GTK_OBJECT(sb), altx_mark, sb);
911 gtk_widget_set_size_request(sb,
912 (upper <= 1.0 || digits == 0)? AUX_SPINBUTTON_WIDTH_SMALL - 10: AUX_SPINBUTTON_WIDTH_SMALL,
913 AUX_SPINBUTTON_HEIGHT);
914 gtk_widget_show(sb);
915 gtk_signal_connect(GTK_OBJECT(sb), "focus-in-event", GTK_SIGNAL_FUNC(spinbutton_focus_in), tbl);
916 gtk_signal_connect(GTK_OBJECT(sb), "key-press-event", GTK_SIGNAL_FUNC(spinbutton_keypress), tbl);
917 gtk_container_add(GTK_CONTAINER(hb), sb);
918 gtk_signal_connect(GTK_OBJECT(a), "value_changed", GTK_SIGNAL_FUNC(callback), tbl);
920 return hb;
921 }
923 static EgeAdjustmentAction * create_adjustment_action( gchar const *name,
924 gchar const *label, gchar const *tooltip,
925 gchar const *path, gchar const *data, gdouble def,
926 GtkWidget *focusTarget,
927 GtkWidget *us,
928 GtkWidget *dataKludge,
929 gboolean altx, gchar const *altx_mark,
930 gdouble lower, gdouble upper, gdouble step, gdouble page,
931 gchar const** descrLabels, gdouble const* descrValues, guint descrCount,
932 void (*callback)(GtkAdjustment *, GtkWidget *),
933 gdouble climb = 0.1, guint digits = 3, double factor = 1.0 )
934 {
935 GtkAdjustment* adj = GTK_ADJUSTMENT( gtk_adjustment_new( prefs_get_double_attribute(path, data, def) * factor,
936 lower, upper, step, page, page ) );
937 if (us) {
938 sp_unit_selector_add_adjustment( SP_UNIT_SELECTOR(us), adj );
939 }
941 gtk_signal_connect( GTK_OBJECT(adj), "value-changed", GTK_SIGNAL_FUNC(callback), dataKludge );
943 EgeAdjustmentAction* act = ege_adjustment_action_new( adj, name, label, tooltip, 0, climb, digits );
945 if ( (descrCount > 0) && descrLabels && descrValues ) {
946 ege_adjustment_action_set_descriptions( act, descrLabels, descrValues, descrCount );
947 }
949 if ( focusTarget ) {
950 ege_adjustment_action_set_focuswidget( act, focusTarget );
951 }
953 if ( altx && altx_mark ) {
954 g_object_set( G_OBJECT(act), "self-id", altx_mark, NULL );
955 }
957 if ( dataKludge ) {
958 gtk_object_set_data( GTK_OBJECT(dataKludge), data, adj );
959 }
961 // Using a cast just to make sure we pass in the right kind of function pointer
962 g_object_set( G_OBJECT(act), "tool-post", static_cast<EgeWidgetFixup>(sp_set_font_size_smaller), NULL );
964 return act;
965 }
968 #define MODE_LABEL_WIDTH 70
970 //########################
971 //## Star ##
972 //########################
974 static void sp_stb_magnitude_value_changed( GtkAdjustment *adj, GtkWidget *dataKludge )
975 {
976 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(dataKludge), "desktop");
978 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
979 // do not remember prefs if this call is initiated by an undo change, because undoing object
980 // creation sets bogus values to its attributes before it is deleted
981 prefs_set_int_attribute("tools.shapes.star", "magnitude", (gint)adj->value);
982 }
984 // quit if run by the attr_changed listener
985 if (g_object_get_data(G_OBJECT(dataKludge), "freeze")) {
986 return;
987 }
989 // in turn, prevent listener from responding
990 g_object_set_data(G_OBJECT(dataKludge), "freeze", GINT_TO_POINTER(TRUE));
992 bool modmade = false;
994 Inkscape::Selection *selection = sp_desktop_selection(desktop);
995 GSList const *items = selection->itemList();
996 for (; items != NULL; items = items->next) {
997 if (SP_IS_STAR((SPItem *) items->data)) {
998 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
999 sp_repr_set_int(repr,"sodipodi:sides",(gint)adj->value);
1000 sp_repr_set_svg_double(repr, "sodipodi:arg2",
1001 (sp_repr_get_double_attribute(repr, "sodipodi:arg1", 0.5)
1002 + M_PI / (gint)adj->value));
1003 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
1004 modmade = true;
1005 }
1006 }
1007 if (modmade) sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
1008 _("Star: Change number of corners"));
1010 g_object_set_data(G_OBJECT(dataKludge), "freeze", GINT_TO_POINTER(FALSE));
1011 }
1013 static void sp_stb_proportion_value_changed( GtkAdjustment *adj, GtkWidget *dataKludge )
1014 {
1015 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(dataKludge), "desktop");
1017 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1018 prefs_set_double_attribute("tools.shapes.star", "proportion", adj->value);
1019 }
1021 // quit if run by the attr_changed listener
1022 if (g_object_get_data(G_OBJECT(dataKludge), "freeze")) {
1023 return;
1024 }
1026 // in turn, prevent listener from responding
1027 g_object_set_data(G_OBJECT(dataKludge), "freeze", GINT_TO_POINTER(TRUE));
1029 bool modmade = false;
1030 Inkscape::Selection *selection = sp_desktop_selection(desktop);
1031 GSList const *items = selection->itemList();
1032 for (; items != NULL; items = items->next) {
1033 if (SP_IS_STAR((SPItem *) items->data)) {
1034 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
1036 gdouble r1 = sp_repr_get_double_attribute(repr, "sodipodi:r1", 1.0);
1037 gdouble r2 = sp_repr_get_double_attribute(repr, "sodipodi:r2", 1.0);
1038 if (r2 < r1) {
1039 sp_repr_set_svg_double(repr, "sodipodi:r2", r1*adj->value);
1040 } else {
1041 sp_repr_set_svg_double(repr, "sodipodi:r1", r2*adj->value);
1042 }
1044 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
1045 modmade = true;
1046 }
1047 }
1049 if (modmade) sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
1050 _("Star: Change spoke ratio"));
1052 g_object_set_data(G_OBJECT(dataKludge), "freeze", GINT_TO_POINTER(FALSE));
1053 }
1055 static void sp_stb_sides_flat_state_changed( GtkToggleAction *act, GtkObject *dataKludge )
1056 {
1057 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(dataKludge), "desktop");
1058 bool flat = gtk_toggle_action_get_active(act);
1060 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1061 prefs_set_string_attribute( "tools.shapes.star", "isflatsided",
1062 flat ? "true" : "false" );
1063 }
1065 // quit if run by the attr_changed listener
1066 if (g_object_get_data(G_OBJECT(dataKludge), "freeze")) {
1067 return;
1068 }
1070 // in turn, prevent listener from responding
1071 g_object_set_data(G_OBJECT(dataKludge), "freeze", GINT_TO_POINTER(TRUE));
1073 Inkscape::Selection *selection = sp_desktop_selection(desktop);
1074 GSList const *items = selection->itemList();
1075 GtkAction* prop_action = GTK_ACTION( g_object_get_data(G_OBJECT(dataKludge), "prop_action") );
1076 bool modmade = false;
1078 if ( prop_action ) {
1079 gtk_action_set_sensitive( prop_action, !flat );
1080 }
1082 for (; items != NULL; items = items->next) {
1083 if (SP_IS_STAR((SPItem *) items->data)) {
1084 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
1085 repr->setAttribute("inkscape:flatsided", flat ? "true" : "false" );
1086 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
1087 modmade = true;
1088 }
1089 }
1091 if (modmade) {
1092 sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
1093 flat ? _("Make polygon") : _("Make star"));
1094 }
1096 g_object_set_data(G_OBJECT(dataKludge), "freeze", GINT_TO_POINTER(FALSE));
1097 }
1099 static void sp_stb_rounded_value_changed( GtkAdjustment *adj, GtkWidget *dataKludge )
1100 {
1101 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(dataKludge), "desktop");
1103 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1104 prefs_set_double_attribute("tools.shapes.star", "rounded", (gdouble) adj->value);
1105 }
1107 // quit if run by the attr_changed listener
1108 if (g_object_get_data(G_OBJECT(dataKludge), "freeze")) {
1109 return;
1110 }
1112 // in turn, prevent listener from responding
1113 g_object_set_data(G_OBJECT(dataKludge), "freeze", GINT_TO_POINTER(TRUE));
1115 bool modmade = false;
1117 Inkscape::Selection *selection = sp_desktop_selection(desktop);
1118 GSList const *items = selection->itemList();
1119 for (; items != NULL; items = items->next) {
1120 if (SP_IS_STAR((SPItem *) items->data)) {
1121 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
1122 sp_repr_set_svg_double(repr, "inkscape:rounded", (gdouble) adj->value);
1123 SP_OBJECT(items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
1124 modmade = true;
1125 }
1126 }
1127 if (modmade) sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
1128 _("Star: Change rounding"));
1130 g_object_set_data(G_OBJECT(dataKludge), "freeze", GINT_TO_POINTER(FALSE));
1131 }
1133 static void sp_stb_randomized_value_changed( GtkAdjustment *adj, GtkWidget *dataKludge )
1134 {
1135 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(dataKludge), "desktop");
1137 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1138 prefs_set_double_attribute("tools.shapes.star", "randomized", (gdouble) adj->value);
1139 }
1141 // quit if run by the attr_changed listener
1142 if (g_object_get_data(G_OBJECT(dataKludge), "freeze")) {
1143 return;
1144 }
1146 // in turn, prevent listener from responding
1147 g_object_set_data(G_OBJECT(dataKludge), "freeze", GINT_TO_POINTER(TRUE));
1149 bool modmade = false;
1151 Inkscape::Selection *selection = sp_desktop_selection(desktop);
1152 GSList const *items = selection->itemList();
1153 for (; items != NULL; items = items->next) {
1154 if (SP_IS_STAR((SPItem *) items->data)) {
1155 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
1156 sp_repr_set_svg_double(repr, "inkscape:randomized", (gdouble) adj->value);
1157 SP_OBJECT(items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
1158 modmade = true;
1159 }
1160 }
1161 if (modmade) sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
1162 _("Star: Change randomization"));
1164 g_object_set_data(G_OBJECT(dataKludge), "freeze", GINT_TO_POINTER(FALSE));
1165 }
1168 static void star_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1169 gchar const *old_value, gchar const *new_value,
1170 bool is_interactive, gpointer data)
1171 {
1172 GtkWidget *tbl = GTK_WIDGET(data);
1174 // quit if run by the _changed callbacks
1175 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1176 return;
1177 }
1179 // in turn, prevent callbacks from responding
1180 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1182 GtkAdjustment *adj = 0;
1184 if (!strcmp(name, "inkscape:randomized")) {
1185 adj = GTK_ADJUSTMENT( gtk_object_get_data(GTK_OBJECT(tbl), "randomized") );
1186 gtk_adjustment_set_value(adj, sp_repr_get_double_attribute(repr, "inkscape:randomized", 0.0));
1187 } else if (!strcmp(name, "inkscape:rounded")) {
1188 adj = GTK_ADJUSTMENT( gtk_object_get_data(GTK_OBJECT(tbl), "rounded") );
1189 gtk_adjustment_set_value(adj, sp_repr_get_double_attribute(repr, "inkscape:rounded", 0.0));
1190 } else if (!strcmp(name, "inkscape:flatsided")) {
1191 GtkAction* prop_action = GTK_ACTION( g_object_get_data(G_OBJECT(tbl), "prop_action") );
1192 char const *flatsides = repr->attribute("inkscape:flatsided");
1193 if (flatsides && !strcmp(flatsides,"false" )) {
1194 GtkToggleAction* flat2_action = GTK_TOGGLE_ACTION( g_object_get_data( G_OBJECT(tbl), "flat2_action" ) );
1195 gtk_toggle_action_set_active( flat2_action, TRUE );
1196 gtk_action_set_sensitive( prop_action, TRUE );
1197 } else {
1198 GtkToggleAction* flat_action = GTK_TOGGLE_ACTION( g_object_get_data( G_OBJECT(tbl), "flat_action" ) );
1199 gtk_toggle_action_set_active( flat_action, TRUE );
1200 gtk_action_set_sensitive( prop_action, FALSE );
1201 }
1202 } else if (!strcmp(name, "sodipodi:r1") || !strcmp(name, "sodipodi:r2")) {
1203 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "proportion");
1204 gdouble r1 = sp_repr_get_double_attribute(repr, "sodipodi:r1", 1.0);
1205 gdouble r2 = sp_repr_get_double_attribute(repr, "sodipodi:r2", 1.0);
1206 if (r2 < r1) {
1207 gtk_adjustment_set_value(adj, r2/r1);
1208 } else {
1209 gtk_adjustment_set_value(adj, r1/r2);
1210 }
1211 } else if (!strcmp(name, "sodipodi:sides")) {
1212 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "magnitude");
1213 gtk_adjustment_set_value(adj, sp_repr_get_int_attribute(repr, "sodipodi:sides", 0));
1214 }
1216 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1217 }
1220 static Inkscape::XML::NodeEventVector star_tb_repr_events =
1221 {
1222 NULL, /* child_added */
1223 NULL, /* child_removed */
1224 star_tb_event_attr_changed,
1225 NULL, /* content_changed */
1226 NULL /* order_changed */
1227 };
1230 /**
1231 * \param selection Should not be NULL.
1232 */
1233 static void
1234 sp_star_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1235 {
1236 int n_selected = 0;
1237 Inkscape::XML::Node *repr = NULL;
1238 Inkscape::XML::Node *oldrepr = NULL;
1240 for (GSList const *items = selection->itemList();
1241 items != NULL;
1242 items = items->next)
1243 {
1244 if (SP_IS_STAR((SPItem *) items->data)) {
1245 n_selected++;
1246 repr = SP_OBJECT_REPR((SPItem *) items->data);
1247 }
1248 }
1250 EgeOutputAction* act = EGE_OUTPUT_ACTION( gtk_object_get_data(GTK_OBJECT(tbl), "mode_action") );
1252 if (n_selected == 0) {
1253 g_object_set( G_OBJECT(act), "label", _("<b>New:</b>"), NULL );
1254 } else if (n_selected == 1) {
1255 g_object_set( G_OBJECT(act), "label", _("<b>Change:</b>"), NULL );
1257 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1258 if (oldrepr) { // remove old listener
1259 sp_repr_remove_listener_by_data(oldrepr, tbl);
1260 Inkscape::GC::release(oldrepr);
1261 oldrepr = 0;
1262 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1263 }
1265 if (repr) {
1266 g_object_set_data(G_OBJECT(tbl), "repr", repr);
1267 Inkscape::GC::anchor(repr);
1268 sp_repr_add_listener(repr, &star_tb_repr_events, tbl);
1269 sp_repr_synthesize_events(repr, &star_tb_repr_events, tbl);
1270 }
1271 } else {
1272 // FIXME: implement averaging of all parameters for multiple selected stars
1273 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1274 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
1275 }
1276 }
1279 static void sp_stb_defaults( GtkWidget *widget, GtkWidget *dataKludge )
1280 {
1281 // FIXME: in this and all other _default functions, set some flag telling the value_changed
1282 // callbacks to lump all the changes for all selected objects in one undo step
1284 GtkAdjustment *adj = 0;
1286 // fixme: make settable in prefs!
1287 gint mag = 5;
1288 gdouble prop = 0.5;
1289 gboolean flat = FALSE;
1290 gdouble randomized = 0;
1291 gdouble rounded = 0;
1293 GtkToggleAction* flat_action = GTK_TOGGLE_ACTION( g_object_get_data( G_OBJECT(dataKludge), "flat_action" ) );
1294 GtkToggleAction* flat2_action = GTK_TOGGLE_ACTION( g_object_get_data( G_OBJECT(dataKludge), "flat2_action" ) );
1295 gtk_toggle_action_set_active( flat ? flat_action : flat2_action, TRUE );
1297 GtkAction* sb2 = GTK_ACTION( g_object_get_data(G_OBJECT(dataKludge), "prop_action") );
1298 gtk_action_set_sensitive( sb2, !flat );
1300 adj = GTK_ADJUSTMENT( gtk_object_get_data(GTK_OBJECT(dataKludge), "magnitude") );
1301 gtk_adjustment_set_value(adj, mag);
1302 gtk_adjustment_value_changed(adj);
1304 adj = GTK_ADJUSTMENT( gtk_object_get_data(GTK_OBJECT(dataKludge), "proportion") );
1305 gtk_adjustment_set_value(adj, prop);
1306 gtk_adjustment_value_changed(adj);
1308 adj = GTK_ADJUSTMENT( gtk_object_get_data(GTK_OBJECT(dataKludge), "rounded") );
1309 gtk_adjustment_set_value(adj, rounded);
1310 gtk_adjustment_value_changed(adj);
1312 adj = GTK_ADJUSTMENT( gtk_object_get_data(GTK_OBJECT(dataKludge), "randomized") );
1313 gtk_adjustment_set_value(adj, randomized);
1314 gtk_adjustment_value_changed(adj);
1315 }
1318 void
1319 sp_toolbox_add_label(GtkWidget *tbl, gchar const *title, bool wide)
1320 {
1321 GtkWidget *boxl = gtk_hbox_new(FALSE, 0);
1322 if (wide) gtk_widget_set_size_request(boxl, MODE_LABEL_WIDTH, -1);
1323 GtkWidget *l = gtk_label_new(NULL);
1324 gtk_label_set_markup(GTK_LABEL(l), title);
1325 gtk_box_pack_end(GTK_BOX(boxl), l, FALSE, FALSE, 0);
1326 gtk_box_pack_start(GTK_BOX(tbl), boxl, FALSE, FALSE, 0);
1327 gtk_object_set_data(GTK_OBJECT(tbl), "mode_label", l);
1328 }
1331 static GtkWidget *
1332 sp_star_toolbox_new(SPDesktop *desktop)
1333 {
1334 GtkWidget* holder = gtk_table_new( 1, 2, FALSE );
1336 gchar const * descr =
1337 "<ui>"
1338 " <toolbar name='StarToolbar'>"
1339 " <separator />"
1340 " <toolitem action='StarStateAction' />"
1341 " <separator />"
1342 " <toolitem action='FlatAction' />"
1343 " <toolitem action='FlatAction2' />"
1344 " <separator />"
1345 " <toolitem action='MagnitudeAction' />"
1346 " <toolitem action='SpokeAction' />"
1347 " <toolitem action='RoundednessAction' />"
1348 " <toolitem action='RandomizationAction' />"
1349 " <separator />"
1350 " <toolitem action='ResetAction' />"
1351 " </toolbar>"
1352 "</ui>";
1353 GtkActionGroup* mainActions = gtk_action_group_new("main");
1355 {
1356 EgeOutputAction* act = ege_output_action_new( "StarStateAction", _("<b>New:</b>"), "", 0 );
1357 ege_output_action_set_use_markup( act, TRUE );
1358 gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
1359 gtk_object_set_data( GTK_OBJECT(holder), "mode_action", act );
1360 }
1362 {
1363 gtk_object_set_data(GTK_OBJECT(holder), "dtw", desktop->canvas);
1364 gtk_object_set_data(GTK_OBJECT(holder), "desktop", desktop);
1366 //EgeAdjustmentAction* calligraphy_angle = 0;
1367 EgeAdjustmentAction* eact = 0;
1368 gchar const *flatsidedstr = prefs_get_string_attribute( "tools.shapes.star", "isflatsided" );
1369 bool isFlatSided = flatsidedstr ? (strcmp(flatsidedstr, "false") != 0) : true;
1371 /* Flatsided checkbox */
1372 {
1373 InkRadioAction* act = ink_radio_action_new( "FlatAction",
1374 _("Polygon"),
1375 _("Regular polygon (with one handle) instead of a star"),
1376 "star_flat",
1377 Inkscape::ICON_SIZE_SMALL_TOOLBAR );
1378 gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
1380 InkRadioAction* act2 = ink_radio_action_new( "FlatAction2",
1381 _("Star"),
1382 _("Star instead of a regular polygon (with one handle)"),
1383 "star_angled",
1384 Inkscape::ICON_SIZE_SMALL_TOOLBAR );
1385 gtk_action_group_add_action( mainActions, GTK_ACTION( act2 ) );
1387 // Connect to be in the same radio button group.
1388 gtk_radio_action_set_group( GTK_RADIO_ACTION(act), 0 );
1389 GSList* radioGroup = gtk_radio_action_get_group( GTK_RADIO_ACTION(act) );
1390 gtk_radio_action_set_group( GTK_RADIO_ACTION(act2), radioGroup );
1392 gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), isFlatSided );
1393 gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act2), !isFlatSided );
1395 g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_stb_sides_flat_state_changed), holder);
1396 gtk_object_set_data( GTK_OBJECT(holder), "flat_action", act );
1397 gtk_object_set_data( GTK_OBJECT(holder), "flat2_action", act2 );
1398 }
1400 /* Magnitude */
1401 //gchar const* labels[] = {_("tri (default)"), _("quad"), _("pent")};
1402 //gdouble values[] = {3, 4, 5};
1403 eact = create_adjustment_action( "MagnitudeAction",
1404 _("Corners:"), _("Number of corners of a polygon or star"),
1405 "tools.shapes.star", "magnitude", 3,
1406 GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
1407 3, 1024, 1, 5,
1408 0, 0, 0, // labels, values, G_N_ELEMENTS(labels),
1409 sp_stb_magnitude_value_changed,
1410 1.0, 0 );
1411 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
1412 gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
1414 /* Spoke ratio */
1415 //gchar const* labels2[] = {_("(left edge up)"), _("(horizontal)"), _("(default)"), _("(right edge up)")};
1416 //gdouble values2[] = {-90, 0, 30, 90};
1417 eact = create_adjustment_action( "SpokeAction",
1418 _("Spoke ratio:"),
1419 // TRANSLATORS: Tip radius of a star is the distance from the center to the farthest handle.
1420 // Base radius is the same for the closest handle.
1421 _("Base radius to tip radius ratio"),
1422 "tools.shapes.star", "proportion", 0.5,
1423 GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
1424 0.01, 1.0, 0.01, 0.1,
1425 0, 0, 0, // labels2, values2, G_N_ELEMENTS(labels2),
1426 sp_stb_proportion_value_changed );
1427 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
1428 g_object_set_data(G_OBJECT(holder), "prop_action", eact);
1430 if ( !isFlatSided ) {
1431 gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
1432 } else {
1433 gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
1434 }
1436 /* Roundedness */
1437 //gchar const* labels3[] = {_("(left edge up)"), _("(horizontal)"), _("(default)"), _("(right edge up)")};
1438 //gdouble values3[] = {-90, 0, 30, 90};
1439 eact = create_adjustment_action( "RoundednessAction",
1440 _("Rounded:"), _("How much rounded are the corners (0 for sharp)"),
1441 "tools.shapes.star", "rounded", 0.0,
1442 GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
1443 -100.0, 100.0, 0.01, 0.1,
1444 0, 0, 0, // labels3, values3, G_N_ELEMENTS(labels3),
1445 sp_stb_rounded_value_changed );
1446 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
1447 gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
1449 /* Randomization */
1450 //gchar const* labels4[] = {_("(left edge up)"), _("(horizontal)"), _("(default)"), _("(right edge up)")};
1451 //gdouble values4[] = {-90, 0, 30, 90};
1452 eact = create_adjustment_action( "RandomizationAction",
1453 _("Randomized:"), _("Scatter randomly the corners and angles"),
1454 "tools.shapes.star", "randomized", 0.0,
1455 GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
1456 -10.0, 10.0, 0.001, 0.01,
1457 0, 0, 0, // labels4, values4, G_N_ELEMENTS(labels4),
1458 sp_stb_randomized_value_changed, 0.1, 3 );
1459 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
1460 gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
1461 }
1463 {
1464 /* Reset */
1465 {
1466 GtkAction* act = gtk_action_new( "ResetAction",
1467 _("Defaults"),
1468 _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"),
1469 GTK_STOCK_CLEAR );
1470 g_signal_connect_after( G_OBJECT(act), "activate", G_CALLBACK(sp_stb_defaults), holder );
1471 gtk_action_group_add_action( mainActions, act );
1472 gtk_action_set_sensitive( act, TRUE );
1473 }
1474 }
1477 GtkUIManager* mgr = gtk_ui_manager_new();
1478 GError* errVal = 0;
1480 gtk_ui_manager_insert_action_group( mgr, mainActions, 0 );
1481 gtk_ui_manager_add_ui_from_string( mgr, descr, -1, &errVal );
1483 GtkWidget* toolBar = gtk_ui_manager_get_widget( mgr, "/ui/StarToolbar" );
1484 gtk_toolbar_set_style( GTK_TOOLBAR(toolBar), GTK_TOOLBAR_ICONS );
1485 gtk_toolbar_set_icon_size( GTK_TOOLBAR(toolBar), GTK_ICON_SIZE_SMALL_TOOLBAR );
1488 gtk_table_attach( GTK_TABLE(holder), toolBar, 0, 1, 0, 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 0, 0 );
1490 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL, _("Style of new stars"));
1491 swatch->setDesktop( desktop );
1492 swatch->setClickVerb( SP_VERB_CONTEXT_STAR_PREFS );
1493 swatch->setWatchedTool( "tools.shapes.star", true );
1494 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1495 gtk_table_attach( GTK_TABLE(holder), swatch_, 1, 2, 0, 1, (GtkAttachOptions)(GTK_SHRINK | GTK_FILL), (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), AUX_BETWEEN_BUTTON_GROUPS, 0 );
1497 gtk_widget_show_all(holder);
1498 //sp_set_font_size_smaller (tbl);
1500 sigc::connection *connection = new sigc::connection(
1501 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_star_toolbox_selection_changed), (GtkObject *)holder))
1502 );
1503 g_signal_connect(G_OBJECT(holder), "destroy", G_CALLBACK(delete_connection), connection);
1505 return holder;
1506 }
1509 //########################
1510 //## Rect ##
1511 //########################
1513 static void
1514 sp_rtb_sensitivize (GtkWidget *tbl)
1515 {
1516 GtkAdjustment *adj1 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "rx"));
1517 GtkAdjustment *adj2 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "ry"));
1518 GtkAction* not_rounded = GTK_ACTION( g_object_get_data(G_OBJECT(tbl), "not_rounded") );
1520 if (adj1->value == 0 && adj2->value == 0 && gtk_object_get_data(GTK_OBJECT(tbl), "single")) { // only for a single selected rect (for now)
1521 gtk_action_set_sensitive( not_rounded, FALSE );
1522 } else {
1523 gtk_action_set_sensitive( not_rounded, TRUE );
1524 }
1525 }
1528 static void
1529 sp_rtb_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name,
1530 void (*setter)(SPRect *, gdouble))
1531 {
1532 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
1534 UnitTracker* tracker = reinterpret_cast<UnitTracker*>(gtk_object_get_data(GTK_OBJECT(tbl), "tracker"));
1535 SPUnit const *unit = tracker->getActiveUnit();
1537 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1538 prefs_set_double_attribute("tools.shapes.rect", value_name, sp_units_get_pixels(adj->value, *unit));
1539 }
1541 // quit if run by the attr_changed listener
1542 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1543 return;
1544 }
1546 // in turn, prevent listener from responding
1547 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1549 bool modmade = false;
1550 Inkscape::Selection *selection = sp_desktop_selection(desktop);
1551 for (GSList const *items = selection->itemList(); items != NULL; items = items->next) {
1552 if (SP_IS_RECT(items->data)) {
1553 if (adj->value != 0) {
1554 setter(SP_RECT(items->data), sp_units_get_pixels(adj->value, *unit));
1555 } else {
1556 SP_OBJECT_REPR(items->data)->setAttribute(value_name, NULL);
1557 }
1558 modmade = true;
1559 }
1560 }
1562 sp_rtb_sensitivize (tbl);
1564 if (modmade) {
1565 sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_RECT,
1566 _("Change rectangle"));
1567 }
1569 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1571 // defocus spinbuttons by moving focus to the canvas, unless "stay" is on
1572 spinbutton_defocus(GTK_OBJECT(tbl));
1573 }
1575 static void
1576 sp_rtb_rx_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1577 {
1578 sp_rtb_value_changed(adj, tbl, "rx", sp_rect_set_visible_rx);
1579 }
1581 static void
1582 sp_rtb_ry_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1583 {
1584 sp_rtb_value_changed(adj, tbl, "ry", sp_rect_set_visible_ry);
1585 }
1587 static void
1588 sp_rtb_width_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1589 {
1590 sp_rtb_value_changed(adj, tbl, "width", sp_rect_set_visible_width);
1591 }
1593 static void
1594 sp_rtb_height_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1595 {
1596 sp_rtb_value_changed(adj, tbl, "height", sp_rect_set_visible_height);
1597 }
1601 static void
1602 sp_rtb_defaults( GtkWidget *widget, GtkObject *obj)
1603 {
1604 GtkWidget *tbl = GTK_WIDGET(obj);
1606 GtkAdjustment *adj = 0;
1608 adj = GTK_ADJUSTMENT( gtk_object_get_data(obj, "rx") );
1609 gtk_adjustment_set_value(adj, 0.0);
1610 // this is necessary if the previous value was 0, but we still need to run the callback to change all selected objects
1611 gtk_adjustment_value_changed(adj);
1613 adj = GTK_ADJUSTMENT( gtk_object_get_data(obj, "ry") );
1614 gtk_adjustment_set_value(adj, 0.0);
1615 gtk_adjustment_value_changed(adj);
1617 sp_rtb_sensitivize (tbl);
1618 }
1620 static void rect_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1621 gchar const *old_value, gchar const *new_value,
1622 bool is_interactive, gpointer data)
1623 {
1624 GtkWidget *tbl = GTK_WIDGET(data);
1626 // quit if run by the _changed callbacks
1627 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1628 return;
1629 }
1631 // in turn, prevent callbacks from responding
1632 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1634 UnitTracker* tracker = reinterpret_cast<UnitTracker*>( gtk_object_get_data(GTK_OBJECT(tbl), "tracker") );
1635 SPUnit const *unit = tracker->getActiveUnit();
1637 gpointer item = g_object_get_data(G_OBJECT(tbl), "item");
1638 if (item && SP_IS_RECT(item)) {
1639 {
1640 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "rx");
1641 gdouble rx = sp_rect_get_visible_rx(SP_RECT(item));
1642 gtk_adjustment_set_value(adj, sp_pixels_get_units(rx, *unit));
1643 }
1645 {
1646 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "ry");
1647 gdouble ry = sp_rect_get_visible_ry(SP_RECT(item));
1648 gtk_adjustment_set_value(adj, sp_pixels_get_units(ry, *unit));
1649 }
1651 {
1652 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "width");
1653 gdouble width = sp_rect_get_visible_width (SP_RECT(item));
1654 gtk_adjustment_set_value(adj, sp_pixels_get_units(width, *unit));
1655 }
1657 {
1658 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "height");
1659 gdouble height = sp_rect_get_visible_height (SP_RECT(item));
1660 gtk_adjustment_set_value(adj, sp_pixels_get_units(height, *unit));
1661 }
1662 }
1664 sp_rtb_sensitivize (tbl);
1666 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1667 }
1670 static Inkscape::XML::NodeEventVector rect_tb_repr_events = {
1671 NULL, /* child_added */
1672 NULL, /* child_removed */
1673 rect_tb_event_attr_changed,
1674 NULL, /* content_changed */
1675 NULL /* order_changed */
1676 };
1678 /**
1679 * \param selection should not be NULL.
1680 */
1681 static void
1682 sp_rect_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
1683 {
1684 int n_selected = 0;
1685 Inkscape::XML::Node *repr = NULL;
1686 SPItem *item = NULL;
1687 Inkscape::XML::Node *oldrepr = NULL;
1689 for (GSList const *items = selection->itemList();
1690 items != NULL;
1691 items = items->next) {
1692 if (SP_IS_RECT((SPItem *) items->data)) {
1693 n_selected++;
1694 item = (SPItem *) items->data;
1695 repr = SP_OBJECT_REPR(item);
1696 }
1697 }
1699 EgeOutputAction* act = EGE_OUTPUT_ACTION( gtk_object_get_data(GTK_OBJECT(tbl), "mode_action") );
1701 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(FALSE));
1703 if (n_selected == 0) {
1704 g_object_set( G_OBJECT(act), "label", _("<b>New:</b>"), NULL );
1706 GtkAction* w = GTK_ACTION( gtk_object_get_data(GTK_OBJECT(tbl), "width_action") );
1707 gtk_action_set_sensitive(w, FALSE);
1708 GtkAction* h = GTK_ACTION( gtk_object_get_data(GTK_OBJECT(tbl), "height_action") );
1709 gtk_action_set_sensitive(h, FALSE);
1711 } else if (n_selected == 1) {
1712 g_object_set( G_OBJECT(act), "label", _("<b>Change:</b>"), NULL );
1713 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
1715 GtkAction* w = GTK_ACTION( gtk_object_get_data(GTK_OBJECT(tbl), "width_action") );
1716 gtk_action_set_sensitive(w, TRUE);
1717 GtkAction* h = GTK_ACTION( gtk_object_get_data(GTK_OBJECT(tbl), "height_action") );
1718 gtk_action_set_sensitive(h, TRUE);
1720 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
1721 if (oldrepr) { // remove old listener
1722 sp_repr_remove_listener_by_data(oldrepr, tbl);
1723 Inkscape::GC::release(oldrepr);
1724 oldrepr = 0;
1725 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
1726 g_object_set_data(G_OBJECT(tbl), "item", NULL);
1727 }
1728 if (repr) {
1729 g_object_set_data(G_OBJECT(tbl), "repr", repr);
1730 g_object_set_data(G_OBJECT(tbl), "item", item);
1731 Inkscape::GC::anchor(repr);
1732 sp_repr_add_listener(repr, &rect_tb_repr_events, tbl);
1733 sp_repr_synthesize_events(repr, &rect_tb_repr_events, tbl);
1734 }
1735 } else {
1736 // FIXME: implement averaging of all parameters for multiple selected
1737 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
1738 g_object_set( G_OBJECT(act), "label", _("<b>Change:</b>"), NULL );
1739 sp_rtb_sensitivize (GTK_WIDGET(tbl));
1740 }
1741 }
1744 static GtkWidget *
1745 sp_rect_toolbox_new(SPDesktop *desktop)
1746 {
1747 GtkWidget *holder = gtk_hbox_new(FALSE, 0);
1748 gtk_object_set_data(GTK_OBJECT(holder), "dtw", desktop->canvas);
1749 gtk_object_set_data(GTK_OBJECT(holder), "desktop", desktop);
1751 gchar const * descr =
1752 "<ui>"
1753 " <toolbar name='RectToolbar'>"
1754 " <toolitem action='RectStateAction' />"
1755 " <toolitem action='WidthAction' />"
1756 " <toolitem action='HeightAction' />"
1757 " <toolitem action='RadiusXAction' />"
1758 " <toolitem action='RadiusYAction' />"
1759 " <toolitem action='RectUnitsAction' />"
1760 " <separator />"
1761 " <toolitem action='RectResetAction' />"
1762 " </toolbar>"
1763 "</ui>";
1764 GtkActionGroup* mainActions = gtk_action_group_new("main");
1766 EgeAdjustmentAction* eact = 0;
1768 {
1769 EgeOutputAction* act = ege_output_action_new( "RectStateAction", _("<b>New:</b>"), "", 0 );
1770 ege_output_action_set_use_markup( act, TRUE );
1771 gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
1772 gtk_object_set_data( GTK_OBJECT(holder), "mode_action", act );
1773 }
1775 // rx/ry units menu: create
1776 UnitTracker* tracker = new UnitTracker( SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE );
1777 //tracker->addUnit( SP_UNIT_PERCENT, 0 );
1778 // fixme: add % meaning per cent of the width/height
1779 tracker->setActiveUnit( sp_desktop_namedview(desktop)->doc_units );
1780 gtk_object_set_data( GTK_OBJECT(holder), "tracker", tracker );
1782 /* W */
1783 {
1784 eact = create_adjustment_action( "WidthAction",
1785 _("W:"), _("Width of rectangle"),
1786 "tools.shapes.rect", "width", 0,
1787 GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, TRUE, "altx-rect",
1788 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1789 0, 0, 0,
1790 sp_rtb_width_value_changed );
1791 tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) );
1792 gtk_object_set_data( GTK_OBJECT(holder), "width_action", eact );
1793 gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
1794 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
1795 }
1797 /* H */
1798 {
1799 eact = create_adjustment_action( "HeightAction",
1800 _("H:"), _("Height of rectangle"),
1801 "tools.shapes.rect", "height", 0,
1802 GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, FALSE, NULL,
1803 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1804 0, 0, 0,
1805 sp_rtb_height_value_changed );
1806 tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) );
1807 gtk_object_set_data( GTK_OBJECT(holder), "height_action", eact );
1808 gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
1809 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
1810 }
1812 /* rx */
1813 {
1814 eact = create_adjustment_action( "RadiusXAction",
1815 _("Rx:"), _("Horizontal radius of rounded corners"),
1816 "tools.shapes.rect", "rx", 0,
1817 GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, FALSE, NULL,
1818 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1819 0, 0, 0,
1820 sp_rtb_rx_value_changed);
1821 tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) );
1822 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
1823 }
1825 /* ry */
1826 {
1827 eact = create_adjustment_action( "RadiusYAction",
1828 _("Ry:"), _("Vertical radius of rounded corners"),
1829 "tools.shapes.rect", "ry", 0,
1830 GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, FALSE, NULL,
1831 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1832 0, 0, 0,
1833 sp_rtb_ry_value_changed);
1834 tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) );
1835 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
1836 }
1838 // add the units menu
1839 {
1840 GtkAction* act = tracker->createAction( "RectUnitsAction", _("Units"), _("") );
1841 gtk_action_group_add_action( mainActions, act );
1842 }
1844 /* Reset */
1845 {
1846 InkAction* inky = ink_action_new( "RectResetAction",
1847 _("Not rounded"),
1848 _("Make corners sharp"),
1849 "squared_corner",
1850 Inkscape::ICON_SIZE_SMALL_TOOLBAR );
1851 g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_rtb_defaults), holder );
1852 gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
1853 gtk_action_set_sensitive( GTK_ACTION(inky), TRUE );
1854 gtk_object_set_data( GTK_OBJECT(holder), "not_rounded", inky );
1855 }
1857 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL, _("Style of new rectangles"));
1858 swatch->setDesktop (desktop);
1859 swatch->setClickVerb (SP_VERB_CONTEXT_RECT_PREFS);
1860 swatch->setWatchedTool ("tools.shapes.rect", true);
1861 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
1862 gtk_box_pack_end(GTK_BOX(holder), swatch_, FALSE, FALSE, 0);
1864 g_object_set_data(G_OBJECT(holder), "single", GINT_TO_POINTER(TRUE));
1865 sp_rtb_sensitivize (holder);
1868 GtkUIManager* mgr = gtk_ui_manager_new();
1869 GError* errVal = 0;
1871 gtk_ui_manager_insert_action_group( mgr, mainActions, 0 );
1872 gtk_ui_manager_add_ui_from_string( mgr, descr, -1, &errVal );
1874 GtkWidget* toolBar = gtk_ui_manager_get_widget( mgr, "/ui/RectToolbar" );
1875 gtk_toolbar_set_style( GTK_TOOLBAR(toolBar), GTK_TOOLBAR_ICONS );
1876 gtk_toolbar_set_icon_size( GTK_TOOLBAR(toolBar), GTK_ICON_SIZE_SMALL_TOOLBAR );
1879 gtk_box_pack_start( GTK_BOX(holder), toolBar, TRUE, TRUE, 0 );
1882 gtk_widget_show_all(holder);
1883 sp_set_font_size_smaller(holder);
1885 sigc::connection *connection = new sigc::connection(
1886 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_rect_toolbox_selection_changed), (GtkObject *)holder))
1887 );
1888 g_signal_connect(G_OBJECT(holder), "destroy", G_CALLBACK(delete_connection), connection);
1890 return holder;
1891 }
1893 //########################
1894 //## Spiral ##
1895 //########################
1897 static void
1898 sp_spl_tb_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name)
1899 {
1900 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
1902 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1903 prefs_set_double_attribute("tools.shapes.spiral", value_name, adj->value);
1904 }
1906 // quit if run by the attr_changed listener
1907 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1908 return;
1909 }
1911 // in turn, prevent listener from responding
1912 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
1914 gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
1916 bool modmade = false;
1917 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
1918 items != NULL;
1919 items = items->next)
1920 {
1921 if (SP_IS_SPIRAL((SPItem *) items->data)) {
1922 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
1923 sp_repr_set_svg_double( repr, namespaced_name, adj->value );
1924 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
1925 modmade = true;
1926 }
1927 }
1929 g_free(namespaced_name);
1931 if (modmade) {
1932 sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_SPIRAL,
1933 _("Change spiral"));
1934 }
1936 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
1938 spinbutton_defocus(GTK_OBJECT(tbl));
1939 }
1941 static void
1942 sp_spl_tb_revolution_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1943 {
1944 sp_spl_tb_value_changed(adj, tbl, "revolution");
1945 }
1947 static void
1948 sp_spl_tb_expansion_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1949 {
1950 sp_spl_tb_value_changed(adj, tbl, "expansion");
1951 }
1953 static void
1954 sp_spl_tb_t0_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
1955 {
1956 sp_spl_tb_value_changed(adj, tbl, "t0");
1957 }
1959 static void
1960 sp_spl_tb_defaults(GtkWidget *widget, GtkObject *obj)
1961 {
1962 GtkWidget *tbl = GTK_WIDGET(obj);
1964 GtkAdjustment *adj;
1966 // fixme: make settable
1967 gdouble rev = 5;
1968 gdouble exp = 1.0;
1969 gdouble t0 = 0.0;
1971 adj = (GtkAdjustment*)gtk_object_get_data(obj, "revolution");
1972 gtk_adjustment_set_value(adj, rev);
1973 gtk_adjustment_value_changed(adj);
1975 adj = (GtkAdjustment*)gtk_object_get_data(obj, "expansion");
1976 gtk_adjustment_set_value(adj, exp);
1977 gtk_adjustment_value_changed(adj);
1979 adj = (GtkAdjustment*)gtk_object_get_data(obj, "t0");
1980 gtk_adjustment_set_value(adj, t0);
1981 gtk_adjustment_value_changed(adj);
1983 spinbutton_defocus(GTK_OBJECT(tbl));
1984 }
1987 static void spiral_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
1988 gchar const *old_value, gchar const *new_value,
1989 bool is_interactive, gpointer data)
1990 {
1991 GtkWidget *tbl = GTK_WIDGET(data);
1993 // quit if run by the _changed callbacks
1994 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
1995 return;
1996 }
1998 // in turn, prevent callbacks from responding
1999 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2001 GtkAdjustment *adj;
2002 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "revolution");
2003 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:revolution", 3.0)));
2005 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "expansion");
2006 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:expansion", 1.0)));
2008 adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "t0");
2009 gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:t0", 0.0)));
2011 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2012 }
2015 static Inkscape::XML::NodeEventVector spiral_tb_repr_events = {
2016 NULL, /* child_added */
2017 NULL, /* child_removed */
2018 spiral_tb_event_attr_changed,
2019 NULL, /* content_changed */
2020 NULL /* order_changed */
2021 };
2023 static void
2024 sp_spiral_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
2025 {
2026 int n_selected = 0;
2027 Inkscape::XML::Node *repr = NULL;
2028 Inkscape::XML::Node *oldrepr = NULL;
2030 for (GSList const *items = selection->itemList();
2031 items != NULL;
2032 items = items->next)
2033 {
2034 if (SP_IS_SPIRAL((SPItem *) items->data)) {
2035 n_selected++;
2036 repr = SP_OBJECT_REPR((SPItem *) items->data);
2037 }
2038 }
2040 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
2042 if (n_selected == 0) {
2043 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
2044 } else if (n_selected == 1) {
2045 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2047 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
2048 if (oldrepr) { // remove old listener
2049 sp_repr_remove_listener_by_data(oldrepr, tbl);
2050 Inkscape::GC::release(oldrepr);
2051 oldrepr = 0;
2052 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
2053 }
2055 if (repr) {
2056 g_object_set_data(G_OBJECT(tbl), "repr", repr);
2057 Inkscape::GC::anchor(repr);
2058 sp_repr_add_listener(repr, &spiral_tb_repr_events, tbl);
2059 sp_repr_synthesize_events(repr, &spiral_tb_repr_events, tbl);
2060 }
2061 } else {
2062 // FIXME: implement averaging of all parameters for multiple selected
2063 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
2064 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2065 }
2066 }
2069 static GtkWidget *
2070 sp_spiral_toolbox_new(SPDesktop *desktop)
2071 {
2072 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2073 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2074 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2076 GtkTooltips *tt = gtk_tooltips_new();
2078 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
2080 /* Revolution */
2081 {
2082 GtkWidget *hb = sp_tb_spinbutton(_("Turns:"), _("Number of revolutions"),
2083 "tools.shapes.spiral", "revolution", 3.0,
2084 NULL, tbl, TRUE, "altx-spiral",
2085 0.01, 1024.0, 0.1, 1.0,
2086 sp_spl_tb_revolution_value_changed, 1, 2);
2087 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2088 }
2090 /* Expansion */
2091 {
2092 GtkWidget *hb = sp_tb_spinbutton(_("Divergence:"), _("How much denser/sparser are outer revolutions; 1 = uniform"),
2093 "tools.shapes.spiral", "expansion", 1.0,
2094 NULL, tbl, FALSE, NULL,
2095 0.0, 1000.0, 0.01, 1.0,
2096 sp_spl_tb_expansion_value_changed);
2097 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2098 }
2100 /* T0 */
2101 {
2102 GtkWidget *hb = sp_tb_spinbutton(_("Inner radius:"), _("Radius of the innermost revolution (relative to the spiral size)"),
2103 "tools.shapes.spiral", "t0", 0.0,
2104 NULL, tbl, FALSE, NULL,
2105 0.0, 0.999, 0.01, 1.0,
2106 sp_spl_tb_t0_value_changed);
2107 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
2108 }
2110 aux_toolbox_space(tbl, AUX_SPACING);
2112 /* Reset */
2113 {
2114 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2115 GtkWidget *b = gtk_button_new_with_label(_("Defaults"));
2116 gtk_tooltips_set_tip(tt, b, _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"), NULL);
2117 gtk_widget_show(b);
2118 gtk_container_add(GTK_CONTAINER(hb), b);
2119 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_spl_tb_defaults), tbl);
2120 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2121 }
2123 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL, _("Style of new spirals"));
2124 swatch->setDesktop (desktop);
2125 swatch->setClickVerb (SP_VERB_CONTEXT_SPIRAL_PREFS);
2126 swatch->setWatchedTool ("tools.shapes.spiral", true);
2127 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
2128 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
2130 gtk_widget_show_all(tbl);
2131 sp_set_font_size_smaller (tbl);
2133 sigc::connection *connection = new sigc::connection(
2134 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_spiral_toolbox_selection_changed), (GtkObject *)tbl))
2135 );
2136 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
2138 return tbl;
2139 }
2141 //########################
2142 //## Pen/Pencil ##
2143 //########################
2146 static GtkWidget *
2147 sp_pen_toolbox_new(SPDesktop *desktop)
2148 {
2149 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2150 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2151 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2153 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL, _("Style of new paths created by Pen"));
2154 swatch->setDesktop (desktop);
2155 swatch->setClickVerb (SP_VERB_CONTEXT_PEN_PREFS);
2156 swatch->setWatchedTool ("tools.freehand.pen", true);
2157 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
2158 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
2160 gtk_widget_show_all(tbl);
2161 sp_set_font_size_smaller (tbl);
2163 return tbl;
2164 }
2166 static GtkWidget *
2167 sp_pencil_toolbox_new(SPDesktop *desktop)
2168 {
2169 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2170 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2171 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2173 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL, _("Style of new paths created by Pencil"));
2174 swatch->setDesktop (desktop);
2175 swatch->setClickVerb (SP_VERB_CONTEXT_PENCIL_PREFS);
2176 swatch->setWatchedTool ("tools.freehand.pencil", true);
2177 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
2178 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
2180 gtk_widget_show_all(tbl);
2181 sp_set_font_size_smaller (tbl);
2183 return tbl;
2184 }
2187 //########################
2188 //## Calligraphy ##
2189 //########################
2191 static void sp_ddc_mass_value_changed( GtkAdjustment *adj, GtkWidget *tbl )
2192 {
2193 prefs_set_double_attribute( "tools.calligraphic", "mass", adj->value );
2194 }
2196 static void sp_ddc_wiggle_value_changed( GtkAdjustment *adj, GtkWidget *tbl )
2197 {
2198 prefs_set_double_attribute( "tools.calligraphic", "wiggle", adj->value );
2199 }
2201 static void sp_ddc_angle_value_changed( GtkAdjustment *adj, GtkWidget *tbl )
2202 {
2203 prefs_set_double_attribute( "tools.calligraphic", "angle", adj->value );
2204 }
2206 static void sp_ddc_width_value_changed( GtkAdjustment *adj, GtkWidget *tbl )
2207 {
2208 prefs_set_double_attribute( "tools.calligraphic", "width", adj->value * 0.01 );
2209 }
2211 static void sp_ddc_velthin_value_changed( GtkAdjustment *adj, GtkWidget *tbl )
2212 {
2213 prefs_set_double_attribute("tools.calligraphic", "thinning", adj->value);
2214 }
2216 static void sp_ddc_flatness_value_changed( GtkAdjustment *adj, GtkWidget *tbl )
2217 {
2218 prefs_set_double_attribute( "tools.calligraphic", "flatness", adj->value );
2219 }
2221 static void sp_ddc_tremor_value_changed( GtkAdjustment *adj, GtkWidget *tbl )
2222 {
2223 prefs_set_double_attribute( "tools.calligraphic", "tremor", adj->value );
2224 }
2226 static void sp_ddc_cap_rounding_value_changed( GtkAdjustment *adj, GtkWidget *tbl )
2227 {
2228 prefs_set_double_attribute( "tools.calligraphic", "cap_rounding", adj->value );
2229 }
2231 static void sp_ddc_pressure_state_changed( GtkToggleAction *act, gpointer data )
2232 {
2233 prefs_set_int_attribute( "tools.calligraphic", "usepressure", gtk_toggle_action_get_active( act ) ? 1 : 0);
2234 }
2236 static void sp_ddc_trace_background_changed( GtkToggleAction *act, gpointer data )
2237 {
2238 prefs_set_int_attribute( "tools.calligraphic", "tracebackground", gtk_toggle_action_get_active( act ) ? 1 : 0);
2239 }
2241 static void sp_ddc_tilt_state_changed( GtkToggleAction *act, GtkAction *calligraphy_angle )
2242 {
2243 prefs_set_int_attribute( "tools.calligraphic", "usetilt", gtk_toggle_action_get_active( act ) ? 1 : 0 );
2245 gtk_action_set_sensitive( calligraphy_angle, !gtk_toggle_action_get_active( act ) );
2246 }
2248 static void sp_ddc_defaults(GtkWidget *, GtkWidget *dataKludge)
2249 {
2250 // FIXME: make defaults settable via Inkscape Options
2251 struct KeyValue {
2252 char const *key;
2253 double value;
2254 } const key_values[] = {
2255 {"mass", 0.02},
2256 {"wiggle", 0.0},
2257 {"angle", 30.0},
2258 {"width", 15},
2259 {"thinning", 0.1},
2260 {"tremor", 0.0},
2261 {"flatness", 0.9},
2262 {"cap_rounding", 0.0}
2263 };
2265 for (unsigned i = 0; i < G_N_ELEMENTS(key_values); ++i) {
2266 KeyValue const &kv = key_values[i];
2267 GtkAdjustment* adj = static_cast<GtkAdjustment *>(gtk_object_get_data(GTK_OBJECT(dataKludge), kv.key));
2268 if ( adj ) {
2269 gtk_adjustment_set_value(adj, kv.value);
2270 }
2271 }
2272 }
2275 static GtkWidget *
2276 sp_calligraphy_toolbox_new(SPDesktop *desktop)
2277 {
2278 GtkWidget* holder = gtk_table_new( 1, 2, FALSE );
2280 gchar const * descr =
2281 "<ui>"
2282 " <toolbar name='CalligraphyToolbar'>"
2283 " <separator />"
2284 " <toolitem name='Width' action='WidthAction' />"
2285 " <toolitem name='Thinning' action='ThinningAction' />"
2286 " <separator />"
2287 " <toolitem name='Angle' action='AngleAction' />"
2288 " <toolitem action='FixationAction' />"
2289 " <toolitem action='CapRoundingAction' />"
2290 " <separator />"
2291 " <toolitem action='TremorAction' />"
2292 " <toolitem action='WiggleAction' />"
2293 " <toolitem action='MassAction' />"
2294 " <separator />"
2295 " <toolitem action='TraceAction' />"
2296 " <toolitem action='PressureAction' />"
2297 " <toolitem action='TiltAction' />"
2298 " <toolitem action='ResetAction' />"
2299 " </toolbar>"
2300 "</ui>";
2301 GtkActionGroup* mainActions = gtk_action_group_new("main");
2303 {
2304 EgeAdjustmentAction* calligraphy_angle = 0;
2306 {
2307 /* Width */
2308 gchar const* labels[] = {_("(hairline)"), 0, 0, 0, _("(default)"), 0, 0, 0, 0, _("(broad stroke)")};
2309 gdouble values[] = {1, 3, 5, 10, 15, 20, 30, 50, 75, 100};
2310 EgeAdjustmentAction *eact = create_adjustment_action( "WidthAction",
2311 _("Width:"), _("The width of the calligraphic pen (relative to the visible canvas area)"),
2312 "tools.calligraphic", "width", 15,
2313 GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "altx-calligraphy",
2314 1, 100, 1.0, 10.0,
2315 labels, values, G_N_ELEMENTS(labels),
2316 sp_ddc_width_value_changed, 0.01, 0, 100 );
2317 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
2318 gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
2319 }
2321 {
2322 /* Thinning */
2323 gchar const* labels[] = {_("(speed blows up stroke)"), 0, 0, _("(slight widening)"), _("(constant width)"), _("(slight thinning, default)"), 0, 0, _("(speed deflates stroke)")};
2324 gdouble values[] = {-1, -0.4, -0.2, -0.1, 0, 0.1, 0.2, 0.4, 1};
2325 EgeAdjustmentAction* eact = create_adjustment_action( "ThinningAction",
2326 _("Thinning:"), _("How much velocity thins the stroke (> 0 makes fast strokes thinner, < 0 makes them broader, 0 makes width independent of velocity)"),
2327 "tools.calligraphic", "thinning", 0.1,
2328 GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
2329 -1.0, 1.0, 0.01, 0.1,
2330 labels, values, G_N_ELEMENTS(labels),
2331 sp_ddc_velthin_value_changed, 0.01, 2);
2332 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
2333 gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
2334 }
2336 {
2337 /* Angle */
2338 gchar const* labels[] = {_("(left edge up)"), 0, 0, _("(horizontal)"), _("(default)"), 0, _("(right edge up)")};
2339 gdouble values[] = {-90, -60, -30, 0, 30, 60, 90};
2340 EgeAdjustmentAction* eact = create_adjustment_action( "AngleAction",
2341 _("Angle:"), _("The angle of the pen's nib (in degrees; 0 = horizontal; has no effect if fixation = 0)"),
2342 "tools.calligraphic", "angle", 30,
2343 GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "calligraphy-angle",
2344 -90.0, 90.0, 1.0, 10.0,
2345 labels, values, G_N_ELEMENTS(labels),
2346 sp_ddc_angle_value_changed, 1, 0 );
2347 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
2348 gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
2349 calligraphy_angle = eact;
2350 }
2352 {
2353 /* Fixation */
2354 gchar const* labels[] = {_("(perpendicular to stroke, \"brush\")"), 0, 0, 0, _("(almost fixed, default)"), _("(fixed by Angle, \"pen\")")};
2355 gdouble values[] = {0, 0.2, 0.4, 0.6, 0.9, 1.0};
2356 EgeAdjustmentAction* eact = create_adjustment_action( "FixationAction",
2357 _("Fixation:"), _("Angle behavior (0 = nib always perpendicular to stroke direction, 1 = fixed angle)"),
2358 "tools.calligraphic", "flatness", 0.9,
2359 GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
2360 0.0, 1.0, 0.01, 0.1,
2361 labels, values, G_N_ELEMENTS(labels),
2362 sp_ddc_flatness_value_changed, 0.01, 2 );
2363 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
2364 gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
2365 }
2367 {
2368 /* Cap Rounding */
2369 gchar const* labels[] = {_("(blunt caps, default)"), _("(slightly bulging)"), 0, 0, _("(approximately round)"), _("(long protruding caps)")};
2370 gdouble values[] = {0, 0.3, 0.5, 1.0, 1.4, 5.0};
2371 // TRANSLATORS: "cap" means "end" (both start and finish) here
2372 EgeAdjustmentAction* eact = create_adjustment_action( "CapRoundingAction",
2373 _("Caps:"), _("Increase to make caps at the ends of strokes protrude more (0 = no caps, 1 = round caps)"),
2374 "tools.calligraphic", "cap_rounding", 0.0,
2375 GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
2376 0.0, 5.0, 0.01, 0.1,
2377 labels, values, G_N_ELEMENTS(labels),
2378 sp_ddc_cap_rounding_value_changed, 0.01, 2 );
2379 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
2380 gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
2381 }
2383 {
2384 /* Tremor */
2385 gchar const* labels[] = {_("(smooth line)"), _("(slight tremor)"), _("(noticeable tremor)"), 0, 0, _("(maximum tremor)")};
2386 gdouble values[] = {0, 0.1, 0.2, 0.4, 0.6, 1.0};
2387 EgeAdjustmentAction* eact = create_adjustment_action( "TremorAction",
2388 _("Tremor:"), _("Increase to make strokes rugged and trembling"),
2389 "tools.calligraphic", "tremor", 0.0,
2390 GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
2391 0.0, 1.0, 0.01, 0.1,
2392 labels, values, G_N_ELEMENTS(labels),
2393 sp_ddc_tremor_value_changed, 0.01, 2 );
2395 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
2396 gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
2397 }
2399 {
2400 /* Wiggle */
2401 gchar const* labels[] = {_("(no wiggle)"), _("(slight deviation)"), 0, 0, _("(wild waves and curls)")};
2402 gdouble values[] = {0, 0.2, 0.4, 0.6, 1.0};
2403 EgeAdjustmentAction* eact = create_adjustment_action( "WiggleAction",
2404 _("Wiggle:"), _("Increase to make the pen waver and wiggle"),
2405 "tools.calligraphic", "wiggle", 0.0,
2406 GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
2407 0.0, 1.0, 0.01, 0.1,
2408 labels, values, G_N_ELEMENTS(labels),
2409 sp_ddc_wiggle_value_changed, 0.01, 2 );
2410 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
2411 gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
2412 }
2414 {
2415 /* Mass */
2416 gchar const* labels[] = {_("(no inertia)"), _("(slight smoothing, default)"), _("(noticeable lagging)"), 0, 0, _("(maximum inertia)")};
2417 gdouble values[] = {0.0, 0.02, 0.1, 0.2, 0.5, 1.0};
2418 EgeAdjustmentAction* eact = create_adjustment_action( "MassAction",
2419 _("Mass:"), _("Increase to make the pen drag behind, as if slowed by inertia"),
2420 "tools.calligraphic", "mass", 0.02,
2421 GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
2422 0.0, 1.0, 0.01, 0.1,
2423 labels, values, G_N_ELEMENTS(labels),
2424 sp_ddc_mass_value_changed, 0.01, 2 );
2425 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
2426 gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
2427 }
2430 /* Trace Background button */
2431 {
2432 InkToggleAction* act = ink_toggle_action_new( "TraceAction",
2433 _("Trace Background"),
2434 _("Trace the lightness of the background by the width of the pen (white - minimum width, black - maximum width)"),
2435 "trace_background",
2436 Inkscape::ICON_SIZE_DECORATION );
2437 gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
2438 g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_ddc_trace_background_changed), NULL);
2439 gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs_get_int_attribute( "tools.calligraphic", "tracebackground", 0 ) );
2440 }
2442 /* Use Pressure button */
2443 {
2444 InkToggleAction* act = ink_toggle_action_new( "PressureAction",
2445 _("Pressure"),
2446 _("Use the pressure of the input device to alter the width of the pen"),
2447 "use_pressure",
2448 Inkscape::ICON_SIZE_DECORATION );
2449 gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
2450 g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_ddc_pressure_state_changed), NULL);
2451 gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs_get_int_attribute( "tools.calligraphic", "usepressure", 1 ) );
2452 }
2454 /* Use Tilt button */
2455 {
2456 InkToggleAction* act = ink_toggle_action_new( "TiltAction",
2457 _("Tilt"),
2458 _("Use the tilt of the input device to alter the angle of the pen's nib"),
2459 "use_tilt",
2460 Inkscape::ICON_SIZE_DECORATION );
2461 gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
2462 g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_ddc_tilt_state_changed), calligraphy_angle );
2463 gtk_action_set_sensitive( GTK_ACTION(calligraphy_angle), !prefs_get_int_attribute( "tools.calligraphic", "usetilt", 1 ) );
2464 gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs_get_int_attribute( "tools.calligraphic", "usetilt", 1 ) );
2465 }
2467 /* Reset */
2468 {
2469 GtkAction* act = gtk_action_new( "ResetAction",
2470 _("Defaults"),
2471 _("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"),
2472 GTK_STOCK_CLEAR );
2473 g_signal_connect_after( G_OBJECT(act), "activate", G_CALLBACK(sp_ddc_defaults), holder );
2474 gtk_action_group_add_action( mainActions, act );
2475 gtk_action_set_sensitive( act, TRUE );
2476 }
2477 }
2480 GtkUIManager* mgr = gtk_ui_manager_new();
2481 GError* errVal = 0;
2483 gtk_ui_manager_insert_action_group( mgr, mainActions, 0 );
2484 gtk_ui_manager_add_ui_from_string( mgr, descr, -1, &errVal );
2486 GtkWidget* toolBar = gtk_ui_manager_get_widget( mgr, "/ui/CalligraphyToolbar" );
2487 gtk_toolbar_set_style( GTK_TOOLBAR(toolBar), GTK_TOOLBAR_ICONS );
2488 gtk_toolbar_set_icon_size( GTK_TOOLBAR(toolBar), GTK_ICON_SIZE_SMALL_TOOLBAR );
2491 gtk_table_attach( GTK_TABLE(holder), toolBar, 0, 1, 0, 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 0, 0 );
2493 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL, _("Style of new calligraphic strokes"));
2494 swatch->setDesktop (desktop);
2495 swatch->setClickVerb (SP_VERB_CONTEXT_CALLIGRAPHIC_PREFS);
2496 swatch->setWatchedTool ("tools.calligraphic", true);
2497 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
2498 gtk_table_attach( GTK_TABLE(holder), swatch_, 1, 2, 0, 1, (GtkAttachOptions)(GTK_SHRINK | GTK_FILL), (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), AUX_BETWEEN_BUTTON_GROUPS, 0 );
2500 gtk_widget_show_all(holder);
2501 //sp_set_font_size_smaller (tbl);
2503 return holder;
2504 }
2507 //########################
2508 //## Circle / Arc ##
2509 //########################
2511 static void
2512 sp_arctb_sensitivize (GtkWidget *tbl, double v1, double v2)
2513 {
2514 GtkWidget *ocb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "open_checkbox");
2515 GtkWidget *make_whole = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "make_whole");
2517 if (v1 == 0 && v2 == 0) {
2518 if (gtk_object_get_data(GTK_OBJECT(tbl), "single")) { // only for a single selected ellipse (for now)
2519 gtk_widget_set_sensitive(GTK_WIDGET(ocb), FALSE);
2520 gtk_widget_set_sensitive(GTK_WIDGET(make_whole), FALSE);
2521 }
2522 } else {
2523 gtk_widget_set_sensitive(GTK_WIDGET(ocb), TRUE);
2524 gtk_widget_set_sensitive(GTK_WIDGET(make_whole), TRUE);
2525 }
2526 }
2528 static void
2529 sp_arctb_startend_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_name, gchar const *other_name)
2530 {
2531 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2533 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2534 prefs_set_double_attribute("tools.shapes.arc", value_name, (adj->value * M_PI)/ 180);
2535 }
2537 // quit if run by the attr_changed listener
2538 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2539 return;
2540 }
2542 // in turn, prevent listener from responding
2543 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2545 gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
2547 bool modmade = false;
2548 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2549 items != NULL;
2550 items = items->next)
2551 {
2552 SPItem *item = SP_ITEM(items->data);
2554 if (SP_IS_ARC(item) && SP_IS_GENERICELLIPSE(item)) {
2556 SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
2557 SPArc *arc = SP_ARC(item);
2559 if (!strcmp(value_name, "start"))
2560 ge->start = (adj->value * M_PI)/ 180;
2561 else
2562 ge->end = (adj->value * M_PI)/ 180;
2564 sp_genericellipse_normalize(ge);
2565 ((SPObject *)arc)->updateRepr();
2566 ((SPObject *)arc)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
2568 modmade = true;
2569 }
2570 }
2572 g_free(namespaced_name);
2574 GtkAdjustment *other = (GtkAdjustment *)gtk_object_get_data(GTK_OBJECT(tbl), other_name);
2576 sp_arctb_sensitivize (tbl, adj->value, other->value);
2578 if (modmade) {
2579 sp_document_maybe_done(sp_desktop_document(desktop), value_name, SP_VERB_CONTEXT_ARC,
2580 _("Arc: Change start/end"));
2581 }
2583 // defocus spinbuttons by moving focus to the canvas, unless "stay" is on
2584 spinbutton_defocus(GTK_OBJECT(tbl));
2586 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2587 }
2590 static void
2591 sp_arctb_start_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
2592 {
2593 sp_arctb_startend_value_changed(adj, tbl, "start", "end");
2594 }
2596 static void
2597 sp_arctb_end_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
2598 {
2599 sp_arctb_startend_value_changed(adj, tbl, "end", "start");
2600 }
2602 static void
2603 sp_arctb_open_state_changed(GtkWidget *widget, GtkObject *tbl)
2604 {
2605 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2607 if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2608 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
2609 prefs_set_string_attribute("tools.shapes.arc", "open", "true");
2610 } else {
2611 prefs_set_string_attribute("tools.shapes.arc", "open", NULL);
2612 }
2613 }
2615 // quit if run by the attr_changed listener
2616 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2617 return;
2618 }
2620 // in turn, prevent listener from responding
2621 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2623 bool modmade = false;
2625 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
2626 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2627 items != NULL;
2628 items = items->next)
2629 {
2630 if (SP_IS_ARC((SPItem *) items->data)) {
2631 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2632 repr->setAttribute("sodipodi:open", "true");
2633 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
2634 modmade = true;
2635 }
2636 }
2637 } else {
2638 for (GSList const *items = sp_desktop_selection(desktop)->itemList();
2639 items != NULL;
2640 items = items->next)
2641 {
2642 if (SP_IS_ARC((SPItem *) items->data)) {
2643 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2644 repr->setAttribute("sodipodi:open", NULL);
2645 SP_OBJECT((SPItem *) items->data)->updateRepr(repr, SP_OBJECT_WRITE_EXT);
2646 modmade = true;
2647 }
2648 }
2649 }
2651 if (modmade) {
2652 sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_ARC,
2653 _("Arc: Change open/closed"));
2654 }
2656 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2658 spinbutton_defocus(GTK_OBJECT(tbl));
2659 }
2661 static void sp_arctb_defaults(GtkWidget *, GtkObject *obj)
2662 {
2663 GtkWidget *tbl = GTK_WIDGET(obj);
2665 GtkAdjustment *adj;
2666 adj = (GtkAdjustment*)gtk_object_get_data(obj, "start");
2667 gtk_adjustment_set_value(adj, 0.0);
2668 gtk_adjustment_value_changed(adj);
2670 adj = (GtkAdjustment*)gtk_object_get_data(obj, "end");
2671 gtk_adjustment_set_value(adj, 0.0);
2672 gtk_adjustment_value_changed(adj);
2674 spinbutton_defocus(GTK_OBJECT(tbl));
2675 }
2677 static void arc_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
2678 gchar const *old_value, gchar const *new_value,
2679 bool is_interactive, gpointer data)
2680 {
2681 GtkWidget *tbl = GTK_WIDGET(data);
2683 // quit if run by the _changed callbacks
2684 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2685 return;
2686 }
2688 // in turn, prevent callbacks from responding
2689 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2691 gdouble start = sp_repr_get_double_attribute(repr, "sodipodi:start", 0.0);
2692 gdouble end = sp_repr_get_double_attribute(repr, "sodipodi:end", 0.0);
2694 GtkAdjustment *adj1,*adj2;
2695 adj1 = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "start");
2696 gtk_adjustment_set_value(adj1, mod360((start * 180)/M_PI));
2697 adj2 = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "end");
2698 gtk_adjustment_set_value(adj2, mod360((end * 180)/M_PI));
2700 sp_arctb_sensitivize (tbl, adj1->value, adj2->value);
2702 char const *openstr = NULL;
2703 openstr = repr->attribute("sodipodi:open");
2704 GtkWidget *ocb = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "open_checkbox");
2706 if (openstr) {
2707 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ocb), TRUE);
2708 } else {
2709 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ocb), FALSE);
2710 }
2712 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2713 }
2715 static Inkscape::XML::NodeEventVector arc_tb_repr_events = {
2716 NULL, /* child_added */
2717 NULL, /* child_removed */
2718 arc_tb_event_attr_changed,
2719 NULL, /* content_changed */
2720 NULL /* order_changed */
2721 };
2724 static void
2725 sp_arc_toolbox_selection_changed(Inkscape::Selection *selection, GtkObject *tbl)
2726 {
2727 int n_selected = 0;
2728 Inkscape::XML::Node *repr = NULL;
2729 Inkscape::XML::Node *oldrepr = NULL;
2731 for (GSList const *items = selection->itemList();
2732 items != NULL;
2733 items = items->next)
2734 {
2735 if (SP_IS_ARC((SPItem *) items->data)) {
2736 n_selected++;
2737 repr = SP_OBJECT_REPR((SPItem *) items->data);
2738 }
2739 }
2741 GtkWidget *l = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(tbl), "mode_label"));
2743 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(FALSE));
2744 if (n_selected == 0) {
2745 gtk_label_set_markup(GTK_LABEL(l), _("<b>New:</b>"));
2746 } else if (n_selected == 1) {
2747 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
2748 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2750 oldrepr = (Inkscape::XML::Node *) gtk_object_get_data(GTK_OBJECT(tbl), "repr");
2752 if (oldrepr) { // remove old listener
2753 sp_repr_remove_listener_by_data(oldrepr, tbl);
2754 Inkscape::GC::release(oldrepr);
2755 oldrepr = 0;
2756 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
2757 }
2759 if (repr) {
2760 g_object_set_data(G_OBJECT(tbl), "repr", repr);
2761 Inkscape::GC::anchor(repr);
2762 sp_repr_add_listener(repr, &arc_tb_repr_events, tbl);
2763 sp_repr_synthesize_events(repr, &arc_tb_repr_events, tbl);
2764 }
2765 } else {
2766 // FIXME: implement averaging of all parameters for multiple selected
2767 //gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
2768 gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2769 sp_arctb_sensitivize (GTK_WIDGET(tbl), 1, 0);
2770 }
2771 }
2774 static GtkWidget *
2775 sp_arc_toolbox_new(SPDesktop *desktop)
2776 {
2777 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2779 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2780 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2782 GtkTooltips *tt = gtk_tooltips_new();
2784 sp_toolbox_add_label(tbl, _("<b>New:</b>"));
2786 /* Start */
2787 {
2788 GtkWidget *hb = sp_tb_spinbutton(_("Start:"), _("The angle (in degrees) from the horizontal to the arc's start point"),
2789 "tools.shapes.arc", "start", 0.0,
2790 NULL, tbl, TRUE, "altx-arc",
2791 -360.0, 360.0, 1.0, 10.0,
2792 sp_arctb_start_value_changed);
2793 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2794 }
2796 /* End */
2797 {
2798 GtkWidget *hb = sp_tb_spinbutton(_("End:"), _("The angle (in degrees) from the horizontal to the arc's end point"),
2799 "tools.shapes.arc", "end", 0.0,
2800 NULL, tbl, FALSE, NULL,
2801 -360.0, 360.0, 1.0, 10.0,
2802 sp_arctb_end_value_changed);
2803 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2804 }
2806 /* Segments / Pie checkbox */
2807 {
2808 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2809 GtkWidget *fscb = gtk_check_button_new_with_label(_("Open arc"));
2810 gtk_tooltips_set_tip(tt, fscb, _("Switch between arc (unclosed shape) and segment (closed shape with two radii)"), NULL);
2812 gchar const *openstr = NULL;
2813 openstr = prefs_get_string_attribute("tools.shapes.arc", "open");
2814 if (!openstr || (openstr && !strcmp(openstr, "false")))
2815 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), FALSE);
2816 else
2817 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(fscb), TRUE);
2819 gtk_widget_show(fscb);
2820 gtk_object_set_data(GTK_OBJECT(tbl), "open_checkbox", fscb);
2821 gtk_container_add(GTK_CONTAINER(hb), fscb);
2822 g_signal_connect(G_OBJECT(fscb), "toggled", GTK_SIGNAL_FUNC(sp_arctb_open_state_changed ), tbl);
2823 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2824 }
2826 /* Make Whole */
2827 {
2828 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2829 GtkWidget *b = gtk_button_new_with_label(_("Make whole"));
2830 gtk_object_set_data(GTK_OBJECT(tbl), "make_whole", b);
2831 gtk_tooltips_set_tip(tt, b, _("Make the shape a whole ellipse, not arc or segment"), NULL);
2832 gtk_widget_show(b);
2833 gtk_container_add(GTK_CONTAINER(hb), b);
2834 gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(sp_arctb_defaults), tbl);
2835 gtk_box_pack_start(GTK_BOX(tbl),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
2836 }
2838 g_object_set_data(G_OBJECT(tbl), "single", GINT_TO_POINTER(TRUE));
2839 // sensitivize make whole and open checkbox
2840 {
2841 GtkAdjustment *adj1 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "start"));
2842 GtkAdjustment *adj2 = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "end"));
2843 sp_arctb_sensitivize (tbl, adj1->value, adj2->value);
2844 }
2846 sigc::connection *connection = new sigc::connection(
2847 sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_arc_toolbox_selection_changed), (GtkObject *)tbl))
2848 );
2849 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection), connection);
2851 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL, _("Style of new ellipses"));
2852 swatch->setDesktop (desktop);
2853 swatch->setClickVerb (SP_VERB_CONTEXT_ARC_PREFS);
2854 swatch->setWatchedTool ("tools.shapes.arc", true);
2855 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
2856 gtk_box_pack_end(GTK_BOX(tbl), swatch_, FALSE, FALSE, 0);
2858 gtk_widget_show_all(tbl);
2859 sp_set_font_size_smaller (tbl);
2861 return tbl;
2862 }
2867 // toggle button callbacks and updaters
2869 //########################
2870 //## Dropper ##
2871 //########################
2873 static void toggle_dropper_pick_alpha (GtkWidget *button, gpointer tbl) {
2874 prefs_set_int_attribute ("tools.dropper", "pick",
2875 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)));
2876 GtkWidget *set_checkbox = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "set_checkbox");
2877 if (set_checkbox) {
2878 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) {
2879 gtk_widget_set_sensitive (GTK_WIDGET (set_checkbox), TRUE);
2880 } else {
2881 gtk_widget_set_sensitive (GTK_WIDGET (set_checkbox), FALSE);
2882 }
2883 }
2884 spinbutton_defocus(GTK_OBJECT(tbl));
2885 }
2887 static void toggle_dropper_set_alpha (GtkWidget *button, gpointer tbl) {
2888 prefs_set_int_attribute ("tools.dropper", "setalpha",
2889 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0);
2890 spinbutton_defocus(GTK_OBJECT(tbl));
2891 }
2894 /**
2895 * Copy the current saved desktop color to the clipboard as full hex + alpha
2896 * color representation. This is useful for passing values between various
2897 * input boxes, or directly to xml.
2898 */
2899 /* static void
2900 sp_dropper_copy( GtkWidget *widget, GtkObject *obj)
2901 {
2902 GtkWidget *tbl = GTK_WIDGET(obj);
2904 SPDesktop *desktop =
2905 (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2908 sp_dropper_c32_color_copy( sp_desktop_get_color(desktop, true) );
2909 }*/
2912 /**
2913 * Copies currently saved desktop color to the clipboard as a hex value. This
2914 * is useful for editing webpages and needing a value quickly for web
2915 * colors.
2916 *
2917 * TODO: When the toggle of the dropper is set to not mix color against
2918 * page background, this still just gets the color of the page and
2919 * doesn't get the actual mixed against background which is needed
2920 * for the hex value ppl. want for web pages, etc.
2921 */
2923 /* static void
2924 sp_dropper_copy_as_hex ( GtkWidget *widget, GtkObject *obj)
2925 {
2926 GtkWidget *tbl = GTK_WIDGET(obj);
2928 SPDesktop *desktop =
2929 (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl), "desktop");
2931 sp_dropper_c32_color_copy_hex( sp_desktop_get_color(desktop, true) );
2932 }*/
2935 /**
2936 * Sets the input boxes with the changed color and opacity. This is used as a
2937 * callback for style changing.
2938 */
2939 /* static bool
2940 sp_style_changed (const SPCSSAttr *css, gpointer data)
2941 {
2942 // GrDrag *drag = (GrDrag *) data;
2944 // set fill of text entry box
2945 if (css->attribute("fill"))
2946 gtk_entry_set_text((GtkEntry *)dropper_rgb_entry,
2947 css->attribute("fill"));
2949 // set opacity of text entry box
2950 if (css->attribute("fill-opacity"))
2951 gtk_entry_set_text((GtkEntry *)dropper_opacity_entry,
2952 css->attribute("fill-opacity"));
2954 // set fill of text entry box
2955 if (css->attribute("stroke"))
2956 gtk_entry_set_text((GtkEntry *)dropper_rgb_entry,
2957 css->attribute("stroke"));
2959 // set opacity of text entry box
2960 if (css->attribute("stroke-opacity"))
2961 gtk_entry_set_text((GtkEntry *)dropper_opacity_entry,
2962 css->attribute("stroke-opacity"));
2963 return false;
2965 }
2966 */
2969 /**
2970 * Dropper auxiliary toolbar construction and setup.
2971 *
2972 * TODO: Would like to add swatch of current color.
2973 * TODO: Add queue of last 5 or so colors selected with new swatches so that
2974 * can drag and drop places. Will provide a nice mixing palette.
2975 */
2976 static GtkWidget *
2977 sp_dropper_toolbox_new(SPDesktop *desktop)
2978 {
2979 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
2981 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2982 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2984 GtkTooltips *tt = gtk_tooltips_new();
2987 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
2988 AUX_BETWEEN_BUTTON_GROUPS);
2989 // sp_toolbox_add_label(tbl, _("<b>New:</b>"));
2993 /* RGB Input Field */
2994 /* {
2995 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
2996 GtkWidget *dropper_rgba_label = gtk_label_new ("Color:");
2997 gtk_widget_show (dropper_rgba_label);
2998 gtk_container_add(GTK_CONTAINER(hb), dropper_rgba_label);
3000 dropper_rgb_entry = gtk_entry_new ();
3001 sp_dialog_defocus_on_enter (dropper_rgb_entry);
3002 gtk_entry_set_max_length (GTK_ENTRY (dropper_rgb_entry), 7);
3003 gtk_entry_set_width_chars (GTK_ENTRY (dropper_rgb_entry), 7);
3004 gtk_tooltips_set_tip(tt, dropper_rgb_entry,
3005 _("Hexidecimal representation of last selected "
3006 "color"),
3007 NULL);
3008 gtk_widget_show (dropper_rgb_entry);
3009 gtk_container_add(GTK_CONTAINER(hb), dropper_rgb_entry);
3011 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
3012 AUX_BETWEEN_BUTTON_GROUPS);
3013 } */
3015 /* Opacity Input Field */
3016 /* {
3017 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3018 GtkWidget *dropper_opacity_label = gtk_label_new ( _("Opacity:") );
3019 gtk_widget_show (dropper_opacity_label);
3020 gtk_container_add(GTK_CONTAINER(hb), dropper_opacity_label);
3022 dropper_opacity_entry = gtk_entry_new ();
3023 sp_dialog_defocus_on_enter (dropper_opacity_entry);
3024 gtk_entry_set_max_length (GTK_ENTRY (dropper_opacity_entry), 11);
3025 gtk_entry_set_width_chars (GTK_ENTRY (dropper_opacity_entry), 11);
3026 gtk_tooltips_set_tip(tt, dropper_opacity_entry,
3027 _("Opacity of last selected color"),
3028 NULL);
3029 gtk_widget_show (dropper_opacity_entry);
3030 gtk_container_add(GTK_CONTAINER(hb), dropper_opacity_entry);
3032 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
3033 AUX_BETWEEN_BUTTON_GROUPS);
3034 } */
3037 /* Copy to Clipboard */
3038 /* {
3039 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3040 GtkWidget *b = gtk_button_new_with_label(_("Copy as RGBA"));
3041 gtk_tooltips_set_tip(tt, b, _("Copy last saved color as hexidecimal "
3042 "RGB + Alpha (RGBA) to "
3043 "clipboard"),
3044 NULL);
3045 gtk_widget_show(b);
3046 gtk_container_add(GTK_CONTAINER(hb), b);
3047 gtk_signal_connect(GTK_OBJECT(b), "clicked",
3048 GTK_SIGNAL_FUNC(sp_dropper_copy), tbl);
3049 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
3050 AUX_BETWEEN_BUTTON_GROUPS);
3051 } */
3054 /* Copy to Clipboard as HEX */
3055 /* {
3056 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3057 GtkWidget *b = gtk_button_new_with_label(_("Copy as HEX"));
3058 gtk_tooltips_set_tip(tt, b, _("Copy last saved color as "
3059 "hexidecimal RGB without alpha "
3060 "to clipboard"), NULL);
3061 gtk_widget_show(b);
3062 gtk_container_add(GTK_CONTAINER(hb), b);
3063 gtk_signal_connect(GTK_OBJECT(b), "clicked",
3064 GTK_SIGNAL_FUNC(sp_dropper_copy_as_hex), tbl);
3065 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
3066 AUX_BETWEEN_BUTTON_GROUPS);
3067 } */
3069 // aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
3071 {
3072 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3074 GtkWidget *button = gtk_check_button_new_with_label(_("Pick alpha"));
3075 gtk_tooltips_set_tip(tt, button, _("Pick both the color and the alpha (transparency) under cursor; otherwise, pick only the visible color premultiplied by alpha"), NULL);
3076 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
3077 prefs_get_int_attribute ("tools.dropper",
3078 "pick", 1));
3079 gtk_widget_show(button);
3080 gtk_container_add (GTK_CONTAINER (hb), button);
3081 gtk_object_set_data(GTK_OBJECT(tbl), "pick_checkbox", button);
3082 g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK (toggle_dropper_pick_alpha), tbl);
3083 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
3084 AUX_BETWEEN_BUTTON_GROUPS);
3085 }
3087 {
3088 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
3090 GtkWidget *button = gtk_check_button_new_with_label(_("Set alpha"));
3091 gtk_tooltips_set_tip(tt, button, _("If alpha was picked, assign it to selection as fill or stroke transparency"), NULL);
3092 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
3093 prefs_get_int_attribute ("tools.dropper",
3094 "setalpha", 1));
3095 gtk_widget_show(button);
3096 gtk_container_add (GTK_CONTAINER (hb), button);
3097 gtk_object_set_data(GTK_OBJECT(tbl), "set_checkbox", button);
3098 g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK (toggle_dropper_set_alpha), tbl);
3100 // make sure it's disabled if we're not picking alpha
3101 GtkWidget *pick_checkbox = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "pick_checkbox");
3102 if (pick_checkbox) {
3103 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pick_checkbox))) {
3104 gtk_widget_set_sensitive (GTK_WIDGET (button), TRUE);
3105 } else {
3106 gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
3107 }
3108 }
3110 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE,
3111 AUX_BETWEEN_BUTTON_GROUPS);
3112 }
3114 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
3117 // where new gtkmm stuff should go
3119 gtk_widget_show_all(tbl);
3120 sp_set_font_size_smaller (tbl);
3122 /*
3123 sigc::connection *connection = new sigc::connection(
3124 desktop->connectSetStyle(
3125 sigc::bind(sigc::ptr_fun(sp_style_changed),
3126 desktop)) );
3128 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_connection),
3129 connection); */
3131 return tbl;
3132 }
3135 //########################
3136 //## Text Toolbox ##
3137 //########################
3138 /*
3139 static void
3140 sp_text_letter_changed(GtkAdjustment *adj, GtkWidget *tbl)
3141 {
3142 //Call back for letter sizing spinbutton
3143 }
3145 static void
3146 sp_text_line_changed(GtkAdjustment *adj, GtkWidget *tbl)
3147 {
3148 //Call back for line height spinbutton
3149 }
3151 static void
3152 sp_text_horiz_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
3153 {
3154 //Call back for horizontal kerning spinbutton
3155 }
3157 static void
3158 sp_text_vert_kern_changed(GtkAdjustment *adj, GtkWidget *tbl)
3159 {
3160 //Call back for vertical kerning spinbutton
3161 }
3163 static void
3164 sp_text_letter_rotation_changed(GtkAdjustment *adj, GtkWidget *tbl)
3165 {
3166 //Call back for letter rotation spinbutton
3167 }*/
3169 namespace {
3171 bool visible = false;
3173 void
3174 sp_text_toolbox_selection_changed (Inkscape::Selection *selection, GObject *tbl)
3175 {
3177 SPStyle *query =
3178 sp_style_new ();
3180 int result_family =
3181 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
3183 int result_style =
3184 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
3186 int result_numbers =
3187 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
3189 gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
3191 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
3192 if (result_family == QUERY_STYLE_NOTHING || result_style == QUERY_STYLE_NOTHING || result_numbers == QUERY_STYLE_NOTHING)
3193 {
3194 Inkscape::XML::Node *repr = inkscape_get_repr (INKSCAPE, "tools.text");
3196 if (repr)
3197 {
3198 sp_style_read_from_repr (query, repr);
3199 }
3200 else
3201 {
3202 return;
3203 }
3204 }
3206 if (query->text)
3207 {
3208 if (result_family == QUERY_STYLE_MULTIPLE_DIFFERENT) {
3209 GtkWidget *entry = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "family-entry"));
3210 gtk_entry_set_text (GTK_ENTRY (entry), "");
3212 } else if (query->text->font_family.value) {
3214 GtkWidget *entry = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "family-entry"));
3215 gtk_entry_set_text (GTK_ENTRY (entry), query->text->font_family.value);
3217 Gtk::TreePath path;
3218 try {
3219 path = Inkscape::FontLister::get_instance()->get_row_for_font (query->text->font_family.value);
3220 } catch (...) {
3221 return;
3222 }
3224 GtkTreeSelection *tselection = GTK_TREE_SELECTION (g_object_get_data (G_OBJECT(tbl), "family-tree-selection"));
3225 GtkTreeView *treeview = GTK_TREE_VIEW (g_object_get_data (G_OBJECT(tbl), "family-tree-view"));
3227 g_object_set_data (G_OBJECT (tselection), "block", gpointer(1));
3229 gtk_tree_selection_select_path (tselection, path.gobj());
3230 gtk_tree_view_scroll_to_cell (treeview, path.gobj(), NULL, TRUE, 0.5, 0.0);
3232 g_object_set_data (G_OBJECT (tselection), "block", gpointer(0));
3233 }
3235 //Size
3236 GtkWidget *cbox = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "combo-box-size"));
3237 char *str = g_strdup_printf ("%.5g", query->font_size.computed);
3238 g_object_set_data (tbl, "size-block", gpointer(1));
3239 gtk_entry_set_text (GTK_ENTRY(GTK_BIN (cbox)->child), str);
3240 g_object_set_data (tbl, "size-block", gpointer(0));
3241 free (str);
3243 //Anchor
3244 if (query->text_align.computed == SP_CSS_TEXT_ALIGN_JUSTIFY)
3245 {
3246 GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-fill"));
3247 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
3248 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
3249 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
3250 }
3251 else
3252 {
3253 if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_START)
3254 {
3255 GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-start"));
3256 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
3257 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
3258 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
3259 }
3260 else if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_MIDDLE)
3261 {
3262 GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-middle"));
3263 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
3264 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
3265 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
3266 }
3267 else if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_END)
3268 {
3269 GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "text-end"));
3270 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
3271 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
3272 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
3273 }
3274 }
3276 //Style
3277 {
3278 GtkToggleButton *button = GTK_TOGGLE_BUTTON (g_object_get_data (G_OBJECT (tbl), "style-bold"));
3280 gboolean active = gtk_toggle_button_get_active (button);
3281 gboolean check = (query->font_weight.computed >= SP_CSS_FONT_WEIGHT_700);
3283 if (active != check)
3284 {
3285 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
3286 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), check);
3287 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
3288 }
3289 }
3291 {
3292 GtkToggleButton *button = GTK_TOGGLE_BUTTON (g_object_get_data (G_OBJECT (tbl), "style-italic"));
3294 gboolean active = gtk_toggle_button_get_active (button);
3295 gboolean check = (query->font_style.computed != SP_CSS_FONT_STYLE_NORMAL);
3297 if (active != check)
3298 {
3299 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
3300 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), check);
3301 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
3302 }
3303 }
3305 //Orientation
3306 //locking both buttons, changing one affect all group (both)
3307 GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "orientation-horizontal"));
3308 g_object_set_data (G_OBJECT (button), "block", gpointer(1));
3310 GtkWidget *button1 = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "orientation-vertical"));
3311 g_object_set_data (G_OBJECT (button1), "block", gpointer(1));
3313 if (query->writing_mode.computed == SP_CSS_WRITING_MODE_LR_TB)
3314 {
3315 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
3316 }
3317 else
3318 {
3319 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button1), TRUE);
3320 }
3321 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
3322 g_object_set_data (G_OBJECT (button1), "block", gpointer(0));
3323 }
3324 }
3326 void
3327 sp_text_toolbox_selection_modified (Inkscape::Selection *selection, guint flags, GObject *tbl)
3328 {
3329 sp_text_toolbox_selection_changed (selection, tbl);
3330 }
3332 void
3333 sp_text_toolbox_subselection_changed (gpointer dragger, GObject *tbl)
3334 {
3335 sp_text_toolbox_selection_changed (NULL, tbl);
3336 }
3338 void
3339 sp_text_toolbox_family_changed (GtkTreeSelection *selection,
3340 GObject *tbl)
3341 {
3342 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3343 GtkTreeModel *model = 0;
3344 GtkWidget *popdown = GTK_WIDGET (g_object_get_data (tbl, "family-popdown-window"));
3345 GtkWidget *entry = GTK_WIDGET (g_object_get_data (tbl, "family-entry"));
3346 GtkTreeIter iter;
3347 char *family = 0;
3349 gdk_pointer_ungrab (GDK_CURRENT_TIME);
3350 gdk_keyboard_ungrab (GDK_CURRENT_TIME);
3352 if ( !gtk_tree_selection_get_selected( selection, &model, &iter ) ) {
3353 return;
3354 }
3356 gtk_tree_model_get (model, &iter, 0, &family, -1);
3358 if (g_object_get_data (G_OBJECT (selection), "block"))
3359 {
3360 gtk_entry_set_text (GTK_ENTRY (entry), family);
3361 return;
3362 }
3364 gtk_widget_hide (popdown);
3365 visible = false;
3367 gtk_entry_set_text (GTK_ENTRY (entry), family);
3369 SPStyle *query =
3370 sp_style_new ();
3372 int result_numbers =
3373 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
3375 SPCSSAttr *css = sp_repr_css_attr_new ();
3376 sp_repr_css_set_property (css, "font-family", family);
3378 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
3379 if (result_numbers == QUERY_STYLE_NOTHING)
3380 {
3381 sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
3382 sp_text_edit_dialog_default_set_insensitive (); //FIXME: Replace trough a verb
3383 }
3384 else
3385 {
3386 sp_desktop_set_style (desktop, css, true, true);
3387 }
3389 sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
3390 _("Text: Change font family"));
3391 sp_repr_css_attr_unref (css);
3392 free (family);
3393 gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
3395 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3396 }
3398 void
3399 sp_text_toolbox_family_entry_activate (GtkEntry *entry,
3400 GObject *tbl)
3401 {
3402 const char *family = gtk_entry_get_text (entry);
3404 try {
3405 Gtk::TreePath path = Inkscape::FontLister::get_instance()->get_row_for_font (family);
3406 GtkTreeSelection *selection = GTK_TREE_SELECTION (g_object_get_data (G_OBJECT(tbl), "family-tree-selection"));
3407 GtkTreeView *treeview = GTK_TREE_VIEW (g_object_get_data (G_OBJECT(tbl), "family-tree-view"));
3408 gtk_tree_selection_select_path (selection, path.gobj());
3409 gtk_tree_view_scroll_to_cell (treeview, path.gobj(), NULL, TRUE, 0.5, 0.0);
3410 gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
3411 } catch (...) {
3412 if (family && strlen (family))
3413 {
3414 gtk_widget_show_all (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
3415 }
3416 }
3417 }
3419 void
3420 sp_text_toolbox_anchoring_toggled (GtkRadioButton *button,
3421 gpointer data)
3422 {
3423 if (g_object_get_data (G_OBJECT (button), "block")) return;
3424 if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) return;
3425 int prop = GPOINTER_TO_INT(data);
3427 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3428 SPCSSAttr *css = sp_repr_css_attr_new ();
3430 switch (prop)
3431 {
3432 case 0:
3433 {
3434 sp_repr_css_set_property (css, "text-anchor", "start");
3435 sp_repr_css_set_property (css, "text-align", "start");
3436 break;
3437 }
3438 case 1:
3439 {
3440 sp_repr_css_set_property (css, "text-anchor", "middle");
3441 sp_repr_css_set_property (css, "text-align", "center");
3442 break;
3443 }
3445 case 2:
3446 {
3447 sp_repr_css_set_property (css, "text-anchor", "end");
3448 sp_repr_css_set_property (css, "text-align", "end");
3449 break;
3450 }
3452 case 3:
3453 {
3454 sp_repr_css_set_property (css, "text-anchor", "start");
3455 sp_repr_css_set_property (css, "text-align", "justify");
3456 break;
3457 }
3458 }
3460 SPStyle *query =
3461 sp_style_new ();
3462 int result_numbers =
3463 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
3465 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
3466 if (result_numbers == QUERY_STYLE_NOTHING)
3467 {
3468 sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
3469 }
3471 sp_desktop_set_style (desktop, css, true, true);
3472 sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
3473 _("Text: Change alignment"));
3474 sp_repr_css_attr_unref (css);
3476 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3477 }
3479 void
3480 sp_text_toolbox_style_toggled (GtkToggleButton *button,
3481 gpointer data)
3482 {
3483 if (g_object_get_data (G_OBJECT (button), "block")) return;
3485 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3486 SPCSSAttr *css = sp_repr_css_attr_new ();
3487 int prop = GPOINTER_TO_INT(data);
3488 bool active = gtk_toggle_button_get_active (button);
3491 switch (prop)
3492 {
3493 case 0:
3494 {
3495 sp_repr_css_set_property (css, "font-weight", active ? "bold" : "normal" );
3496 break;
3497 }
3499 case 1:
3500 {
3501 sp_repr_css_set_property (css, "font-style", active ? "italic" : "normal");
3502 break;
3503 }
3504 }
3506 SPStyle *query =
3507 sp_style_new ();
3508 int result_numbers =
3509 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
3511 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
3512 if (result_numbers == QUERY_STYLE_NOTHING)
3513 {
3514 sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
3515 }
3517 sp_desktop_set_style (desktop, css, true, true);
3518 sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
3519 _("Text: Change font style"));
3520 sp_repr_css_attr_unref (css);
3522 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3523 }
3525 void
3526 sp_text_toolbox_orientation_toggled (GtkRadioButton *button,
3527 gpointer data)
3528 {
3529 if (g_object_get_data (G_OBJECT (button), "block")) {
3530 g_object_set_data (G_OBJECT (button), "block", gpointer(0));
3531 return;
3532 }
3534 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3535 SPCSSAttr *css = sp_repr_css_attr_new ();
3536 int prop = GPOINTER_TO_INT(data);
3538 switch (prop)
3539 {
3540 case 0:
3541 {
3542 sp_repr_css_set_property (css, "writing-mode", "lr");
3543 break;
3544 }
3546 case 1:
3547 {
3548 sp_repr_css_set_property (css, "writing-mode", "tb");
3549 break;
3550 }
3551 }
3553 SPStyle *query =
3554 sp_style_new ();
3555 int result_numbers =
3556 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
3558 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
3559 if (result_numbers == QUERY_STYLE_NOTHING)
3560 {
3561 sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
3562 }
3564 sp_desktop_set_style (desktop, css, true, true);
3565 sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
3566 _("Text: Change orientation"));
3567 sp_repr_css_attr_unref (css);
3569 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3570 }
3572 gboolean
3573 sp_text_toolbox_size_keypress (GtkWidget *w, GdkEventKey *event, gpointer data)
3574 {
3575 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3576 if (!desktop) return FALSE;
3578 switch (get_group0_keyval (event)) {
3579 case GDK_Escape: // defocus
3580 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3581 return TRUE; // I consumed the event
3582 break;
3583 case GDK_Return: // defocus
3584 case GDK_KP_Enter:
3585 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3586 return TRUE; // I consumed the event
3587 break;
3588 }
3589 return FALSE;
3590 }
3592 gboolean
3593 sp_text_toolbox_family_keypress (GtkWidget *w, GdkEventKey *event, GObject *tbl)
3594 {
3595 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3596 if (!desktop) return FALSE;
3598 switch (get_group0_keyval (event)) {
3599 case GDK_Escape: // defocus
3600 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3601 sp_text_toolbox_selection_changed (NULL, tbl); // update
3602 return TRUE; // I consumed the event
3603 break;
3604 }
3605 return FALSE;
3606 }
3608 gboolean
3609 sp_text_toolbox_family_list_keypress (GtkWidget *w, GdkEventKey *event, GObject *tbl)
3610 {
3611 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3612 if (!desktop) return FALSE;
3614 switch (get_group0_keyval (event)) {
3615 case GDK_Escape: // defocus
3616 gtk_widget_hide (w);
3617 visible = false;
3618 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3619 return TRUE; // I consumed the event
3620 break;
3621 }
3622 return FALSE;
3623 }
3626 void
3627 sp_text_toolbox_size_changed (GtkComboBox *cbox,
3628 GObject *tbl)
3629 {
3630 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3632 if (g_object_get_data (tbl, "size-block")) return;
3634 #if GTK_CHECK_VERSION(2,6,0)
3635 char *text = gtk_combo_box_get_active_text (cbox);
3636 #else // GTK_CHECK_VERSION(2,6,0)
3637 GtkTreeModel *model = gtk_combo_box_get_model (cbox);
3638 GtkTreeIter iter;
3639 char *text = NULL;
3641 if (gtk_combo_box_get_active_iter (cbox, &iter) && model)
3642 gtk_tree_model_get (model, &iter, 0, &text, -1);
3643 #endif // GTK_CHECK_VERSION(2,6,0)
3645 SPCSSAttr *css = sp_repr_css_attr_new ();
3646 sp_repr_css_set_property (css, "font-size", text);
3647 free (text);
3649 SPStyle *query =
3650 sp_style_new ();
3651 int result_numbers =
3652 sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
3654 // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
3655 if (result_numbers == QUERY_STYLE_NOTHING)
3656 {
3657 sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
3658 }
3660 sp_desktop_set_style (desktop, css, true, true);
3661 sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:size", SP_VERB_NONE,
3662 _("Text: Change font size"));
3663 sp_repr_css_attr_unref (css);
3666 if (gtk_combo_box_get_active (cbox) > 0) // if this was from drop-down (as opposed to type-in), defocus
3667 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3668 }
3670 void
3671 sp_text_toolbox_text_popdown_clicked (GtkButton *button,
3672 GObject *tbl)
3673 {
3674 GtkWidget *popdown = GTK_WIDGET (g_object_get_data (tbl, "family-popdown-window"));
3675 GtkWidget *widget = GTK_WIDGET (g_object_get_data (tbl, "family-entry"));
3676 int x, y;
3678 if (!visible)
3679 {
3680 gdk_window_get_origin (widget->window, &x, &y);
3681 gtk_window_move (GTK_WINDOW (popdown), x, y + widget->allocation.height + 2); //2px of grace space
3682 gtk_widget_show_all (popdown);
3684 gdk_pointer_grab (widget->window, TRUE,
3685 GdkEventMask (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
3686 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
3687 GDK_POINTER_MOTION_MASK),
3688 NULL, NULL, GDK_CURRENT_TIME);
3690 gdk_keyboard_grab (widget->window, TRUE, GDK_CURRENT_TIME);
3692 visible = true;
3693 }
3694 else
3695 {
3696 gdk_pointer_ungrab (GDK_CURRENT_TIME);
3697 gdk_keyboard_ungrab (GDK_CURRENT_TIME);
3698 gtk_widget_hide (popdown);
3699 visible = false;
3700 }
3701 }
3703 gboolean
3704 sp_text_toolbox_entry_focus_in (GtkWidget *entry,
3705 GdkEventFocus *event,
3706 GObject *tbl)
3707 {
3708 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
3709 return FALSE;
3710 }
3712 gboolean
3713 sp_text_toolbox_popdown_focus_out (GtkWidget *popdown,
3714 GdkEventFocus *event,
3715 GObject *tbl)
3716 {
3717 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3719 gtk_widget_hide (popdown);
3720 visible = false;
3721 gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
3722 return TRUE;
3723 }
3725 void
3726 cell_data_func (GtkTreeViewColumn *column,
3727 GtkCellRenderer *cell,
3728 GtkTreeModel *tree_model,
3729 GtkTreeIter *iter,
3730 gpointer data)
3731 {
3732 char *family,
3733 *family_escaped,
3734 *sample_escaped;
3736 static const char *sample = _("AaBbCcIiPpQq12369$\342\202\254\302\242?.;/()");
3738 gtk_tree_model_get (tree_model, iter, 0, &family, -1);
3740 family_escaped = g_markup_escape_text (family, -1);
3741 sample_escaped = g_markup_escape_text (sample, -1);
3743 std::stringstream markup;
3744 markup << family_escaped << " <span foreground='darkgray' font_family='" << family_escaped << "'>" << sample_escaped << "</span>";
3745 g_object_set (G_OBJECT (cell), "markup", markup.str().c_str(), NULL);
3747 free (family);
3748 free (family_escaped);
3749 free (sample_escaped);
3750 }
3752 static void delete_completion(GObject *obj, GtkWidget *entry) {
3753 GObject *completion = (GObject *) gtk_object_get_data(GTK_OBJECT(entry), "completion");
3754 if (completion) {
3755 gtk_entry_set_completion (GTK_ENTRY(entry), NULL);
3756 g_object_unref (completion);
3757 }
3758 }
3760 GtkWidget*
3761 sp_text_toolbox_new (SPDesktop *desktop)
3762 {
3763 GtkWidget *tbl = gtk_hbox_new (FALSE, 0);
3765 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
3766 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
3768 GtkTooltips *tt = gtk_tooltips_new();
3769 Glib::RefPtr<Gtk::ListStore> store = Inkscape::FontLister::get_instance()->get_font_list();
3771 ////////////Family
3772 //Window
3773 GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3774 gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
3776 //Entry
3777 GtkWidget *entry = gtk_entry_new ();
3778 gtk_object_set_data(GTK_OBJECT(entry), "altx-text", entry);
3779 GtkEntryCompletion *completion = gtk_entry_completion_new ();
3780 gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (Glib::unwrap(store)));
3781 gtk_entry_completion_set_text_column (completion, 0);
3782 gtk_entry_completion_set_minimum_key_length (completion, 1);
3783 g_object_set (G_OBJECT(completion), "inline-completion", TRUE, "popup-completion", TRUE, NULL);
3784 gtk_entry_set_completion (GTK_ENTRY(entry), completion);
3785 gtk_object_set_data(GTK_OBJECT(entry), "completion", completion);
3786 aux_toolbox_space (tbl, 1);
3787 gtk_box_pack_start (GTK_BOX (tbl), entry, FALSE, FALSE, 0);
3788 g_signal_connect(G_OBJECT(tbl), "destroy", G_CALLBACK(delete_completion), entry);
3790 //Button
3791 GtkWidget *button = gtk_button_new ();
3792 gtk_container_add (GTK_CONTAINER (button), gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE));
3793 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, 0);
3795 //Popdown
3796 GtkWidget *sw = gtk_scrolled_window_new (NULL, NULL);
3797 GtkWidget *treeview = gtk_tree_view_new ();
3799 GtkCellRenderer *cell = gtk_cell_renderer_text_new ();
3800 GtkTreeViewColumn *column = gtk_tree_view_column_new ();
3801 gtk_tree_view_column_pack_start (column, cell, FALSE);
3802 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
3803 gtk_tree_view_column_set_cell_data_func (column, cell, GtkTreeCellDataFunc (cell_data_func), NULL, NULL);
3804 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
3806 gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (Glib::unwrap(store)));
3807 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
3808 #if GTK_CHECK_VERSION(2,6,0)
3809 gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (treeview), TRUE);
3810 #endif // GTK_CHECK_VERSION(2,6,0)
3812 //gtk_tree_view_set_enable_search (GTK_TREE_VIEW (treeview), TRUE);
3814 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
3815 gtk_container_add (GTK_CONTAINER (sw), treeview);
3817 gtk_container_add (GTK_CONTAINER (window), sw);
3818 gtk_widget_set_size_request (window, 300, 450);
3820 g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (sp_text_toolbox_family_entry_activate), tbl);
3821 g_signal_connect (G_OBJECT (entry), "focus-in-event", G_CALLBACK (sp_text_toolbox_entry_focus_in), tbl);
3822 g_signal_connect (G_OBJECT (entry), "key-press-event", G_CALLBACK(sp_text_toolbox_family_keypress), tbl);
3824 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (sp_text_toolbox_text_popdown_clicked), tbl);
3826 g_signal_connect (G_OBJECT (window), "focus-out-event", G_CALLBACK (sp_text_toolbox_popdown_focus_out), tbl);
3827 g_signal_connect (G_OBJECT (window), "key-press-event", G_CALLBACK(sp_text_toolbox_family_list_keypress), tbl);
3829 GtkTreeSelection *tselection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
3830 g_signal_connect (G_OBJECT (tselection), "changed", G_CALLBACK (sp_text_toolbox_family_changed), tbl);
3832 g_object_set_data (G_OBJECT (tbl), "family-entry", entry);
3833 g_object_set_data (G_OBJECT (tbl), "family-popdown-button", button);
3834 g_object_set_data (G_OBJECT (tbl), "family-popdown-window", window);
3835 g_object_set_data (G_OBJECT (tbl), "family-tree-selection", tselection);
3836 g_object_set_data (G_OBJECT (tbl), "family-tree-view", treeview);
3838 GtkWidget *image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
3839 aux_toolbox_space (tbl, 1);
3840 GtkWidget *box = gtk_event_box_new ();
3841 gtk_container_add (GTK_CONTAINER (box), image);
3842 gtk_box_pack_start (GTK_BOX (tbl), box, FALSE, FALSE, 4);
3843 g_object_set_data (G_OBJECT (tbl), "warning-image", box);
3844 GtkTooltips *tooltips = gtk_tooltips_new ();
3845 gtk_tooltips_set_tip (tooltips, box, _("This font is currently not installed on your system. Inkscape will use the default font instead."), "");
3846 gtk_widget_hide (GTK_WIDGET (box));
3847 g_signal_connect_swapped (G_OBJECT (tbl), "show", G_CALLBACK (gtk_widget_hide), box);
3849 ////////////Size
3850 const char *sizes[] = {
3851 "4", "6", "8", "9", "10", "11", "12", "13", "14",
3852 "16", "18", "20", "22", "24", "28",
3853 "32", "36", "40", "48", "56", "64", "72", "144"
3854 };
3856 GtkWidget *cbox = gtk_combo_box_entry_new_text ();
3857 for (unsigned int n = 0; n < G_N_ELEMENTS (sizes); gtk_combo_box_append_text (GTK_COMBO_BOX(cbox), sizes[n++]));
3858 gtk_widget_set_size_request (cbox, 80, -1);
3859 aux_toolbox_space (tbl, 1);
3860 gtk_box_pack_start (GTK_BOX (tbl), cbox, FALSE, FALSE, 0);
3861 g_object_set_data (G_OBJECT (tbl), "combo-box-size", cbox);
3862 g_signal_connect (G_OBJECT (cbox), "changed", G_CALLBACK (sp_text_toolbox_size_changed), tbl);
3863 gtk_signal_connect(GTK_OBJECT(cbox), "key-press-event", GTK_SIGNAL_FUNC(sp_text_toolbox_size_keypress), NULL);
3865 //spacer
3866 aux_toolbox_space (tbl, 4);
3867 gtk_box_pack_start (GTK_BOX (tbl), gtk_vseparator_new (), FALSE, FALSE, 4);
3869 ////////////Text anchor
3870 GtkWidget *group = gtk_radio_button_new (NULL);
3871 GtkWidget *row = gtk_hbox_new (FALSE, 4);
3872 g_object_set_data (G_OBJECT (tbl), "anchor-group", group);
3874 // left
3875 GtkWidget *rbutton = group;
3876 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3877 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_LEFT, GTK_ICON_SIZE_SMALL_TOOLBAR));
3878 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3880 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3881 g_object_set_data (G_OBJECT (tbl), "text-start", rbutton);
3882 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer(0));
3883 gtk_tooltips_set_tip(tt, rbutton, _("Align left"), NULL);
3885 // center
3886 rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3887 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3888 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_CENTER, GTK_ICON_SIZE_SMALL_TOOLBAR));
3889 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3891 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3892 g_object_set_data (G_OBJECT (tbl), "text-middle", rbutton);
3893 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer (1));
3894 gtk_tooltips_set_tip(tt, rbutton, _("Center"), NULL);
3896 // right
3897 rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3898 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3899 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_RIGHT, GTK_ICON_SIZE_SMALL_TOOLBAR));
3900 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3902 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3903 g_object_set_data (G_OBJECT (tbl), "text-end", rbutton);
3904 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer(2));
3905 gtk_tooltips_set_tip(tt, rbutton, _("Align right"), NULL);
3907 // fill
3908 rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3909 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3910 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_JUSTIFY_FILL, GTK_ICON_SIZE_SMALL_TOOLBAR));
3911 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3913 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3914 g_object_set_data (G_OBJECT (tbl), "text-fill", rbutton);
3915 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_anchoring_toggled), gpointer(3));
3916 gtk_tooltips_set_tip(tt, rbutton, _("Justify"), NULL);
3918 aux_toolbox_space (tbl, 1);
3919 gtk_box_pack_start (GTK_BOX (tbl), row, FALSE, FALSE, 4);
3921 //spacer
3922 gtk_box_pack_start (GTK_BOX (tbl), gtk_vseparator_new (), FALSE, FALSE, 4);
3924 ////////////Text style
3925 row = gtk_hbox_new (FALSE, 4);
3927 // bold
3928 rbutton = gtk_toggle_button_new ();
3929 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3930 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_BOLD, GTK_ICON_SIZE_SMALL_TOOLBAR));
3931 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3932 gtk_tooltips_set_tip(tt, rbutton, _("Bold"), NULL);
3934 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3935 g_object_set_data (G_OBJECT (tbl), "style-bold", rbutton);
3936 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_style_toggled), gpointer(0));
3938 // italic
3939 rbutton = gtk_toggle_button_new ();
3940 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3941 gtk_container_add (GTK_CONTAINER (rbutton), gtk_image_new_from_stock (GTK_STOCK_ITALIC, GTK_ICON_SIZE_SMALL_TOOLBAR));
3942 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3943 gtk_tooltips_set_tip(tt, rbutton, _("Italic"), NULL);
3945 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3946 g_object_set_data (G_OBJECT (tbl), "style-italic", rbutton);
3947 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_style_toggled), gpointer (1));
3949 aux_toolbox_space (tbl, 1);
3950 gtk_box_pack_start (GTK_BOX (tbl), row, FALSE, FALSE, 4);
3952 //spacer
3953 gtk_box_pack_start (GTK_BOX (tbl), gtk_vseparator_new (), FALSE, FALSE, 4);
3955 ////////////Text orientation
3956 group = gtk_radio_button_new (NULL);
3957 row = gtk_hbox_new (FALSE, 4);
3958 g_object_set_data (G_OBJECT (tbl), "orientation-group", group);
3960 // horizontal
3961 rbutton = group;
3962 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3963 gtk_container_add (GTK_CONTAINER (rbutton), sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_LR));
3964 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3965 gtk_tooltips_set_tip(tt, rbutton, _("Horizontal text"), NULL);
3967 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3968 g_object_set_data (G_OBJECT (tbl), "orientation-horizontal", rbutton);
3969 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_orientation_toggled), gpointer(0));
3971 // vertical
3972 rbutton = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
3973 gtk_button_set_relief (GTK_BUTTON (rbutton), GTK_RELIEF_NONE);
3974 gtk_container_add (GTK_CONTAINER (rbutton), sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_TB));
3975 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (rbutton), FALSE);
3976 gtk_tooltips_set_tip(tt, rbutton, _("Vertical text"), NULL);
3978 gtk_box_pack_start (GTK_BOX (row), rbutton, FALSE, FALSE, 0);
3979 g_object_set_data (G_OBJECT (tbl), "orientation-vertical", rbutton);
3980 g_signal_connect (G_OBJECT (rbutton), "toggled", G_CALLBACK (sp_text_toolbox_orientation_toggled), gpointer (1));
3981 gtk_box_pack_start (GTK_BOX (tbl), row, FALSE, FALSE, 4);
3984 //watch selection
3985 Inkscape::ConnectionPool* pool = Inkscape::ConnectionPool::new_connection_pool ("ISTextToolbox");
3987 sigc::connection *c_selection_changed =
3988 new sigc::connection (sp_desktop_selection (desktop)->connectChanged
3989 (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_changed), (GObject*)tbl)));
3990 pool->add_connection ("selection-changed", c_selection_changed);
3992 sigc::connection *c_selection_modified =
3993 new sigc::connection (sp_desktop_selection (desktop)->connectModified
3994 (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_modified), (GObject*)tbl)));
3995 pool->add_connection ("selection-modified", c_selection_modified);
3997 sigc::connection *c_subselection_changed =
3998 new sigc::connection (desktop->connectToolSubselectionChanged
3999 (sigc::bind (sigc::ptr_fun (sp_text_toolbox_subselection_changed), (GObject*)tbl)));
4000 pool->add_connection ("tool-subselection-changed", c_subselection_changed);
4002 Inkscape::ConnectionPool::connect_destroy (G_OBJECT (tbl), pool);
4005 #if 0
4006 // horizontal
4007 {
4008 GtkWidget *px= sp_icon_new(Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_LR);
4009 GtkWidget *b = group = gtk_radio_button_new (NULL);
4010 gtk_container_add (GTK_CONTAINER (b), px);
4011 gtk_tooltips_set_tip (tt, b, _("Horizontal text"), NULL);
4012 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
4013 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
4014 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
4015 }
4017 // vertical
4018 {
4019 GtkWidget *px = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_TB);
4020 GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
4021 gtk_container_add (GTK_CONTAINER (b), px);
4022 gtk_tooltips_set_tip (tt, b, _("Vertical text"), NULL);
4023 gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
4024 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
4025 gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
4026 }
4028 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
4030 // letter spacing
4031 {
4032 {
4033 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LETTER_SPACING);
4034 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
4035 gtk_container_add (GTK_CONTAINER (hb), image);
4036 gtk_widget_show(image);
4037 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
4038 }
4040 {
4041 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Spacing between letters"),
4042 "tools.text", "letter_spacing", 0.0,
4043 us, tbl, FALSE, NULL,
4044 -1000.0, 1000.0, 0.1, 0.1,
4045 sp_text_letter_changed, 0.1, 1);
4046 gtk_widget_set_size_request (hb, 45, 6);
4047 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
4048 }
4049 }
4051 // line spacing
4052 {
4053 {
4054 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LINE_SPACING);
4055 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
4056 gtk_container_add (GTK_CONTAINER (hb), image);
4057 gtk_widget_show(image);
4058 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
4059 }
4061 {
4062 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Spacing between lines"),
4063 "tools.text", "line_spacing", 0,
4064 us, tbl, FALSE, NULL,
4065 -1000.0, 1000.0, 0.1, 0.1,
4066 sp_text_line_changed, 0.1, 1);
4067 gtk_widget_set_size_request (hb, 45, 0);
4068 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 3);
4069 }
4070 }
4072 {
4073 // horizontal kerning/vertical kerning units menu: create
4074 GtkWidget *us = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
4075 sp_unit_selector_setsize(us, AUX_OPTION_MENU_WIDTH, AUX_OPTION_MENU_HEIGHT);
4076 sp_unit_selector_set_unit(SP_UNIT_SELECTOR(us), desktop->namedview->doc_units);
4078 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
4080 // horizontal kerning
4081 {
4082 {
4083 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_HORZ_KERN);
4084 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
4085 gtk_container_add (GTK_CONTAINER (hb), image);
4086 gtk_widget_show(image);
4087 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
4088 }
4090 {
4091 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Horizontal kerning"),
4092 "tools.text", "horizontal_kerning", 0,
4093 us, tbl, FALSE, NULL,
4094 -100.00, 100.00, 0.01, 0.1,
4095 sp_text_horiz_kern_changed);
4096 gtk_widget_set_size_request (hb, 45, 0);
4097 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
4098 }
4099 }
4101 // vertical kerning
4102 {
4103 {
4104 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_VERT_KERN);
4105 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
4106 gtk_container_add (GTK_CONTAINER (hb), image);
4107 gtk_widget_show(image);
4108 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
4109 }
4111 {
4112 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Vertical kerning"),
4113 "tools.text", "vertical_kerning", 0,
4114 us, tbl, FALSE, NULL,
4115 -100.00, 100.00, 0.01, 0.1,
4116 sp_text_vert_kern_changed);
4117 gtk_widget_set_size_request (hb, 45, 0);
4118 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 5);
4119 }
4120 }
4122 // add the units menu
4123 gtk_widget_show(us);
4124 gtk_box_pack_start(GTK_BOX(tbl), us, FALSE, FALSE, 1);
4125 gtk_object_set_data(GTK_OBJECT(tbl), "units", us);
4126 }
4128 // letter rotation
4129 aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
4130 {
4131 {
4132 GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_ROTATION);
4133 GtkWidget *hb = gtk_hbox_new(FALSE, 1);
4134 gtk_container_add (GTK_CONTAINER (hb), image);
4135 gtk_widget_show(image);
4136 gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
4137 }
4138 {
4139 GtkWidget *hb = sp_tb_spinbutton(_(""), _("Letter rotation"),
4140 "tools.text", "letter_rotation", 0,
4141 us, tbl, FALSE, NULL,
4142 -180.0, 180.0, 0.1, 0.1,
4143 sp_text_letter_rotation_changed, 0.1, 1);
4144 gtk_widget_set_size_request (hb, 45, 0);
4145 gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
4146 }
4147 // rotation degree label
4148 {
4149 GtkWidget *label = gtk_widget_new (GTK_TYPE_LABEL, "label", "\302\260", "xalign", 0.0, NULL);
4150 gtk_box_pack_start(GTK_BOX(tbl), label, FALSE, FALSE, 0);
4151 }
4152 }
4154 // Remove Manual Kerns
4155 {
4156 GtkWidget *px = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_REMOVE_KERNS);
4157 GtkWidget *button = gtk_button_new ();
4158 gtk_container_add (GTK_CONTAINER (button), px);
4159 gtk_widget_show(button);
4160 gtk_tooltips_set_tip (tt, button, _("Remove manual kerns"), NULL);
4161 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
4162 gtk_widget_set_sensitive(button, TRUE);
4163 gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
4164 }
4165 #endif
4167 gtk_widget_show_all (tbl);
4168 return tbl;
4170 } // end of sp_text_toolbox_new()
4172 }//<unnamed> namespace
4175 //#########################
4176 //## Connector Toolbox ##
4177 //#########################
4179 static void sp_connector_path_set_avoid(void)
4180 {
4181 cc_selection_set_avoid(true);
4182 }
4185 static void sp_connector_path_set_ignore(void)
4186 {
4187 cc_selection_set_avoid(false);
4188 }
4192 static void connector_spacing_changed(GtkAdjustment *adj, GtkWidget *tbl)
4193 {
4194 // quit if run by the _changed callbacks
4195 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
4196 return;
4197 }
4199 SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl),
4200 "desktop");
4201 SPDocument *doc = sp_desktop_document(desktop);
4203 if (!sp_document_get_undo_sensitive(doc))
4204 {
4205 return;
4206 }
4208 // in turn, prevent callbacks from responding
4209 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
4211 Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
4213 sp_repr_set_css_double(repr, "inkscape:connector-spacing", adj->value);
4214 SP_OBJECT(desktop->namedview)->updateRepr();
4216 GSList *items = get_avoided_items(NULL, desktop->currentRoot(), desktop);
4217 for ( GSList const *iter = items ; iter != NULL ; iter = iter->next ) {
4218 SPItem *item = reinterpret_cast<SPItem *>(iter->data);
4219 NR::Matrix m = NR::identity();
4220 avoid_item_move(&m, item);
4221 }
4223 if (items) {
4224 g_slist_free(items);
4225 }
4227 sp_document_done(doc, SP_VERB_CONTEXT_CONNECTOR,
4228 _("Change connector spacing"));
4230 g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
4232 spinbutton_defocus(GTK_OBJECT(tbl));
4233 }
4235 static void sp_connector_graph_layout(void)
4236 {
4237 if (!SP_ACTIVE_DESKTOP) return;
4239 // hack for clones, see comment in align-and-distribute.cpp
4240 int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
4241 prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
4243 graphlayout(sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList());
4245 prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
4247 sp_document_done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_DIALOG_ALIGN_DISTRIBUTE, _("Arrange connector network"));
4248 }
4250 static void
4251 sp_directed_graph_layout_toggled(GtkWidget *widget, GtkObject *tbl)
4252 {
4253 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
4254 prefs_set_string_attribute("tools.connector", "directedlayout",
4255 "true");
4256 } else {
4257 prefs_set_string_attribute("tools.connector", "directedlayout",
4258 "false");
4259 }
4260 }
4261 static void
4262 sp_nooverlaps_graph_layout_toggled(GtkWidget *widget, GtkObject *tbl)
4263 {
4264 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
4265 prefs_set_string_attribute("tools.connector", "avoidoverlaplayout",
4266 "true");
4267 } else {
4268 prefs_set_string_attribute("tools.connector", "avoidoverlaplayout",
4269 "false");
4270 }
4271 }
4274 static void connector_length_changed(GtkAdjustment *adj, GtkWidget *tbl)
4275 {
4276 prefs_set_double_attribute("tools.connector", "length", adj->value);
4277 spinbutton_defocus(GTK_OBJECT(tbl));
4278 }
4280 static void connector_tb_event_attr_changed(Inkscape::XML::Node *repr,
4281 gchar const *name, gchar const *old_value, gchar const *new_value,
4282 bool is_interactive, gpointer data)
4283 {
4284 GtkWidget *tbl = GTK_WIDGET(data);
4286 if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
4287 return;
4288 }
4289 if (strcmp(name, "inkscape:connector-spacing") != 0) {
4290 return;
4291 }
4293 GtkAdjustment *adj = (GtkAdjustment*)
4294 gtk_object_get_data(GTK_OBJECT(tbl), "spacing");
4295 gdouble spacing = defaultConnSpacing;
4296 sp_repr_get_double(repr, "inkscape:connector-spacing", &spacing);
4298 gtk_adjustment_set_value(adj, spacing);
4299 }
4302 static Inkscape::XML::NodeEventVector connector_tb_repr_events = {
4303 NULL, /* child_added */
4304 NULL, /* child_removed */
4305 connector_tb_event_attr_changed,
4306 NULL, /* content_changed */
4307 NULL /* order_changed */
4308 };
4311 static GtkWidget *
4312 sp_connector_toolbox_new(SPDesktop *desktop)
4313 {
4314 GtkTooltips *tt = gtk_tooltips_new();
4315 GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
4317 gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
4318 gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
4320 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
4321 AUX_BETWEEN_BUTTON_GROUPS);
4323 sp_toolbox_button_new(tbl, Inkscape::ICON_SIZE_SMALL_TOOLBAR,
4324 "connector_avoid", GTK_SIGNAL_FUNC(sp_connector_path_set_avoid),
4325 tt, _("Make connectors avoid selected objects"));
4327 sp_toolbox_button_new(tbl, Inkscape::ICON_SIZE_SMALL_TOOLBAR,
4328 "connector_ignore", GTK_SIGNAL_FUNC(sp_connector_path_set_ignore),
4329 tt, _("Make connectors ignore selected objects"));
4331 // interval
4332 gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
4333 AUX_BETWEEN_BUTTON_GROUPS);
4335 // Spacing spinbox
4336 {
4337 GtkWidget *object_spacing = sp_tb_spinbutton(_("Spacing:"),
4338 _("The amount of space left around objects by auto-routing connectors"),
4339 "tools.connector", "spacing", 10, NULL, tbl, TRUE,
4340 "inkscape:connector-spacing", 0, 100, 1.0, 10.0,
4341 connector_spacing_changed, 1, 0);
4343 gtk_box_pack_start(GTK_BOX(tbl), object_spacing, FALSE, FALSE,
4344 AUX_SPACING);
4345 }
4346 // Graph (connector network) layout
4347 sp_toolbox_button_new(tbl, Inkscape::ICON_SIZE_SMALL_TOOLBAR,
4348 "graph_layout", GTK_SIGNAL_FUNC(sp_connector_graph_layout),
4349 tt, _("Nicely arrange selected connector network"));
4350 // Default connector length spinbox
4351 {
4352 GtkWidget *connector_length = sp_tb_spinbutton(_("Length:"),
4353 _("Ideal length for connectors when layout is applied"),
4354 "tools.connector", "length", 100, NULL, tbl, TRUE,
4355 "inkscape:connector-length", 10, 1000, 10.0, 100.0,
4356 connector_length_changed, 1, 0);
4358 gtk_box_pack_start(GTK_BOX(tbl), connector_length, FALSE, FALSE,
4359 AUX_SPACING);
4360 }
4361 gchar const *tbuttonstate;
4362 // Directed edges toggle button
4363 {
4364 GtkWidget *tbutton = gtk_toggle_button_new ();
4365 gtk_button_set_relief (GTK_BUTTON (tbutton), GTK_RELIEF_NONE);
4366 gtk_container_add (GTK_CONTAINER (tbutton), sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, "directed_graph"));
4367 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (tbutton), FALSE);
4368 gtk_tooltips_set_tip(tt, tbutton, _("Make connectors with end-markers (arrows) point downwards"), NULL);
4370 gtk_box_pack_start (GTK_BOX (tbl), tbutton, FALSE, FALSE, 0);
4371 g_signal_connect(G_OBJECT(tbutton), "toggled", GTK_SIGNAL_FUNC(sp_directed_graph_layout_toggled), tbl);
4372 tbuttonstate = prefs_get_string_attribute("tools.connector", "directedlayout");
4373 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(tbutton),
4374 (tbuttonstate && !strcmp(tbuttonstate, "true"))?TRUE:FALSE );
4375 }
4376 // Avoid overlaps toggle button
4377 {
4378 GtkWidget *tbutton = gtk_toggle_button_new ();
4379 gtk_button_set_relief (GTK_BUTTON (tbutton), GTK_RELIEF_NONE);
4380 gtk_container_add (GTK_CONTAINER (tbutton), sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, "remove_overlaps"));
4381 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (tbutton), FALSE);
4382 gtk_tooltips_set_tip(tt, tbutton, _("Do not allow overlapping shapes"), NULL);
4384 gtk_box_pack_start (GTK_BOX (tbl), tbutton, FALSE, FALSE, 0);
4385 g_signal_connect(G_OBJECT(tbutton), "toggled", GTK_SIGNAL_FUNC(sp_nooverlaps_graph_layout_toggled), tbl);
4386 tbuttonstate = prefs_get_string_attribute("tools.connector", "avoidoverlaplayout");
4387 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(tbutton),
4388 (tbuttonstate && !strcmp(tbuttonstate, "true"))?TRUE:FALSE );
4389 }
4391 gtk_widget_show_all(tbl);
4392 sp_set_font_size_smaller (tbl);
4394 // Code to watch for changes to the connector-spacing attribute in
4395 // the XML.
4396 Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
4397 g_assert(repr != NULL);
4399 Inkscape::XML::Node *oldrepr = (Inkscape::XML::Node *)
4400 gtk_object_get_data(GTK_OBJECT(tbl), "repr");
4402 if (oldrepr) { // remove old listener
4403 sp_repr_remove_listener_by_data(oldrepr, tbl);
4404 Inkscape::GC::release(oldrepr);
4405 oldrepr = NULL;
4406 g_object_set_data(G_OBJECT(tbl), "repr", NULL);
4407 }
4409 if (repr) {
4410 g_object_set_data(G_OBJECT(tbl), "repr", repr);
4411 Inkscape::GC::anchor(repr);
4412 sp_repr_add_listener(repr, &connector_tb_repr_events, tbl);
4413 sp_repr_synthesize_events(repr, &connector_tb_repr_events, tbl);
4414 }
4416 return tbl;
4418 } // end of sp_connector_toolbox_new()
4420 static void paintbucket_channels_changed(EgeSelectOneAction* act, GtkWidget* tbl)
4421 {
4422 gint channels = ege_select_one_action_get_active( act );
4423 flood_channels_set_channels( channels );
4424 }
4426 static void paintbucket_threshold_changed(GtkAdjustment *adj, GtkWidget *tbl)
4427 {
4428 prefs_set_int_attribute("tools.paintbucket", "threshold", (gint)adj->value);
4429 }
4431 static void paintbucket_offset_changed(GtkAdjustment *adj, GtkWidget *tbl)
4432 {
4433 UnitTracker* tracker = reinterpret_cast<UnitTracker*>(gtk_object_get_data(GTK_OBJECT(tbl), "tracker"));
4434 SPUnit const *unit = tracker->getActiveUnit();
4437 prefs_set_double_attribute("tools.paintbucket", "offset", (gdouble)sp_units_get_pixels(adj->value, *unit));
4438 spinbutton_defocus(GTK_OBJECT(tbl));
4439 }
4441 static GtkWidget *
4442 sp_paintbucket_toolbox_new(SPDesktop *desktop)
4443 {
4444 GtkWidget *holder = gtk_hbox_new(FALSE, 0);
4445 gtk_object_set_data(GTK_OBJECT(holder), "dtw", desktop->canvas);
4446 gtk_object_set_data(GTK_OBJECT(holder), "desktop", desktop);
4448 gchar const * descr =
4449 "<ui>"
4450 " <toolbar name='PaintbucketToolbar'>"
4451 " <toolitem action='ChannelsAction' />"
4452 " <separator />"
4453 " <toolitem action='ThresholdAction' />"
4454 " <separator />"
4455 " <toolitem action='OffsetAction' />"
4456 " </toolbar>"
4457 "</ui>";
4458 GtkActionGroup* mainActions = gtk_action_group_new("main");
4460 EgeAdjustmentAction* eact = 0;
4462 {
4463 GtkListStore* model = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_INT );
4465 GList* items = 0;
4466 gint count = 0;
4467 for ( items = flood_channels_dropdown_items_list(); items ; items = g_list_next(items) )
4468 {
4469 GtkTreeIter iter;
4470 gtk_list_store_append( model, &iter );
4471 gtk_list_store_set( model, &iter, 0, reinterpret_cast<gchar*>(items->data), 1, count, -1 );
4472 count++;
4473 }
4474 g_list_free( items );
4475 items = 0;
4476 EgeSelectOneAction* act1 = ege_select_one_action_new( "ChannelsAction", _("Fill by:"), _(""), NULL, GTK_TREE_MODEL(model) );
4477 ege_select_one_action_set_active( act1, prefs_get_int_attribute("tools.paintbucket", "channels", 0) );
4478 g_signal_connect( G_OBJECT(act1), "changed", G_CALLBACK(paintbucket_channels_changed), holder );
4479 gtk_action_group_add_action( mainActions, GTK_ACTION(act1) );
4480 }
4482 // Spacing spinbox
4483 {
4484 eact = create_adjustment_action(
4485 "ThresholdAction",
4486 _("Threshold:"),
4487 _("The maximum allowed difference between the clicked pixel and the neighboring pixels to be counted in the fill"),
4488 "tools.paintbucket", "threshold", 5, GTK_WIDGET(desktop->canvas), NULL, holder, TRUE,
4489 "inkscape:paintbucket-threshold", 0, 100.0, 1.0, 10.0,
4490 0, 0, 0,
4491 paintbucket_threshold_changed, 1, 0 );
4493 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
4494 }
4496 // Create the units menu.
4497 UnitTracker* tracker = new UnitTracker( SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE );
4498 tracker->setActiveUnit( sp_desktop_namedview(desktop)->doc_units );
4499 gtk_object_set_data( GTK_OBJECT(holder), "tracker", tracker );
4500 {
4501 GtkAction* act = tracker->createAction( "PaintbucketUnitsAction", _("Units"), _("") );
4502 gtk_action_group_add_action( mainActions, act );
4503 }
4505 // Offset spinbox
4506 {
4507 eact = create_adjustment_action(
4508 "OffsetAction",
4509 _("Grow/shrink by:"),
4510 _("The amount to grow (positive) or shrink (negative) the created fill path"),
4511 "tools.paintbucket", "offset", 0, GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, TRUE,
4512 "inkscape:paintbucket-offset", -1e6, 1e6, 0.1, 0.5,
4513 0, 0, 0,
4514 paintbucket_offset_changed, 1, 2);
4515 tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) );
4517 gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
4518 }
4521 GtkUIManager* mgr = gtk_ui_manager_new();
4522 GError* errVal = 0;
4524 gtk_ui_manager_insert_action_group( mgr, mainActions, 0 );
4525 gtk_ui_manager_add_ui_from_string( mgr, descr, -1, &errVal );
4527 GtkWidget* toolBar = gtk_ui_manager_get_widget( mgr, "/ui/PaintbucketToolbar" );
4528 gtk_toolbar_set_style( GTK_TOOLBAR(toolBar), GTK_TOOLBAR_ICONS );
4529 gtk_toolbar_set_icon_size( GTK_TOOLBAR(toolBar), GTK_ICON_SIZE_SMALL_TOOLBAR );
4531 gtk_box_pack_start( GTK_BOX(holder), toolBar, TRUE, TRUE, 0 );
4534 Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch(NULL, _("Style of Paint Bucket fill objects"));
4535 swatch->setDesktop (desktop);
4536 swatch->setClickVerb (SP_VERB_CONTEXT_PAINTBUCKET_PREFS);
4537 swatch->setWatchedTool ("tools.paintbucket", true);
4538 GtkWidget *swatch_ = GTK_WIDGET(swatch->gobj());
4539 gtk_box_pack_end( GTK_BOX(holder), swatch_, FALSE, FALSE, 0 );
4541 gtk_widget_show_all( holder );
4542 sp_set_font_size_smaller( holder );
4544 return holder;
4545 }
4547 /*
4548 Local Variables:
4549 mode:c++
4550 c-file-style:"stroustrup"
4551 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
4552 indent-tabs-mode:nil
4553 fill-column:99
4554 End:
4555 */
4556 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :