2
* @brief Controls bars for some of Inkscape's tools (for some tools,
3
* they are in their own files)
6
* MenTaLguY <mental@rydia.net>
7
* Lauris Kaplinski <lauris@kaplinski.com>
8
* bulia byak <buliabyak@users.sf.net>
9
* Frank Felfe <innerspace@iname.com>
10
* John Cliff <simarilius@yahoo.com>
11
* David Turner <novalis@gnu.org>
12
* Josh Andler <scislac@scislac.com>
13
* Jon A. Cruz <jon@joncruz.org>
14
* Maximilian Albert <maximilian.albert@gmail.com>
15
* Tavmjong Bah <tavmjong@free.fr>
17
* Copyright (C) 2004 David Turner
18
* Copyright (C) 2003 MenTaLguY
19
* Copyright (C) 1999-2010 authors
20
* Copyright (C) 2001-2002 Ximian, Inc.
22
* Released under GNU GPL, read the file 'COPYING' for more information
36
#include <glibmm/i18n.h>
38
#include "../box3d-context.h"
40
#include "../conn-avoid-ref.h"
41
#include "../connection-pool.h"
42
#include "../connector-context.h"
43
#include "../desktop.h"
44
#include "../desktop-handles.h"
45
#include "../desktop-style.h"
46
#include "../dialogs/dialog-events.h"
47
#include "../dialogs/text-edit.h"
48
#include "../document-private.h"
49
#include "../ege-adjustment-action.h"
50
#include "../ege-output-action.h"
51
#include "../ege-select-one-action.h"
52
#include "../flood-context.h"
53
#include "gradient-toolbar.h"
54
#include "../graphlayout.h"
55
#include "../helper/unit-menu.h"
56
#include "../helper/units.h"
57
#include "../helper/unit-tracker.h"
59
#include "../ink-action.h"
60
#include "../ink-comboboxentry-action.h"
61
#include "../inkscape.h"
62
#include "../interface.h"
63
#include "../libnrtype/font-instance.h"
64
#include "../libnrtype/font-lister.h"
65
#include "../live_effects/effect.h"
66
#include "../live_effects/lpe-angle_bisector.h"
67
#include "../live_effects/lpe-line_segment.h"
68
#include "../lpe-tool-context.h"
69
#include "../mod360.h"
70
#include "../pen-context.h"
71
#include "../preferences.h"
72
#include "../selection-chemistry.h"
73
#include "../selection.h"
74
#include "select-toolbar.h"
75
#include "../shape-editor.h"
76
#include "../shortcuts.h"
77
#include "../sp-clippath.h"
78
#include "../sp-ellipse.h"
79
#include "../sp-flowtext.h"
80
#include "../sp-mask.h"
81
#include "../sp-namedview.h"
82
#include "../sp-rect.h"
83
#include "../sp-spiral.h"
84
#include "../sp-star.h"
85
#include "../sp-text.h"
87
#include "../svg/css-ostringstream.h"
88
#include "../text-context.h"
89
#include "../text-editing.h"
90
#include "../tools-switch.h"
91
#include "../tweak-context.h"
92
#include "../spray-context.h"
93
#include "../ui/dialog/calligraphic-profile-rename.h"
94
#include "../ui/icon-names.h"
95
#include "../ui/tool/control-point-selection.h"
96
#include "../ui/tool/node-tool.h"
97
#include "../ui/tool/multi-path-manipulator.h"
98
#include "../ui/widget/style-swatch.h"
100
#include "../widgets/button.h"
101
#include "../widgets/spinbutton-events.h"
102
#include "../widgets/spw-utilities.h"
103
#include "../widgets/widget-sizes.h"
104
#include "../xml/attribute-record.h"
105
#include "../xml/node-event-vector.h"
106
#include "../xml/repr.h"
107
#include "ui/uxmanager.h"
113
using Inkscape::UnitTracker;
114
using Inkscape::UI::UXManager;
116
typedef void (*SetupFunction)(GtkWidget *toolbox, SPDesktop *desktop);
117
typedef void (*UpdateFunction)(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
126
#define BAR_ID_KEY "BarIdValue"
127
#define HANDLE_POS_MARK "x-inkscape-pos"
129
static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
130
static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
131
static void sp_spray_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
132
static void sp_zoom_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
133
static void sp_star_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
134
static void sp_arc_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
135
static void sp_rect_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
136
static void box3d_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
137
static void sp_spiral_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
138
static void sp_pencil_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
139
static void sp_pen_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
140
static void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
141
static void sp_dropper_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
142
static GtkWidget *sp_empty_toolbox_new(SPDesktop *desktop);
143
static void sp_connector_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
144
static void sp_paintbucket_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
145
static void sp_eraser_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
146
static void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
147
static void sp_lpetool_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
149
using Inkscape::UI::ToolboxFactory;
152
Inkscape::IconSize ToolboxFactory::prefToSize( Glib::ustring const &path, int base ) {
153
static Inkscape::IconSize sizeChoices[] = {
154
Inkscape::ICON_SIZE_LARGE_TOOLBAR,
155
Inkscape::ICON_SIZE_SMALL_TOOLBAR,
156
Inkscape::ICON_SIZE_MENU
158
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
159
int index = prefs->getIntLimited( path, base, 0, G_N_ELEMENTS(sizeChoices) );
160
return sizeChoices[index];
164
gchar const *type_name;
165
gchar const *data_name;
167
sp_verb_t doubleclick_verb;
169
{ "SPSelectContext", "select_tool", SP_VERB_CONTEXT_SELECT, SP_VERB_CONTEXT_SELECT_PREFS},
170
{ "InkNodeTool", "node_tool", SP_VERB_CONTEXT_NODE, SP_VERB_CONTEXT_NODE_PREFS },
171
{ "SPTweakContext", "tweak_tool", SP_VERB_CONTEXT_TWEAK, SP_VERB_CONTEXT_TWEAK_PREFS },
172
{ "SPSprayContext", "spray_tool", SP_VERB_CONTEXT_SPRAY, SP_VERB_CONTEXT_SPRAY_PREFS },
173
{ "SPZoomContext", "zoom_tool", SP_VERB_CONTEXT_ZOOM, SP_VERB_CONTEXT_ZOOM_PREFS },
174
{ "SPRectContext", "rect_tool", SP_VERB_CONTEXT_RECT, SP_VERB_CONTEXT_RECT_PREFS },
175
{ "Box3DContext", "3dbox_tool", SP_VERB_CONTEXT_3DBOX, SP_VERB_CONTEXT_3DBOX_PREFS },
176
{ "SPArcContext", "arc_tool", SP_VERB_CONTEXT_ARC, SP_VERB_CONTEXT_ARC_PREFS },
177
{ "SPStarContext", "star_tool", SP_VERB_CONTEXT_STAR, SP_VERB_CONTEXT_STAR_PREFS },
178
{ "SPSpiralContext", "spiral_tool", SP_VERB_CONTEXT_SPIRAL, SP_VERB_CONTEXT_SPIRAL_PREFS },
179
{ "SPPencilContext", "pencil_tool", SP_VERB_CONTEXT_PENCIL, SP_VERB_CONTEXT_PENCIL_PREFS },
180
{ "SPPenContext", "pen_tool", SP_VERB_CONTEXT_PEN, SP_VERB_CONTEXT_PEN_PREFS },
181
{ "SPDynaDrawContext", "dyna_draw_tool", SP_VERB_CONTEXT_CALLIGRAPHIC, SP_VERB_CONTEXT_CALLIGRAPHIC_PREFS },
182
{ "SPLPEToolContext", "lpetool_tool", SP_VERB_CONTEXT_LPETOOL, SP_VERB_CONTEXT_LPETOOL_PREFS },
183
{ "SPEraserContext", "eraser_tool", SP_VERB_CONTEXT_ERASER, SP_VERB_CONTEXT_ERASER_PREFS },
184
{ "SPFloodContext", "paintbucket_tool", SP_VERB_CONTEXT_PAINTBUCKET, SP_VERB_CONTEXT_PAINTBUCKET_PREFS },
185
{ "SPTextContext", "text_tool", SP_VERB_CONTEXT_TEXT, SP_VERB_CONTEXT_TEXT_PREFS },
186
{ "SPConnectorContext","connector_tool", SP_VERB_CONTEXT_CONNECTOR, SP_VERB_CONTEXT_CONNECTOR_PREFS },
187
{ "SPGradientContext", "gradient_tool", SP_VERB_CONTEXT_GRADIENT, SP_VERB_CONTEXT_GRADIENT_PREFS },
188
{ "SPDropperContext", "dropper_tool", SP_VERB_CONTEXT_DROPPER, SP_VERB_CONTEXT_DROPPER_PREFS },
193
gchar const *type_name;
194
gchar const *data_name;
195
GtkWidget *(*create_func)(SPDesktop *desktop);
196
void (*prep_func)(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
197
gchar const *ui_name;
199
gchar const *swatch_tool;
200
gchar const *swatch_tip;
201
} const aux_toolboxes[] = {
202
{ "SPSelectContext", "select_toolbox", 0, sp_select_toolbox_prep, "SelectToolbar",
203
SP_VERB_INVALID, 0, 0},
204
{ "InkNodeTool", "node_toolbox", 0, sp_node_toolbox_prep, "NodeToolbar",
205
SP_VERB_INVALID, 0, 0},
206
{ "SPTweakContext", "tweak_toolbox", 0, sp_tweak_toolbox_prep, "TweakToolbar",
207
SP_VERB_CONTEXT_TWEAK_PREFS, "/tools/tweak", N_("Color/opacity used for color tweaking")},
208
{ "SPSprayContext", "spray_toolbox", 0, sp_spray_toolbox_prep, "SprayToolbar",
209
SP_VERB_INVALID, 0, 0},
210
{ "SPZoomContext", "zoom_toolbox", 0, sp_zoom_toolbox_prep, "ZoomToolbar",
211
SP_VERB_INVALID, 0, 0},
212
{ "SPStarContext", "star_toolbox", 0, sp_star_toolbox_prep, "StarToolbar",
213
SP_VERB_CONTEXT_STAR_PREFS, "/tools/shapes/star", N_("Style of new stars")},
214
{ "SPRectContext", "rect_toolbox", 0, sp_rect_toolbox_prep, "RectToolbar",
215
SP_VERB_CONTEXT_RECT_PREFS, "/tools/shapes/rect", N_("Style of new rectangles")},
216
{ "Box3DContext", "3dbox_toolbox", 0, box3d_toolbox_prep, "3DBoxToolbar",
217
SP_VERB_CONTEXT_3DBOX_PREFS, "/tools/shapes/3dbox", N_("Style of new 3D boxes")},
218
{ "SPArcContext", "arc_toolbox", 0, sp_arc_toolbox_prep, "ArcToolbar",
219
SP_VERB_CONTEXT_ARC_PREFS, "/tools/shapes/arc", N_("Style of new ellipses")},
220
{ "SPSpiralContext", "spiral_toolbox", 0, sp_spiral_toolbox_prep, "SpiralToolbar",
221
SP_VERB_CONTEXT_SPIRAL_PREFS, "/tools/shapes/spiral", N_("Style of new spirals")},
222
{ "SPPencilContext", "pencil_toolbox", 0, sp_pencil_toolbox_prep, "PencilToolbar",
223
SP_VERB_CONTEXT_PENCIL_PREFS, "/tools/freehand/pencil", N_("Style of new paths created by Pencil")},
224
{ "SPPenContext", "pen_toolbox", 0, sp_pen_toolbox_prep, "PenToolbar",
225
SP_VERB_CONTEXT_PEN_PREFS, "/tools/freehand/pen", N_("Style of new paths created by Pen")},
226
{ "SPDynaDrawContext", "calligraphy_toolbox", 0, sp_calligraphy_toolbox_prep,"CalligraphyToolbar",
227
SP_VERB_CONTEXT_CALLIGRAPHIC_PREFS, "/tools/calligraphic", N_("Style of new calligraphic strokes")},
228
{ "SPEraserContext", "eraser_toolbox", 0, sp_eraser_toolbox_prep,"EraserToolbar",
229
SP_VERB_CONTEXT_ERASER_PREFS, "/tools/eraser", _("TBD")},
230
{ "SPLPEToolContext", "lpetool_toolbox", 0, sp_lpetool_toolbox_prep, "LPEToolToolbar",
231
SP_VERB_CONTEXT_LPETOOL_PREFS, "/tools/lpetool", _("TBD")},
232
{ "SPTextContext", "text_toolbox", 0, sp_text_toolbox_prep, "TextToolbar",
233
SP_VERB_INVALID, 0, 0},
234
{ "SPDropperContext", "dropper_toolbox", 0, sp_dropper_toolbox_prep, "DropperToolbar",
235
SP_VERB_INVALID, 0, 0},
236
{ "SPGradientContext", "gradient_toolbox", sp_gradient_toolbox_new, 0, 0,
237
SP_VERB_INVALID, 0, 0},
238
{ "SPConnectorContext", "connector_toolbox", 0, sp_connector_toolbox_prep, "ConnectorToolbar",
239
SP_VERB_INVALID, 0, 0},
240
{ "SPFloodContext", "paintbucket_toolbox", 0, sp_paintbucket_toolbox_prep, "PaintbucketToolbar",
241
SP_VERB_CONTEXT_PAINTBUCKET_PREFS, "/tools/paintbucket", N_("Style of Paint Bucket fill objects")},
242
{ NULL, NULL, NULL, NULL, NULL, SP_VERB_INVALID, NULL, NULL }
245
#define TOOLBAR_SLIDER_HINT "full"
247
static gchar const * ui_descr =
249
" <toolbar name='SelectToolbar'>"
250
" <toolitem action='EditSelectAll' />"
251
" <toolitem action='EditSelectAllInAllLayers' />"
252
" <toolitem action='EditDeselect' />"
254
" <toolitem action='ObjectRotate90CCW' />"
255
" <toolitem action='ObjectRotate90' />"
256
" <toolitem action='ObjectFlipHorizontally' />"
257
" <toolitem action='ObjectFlipVertically' />"
259
" <toolitem action='SelectionToBack' />"
260
" <toolitem action='SelectionLower' />"
261
" <toolitem action='SelectionRaise' />"
262
" <toolitem action='SelectionToFront' />"
264
" <toolitem action='XAction' />"
265
" <toolitem action='YAction' />"
266
" <toolitem action='WidthAction' />"
267
" <toolitem action='LockAction' />"
268
" <toolitem action='HeightAction' />"
269
" <toolitem action='UnitsAction' />"
271
" <toolitem action='transform_affect_label' />"
272
" <toolitem action='transform_stroke' />"
273
" <toolitem action='transform_corners' />"
274
" <toolitem action='transform_gradient' />"
275
" <toolitem action='transform_pattern' />"
278
" <toolbar name='NodeToolbar'>"
280
" <toolitem action='NodeInsertAction' />"
281
" <toolitem action='NodeDeleteAction' />"
283
" <toolitem action='NodeJoinAction' />"
284
" <toolitem action='NodeBreakAction' />"
286
" <toolitem action='NodeJoinSegmentAction' />"
287
" <toolitem action='NodeDeleteSegmentAction' />"
289
" <toolitem action='NodeCuspAction' />"
290
" <toolitem action='NodeSmoothAction' />"
291
" <toolitem action='NodeSymmetricAction' />"
292
" <toolitem action='NodeAutoAction' />"
294
" <toolitem action='NodeLineAction' />"
295
" <toolitem action='NodeCurveAction' />"
297
" <toolitem action='ObjectToPath' />"
298
" <toolitem action='StrokeToPath' />"
300
" <toolitem action='NodeXAction' />"
301
" <toolitem action='NodeYAction' />"
302
" <toolitem action='NodeUnitsAction' />"
304
" <toolitem action='ObjectEditClipPathAction' />"
305
" <toolitem action='ObjectEditMaskPathAction' />"
306
" <toolitem action='EditNextPathEffectParameter' />"
308
" <toolitem action='NodesShowTransformHandlesAction' />"
309
" <toolitem action='NodesShowHandlesAction' />"
310
" <toolitem action='NodesShowHelperpath' />"
313
" <toolbar name='TweakToolbar'>"
314
" <toolitem action='TweakWidthAction' />"
316
" <toolitem action='TweakForceAction' />"
317
" <toolitem action='TweakPressureAction' />"
319
" <toolitem action='TweakModeAction' />"
321
" <toolitem action='TweakFidelityAction' />"
323
" <toolitem action='TweakChannelsLabel' />"
324
" <toolitem action='TweakDoH' />"
325
" <toolitem action='TweakDoS' />"
326
" <toolitem action='TweakDoL' />"
327
" <toolitem action='TweakDoO' />"
330
" <toolbar name='SprayToolbar'>"
331
" <toolitem action='SprayModeAction' />"
334
" <toolitem action='SprayWidthAction' />"
335
" <toolitem action='SprayPressureAction' />"
336
" <toolitem action='SprayPopulationAction' />"
338
" <toolitem action='SprayRotationAction' />"
339
" <toolitem action='SprayScaleAction' />"
341
" <toolitem action='SprayStandard_deviationAction' />"
342
" <toolitem action='SprayMeanAction' />"
345
" <toolbar name='ZoomToolbar'>"
346
" <toolitem action='ZoomIn' />"
347
" <toolitem action='ZoomOut' />"
349
" <toolitem action='Zoom1:0' />"
350
" <toolitem action='Zoom1:2' />"
351
" <toolitem action='Zoom2:1' />"
353
" <toolitem action='ZoomSelection' />"
354
" <toolitem action='ZoomDrawing' />"
355
" <toolitem action='ZoomPage' />"
356
" <toolitem action='ZoomPageWidth' />"
358
" <toolitem action='ZoomPrev' />"
359
" <toolitem action='ZoomNext' />"
362
" <toolbar name='StarToolbar'>"
364
" <toolitem action='StarStateAction' />"
366
" <toolitem action='FlatAction' />"
368
" <toolitem action='MagnitudeAction' />"
369
" <toolitem action='SpokeAction' />"
370
" <toolitem action='RoundednessAction' />"
371
" <toolitem action='RandomizationAction' />"
373
" <toolitem action='StarResetAction' />"
376
" <toolbar name='RectToolbar'>"
377
" <toolitem action='RectStateAction' />"
378
" <toolitem action='RectWidthAction' />"
379
" <toolitem action='RectHeightAction' />"
380
" <toolitem action='RadiusXAction' />"
381
" <toolitem action='RadiusYAction' />"
382
" <toolitem action='RectUnitsAction' />"
384
" <toolitem action='RectResetAction' />"
387
" <toolbar name='3DBoxToolbar'>"
388
" <toolitem action='3DBoxAngleXAction' />"
389
" <toolitem action='3DBoxVPXStateAction' />"
391
" <toolitem action='3DBoxAngleYAction' />"
392
" <toolitem action='3DBoxVPYStateAction' />"
394
" <toolitem action='3DBoxAngleZAction' />"
395
" <toolitem action='3DBoxVPZStateAction' />"
398
" <toolbar name='SpiralToolbar'>"
399
" <toolitem action='SpiralStateAction' />"
400
" <toolitem action='SpiralRevolutionAction' />"
401
" <toolitem action='SpiralExpansionAction' />"
402
" <toolitem action='SpiralT0Action' />"
404
" <toolitem action='SpiralResetAction' />"
407
" <toolbar name='PenToolbar'>"
408
" <toolitem action='FreehandModeActionPen' />"
410
" <toolitem action='SetPenShapeAction'/>"
413
" <toolbar name='PencilToolbar'>"
414
" <toolitem action='FreehandModeActionPencil' />"
416
" <toolitem action='PencilToleranceAction' />"
418
" <toolitem action='PencilResetAction' />"
420
" <toolitem action='SetPencilShapeAction'/>"
423
" <toolbar name='CalligraphyToolbar'>"
425
" <toolitem action='SetProfileAction'/>"
427
" <toolitem action='CalligraphyWidthAction' />"
428
" <toolitem action='PressureAction' />"
429
" <toolitem action='TraceAction' />"
430
" <toolitem action='ThinningAction' />"
432
" <toolitem action='AngleAction' />"
433
" <toolitem action='TiltAction' />"
434
" <toolitem action='FixationAction' />"
436
" <toolitem action='CapRoundingAction' />"
438
" <toolitem action='TremorAction' />"
439
" <toolitem action='WiggleAction' />"
440
" <toolitem action='MassAction' />"
444
" <toolbar name='ArcToolbar'>"
445
" <toolitem action='ArcStateAction' />"
447
" <toolitem action='ArcStartAction' />"
448
" <toolitem action='ArcEndAction' />"
450
" <toolitem action='ArcOpenAction' />"
452
" <toolitem action='ArcResetAction' />"
456
" <toolbar name='PaintbucketToolbar'>"
457
" <toolitem action='ChannelsAction' />"
459
" <toolitem action='ThresholdAction' />"
461
" <toolitem action='OffsetAction' />"
462
" <toolitem action='PaintbucketUnitsAction' />"
464
" <toolitem action='AutoGapAction' />"
466
" <toolitem action='PaintbucketResetAction' />"
469
" <toolbar name='EraserToolbar'>"
470
" <toolitem action='EraserWidthAction' />"
472
" <toolitem action='EraserModeAction' />"
475
" <toolbar name='TextToolbar'>"
476
" <toolitem action='TextFontFamilyAction' />"
477
" <toolitem action='TextFontSizeAction' />"
478
" <toolitem action='TextBoldAction' />"
479
" <toolitem action='TextItalicAction' />"
481
" <toolitem action='TextAlignAction' />"
483
" <toolitem action='TextSuperscriptAction' />"
484
" <toolitem action='TextSubscriptAction' />"
486
" <toolitem action='TextLineHeightAction' />"
487
" <toolitem action='TextLetterSpacingAction' />"
488
" <toolitem action='TextWordSpacingAction' />"
489
" <toolitem action='TextDxAction' />"
490
" <toolitem action='TextDyAction' />"
491
" <toolitem action='TextRotationAction' />"
493
" <toolitem action='TextOrientationAction' />"
496
" <toolbar name='LPEToolToolbar'>"
497
" <toolitem action='LPEToolModeAction' />"
499
" <toolitem action='LPEShowBBoxAction' />"
500
" <toolitem action='LPEBBoxFromSelectionAction' />"
502
" <toolitem action='LPELineSegmentAction' />"
504
" <toolitem action='LPEMeasuringAction' />"
505
" <toolitem action='LPEToolUnitsAction' />"
507
" <toolitem action='LPEOpenLPEDialogAction' />"
510
" <toolbar name='DropperToolbar'>"
511
" <toolitem action='DropperOpacityAction' />"
512
" <toolitem action='DropperPickAlphaAction' />"
513
" <toolitem action='DropperSetAlphaAction' />"
516
" <toolbar name='ConnectorToolbar'>"
517
// " <toolitem action='ConnectorEditModeAction' />"
518
" <toolitem action='ConnectorAvoidAction' />"
519
" <toolitem action='ConnectorIgnoreAction' />"
520
" <toolitem action='ConnectorOrthogonalAction' />"
521
" <toolitem action='ConnectorCurvatureAction' />"
522
" <toolitem action='ConnectorSpacingAction' />"
523
" <toolitem action='ConnectorGraphAction' />"
524
" <toolitem action='ConnectorLengthAction' />"
525
" <toolitem action='ConnectorDirectedAction' />"
526
" <toolitem action='ConnectorOverlapAction' />"
527
// " <toolitem action='ConnectorNewConnPointAction' />"
528
// " <toolitem action='ConnectorRemoveConnPointAction' />"
534
static Glib::RefPtr<Gtk::ActionGroup> create_or_fetch_actions( SPDesktop* desktop );
536
static void setup_snap_toolbox(GtkWidget *toolbox, SPDesktop *desktop);
538
static void setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop);
539
static void update_tool_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
541
static void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop);
542
static void update_aux_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
544
static void setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop);
545
static void update_commands_toolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox);
547
static GtkWidget * sp_toolbox_button_new_from_verb_with_doubleclick( GtkWidget *t, Inkscape::IconSize size, SPButtonType type,
548
Inkscape::Verb *verb, Inkscape::Verb *doubleclick_verb,
549
Inkscape::UI::View::View *view, GtkTooltips *tt);
551
class VerbAction : public Gtk::Action {
553
static Glib::RefPtr<VerbAction> create(Inkscape::Verb* verb, Inkscape::Verb* verb2, Inkscape::UI::View::View *view, GtkTooltips *tooltips);
555
virtual ~VerbAction();
556
virtual void set_active(bool active = true);
559
virtual Gtk::Widget* create_menu_item_vfunc();
560
virtual Gtk::Widget* create_tool_item_vfunc();
562
virtual void connect_proxy_vfunc(Gtk::Widget* proxy);
563
virtual void disconnect_proxy_vfunc(Gtk::Widget* proxy);
565
virtual void on_activate();
568
Inkscape::Verb* verb;
569
Inkscape::Verb* verb2;
570
Inkscape::UI::View::View *view;
571
GtkTooltips *tooltips;
574
VerbAction(Inkscape::Verb* verb, Inkscape::Verb* verb2, Inkscape::UI::View::View *view, GtkTooltips *tooltips);
578
Glib::RefPtr<VerbAction> VerbAction::create(Inkscape::Verb* verb, Inkscape::Verb* verb2, Inkscape::UI::View::View *view, GtkTooltips *tooltips)
580
Glib::RefPtr<VerbAction> result;
581
SPAction *action = verb->get_action(view);
583
//SPAction* action2 = verb2 ? verb2->get_action(view) : 0;
584
result = Glib::RefPtr<VerbAction>(new VerbAction(verb, verb2, view, tooltips));
590
VerbAction::VerbAction(Inkscape::Verb* verb, Inkscape::Verb* verb2, Inkscape::UI::View::View *view, GtkTooltips *tooltips) :
591
Gtk::Action(Glib::ustring(verb->get_id()), Gtk::StockID(verb->get_image()), Glib::ustring(_(verb->get_name())), Glib::ustring(_(verb->get_tip()))),
600
VerbAction::~VerbAction()
604
Gtk::Widget* VerbAction::create_menu_item_vfunc()
606
// First call in to get the icon rendered if present in SVG
607
Gtk::Widget *widget = sp_icon_get_icon( property_stock_id().get_value().get_string(), Inkscape::ICON_SIZE_MENU );
611
Gtk::Widget* widg = Gtk::Action::create_menu_item_vfunc();
612
// g_message("create_menu_item_vfunc() = %p for '%s'", widg, verb->get_id());
616
Gtk::Widget* VerbAction::create_tool_item_vfunc()
618
// Gtk::Widget* widg = Gtk::Action::create_tool_item_vfunc();
619
Inkscape::IconSize toolboxSize = ToolboxFactory::prefToSize("/toolbox/tools/small");
620
GtkWidget* toolbox = 0;
621
GtkWidget *button = sp_toolbox_button_new_from_verb_with_doubleclick( toolbox, toolboxSize,
622
SP_BUTTON_TYPE_TOGGLE,
628
sp_button_toggle_set_down( SP_BUTTON(button), active);
630
gtk_widget_show_all( button );
631
Gtk::Widget* wrapped = Glib::wrap(button);
632
Gtk::ToolItem* holder = Gtk::manage(new Gtk::ToolItem());
633
holder->add(*wrapped);
635
// g_message("create_tool_item_vfunc() = %p for '%s'", holder, verb->get_id());
639
void VerbAction::connect_proxy_vfunc(Gtk::Widget* proxy)
641
// g_message("connect_proxy_vfunc(%p) for '%s'", proxy, verb->get_id());
642
Gtk::Action::connect_proxy_vfunc(proxy);
645
void VerbAction::disconnect_proxy_vfunc(Gtk::Widget* proxy)
647
// g_message("disconnect_proxy_vfunc(%p) for '%s'", proxy, verb->get_id());
648
Gtk::Action::disconnect_proxy_vfunc(proxy);
651
void VerbAction::set_active(bool active)
653
this->active = active;
654
Glib::SListHandle<Gtk::Widget*> proxies = get_proxies();
655
for ( Glib::SListHandle<Gtk::Widget*>::iterator it = proxies.begin(); it != proxies.end(); ++it ) {
656
Gtk::ToolItem* ti = dynamic_cast<Gtk::ToolItem*>(*it);
658
// *should* have one child that is the SPButton
659
Gtk::Widget* child = ti->get_child();
660
if ( child && SP_IS_BUTTON(child->gobj()) ) {
661
SPButton* button = SP_BUTTON(child->gobj());
662
sp_button_toggle_set_down( button, active );
668
void VerbAction::on_activate()
671
SPAction *action = verb->get_action(view);
673
sp_action_perform(action, 0);
678
/* Global text entry widgets necessary for update */
679
/* GtkWidget *dropper_rgb_entry,
680
*dropper_opacity_entry ; */
681
// should be made a private member once this is converted to class
683
static void delete_connection(GObject * /*obj*/, sigc::connection *connection)
685
connection->disconnect();
689
static void purge_repr_listener( GObject* /*obj*/, GObject* tbl )
691
Inkscape::XML::Node* oldrepr = reinterpret_cast<Inkscape::XML::Node *>( g_object_get_data( tbl, "repr" ) );
692
if (oldrepr) { // remove old listener
693
sp_repr_remove_listener_by_data(oldrepr, tbl);
694
Inkscape::GC::release(oldrepr);
696
g_object_set_data( tbl, "repr", NULL );
700
// ------------------------------------------------------
703
* A simple mediator class that keeps UI controls matched to the preference values they set.
705
class PrefPusher : public Inkscape::Preferences::Observer
709
* Constructor for a boolean value that syncs to the supplied path.
710
* Initializes the widget to the current preference stored state and registers callbacks
711
* for widget changes and preference changes.
713
* @param act the widget to synchronize preference with.
714
* @param path the path to the preference the widget is synchronized with.
715
* @param callback function to invoke when changes are pushed.
716
* @param cbData data to be passed on to the callback function.
718
PrefPusher( GtkToggleAction *act, Glib::ustring const &path, void (*callback)(GObject*) = 0, GObject *cbData = 0 );
721
* Destructor that unregisters the preference callback.
723
virtual ~PrefPusher();
726
* Callback method invoked when the preference setting changes.
728
virtual void notify(Inkscape::Preferences::Entry const &new_val);
732
* Callback hook invoked when the widget changes.
734
* @param act the toggle action widget that was changed.
735
* @param self the PrefPusher instance the callback was registered to.
737
static void toggleCB( GtkToggleAction *act, PrefPusher *self );
740
* Method to handle the widget change.
742
void handleToggled();
744
GtkToggleAction *act;
745
void (*callback)(GObject*);
750
PrefPusher::PrefPusher( GtkToggleAction *act, Glib::ustring const &path, void (*callback)(GObject*), GObject *cbData ) :
757
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggleCB), this);
759
gtk_toggle_action_set_active( act, Inkscape::Preferences::get()->getBool(observed_path) );
762
Inkscape::Preferences::get()->addObserver(*this);
765
PrefPusher::~PrefPusher()
767
Inkscape::Preferences::get()->removeObserver(*this);
770
void PrefPusher::toggleCB( GtkToggleAction * /*act*/, PrefPusher *self )
773
self->handleToggled();
777
void PrefPusher::handleToggled()
781
Inkscape::Preferences::get()->setBool(observed_path, gtk_toggle_action_get_active( act ));
789
void PrefPusher::notify(Inkscape::Preferences::Entry const &newVal)
791
bool newBool = newVal.getBool();
792
bool oldBool = gtk_toggle_action_get_active(act);
794
if (!freeze && (newBool != oldBool)) {
795
gtk_toggle_action_set_active( act, newBool );
799
static void delete_prefspusher(GtkObject * /*obj*/, PrefPusher *watcher )
804
// ------------------------------------------------------
807
GtkWidget * sp_toolbox_button_new_from_verb_with_doubleclick(GtkWidget *t, Inkscape::IconSize size, SPButtonType type,
808
Inkscape::Verb *verb, Inkscape::Verb *doubleclick_verb,
809
Inkscape::UI::View::View *view, GtkTooltips *tt)
811
SPAction *action = verb->get_action(view);
816
SPAction *doubleclick_action;
817
if (doubleclick_verb) {
818
doubleclick_action = doubleclick_verb->get_action(view);
820
doubleclick_action = NULL;
823
/* fixme: Handle sensitive/unsensitive */
824
/* fixme: Implement sp_button_new_from_action */
825
GtkWidget *b = sp_button_new(size, type, action, doubleclick_action, tt);
829
unsigned int shortcut = sp_shortcut_get_primary(verb);
830
if (shortcut != GDK_VoidSymbol) {
831
gchar *key = sp_shortcut_get_label(shortcut);
832
gchar *tip = g_strdup_printf ("%s (%s)", action->tip, key);
834
gtk_toolbar_append_widget( GTK_TOOLBAR(t), b, tip, 0 );
840
gtk_toolbar_append_widget( GTK_TOOLBAR(t), b, action->tip, 0 );
848
static void trigger_sp_action( GtkAction* /*act*/, gpointer user_data )
850
SPAction* targetAction = SP_ACTION(user_data);
851
if ( targetAction ) {
852
sp_action_perform( targetAction, NULL );
856
static void sp_action_action_set_sensitive(SPAction * /*action*/, unsigned int sensitive, void *data)
859
GtkAction* act = GTK_ACTION(data);
860
gtk_action_set_sensitive( act, sensitive );
864
static SPActionEventVector action_event_vector = {
868
sp_action_action_set_sensitive,
873
static GtkAction* create_action_for_verb( Inkscape::Verb* verb, Inkscape::UI::View::View* view, Inkscape::IconSize size )
877
SPAction* targetAction = verb->get_action(view);
878
InkAction* inky = ink_action_new( verb->get_id(), _(verb->get_name()), verb->get_tip(), verb->get_image(), size );
879
act = GTK_ACTION(inky);
880
gtk_action_set_sensitive( act, targetAction->sensitive );
882
g_signal_connect( G_OBJECT(inky), "activate", GTK_SIGNAL_FUNC(trigger_sp_action), targetAction );
884
SPAction*rebound = dynamic_cast<SPAction *>( nr_object_ref( dynamic_cast<NRObject *>(targetAction) ) );
885
nr_active_object_add_listener( (NRActiveObject *)rebound, (NRObjectEventVector *)&action_event_vector, sizeof(SPActionEventVector), inky );
890
static Glib::RefPtr<Gtk::ActionGroup> create_or_fetch_actions( SPDesktop* desktop )
892
Inkscape::UI::View::View *view = desktop;
893
gint verbsToUse[] = {
894
// disabled until we have icons for them:
897
//SP_VERB_EDIT_UNTILE,
898
SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
899
SP_VERB_DIALOG_DISPLAY,
900
SP_VERB_DIALOG_FILL_STROKE,
901
SP_VERB_DIALOG_NAMEDVIEW,
903
SP_VERB_DIALOG_XML_EDITOR,
904
SP_VERB_DIALOG_LAYERS,
908
SP_VERB_EDIT_DUPLICATE,
912
SP_VERB_EDIT_UNLINK_CLONE,
919
SP_VERB_OBJECT_TO_CURVE,
920
SP_VERB_SELECTION_GROUP,
921
SP_VERB_SELECTION_OUTLINE,
922
SP_VERB_SELECTION_UNGROUP,
926
SP_VERB_ZOOM_DRAWING,
931
SP_VERB_ZOOM_PAGE_WIDTH,
933
SP_VERB_ZOOM_SELECTION,
936
Inkscape::IconSize toolboxSize = ToolboxFactory::prefToSize("/toolbox/small");
938
static std::map<SPDesktop*, Glib::RefPtr<Gtk::ActionGroup> > groups;
939
Glib::RefPtr<Gtk::ActionGroup> mainActions;
940
if ( groups.find(desktop) != groups.end() ) {
941
mainActions = groups[desktop];
944
if ( !mainActions ) {
945
mainActions = Gtk::ActionGroup::create("main");
946
groups[desktop] = mainActions;
949
for ( guint i = 0; i < G_N_ELEMENTS(verbsToUse); i++ ) {
950
Inkscape::Verb* verb = Inkscape::Verb::get(verbsToUse[i]);
952
if (!mainActions->get_action(verb->get_id())) {
953
GtkAction* act = create_action_for_verb( verb, view, toolboxSize );
954
mainActions->add(Glib::wrap(act));
959
if ( !mainActions->get_action("ToolZoom") ) {
960
GtkTooltips *tt = gtk_tooltips_new();
961
for ( guint i = 0; i < G_N_ELEMENTS(tools) && tools[i].type_name; i++ ) {
962
Glib::RefPtr<VerbAction> va = VerbAction::create(Inkscape::Verb::get(tools[i].verb), Inkscape::Verb::get(tools[i].doubleclick_verb), view, tt);
964
mainActions->add(va);
966
va->set_active(true);
976
static void handlebox_detached(GtkHandleBox* /*handlebox*/, GtkWidget* widget, gpointer /*userData*/)
978
gtk_widget_set_size_request( widget,
979
widget->allocation.width,
980
widget->allocation.height );
983
static void handlebox_attached(GtkHandleBox* /*handlebox*/, GtkWidget* widget, gpointer /*userData*/)
985
gtk_widget_set_size_request( widget, -1, -1 );
988
static GtkWidget* toolboxNewCommon( GtkWidget* tb, BarId id, GtkPositionType handlePos )
990
g_object_set_data(G_OBJECT(tb), "desktop", NULL);
992
gtk_widget_set_sensitive(tb, FALSE);
995
gboolean forceFloatAllowed = Inkscape::Preferences::get()->getBool("/options/workarounds/floatallowed", false);
996
if ( UXManager::getInstance()->isFloatWindowProblem() && !forceFloatAllowed ) {
997
hb = gtk_event_box_new(); // A simple, neutral container.
999
hb = gtk_handle_box_new();
1000
gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), handlePos);
1001
gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(hb), GTK_SHADOW_OUT);
1002
gtk_handle_box_set_snap_edge(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
1005
gtk_container_add(GTK_CONTAINER(hb), tb);
1006
gtk_widget_show(GTK_WIDGET(tb));
1008
sigc::connection* conn = new sigc::connection;
1009
g_object_set_data(G_OBJECT(hb), "event_context_connection", conn);
1011
if ( GTK_IS_HANDLE_BOX(hb) ) {
1012
g_signal_connect(G_OBJECT(hb), "child_detached", G_CALLBACK(handlebox_detached), static_cast<gpointer>(0));
1013
g_signal_connect(G_OBJECT(hb), "child_attached", G_CALLBACK(handlebox_attached), static_cast<gpointer>(0));
1016
gpointer val = GINT_TO_POINTER(id);
1017
g_object_set_data(G_OBJECT(hb), BAR_ID_KEY, val);
1022
GtkWidget *ToolboxFactory::createToolToolbox()
1024
GtkWidget *tb = gtk_vbox_new(FALSE, 0);
1026
return toolboxNewCommon( tb, BAR_TOOL, GTK_POS_TOP );
1029
GtkWidget *ToolboxFactory::createAuxToolbox()
1031
GtkWidget *tb = gtk_vbox_new(FALSE, 0);
1033
return toolboxNewCommon( tb, BAR_AUX, GTK_POS_LEFT );
1036
//####################################
1038
//####################################
1040
GtkWidget *ToolboxFactory::createCommandsToolbox()
1042
GtkWidget *tb = gtk_vbox_new(FALSE, 0);
1044
return toolboxNewCommon( tb, BAR_COMMANDS, GTK_POS_LEFT );
1047
GtkWidget *ToolboxFactory::createSnapToolbox()
1049
GtkWidget *tb = gtk_vbox_new(FALSE, 0);
1051
return toolboxNewCommon( tb, BAR_SNAP, GTK_POS_LEFT );
1054
static EgeAdjustmentAction * create_adjustment_action( gchar const *name,
1055
gchar const *label, gchar const *shortLabel, gchar const *tooltip,
1056
Glib::ustring const &path, gdouble def,
1057
GtkWidget *focusTarget,
1059
GObject *dataKludge,
1060
gboolean altx, gchar const *altx_mark,
1061
gdouble lower, gdouble upper, gdouble step, gdouble page,
1062
gchar const** descrLabels, gdouble const* descrValues, guint descrCount,
1063
void (*callback)(GtkAdjustment *, GObject *),
1064
gdouble climb = 0.1, guint digits = 3, double factor = 1.0 )
1066
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1067
GtkAdjustment* adj = GTK_ADJUSTMENT( gtk_adjustment_new( prefs->getDouble(path, def) * factor,
1068
lower, upper, step, page, 0 ) );
1070
sp_unit_selector_add_adjustment( SP_UNIT_SELECTOR(us), adj );
1073
gtk_signal_connect( GTK_OBJECT(adj), "value-changed", GTK_SIGNAL_FUNC(callback), dataKludge );
1075
EgeAdjustmentAction* act = ege_adjustment_action_new( adj, name, label, tooltip, 0, climb, digits );
1077
g_object_set( act, "short_label", shortLabel, NULL );
1080
if ( (descrCount > 0) && descrLabels && descrValues ) {
1081
ege_adjustment_action_set_descriptions( act, descrLabels, descrValues, descrCount );
1084
if ( focusTarget ) {
1085
ege_adjustment_action_set_focuswidget( act, focusTarget );
1088
if ( altx && altx_mark ) {
1089
g_object_set( G_OBJECT(act), "self-id", altx_mark, NULL );
1093
// Rather lame, but it's the only place where we need to get the entry name
1094
// but we don't have an Entry
1095
g_object_set_data( dataKludge, prefs->getEntry(path).getEntryName().data(), adj );
1098
// Using a cast just to make sure we pass in the right kind of function pointer
1099
g_object_set( G_OBJECT(act), "tool-post", static_cast<EgeWidgetFixup>(sp_set_font_size_smaller), NULL );
1105
//####################################
1106
//# node editing callbacks
1107
//####################################
1109
/** Temporary hack: Returns the node tool in the active desktop.
1110
* Will go away during tool refactoring. */
1111
static InkNodeTool *get_node_tool()
1113
InkNodeTool *tool = 0;
1114
if (SP_ACTIVE_DESKTOP ) {
1115
SPEventContext *ec = SP_ACTIVE_DESKTOP->event_context;
1116
if (INK_IS_NODE_TOOL(ec)) {
1117
tool = static_cast<InkNodeTool*>(ec);
1123
static void sp_node_path_edit_add(void)
1125
InkNodeTool *nt = get_node_tool();
1127
nt->_multipath->insertNodes();
1131
static void sp_node_path_edit_delete(void)
1133
InkNodeTool *nt = get_node_tool();
1135
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1136
nt->_multipath->deleteNodes(prefs->getBool("/tools/nodes/delete_preserves_shape", true));
1140
static void sp_node_path_edit_delete_segment(void)
1142
InkNodeTool *nt = get_node_tool();
1144
nt->_multipath->deleteSegments();
1148
static void sp_node_path_edit_break(void)
1150
InkNodeTool *nt = get_node_tool();
1152
nt->_multipath->breakNodes();
1156
static void sp_node_path_edit_join(void)
1158
InkNodeTool *nt = get_node_tool();
1160
nt->_multipath->joinNodes();
1164
static void sp_node_path_edit_join_segment(void)
1166
InkNodeTool *nt = get_node_tool();
1168
nt->_multipath->joinSegments();
1172
static void sp_node_path_edit_toline(void)
1174
InkNodeTool *nt = get_node_tool();
1176
nt->_multipath->setSegmentType(Inkscape::UI::SEGMENT_STRAIGHT);
1180
static void sp_node_path_edit_tocurve(void)
1182
InkNodeTool *nt = get_node_tool();
1184
nt->_multipath->setSegmentType(Inkscape::UI::SEGMENT_CUBIC_BEZIER);
1188
static void sp_node_path_edit_cusp(void)
1190
InkNodeTool *nt = get_node_tool();
1192
nt->_multipath->setNodeType(Inkscape::UI::NODE_CUSP);
1196
static void sp_node_path_edit_smooth(void)
1198
InkNodeTool *nt = get_node_tool();
1200
nt->_multipath->setNodeType(Inkscape::UI::NODE_SMOOTH);
1204
static void sp_node_path_edit_symmetrical(void)
1206
InkNodeTool *nt = get_node_tool();
1208
nt->_multipath->setNodeType(Inkscape::UI::NODE_SYMMETRIC);
1212
static void sp_node_path_edit_auto(void)
1214
InkNodeTool *nt = get_node_tool();
1216
nt->_multipath->setNodeType(Inkscape::UI::NODE_AUTO);
1220
static void sp_node_path_edit_nextLPEparam(GtkAction * /*act*/, gpointer data) {
1221
sp_selection_next_patheffect_param( reinterpret_cast<SPDesktop*>(data) );
1224
/* is called when the node selection is modified */
1225
static void sp_node_toolbox_coord_changed(gpointer /*shape_editor*/, GObject *tbl)
1227
GtkAction* xact = GTK_ACTION( g_object_get_data( tbl, "nodes_x_action" ) );
1228
GtkAction* yact = GTK_ACTION( g_object_get_data( tbl, "nodes_y_action" ) );
1229
GtkAdjustment *xadj = ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION(xact));
1230
GtkAdjustment *yadj = ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION(yact));
1232
// quit if run by the attr_changed listener
1233
if (g_object_get_data( tbl, "freeze" )) {
1237
// in turn, prevent listener from responding
1238
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE));
1240
UnitTracker* tracker = reinterpret_cast<UnitTracker*>( g_object_get_data( tbl, "tracker" ) );
1241
SPUnit const *unit = tracker->getActiveUnit();
1243
InkNodeTool *nt = get_node_tool();
1244
if (!nt || nt->_selected_nodes->empty()) {
1246
gtk_action_set_sensitive(xact, FALSE);
1247
gtk_action_set_sensitive(yact, FALSE);
1249
gtk_action_set_sensitive(xact, TRUE);
1250
gtk_action_set_sensitive(yact, TRUE);
1251
Geom::Coord oldx = sp_units_get_pixels(gtk_adjustment_get_value(xadj), *unit);
1252
Geom::Coord oldy = sp_units_get_pixels(gtk_adjustment_get_value(xadj), *unit);
1253
Geom::Point mid = nt->_selected_nodes->pointwiseBounds()->midpoint();
1255
if (oldx != mid[Geom::X]) {
1256
gtk_adjustment_set_value(xadj, sp_pixels_get_units(mid[Geom::X], *unit));
1258
if (oldy != mid[Geom::Y]) {
1259
gtk_adjustment_set_value(yadj, sp_pixels_get_units(mid[Geom::Y], *unit));
1263
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
1266
static void sp_node_path_value_changed(GtkAdjustment *adj, GObject *tbl, Geom::Dim2 d)
1268
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
1269
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1271
UnitTracker* tracker = reinterpret_cast<UnitTracker*>(g_object_get_data( tbl, "tracker" ));
1272
SPUnit const *unit = tracker->getActiveUnit();
1274
if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
1275
prefs->setDouble(Glib::ustring("/tools/nodes/") + (d == Geom::X ? "x" : "y"),
1276
sp_units_get_pixels(adj->value, *unit));
1279
// quit if run by the attr_changed listener
1280
if (g_object_get_data( tbl, "freeze" )) {
1284
// in turn, prevent listener from responding
1285
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE));
1287
InkNodeTool *nt = get_node_tool();
1288
if (nt && !nt->_selected_nodes->empty()) {
1289
double val = sp_units_get_pixels(gtk_adjustment_get_value(adj), *unit);
1290
double oldval = nt->_selected_nodes->pointwiseBounds()->midpoint()[d];
1291
Geom::Point delta(0,0);
1292
delta[d] = val - oldval;
1293
nt->_multipath->move(delta);
1296
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
1299
static void sp_node_path_x_value_changed(GtkAdjustment *adj, GObject *tbl)
1301
sp_node_path_value_changed(adj, tbl, Geom::X);
1304
static void sp_node_path_y_value_changed(GtkAdjustment *adj, GObject *tbl)
1306
sp_node_path_value_changed(adj, tbl, Geom::Y);
1309
static void sp_node_toolbox_sel_changed(Inkscape::Selection *selection, GObject *tbl)
1312
GtkAction* w = GTK_ACTION( g_object_get_data( tbl, "nodes_lpeedit" ) );
1313
SPItem *item = selection->singleItem();
1314
if (item && SP_IS_LPE_ITEM(item)) {
1315
if (sp_lpe_item_has_path_effect(SP_LPE_ITEM(item))) {
1316
gtk_action_set_sensitive(w, TRUE);
1318
gtk_action_set_sensitive(w, FALSE);
1321
gtk_action_set_sensitive(w, FALSE);
1326
static void sp_node_toolbox_sel_modified(Inkscape::Selection *selection, guint /*flags*/, GObject *tbl)
1328
sp_node_toolbox_sel_changed (selection, tbl);
1333
//################################
1334
//## Node Editing Toolbox ##
1335
//################################
1337
static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
1339
UnitTracker* tracker = new UnitTracker( SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE );
1340
tracker->setActiveUnit( sp_desktop_namedview(desktop)->doc_units );
1341
g_object_set_data( holder, "tracker", tracker );
1343
Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1);
1346
InkAction* inky = ink_action_new( "NodeInsertAction",
1348
_("Insert new nodes into selected segments"),
1349
INKSCAPE_ICON_NODE_ADD,
1351
g_object_set( inky, "short_label", _("Insert"), NULL );
1352
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_node_path_edit_add), 0 );
1353
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
1357
InkAction* inky = ink_action_new( "NodeDeleteAction",
1359
_("Delete selected nodes"),
1360
INKSCAPE_ICON_NODE_DELETE,
1362
g_object_set( inky, "short_label", _("Delete"), NULL );
1363
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_node_path_edit_delete), 0 );
1364
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
1368
InkAction* inky = ink_action_new( "NodeJoinAction",
1370
_("Join selected nodes"),
1371
INKSCAPE_ICON_NODE_JOIN,
1373
g_object_set( inky, "short_label", _("Join"), NULL );
1374
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_node_path_edit_join), 0 );
1375
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
1379
InkAction* inky = ink_action_new( "NodeBreakAction",
1381
_("Break path at selected nodes"),
1382
INKSCAPE_ICON_NODE_BREAK,
1384
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_node_path_edit_break), 0 );
1385
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
1390
InkAction* inky = ink_action_new( "NodeJoinSegmentAction",
1391
_("Join with segment"),
1392
_("Join selected endnodes with a new segment"),
1393
INKSCAPE_ICON_NODE_JOIN_SEGMENT,
1395
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_node_path_edit_join_segment), 0 );
1396
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
1400
InkAction* inky = ink_action_new( "NodeDeleteSegmentAction",
1401
_("Delete segment"),
1402
_("Delete segment between two non-endpoint nodes"),
1403
INKSCAPE_ICON_NODE_DELETE_SEGMENT,
1405
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_node_path_edit_delete_segment), 0 );
1406
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
1410
InkAction* inky = ink_action_new( "NodeCuspAction",
1412
_("Make selected nodes corner"),
1413
INKSCAPE_ICON_NODE_TYPE_CUSP,
1415
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_node_path_edit_cusp), 0 );
1416
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
1420
InkAction* inky = ink_action_new( "NodeSmoothAction",
1422
_("Make selected nodes smooth"),
1423
INKSCAPE_ICON_NODE_TYPE_SMOOTH,
1425
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_node_path_edit_smooth), 0 );
1426
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
1430
InkAction* inky = ink_action_new( "NodeSymmetricAction",
1431
_("Node Symmetric"),
1432
_("Make selected nodes symmetric"),
1433
INKSCAPE_ICON_NODE_TYPE_SYMMETRIC,
1435
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_node_path_edit_symmetrical), 0 );
1436
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
1440
InkAction* inky = ink_action_new( "NodeAutoAction",
1442
_("Make selected nodes auto-smooth"),
1443
INKSCAPE_ICON_NODE_TYPE_AUTO_SMOOTH,
1445
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_node_path_edit_auto), 0 );
1446
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
1450
InkAction* inky = ink_action_new( "NodeLineAction",
1452
_("Make selected segments lines"),
1453
INKSCAPE_ICON_NODE_SEGMENT_LINE,
1455
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_node_path_edit_toline), 0 );
1456
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
1460
InkAction* inky = ink_action_new( "NodeCurveAction",
1462
_("Make selected segments curves"),
1463
INKSCAPE_ICON_NODE_SEGMENT_CURVE,
1465
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_node_path_edit_tocurve), 0 );
1466
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
1470
InkToggleAction* act = ink_toggle_action_new( "NodesShowTransformHandlesAction",
1471
_("Show Transform Handles"),
1472
_("Show transformation handles for selected nodes"),
1475
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
1476
PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/nodes/show_transform_handles");
1477
g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
1481
InkToggleAction* act = ink_toggle_action_new( "NodesShowHandlesAction",
1483
_("Show Bezier handles of selected nodes"),
1484
INKSCAPE_ICON_SHOW_NODE_HANDLES,
1486
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
1487
PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/nodes/show_handles");
1488
g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
1492
InkToggleAction* act = ink_toggle_action_new( "NodesShowHelperpath",
1494
_("Show path outline (without path effects)"),
1495
INKSCAPE_ICON_SHOW_PATH_OUTLINE,
1497
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
1498
PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/nodes/show_outline");
1499
g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
1503
Inkscape::Verb* verb = Inkscape::Verb::get(SP_VERB_EDIT_NEXT_PATHEFFECT_PARAMETER);
1504
InkAction* inky = ink_action_new( verb->get_id(),
1507
INKSCAPE_ICON_PATH_EFFECT_PARAMETER_NEXT,
1509
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_node_path_edit_nextLPEparam), desktop );
1510
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
1511
g_object_set_data( holder, "nodes_lpeedit", inky);
1515
InkToggleAction* inky = ink_toggle_action_new( "ObjectEditClipPathAction",
1516
_("Edit clipping paths"),
1517
_("Show clipping path(s) of selected object(s)"),
1518
INKSCAPE_ICON_PATH_CLIP_EDIT,
1520
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
1521
PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(inky), "/tools/nodes/edit_clipping_paths");
1522
g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
1526
InkToggleAction* inky = ink_toggle_action_new( "ObjectEditMaskPathAction",
1528
_("Show mask(s) of selected object(s)"),
1529
INKSCAPE_ICON_PATH_MASK_EDIT,
1531
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
1532
PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(inky), "/tools/nodes/edit_masks");
1533
g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
1536
/* X coord of selected node(s) */
1538
EgeAdjustmentAction* eact = 0;
1539
gchar const* labels[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1540
gdouble values[] = {1, 2, 3, 5, 10, 20, 50, 100, 200, 500};
1541
eact = create_adjustment_action( "NodeXAction",
1542
_("X coordinate:"), _("X:"), _("X coordinate of selected node(s)"),
1543
"/tools/nodes/Xcoord", 0,
1544
GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, TRUE, "altx-nodes",
1545
-1e6, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1546
labels, values, G_N_ELEMENTS(labels),
1547
sp_node_path_x_value_changed );
1548
tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) );
1549
g_object_set_data( holder, "nodes_x_action", eact );
1550
gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
1551
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
1554
/* Y coord of selected node(s) */
1556
EgeAdjustmentAction* eact = 0;
1557
gchar const* labels[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1558
gdouble values[] = {1, 2, 3, 5, 10, 20, 50, 100, 200, 500};
1559
eact = create_adjustment_action( "NodeYAction",
1560
_("Y coordinate:"), _("Y:"), _("Y coordinate of selected node(s)"),
1561
"/tools/nodes/Ycoord", 0,
1562
GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, FALSE, NULL,
1563
-1e6, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
1564
labels, values, G_N_ELEMENTS(labels),
1565
sp_node_path_y_value_changed );
1566
tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) );
1567
g_object_set_data( holder, "nodes_y_action", eact );
1568
gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
1569
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
1572
// add the units menu
1574
GtkAction* act = tracker->createAction( "NodeUnitsAction", _("Units"), ("") );
1575
gtk_action_group_add_action( mainActions, act );
1579
sp_node_toolbox_sel_changed(sp_desktop_selection(desktop), holder);
1582
Inkscape::ConnectionPool* pool = Inkscape::ConnectionPool::new_connection_pool ("ISNodeToolbox");
1584
sigc::connection *c_selection_changed =
1585
new sigc::connection (sp_desktop_selection (desktop)->connectChanged
1586
(sigc::bind (sigc::ptr_fun (sp_node_toolbox_sel_changed), (GObject*)holder)));
1587
pool->add_connection ("selection-changed", c_selection_changed);
1589
sigc::connection *c_selection_modified =
1590
new sigc::connection (sp_desktop_selection (desktop)->connectModified
1591
(sigc::bind (sigc::ptr_fun (sp_node_toolbox_sel_modified), (GObject*)holder)));
1592
pool->add_connection ("selection-modified", c_selection_modified);
1594
sigc::connection *c_subselection_changed =
1595
new sigc::connection (desktop->connectToolSubselectionChanged
1596
(sigc::bind (sigc::ptr_fun (sp_node_toolbox_coord_changed), (GObject*)holder)));
1597
pool->add_connection ("tool-subselection-changed", c_subselection_changed);
1599
Inkscape::ConnectionPool::connect_destroy (G_OBJECT (holder), pool);
1601
g_signal_connect( holder, "destroy", G_CALLBACK(purge_repr_listener), holder );
1602
} // end of sp_node_toolbox_prep()
1605
//########################
1606
//## Zoom Toolbox ##
1607
//########################
1609
static void sp_zoom_toolbox_prep(SPDesktop * /*desktop*/, GtkActionGroup* /*mainActions*/, GObject* /*holder*/)
1611
// no custom GtkAction setup needed
1612
} // end of sp_zoom_toolbox_prep()
1614
void ToolboxFactory::setToolboxDesktop(GtkWidget *toolbox, SPDesktop *desktop)
1616
sigc::connection *conn = static_cast<sigc::connection*>(g_object_get_data(G_OBJECT(toolbox),
1617
"event_context_connection"));
1619
BarId id = static_cast<BarId>( GPOINTER_TO_INT(g_object_get_data(G_OBJECT(toolbox), BAR_ID_KEY)) );
1621
SetupFunction setup_func = 0;
1622
UpdateFunction update_func = 0;
1626
setup_func = setup_tool_toolbox;
1627
update_func = update_tool_toolbox;
1631
toolbox = gtk_bin_get_child(GTK_BIN(toolbox));
1632
setup_func = setup_aux_toolbox;
1633
update_func = update_aux_toolbox;
1637
setup_func = setup_commands_toolbox;
1638
update_func = update_commands_toolbox;
1642
setup_func = setup_snap_toolbox;
1643
update_func = updateSnapToolbox;
1646
g_warning("Unexpected toolbox id encountered.");
1649
gpointer ptr = g_object_get_data(G_OBJECT(toolbox), "desktop");
1650
SPDesktop *old_desktop = static_cast<SPDesktop*>(ptr);
1653
GList *children, *iter;
1655
children = gtk_container_get_children(GTK_CONTAINER(toolbox));
1656
for ( iter = children ; iter ; iter = iter->next ) {
1657
gtk_container_remove( GTK_CONTAINER(toolbox), GTK_WIDGET(iter->data) );
1659
g_list_free(children);
1662
g_object_set_data(G_OBJECT(toolbox), "desktop", (gpointer)desktop);
1664
if (desktop && setup_func && update_func) {
1665
gtk_widget_set_sensitive(toolbox, TRUE);
1666
setup_func(toolbox, desktop);
1667
update_func(desktop, desktop->event_context, toolbox);
1668
*conn = desktop->connectEventContextChanged(sigc::bind (sigc::ptr_fun(update_func), toolbox));
1670
gtk_widget_set_sensitive(toolbox, FALSE);
1673
} // end of sp_toolbox_set_desktop()
1676
static void setupToolboxCommon( GtkWidget *toolbox,
1679
gchar const* toolbarName,
1680
gchar const* sizePref )
1682
Glib::RefPtr<Gtk::ActionGroup> mainActions = create_or_fetch_actions( desktop );
1683
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1685
GtkUIManager* mgr = gtk_ui_manager_new();
1688
GtkOrientation orientation = GTK_ORIENTATION_HORIZONTAL;
1690
gtk_ui_manager_insert_action_group( mgr, mainActions->gobj(), 0 );
1691
gtk_ui_manager_add_ui_from_string( mgr, descr, -1, &errVal );
1693
GtkWidget* toolBar = gtk_ui_manager_get_widget( mgr, toolbarName );
1694
if ( prefs->getBool("/toolbox/icononly", true) ) {
1695
gtk_toolbar_set_style( GTK_TOOLBAR(toolBar), GTK_TOOLBAR_ICONS );
1698
Inkscape::IconSize toolboxSize = ToolboxFactory::prefToSize(sizePref);
1699
gtk_toolbar_set_icon_size( GTK_TOOLBAR(toolBar), static_cast<GtkIconSize>(toolboxSize) );
1701
if (GTK_IS_HANDLE_BOX(toolbox)) {
1702
// g_message("GRABBING ORIENTATION [%s]", toolbarName);
1703
GtkPositionType pos = gtk_handle_box_get_handle_position(GTK_HANDLE_BOX(toolbox));
1704
orientation = ((pos == GTK_POS_LEFT) || (pos == GTK_POS_RIGHT)) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL;
1706
GtkPositionType pos = static_cast<GtkPositionType>(GPOINTER_TO_INT(g_object_get_data( G_OBJECT(toolbox), HANDLE_POS_MARK )));
1707
orientation = ((pos == GTK_POS_LEFT) || (pos == GTK_POS_RIGHT)) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL;
1709
gtk_toolbar_set_orientation(GTK_TOOLBAR(toolBar), orientation);
1710
gtk_toolbar_set_show_arrow(GTK_TOOLBAR(toolBar), TRUE);
1712
g_object_set_data(G_OBJECT(toolBar), "desktop", NULL);
1714
GtkWidget* child = gtk_bin_get_child(GTK_BIN(toolbox));
1716
gtk_container_remove( GTK_CONTAINER(toolbox), child );
1719
gtk_container_add( GTK_CONTAINER(toolbox), toolBar );
1722
#define noDUMP_DETAILS 1
1724
void ToolboxFactory::setOrientation(GtkWidget* toolbox, GtkOrientation orientation)
1727
g_message("Set orientation for %p to be %d", toolbox, orientation);
1728
GType type = GTK_WIDGET_TYPE(toolbox);
1729
g_message(" [%s]", g_type_name(type));
1730
g_message(" %p", g_object_get_data(G_OBJECT(toolbox), BAR_ID_KEY));
1733
GtkPositionType pos = (orientation == GTK_ORIENTATION_HORIZONTAL) ? GTK_POS_LEFT : GTK_POS_TOP;
1734
GtkHandleBox* handleBox = 0;
1736
if (GTK_IS_BIN(toolbox)) {
1738
g_message(" is a BIN");
1739
#endif // DUMP_DETAILS
1740
GtkWidget* child = gtk_bin_get_child(GTK_BIN(toolbox));
1743
GType type2 = GTK_WIDGET_TYPE(child);
1744
g_message(" child [%s]", g_type_name(type2));
1745
#endif // DUMP_DETAILS
1747
if (GTK_IS_BOX(child)) {
1749
g_message(" is a BOX");
1750
#endif // DUMP_DETAILS
1752
GList* children = gtk_container_get_children(GTK_CONTAINER(child));
1754
for (GList* curr = children; curr; curr = g_list_next(curr)) {
1755
GtkWidget* child2 = GTK_WIDGET(curr->data);
1757
GType type3 = GTK_WIDGET_TYPE(child2);
1758
g_message(" child2 [%s]", g_type_name(type3));
1759
#endif // DUMP_DETAILS
1761
if (GTK_IS_CONTAINER(child2)) {
1762
GList* children2 = gtk_container_get_children(GTK_CONTAINER(child2));
1764
for (GList* curr2 = children2; curr2; curr2 = g_list_next(curr2)) {
1765
GtkWidget* child3 = GTK_WIDGET(curr2->data);
1767
GType type4 = GTK_WIDGET_TYPE(child3);
1768
g_message(" child3 [%s]", g_type_name(type4));
1769
#endif // DUMP_DETAILS
1770
if (GTK_IS_TOOLBAR(child3)) {
1771
GtkToolbar* childBar = GTK_TOOLBAR(child3);
1772
gtk_toolbar_set_orientation(childBar, orientation);
1775
g_list_free(children2);
1780
if (GTK_IS_TOOLBAR(child2)) {
1781
GtkToolbar* childBar = GTK_TOOLBAR(child2);
1782
gtk_toolbar_set_orientation(childBar, orientation);
1783
if (GTK_IS_HANDLE_BOX(toolbox)) {
1784
handleBox = GTK_HANDLE_BOX(toolbox);
1787
g_message("need to add dynamic switch");
1790
g_list_free(children);
1792
// The call is being made before the toolbox proper has been setup.
1793
if (GTK_IS_HANDLE_BOX(toolbox)) {
1794
handleBox = GTK_HANDLE_BOX(toolbox);
1796
g_object_set_data(G_OBJECT(toolbox), HANDLE_POS_MARK, GINT_TO_POINTER(pos));
1799
} else if (GTK_IS_TOOLBAR(child)) {
1800
GtkToolbar* toolbar = GTK_TOOLBAR(child);
1801
gtk_toolbar_set_orientation( toolbar, orientation );
1802
if (GTK_IS_HANDLE_BOX(toolbox)) {
1803
handleBox = GTK_HANDLE_BOX(toolbox);
1810
gtk_handle_box_set_handle_position(handleBox, pos);
1814
void setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
1816
gchar const * descr =
1818
" <toolbar name='ToolToolbar'>"
1821
" <toolitem action='ToolSelector' />"
1822
" <toolitem action='ToolNode' />"
1823
" <toolitem action='ToolTweak' />"
1824
" <toolitem action='ToolZoom' />"
1827
" <toolitem action='ToolRect' />"
1828
" <toolitem action='Tool3DBox' />"
1829
" <toolitem action='ToolArc' />"
1830
" <toolitem action='ToolStar' />"
1831
" <toolitem action='ToolSpiral' />"
1834
" <toolitem action='ToolPencil' />"
1835
" <toolitem action='ToolPen' />"
1836
" <toolitem action='ToolCalligraphic' />"
1839
" <toolitem action='ToolText' />"
1841
" <!-- Paint large areas -->"
1842
" <toolitem action='ToolSpray' />"
1843
" <toolitem action='ToolEraser' />"
1846
" <toolitem action='ToolPaintBucket' />"
1847
" <toolitem action='ToolGradient' />"
1848
" <toolitem action='ToolDropper' />"
1850
" <toolitem action='ToolConnector' />"
1852
// " <toolitem action='ToolLPETool' />"
1856
setupToolboxCommon( toolbox, desktop, descr,
1858
"/toolbox/tools/small");
1861
void update_tool_toolbox( SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget * /*toolbox*/ )
1863
gchar const *const tname = ( eventcontext
1864
? gtk_type_name(GTK_OBJECT_TYPE(eventcontext))
1866
Glib::RefPtr<Gtk::ActionGroup> mainActions = create_or_fetch_actions( desktop );
1868
for (int i = 0 ; tools[i].type_name ; i++ ) {
1869
Glib::RefPtr<Gtk::Action> act = mainActions->get_action( Inkscape::Verb::get(tools[i].verb)->get_id() );
1871
bool setActive = tname && !strcmp(tname, tools[i].type_name);
1872
Glib::RefPtr<VerbAction> verbAct = Glib::RefPtr<VerbAction>::cast_dynamic(act);
1874
verbAct->set_active(setActive);
1880
void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
1882
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1883
GtkSizeGroup* grouper = gtk_size_group_new( GTK_SIZE_GROUP_BOTH );
1884
Glib::RefPtr<Gtk::ActionGroup> mainActions = create_or_fetch_actions( desktop );
1885
GtkUIManager* mgr = gtk_ui_manager_new();
1887
gtk_ui_manager_insert_action_group( mgr, mainActions->gobj(), 0 );
1888
gtk_ui_manager_add_ui_from_string( mgr, ui_descr, -1, &errVal );
1890
std::map<std::string, GtkWidget*> dataHolders;
1892
for (int i = 0 ; aux_toolboxes[i].type_name ; i++ ) {
1893
if ( aux_toolboxes[i].prep_func ) {
1894
// converted to GtkActions and UIManager
1896
GtkWidget* kludge = gtk_toolbar_new();
1897
g_object_set_data( G_OBJECT(kludge), "dtw", desktop->canvas);
1898
g_object_set_data( G_OBJECT(kludge), "desktop", desktop);
1899
dataHolders[aux_toolboxes[i].type_name] = kludge;
1900
aux_toolboxes[i].prep_func( desktop, mainActions->gobj(), G_OBJECT(kludge) );
1903
GtkWidget *sub_toolbox = 0;
1904
if (aux_toolboxes[i].create_func == NULL) {
1905
sub_toolbox = sp_empty_toolbox_new(desktop);
1907
sub_toolbox = aux_toolboxes[i].create_func(desktop);
1910
gtk_size_group_add_widget( grouper, sub_toolbox );
1912
gtk_container_add(GTK_CONTAINER(toolbox), sub_toolbox);
1913
g_object_set_data(G_OBJECT(toolbox), aux_toolboxes[i].data_name, sub_toolbox);
1918
// Second pass to create toolbars *after* all GtkActions are created
1919
for (int i = 0 ; aux_toolboxes[i].type_name ; i++ ) {
1920
if ( aux_toolboxes[i].prep_func ) {
1921
// converted to GtkActions and UIManager
1923
GtkWidget* kludge = dataHolders[aux_toolboxes[i].type_name];
1925
GtkWidget* holder = gtk_table_new( 1, 3, FALSE );
1926
gtk_table_attach( GTK_TABLE(holder), kludge, 2, 3, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0 );
1928
gchar* tmp = g_strdup_printf( "/ui/%s", aux_toolboxes[i].ui_name );
1929
GtkWidget* toolBar = gtk_ui_manager_get_widget( mgr, tmp );
1933
if ( prefs->getBool( "/toolbox/icononly", true) ) {
1934
gtk_toolbar_set_style( GTK_TOOLBAR(toolBar), GTK_TOOLBAR_ICONS );
1937
Inkscape::IconSize toolboxSize = ToolboxFactory::prefToSize("/toolbox/small");
1938
gtk_toolbar_set_icon_size( GTK_TOOLBAR(toolBar), static_cast<GtkIconSize>(toolboxSize) );
1940
gtk_table_attach( GTK_TABLE(holder), toolBar, 0, 1, 0, 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 0, 0 );
1942
if ( aux_toolboxes[i].swatch_verb_id != SP_VERB_INVALID ) {
1943
Inkscape::UI::Widget::StyleSwatch *swatch = new Inkscape::UI::Widget::StyleSwatch( NULL, _(aux_toolboxes[i].swatch_tip) );
1944
swatch->setDesktop( desktop );
1945
swatch->setClickVerb( aux_toolboxes[i].swatch_verb_id );
1946
swatch->setWatchedTool( aux_toolboxes[i].swatch_tool, true );
1947
GtkWidget *swatch_ = GTK_WIDGET( swatch->gobj() );
1948
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 );
1951
gtk_widget_show_all( holder );
1952
sp_set_font_size_smaller( holder );
1954
gtk_size_group_add_widget( grouper, holder );
1956
gtk_container_add( GTK_CONTAINER(toolbox), holder );
1957
g_object_set_data( G_OBJECT(toolbox), aux_toolboxes[i].data_name, holder );
1961
g_object_unref( G_OBJECT(grouper) );
1964
void update_aux_toolbox(SPDesktop * /*desktop*/, SPEventContext *eventcontext, GtkWidget *toolbox)
1966
gchar const *tname = ( eventcontext
1967
? gtk_type_name(GTK_OBJECT_TYPE(eventcontext))
1969
for (int i = 0 ; aux_toolboxes[i].type_name ; i++ ) {
1970
GtkWidget *sub_toolbox = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), aux_toolboxes[i].data_name));
1971
if (tname && !strcmp(tname, aux_toolboxes[i].type_name)) {
1972
gtk_widget_show_all(sub_toolbox);
1973
g_object_set_data(G_OBJECT(toolbox), "shows", sub_toolbox);
1975
gtk_widget_hide(sub_toolbox);
1980
void setup_commands_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
1982
gchar const * descr =
1984
" <toolbar name='CommandsToolbar'>"
1985
" <toolitem action='FileNew' />"
1986
" <toolitem action='FileOpen' />"
1987
" <toolitem action='FileSave' />"
1988
" <toolitem action='FilePrint' />"
1990
" <toolitem action='FileImport' />"
1991
" <toolitem action='FileExport' />"
1993
" <toolitem action='EditUndo' />"
1994
" <toolitem action='EditRedo' />"
1996
" <toolitem action='EditCopy' />"
1997
" <toolitem action='EditCut' />"
1998
" <toolitem action='EditPaste' />"
2000
" <toolitem action='ZoomSelection' />"
2001
" <toolitem action='ZoomDrawing' />"
2002
" <toolitem action='ZoomPage' />"
2004
" <toolitem action='EditDuplicate' />"
2005
" <toolitem action='EditClone' />"
2006
" <toolitem action='EditUnlinkClone' />"
2008
" <toolitem action='SelectionGroup' />"
2009
" <toolitem action='SelectionUnGroup' />"
2011
" <toolitem action='DialogFillStroke' />"
2012
" <toolitem action='DialogText' />"
2013
" <toolitem action='DialogLayers' />"
2014
" <toolitem action='DialogXMLEditor' />"
2015
" <toolitem action='DialogAlignDistribute' />"
2017
" <toolitem action='DialogPreferences' />"
2018
" <toolitem action='DialogDocumentProperties' />"
2022
setupToolboxCommon( toolbox, desktop, descr,
2023
"/ui/CommandsToolbar",
2027
void update_commands_toolbox(SPDesktop * /*desktop*/, SPEventContext * /*eventcontext*/, GtkWidget * /*toolbox*/)
2031
static void toggle_snap_callback(GtkToggleAction *act, gpointer data) //data points to the toolbox
2033
if (g_object_get_data(G_OBJECT(data), "freeze" )) {
2037
gpointer ptr = g_object_get_data(G_OBJECT(data), "desktop");
2038
g_assert(ptr != NULL);
2040
SPDesktop *dt = reinterpret_cast<SPDesktop*>(ptr);
2041
SPNamedView *nv = sp_desktop_namedview(dt);
2042
SPDocument *doc = SP_OBJECT_DOCUMENT(nv);
2044
if (dt == NULL || nv == NULL) {
2045
g_warning("No desktop or namedview specified (in toggle_snap_callback)!");
2049
Inkscape::XML::Node *repr = SP_OBJECT_REPR(nv);
2052
g_warning("This namedview doesn't have a xml representation attached!");
2056
bool saved = sp_document_get_undo_sensitive(doc);
2057
sp_document_set_undo_sensitive(doc, false);
2060
SPAttributeEnum attr = (SPAttributeEnum) GPOINTER_TO_INT(g_object_get_data(G_OBJECT(act), "SP_ATTR_INKSCAPE"));
2063
case SP_ATTR_INKSCAPE_SNAP_GLOBAL:
2064
dt->toggleSnapGlobal();
2066
case SP_ATTR_INKSCAPE_SNAP_BBOX:
2067
v = nv->snap_manager.snapprefs.getSnapModeBBox();
2068
sp_repr_set_boolean(repr, "inkscape:snap-bbox", !v);
2070
case SP_ATTR_INKSCAPE_BBOX_PATHS:
2071
v = nv->snap_manager.snapprefs.getSnapToBBoxPath();
2072
sp_repr_set_boolean(repr, "inkscape:bbox-paths", !v);
2074
case SP_ATTR_INKSCAPE_BBOX_NODES:
2075
v = nv->snap_manager.snapprefs.getSnapToBBoxNode();
2076
sp_repr_set_boolean(repr, "inkscape:bbox-nodes", !v);
2078
case SP_ATTR_INKSCAPE_SNAP_NODES:
2079
v = nv->snap_manager.snapprefs.getSnapModeNode();
2080
sp_repr_set_boolean(repr, "inkscape:snap-nodes", !v);
2082
case SP_ATTR_INKSCAPE_OBJECT_PATHS:
2083
v = nv->snap_manager.snapprefs.getSnapToItemPath();
2084
sp_repr_set_boolean(repr, "inkscape:object-paths", !v);
2086
case SP_ATTR_INKSCAPE_OBJECT_NODES:
2087
v = nv->snap_manager.snapprefs.getSnapToItemNode();
2088
sp_repr_set_boolean(repr, "inkscape:object-nodes", !v);
2090
case SP_ATTR_INKSCAPE_SNAP_SMOOTH_NODES:
2091
v = nv->snap_manager.snapprefs.getSnapSmoothNodes();
2092
sp_repr_set_boolean(repr, "inkscape:snap-smooth-nodes", !v);
2094
case SP_ATTR_INKSCAPE_SNAP_INTERS_PATHS:
2095
v = nv->snap_manager.snapprefs.getSnapIntersectionCS();
2096
sp_repr_set_boolean(repr, "inkscape:snap-intersection-paths", !v);
2098
case SP_ATTR_INKSCAPE_SNAP_CENTER:
2099
v = nv->snap_manager.snapprefs.getIncludeItemCenter();
2100
sp_repr_set_boolean(repr, "inkscape:snap-center", !v);
2102
case SP_ATTR_INKSCAPE_SNAP_GRIDS:
2103
v = nv->snap_manager.snapprefs.getSnapToGrids();
2104
sp_repr_set_boolean(repr, "inkscape:snap-grids", !v);
2106
case SP_ATTR_INKSCAPE_SNAP_TO_GUIDES:
2107
v = nv->snap_manager.snapprefs.getSnapToGuides();
2108
sp_repr_set_boolean(repr, "inkscape:snap-to-guides", !v);
2110
case SP_ATTR_INKSCAPE_SNAP_PAGE:
2111
v = nv->snap_manager.snapprefs.getSnapToPageBorder();
2112
sp_repr_set_boolean(repr, "inkscape:snap-page", !v);
2114
/*case SP_ATTR_INKSCAPE_SNAP_INTERS_GRIDGUIDE:
2115
v = nv->snap_manager.snapprefs.getSnapIntersectionGG();
2116
sp_repr_set_boolean(repr, "inkscape:snap-intersection-grid-guide", !v);
2118
case SP_ATTR_INKSCAPE_SNAP_LINE_MIDPOINTS:
2119
v = nv->snap_manager.snapprefs.getSnapLineMidpoints();
2120
sp_repr_set_boolean(repr, "inkscape:snap-midpoints", !v);
2122
case SP_ATTR_INKSCAPE_SNAP_OBJECT_MIDPOINTS:
2123
v = nv->snap_manager.snapprefs.getSnapObjectMidpoints();
2124
sp_repr_set_boolean(repr, "inkscape:snap-object-midpoints", !v);
2126
case SP_ATTR_INKSCAPE_SNAP_BBOX_EDGE_MIDPOINTS:
2127
v = nv->snap_manager.snapprefs.getSnapBBoxEdgeMidpoints();
2128
sp_repr_set_boolean(repr, "inkscape:snap-bbox-edge-midpoints", !v);
2130
case SP_ATTR_INKSCAPE_SNAP_BBOX_MIDPOINTS:
2131
v = nv->snap_manager.snapprefs.getSnapBBoxMidpoints();
2132
sp_repr_set_boolean(repr, "inkscape:snap-bbox-midpoints", !v);
2135
g_warning("toggle_snap_callback has been called with an ID for which no action has been defined");
2139
// The snapping preferences are stored in the document, and therefore toggling makes the document dirty
2140
doc->setModifiedSinceSave();
2142
sp_document_set_undo_sensitive(doc, saved);
2145
void setup_snap_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
2147
Glib::RefPtr<Gtk::ActionGroup> mainActions = create_or_fetch_actions(desktop);
2149
gchar const * descr =
2151
" <toolbar name='SnapToolbar'>"
2152
" <toolitem action='ToggleSnapGlobal' />"
2154
" <toolitem action='ToggleSnapFromBBoxCorner' />"
2155
" <toolitem action='ToggleSnapToBBoxPath' />"
2156
" <toolitem action='ToggleSnapToBBoxNode' />"
2157
" <toolitem action='ToggleSnapToFromBBoxEdgeMidpoints' />"
2158
" <toolitem action='ToggleSnapToFromBBoxCenters' />"
2160
" <toolitem action='ToggleSnapFromNode' />"
2161
" <toolitem action='ToggleSnapToItemPath' />"
2162
" <toolitem action='ToggleSnapToPathIntersections' />"
2163
" <toolitem action='ToggleSnapToItemNode' />"
2164
" <toolitem action='ToggleSnapToSmoothNodes' />"
2165
" <toolitem action='ToggleSnapToFromLineMidpoints' />"
2166
" <toolitem action='ToggleSnapToFromObjectCenters' />"
2167
" <toolitem action='ToggleSnapToFromRotationCenter' />"
2169
" <toolitem action='ToggleSnapToPageBorder' />"
2170
" <toolitem action='ToggleSnapToGrids' />"
2171
" <toolitem action='ToggleSnapToGuides' />"
2172
//" <toolitem action='ToggleSnapToGridGuideIntersections' />"
2176
Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1);
2179
// TODO: This is a cludge. On the one hand we have verbs+actions,
2180
// on the other we have all these explicit callbacks specified here.
2181
// We should really unify these (should save some lines of code as well).
2182
// For example, this action could be based on the verb(+action) + PrefsPusher.
2183
Inkscape::Verb* verb = Inkscape::Verb::get(SP_VERB_TOGGLE_SNAPPING);
2184
InkToggleAction* act = ink_toggle_action_new(verb->get_id(),
2185
verb->get_name(), verb->get_tip(), INKSCAPE_ICON_SNAP, secondarySize,
2186
SP_ATTR_INKSCAPE_SNAP_GLOBAL);
2188
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2189
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2193
InkToggleAction* act = ink_toggle_action_new("ToggleSnapFromBBoxCorner",
2194
_("Bounding box"), _("Snap bounding box corners"), INKSCAPE_ICON_SNAP_BOUNDING_BOX,
2195
secondarySize, SP_ATTR_INKSCAPE_SNAP_BBOX);
2197
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2198
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2202
InkToggleAction* act = ink_toggle_action_new("ToggleSnapToBBoxPath",
2203
_("Bounding box edges"), _("Snap to edges of a bounding box"),
2204
INKSCAPE_ICON_SNAP_BOUNDING_BOX_EDGES, secondarySize, SP_ATTR_INKSCAPE_BBOX_PATHS);
2206
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2207
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2211
InkToggleAction* act = ink_toggle_action_new("ToggleSnapToBBoxNode",
2212
_("Bounding box corners"), _("Snap to bounding box corners"),
2213
INKSCAPE_ICON_SNAP_BOUNDING_BOX_CORNERS, secondarySize, SP_ATTR_INKSCAPE_BBOX_NODES);
2215
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2216
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2220
InkToggleAction* act = ink_toggle_action_new("ToggleSnapToFromBBoxEdgeMidpoints",
2221
_("BBox Edge Midpoints"), _("Snap from and to midpoints of bounding box edges"),
2222
INKSCAPE_ICON_SNAP_BOUNDING_BOX_MIDPOINTS, secondarySize,
2223
SP_ATTR_INKSCAPE_SNAP_BBOX_EDGE_MIDPOINTS);
2225
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2226
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2230
InkToggleAction* act = ink_toggle_action_new("ToggleSnapToFromBBoxCenters",
2231
_("BBox Centers"), _("Snapping from and to centers of bounding boxes"),
2232
INKSCAPE_ICON_SNAP_BOUNDING_BOX_CENTER, secondarySize, SP_ATTR_INKSCAPE_SNAP_BBOX_MIDPOINTS);
2234
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2235
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2239
InkToggleAction* act = ink_toggle_action_new("ToggleSnapFromNode",
2240
_("Nodes"), _("Snap nodes or handles"), INKSCAPE_ICON_SNAP_NODES, secondarySize, SP_ATTR_INKSCAPE_SNAP_NODES);
2242
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2243
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2247
InkToggleAction* act = ink_toggle_action_new("ToggleSnapToItemPath",
2248
_("Paths"), _("Snap to paths"), INKSCAPE_ICON_SNAP_NODES_PATH, secondarySize,
2249
SP_ATTR_INKSCAPE_OBJECT_PATHS);
2251
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2252
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2256
InkToggleAction* act = ink_toggle_action_new("ToggleSnapToPathIntersections",
2257
_("Path intersections"), _("Snap to path intersections"),
2258
INKSCAPE_ICON_SNAP_NODES_INTERSECTION, secondarySize, SP_ATTR_INKSCAPE_SNAP_INTERS_PATHS);
2260
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2261
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2265
InkToggleAction* act = ink_toggle_action_new("ToggleSnapToItemNode",
2266
_("To nodes"), _("Snap to cusp nodes"), INKSCAPE_ICON_SNAP_NODES_CUSP, secondarySize,
2267
SP_ATTR_INKSCAPE_OBJECT_NODES);
2269
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2270
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2274
InkToggleAction* act = ink_toggle_action_new("ToggleSnapToSmoothNodes",
2275
_("Smooth nodes"), _("Snap to smooth nodes"), INKSCAPE_ICON_SNAP_NODES_SMOOTH,
2276
secondarySize, SP_ATTR_INKSCAPE_SNAP_SMOOTH_NODES);
2278
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2279
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2283
InkToggleAction* act = ink_toggle_action_new("ToggleSnapToFromLineMidpoints",
2284
_("Line Midpoints"), _("Snap from and to midpoints of line segments"),
2285
INKSCAPE_ICON_SNAP_NODES_MIDPOINT, secondarySize, SP_ATTR_INKSCAPE_SNAP_LINE_MIDPOINTS);
2287
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2288
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2292
InkToggleAction* act = ink_toggle_action_new("ToggleSnapToFromObjectCenters",
2293
_("Object Centers"), _("Snap from and to centers of objects"),
2294
INKSCAPE_ICON_SNAP_NODES_CENTER, secondarySize, SP_ATTR_INKSCAPE_SNAP_OBJECT_MIDPOINTS);
2296
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2297
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2301
InkToggleAction* act = ink_toggle_action_new("ToggleSnapToFromRotationCenter",
2302
_("Rotation Centers"), _("Snap from and to an item's rotation center"),
2303
INKSCAPE_ICON_SNAP_NODES_ROTATION_CENTER, secondarySize, SP_ATTR_INKSCAPE_SNAP_CENTER);
2305
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2306
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2310
InkToggleAction* act = ink_toggle_action_new("ToggleSnapToPageBorder",
2311
_("Page border"), _("Snap to the page border"), INKSCAPE_ICON_SNAP_PAGE,
2312
secondarySize, SP_ATTR_INKSCAPE_SNAP_PAGE);
2314
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2315
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2319
InkToggleAction* act = ink_toggle_action_new("ToggleSnapToGrids",
2320
_("Grids"), _("Snap to grids"), INKSCAPE_ICON_GRID_RECTANGULAR, secondarySize,
2321
SP_ATTR_INKSCAPE_SNAP_GRIDS);
2323
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2324
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2328
InkToggleAction* act = ink_toggle_action_new("ToggleSnapToGuides",
2329
_("Guides"), _("Snap to guides"), INKSCAPE_ICON_GUIDES, secondarySize,
2330
SP_ATTR_INKSCAPE_SNAP_TO_GUIDES);
2332
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2333
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2337
InkToggleAction* act = ink_toggle_action_new("ToggleSnapToGridGuideIntersections",
2338
_("Grid/guide intersections"), _("Snap to intersections of a grid with a guide"),
2339
INKSCAPE_ICON_SNAP_GRID_GUIDE_INTERSECTIONS, secondarySize,
2340
SP_ATTR_INKSCAPE_SNAP_INTERS_GRIDGUIDE);
2342
gtk_action_group_add_action( mainActions->gobj(), GTK_ACTION( act ) );
2343
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_snap_callback), toolbox );
2346
setupToolboxCommon( toolbox, desktop, descr,
2348
"/toolbox/secondary" );
2351
Glib::ustring ToolboxFactory::getToolboxName(GtkWidget* toolbox)
2354
BarId id = static_cast<BarId>( GPOINTER_TO_INT(g_object_get_data(G_OBJECT(toolbox), BAR_ID_KEY)) );
2357
name = "ToolToolbar";
2360
name = "AuxToolbar";
2363
name = "CommandsToolbar";
2366
name = "SnapToolbar";
2373
void ToolboxFactory::updateSnapToolbox(SPDesktop *desktop, SPEventContext * /*eventcontext*/, GtkWidget *toolbox)
2375
g_assert(desktop != NULL);
2376
g_assert(toolbox != NULL);
2378
SPNamedView *nv = sp_desktop_namedview(desktop);
2380
g_warning("Namedview cannot be retrieved (in updateSnapToolbox)!");
2384
Glib::RefPtr<Gtk::ActionGroup> mainActions = create_or_fetch_actions(desktop);
2386
Glib::RefPtr<Gtk::Action> act1 = mainActions->get_action("ToggleSnapGlobal");
2387
Glib::RefPtr<Gtk::Action> act2 = mainActions->get_action("ToggleSnapFromBBoxCorner");
2388
Glib::RefPtr<Gtk::Action> act3 = mainActions->get_action("ToggleSnapToBBoxPath");
2389
Glib::RefPtr<Gtk::Action> act4 = mainActions->get_action("ToggleSnapToBBoxNode");
2390
Glib::RefPtr<Gtk::Action> act4b = mainActions->get_action("ToggleSnapToFromBBoxEdgeMidpoints");
2391
Glib::RefPtr<Gtk::Action> act4c = mainActions->get_action("ToggleSnapToFromBBoxCenters");
2392
Glib::RefPtr<Gtk::Action> act5 = mainActions->get_action("ToggleSnapFromNode");
2393
Glib::RefPtr<Gtk::Action> act6 = mainActions->get_action("ToggleSnapToItemPath");
2394
Glib::RefPtr<Gtk::Action> act6b = mainActions->get_action("ToggleSnapToPathIntersections");
2395
Glib::RefPtr<Gtk::Action> act7 = mainActions->get_action("ToggleSnapToItemNode");
2396
Glib::RefPtr<Gtk::Action> act8 = mainActions->get_action("ToggleSnapToSmoothNodes");
2397
Glib::RefPtr<Gtk::Action> act9 = mainActions->get_action("ToggleSnapToFromLineMidpoints");
2398
Glib::RefPtr<Gtk::Action> act10 = mainActions->get_action("ToggleSnapToFromObjectCenters");
2399
Glib::RefPtr<Gtk::Action> act11 = mainActions->get_action("ToggleSnapToFromRotationCenter");
2400
Glib::RefPtr<Gtk::Action> act12 = mainActions->get_action("ToggleSnapToPageBorder");
2401
//Glib::RefPtr<Gtk::Action> act13 = mainActions->get_action("ToggleSnapToGridGuideIntersections");
2402
Glib::RefPtr<Gtk::Action> act14 = mainActions->get_action("ToggleSnapToGrids");
2403
Glib::RefPtr<Gtk::Action> act15 = mainActions->get_action("ToggleSnapToGuides");
2407
return; // The snap actions haven't been defined yet (might be the case during startup)
2410
// The ..._set_active calls below will toggle the buttons, but this shouldn't lead to
2411
// changes in our document because we're only updating the UI;
2412
// Setting the "freeze" parameter to true will block the code in toggle_snap_callback()
2413
g_object_set_data(G_OBJECT(toolbox), "freeze", GINT_TO_POINTER(TRUE));
2415
bool const c1 = nv->snap_manager.snapprefs.getSnapEnabledGlobally();
2416
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act1->gobj()), c1);
2418
bool const c2 = nv->snap_manager.snapprefs.getSnapModeBBox();
2419
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act2->gobj()), c2);
2420
gtk_action_set_sensitive(GTK_ACTION(act2->gobj()), c1);
2422
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act3->gobj()), nv->snap_manager.snapprefs.getSnapToBBoxPath());
2423
gtk_action_set_sensitive(GTK_ACTION(act3->gobj()), c1 && c2);
2424
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act4->gobj()), nv->snap_manager.snapprefs.getSnapToBBoxNode());
2425
gtk_action_set_sensitive(GTK_ACTION(act4->gobj()), c1 && c2);
2426
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act4b->gobj()), nv->snap_manager.snapprefs.getSnapBBoxEdgeMidpoints());
2427
gtk_action_set_sensitive(GTK_ACTION(act4b->gobj()), c1 && c2);
2428
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act4c->gobj()), nv->snap_manager.snapprefs.getSnapBBoxMidpoints());
2429
gtk_action_set_sensitive(GTK_ACTION(act4c->gobj()), c1 && c2);
2431
bool const c3 = nv->snap_manager.snapprefs.getSnapModeNode();
2432
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act5->gobj()), c3);
2433
gtk_action_set_sensitive(GTK_ACTION(act5->gobj()), c1);
2435
bool const c4 = nv->snap_manager.snapprefs.getSnapToItemPath();
2436
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act6->gobj()), c4);
2437
gtk_action_set_sensitive(GTK_ACTION(act6->gobj()), c1 && c3);
2438
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act6b->gobj()), nv->snap_manager.snapprefs.getSnapIntersectionCS());
2439
gtk_action_set_sensitive(GTK_ACTION(act6b->gobj()), c1 && c3 && c4);
2440
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act7->gobj()), nv->snap_manager.snapprefs.getSnapToItemNode());
2441
gtk_action_set_sensitive(GTK_ACTION(act7->gobj()), c1 && c3);
2442
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act8->gobj()), nv->snap_manager.snapprefs.getSnapSmoothNodes());
2443
gtk_action_set_sensitive(GTK_ACTION(act8->gobj()), c1 && c3);
2444
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act9->gobj()), nv->snap_manager.snapprefs.getSnapLineMidpoints());
2445
gtk_action_set_sensitive(GTK_ACTION(act9->gobj()), c1 && c3);
2446
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act10->gobj()), nv->snap_manager.snapprefs.getSnapObjectMidpoints());
2447
gtk_action_set_sensitive(GTK_ACTION(act10->gobj()), c1 && c3);
2448
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act11->gobj()), nv->snap_manager.snapprefs.getIncludeItemCenter());
2449
gtk_action_set_sensitive(GTK_ACTION(act11->gobj()), c1 && c3);
2451
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act12->gobj()), nv->snap_manager.snapprefs.getSnapToPageBorder());
2452
gtk_action_set_sensitive(GTK_ACTION(act12->gobj()), c1);
2453
//gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act13->gobj()), nv->snap_manager.snapprefs.getSnapIntersectionGG());
2454
//gtk_action_set_sensitive(GTK_ACTION(act13->gobj()), c1);
2456
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act14->gobj()), nv->snap_manager.snapprefs.getSnapToGrids());
2457
gtk_action_set_sensitive(GTK_ACTION(act14->gobj()), c1);
2458
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act15->gobj()), nv->snap_manager.snapprefs.getSnapToGuides());
2459
gtk_action_set_sensitive(GTK_ACTION(act15->gobj()), c1);
2462
g_object_set_data(G_OBJECT(toolbox), "freeze", GINT_TO_POINTER(FALSE)); // unfreeze (see above)
2465
void ToolboxFactory::showAuxToolbox(GtkWidget *toolbox_toplevel)
2467
gtk_widget_show(toolbox_toplevel);
2468
GtkWidget *toolbox = gtk_bin_get_child(GTK_BIN(toolbox_toplevel));
2470
GtkWidget *shown_toolbox = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), "shows"));
2471
if (!shown_toolbox) {
2474
gtk_widget_show(toolbox);
2476
gtk_widget_show_all(shown_toolbox);
2479
static GtkWidget *sp_empty_toolbox_new(SPDesktop *desktop)
2481
GtkWidget *tbl = gtk_toolbar_new();
2482
gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
2483
gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
2485
gtk_widget_show_all(tbl);
2486
sp_set_font_size_smaller (tbl);
2491
#define MODE_LABEL_WIDTH 70
2493
//########################
2495
//########################
2497
static void sp_stb_magnitude_value_changed( GtkAdjustment *adj, GObject *dataKludge )
2499
SPDesktop *desktop = (SPDesktop *) g_object_get_data( dataKludge, "desktop" );
2501
if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2502
// do not remember prefs if this call is initiated by an undo change, because undoing object
2503
// creation sets bogus values to its attributes before it is deleted
2504
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
2505
prefs->setInt("/tools/shapes/star/magnitude", (gint)adj->value);
2508
// quit if run by the attr_changed listener
2509
if (g_object_get_data( dataKludge, "freeze" )) {
2513
// in turn, prevent listener from responding
2514
g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(TRUE) );
2516
bool modmade = false;
2518
Inkscape::Selection *selection = sp_desktop_selection(desktop);
2519
GSList const *items = selection->itemList();
2520
for (; items != NULL; items = items->next) {
2521
if (SP_IS_STAR((SPItem *) items->data)) {
2522
Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2523
sp_repr_set_int(repr,"sodipodi:sides",(gint)adj->value);
2524
sp_repr_set_svg_double(repr, "sodipodi:arg2",
2525
(sp_repr_get_double_attribute(repr, "sodipodi:arg1", 0.5)
2526
+ M_PI / (gint)adj->value));
2527
SP_OBJECT((SPItem *) items->data)->updateRepr();
2532
sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
2533
_("Star: Change number of corners"));
2536
g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(FALSE) );
2539
static void sp_stb_proportion_value_changed( GtkAdjustment *adj, GObject *dataKludge )
2541
SPDesktop *desktop = (SPDesktop *) g_object_get_data( dataKludge, "desktop" );
2543
if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2544
if (!IS_NAN(adj->value)) {
2545
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
2546
prefs->setDouble("/tools/shapes/star/proportion", adj->value);
2550
// quit if run by the attr_changed listener
2551
if (g_object_get_data( dataKludge, "freeze" )) {
2555
// in turn, prevent listener from responding
2556
g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(TRUE) );
2558
bool modmade = false;
2559
Inkscape::Selection *selection = sp_desktop_selection(desktop);
2560
GSList const *items = selection->itemList();
2561
for (; items != NULL; items = items->next) {
2562
if (SP_IS_STAR((SPItem *) items->data)) {
2563
Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2565
gdouble r1 = sp_repr_get_double_attribute(repr, "sodipodi:r1", 1.0);
2566
gdouble r2 = sp_repr_get_double_attribute(repr, "sodipodi:r2", 1.0);
2568
sp_repr_set_svg_double(repr, "sodipodi:r2", r1*adj->value);
2570
sp_repr_set_svg_double(repr, "sodipodi:r1", r2*adj->value);
2573
SP_OBJECT((SPItem *) items->data)->updateRepr();
2579
sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
2580
_("Star: Change spoke ratio"));
2583
g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(FALSE) );
2586
static void sp_stb_sides_flat_state_changed( EgeSelectOneAction *act, GObject *dataKludge )
2588
SPDesktop *desktop = (SPDesktop *) g_object_get_data( dataKludge, "desktop" );
2589
bool flat = ege_select_one_action_get_active( act ) == 0;
2591
if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2592
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
2593
prefs->setBool( "/tools/shapes/star/isflatsided", flat);
2596
// quit if run by the attr_changed listener
2597
if (g_object_get_data( dataKludge, "freeze" )) {
2601
// in turn, prevent listener from responding
2602
g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(TRUE) );
2604
Inkscape::Selection *selection = sp_desktop_selection(desktop);
2605
GSList const *items = selection->itemList();
2606
GtkAction* prop_action = GTK_ACTION( g_object_get_data( dataKludge, "prop_action" ) );
2607
bool modmade = false;
2609
if ( prop_action ) {
2610
gtk_action_set_sensitive( prop_action, !flat );
2613
for (; items != NULL; items = items->next) {
2614
if (SP_IS_STAR((SPItem *) items->data)) {
2615
Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2616
repr->setAttribute("inkscape:flatsided", flat ? "true" : "false" );
2617
SP_OBJECT((SPItem *) items->data)->updateRepr();
2623
sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
2624
flat ? _("Make polygon") : _("Make star"));
2627
g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(FALSE) );
2630
static void sp_stb_rounded_value_changed( GtkAdjustment *adj, GObject *dataKludge )
2632
SPDesktop *desktop = (SPDesktop *) g_object_get_data( dataKludge, "desktop" );
2634
if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2635
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
2636
prefs->setDouble("/tools/shapes/star/rounded", (gdouble) adj->value);
2639
// quit if run by the attr_changed listener
2640
if (g_object_get_data( dataKludge, "freeze" )) {
2644
// in turn, prevent listener from responding
2645
g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(TRUE) );
2647
bool modmade = false;
2649
Inkscape::Selection *selection = sp_desktop_selection(desktop);
2650
GSList const *items = selection->itemList();
2651
for (; items != NULL; items = items->next) {
2652
if (SP_IS_STAR((SPItem *) items->data)) {
2653
Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2654
sp_repr_set_svg_double(repr, "inkscape:rounded", (gdouble) adj->value);
2655
SP_OBJECT(items->data)->updateRepr();
2660
sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
2661
_("Star: Change rounding"));
2664
g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(FALSE) );
2667
static void sp_stb_randomized_value_changed( GtkAdjustment *adj, GObject *dataKludge )
2669
SPDesktop *desktop = (SPDesktop *) g_object_get_data( dataKludge, "desktop" );
2671
if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
2672
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
2673
prefs->setDouble("/tools/shapes/star/randomized", (gdouble) adj->value);
2676
// quit if run by the attr_changed listener
2677
if (g_object_get_data( dataKludge, "freeze" )) {
2681
// in turn, prevent listener from responding
2682
g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(TRUE) );
2684
bool modmade = false;
2686
Inkscape::Selection *selection = sp_desktop_selection(desktop);
2687
GSList const *items = selection->itemList();
2688
for (; items != NULL; items = items->next) {
2689
if (SP_IS_STAR((SPItem *) items->data)) {
2690
Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
2691
sp_repr_set_svg_double(repr, "inkscape:randomized", (gdouble) adj->value);
2692
SP_OBJECT(items->data)->updateRepr();
2697
sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_STAR,
2698
_("Star: Change randomization"));
2701
g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(FALSE) );
2705
static void star_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
2706
gchar const * /*old_value*/, gchar const * /*new_value*/,
2707
bool /*is_interactive*/, gpointer data)
2709
GtkWidget *tbl = GTK_WIDGET(data);
2711
// quit if run by the _changed callbacks
2712
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
2716
// in turn, prevent callbacks from responding
2717
g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
2719
GtkAdjustment *adj = 0;
2721
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
2722
bool isFlatSided = prefs->getBool("/tools/shapes/star/isflatsided", true);
2724
if (!strcmp(name, "inkscape:randomized")) {
2725
adj = GTK_ADJUSTMENT( gtk_object_get_data(GTK_OBJECT(tbl), "randomized") );
2726
gtk_adjustment_set_value(adj, sp_repr_get_double_attribute(repr, "inkscape:randomized", 0.0));
2727
} else if (!strcmp(name, "inkscape:rounded")) {
2728
adj = GTK_ADJUSTMENT( gtk_object_get_data(GTK_OBJECT(tbl), "rounded") );
2729
gtk_adjustment_set_value(adj, sp_repr_get_double_attribute(repr, "inkscape:rounded", 0.0));
2730
} else if (!strcmp(name, "inkscape:flatsided")) {
2731
GtkAction* prop_action = GTK_ACTION( g_object_get_data(G_OBJECT(tbl), "prop_action") );
2732
char const *flatsides = repr->attribute("inkscape:flatsided");
2733
EgeSelectOneAction* flat_action = EGE_SELECT_ONE_ACTION( g_object_get_data( G_OBJECT(tbl), "flat_action" ) );
2734
if ( flatsides && !strcmp(flatsides,"false") ) {
2735
ege_select_one_action_set_active( flat_action, 1 );
2736
gtk_action_set_sensitive( prop_action, TRUE );
2738
ege_select_one_action_set_active( flat_action, 0 );
2739
gtk_action_set_sensitive( prop_action, FALSE );
2741
} else if ((!strcmp(name, "sodipodi:r1") || !strcmp(name, "sodipodi:r2")) && (!isFlatSided) ) {
2742
adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "proportion");
2743
gdouble r1 = sp_repr_get_double_attribute(repr, "sodipodi:r1", 1.0);
2744
gdouble r2 = sp_repr_get_double_attribute(repr, "sodipodi:r2", 1.0);
2746
gtk_adjustment_set_value(adj, r2/r1);
2748
gtk_adjustment_set_value(adj, r1/r2);
2750
} else if (!strcmp(name, "sodipodi:sides")) {
2751
adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "magnitude");
2752
gtk_adjustment_set_value(adj, sp_repr_get_int_attribute(repr, "sodipodi:sides", 0));
2755
g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
2759
static Inkscape::XML::NodeEventVector star_tb_repr_events =
2761
NULL, /* child_added */
2762
NULL, /* child_removed */
2763
star_tb_event_attr_changed,
2764
NULL, /* content_changed */
2765
NULL /* order_changed */
2770
* \param selection Should not be NULL.
2773
sp_star_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
2776
Inkscape::XML::Node *repr = NULL;
2778
purge_repr_listener( tbl, tbl );
2780
for (GSList const *items = selection->itemList();
2782
items = items->next)
2784
if (SP_IS_STAR((SPItem *) items->data)) {
2786
repr = SP_OBJECT_REPR((SPItem *) items->data);
2790
EgeOutputAction* act = EGE_OUTPUT_ACTION( g_object_get_data( tbl, "mode_action" ) );
2792
if (n_selected == 0) {
2793
g_object_set( G_OBJECT(act), "label", _("<b>New:</b>"), NULL );
2794
} else if (n_selected == 1) {
2795
g_object_set( G_OBJECT(act), "label", _("<b>Change:</b>"), NULL );
2798
g_object_set_data( tbl, "repr", repr );
2799
Inkscape::GC::anchor(repr);
2800
sp_repr_add_listener(repr, &star_tb_repr_events, tbl);
2801
sp_repr_synthesize_events(repr, &star_tb_repr_events, tbl);
2804
// FIXME: implement averaging of all parameters for multiple selected stars
2805
//gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
2806
//gtk_label_set_markup(GTK_LABEL(l), _("<b>Change:</b>"));
2811
static void sp_stb_defaults( GtkWidget * /*widget*/, GObject *dataKludge )
2813
// FIXME: in this and all other _default functions, set some flag telling the value_changed
2814
// callbacks to lump all the changes for all selected objects in one undo step
2816
GtkAdjustment *adj = 0;
2818
// fixme: make settable in prefs!
2821
gboolean flat = FALSE;
2822
gdouble randomized = 0;
2823
gdouble rounded = 0;
2825
EgeSelectOneAction* flat_action = EGE_SELECT_ONE_ACTION( g_object_get_data( dataKludge, "flat_action" ) );
2826
ege_select_one_action_set_active( flat_action, flat ? 0 : 1 );
2828
GtkAction* sb2 = GTK_ACTION( g_object_get_data( dataKludge, "prop_action" ) );
2829
gtk_action_set_sensitive( sb2, !flat );
2831
adj = GTK_ADJUSTMENT( g_object_get_data( dataKludge, "magnitude" ) );
2832
gtk_adjustment_set_value(adj, mag);
2833
gtk_adjustment_value_changed(adj);
2835
adj = GTK_ADJUSTMENT( g_object_get_data( dataKludge, "proportion" ) );
2836
gtk_adjustment_set_value(adj, prop);
2837
gtk_adjustment_value_changed(adj);
2839
adj = GTK_ADJUSTMENT( g_object_get_data( dataKludge, "rounded" ) );
2840
gtk_adjustment_set_value(adj, rounded);
2841
gtk_adjustment_value_changed(adj);
2843
adj = GTK_ADJUSTMENT( g_object_get_data( dataKludge, "randomized" ) );
2844
gtk_adjustment_set_value(adj, randomized);
2845
gtk_adjustment_value_changed(adj);
2850
void sp_toolbox_add_label(GtkWidget *tbl, gchar const *title, bool wide)
2852
GtkWidget *boxl = gtk_hbox_new(FALSE, 0);
2854
gtk_widget_set_size_request(boxl, MODE_LABEL_WIDTH, -1);
2856
GtkWidget *l = gtk_label_new(NULL);
2857
gtk_label_set_markup(GTK_LABEL(l), title);
2858
gtk_box_pack_end(GTK_BOX(boxl), l, FALSE, FALSE, 0);
2859
if ( GTK_IS_TOOLBAR(tbl) ) {
2860
gtk_toolbar_append_widget( GTK_TOOLBAR(tbl), boxl, "", "" );
2862
gtk_box_pack_start(GTK_BOX(tbl), boxl, FALSE, FALSE, 0);
2864
gtk_object_set_data(GTK_OBJECT(tbl), "mode_label", l);
2868
static void sp_star_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
2870
Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1);
2873
EgeOutputAction* act = ege_output_action_new( "StarStateAction", _("<b>New:</b>"), "", 0 );
2874
ege_output_action_set_use_markup( act, TRUE );
2875
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
2876
g_object_set_data( holder, "mode_action", act );
2880
EgeAdjustmentAction* eact = 0;
2881
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
2882
bool isFlatSided = prefs->getBool("/tools/shapes/star/isflatsided", true);
2884
/* Flatsided checkbox */
2886
GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING );
2889
gtk_list_store_append( model, &iter );
2890
gtk_list_store_set( model, &iter,
2892
1, _("Regular polygon (with one handle) instead of a star"),
2893
2, INKSCAPE_ICON_DRAW_POLYGON,
2896
gtk_list_store_append( model, &iter );
2897
gtk_list_store_set( model, &iter,
2899
1, _("Star instead of a regular polygon (with one handle)"),
2900
2, INKSCAPE_ICON_DRAW_STAR,
2903
EgeSelectOneAction* act = ege_select_one_action_new( "FlatAction", (""), (""), NULL, GTK_TREE_MODEL(model) );
2904
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
2905
g_object_set_data( holder, "flat_action", act );
2907
ege_select_one_action_set_appearance( act, "full" );
2908
ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE );
2909
g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL );
2910
ege_select_one_action_set_icon_column( act, 2 );
2911
ege_select_one_action_set_icon_size( act, secondarySize );
2912
ege_select_one_action_set_tooltip_column( act, 1 );
2914
ege_select_one_action_set_active( act, isFlatSided ? 0 : 1 );
2915
g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_stb_sides_flat_state_changed), holder);
2920
gchar const* labels[] = {_("triangle/tri-star"), _("square/quad-star"), _("pentagon/five-pointed star"), _("hexagon/six-pointed star"), 0, 0, 0, 0, 0};
2921
gdouble values[] = {3, 4, 5, 6, 7, 8, 10, 12, 20};
2922
eact = create_adjustment_action( "MagnitudeAction",
2923
_("Corners"), _("Corners:"), _("Number of corners of a polygon or star"),
2924
"/tools/shapes/star/magnitude", 3,
2925
GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
2927
labels, values, G_N_ELEMENTS(labels),
2928
sp_stb_magnitude_value_changed,
2930
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
2931
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
2936
gchar const* labels[] = {_("thin-ray star"), 0, _("pentagram"), _("hexagram"), _("heptagram"), _("octagram"), _("regular polygon")};
2937
gdouble values[] = {0.01, 0.2, 0.382, 0.577, 0.692, 0.765, 1};
2938
eact = create_adjustment_action( "SpokeAction",
2939
_("Spoke ratio"), _("Spoke ratio:"),
2940
// TRANSLATORS: Tip radius of a star is the distance from the center to the farthest handle.
2941
// Base radius is the same for the closest handle.
2942
_("Base radius to tip radius ratio"),
2943
"/tools/shapes/star/proportion", 0.5,
2944
GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
2945
0.01, 1.0, 0.01, 0.1,
2946
labels, values, G_N_ELEMENTS(labels),
2947
sp_stb_proportion_value_changed );
2948
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
2949
g_object_set_data( holder, "prop_action", eact );
2952
if ( !isFlatSided ) {
2953
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
2955
gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
2960
gchar const* labels[] = {_("stretched"), _("twisted"), _("slightly pinched"), _("NOT rounded"), _("slightly rounded"), _("visibly rounded"), _("well rounded"), _("amply rounded"), 0, _("stretched"), _("blown up")};
2961
gdouble values[] = {-1, -0.2, -0.03, 0, 0.05, 0.1, 0.2, 0.3, 0.5, 1, 10};
2962
eact = create_adjustment_action( "RoundednessAction",
2963
_("Rounded"), _("Rounded:"), _("How much rounded are the corners (0 for sharp)"),
2964
"/tools/shapes/star/rounded", 0.0,
2965
GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
2966
-10.0, 10.0, 0.01, 0.1,
2967
labels, values, G_N_ELEMENTS(labels),
2968
sp_stb_rounded_value_changed );
2969
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
2970
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
2975
gchar const* labels[] = {_("NOT randomized"), _("slightly irregular"), _("visibly randomized"), _("strongly randomized"), _("blown up")};
2976
gdouble values[] = {0, 0.01, 0.1, 0.5, 10};
2977
eact = create_adjustment_action( "RandomizationAction",
2978
_("Randomized"), _("Randomized:"), _("Scatter randomly the corners and angles"),
2979
"/tools/shapes/star/randomized", 0.0,
2980
GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
2981
-10.0, 10.0, 0.001, 0.01,
2982
labels, values, G_N_ELEMENTS(labels),
2983
sp_stb_randomized_value_changed, 0.1, 3 );
2984
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
2985
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
2992
GtkAction* act = gtk_action_new( "StarResetAction",
2994
_("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"),
2996
g_signal_connect_after( G_OBJECT(act), "activate", G_CALLBACK(sp_stb_defaults), holder );
2997
gtk_action_group_add_action( mainActions, act );
2998
gtk_action_set_sensitive( act, TRUE );
3002
sigc::connection *connection = new sigc::connection(
3003
sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_star_toolbox_selection_changed), (GObject *)holder))
3005
g_signal_connect( holder, "destroy", G_CALLBACK(delete_connection), connection );
3006
g_signal_connect( holder, "destroy", G_CALLBACK(purge_repr_listener), holder );
3010
//########################
3012
//########################
3014
static void sp_rtb_sensitivize( GObject *tbl )
3016
GtkAdjustment *adj1 = GTK_ADJUSTMENT( g_object_get_data(tbl, "rx") );
3017
GtkAdjustment *adj2 = GTK_ADJUSTMENT( g_object_get_data(tbl, "ry") );
3018
GtkAction* not_rounded = GTK_ACTION( g_object_get_data(tbl, "not_rounded") );
3020
if (adj1->value == 0 && adj2->value == 0 && g_object_get_data(tbl, "single")) { // only for a single selected rect (for now)
3021
gtk_action_set_sensitive( not_rounded, FALSE );
3023
gtk_action_set_sensitive( not_rounded, TRUE );
3028
static void sp_rtb_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *value_name,
3029
void (*setter)(SPRect *, gdouble))
3031
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
3033
UnitTracker* tracker = reinterpret_cast<UnitTracker*>(g_object_get_data( tbl, "tracker" ));
3034
SPUnit const *unit = tracker->getActiveUnit();
3036
if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
3037
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
3038
prefs->setDouble(Glib::ustring("/tools/shapes/rect/") + value_name, sp_units_get_pixels(adj->value, *unit));
3041
// quit if run by the attr_changed listener
3042
if (g_object_get_data( tbl, "freeze" )) {
3046
// in turn, prevent listener from responding
3047
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE));
3049
bool modmade = false;
3050
Inkscape::Selection *selection = sp_desktop_selection(desktop);
3051
for (GSList const *items = selection->itemList(); items != NULL; items = items->next) {
3052
if (SP_IS_RECT(items->data)) {
3053
if (adj->value != 0) {
3054
setter(SP_RECT(items->data), sp_units_get_pixels(adj->value, *unit));
3056
SP_OBJECT_REPR(items->data)->setAttribute(value_name, NULL);
3062
sp_rtb_sensitivize( tbl );
3065
sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_RECT,
3066
_("Change rectangle"));
3069
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
3072
static void sp_rtb_rx_value_changed(GtkAdjustment *adj, GObject *tbl)
3074
sp_rtb_value_changed(adj, tbl, "rx", sp_rect_set_visible_rx);
3077
static void sp_rtb_ry_value_changed(GtkAdjustment *adj, GObject *tbl)
3079
sp_rtb_value_changed(adj, tbl, "ry", sp_rect_set_visible_ry);
3082
static void sp_rtb_width_value_changed(GtkAdjustment *adj, GObject *tbl)
3084
sp_rtb_value_changed(adj, tbl, "width", sp_rect_set_visible_width);
3087
static void sp_rtb_height_value_changed(GtkAdjustment *adj, GObject *tbl)
3089
sp_rtb_value_changed(adj, tbl, "height", sp_rect_set_visible_height);
3094
static void sp_rtb_defaults( GtkWidget * /*widget*/, GObject *obj)
3096
GtkAdjustment *adj = 0;
3098
adj = GTK_ADJUSTMENT( g_object_get_data(obj, "rx") );
3099
gtk_adjustment_set_value(adj, 0.0);
3100
// this is necessary if the previous value was 0, but we still need to run the callback to change all selected objects
3101
gtk_adjustment_value_changed(adj);
3103
adj = GTK_ADJUSTMENT( g_object_get_data(obj, "ry") );
3104
gtk_adjustment_set_value(adj, 0.0);
3105
gtk_adjustment_value_changed(adj);
3107
sp_rtb_sensitivize( obj );
3110
static void rect_tb_event_attr_changed(Inkscape::XML::Node * /*repr*/, gchar const * /*name*/,
3111
gchar const * /*old_value*/, gchar const * /*new_value*/,
3112
bool /*is_interactive*/, gpointer data)
3114
GObject *tbl = G_OBJECT(data);
3116
// quit if run by the _changed callbacks
3117
if (g_object_get_data( tbl, "freeze" )) {
3121
// in turn, prevent callbacks from responding
3122
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
3124
UnitTracker* tracker = reinterpret_cast<UnitTracker*>( g_object_get_data( tbl, "tracker" ) );
3125
SPUnit const *unit = tracker->getActiveUnit();
3127
gpointer item = g_object_get_data( tbl, "item" );
3128
if (item && SP_IS_RECT(item)) {
3130
GtkAdjustment *adj = GTK_ADJUSTMENT( g_object_get_data( tbl, "rx" ) );
3131
gdouble rx = sp_rect_get_visible_rx(SP_RECT(item));
3132
gtk_adjustment_set_value(adj, sp_pixels_get_units(rx, *unit));
3136
GtkAdjustment *adj = GTK_ADJUSTMENT( g_object_get_data( tbl, "ry" ) );
3137
gdouble ry = sp_rect_get_visible_ry(SP_RECT(item));
3138
gtk_adjustment_set_value(adj, sp_pixels_get_units(ry, *unit));
3142
GtkAdjustment *adj = GTK_ADJUSTMENT( g_object_get_data( tbl, "width" ) );
3143
gdouble width = sp_rect_get_visible_width (SP_RECT(item));
3144
gtk_adjustment_set_value(adj, sp_pixels_get_units(width, *unit));
3148
GtkAdjustment *adj = GTK_ADJUSTMENT( g_object_get_data( tbl, "height" ) );
3149
gdouble height = sp_rect_get_visible_height (SP_RECT(item));
3150
gtk_adjustment_set_value(adj, sp_pixels_get_units(height, *unit));
3154
sp_rtb_sensitivize( tbl );
3156
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
3160
static Inkscape::XML::NodeEventVector rect_tb_repr_events = {
3161
NULL, /* child_added */
3162
NULL, /* child_removed */
3163
rect_tb_event_attr_changed,
3164
NULL, /* content_changed */
3165
NULL /* order_changed */
3169
* \param selection should not be NULL.
3171
static void sp_rect_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
3174
Inkscape::XML::Node *repr = NULL;
3175
SPItem *item = NULL;
3177
if ( g_object_get_data( tbl, "repr" ) ) {
3178
g_object_set_data( tbl, "item", NULL );
3180
purge_repr_listener( tbl, tbl );
3182
for (GSList const *items = selection->itemList();
3184
items = items->next) {
3185
if (SP_IS_RECT((SPItem *) items->data)) {
3187
item = (SPItem *) items->data;
3188
repr = SP_OBJECT_REPR(item);
3192
EgeOutputAction* act = EGE_OUTPUT_ACTION( g_object_get_data( tbl, "mode_action" ) );
3194
g_object_set_data( tbl, "single", GINT_TO_POINTER(FALSE) );
3196
if (n_selected == 0) {
3197
g_object_set( G_OBJECT(act), "label", _("<b>New:</b>"), NULL );
3199
GtkAction* w = GTK_ACTION( g_object_get_data( tbl, "width_action" ) );
3200
gtk_action_set_sensitive(w, FALSE);
3201
GtkAction* h = GTK_ACTION( g_object_get_data( tbl, "height_action" ) );
3202
gtk_action_set_sensitive(h, FALSE);
3204
} else if (n_selected == 1) {
3205
g_object_set( G_OBJECT(act), "label", _("<b>Change:</b>"), NULL );
3206
g_object_set_data( tbl, "single", GINT_TO_POINTER(TRUE) );
3208
GtkAction* w = GTK_ACTION( g_object_get_data( tbl, "width_action" ) );
3209
gtk_action_set_sensitive(w, TRUE);
3210
GtkAction* h = GTK_ACTION( g_object_get_data( tbl, "height_action" ) );
3211
gtk_action_set_sensitive(h, TRUE);
3214
g_object_set_data( tbl, "repr", repr );
3215
g_object_set_data( tbl, "item", item );
3216
Inkscape::GC::anchor(repr);
3217
sp_repr_add_listener(repr, &rect_tb_repr_events, tbl);
3218
sp_repr_synthesize_events(repr, &rect_tb_repr_events, tbl);
3221
// FIXME: implement averaging of all parameters for multiple selected
3222
//gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
3223
g_object_set( G_OBJECT(act), "label", _("<b>Change:</b>"), NULL );
3224
sp_rtb_sensitivize( tbl );
3229
static void sp_rect_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
3231
EgeAdjustmentAction* eact = 0;
3232
Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1);
3235
EgeOutputAction* act = ege_output_action_new( "RectStateAction", _("<b>New:</b>"), "", 0 );
3236
ege_output_action_set_use_markup( act, TRUE );
3237
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
3238
g_object_set_data( holder, "mode_action", act );
3241
// rx/ry units menu: create
3242
UnitTracker* tracker = new UnitTracker( SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE );
3243
//tracker->addUnit( SP_UNIT_PERCENT, 0 );
3244
// fixme: add % meaning per cent of the width/height
3245
tracker->setActiveUnit( sp_desktop_namedview(desktop)->doc_units );
3246
g_object_set_data( holder, "tracker", tracker );
3250
gchar const* labels[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3251
gdouble values[] = {1, 2, 3, 5, 10, 20, 50, 100, 200, 500};
3252
eact = create_adjustment_action( "RectWidthAction",
3253
_("Width"), _("W:"), _("Width of rectangle"),
3254
"/tools/shapes/rect/width", 0,
3255
GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, TRUE, "altx-rect",
3256
0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
3257
labels, values, G_N_ELEMENTS(labels),
3258
sp_rtb_width_value_changed );
3259
tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) );
3260
g_object_set_data( holder, "width_action", eact );
3261
gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
3262
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
3267
gchar const* labels[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3268
gdouble values[] = {1, 2, 3, 5, 10, 20, 50, 100, 200, 500};
3269
eact = create_adjustment_action( "RectHeightAction",
3270
_("Height"), _("H:"), _("Height of rectangle"),
3271
"/tools/shapes/rect/height", 0,
3272
GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, FALSE, NULL,
3273
0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
3274
labels, values, G_N_ELEMENTS(labels),
3275
sp_rtb_height_value_changed );
3276
tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) );
3277
g_object_set_data( holder, "height_action", eact );
3278
gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
3279
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
3284
gchar const* labels[] = {_("not rounded"), 0, 0, 0, 0, 0, 0, 0, 0};
3285
gdouble values[] = {0.5, 1, 2, 3, 5, 10, 20, 50, 100};
3286
eact = create_adjustment_action( "RadiusXAction",
3287
_("Horizontal radius"), _("Rx:"), _("Horizontal radius of rounded corners"),
3288
"/tools/shapes/rect/rx", 0,
3289
GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, FALSE, NULL,
3290
0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
3291
labels, values, G_N_ELEMENTS(labels),
3292
sp_rtb_rx_value_changed);
3293
tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) );
3294
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
3299
gchar const* labels[] = {_("not rounded"), 0, 0, 0, 0, 0, 0, 0, 0};
3300
gdouble values[] = {0.5, 1, 2, 3, 5, 10, 20, 50, 100};
3301
eact = create_adjustment_action( "RadiusYAction",
3302
_("Vertical radius"), _("Ry:"), _("Vertical radius of rounded corners"),
3303
"/tools/shapes/rect/ry", 0,
3304
GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, FALSE, NULL,
3305
0, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
3306
labels, values, G_N_ELEMENTS(labels),
3307
sp_rtb_ry_value_changed);
3308
tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) );
3309
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
3312
// add the units menu
3314
GtkAction* act = tracker->createAction( "RectUnitsAction", _("Units"), ("") );
3315
gtk_action_group_add_action( mainActions, act );
3320
InkAction* inky = ink_action_new( "RectResetAction",
3322
_("Make corners sharp"),
3323
INKSCAPE_ICON_RECTANGLE_MAKE_CORNERS_SHARP,
3325
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_rtb_defaults), holder );
3326
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
3327
gtk_action_set_sensitive( GTK_ACTION(inky), TRUE );
3328
g_object_set_data( holder, "not_rounded", inky );
3331
g_object_set_data( holder, "single", GINT_TO_POINTER(TRUE) );
3332
sp_rtb_sensitivize( holder );
3334
sigc::connection *connection = new sigc::connection(
3335
sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_rect_toolbox_selection_changed), (GObject *)holder))
3337
g_signal_connect( holder, "destroy", G_CALLBACK(delete_connection), connection );
3338
g_signal_connect( holder, "destroy", G_CALLBACK(purge_repr_listener), holder );
3341
//########################
3343
//########################
3345
// normalize angle so that it lies in the interval [0,360]
3346
static double box3d_normalize_angle (double a) {
3347
double angle = a + ((int) (a/360.0))*360;
3354
static void box3d_set_button_and_adjustment(Persp3D *persp,
3358
GtkToggleAction *tact)
3360
// TODO: Take all selected perspectives into account but don't touch the state button if not all of them
3361
// have the same state (otherwise a call to box3d_vp_z_state_changed() is triggered and the states
3363
bool is_infinite = !persp3d_VP_is_finite(persp->perspective_impl, axis);
3366
gtk_toggle_action_set_active(tact, TRUE);
3367
gtk_action_set_sensitive(act, TRUE);
3369
double angle = persp3d_get_infinite_angle(persp, axis);
3370
if (angle != NR_HUGE) { // FIXME: We should catch this error earlier (don't show the spinbutton at all)
3371
gtk_adjustment_set_value(adj, box3d_normalize_angle(angle));
3374
gtk_toggle_action_set_active(tact, FALSE);
3375
gtk_action_set_sensitive(act, FALSE);
3379
static void box3d_resync_toolbar(Inkscape::XML::Node *persp_repr, GObject *data)
3382
g_print ("No perspective given to box3d_resync_toolbar().\n");
3386
GtkWidget *tbl = GTK_WIDGET(data);
3387
GtkAdjustment *adj = 0;
3389
GtkToggleAction *tact = 0;
3390
Persp3D *persp = persp3d_get_from_repr(persp_repr);
3392
// Hmm, is it an error if this happens?
3396
adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "box3d_angle_x"));
3397
act = GTK_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_angle_x_action"));
3398
tact = &INK_TOGGLE_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_vp_x_state_action"))->action;
3400
box3d_set_button_and_adjustment(persp, Proj::X, adj, act, tact);
3403
adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "box3d_angle_y"));
3404
act = GTK_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_angle_y_action"));
3405
tact = &INK_TOGGLE_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_vp_y_state_action"))->action;
3407
box3d_set_button_and_adjustment(persp, Proj::Y, adj, act, tact);
3410
adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "box3d_angle_z"));
3411
act = GTK_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_angle_z_action"));
3412
tact = &INK_TOGGLE_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_vp_z_state_action"))->action;
3414
box3d_set_button_and_adjustment(persp, Proj::Z, adj, act, tact);
3418
static void box3d_persp_tb_event_attr_changed(Inkscape::XML::Node *repr,
3419
gchar const * /*name*/,
3420
gchar const * /*old_value*/,
3421
gchar const * /*new_value*/,
3422
bool /*is_interactive*/,
3425
GtkWidget *tbl = GTK_WIDGET(data);
3427
// quit if run by the attr_changed or selection changed listener
3428
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
3432
// set freeze so that it can be caught in box3d_angle_z_value_changed() (to avoid calling
3433
// sp_document_maybe_done() when the document is undo insensitive)
3434
g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
3436
// TODO: Only update the appropriate part of the toolbar
3437
// if (!strcmp(name, "inkscape:vp_z")) {
3438
box3d_resync_toolbar(repr, G_OBJECT(tbl));
3441
Persp3D *persp = persp3d_get_from_repr(repr);
3442
persp3d_update_box_reprs(persp);
3444
g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
3447
static Inkscape::XML::NodeEventVector box3d_persp_tb_repr_events =
3449
NULL, /* child_added */
3450
NULL, /* child_removed */
3451
box3d_persp_tb_event_attr_changed,
3452
NULL, /* content_changed */
3453
NULL /* order_changed */
3457
* \param selection Should not be NULL.
3459
// FIXME: This should rather be put into persp3d-reference.cpp or something similar so that it reacts upon each
3460
// Change of the perspective, and not of the current selection (but how to refer to the toolbar then?)
3461
static void box3d_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
3463
// Here the following should be done: If all selected boxes have finite VPs in a certain direction,
3464
// disable the angle entry fields for this direction (otherwise entering a value in them should only
3465
// update the perspectives with infinite VPs and leave the other ones untouched).
3467
Inkscape::XML::Node *persp_repr = NULL;
3468
purge_repr_listener(tbl, tbl);
3470
SPItem *item = selection->singleItem();
3471
if (item && SP_IS_BOX3D(item)) {
3472
// FIXME: Also deal with multiple selected boxes
3473
SPBox3D *box = SP_BOX3D(item);
3474
Persp3D *persp = box3d_get_perspective(box);
3475
persp_repr = SP_OBJECT_REPR(persp);
3477
g_object_set_data(tbl, "repr", persp_repr);
3478
Inkscape::GC::anchor(persp_repr);
3479
sp_repr_add_listener(persp_repr, &box3d_persp_tb_repr_events, tbl);
3480
sp_repr_synthesize_events(persp_repr, &box3d_persp_tb_repr_events, tbl);
3483
inkscape_active_document()->setCurrentPersp3D(persp3d_get_from_repr(persp_repr));
3484
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
3485
prefs->setString("/tools/shapes/3dbox/persp", persp_repr->attribute("id"));
3487
g_object_set_data(tbl, "freeze", GINT_TO_POINTER(TRUE));
3488
box3d_resync_toolbar(persp_repr, tbl);
3489
g_object_set_data(tbl, "freeze", GINT_TO_POINTER(FALSE));
3493
static void box3d_angle_value_changed(GtkAdjustment *adj, GObject *dataKludge, Proj::Axis axis)
3495
SPDesktop *desktop = (SPDesktop *) g_object_get_data( dataKludge, "desktop" );
3496
SPDocument *document = sp_desktop_document(desktop);
3498
// quit if run by the attr_changed or selection changed listener
3499
if (g_object_get_data( dataKludge, "freeze" )) {
3503
// in turn, prevent listener from responding
3504
g_object_set_data(dataKludge, "freeze", GINT_TO_POINTER(TRUE));
3506
std::list<Persp3D *> sel_persps = sp_desktop_selection(desktop)->perspList();
3507
if (sel_persps.empty()) {
3508
// this can happen when the document is created; we silently ignore it
3511
Persp3D *persp = sel_persps.front();
3513
persp->perspective_impl->tmat.set_infinite_direction (axis, adj->value);
3514
SP_OBJECT(persp)->updateRepr();
3516
// TODO: use the correct axis here, too
3517
sp_document_maybe_done(document, "perspangle", SP_VERB_CONTEXT_3DBOX, _("3D Box: Change perspective (angle of infinite axis)"));
3519
g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(FALSE) );
3523
static void box3d_angle_x_value_changed(GtkAdjustment *adj, GObject *dataKludge)
3525
box3d_angle_value_changed(adj, dataKludge, Proj::X);
3528
static void box3d_angle_y_value_changed(GtkAdjustment *adj, GObject *dataKludge)
3530
box3d_angle_value_changed(adj, dataKludge, Proj::Y);
3533
static void box3d_angle_z_value_changed(GtkAdjustment *adj, GObject *dataKludge)
3535
box3d_angle_value_changed(adj, dataKludge, Proj::Z);
3539
static void box3d_vp_state_changed( GtkToggleAction *act, GtkAction * /*box3d_angle*/, Proj::Axis axis )
3541
// TODO: Take all selected perspectives into account
3542
std::list<Persp3D *> sel_persps = sp_desktop_selection(inkscape_active_desktop())->perspList();
3543
if (sel_persps.empty()) {
3544
// this can happen when the document is created; we silently ignore it
3547
Persp3D *persp = sel_persps.front();
3549
bool set_infinite = gtk_toggle_action_get_active(act);
3550
persp3d_set_VP_state (persp, axis, set_infinite ? Proj::VP_INFINITE : Proj::VP_FINITE);
3553
static void box3d_vp_x_state_changed( GtkToggleAction *act, GtkAction *box3d_angle )
3555
box3d_vp_state_changed(act, box3d_angle, Proj::X);
3558
static void box3d_vp_y_state_changed( GtkToggleAction *act, GtkAction *box3d_angle )
3560
box3d_vp_state_changed(act, box3d_angle, Proj::Y);
3563
static void box3d_vp_z_state_changed( GtkToggleAction *act, GtkAction *box3d_angle )
3565
box3d_vp_state_changed(act, box3d_angle, Proj::Z);
3568
static void box3d_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
3570
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
3571
EgeAdjustmentAction* eact = 0;
3572
SPDocument *document = sp_desktop_document (desktop);
3573
Persp3DImpl *persp_impl = document->getCurrentPersp3DImpl();
3575
EgeAdjustmentAction* box3d_angle_x = 0;
3576
EgeAdjustmentAction* box3d_angle_y = 0;
3577
EgeAdjustmentAction* box3d_angle_z = 0;
3581
gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0 };
3582
gdouble values[] = {-90, -60, -30, 0, 30, 60, 90};
3583
eact = create_adjustment_action( "3DBoxAngleXAction",
3584
_("Angle in X direction"), _("Angle X:"),
3585
// Translators: PL is short for 'perspective line'
3586
_("Angle of PLs in X direction"),
3587
"/tools/shapes/3dbox/box3d_angle_x", 30,
3588
GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "altx-box3d",
3589
-360.0, 360.0, 1.0, 10.0,
3590
labels, values, G_N_ELEMENTS(labels),
3591
box3d_angle_x_value_changed );
3592
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
3593
g_object_set_data( holder, "box3d_angle_x_action", eact );
3594
box3d_angle_x = eact;
3597
if (!persp_impl || !persp3d_VP_is_finite(persp_impl, Proj::X)) {
3598
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
3600
gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
3606
InkToggleAction* act = ink_toggle_action_new( "3DBoxVPXStateAction",
3607
// Translators: VP is short for 'vanishing point'
3608
_("State of VP in X direction"),
3609
_("Toggle VP in X direction between 'finite' and 'infinite' (=parallel)"),
3610
INKSCAPE_ICON_PERSPECTIVE_PARALLEL,
3611
Inkscape::ICON_SIZE_DECORATION );
3612
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
3613
g_object_set_data( holder, "box3d_vp_x_state_action", act );
3614
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(box3d_vp_x_state_changed), box3d_angle_x );
3615
gtk_action_set_sensitive( GTK_ACTION(box3d_angle_x), !prefs->getBool("/tools/shapes/3dbox/vp_x_state", true) );
3616
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/shapes/3dbox/vp_x_state", true) );
3621
gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0 };
3622
gdouble values[] = {-90, -60, -30, 0, 30, 60, 90};
3623
eact = create_adjustment_action( "3DBoxAngleYAction",
3624
_("Angle in Y direction"), _("Angle Y:"),
3625
// Translators: PL is short for 'perspective line'
3626
_("Angle of PLs in Y direction"),
3627
"/tools/shapes/3dbox/box3d_angle_y", 30,
3628
GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
3629
-360.0, 360.0, 1.0, 10.0,
3630
labels, values, G_N_ELEMENTS(labels),
3631
box3d_angle_y_value_changed );
3632
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
3633
g_object_set_data( holder, "box3d_angle_y_action", eact );
3634
box3d_angle_y = eact;
3637
if (!persp_impl || !persp3d_VP_is_finite(persp_impl, Proj::Y)) {
3638
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
3640
gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
3645
InkToggleAction* act = ink_toggle_action_new( "3DBoxVPYStateAction",
3646
// Translators: VP is short for 'vanishing point'
3647
_("State of VP in Y direction"),
3648
_("Toggle VP in Y direction between 'finite' and 'infinite' (=parallel)"),
3649
INKSCAPE_ICON_PERSPECTIVE_PARALLEL,
3650
Inkscape::ICON_SIZE_DECORATION );
3651
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
3652
g_object_set_data( holder, "box3d_vp_y_state_action", act );
3653
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(box3d_vp_y_state_changed), box3d_angle_y );
3654
gtk_action_set_sensitive( GTK_ACTION(box3d_angle_y), !prefs->getBool("/tools/shapes/3dbox/vp_y_state", true) );
3655
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/shapes/3dbox/vp_y_state", true) );
3660
gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0 };
3661
gdouble values[] = {-90, -60, -30, 0, 30, 60, 90};
3662
eact = create_adjustment_action( "3DBoxAngleZAction",
3663
_("Angle in Z direction"), _("Angle Z:"),
3664
// Translators: PL is short for 'perspective line'
3665
_("Angle of PLs in Z direction"),
3666
"/tools/shapes/3dbox/box3d_angle_z", 30,
3667
GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
3668
-360.0, 360.0, 1.0, 10.0,
3669
labels, values, G_N_ELEMENTS(labels),
3670
box3d_angle_z_value_changed );
3671
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
3672
g_object_set_data( holder, "box3d_angle_z_action", eact );
3673
box3d_angle_z = eact;
3676
if (!persp_impl || !persp3d_VP_is_finite(persp_impl, Proj::Z)) {
3677
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
3679
gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
3684
InkToggleAction* act = ink_toggle_action_new( "3DBoxVPZStateAction",
3685
// Translators: VP is short for 'vanishing point'
3686
_("State of VP in Z direction"),
3687
_("Toggle VP in Z direction between 'finite' and 'infinite' (=parallel)"),
3688
INKSCAPE_ICON_PERSPECTIVE_PARALLEL,
3689
Inkscape::ICON_SIZE_DECORATION );
3690
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
3691
g_object_set_data( holder, "box3d_vp_z_state_action", act );
3692
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(box3d_vp_z_state_changed), box3d_angle_z );
3693
gtk_action_set_sensitive( GTK_ACTION(box3d_angle_z), !prefs->getBool("/tools/shapes/3dbox/vp_z_state", true) );
3694
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/shapes/3dbox/vp_z_state", true) );
3697
sigc::connection *connection = new sigc::connection(
3698
sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(box3d_toolbox_selection_changed), (GObject *)holder))
3700
g_signal_connect(holder, "destroy", G_CALLBACK(delete_connection), connection);
3701
g_signal_connect(holder, "destroy", G_CALLBACK(purge_repr_listener), holder);
3704
//########################
3706
//########################
3708
static void sp_spl_tb_value_changed(GtkAdjustment *adj, GObject *tbl, Glib::ustring const &value_name)
3710
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
3712
if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
3713
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
3714
prefs->setDouble("/tools/shapes/spiral/" + value_name, adj->value);
3717
// quit if run by the attr_changed listener
3718
if (g_object_get_data( tbl, "freeze" )) {
3722
// in turn, prevent listener from responding
3723
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
3725
gchar* namespaced_name = g_strconcat("sodipodi:", value_name.data(), NULL);
3727
bool modmade = false;
3728
for (GSList const *items = sp_desktop_selection(desktop)->itemList();
3730
items = items->next)
3732
if (SP_IS_SPIRAL((SPItem *) items->data)) {
3733
Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
3734
sp_repr_set_svg_double( repr, namespaced_name, adj->value );
3735
SP_OBJECT((SPItem *) items->data)->updateRepr();
3740
g_free(namespaced_name);
3743
sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_SPIRAL,
3744
_("Change spiral"));
3747
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
3750
static void sp_spl_tb_revolution_value_changed(GtkAdjustment *adj, GObject *tbl)
3752
sp_spl_tb_value_changed(adj, tbl, "revolution");
3755
static void sp_spl_tb_expansion_value_changed(GtkAdjustment *adj, GObject *tbl)
3757
sp_spl_tb_value_changed(adj, tbl, "expansion");
3760
static void sp_spl_tb_t0_value_changed(GtkAdjustment *adj, GObject *tbl)
3762
sp_spl_tb_value_changed(adj, tbl, "t0");
3765
static void sp_spl_tb_defaults(GtkWidget * /*widget*/, GtkObject *obj)
3767
GtkWidget *tbl = GTK_WIDGET(obj);
3771
// fixme: make settable
3776
adj = (GtkAdjustment*)gtk_object_get_data(obj, "revolution");
3777
gtk_adjustment_set_value(adj, rev);
3778
gtk_adjustment_value_changed(adj);
3780
adj = (GtkAdjustment*)gtk_object_get_data(obj, "expansion");
3781
gtk_adjustment_set_value(adj, exp);
3782
gtk_adjustment_value_changed(adj);
3784
adj = (GtkAdjustment*)gtk_object_get_data(obj, "t0");
3785
gtk_adjustment_set_value(adj, t0);
3786
gtk_adjustment_value_changed(adj);
3788
spinbutton_defocus(GTK_OBJECT(tbl));
3792
static void spiral_tb_event_attr_changed(Inkscape::XML::Node *repr,
3793
gchar const * /*name*/,
3794
gchar const * /*old_value*/,
3795
gchar const * /*new_value*/,
3796
bool /*is_interactive*/,
3799
GtkWidget *tbl = GTK_WIDGET(data);
3801
// quit if run by the _changed callbacks
3802
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
3806
// in turn, prevent callbacks from responding
3807
g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
3810
adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "revolution");
3811
gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:revolution", 3.0)));
3813
adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "expansion");
3814
gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:expansion", 1.0)));
3816
adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "t0");
3817
gtk_adjustment_set_value(adj, (sp_repr_get_double_attribute(repr, "sodipodi:t0", 0.0)));
3819
g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
3823
static Inkscape::XML::NodeEventVector spiral_tb_repr_events = {
3824
NULL, /* child_added */
3825
NULL, /* child_removed */
3826
spiral_tb_event_attr_changed,
3827
NULL, /* content_changed */
3828
NULL /* order_changed */
3831
static void sp_spiral_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
3834
Inkscape::XML::Node *repr = NULL;
3836
purge_repr_listener( tbl, tbl );
3838
for (GSList const *items = selection->itemList();
3840
items = items->next)
3842
if (SP_IS_SPIRAL((SPItem *) items->data)) {
3844
repr = SP_OBJECT_REPR((SPItem *) items->data);
3848
EgeOutputAction* act = EGE_OUTPUT_ACTION( g_object_get_data( tbl, "mode_action" ) );
3850
if (n_selected == 0) {
3851
g_object_set( G_OBJECT(act), "label", _("<b>New:</b>"), NULL );
3852
} else if (n_selected == 1) {
3853
g_object_set( G_OBJECT(act), "label", _("<b>Change:</b>"), NULL );
3856
g_object_set_data( tbl, "repr", repr );
3857
Inkscape::GC::anchor(repr);
3858
sp_repr_add_listener(repr, &spiral_tb_repr_events, tbl);
3859
sp_repr_synthesize_events(repr, &spiral_tb_repr_events, tbl);
3862
// FIXME: implement averaging of all parameters for multiple selected
3863
//gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
3864
g_object_set( G_OBJECT(act), "label", _("<b>Change:</b>"), NULL );
3869
static void sp_spiral_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
3871
EgeAdjustmentAction* eact = 0;
3872
Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1);
3875
EgeOutputAction* act = ege_output_action_new( "SpiralStateAction", _("<b>New:</b>"), "", 0 );
3876
ege_output_action_set_use_markup( act, TRUE );
3877
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
3878
g_object_set_data( holder, "mode_action", act );
3883
gchar const* labels[] = {_("just a curve"), 0, _("one full revolution"), 0, 0, 0, 0, 0, 0};
3884
gdouble values[] = {0.01, 0.5, 1, 2, 3, 5, 10, 20, 50, 100};
3885
eact = create_adjustment_action( "SpiralRevolutionAction",
3886
_("Number of turns"), _("Turns:"), _("Number of revolutions"),
3887
"/tools/shapes/spiral/revolution", 3.0,
3888
GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "altx-spiral",
3889
0.01, 1024.0, 0.1, 1.0,
3890
labels, values, G_N_ELEMENTS(labels),
3891
sp_spl_tb_revolution_value_changed, 1, 2);
3892
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
3897
gchar const* labels[] = {_("circle"), _("edge is much denser"), _("edge is denser"), _("even"), _("center is denser"), _("center is much denser"), 0};
3898
gdouble values[] = {0, 0.1, 0.5, 1, 1.5, 5, 20};
3899
eact = create_adjustment_action( "SpiralExpansionAction",
3900
_("Divergence"), _("Divergence:"), _("How much denser/sparser are outer revolutions; 1 = uniform"),
3901
"/tools/shapes/spiral/expansion", 1.0,
3902
GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
3903
0.0, 1000.0, 0.01, 1.0,
3904
labels, values, G_N_ELEMENTS(labels),
3905
sp_spl_tb_expansion_value_changed);
3906
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
3911
gchar const* labels[] = {_("starts from center"), _("starts mid-way"), _("starts near edge")};
3912
gdouble values[] = {0, 0.5, 0.9};
3913
eact = create_adjustment_action( "SpiralT0Action",
3914
_("Inner radius"), _("Inner radius:"), _("Radius of the innermost revolution (relative to the spiral size)"),
3915
"/tools/shapes/spiral/t0", 0.0,
3916
GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
3917
0.0, 0.999, 0.01, 1.0,
3918
labels, values, G_N_ELEMENTS(labels),
3919
sp_spl_tb_t0_value_changed);
3920
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
3925
InkAction* inky = ink_action_new( "SpiralResetAction",
3927
_("Reset shape parameters to defaults (use Inkscape Preferences > Tools to change defaults)"),
3930
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_spl_tb_defaults), holder );
3931
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
3935
sigc::connection *connection = new sigc::connection(
3936
sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_spiral_toolbox_selection_changed), (GObject *)holder))
3938
g_signal_connect( holder, "destroy", G_CALLBACK(delete_connection), connection );
3939
g_signal_connect( holder, "destroy", G_CALLBACK(purge_repr_listener), holder );
3942
//########################
3944
//########################
3946
/* This is used in generic functions below to share large portions of code between pen and pencil tool */
3947
static Glib::ustring const freehand_tool_name(GObject *dataKludge)
3949
SPDesktop *desktop = (SPDesktop *) g_object_get_data(dataKludge, "desktop");
3950
return ( tools_isactive(desktop, TOOLS_FREEHAND_PEN)
3951
? "/tools/freehand/pen"
3952
: "/tools/freehand/pencil" );
3955
static void freehand_mode_changed(EgeSelectOneAction* act, GObject* tbl)
3957
gint mode = ege_select_one_action_get_active(act);
3959
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
3960
prefs->setInt(freehand_tool_name(tbl) + "/freehand-mode", mode);
3962
SPDesktop *desktop = (SPDesktop *) g_object_get_data(tbl, "desktop");
3964
// in pen tool we have more options than in pencil tool; if one of them was chosen, we do any
3965
// preparatory work here
3966
if (SP_IS_PEN_CONTEXT(desktop->event_context)) {
3967
SPPenContext *pc = SP_PEN_CONTEXT(desktop->event_context);
3968
sp_pen_context_set_polyline_mode(pc);
3972
static void sp_add_freehand_mode_toggle(GtkActionGroup* mainActions, GObject* holder, bool tool_is_pencil)
3974
/* Freehand mode toggle buttons */
3976
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
3977
guint freehandMode = prefs->getInt(( tool_is_pencil ? "/tools/freehand/pencil/freehand-mode" : "/tools/freehand/pen/freehand-mode" ), 0);
3978
Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1);
3981
GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING );
3984
gtk_list_store_append( model, &iter );
3985
gtk_list_store_set( model, &iter,
3987
1, _("Create regular Bezier path"),
3988
2, INKSCAPE_ICON_PATH_MODE_BEZIER,
3991
gtk_list_store_append( model, &iter );
3992
gtk_list_store_set( model, &iter,
3994
1, _("Create Spiro path"),
3995
2, INKSCAPE_ICON_PATH_MODE_SPIRO,
3998
if (!tool_is_pencil) {
3999
gtk_list_store_append( model, &iter );
4000
gtk_list_store_set( model, &iter,
4002
1, _("Create a sequence of straight line segments"),
4003
2, INKSCAPE_ICON_PATH_MODE_POLYLINE,
4006
gtk_list_store_append( model, &iter );
4007
gtk_list_store_set( model, &iter,
4009
1, _("Create a sequence of paraxial line segments"),
4010
2, INKSCAPE_ICON_PATH_MODE_POLYLINE_PARAXIAL,
4014
EgeSelectOneAction* act = ege_select_one_action_new(tool_is_pencil ?
4015
"FreehandModeActionPencil" :
4016
"FreehandModeActionPen",
4017
(_("Mode:")), (_("Mode of new lines drawn by this tool")), NULL, GTK_TREE_MODEL(model) );
4018
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
4020
ege_select_one_action_set_appearance( act, "full" );
4021
ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE );
4022
g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL );
4023
ege_select_one_action_set_icon_column( act, 2 );
4024
ege_select_one_action_set_icon_size( act, secondarySize );
4025
ege_select_one_action_set_tooltip_column( act, 1 );
4027
ege_select_one_action_set_active( act, freehandMode);
4028
g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(freehand_mode_changed), holder);
4033
static void freehand_change_shape(EgeSelectOneAction* act, GObject *dataKludge) {
4034
gint shape = ege_select_one_action_get_active( act );
4035
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4036
prefs->setInt(freehand_tool_name(dataKludge) + "/shape", shape);
4040
* \brief Generate the list of freehand advanced shape option entries.
4042
static GList * freehand_shape_dropdown_items_list() {
4043
GList *glist = NULL;
4045
glist = g_list_append (glist, _("None"));
4046
glist = g_list_append (glist, _("Triangle in"));
4047
glist = g_list_append (glist, _("Triangle out"));
4048
glist = g_list_append (glist, _("Ellipse"));
4049
glist = g_list_append (glist, _("From clipboard"));
4054
static void freehand_add_advanced_shape_options(GtkActionGroup* mainActions, GObject* holder, bool tool_is_pencil)
4056
/*advanced shape options */
4058
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4059
GtkListStore* model = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_INT );
4063
for ( items = freehand_shape_dropdown_items_list(); items ; items = g_list_next(items) )
4066
gtk_list_store_append( model, &iter );
4067
gtk_list_store_set( model, &iter, 0, reinterpret_cast<gchar*>(items->data), 1, count, -1 );
4070
g_list_free( items );
4072
EgeSelectOneAction* act1 = ege_select_one_action_new(
4073
tool_is_pencil ? "SetPencilShapeAction" : "SetPenShapeAction",
4074
_("Shape:"), (_("Shape of new paths drawn by this tool")), NULL, GTK_TREE_MODEL(model));
4075
g_object_set( act1, "short_label", _("Shape:"), NULL );
4076
ege_select_one_action_set_appearance( act1, "compact" );
4077
ege_select_one_action_set_active( act1, prefs->getInt(( tool_is_pencil ? "/tools/freehand/pencil/shape" : "/tools/freehand/pen/shape" ), 0) );
4078
g_signal_connect( G_OBJECT(act1), "changed", G_CALLBACK(freehand_change_shape), holder );
4079
gtk_action_group_add_action( mainActions, GTK_ACTION(act1) );
4080
g_object_set_data( holder, "shape_action", act1 );
4084
static void sp_pen_toolbox_prep(SPDesktop * /*desktop*/, GtkActionGroup* mainActions, GObject* holder)
4086
sp_add_freehand_mode_toggle(mainActions, holder, false);
4087
freehand_add_advanced_shape_options(mainActions, holder, false);
4091
static void sp_pencil_tb_defaults(GtkWidget * /*widget*/, GtkObject *obj)
4093
GtkWidget *tbl = GTK_WIDGET(obj);
4097
// fixme: make settable
4098
gdouble tolerance = 4;
4100
adj = (GtkAdjustment*)gtk_object_get_data(obj, "tolerance");
4101
gtk_adjustment_set_value(adj, tolerance);
4102
gtk_adjustment_value_changed(adj);
4104
spinbutton_defocus(GTK_OBJECT(tbl));
4107
static void sp_pencil_tb_tolerance_value_changed(GtkAdjustment *adj, GObject *tbl)
4109
// quit if run by the attr_changed listener
4110
if (g_object_get_data( tbl, "freeze" )) {
4113
// in turn, prevent listener from responding
4114
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4115
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
4116
prefs->setDouble("/tools/freehand/pencil/tolerance", adj->value);
4117
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
4121
class PencilToleranceObserver : public Inkscape::Preferences::Observer {
4123
PencilToleranceObserver(Glib::ustring const &path, GObject *x) : Observer(path), _obj(x)
4125
g_object_set_data(_obj, "prefobserver", this);
4127
virtual ~PencilToleranceObserver() {
4128
if (g_object_get_data(_obj, "prefobserver") == this) {
4129
g_object_set_data(_obj, "prefobserver", NULL);
4132
virtual void notify(Inkscape::Preferences::Entry const &val) {
4133
GObject* tbl = _obj;
4134
if (g_object_get_data( tbl, "freeze" )) {
4137
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
4139
GtkAdjustment * adj = (GtkAdjustment*)g_object_get_data(tbl, "tolerance");
4141
double v = val.getDouble(adj->value);
4142
gtk_adjustment_set_value(adj, v);
4143
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
4150
static void sp_pencil_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
4152
sp_add_freehand_mode_toggle(mainActions, holder, true);
4154
EgeAdjustmentAction* eact = 0;
4158
gchar const* labels[] = {_("(many nodes, rough)"), _("(default)"), 0, 0, 0, 0, _("(few nodes, smooth)")};
4159
gdouble values[] = {1, 10, 20, 30, 50, 75, 100};
4160
eact = create_adjustment_action( "PencilToleranceAction",
4161
_("Smoothing:"), _("Smoothing: "),
4162
_("How much smoothing (simplifying) is applied to the line"),
4163
"/tools/freehand/pencil/tolerance",
4165
GTK_WIDGET(desktop->canvas), NULL,
4166
holder, TRUE, "altx-pencil",
4168
labels, values, G_N_ELEMENTS(labels),
4169
sp_pencil_tb_tolerance_value_changed,
4171
ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
4172
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
4175
/* advanced shape options */
4176
freehand_add_advanced_shape_options(mainActions, holder, true);
4180
InkAction* inky = ink_action_new( "PencilResetAction",
4182
_("Reset pencil parameters to defaults (use Inkscape Preferences > Tools to change defaults)"),
4184
Inkscape::ICON_SIZE_SMALL_TOOLBAR );
4185
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_pencil_tb_defaults), holder );
4186
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
4189
g_signal_connect( holder, "destroy", G_CALLBACK(purge_repr_listener), holder );
4194
//########################
4196
//########################
4198
static void sp_tweak_width_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
4200
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4201
prefs->setDouble( "/tools/tweak/width", adj->value * 0.01 );
4204
static void sp_tweak_force_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
4206
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4207
prefs->setDouble( "/tools/tweak/force", adj->value * 0.01 );
4210
static void sp_tweak_pressure_state_changed( GtkToggleAction *act, gpointer /*data*/ )
4212
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4213
prefs->setBool("/tools/tweak/usepressure", gtk_toggle_action_get_active(act));
4216
static void sp_tweak_mode_changed( EgeSelectOneAction *act, GObject *tbl )
4218
int mode = ege_select_one_action_get_active( act );
4219
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4220
prefs->setInt("/tools/tweak/mode", mode);
4222
static gchar const* names[] = {"tweak_doh", "tweak_dos", "tweak_dol", "tweak_doo", "tweak_channels_label"};
4223
bool flag = ((mode == TWEAK_MODE_COLORPAINT) || (mode == TWEAK_MODE_COLORJITTER));
4224
for (size_t i = 0; i < G_N_ELEMENTS(names); ++i) {
4225
GtkAction *act = GTK_ACTION(g_object_get_data( tbl, names[i] ));
4227
gtk_action_set_sensitive(act, flag);
4230
GtkAction *fid = GTK_ACTION(g_object_get_data( tbl, "tweak_fidelity"));
4232
gtk_action_set_sensitive(fid, !flag);
4236
static void sp_tweak_fidelity_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
4238
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4239
prefs->setDouble( "/tools/tweak/fidelity", adj->value * 0.01 );
4242
static void tweak_toggle_doh(GtkToggleAction *act, gpointer /*data*/) {
4243
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4244
prefs->setBool("/tools/tweak/doh", gtk_toggle_action_get_active(act));
4246
static void tweak_toggle_dos(GtkToggleAction *act, gpointer /*data*/) {
4247
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4248
prefs->setBool("/tools/tweak/dos", gtk_toggle_action_get_active(act));
4250
static void tweak_toggle_dol(GtkToggleAction *act, gpointer /*data*/) {
4251
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4252
prefs->setBool("/tools/tweak/dol", gtk_toggle_action_get_active(act));
4254
static void tweak_toggle_doo(GtkToggleAction *act, gpointer /*data*/) {
4255
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4256
prefs->setBool("/tools/tweak/doo", gtk_toggle_action_get_active(act));
4259
static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
4261
Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1);
4262
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4266
gchar const* labels[] = {_("(pinch tweak)"), 0, 0, 0, _("(default)"), 0, 0, 0, 0, _("(broad tweak)")};
4267
gdouble values[] = {1, 3, 5, 10, 15, 20, 30, 50, 75, 100};
4268
EgeAdjustmentAction *eact = create_adjustment_action( "TweakWidthAction",
4269
_("Width"), _("Width:"), _("The width of the tweak area (relative to the visible canvas area)"),
4270
"/tools/tweak/width", 15,
4271
GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "altx-tweak",
4273
labels, values, G_N_ELEMENTS(labels),
4274
sp_tweak_width_value_changed, 0.01, 0, 100 );
4275
ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
4276
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
4277
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
4283
gchar const* labels[] = {_("(minimum force)"), 0, 0, _("(default)"), 0, 0, 0, _("(maximum force)")};
4284
gdouble values[] = {1, 5, 10, 20, 30, 50, 70, 100};
4285
EgeAdjustmentAction *eact = create_adjustment_action( "TweakForceAction",
4286
_("Force"), _("Force:"), _("The force of the tweak action"),
4287
"/tools/tweak/force", 20,
4288
GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "tweak-force",
4290
labels, values, G_N_ELEMENTS(labels),
4291
sp_tweak_force_value_changed, 0.01, 0, 100 );
4292
ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
4293
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
4294
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
4299
GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING );
4302
gtk_list_store_append( model, &iter );
4303
gtk_list_store_set( model, &iter,
4305
1, _("Move objects in any direction"),
4306
2, INKSCAPE_ICON_OBJECT_TWEAK_PUSH,
4309
gtk_list_store_append( model, &iter );
4310
gtk_list_store_set( model, &iter,
4311
0, _("Move in/out mode"),
4312
1, _("Move objects towards cursor; with Shift from cursor"),
4313
2, INKSCAPE_ICON_OBJECT_TWEAK_ATTRACT,
4316
gtk_list_store_append( model, &iter );
4317
gtk_list_store_set( model, &iter,
4318
0, _("Move jitter mode"),
4319
1, _("Move objects in random directions"),
4320
2, INKSCAPE_ICON_OBJECT_TWEAK_RANDOMIZE,
4323
gtk_list_store_append( model, &iter );
4324
gtk_list_store_set( model, &iter,
4326
1, _("Shrink objects, with Shift enlarge"),
4327
2, INKSCAPE_ICON_OBJECT_TWEAK_SHRINK,
4330
gtk_list_store_append( model, &iter );
4331
gtk_list_store_set( model, &iter,
4332
0, _("Rotate mode"),
4333
1, _("Rotate objects, with Shift counterclockwise"),
4334
2, INKSCAPE_ICON_OBJECT_TWEAK_ROTATE,
4337
gtk_list_store_append( model, &iter );
4338
gtk_list_store_set( model, &iter,
4339
0, _("Duplicate/delete mode"),
4340
1, _("Duplicate objects, with Shift delete"),
4341
2, INKSCAPE_ICON_OBJECT_TWEAK_DUPLICATE,
4344
gtk_list_store_append( model, &iter );
4345
gtk_list_store_set( model, &iter,
4347
1, _("Push parts of paths in any direction"),
4348
2, INKSCAPE_ICON_PATH_TWEAK_PUSH,
4351
gtk_list_store_append( model, &iter );
4352
gtk_list_store_set( model, &iter,
4353
0, _("Shrink/grow mode"),
4354
1, _("Shrink (inset) parts of paths; with Shift grow (outset)"),
4355
2, INKSCAPE_ICON_PATH_TWEAK_SHRINK,
4358
gtk_list_store_append( model, &iter );
4359
gtk_list_store_set( model, &iter,
4360
0, _("Attract/repel mode"),
4361
1, _("Attract parts of paths towards cursor; with Shift from cursor"),
4362
2, INKSCAPE_ICON_PATH_TWEAK_ATTRACT,
4365
gtk_list_store_append( model, &iter );
4366
gtk_list_store_set( model, &iter,
4367
0, _("Roughen mode"),
4368
1, _("Roughen parts of paths"),
4369
2, INKSCAPE_ICON_PATH_TWEAK_ROUGHEN,
4372
gtk_list_store_append( model, &iter );
4373
gtk_list_store_set( model, &iter,
4374
0, _("Color paint mode"),
4375
1, _("Paint the tool's color upon selected objects"),
4376
2, INKSCAPE_ICON_OBJECT_TWEAK_PAINT,
4379
gtk_list_store_append( model, &iter );
4380
gtk_list_store_set( model, &iter,
4381
0, _("Color jitter mode"),
4382
1, _("Jitter the colors of selected objects"),
4383
2, INKSCAPE_ICON_OBJECT_TWEAK_JITTER_COLOR,
4386
gtk_list_store_append( model, &iter );
4387
gtk_list_store_set( model, &iter,
4389
1, _("Blur selected objects more; with Shift, blur less"),
4390
2, INKSCAPE_ICON_OBJECT_TWEAK_BLUR,
4394
EgeSelectOneAction* act = ege_select_one_action_new( "TweakModeAction", _("Mode"), (""), NULL, GTK_TREE_MODEL(model) );
4395
g_object_set( act, "short_label", _("Mode:"), NULL );
4396
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
4397
g_object_set_data( holder, "mode_action", act );
4399
ege_select_one_action_set_appearance( act, "full" );
4400
ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE );
4401
g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL );
4402
ege_select_one_action_set_icon_column( act, 2 );
4403
ege_select_one_action_set_icon_size( act, secondarySize );
4404
ege_select_one_action_set_tooltip_column( act, 1 );
4406
gint mode = prefs->getInt("/tools/tweak/mode", 0);
4407
ege_select_one_action_set_active( act, mode );
4408
g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_tweak_mode_changed), holder );
4410
g_object_set_data( G_OBJECT(holder), "tweak_tool_mode", act);
4413
guint mode = prefs->getInt("/tools/tweak/mode", 0);
4416
EgeOutputAction* act = ege_output_action_new( "TweakChannelsLabel", _("Channels:"), "", 0 );
4417
ege_output_action_set_use_markup( act, TRUE );
4418
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
4419
if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) {
4420
gtk_action_set_sensitive (GTK_ACTION(act), FALSE);
4422
g_object_set_data( holder, "tweak_channels_label", act);
4426
InkToggleAction* act = ink_toggle_action_new( "TweakDoH",
4428
_("In color mode, act on objects' hue"),
4430
Inkscape::ICON_SIZE_DECORATION );
4431
//TRANSLATORS: "H" here stands for hue
4432
g_object_set( act, "short_label", _("H"), NULL );
4433
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
4434
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(tweak_toggle_doh), desktop );
4435
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/tweak/doh", true) );
4436
if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) {
4437
gtk_action_set_sensitive (GTK_ACTION(act), FALSE);
4439
g_object_set_data( holder, "tweak_doh", act);
4442
InkToggleAction* act = ink_toggle_action_new( "TweakDoS",
4444
_("In color mode, act on objects' saturation"),
4446
Inkscape::ICON_SIZE_DECORATION );
4447
//TRANSLATORS: "S" here stands for Saturation
4448
g_object_set( act, "short_label", _("S"), NULL );
4449
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
4450
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(tweak_toggle_dos), desktop );
4451
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/tweak/dos", true) );
4452
if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) {
4453
gtk_action_set_sensitive (GTK_ACTION(act), FALSE);
4455
g_object_set_data( holder, "tweak_dos", act );
4458
InkToggleAction* act = ink_toggle_action_new( "TweakDoL",
4460
_("In color mode, act on objects' lightness"),
4462
Inkscape::ICON_SIZE_DECORATION );
4463
//TRANSLATORS: "L" here stands for Lightness
4464
g_object_set( act, "short_label", _("L"), NULL );
4465
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
4466
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(tweak_toggle_dol), desktop );
4467
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/tweak/dol", true) );
4468
if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) {
4469
gtk_action_set_sensitive (GTK_ACTION(act), FALSE);
4471
g_object_set_data( holder, "tweak_dol", act );
4474
InkToggleAction* act = ink_toggle_action_new( "TweakDoO",
4476
_("In color mode, act on objects' opacity"),
4478
Inkscape::ICON_SIZE_DECORATION );
4479
//TRANSLATORS: "O" here stands for Opacity
4480
g_object_set( act, "short_label", _("O"), NULL );
4481
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
4482
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(tweak_toggle_doo), desktop );
4483
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/tweak/doo", true) );
4484
if (mode != TWEAK_MODE_COLORPAINT && mode != TWEAK_MODE_COLORJITTER) {
4485
gtk_action_set_sensitive (GTK_ACTION(act), FALSE);
4487
g_object_set_data( holder, "tweak_doo", act );
4491
gchar const* labels[] = {_("(rough, simplified)"), 0, 0, _("(default)"), 0, 0, _("(fine, but many nodes)")};
4492
gdouble values[] = {10, 25, 35, 50, 60, 80, 100};
4493
EgeAdjustmentAction *eact = create_adjustment_action( "TweakFidelityAction",
4494
_("Fidelity"), _("Fidelity:"),
4495
_("Low fidelity simplifies paths; high fidelity preserves path features but may generate a lot of new nodes"),
4496
"/tools/tweak/fidelity", 50,
4497
GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "tweak-fidelity",
4499
labels, values, G_N_ELEMENTS(labels),
4500
sp_tweak_fidelity_value_changed, 0.01, 0, 100 );
4501
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
4502
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
4503
if (mode == TWEAK_MODE_COLORPAINT || mode == TWEAK_MODE_COLORJITTER) {
4504
gtk_action_set_sensitive (GTK_ACTION(eact), FALSE);
4506
g_object_set_data( holder, "tweak_fidelity", eact );
4510
/* Use Pressure button */
4512
InkToggleAction* act = ink_toggle_action_new( "TweakPressureAction",
4514
_("Use the pressure of the input device to alter the force of tweak action"),
4515
INKSCAPE_ICON_DRAW_USE_PRESSURE,
4516
Inkscape::ICON_SIZE_DECORATION );
4517
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
4518
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_tweak_pressure_state_changed), NULL);
4519
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/tweak/usepressure", true) );
4525
//########################
4527
//########################
4529
static void sp_spray_width_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
4531
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4532
prefs->setDouble( "/tools/spray/width", adj->value );
4535
static void sp_spray_mean_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
4537
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4538
prefs->setDouble( "/tools/spray/mean", adj->value );
4541
static void sp_spray_standard_deviation_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
4543
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4544
prefs->setDouble( "/tools/spray/standard_deviation", adj->value );
4547
static void sp_spray_pressure_state_changed( GtkToggleAction *act, gpointer /*data*/ )
4549
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4550
prefs->setBool("/tools/spray/usepressure", gtk_toggle_action_get_active(act));
4553
static void sp_spray_mode_changed( EgeSelectOneAction *act, GObject * /*tbl*/ )
4555
int mode = ege_select_one_action_get_active( act );
4556
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4557
prefs->setInt("/tools/spray/mode", mode);
4560
static void sp_spray_population_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
4562
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4563
prefs->setDouble( "/tools/spray/population", adj->value );
4566
static void sp_spray_rotation_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
4568
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4569
prefs->setDouble( "/tools/spray/rotation_variation", adj->value );
4572
static void sp_spray_scale_value_changed( GtkAdjustment *adj, GObject * /*tbl*/ )
4574
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4575
prefs->setDouble( "/tools/spray/scale_variation", adj->value );
4579
static void sp_spray_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
4581
Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1);
4582
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4586
gchar const* labels[] = {_("(narrow spray)"), 0, 0, 0, _("(default)"), 0, 0, 0, 0, _("(broad spray)")};
4587
gdouble values[] = {1, 3, 5, 10, 15, 20, 30, 50, 75, 100};
4588
EgeAdjustmentAction *eact = create_adjustment_action( "SprayWidthAction",
4589
_("Width"), _("Width:"), _("The width of the spray area (relative to the visible canvas area)"),
4590
"/tools/spray/width", 15,
4591
GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "altx-spray",
4593
labels, values, G_N_ELEMENTS(labels),
4594
sp_spray_width_value_changed, 1, 0 );
4595
ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
4596
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
4597
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
4602
gchar const* labels[] = {_("(minimum mean)"), 0, 0, _("(default)"), 0, 0, 0, _("(maximum mean)")};
4603
gdouble values[] = {1, 5, 10, 20, 30, 50, 70, 100};
4604
EgeAdjustmentAction *eact = create_adjustment_action( "SprayMeanAction",
4605
_("Focus"), _("Focus:"), _("0 to spray a spot. Increase to enlarge the ring radius."),
4606
"/tools/spray/mean", 0,
4607
GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "spray-mean",
4609
labels, values, G_N_ELEMENTS(labels),
4610
sp_spray_mean_value_changed, 1, 0 );
4611
ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
4612
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
4613
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
4617
/* Standard_deviation */
4618
gchar const* labels[] = {_("(minimum scatter)"), 0, 0, _("(default)"), 0, 0, 0, _("(maximum scatter)")};
4619
gdouble values[] = {1, 5, 10, 20, 30, 50, 70, 100};
4621
//TRANSLATORS: only translate "string" in "context|string".
4622
// For more details, see http://developer.gnome.org/doc/API/2.0/glib/glib-I18N.html#Q-:CAPS
4623
EgeAdjustmentAction *eact = create_adjustment_action( "SprayStandard_deviationAction",
4624
Q_("Toolbox|Scatter"), Q_("Toolbox|Scatter:"), _("Increase to scatter sprayed objects."),
4625
"/tools/spray/standard_deviation", 70,
4626
GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "spray-standard_deviation",
4628
labels, values, G_N_ELEMENTS(labels),
4629
sp_spray_standard_deviation_value_changed, 1, 0 );
4630
ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
4631
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
4632
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
4637
GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING );
4640
gtk_list_store_append( model, &iter );
4641
gtk_list_store_set( model, &iter,
4642
0, _("Spray with copies"),
4643
1, _("Spray copies of the initial selection"),
4644
2, INKSCAPE_ICON_SPRAY_COPY_MODE,
4647
gtk_list_store_append( model, &iter );
4648
gtk_list_store_set( model, &iter,
4649
0, _("Spray with clones"),
4650
1, _("Spray clones of the initial selection"),
4651
2, INKSCAPE_ICON_SPRAY_CLONE_MODE,
4654
gtk_list_store_append( model, &iter );
4655
gtk_list_store_set( model, &iter,
4656
0, _("Spray single path"),
4657
1, _("Spray objects in a single path"),
4658
2, INKSCAPE_ICON_SPRAY_UNION_MODE,
4661
EgeSelectOneAction* act = ege_select_one_action_new( "SprayModeAction", _("Mode"), (""), NULL, GTK_TREE_MODEL(model) );
4662
g_object_set( act, "short_label", _("Mode:"), NULL );
4663
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
4664
g_object_set_data( holder, "mode_action", act );
4666
ege_select_one_action_set_appearance( act, "full" );
4667
ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE );
4668
g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL );
4669
ege_select_one_action_set_icon_column( act, 2 );
4670
ege_select_one_action_set_icon_size( act, secondarySize );
4671
ege_select_one_action_set_tooltip_column( act, 1 );
4673
gint mode = prefs->getInt("/tools/spray/mode", 1);
4674
ege_select_one_action_set_active( act, mode );
4675
g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_spray_mode_changed), holder );
4677
g_object_set_data( G_OBJECT(holder), "spray_tool_mode", act);
4681
gchar const* labels[] = {_("(low population)"), 0, 0, _("(default)"), 0, 0, _("(high population)")};
4682
gdouble values[] = {10, 25, 35, 50, 60, 80, 100};
4683
EgeAdjustmentAction *eact = create_adjustment_action( "SprayPopulationAction",
4684
_("Amount"), _("Amount:"),
4685
_("Adjusts the number of items sprayed per clic."),
4686
"/tools/spray/population", 70,
4687
GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "spray-population",
4689
labels, values, G_N_ELEMENTS(labels),
4690
sp_spray_population_value_changed, 1, 0 );
4691
ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
4692
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
4693
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
4694
g_object_set_data( holder, "spray_population", eact );
4697
/* Use Pressure button */
4699
InkToggleAction* act = ink_toggle_action_new( "SprayPressureAction",
4701
_("Use the pressure of the input device to alter the amount of sprayed objects."),
4703
Inkscape::ICON_SIZE_DECORATION );
4704
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
4705
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_spray_pressure_state_changed), NULL);
4706
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/spray/usepressure", true) );
4710
gchar const* labels[] = {_("(low rotation variation)"), 0, 0, _("(default)"), 0, 0, _("(high rotation variation)")};
4711
gdouble values[] = {10, 25, 35, 50, 60, 80, 100};
4712
EgeAdjustmentAction *eact = create_adjustment_action( "SprayRotationAction",
4713
_("Rotation"), _("Rotation:"),
4714
// xgettext:no-c-format
4715
_("Variation of the rotation of the sprayed objects. 0% for the same rotation than the original object."),
4716
"/tools/spray/rotation_variation", 0,
4717
GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "spray-rotation",
4719
labels, values, G_N_ELEMENTS(labels),
4720
sp_spray_rotation_value_changed, 1, 0 );
4721
ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
4722
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
4723
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
4724
g_object_set_data( holder, "spray_rotation", eact );
4728
gchar const* labels[] = {_("(low scale variation)"), 0, 0, _("(default)"), 0, 0, _("(high scale variation)")};
4729
gdouble values[] = {10, 25, 35, 50, 60, 80, 100};
4731
//TRANSLATORS: only translate "string" in "context|string".
4732
// For more details, see http://developer.gnome.org/doc/API/2.0/glib/glib-I18N.html#Q-:CAPS
4733
EgeAdjustmentAction *eact = create_adjustment_action( "SprayScaleAction",
4734
Q_("Toolbox|Scale"), Q_("Toolbox|Scale:"),
4735
// xgettext:no-c-format
4736
_("Variation in the scale of the sprayed objects. 0% for the same scale than the original object."),
4737
"/tools/spray/scale_variation", 0,
4738
GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "spray-scale",
4740
labels, values, G_N_ELEMENTS(labels),
4741
sp_spray_scale_value_changed, 1, 0 );
4742
ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
4743
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
4744
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
4745
g_object_set_data( holder, "spray_scale", eact );
4753
//########################
4755
//########################
4756
static void update_presets_list(GObject *tbl)
4758
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4759
if (g_object_get_data(tbl, "presets_blocked")) {
4763
EgeSelectOneAction *sel = static_cast<EgeSelectOneAction *>(g_object_get_data(tbl, "profile_selector"));
4765
// WTF!? This will cause a segfault if ever reached
4766
//ege_select_one_action_set_active(sel, 0);
4770
std::vector<Glib::ustring> presets = prefs->getAllDirs("/tools/calligraphic/preset");
4773
for (std::vector<Glib::ustring>::iterator i = presets.begin(); i != presets.end(); ++i, ++ege_index) {
4776
std::vector<Inkscape::Preferences::Entry> preset = prefs->getAllEntries(*i);
4777
for (std::vector<Inkscape::Preferences::Entry>::iterator j = preset.begin(); j != preset.end(); ++j) {
4778
Glib::ustring entry_name = j->getEntryName();
4779
if (entry_name == "id" || entry_name == "name") {
4783
void *widget = g_object_get_data(tbl, entry_name.data());
4785
if (GTK_IS_ADJUSTMENT(widget)) {
4786
double v = j->getDouble();
4787
GtkAdjustment* adj = static_cast<GtkAdjustment *>(widget);
4788
//std::cout << "compared adj " << attr_name << gtk_adjustment_get_value(adj) << " to " << v << "\n";
4789
if (fabs(gtk_adjustment_get_value(adj) - v) > 1e-6) {
4793
} else if (GTK_IS_TOGGLE_ACTION(widget)) {
4794
bool v = j->getBool();
4795
GtkToggleAction* toggle = static_cast<GtkToggleAction *>(widget);
4796
//std::cout << "compared toggle " << attr_name << gtk_toggle_action_get_active(toggle) << " to " << v << "\n";
4797
if ( static_cast<bool>(gtk_toggle_action_get_active(toggle)) != v ) {
4806
// newly added item is at the same index as the
4807
// save command, so we need to change twice for it to take effect
4808
ege_select_one_action_set_active(sel, 0);
4809
ege_select_one_action_set_active(sel, ege_index); // one-based index
4815
ege_select_one_action_set_active(sel, 0);
4818
static void sp_ddc_mass_value_changed( GtkAdjustment *adj, GObject* tbl )
4820
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4821
prefs->setDouble( "/tools/calligraphic/mass", adj->value );
4822
update_presets_list(tbl);
4825
static void sp_ddc_wiggle_value_changed( GtkAdjustment *adj, GObject* tbl )
4827
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4828
prefs->setDouble( "/tools/calligraphic/wiggle", adj->value );
4829
update_presets_list(tbl);
4832
static void sp_ddc_angle_value_changed( GtkAdjustment *adj, GObject* tbl )
4834
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4835
prefs->setDouble( "/tools/calligraphic/angle", adj->value );
4836
update_presets_list(tbl);
4839
static void sp_ddc_width_value_changed( GtkAdjustment *adj, GObject *tbl )
4841
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4842
prefs->setDouble( "/tools/calligraphic/width", adj->value );
4843
update_presets_list(tbl);
4846
static void sp_ddc_velthin_value_changed( GtkAdjustment *adj, GObject* tbl )
4848
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4849
prefs->setDouble("/tools/calligraphic/thinning", adj->value );
4850
update_presets_list(tbl);
4853
static void sp_ddc_flatness_value_changed( GtkAdjustment *adj, GObject* tbl )
4855
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4856
prefs->setDouble( "/tools/calligraphic/flatness", adj->value );
4857
update_presets_list(tbl);
4860
static void sp_ddc_tremor_value_changed( GtkAdjustment *adj, GObject* tbl )
4862
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4863
prefs->setDouble( "/tools/calligraphic/tremor", adj->value );
4864
update_presets_list(tbl);
4867
static void sp_ddc_cap_rounding_value_changed( GtkAdjustment *adj, GObject* tbl )
4869
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4870
prefs->setDouble( "/tools/calligraphic/cap_rounding", adj->value );
4871
update_presets_list(tbl);
4874
static void sp_ddc_tilt_state_changed( GtkToggleAction *act, GObject* tbl )
4876
// TODO merge into PrefPusher
4877
GtkAction * calligraphy_angle = static_cast<GtkAction *> (g_object_get_data(tbl,"angle_action"));
4878
if (calligraphy_angle ) {
4879
gtk_action_set_sensitive( calligraphy_angle, !gtk_toggle_action_get_active( act ) );
4884
static gchar const *const widget_names[] = {
4899
static void sp_dcc_build_presets_list(GObject *tbl)
4901
g_object_set_data(tbl, "presets_blocked", GINT_TO_POINTER(TRUE));
4903
EgeSelectOneAction* selector = static_cast<EgeSelectOneAction *>(g_object_get_data(tbl, "profile_selector"));
4904
GtkListStore* model = GTK_LIST_STORE(ege_select_one_action_get_model(selector));
4905
gtk_list_store_clear (model);
4909
gtk_list_store_append( model, &iter );
4910
gtk_list_store_set( model, &iter, 0, _("No preset"), 1, 0, -1 );
4913
// iterate over all presets to populate the list
4914
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4915
std::vector<Glib::ustring> presets = prefs->getAllDirs("/tools/calligraphic/preset");
4918
for (std::vector<Glib::ustring>::iterator i = presets.begin(); i != presets.end(); ++i) {
4920
Glib::ustring preset_name = prefs->getString(*i + "/name");
4921
gtk_list_store_append( model, &iter );
4922
gtk_list_store_set( model, &iter, 0, _(preset_name.data()), 1, ii++, -1 );
4927
gtk_list_store_append( model, &iter );
4928
gtk_list_store_set( model, &iter, 0, _("Save..."), 1, ii, -1 );
4929
g_object_set_data(tbl, "save_presets_index", GINT_TO_POINTER(ii));
4932
g_object_set_data(tbl, "presets_blocked", GINT_TO_POINTER(FALSE));
4934
update_presets_list (tbl);
4937
static void sp_dcc_save_profile(GtkWidget * /*widget*/, GObject *tbl)
4939
using Inkscape::UI::Dialog::CalligraphicProfileRename;
4940
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
4941
SPDesktop *desktop = (SPDesktop *) g_object_get_data(tbl, "desktop" );
4946
if (g_object_get_data(tbl, "presets_blocked")) {
4950
CalligraphicProfileRename::show(desktop);
4951
if ( !CalligraphicProfileRename::applied()) {
4953
update_presets_list (tbl);
4956
Glib::ustring profile_name = CalligraphicProfileRename::getProfileName();
4958
if (profile_name.empty()) {
4959
// empty name entered
4960
update_presets_list (tbl);
4964
g_object_set_data(tbl, "presets_blocked", GINT_TO_POINTER(TRUE));
4966
// If there's a preset with the given name, find it and set save_path appropriately
4967
std::vector<Glib::ustring> presets = prefs->getAllDirs("/tools/calligraphic/preset");
4968
int total_presets = presets.size();
4970
Glib::ustring save_path; // profile pref path without a trailing slash
4973
for (std::vector<Glib::ustring>::iterator i = presets.begin(); i != presets.end(); ++i, ++temp_index) {
4974
Glib::ustring name = prefs->getString(*i + "/name");
4975
if (!name.empty() && profile_name == name) {
4976
new_index = temp_index;
4982
if (new_index == -1) {
4983
// no preset with this name, create
4984
new_index = total_presets + 1;
4985
gchar *profile_id = g_strdup_printf("/dcc%d", new_index);
4986
save_path = Glib::ustring("/tools/calligraphic/preset") + profile_id;
4990
for (unsigned i = 0; i < G_N_ELEMENTS(widget_names); ++i) {
4991
gchar const *const widget_name = widget_names[i];
4992
void *widget = g_object_get_data(tbl, widget_name);
4994
if (GTK_IS_ADJUSTMENT(widget)) {
4995
GtkAdjustment* adj = static_cast<GtkAdjustment *>(widget);
4996
prefs->setDouble(save_path + "/" + widget_name, gtk_adjustment_get_value(adj));
4997
//std::cout << "wrote adj " << widget_name << ": " << v << "\n";
4998
} else if (GTK_IS_TOGGLE_ACTION(widget)) {
4999
GtkToggleAction* toggle = static_cast<GtkToggleAction *>(widget);
5000
prefs->setBool(save_path + "/" + widget_name, gtk_toggle_action_get_active(toggle));
5001
//std::cout << "wrote tog " << widget_name << ": " << v << "\n";
5003
g_warning("Unknown widget type for preset: %s\n", widget_name);
5006
g_warning("Bad key when writing preset: %s\n", widget_name);
5009
prefs->setString(save_path + "/name", profile_name);
5011
g_object_set_data(tbl, "presets_blocked", GINT_TO_POINTER(FALSE));
5012
sp_dcc_build_presets_list (tbl);
5016
static void sp_ddc_change_profile(EgeSelectOneAction* act, GObject* tbl)
5018
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
5020
gint preset_index = ege_select_one_action_get_active( act );
5021
// This is necessary because EgeSelectOneAction spams us with GObject "changed" signal calls
5022
// even when the preset is not changed. It would be good to replace it with something more
5023
// modern. Index 0 means "No preset", so we don't do anything.
5024
if (preset_index == 0) {
5028
gint save_presets_index = GPOINTER_TO_INT(g_object_get_data(tbl, "save_presets_index"));
5030
if (preset_index == save_presets_index) {
5031
// this is the Save command
5032
sp_dcc_save_profile(NULL, tbl);
5036
if (g_object_get_data(tbl, "presets_blocked")) {
5040
// preset_index is one-based so we subtract 1
5041
std::vector<Glib::ustring> presets = prefs->getAllDirs("/tools/calligraphic/preset");
5042
Glib::ustring preset_path = presets.at(preset_index - 1);
5044
if (!preset_path.empty()) {
5045
g_object_set_data(tbl, "presets_blocked", GINT_TO_POINTER(TRUE)); //temporarily block the selector so no one will updadte it while we're reading it
5047
std::vector<Inkscape::Preferences::Entry> preset = prefs->getAllEntries(preset_path);
5049
// Shouldn't this be std::map?
5050
for (std::vector<Inkscape::Preferences::Entry>::iterator i = preset.begin(); i != preset.end(); ++i) {
5051
Glib::ustring entry_name = i->getEntryName();
5052
if (entry_name == "id" || entry_name == "name") {
5055
void *widget = g_object_get_data(tbl, entry_name.data());
5057
if (GTK_IS_ADJUSTMENT(widget)) {
5058
GtkAdjustment* adj = static_cast<GtkAdjustment *>(widget);
5059
gtk_adjustment_set_value(adj, i->getDouble());
5060
//std::cout << "set adj " << attr_name << " to " << v << "\n";
5061
} else if (GTK_IS_TOGGLE_ACTION(widget)) {
5062
GtkToggleAction* toggle = static_cast<GtkToggleAction *>(widget);
5063
gtk_toggle_action_set_active(toggle, i->getBool());
5064
//std::cout << "set toggle " << attr_name << " to " << v << "\n";
5066
g_warning("Unknown widget type for preset: %s\n", entry_name.data());
5069
g_warning("Bad key found in a preset record: %s\n", entry_name.data());
5072
g_object_set_data(tbl, "presets_blocked", GINT_TO_POINTER(FALSE));
5076
static void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
5078
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
5080
g_object_set_data(holder, "presets_blocked", GINT_TO_POINTER(TRUE));
5082
EgeAdjustmentAction* calligraphy_angle = 0;
5086
gchar const* labels[] = {_("(hairline)"), 0, 0, 0, _("(default)"), 0, 0, 0, 0, _("(broad stroke)")};
5087
gdouble values[] = {1, 3, 5, 10, 15, 20, 30, 50, 75, 100};
5088
EgeAdjustmentAction *eact = create_adjustment_action( "CalligraphyWidthAction",
5089
_("Pen Width"), _("Width:"),
5090
_("The width of the calligraphic pen (relative to the visible canvas area)"),
5091
"/tools/calligraphic/width", 15,
5092
GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "altx-calligraphy",
5094
labels, values, G_N_ELEMENTS(labels),
5095
sp_ddc_width_value_changed, 1, 0 );
5096
ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
5097
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
5098
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
5103
gchar const* labels[] = {_("(speed blows up stroke)"), 0, 0, _("(slight widening)"), _("(constant width)"), _("(slight thinning, default)"), 0, 0, _("(speed deflates stroke)")};
5104
gdouble values[] = {-100, -40, -20, -10, 0, 10, 20, 40, 100};
5105
EgeAdjustmentAction* eact = create_adjustment_action( "ThinningAction",
5106
_("Stroke Thinning"), _("Thinning:"),
5107
_("How much velocity thins the stroke (> 0 makes fast strokes thinner, < 0 makes them broader, 0 makes width independent of velocity)"),
5108
"/tools/calligraphic/thinning", 10,
5109
GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
5111
labels, values, G_N_ELEMENTS(labels),
5112
sp_ddc_velthin_value_changed, 1, 0);
5113
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
5114
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
5119
gchar const* labels[] = {_("(left edge up)"), 0, 0, _("(horizontal)"), _("(default)"), 0, _("(right edge up)")};
5120
gdouble values[] = {-90, -60, -30, 0, 30, 60, 90};
5121
EgeAdjustmentAction* eact = create_adjustment_action( "AngleAction",
5122
_("Pen Angle"), _("Angle:"),
5123
_("The angle of the pen's nib (in degrees; 0 = horizontal; has no effect if fixation = 0)"),
5124
"/tools/calligraphic/angle", 30,
5125
GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "calligraphy-angle",
5126
-90.0, 90.0, 1.0, 10.0,
5127
labels, values, G_N_ELEMENTS(labels),
5128
sp_ddc_angle_value_changed, 1, 0 );
5129
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
5130
g_object_set_data( holder, "angle_action", eact );
5131
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
5132
calligraphy_angle = eact;
5137
gchar const* labels[] = {_("(perpendicular to stroke, \"brush\")"), 0, 0, 0, _("(almost fixed, default)"), _("(fixed by Angle, \"pen\")")};
5138
gdouble values[] = {0, 20, 40, 60, 90, 100};
5139
EgeAdjustmentAction* eact = create_adjustment_action( "FixationAction",
5140
_("Fixation"), _("Fixation:"),
5141
_("Angle behavior (0 = nib always perpendicular to stroke direction, 100 = fixed angle)"),
5142
"/tools/calligraphic/flatness", 90,
5143
GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
5144
0.0, 100, 1.0, 10.0,
5145
labels, values, G_N_ELEMENTS(labels),
5146
sp_ddc_flatness_value_changed, 1, 0);
5147
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
5148
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
5153
gchar const* labels[] = {_("(blunt caps, default)"), _("(slightly bulging)"), 0, 0, _("(approximately round)"), _("(long protruding caps)")};
5154
gdouble values[] = {0, 0.3, 0.5, 1.0, 1.4, 5.0};
5155
// TRANSLATORS: "cap" means "end" (both start and finish) here
5156
EgeAdjustmentAction* eact = create_adjustment_action( "CapRoundingAction",
5157
_("Cap rounding"), _("Caps:"),
5158
_("Increase to make caps at the ends of strokes protrude more (0 = no caps, 1 = round caps)"),
5159
"/tools/calligraphic/cap_rounding", 0.0,
5160
GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
5161
0.0, 5.0, 0.01, 0.1,
5162
labels, values, G_N_ELEMENTS(labels),
5163
sp_ddc_cap_rounding_value_changed, 0.01, 2 );
5164
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
5165
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
5170
gchar const* labels[] = {_("(smooth line)"), _("(slight tremor)"), _("(noticeable tremor)"), 0, 0, _("(maximum tremor)")};
5171
gdouble values[] = {0, 10, 20, 40, 60, 100};
5172
EgeAdjustmentAction* eact = create_adjustment_action( "TremorAction",
5173
_("Stroke Tremor"), _("Tremor:"),
5174
_("Increase to make strokes rugged and trembling"),
5175
"/tools/calligraphic/tremor", 0.0,
5176
GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
5178
labels, values, G_N_ELEMENTS(labels),
5179
sp_ddc_tremor_value_changed, 1, 0);
5181
ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
5182
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
5183
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
5188
gchar const* labels[] = {_("(no wiggle)"), _("(slight deviation)"), 0, 0, _("(wild waves and curls)")};
5189
gdouble values[] = {0, 20, 40, 60, 100};
5190
EgeAdjustmentAction* eact = create_adjustment_action( "WiggleAction",
5191
_("Pen Wiggle"), _("Wiggle:"),
5192
_("Increase to make the pen waver and wiggle"),
5193
"/tools/calligraphic/wiggle", 0.0,
5194
GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
5196
labels, values, G_N_ELEMENTS(labels),
5197
sp_ddc_wiggle_value_changed, 1, 0);
5198
ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
5199
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
5200
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
5205
gchar const* labels[] = {_("(no inertia)"), _("(slight smoothing, default)"), _("(noticeable lagging)"), 0, 0, _("(maximum inertia)")};
5206
gdouble values[] = {0.0, 2, 10, 20, 50, 100};
5207
EgeAdjustmentAction* eact = create_adjustment_action( "MassAction",
5208
_("Pen Mass"), _("Mass:"),
5209
_("Increase to make the pen drag behind, as if slowed by inertia"),
5210
"/tools/calligraphic/mass", 2.0,
5211
GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
5213
labels, values, G_N_ELEMENTS(labels),
5214
sp_ddc_mass_value_changed, 1, 0);
5215
ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
5216
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
5217
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
5221
/* Trace Background button */
5223
InkToggleAction* act = ink_toggle_action_new( "TraceAction",
5224
_("Trace Background"),
5225
_("Trace the lightness of the background by the width of the pen (white - minimum width, black - maximum width)"),
5226
INKSCAPE_ICON_DRAW_TRACE_BACKGROUND,
5227
Inkscape::ICON_SIZE_DECORATION );
5228
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
5229
PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/calligraphic/tracebackground", update_presets_list, holder);
5230
g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
5231
g_object_set_data( holder, "tracebackground", act );
5234
/* Use Pressure button */
5236
InkToggleAction* act = ink_toggle_action_new( "PressureAction",
5238
_("Use the pressure of the input device to alter the width of the pen"),
5239
INKSCAPE_ICON_DRAW_USE_PRESSURE,
5240
Inkscape::ICON_SIZE_DECORATION );
5241
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
5242
PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/calligraphic/usepressure", update_presets_list, holder);
5243
g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
5244
g_object_set_data( holder, "usepressure", act );
5247
/* Use Tilt button */
5249
InkToggleAction* act = ink_toggle_action_new( "TiltAction",
5251
_("Use the tilt of the input device to alter the angle of the pen's nib"),
5252
INKSCAPE_ICON_DRAW_USE_TILT,
5253
Inkscape::ICON_SIZE_DECORATION );
5254
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
5255
PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/calligraphic/usetilt", update_presets_list, holder);
5256
g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
5257
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_ddc_tilt_state_changed), holder );
5258
gtk_action_set_sensitive( GTK_ACTION(calligraphy_angle), !prefs->getBool("/tools/calligraphic/usetilt", true) );
5259
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/calligraphic/usetilt", true) );
5260
g_object_set_data( holder, "usetilt", act );
5263
/*calligraphic profile */
5265
GtkListStore* model = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
5266
EgeSelectOneAction* act1 = ege_select_one_action_new ("SetProfileAction", "" , (_("Choose a preset")), NULL, GTK_TREE_MODEL(model));
5267
ege_select_one_action_set_appearance (act1, "compact");
5268
g_object_set_data (holder, "profile_selector", act1 );
5270
g_object_set_data(holder, "presets_blocked", GINT_TO_POINTER(FALSE));
5272
sp_dcc_build_presets_list (holder);
5274
g_signal_connect(G_OBJECT(act1), "changed", G_CALLBACK(sp_ddc_change_profile), holder);
5275
gtk_action_group_add_action(mainActions, GTK_ACTION(act1));
5281
//########################
5282
//## Circle / Arc ##
5283
//########################
5285
static void sp_arctb_sensitivize( GObject *tbl, double v1, double v2 )
5287
GtkAction *ocb = GTK_ACTION( g_object_get_data( tbl, "open_action" ) );
5288
GtkAction *make_whole = GTK_ACTION( g_object_get_data( tbl, "make_whole" ) );
5290
if (v1 == 0 && v2 == 0) {
5291
if (g_object_get_data( tbl, "single" )) { // only for a single selected ellipse (for now)
5292
gtk_action_set_sensitive( ocb, FALSE );
5293
gtk_action_set_sensitive( make_whole, FALSE );
5296
gtk_action_set_sensitive( ocb, TRUE );
5297
gtk_action_set_sensitive( make_whole, TRUE );
5302
sp_arctb_startend_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *value_name, gchar const *other_name)
5304
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
5306
if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
5307
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
5308
prefs->setDouble(Glib::ustring("/tools/shapes/arc/") + value_name, adj->value);
5311
// quit if run by the attr_changed listener
5312
if (g_object_get_data( tbl, "freeze" )) {
5316
// in turn, prevent listener from responding
5317
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
5319
gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
5321
bool modmade = false;
5322
for (GSList const *items = sp_desktop_selection(desktop)->itemList();
5324
items = items->next)
5326
SPItem *item = SP_ITEM(items->data);
5328
if (SP_IS_ARC(item) && SP_IS_GENERICELLIPSE(item)) {
5330
SPGenericEllipse *ge = SP_GENERICELLIPSE(item);
5331
SPArc *arc = SP_ARC(item);
5333
if (!strcmp(value_name, "start")) {
5334
ge->start = (adj->value * M_PI)/ 180;
5336
ge->end = (adj->value * M_PI)/ 180;
5339
sp_genericellipse_normalize(ge);
5340
((SPObject *)arc)->updateRepr();
5341
((SPObject *)arc)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
5347
g_free(namespaced_name);
5349
GtkAdjustment *other = GTK_ADJUSTMENT( g_object_get_data( tbl, other_name ) );
5351
sp_arctb_sensitivize( tbl, adj->value, other->value );
5354
sp_document_maybe_done(sp_desktop_document(desktop), value_name, SP_VERB_CONTEXT_ARC,
5355
_("Arc: Change start/end"));
5358
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
5362
static void sp_arctb_start_value_changed(GtkAdjustment *adj, GObject *tbl)
5364
sp_arctb_startend_value_changed(adj, tbl, "start", "end");
5367
static void sp_arctb_end_value_changed(GtkAdjustment *adj, GObject *tbl)
5369
sp_arctb_startend_value_changed(adj, tbl, "end", "start");
5373
static void sp_arctb_open_state_changed( EgeSelectOneAction *act, GObject *tbl )
5375
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
5376
if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
5377
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
5378
prefs->setBool("/tools/shapes/arc/open", ege_select_one_action_get_active(act) != 0);
5381
// quit if run by the attr_changed listener
5382
if (g_object_get_data( tbl, "freeze" )) {
5386
// in turn, prevent listener from responding
5387
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
5389
bool modmade = false;
5391
if ( ege_select_one_action_get_active(act) != 0 ) {
5392
for (GSList const *items = sp_desktop_selection(desktop)->itemList();
5394
items = items->next)
5396
if (SP_IS_ARC((SPItem *) items->data)) {
5397
Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
5398
repr->setAttribute("sodipodi:open", "true");
5399
SP_OBJECT((SPItem *) items->data)->updateRepr();
5404
for (GSList const *items = sp_desktop_selection(desktop)->itemList();
5406
items = items->next)
5408
if (SP_IS_ARC((SPItem *) items->data)) {
5409
Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data);
5410
repr->setAttribute("sodipodi:open", NULL);
5411
SP_OBJECT((SPItem *) items->data)->updateRepr();
5418
sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_ARC,
5419
_("Arc: Change open/closed"));
5422
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
5425
static void sp_arctb_defaults(GtkWidget *, GObject *obj)
5428
adj = GTK_ADJUSTMENT( g_object_get_data(obj, "start") );
5429
gtk_adjustment_set_value(adj, 0.0);
5430
gtk_adjustment_value_changed(adj);
5432
adj = GTK_ADJUSTMENT( g_object_get_data(obj, "end") );
5433
gtk_adjustment_set_value(adj, 0.0);
5434
gtk_adjustment_value_changed(adj);
5436
spinbutton_defocus( GTK_OBJECT(obj) );
5439
static void arc_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const * /*name*/,
5440
gchar const * /*old_value*/, gchar const * /*new_value*/,
5441
bool /*is_interactive*/, gpointer data)
5443
GObject *tbl = G_OBJECT(data);
5445
// quit if run by the _changed callbacks
5446
if (g_object_get_data( tbl, "freeze" )) {
5450
// in turn, prevent callbacks from responding
5451
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
5453
gdouble start = sp_repr_get_double_attribute(repr, "sodipodi:start", 0.0);
5454
gdouble end = sp_repr_get_double_attribute(repr, "sodipodi:end", 0.0);
5456
GtkAdjustment *adj1,*adj2;
5457
adj1 = GTK_ADJUSTMENT( g_object_get_data( tbl, "start" ) );
5458
gtk_adjustment_set_value(adj1, mod360((start * 180)/M_PI));
5459
adj2 = GTK_ADJUSTMENT( g_object_get_data( tbl, "end" ) );
5460
gtk_adjustment_set_value(adj2, mod360((end * 180)/M_PI));
5462
sp_arctb_sensitivize( tbl, adj1->value, adj2->value );
5464
char const *openstr = NULL;
5465
openstr = repr->attribute("sodipodi:open");
5466
EgeSelectOneAction *ocb = EGE_SELECT_ONE_ACTION( g_object_get_data( tbl, "open_action" ) );
5469
ege_select_one_action_set_active( ocb, 1 );
5471
ege_select_one_action_set_active( ocb, 0 );
5474
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
5477
static Inkscape::XML::NodeEventVector arc_tb_repr_events = {
5478
NULL, /* child_added */
5479
NULL, /* child_removed */
5480
arc_tb_event_attr_changed,
5481
NULL, /* content_changed */
5482
NULL /* order_changed */
5486
static void sp_arc_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
5489
Inkscape::XML::Node *repr = NULL;
5491
purge_repr_listener( tbl, tbl );
5493
for (GSList const *items = selection->itemList();
5495
items = items->next)
5497
if (SP_IS_ARC((SPItem *) items->data)) {
5499
repr = SP_OBJECT_REPR((SPItem *) items->data);
5503
EgeOutputAction* act = EGE_OUTPUT_ACTION( g_object_get_data( tbl, "mode_action" ) );
5505
g_object_set_data( tbl, "single", GINT_TO_POINTER(FALSE) );
5506
if (n_selected == 0) {
5507
g_object_set( G_OBJECT(act), "label", _("<b>New:</b>"), NULL );
5508
} else if (n_selected == 1) {
5509
g_object_set_data( tbl, "single", GINT_TO_POINTER(TRUE) );
5510
g_object_set( G_OBJECT(act), "label", _("<b>Change:</b>"), NULL );
5513
g_object_set_data( tbl, "repr", repr );
5514
Inkscape::GC::anchor(repr);
5515
sp_repr_add_listener(repr, &arc_tb_repr_events, tbl);
5516
sp_repr_synthesize_events(repr, &arc_tb_repr_events, tbl);
5519
// FIXME: implement averaging of all parameters for multiple selected
5520
//gtk_label_set_markup(GTK_LABEL(l), _("<b>Average:</b>"));
5521
g_object_set( G_OBJECT(act), "label", _("<b>Change:</b>"), NULL );
5522
sp_arctb_sensitivize( tbl, 1, 0 );
5527
static void sp_arc_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
5529
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
5531
EgeAdjustmentAction* eact = 0;
5532
Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1);
5536
EgeOutputAction* act = ege_output_action_new( "ArcStateAction", _("<b>New:</b>"), "", 0 );
5537
ege_output_action_set_use_markup( act, TRUE );
5538
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
5539
g_object_set_data( holder, "mode_action", act );
5544
eact = create_adjustment_action( "ArcStartAction",
5545
_("Start"), _("Start:"),
5546
_("The angle (in degrees) from the horizontal to the arc's start point"),
5547
"/tools/shapes/arc/start", 0.0,
5548
GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, TRUE, "altx-arc",
5549
-360.0, 360.0, 1.0, 10.0,
5551
sp_arctb_start_value_changed);
5552
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
5557
eact = create_adjustment_action( "ArcEndAction",
5558
_("End"), _("End:"),
5559
_("The angle (in degrees) from the horizontal to the arc's end point"),
5560
"/tools/shapes/arc/end", 0.0,
5561
GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, FALSE, NULL,
5562
-360.0, 360.0, 1.0, 10.0,
5564
sp_arctb_end_value_changed);
5565
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
5568
/* Segments / Pie checkbox */
5570
GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING );
5573
gtk_list_store_append( model, &iter );
5574
gtk_list_store_set( model, &iter,
5576
1, _("Switch to segment (closed shape with two radii)"),
5577
2, INKSCAPE_ICON_DRAW_ELLIPSE_SEGMENT,
5580
gtk_list_store_append( model, &iter );
5581
gtk_list_store_set( model, &iter,
5583
1, _("Switch to arc (unclosed shape)"),
5584
2, INKSCAPE_ICON_DRAW_ELLIPSE_ARC,
5587
EgeSelectOneAction* act = ege_select_one_action_new( "ArcOpenAction", (""), (""), NULL, GTK_TREE_MODEL(model) );
5588
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
5589
g_object_set_data( holder, "open_action", act );
5591
ege_select_one_action_set_appearance( act, "full" );
5592
ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE );
5593
g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL );
5594
ege_select_one_action_set_icon_column( act, 2 );
5595
ege_select_one_action_set_icon_size( act, secondarySize );
5596
ege_select_one_action_set_tooltip_column( act, 1 );
5598
bool isClosed = !prefs->getBool("/tools/shapes/arc/open", false);
5599
ege_select_one_action_set_active( act, isClosed ? 0 : 1 );
5600
g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_arctb_open_state_changed), holder );
5605
InkAction* inky = ink_action_new( "ArcResetAction",
5607
_("Make the shape a whole ellipse, not arc or segment"),
5608
INKSCAPE_ICON_DRAW_ELLIPSE_WHOLE,
5610
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_arctb_defaults), holder );
5611
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
5612
gtk_action_set_sensitive( GTK_ACTION(inky), TRUE );
5613
g_object_set_data( holder, "make_whole", inky );
5616
g_object_set_data( G_OBJECT(holder), "single", GINT_TO_POINTER(TRUE) );
5617
// sensitivize make whole and open checkbox
5619
GtkAdjustment *adj1 = GTK_ADJUSTMENT( g_object_get_data( holder, "start" ) );
5620
GtkAdjustment *adj2 = GTK_ADJUSTMENT( g_object_get_data( holder, "end" ) );
5621
sp_arctb_sensitivize( holder, adj1->value, adj2->value );
5625
sigc::connection *connection = new sigc::connection(
5626
sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_arc_toolbox_selection_changed), (GObject *)holder))
5628
g_signal_connect( holder, "destroy", G_CALLBACK(delete_connection), connection );
5629
g_signal_connect( holder, "destroy", G_CALLBACK(purge_repr_listener), holder );
5635
// toggle button callbacks and updaters
5637
//########################
5639
//########################
5641
static void toggle_dropper_pick_alpha( GtkToggleAction* act, gpointer tbl )
5643
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
5644
prefs->setInt( "/tools/dropper/pick", gtk_toggle_action_get_active( act ) );
5645
GtkAction* set_action = GTK_ACTION( g_object_get_data(G_OBJECT(tbl), "set_action") );
5647
if ( gtk_toggle_action_get_active( act ) ) {
5648
gtk_action_set_sensitive( set_action, TRUE );
5650
gtk_action_set_sensitive( set_action, FALSE );
5654
spinbutton_defocus(GTK_OBJECT(tbl));
5657
static void toggle_dropper_set_alpha( GtkToggleAction* act, gpointer tbl )
5659
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
5660
prefs->setBool( "/tools/dropper/setalpha", gtk_toggle_action_get_active( act ) );
5661
spinbutton_defocus(GTK_OBJECT(tbl));
5666
* Dropper auxiliary toolbar construction and setup.
5668
* TODO: Would like to add swatch of current color.
5669
* TODO: Add queue of last 5 or so colors selected with new swatches so that
5670
* can drag and drop places. Will provide a nice mixing palette.
5672
static void sp_dropper_toolbox_prep(SPDesktop * /*desktop*/, GtkActionGroup* mainActions, GObject* holder)
5674
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
5675
gint pickAlpha = prefs->getInt( "/tools/dropper/pick", 1 );
5678
EgeOutputAction* act = ege_output_action_new( "DropperOpacityAction", _("Opacity:"), "", 0 );
5679
ege_output_action_set_use_markup( act, TRUE );
5680
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
5684
InkToggleAction* act = ink_toggle_action_new( "DropperPickAlphaAction",
5686
_("Pick both the color and the alpha (transparency) under cursor; otherwise, pick only the visible color premultiplied by alpha"),
5688
Inkscape::ICON_SIZE_DECORATION );
5689
g_object_set( act, "short_label", _("Pick"), NULL );
5690
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
5691
g_object_set_data( holder, "pick_action", act );
5692
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), pickAlpha );
5693
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_dropper_pick_alpha), holder );
5697
InkToggleAction* act = ink_toggle_action_new( "DropperSetAlphaAction",
5698
_("Assign opacity"),
5699
_("If alpha was picked, assign it to selection as fill or stroke transparency"),
5701
Inkscape::ICON_SIZE_DECORATION );
5702
g_object_set( act, "short_label", _("Assign"), NULL );
5703
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
5704
g_object_set_data( holder, "set_action", act );
5705
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool( "/tools/dropper/setalpha", true) );
5706
// make sure it's disabled if we're not picking alpha
5707
gtk_action_set_sensitive( GTK_ACTION(act), pickAlpha );
5708
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_dropper_set_alpha), holder );
5713
//########################
5715
//########################
5717
// the subtools from which the toolbar is built automatically are listed in lpe-tool-context.h
5719
// this is called when the mode is changed via the toolbar (i.e., one of the subtool buttons is pressed)
5720
static void sp_lpetool_mode_changed(EgeSelectOneAction *act, GObject *tbl)
5722
using namespace Inkscape::LivePathEffect;
5724
SPDesktop *desktop = (SPDesktop *) g_object_get_data(tbl, "desktop");
5725
SPEventContext *ec = desktop->event_context;
5726
if (!SP_IS_LPETOOL_CONTEXT(ec)) {
5730
// only take action if run by the attr_changed listener
5731
if (!g_object_get_data(tbl, "freeze")) {
5732
// in turn, prevent listener from responding
5733
g_object_set_data(tbl, "freeze", GINT_TO_POINTER(TRUE));
5735
gint mode = ege_select_one_action_get_active(act);
5736
EffectType type = lpesubtools[mode].type;
5738
SPLPEToolContext *lc = SP_LPETOOL_CONTEXT(desktop->event_context);
5739
bool success = lpetool_try_construction(lc, type);
5741
// since the construction was already performed, we set the state back to inactive
5742
ege_select_one_action_set_active(act, 0);
5745
// switch to the chosen subtool
5746
SP_LPETOOL_CONTEXT(desktop->event_context)->mode = type;
5749
if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
5750
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
5751
prefs->setInt( "/tools/lpetool/mode", mode );
5754
g_object_set_data(tbl, "freeze", GINT_TO_POINTER(FALSE));
5758
static void sp_lpetool_toolbox_sel_modified(Inkscape::Selection *selection, guint /*flags*/, GObject * /*tbl*/)
5760
SPEventContext *ec = selection->desktop()->event_context;
5761
if (SP_IS_LPETOOL_CONTEXT(ec)) {
5762
lpetool_update_measuring_items(SP_LPETOOL_CONTEXT(ec));
5766
static void sp_lpetool_toolbox_sel_changed(Inkscape::Selection *selection, GObject *tbl)
5768
using namespace Inkscape::LivePathEffect;
5769
SPEventContext *ec = selection->desktop()->event_context;
5770
if (!SP_IS_LPETOOL_CONTEXT(ec)) {
5773
SPLPEToolContext *lc = SP_LPETOOL_CONTEXT(ec);
5775
lpetool_delete_measuring_items(lc);
5776
lpetool_create_measuring_items(lc, selection);
5778
// activate line segment combo box if a single item with LPELineSegment is selected
5779
GtkAction* w = GTK_ACTION(g_object_get_data(tbl, "lpetool_line_segment_action"));
5780
SPItem *item = selection->singleItem();
5781
if (item && SP_IS_LPE_ITEM(item) && lpetool_item_has_construction(lc, item)) {
5782
SPLPEItem *lpeitem = SP_LPE_ITEM(item);
5783
Effect* lpe = sp_lpe_item_get_current_lpe(lpeitem);
5784
if (lpe && lpe->effectType() == LINE_SEGMENT) {
5785
LPELineSegment *lpels = static_cast<LPELineSegment*>(lpe);
5786
g_object_set_data(tbl, "currentlpe", lpe);
5787
g_object_set_data(tbl, "currentlpeitem", lpeitem);
5788
gtk_action_set_sensitive(w, TRUE);
5789
ege_select_one_action_set_active(EGE_SELECT_ONE_ACTION(w), lpels->end_type.get_value());
5791
g_object_set_data(tbl, "currentlpe", NULL);
5792
g_object_set_data(tbl, "currentlpeitem", NULL);
5793
gtk_action_set_sensitive(w, FALSE);
5796
g_object_set_data(tbl, "currentlpe", NULL);
5797
g_object_set_data(tbl, "currentlpeitem", NULL);
5798
gtk_action_set_sensitive(w, FALSE);
5802
static void lpetool_toggle_show_bbox(GtkToggleAction *act, gpointer data) {
5803
SPDesktop *desktop = static_cast<SPDesktop *>(data);
5804
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
5806
bool show = gtk_toggle_action_get_active( act );
5807
prefs->setBool("/tools/lpetool/show_bbox", show);
5809
if (tools_isactive(desktop, TOOLS_LPETOOL)) {
5810
SPLPEToolContext *lc = SP_LPETOOL_CONTEXT(desktop->event_context);
5811
lpetool_context_reset_limiting_bbox(lc);
5815
static void lpetool_toggle_show_measuring_info(GtkToggleAction *act, GObject *tbl)
5817
SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(tbl, "desktop"));
5818
if (!tools_isactive(desktop, TOOLS_LPETOOL)) {
5822
GtkAction *unitact = static_cast<GtkAction*>(g_object_get_data(tbl, "lpetool_units_action"));
5823
SPLPEToolContext *lc = SP_LPETOOL_CONTEXT(desktop->event_context);
5824
if (tools_isactive(desktop, TOOLS_LPETOOL)) {
5825
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
5826
bool show = gtk_toggle_action_get_active( act );
5827
prefs->setBool("/tools/lpetool/show_measuring_info", show);
5828
lpetool_show_measuring_info(lc, show);
5829
gtk_action_set_sensitive(GTK_ACTION(unitact), show);
5833
static void lpetool_unit_changed(GtkAction* /*act*/, GObject* tbl)
5835
UnitTracker* tracker = reinterpret_cast<UnitTracker*>(g_object_get_data(tbl, "tracker"));
5836
SPUnit const *unit = tracker->getActiveUnit();
5837
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
5838
prefs->setInt("/tools/lpetool/unitid", unit->unit_id);
5840
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
5841
if (SP_IS_LPETOOL_CONTEXT(desktop->event_context)) {
5842
SPLPEToolContext *lc = SP_LPETOOL_CONTEXT(desktop->event_context);
5843
lpetool_delete_measuring_items(lc);
5844
lpetool_create_measuring_items(lc);
5848
static void lpetool_toggle_set_bbox(GtkToggleAction *act, gpointer data)
5850
SPDesktop *desktop = static_cast<SPDesktop *>(data);
5851
Inkscape::Selection *selection = desktop->selection;
5853
Geom::OptRect bbox = selection->bounds();
5856
Geom::Point A(bbox->min());
5857
Geom::Point B(bbox->max());
5859
A *= desktop->doc2dt();
5860
B *= desktop->doc2dt();
5862
// TODO: should we provide a way to store points in prefs?
5863
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
5864
prefs->setDouble("/tools/lpetool/bbox_upperleftx", A[Geom::X]);
5865
prefs->setDouble("/tools/lpetool/bbox_upperlefty", A[Geom::Y]);
5866
prefs->setDouble("/tools/lpetool/bbox_lowerrightx", B[Geom::X]);
5867
prefs->setDouble("/tools/lpetool/bbox_lowerrighty", B[Geom::Y]);
5869
lpetool_context_reset_limiting_bbox(SP_LPETOOL_CONTEXT(desktop->event_context));
5872
gtk_toggle_action_set_active(act, false);
5875
static void sp_line_segment_build_list(GObject *tbl)
5877
g_object_set_data(tbl, "line_segment_list_blocked", GINT_TO_POINTER(TRUE));
5879
EgeSelectOneAction* selector = static_cast<EgeSelectOneAction *>(g_object_get_data(tbl, "lpetool_line_segment_action"));
5880
GtkListStore* model = GTK_LIST_STORE(ege_select_one_action_get_model(selector));
5881
gtk_list_store_clear (model);
5883
// TODO: we add the entries of rht combo box manually; later this should be done automatically
5886
gtk_list_store_append( model, &iter );
5887
gtk_list_store_set( model, &iter, 0, _("Closed"), 1, 0, -1 );
5888
gtk_list_store_append( model, &iter );
5889
gtk_list_store_set( model, &iter, 0, _("Open start"), 1, 1, -1 );
5890
gtk_list_store_append( model, &iter );
5891
gtk_list_store_set( model, &iter, 0, _("Open end"), 1, 2, -1 );
5892
gtk_list_store_append( model, &iter );
5893
gtk_list_store_set( model, &iter, 0, _("Open both"), 1, 3, -1 );
5896
g_object_set_data(tbl, "line_segment_list_blocked", GINT_TO_POINTER(FALSE));
5899
static void sp_lpetool_change_line_segment_type(EgeSelectOneAction* act, GObject* tbl)
5901
using namespace Inkscape::LivePathEffect;
5903
// quit if run by the attr_changed listener
5904
if (g_object_get_data(tbl, "freeze")) {
5908
// in turn, prevent listener from responding
5909
g_object_set_data(tbl, "freeze", GINT_TO_POINTER(TRUE));
5911
LPELineSegment *lpe = static_cast<LPELineSegment *>(g_object_get_data(tbl, "currentlpe"));
5912
SPLPEItem *lpeitem = static_cast<SPLPEItem *>(g_object_get_data(tbl, "currentlpeitem"));
5914
SPLPEItem *lpeitem = static_cast<SPLPEItem *>(g_object_get_data(tbl, "currentlpeitem"));
5915
lpe->end_type.param_set_value(static_cast<Inkscape::LivePathEffect::EndType>(ege_select_one_action_get_active(act)));
5916
sp_lpe_item_update_patheffect(lpeitem, true, true);
5919
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
5922
static void lpetool_open_lpe_dialog(GtkToggleAction *act, gpointer data)
5924
SPDesktop *desktop = static_cast<SPDesktop *>(data);
5926
if (tools_isactive(desktop, TOOLS_LPETOOL)) {
5927
sp_action_perform(Inkscape::Verb::get(SP_VERB_DIALOG_LIVE_PATH_EFFECT)->get_action(desktop), NULL);
5929
gtk_toggle_action_set_active(act, false);
5932
static void sp_lpetool_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
5934
UnitTracker* tracker = new UnitTracker(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
5935
tracker->setActiveUnit(sp_desktop_namedview(desktop)->doc_units);
5936
g_object_set_data(holder, "tracker", tracker);
5937
SPUnit const *unit = tracker->getActiveUnit();
5939
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
5940
prefs->setInt("/tools/lpetool/unitid", unit->unit_id);
5942
/** Automatically create a list of LPEs that get added to the toolbar **/
5944
GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING );
5948
// the first toggle button represents the state that no subtool is active (remove this when
5949
// this can be modeled by EgeSelectOneAction or some other action)
5950
gtk_list_store_append( model, &iter );
5951
gtk_list_store_set( model, &iter,
5952
0, _("All inactive"),
5953
1, _("No geometric tool is active"),
5954
2, "draw-geometry-inactive",
5957
Inkscape::LivePathEffect::EffectType type;
5958
for (int i = 1; i < num_subtools; ++i) { // we start with i = 1 because INVALID_LPE was already added
5959
type = lpesubtools[i].type;
5960
gtk_list_store_append( model, &iter );
5961
gtk_list_store_set( model, &iter,
5962
0, Inkscape::LivePathEffect::LPETypeConverter.get_label(type).c_str(),
5963
1, Inkscape::LivePathEffect::LPETypeConverter.get_label(type).c_str(),
5964
2, lpesubtools[i].icon_name,
5968
EgeSelectOneAction* act = ege_select_one_action_new( "LPEToolModeAction", (""), (""), NULL, GTK_TREE_MODEL(model) );
5969
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
5970
g_object_set_data( holder, "lpetool_mode_action", act );
5972
ege_select_one_action_set_appearance( act, "full" );
5973
ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE );
5974
g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL );
5975
ege_select_one_action_set_icon_column( act, 2 );
5976
ege_select_one_action_set_tooltip_column( act, 1 );
5978
gint lpeToolMode = prefs->getInt("/tools/lpetool/mode", 0);
5979
ege_select_one_action_set_active( act, lpeToolMode );
5980
g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_lpetool_mode_changed), holder );
5983
/* Show limiting bounding box */
5985
InkToggleAction* act = ink_toggle_action_new( "LPEShowBBoxAction",
5986
_("Show limiting bounding box"),
5987
_("Show bounding box (used to cut infinite lines)"),
5988
"show-bounding-box",
5989
Inkscape::ICON_SIZE_DECORATION );
5990
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
5991
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(lpetool_toggle_show_bbox), desktop );
5992
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool( "/tools/lpetool/show_bbox", true ) );
5995
/* Set limiting bounding box to bbox of current selection */
5997
InkToggleAction* act = ink_toggle_action_new( "LPEBBoxFromSelectionAction",
5998
_("Get limiting bounding box from selection"),
5999
_("Set limiting bounding box (used to cut infinite lines) to the bounding box of current selection"),
6000
"draw-geometry-set-bounding-box",
6001
Inkscape::ICON_SIZE_DECORATION );
6002
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
6003
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(lpetool_toggle_set_bbox), desktop );
6004
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), FALSE );
6008
/* Combo box to choose line segment type */
6010
GtkListStore* model = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
6011
EgeSelectOneAction* act = ege_select_one_action_new ("LPELineSegmentAction", "" , (_("Choose a line segment type")), NULL, GTK_TREE_MODEL(model));
6012
ege_select_one_action_set_appearance (act, "compact");
6013
g_object_set_data (holder, "lpetool_line_segment_action", act );
6015
g_object_set_data(holder, "line_segment_list_blocked", GINT_TO_POINTER(FALSE));
6017
sp_line_segment_build_list (holder);
6019
g_signal_connect(G_OBJECT(act), "changed", G_CALLBACK(sp_lpetool_change_line_segment_type), holder);
6020
gtk_action_set_sensitive( GTK_ACTION(act), FALSE );
6021
gtk_action_group_add_action(mainActions, GTK_ACTION(act));
6024
/* Display measuring info for selected items */
6026
InkToggleAction* act = ink_toggle_action_new( "LPEMeasuringAction",
6027
_("Display measuring info"),
6028
_("Display measuring info for selected items"),
6029
"draw-geometry-show-measuring-info",
6030
Inkscape::ICON_SIZE_DECORATION );
6031
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
6032
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(lpetool_toggle_show_measuring_info), holder );
6033
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool( "/tools/lpetool/show_measuring_info", true ) );
6036
// add the units menu
6038
GtkAction* act = tracker->createAction( "LPEToolUnitsAction", _("Units"), ("") );
6039
gtk_action_group_add_action( mainActions, act );
6040
g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(lpetool_unit_changed), (GObject*)holder );
6041
g_object_set_data(holder, "lpetool_units_action", act);
6042
gtk_action_set_sensitive(act, prefs->getBool("/tools/lpetool/show_measuring_info", true));
6045
/* Open LPE dialog (to adapt parameters numerically) */
6047
InkToggleAction* act = ink_toggle_action_new( "LPEOpenLPEDialogAction",
6048
_("Open LPE dialog"),
6049
_("Open LPE dialog (to adapt parameters numerically)"),
6051
Inkscape::ICON_SIZE_DECORATION );
6052
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
6053
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(lpetool_open_lpe_dialog), desktop );
6054
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), FALSE );
6058
Inkscape::ConnectionPool* pool = Inkscape::ConnectionPool::new_connection_pool ("ISNodeToolbox");
6060
sigc::connection *c_selection_modified =
6061
new sigc::connection (sp_desktop_selection (desktop)->connectModified
6062
(sigc::bind (sigc::ptr_fun (sp_lpetool_toolbox_sel_modified), (GObject*)holder)));
6063
pool->add_connection ("selection-modified", c_selection_modified);
6065
sigc::connection *c_selection_changed =
6066
new sigc::connection (sp_desktop_selection (desktop)->connectChanged
6067
(sigc::bind (sigc::ptr_fun(sp_lpetool_toolbox_sel_changed), (GObject*)holder)));
6068
pool->add_connection ("selection-changed", c_selection_changed);
6071
//########################
6073
//########################
6075
static void sp_erc_width_value_changed( GtkAdjustment *adj, GObject *tbl )
6077
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6078
prefs->setDouble( "/tools/eraser/width", adj->value );
6079
update_presets_list(tbl);
6082
static void sp_erasertb_mode_changed( EgeSelectOneAction *act, GObject *tbl )
6084
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
6085
bool eraserMode = ege_select_one_action_get_active( act ) != 0;
6086
if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
6087
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6088
prefs->setBool( "/tools/eraser/mode", eraserMode );
6091
// only take action if run by the attr_changed listener
6092
if (!g_object_get_data( tbl, "freeze" )) {
6093
// in turn, prevent listener from responding
6094
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
6096
if ( eraserMode != 0 ) {
6099
// TODO finish implementation
6101
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
6105
static void sp_eraser_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
6109
gchar const* labels[] = {_("(hairline)"), 0, 0, 0, _("(default)"), 0, 0, 0, 0, _("(broad stroke)")};
6110
gdouble values[] = {1, 3, 5, 10, 15, 20, 30, 50, 75, 100};
6111
EgeAdjustmentAction *eact = create_adjustment_action( "EraserWidthAction",
6112
_("Pen Width"), _("Width:"),
6113
_("The width of the eraser pen (relative to the visible canvas area)"),
6114
"/tools/eraser/width", 15,
6115
GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "altx-eraser",
6117
labels, values, G_N_ELEMENTS(labels),
6118
sp_erc_width_value_changed, 1, 0);
6119
ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
6120
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
6121
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
6125
GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING );
6128
gtk_list_store_append( model, &iter );
6129
gtk_list_store_set( model, &iter,
6131
1, _("Delete objects touched by the eraser"),
6132
2, INKSCAPE_ICON_DRAW_ERASER_DELETE_OBJECTS,
6135
gtk_list_store_append( model, &iter );
6136
gtk_list_store_set( model, &iter,
6138
1, _("Cut out from objects"),
6139
2, INKSCAPE_ICON_PATH_DIFFERENCE,
6142
EgeSelectOneAction* act = ege_select_one_action_new( "EraserModeAction", (""), (""), NULL, GTK_TREE_MODEL(model) );
6143
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
6144
g_object_set_data( holder, "eraser_mode_action", act );
6146
ege_select_one_action_set_appearance( act, "full" );
6147
ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE );
6148
g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL );
6149
ege_select_one_action_set_icon_column( act, 2 );
6150
ege_select_one_action_set_tooltip_column( act, 1 );
6152
/// @todo Convert to boolean?
6153
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6154
gint eraserMode = prefs->getBool("/tools/eraser/mode") ? 1 : 0;
6155
ege_select_one_action_set_active( act, eraserMode );
6156
g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_erasertb_mode_changed), holder );
6161
//########################
6162
//## Text Toolbox ##
6163
//########################
6165
// Functions for debugging:
6168
static void sp_print_font( SPStyle *query ) {
6170
bool family_set = query->text->font_family.set;
6171
bool style_set = query->font_style.set;
6172
bool fontspec_set = query->text->font_specification.set;
6174
std::cout << " Family set? " << family_set
6175
<< " Style set? " << style_set
6176
<< " FontSpec set? " << fontspec_set
6178
std::cout << " Family: "
6179
<< (query->text->font_family.value ? query->text->font_family.value : "No value")
6180
<< " Style: " << query->font_style.computed
6181
<< " Weight: " << query->font_weight.computed
6183
<< (query->text->font_specification.value ? query->text->font_specification.value : "No value")
6187
static void sp_print_fontweight( SPStyle *query ) {
6188
const gchar* names[] = {"100", "200", "300", "400", "500", "600", "700", "800", "900",
6189
"NORMAL", "BOLD", "LIGHTER", "BOLDER", "Out of range"};
6190
// Missing book = 380
6191
int index = query->font_weight.computed;
6192
if( index < 0 || index > 13 ) index = 13;
6193
std::cout << " Weight: " << names[ index ]
6194
<< " (" << query->font_weight.computed << ")" << std::endl;
6198
static void sp_print_fontstyle( SPStyle *query ) {
6200
const gchar* names[] = {"NORMAL", "ITALIC", "OBLIQUE", "Out of range"};
6201
int index = query->font_style.computed;
6202
if( index < 0 || index > 3 ) index = 3;
6203
std::cout << " Style: " << names[ index ] << std::endl;
6208
// Format family drop-down menu.
6209
static void cell_data_func(GtkCellLayout * /*cell_layout*/,
6210
GtkCellRenderer *cell,
6211
GtkTreeModel *tree_model,
6216
gtk_tree_model_get(tree_model, iter, 0, &family, -1);
6217
gchar *const family_escaped = g_markup_escape_text(family, -1);
6219
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6220
int show_sample = prefs->getInt("/tools/text/show_sample_in_list", 1);
6223
Glib::ustring sample = prefs->getString("/tools/text/font_sample");
6224
gchar *const sample_escaped = g_markup_escape_text(sample.data(), -1);
6226
std::stringstream markup;
6227
markup << family_escaped << " <span foreground='gray' font_family='"
6228
<< family_escaped << "'>" << sample_escaped << "</span>";
6229
g_object_set (G_OBJECT (cell), "markup", markup.str().c_str(), NULL);
6231
g_free(sample_escaped);
6233
g_object_set (G_OBJECT (cell), "markup", family_escaped, NULL);
6235
// This doesn't work for two reasons... it set both selected and not selected backgrounds
6236
// to white.. which means that white foreground text is invisible. It also only effects
6237
// the text region, leaving the padding untouched.
6238
// g_object_set (G_OBJECT (cell), "cell-background", "white", "cell-background-set", true, NULL);
6241
g_free(family_escaped);
6245
static void sp_text_fontfamily_value_changed( Ink_ComboBoxEntry_Action *act, GObject *tbl )
6248
std::cout << std::endl;
6249
std::cout << "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM" << std::endl;
6250
std::cout << "sp_text_fontfamily_value_changed: " << std::endl;
6253
// quit if run by the _changed callbacks
6254
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
6257
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
6259
gchar *family = ink_comboboxentry_action_get_active_text( act );
6261
std::cout << " New family: " << family << std::endl;
6264
// First try to get the old font spec from the stored value
6265
SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
6266
int result_fontspec = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
6268
Glib::ustring fontSpec = query->text->font_specification.set ? query->text->font_specification.value : "";
6270
// If that didn't work, try to get font spec from style
6271
if (fontSpec.empty()) {
6273
// Must query all to fill font-family, font-style, font-weight, font-specification
6274
sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
6275
sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
6276
sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
6278
// Construct a new font specification if it does not yet exist
6279
font_instance * fontFromStyle = font_factory::Default()->FaceFromStyle(query);
6280
if( fontFromStyle ) {
6281
fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle);
6282
fontFromStyle->Unref();
6285
std::cout << " Fontspec not defined, reconstructed from style :" << fontSpec << ":" << std::endl;
6286
sp_print_font( query );
6290
// And if that didn't work use default
6291
if( fontSpec.empty() ) {
6292
sp_style_read_from_prefs(query, "/tools/text");
6294
std::cout << " read style from prefs:" << std::endl;
6295
sp_print_font( query );
6297
// Construct a new font specification if it does not yet exist
6298
font_instance * fontFromStyle = font_factory::Default()->FaceFromStyle(query);
6299
if( fontFromStyle ) {
6300
fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle);
6301
fontFromStyle->Unref();
6304
std::cout << " Fontspec not defined, reconstructed from style :" << fontSpec << ":" << std::endl;
6305
sp_print_font( query );
6309
SPCSSAttr *css = sp_repr_css_attr_new ();
6310
if (!fontSpec.empty()) {
6312
// Now we have a font specification, replace family.
6313
Glib::ustring newFontSpec = font_factory::Default()->ReplaceFontSpecificationFamily(fontSpec, family);
6316
std::cout << " New FontSpec from ReplaceFontSpecificationFamily :" << newFontSpec << ":" << std::endl;
6319
if (!newFontSpec.empty()) {
6321
if (fontSpec != newFontSpec) {
6323
font_instance *font = font_factory::Default()->FaceFromFontSpecification(newFontSpec.c_str());
6326
sp_repr_css_set_property (css, "-inkscape-font-specification", newFontSpec.c_str());
6328
// Set all the these just in case they were altered when finding the best
6329
// match for the new family and old style...
6333
font->Family(c, 256);
6335
sp_repr_css_set_property (css, "font-family", c);
6337
font->Attribute( "weight", c, 256);
6338
sp_repr_css_set_property (css, "font-weight", c);
6340
font->Attribute("style", c, 256);
6341
sp_repr_css_set_property (css, "font-style", c);
6343
font->Attribute("stretch", c, 256);
6344
sp_repr_css_set_property (css, "font-stretch", c);
6346
font->Attribute("variant", c, 256);
6347
sp_repr_css_set_property (css, "font-variant", c);
6355
// newFontSpec empty
6356
// If the old font on selection (or default) does not exist on the system,
6357
// or the new font family does not exist,
6358
// ReplaceFontSpecificationFamily does not work. In that case we fall back to blindly
6359
// setting the family reported by the family chooser.
6361
// g_print ("fallback setting family: %s\n", family);
6362
sp_repr_css_set_property (css, "-inkscape-font-specification", family);
6363
sp_repr_css_set_property (css, "font-family", family);
6364
// Shoud we set other css font attributes?
6367
} // fontSpec not empty or not
6369
// If querying returned nothing, update default style.
6370
if (result_fontspec == QUERY_STYLE_NOTHING)
6372
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6373
prefs->mergeStyle("/tools/text/style", css);
6374
sp_text_edit_dialog_default_set_insensitive (); //FIXME: Replace through a verb
6378
sp_desktop_set_style (SP_ACTIVE_DESKTOP, css, true, true);
6381
sp_style_unref(query);
6386
if (result_fontspec != QUERY_STYLE_NOTHING) {
6387
sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
6388
_("Text: Change font family"));
6390
sp_repr_css_attr_unref (css);
6393
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
6396
gtk_widget_grab_focus (GTK_WIDGET((SP_ACTIVE_DESKTOP)->canvas));
6399
std::cout << "sp_text_toolbox_fontfamily_changes: exit" << std::endl;
6400
std::cout << "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM" << std::endl;
6401
std::cout << std::endl;
6406
static void sp_text_fontsize_value_changed( Ink_ComboBoxEntry_Action *act, GObject *tbl )
6408
// quit if run by the _changed callbacks
6409
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
6412
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
6414
gchar *text = ink_comboboxentry_action_get_active_text( act );
6416
gdouble size = g_strtod( text, &endptr );
6417
if (endptr == text) { // Conversion failed, non-numeric input.
6418
g_warning( "Conversion of size text to double failed, input: %s\n", text );
6424
// Set css font size.
6425
SPCSSAttr *css = sp_repr_css_attr_new ();
6426
Inkscape::CSSOStringStream osfs;
6427
osfs << size << "px"; // For now always use px
6428
sp_repr_css_set_property (css, "font-size", osfs.str().c_str());
6430
// Apply font size to selected objects.
6431
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
6432
sp_desktop_set_style (desktop, css, true, true);
6434
// If no selected objects, set default.
6435
SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
6436
int result_numbers =
6437
sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
6438
if (result_numbers == QUERY_STYLE_NOTHING)
6440
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6441
prefs->mergeStyle("/tools/text/style", css);
6444
sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:size", SP_VERB_NONE,
6445
_("Text: Change font size"));
6448
sp_style_unref(query);
6450
sp_repr_css_attr_unref (css);
6452
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
6455
// Handles both Bold and Italic/Oblique
6456
static void sp_text_style_changed( InkToggleAction* act, GObject *tbl )
6458
// quit if run by the _changed callbacks
6459
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
6462
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
6464
// Called by Bold or Italics button?
6465
const gchar* name = gtk_action_get_name( GTK_ACTION( act ) );
6466
gint prop = (strcmp(name, "TextBoldAction") == 0) ? 0 : 1;
6468
// First query font-specification, this is the most complete font face description.
6469
SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
6470
int result_fontspec = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
6472
// font_specification will not be set unless defined explicitely on a tspan.
6473
// This should be fixed!
6474
Glib::ustring fontSpec = query->text->font_specification.set ? query->text->font_specification.value : "";
6476
if (fontSpec.empty()) {
6477
// Construct a new font specification if it does not yet exist
6478
// Must query font-family, font-style, font-weight, to find correct font face.
6479
sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
6480
sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
6481
sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
6483
font_instance * fontFromStyle = font_factory::Default()->FaceFromStyle(query);
6484
if( fontFromStyle ) {
6485
fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle);
6486
fontFromStyle->Unref();
6490
// Now that we have the old face, find the new face.
6491
Glib::ustring newFontSpec = "";
6492
SPCSSAttr *css = sp_repr_css_attr_new ();
6493
gboolean nochange = true;
6494
gboolean active = gtk_toggle_action_get_active( GTK_TOGGLE_ACTION(act) );
6501
if (!fontSpec.empty()) {
6503
newFontSpec = font_factory::Default()->FontSpecificationSetBold(fontSpec, active);
6505
if (!newFontSpec.empty()) {
6507
// Set weight if we found font.
6508
font_instance * font = font_factory::Default()->FaceFromFontSpecification(newFontSpec.c_str());
6511
font->Attribute( "weight", c, 256);
6512
sp_repr_css_set_property (css, "font-weight", c);
6519
// Reset button if no change.
6520
// The reset code didn't work in 0.47 and doesn't here... one must prevent an infinite loop
6523
gtk_action_block_activate( GTK_ACTION(act) );
6524
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), !active );
6525
gtk_action_unblock_activate( GTK_ACTION(act) );
6534
if (!fontSpec.empty()) {
6536
newFontSpec = font_factory::Default()->FontSpecificationSetItalic(fontSpec, active);
6538
if (!newFontSpec.empty()) {
6540
// Don't even set the italic/oblique if the font didn't exist on the system
6542
if( newFontSpec.find( "Italic" ) != Glib::ustring::npos ) {
6543
sp_repr_css_set_property (css, "font-style", "italic");
6545
sp_repr_css_set_property (css, "font-style", "oblique");
6548
sp_repr_css_set_property (css, "font-style", "normal");
6553
// Reset button if no change.
6554
// The reset code didn't work in 0.47... one must prevent an infinite loop
6557
gtk_action_block_activate( GTK_ACTION(act) );
6558
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), !active );
6559
gtk_action_unblock_activate( GTK_ACTION(act) );
6566
if (!newFontSpec.empty()) {
6567
sp_repr_css_set_property (css, "-inkscape-font-specification", newFontSpec.c_str());
6570
// If querying returned nothing, update default style.
6571
if (result_fontspec == QUERY_STYLE_NOTHING)
6573
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6574
prefs->mergeStyle("/tools/text/style", css);
6577
sp_style_unref(query);
6579
// Do we need to update other CSS values?
6580
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
6581
sp_desktop_set_style (desktop, css, true, true);
6582
if (result_fontspec != QUERY_STYLE_NOTHING) {
6583
sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
6584
_("Text: Change font style"));
6586
sp_repr_css_attr_unref (css);
6588
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
6591
// Handles both Superscripts and Subscripts
6592
static void sp_text_script_changed( InkToggleAction* act, GObject *tbl )
6594
// quit if run by the _changed callbacks
6595
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
6598
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
6600
// Called by Superscript or Subscript button?
6601
const gchar* name = gtk_action_get_name( GTK_ACTION( act ) );
6602
gint prop = (strcmp(name, "TextSuperscriptAction") == 0) ? 0 : 1;
6605
std::cout << "sp_text_script_changed: " << prop << std::endl;
6609
SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
6610
int result_baseline = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_BASELINES);
6612
bool setSuper = false;
6613
bool setSub = false;
6615
if(result_baseline == QUERY_STYLE_NOTHING || result_baseline == QUERY_STYLE_MULTIPLE_DIFFERENT ) {
6616
// If not set or mixed, turn on superscript or subscript
6624
gboolean superscriptSet = (query->baseline_shift.set &&
6625
query->baseline_shift.type == SP_BASELINE_SHIFT_LITERAL &&
6626
query->baseline_shift.literal == SP_CSS_BASELINE_SHIFT_SUPER );
6629
gboolean subscriptSet = (query->baseline_shift.set &&
6630
query->baseline_shift.type == SP_BASELINE_SHIFT_LITERAL &&
6631
query->baseline_shift.literal == SP_CSS_BASELINE_SHIFT_SUB );
6633
setSuper = !superscriptSet && prop == 0;
6634
setSub = !subscriptSet && prop == 1;
6637
// Set css properties
6638
SPCSSAttr *css = sp_repr_css_attr_new ();
6639
if( setSuper || setSub ) {
6640
// Openoffice 2.3 and Adobe use 58%, Microsoft Word 2002 uses 65%, LaTex about 70%.
6641
// 58% looks too small to me, especially if a superscript is placed on a superscript.
6642
// If you make a change here, consider making a change to baseline-shift amount
6644
sp_repr_css_set_property (css, "font-size", "65%");
6646
sp_repr_css_set_property (css, "font-size", "");
6649
sp_repr_css_set_property (css, "baseline-shift", "super");
6650
} else if( setSub ) {
6651
sp_repr_css_set_property (css, "baseline-shift", "sub");
6653
sp_repr_css_set_property (css, "baseline-shift", "baseline");
6656
// Apply css to selected objects.
6657
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
6658
sp_desktop_set_style (desktop, css, true, false);
6661
if(result_baseline != QUERY_STYLE_NOTHING) {
6662
sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:script", SP_VERB_NONE,
6663
_("Text: Change superscript or subscript"));
6665
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
6668
static void sp_text_align_mode_changed( EgeSelectOneAction *act, GObject *tbl )
6670
// quit if run by the _changed callbacks
6671
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
6674
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
6676
int mode = ege_select_one_action_get_active( act );
6678
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6679
prefs->setInt("/tools/text/align_mode", mode);
6681
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
6683
// move the x of all texts to preserve the same bbox
6684
Inkscape::Selection *selection = sp_desktop_selection(desktop);
6685
for (GSList const *items = selection->itemList(); items != NULL; items = items->next) {
6686
if (SP_IS_TEXT((SPItem *) items->data)) {
6687
SPItem *item = SP_ITEM(items->data);
6689
unsigned writing_mode = SP_OBJECT_STYLE(item)->writing_mode.value;
6690
// below, variable names suggest horizontal move, but we check the writing direction
6691
// and move in the corresponding axis
6693
if (writing_mode == SP_CSS_WRITING_MODE_LR_TB || writing_mode == SP_CSS_WRITING_MODE_RL_TB) {
6700
= item->getBounds(Geom::identity(), SPItem::GEOMETRIC_BBOX);
6703
double width = bbox->dimensions()[axis];
6704
// If you want to align within some frame, other than the text's own bbox, calculate
6705
// the left and right (or top and bottom for tb text) slacks of the text inside that
6706
// frame (currently unused)
6707
double left_slack = 0;
6708
double right_slack = 0;
6709
unsigned old_align = SP_OBJECT_STYLE(item)->text_align.value;
6711
if (old_align == SP_CSS_TEXT_ALIGN_START || old_align == SP_CSS_TEXT_ALIGN_LEFT) {
6717
move = width/2 + (right_slack - left_slack)/2;
6720
move = width + right_slack;
6723
} else if (old_align == SP_CSS_TEXT_ALIGN_CENTER) {
6726
move = -width/2 - left_slack;
6729
move = (right_slack - left_slack)/2;
6732
move = width/2 + right_slack;
6735
} else if (old_align == SP_CSS_TEXT_ALIGN_END || old_align == SP_CSS_TEXT_ALIGN_RIGHT) {
6738
move = -width - left_slack;
6741
move = -width/2 + (right_slack - left_slack)/2;
6748
Geom::Point XY = SP_TEXT(item)->attributes.firstXY();
6749
if (axis == NR::X) {
6750
XY = XY + Geom::Point (move, 0);
6752
XY = XY + Geom::Point (0, move);
6754
SP_TEXT(item)->attributes.setFirstXY(XY);
6755
SP_OBJECT(item)->updateRepr();
6756
SP_OBJECT(item)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
6760
SPCSSAttr *css = sp_repr_css_attr_new ();
6765
sp_repr_css_set_property (css, "text-anchor", "start");
6766
sp_repr_css_set_property (css, "text-align", "start");
6771
sp_repr_css_set_property (css, "text-anchor", "middle");
6772
sp_repr_css_set_property (css, "text-align", "center");
6778
sp_repr_css_set_property (css, "text-anchor", "end");
6779
sp_repr_css_set_property (css, "text-align", "end");
6785
sp_repr_css_set_property (css, "text-anchor", "start");
6786
sp_repr_css_set_property (css, "text-align", "justify");
6792
sp_style_new (SP_ACTIVE_DOCUMENT);
6793
int result_numbers =
6794
sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
6796
// If querying returned nothing, update default style.
6797
if (result_numbers == QUERY_STYLE_NOTHING)
6799
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6800
prefs->mergeStyle("/tools/text/style", css);
6803
sp_style_unref(query);
6805
sp_desktop_set_style (desktop, css, true, true);
6806
if (result_numbers != QUERY_STYLE_NOTHING)
6808
sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
6809
_("Text: Change alignment"));
6811
sp_repr_css_attr_unref (css);
6813
gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
6815
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
6818
static void sp_text_lineheight_value_changed( GtkAdjustment *adj, GObject *tbl )
6820
// quit if run by the _changed callbacks
6821
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
6824
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
6826
// At the moment this handles only numerical values (i.e. no percent).
6827
// Set css line height.
6828
SPCSSAttr *css = sp_repr_css_attr_new ();
6829
Inkscape::CSSOStringStream osfs;
6830
osfs << adj->value*100 << "%";
6831
sp_repr_css_set_property (css, "line-height", osfs.str().c_str());
6833
// Apply line-height to selected objects.
6834
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
6835
sp_desktop_set_style (desktop, css, true, false);
6838
// Until deprecated sodipodi:linespacing purged:
6839
Inkscape::Selection *selection = sp_desktop_selection(desktop);
6840
GSList const *items = selection->itemList();
6841
bool modmade = false;
6842
for (; items != NULL; items = items->next) {
6843
if (SP_IS_TEXT (items->data)) {
6844
SP_OBJECT_REPR(items->data)->setAttribute("sodipodi:linespacing", sp_repr_css_property (css, "line-height", NULL));
6851
sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:line-height", SP_VERB_NONE,
6852
_("Text: Change line-height"));
6855
// If no selected objects, set default.
6856
SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
6857
int result_numbers =
6858
sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
6859
if (result_numbers == QUERY_STYLE_NOTHING)
6861
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6862
prefs->mergeStyle("/tools/text/style", css);
6864
sp_style_unref(query);
6866
sp_repr_css_attr_unref (css);
6868
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
6871
static void sp_text_wordspacing_value_changed( GtkAdjustment *adj, GObject *tbl )
6873
// quit if run by the _changed callbacks
6874
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
6877
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
6879
// At the moment this handles only numerical values (i.e. no em unit).
6880
// Set css word-spacing
6881
SPCSSAttr *css = sp_repr_css_attr_new ();
6882
Inkscape::CSSOStringStream osfs;
6883
osfs << adj->value << "px"; // For now always use px
6884
sp_repr_css_set_property (css, "word-spacing", osfs.str().c_str());
6886
// Apply word-spacing to selected objects.
6887
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
6888
sp_desktop_set_style (desktop, css, true, false);
6890
// If no selected objects, set default.
6891
SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
6892
int result_numbers =
6893
sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
6894
if (result_numbers == QUERY_STYLE_NOTHING)
6896
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6897
prefs->mergeStyle("/tools/text/style", css);
6900
sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:word-spacing", SP_VERB_NONE,
6901
_("Text: Change word-spacing"));
6903
sp_style_unref(query);
6905
sp_repr_css_attr_unref (css);
6907
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
6910
static void sp_text_letterspacing_value_changed( GtkAdjustment *adj, GObject *tbl )
6912
// quit if run by the _changed callbacks
6913
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
6916
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
6918
// At the moment this handles only numerical values (i.e. no em unit).
6919
// Set css letter-spacing
6920
SPCSSAttr *css = sp_repr_css_attr_new ();
6921
Inkscape::CSSOStringStream osfs;
6922
osfs << adj->value << "px"; // For now always use px
6923
sp_repr_css_set_property (css, "letter-spacing", osfs.str().c_str());
6925
// Apply letter-spacing to selected objects.
6926
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
6927
sp_desktop_set_style (desktop, css, true, false);
6930
// If no selected objects, set default.
6931
SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
6932
int result_numbers =
6933
sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
6934
if (result_numbers == QUERY_STYLE_NOTHING)
6936
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6937
prefs->mergeStyle("/tools/text/style", css);
6942
sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:letter-spacing", SP_VERB_NONE,
6943
_("Text: Change letter-spacing"));
6946
sp_style_unref(query);
6948
sp_repr_css_attr_unref (css);
6950
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
6954
static void sp_text_dx_value_changed( GtkAdjustment *adj, GObject *tbl )
6956
// quit if run by the _changed callbacks
6957
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
6960
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
6962
gdouble new_dx = adj->value;
6963
bool modmade = false;
6965
if( SP_IS_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context) ) {
6966
SPTextContext *const tc = SP_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context);
6968
unsigned char_index = -1;
6969
TextTagAttributes *attributes =
6970
text_tag_attributes_at_position( tc->text, std::min(tc->text_sel_start, tc->text_sel_end), &char_index );
6972
double old_dx = attributes->getDx( char_index );
6973
double delta_dx = new_dx - old_dx;
6974
sp_te_adjust_dx( tc->text, tc->text_sel_start, tc->text_sel_end, SP_ACTIVE_DESKTOP, delta_dx );
6982
sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:dx", SP_VERB_NONE,
6983
_("Text: Change dx (kern)"));
6985
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
6988
static void sp_text_dy_value_changed( GtkAdjustment *adj, GObject *tbl )
6990
// quit if run by the _changed callbacks
6991
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
6994
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
6996
gdouble new_dy = adj->value;
6997
bool modmade = false;
6999
if( SP_IS_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context) ) {
7000
SPTextContext *const tc = SP_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context);
7002
unsigned char_index = -1;
7003
TextTagAttributes *attributes =
7004
text_tag_attributes_at_position( tc->text, std::min(tc->text_sel_start, tc->text_sel_end), &char_index );
7006
double old_dy = attributes->getDy( char_index );
7007
double delta_dy = new_dy - old_dy;
7008
sp_te_adjust_dy( tc->text, tc->text_sel_start, tc->text_sel_end, SP_ACTIVE_DESKTOP, delta_dy );
7016
sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:dy", SP_VERB_NONE,
7017
_("Text: Change dy"));
7020
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
7023
static void sp_text_rotation_value_changed( GtkAdjustment *adj, GObject *tbl )
7025
// quit if run by the _changed callbacks
7026
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
7029
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
7031
gdouble new_degrees = adj->value;
7033
bool modmade = false;
7034
if( SP_IS_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context) ) {
7035
SPTextContext *const tc = SP_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context);
7037
unsigned char_index = -1;
7038
TextTagAttributes *attributes =
7039
text_tag_attributes_at_position( tc->text, std::min(tc->text_sel_start, tc->text_sel_end), &char_index );
7041
double old_degrees = attributes->getRotate( char_index );
7042
double delta_deg = new_degrees - old_degrees;
7043
sp_te_adjust_rotation( tc->text, tc->text_sel_start, tc->text_sel_end, SP_ACTIVE_DESKTOP, delta_deg );
7051
sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "ttb:rotate", SP_VERB_NONE,
7052
_("Text: Change rotate"));
7055
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
7058
static void sp_text_orientation_mode_changed( EgeSelectOneAction *act, GObject *tbl )
7060
// quit if run by the _changed callbacks
7061
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
7064
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
7066
int mode = ege_select_one_action_get_active( act );
7068
SPCSSAttr *css = sp_repr_css_attr_new ();
7073
sp_repr_css_set_property (css, "writing-mode", "lr");
7079
sp_repr_css_set_property (css, "writing-mode", "tb");
7085
sp_style_new (SP_ACTIVE_DOCUMENT);
7086
int result_numbers =
7087
sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
7089
// If querying returned nothing, update default style.
7090
if (result_numbers == QUERY_STYLE_NOTHING)
7092
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
7093
prefs->mergeStyle("/tools/text/style", css);
7096
sp_desktop_set_style (SP_ACTIVE_DESKTOP, css, true, true);
7097
if(result_numbers != QUERY_STYLE_NOTHING)
7099
sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
7100
_("Text: Change orientation"));
7102
sp_repr_css_attr_unref (css);
7104
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
7108
* This function sets up the text-tool tool-controls, setting the entry boxes
7109
* etc. to the values from the current selection or the default if no selection.
7110
* It is called whenever a text selection is changed, including stepping cursor
7113
static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/, GObject *tbl)
7116
static int count = 0;
7118
std::cout << std::endl;
7119
std::cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << std::endl;
7120
std::cout << "sp_text_toolbox_selection_changed: start " << count << std::endl;
7122
std::cout << " Selected items:" << std::endl;
7123
for (GSList const *items = sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList();
7125
items = items->next)
7127
const gchar* id = SP_OBJECT_ID((SPItem *) items->data);
7128
std::cout << " " << id << std::endl;
7130
Glib::ustring selected_text = sp_text_get_selected_text((SP_ACTIVE_DESKTOP)->event_context);
7131
std::cout << " Selected text:" << std::endl;
7132
std::cout << selected_text << std::endl;
7135
// quit if run by the _changed callbacks
7136
if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
7138
std::cout << " Frozen, returning" << std::endl;
7139
std::cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << std::endl;
7140
std::cout << std::endl;
7144
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
7146
// Only flowed text can be justified, only normal text can be kerned...
7147
// Find out if we have flowed text now so we can use it several places
7148
gboolean isFlow = false;
7149
for (GSList const *items = sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList();
7151
items = items->next) {
7152
// const gchar* id = SP_OBJECT_ID((SPItem *) items->data);
7153
// std::cout << " " << id << std::endl;
7154
if( SP_IS_FLOWTEXT(( SPItem *) items->data )) {
7156
// std::cout << " Found flowed text" << std::endl;
7162
* Query from current selection:
7163
* Font family (font-family)
7164
* Style (font-weight, font-style, font-stretch, font-variant, font-align)
7165
* Numbers (font-size, letter-spacing, word-spacing, line-height, text-anchor, writing-mode)
7166
* Font specification (Inkscape private attribute)
7169
sp_style_new (SP_ACTIVE_DOCUMENT);
7170
int result_family = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
7171
int result_style = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
7172
int result_numbers = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
7173
int result_baseline = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_BASELINES);
7176
sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
7179
* If no text in selection (querying returned nothing), read the style from
7180
* the /tools/text preferencess (default style for new texts). Return if
7181
* tool bar already set to these preferences.
7183
if (result_family == QUERY_STYLE_NOTHING || result_style == QUERY_STYLE_NOTHING || result_numbers == QUERY_STYLE_NOTHING) {
7184
// There are no texts in selection, read from preferences.
7185
sp_style_read_from_prefs(query, "/tools/text");
7187
std::cout << " read style from prefs:" << std::endl;
7188
sp_print_font( query );
7190
if (g_object_get_data(tbl, "text_style_from_prefs")) {
7191
// Do not reset the toolbar style from prefs if we already did it last time
7192
sp_style_unref(query);
7193
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
7195
std::cout << " text_style_from_prefs: toolbar already set" << std:: endl;
7196
std::cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << std::endl;
7197
std::cout << std::endl;
7202
g_object_set_data(tbl, "text_style_from_prefs", GINT_TO_POINTER(TRUE));
7204
g_object_set_data(tbl, "text_style_from_prefs", GINT_TO_POINTER(FALSE));
7207
// If we have valid query data for text (font-family, font-specification) set toolbar accordingly.
7211
if( query->text->font_family.value ) {
7212
gchar *fontFamily = query->text->font_family.value;
7214
Ink_ComboBoxEntry_Action* fontFamilyAction =
7215
INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontFamilyAction" ) );
7216
ink_comboboxentry_action_set_active_text( fontFamilyAction, fontFamily );
7220
// Size (average of text selected)
7221
double size = query->font_size.computed;
7222
gchar size_text[G_ASCII_DTOSTR_BUF_SIZE];
7223
g_ascii_dtostr (size_text, sizeof (size_text), size);
7225
Ink_ComboBoxEntry_Action* fontSizeAction =
7226
INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontSizeAction" ) );
7227
ink_comboboxentry_action_set_active_text( fontSizeAction, size_text );
7231
// Note: in the enumeration, normal and lighter come at the end so we must explicitly test for them.
7232
gboolean boldSet = ((query->font_weight.computed >= SP_CSS_FONT_WEIGHT_700) &&
7233
(query->font_weight.computed != SP_CSS_FONT_WEIGHT_NORMAL) &&
7234
(query->font_weight.computed != SP_CSS_FONT_WEIGHT_LIGHTER));
7236
InkToggleAction* textBoldAction = INK_TOGGLE_ACTION( g_object_get_data( tbl, "TextBoldAction" ) );
7237
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(textBoldAction), boldSet );
7240
// Style (Italic/Oblique)
7241
gboolean italicSet = (query->font_style.computed != SP_CSS_FONT_STYLE_NORMAL);
7243
InkToggleAction* textItalicAction = INK_TOGGLE_ACTION( g_object_get_data( tbl, "TextItalicAction" ) );
7244
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(textItalicAction), italicSet );
7248
gboolean superscriptSet =
7249
((result_baseline == QUERY_STYLE_SINGLE || result_baseline == QUERY_STYLE_MULTIPLE_SAME ) &&
7250
query->baseline_shift.set &&
7251
query->baseline_shift.type == SP_BASELINE_SHIFT_LITERAL &&
7252
query->baseline_shift.literal == SP_CSS_BASELINE_SHIFT_SUPER );
7254
InkToggleAction* textSuperscriptAction = INK_TOGGLE_ACTION( g_object_get_data( tbl, "TextSuperscriptAction" ) );
7255
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(textSuperscriptAction), superscriptSet );
7259
gboolean subscriptSet =
7260
((result_baseline == QUERY_STYLE_SINGLE || result_baseline == QUERY_STYLE_MULTIPLE_SAME ) &&
7261
query->baseline_shift.set &&
7262
query->baseline_shift.type == SP_BASELINE_SHIFT_LITERAL &&
7263
query->baseline_shift.literal == SP_CSS_BASELINE_SHIFT_SUB );
7265
InkToggleAction* textSubscriptAction = INK_TOGGLE_ACTION( g_object_get_data( tbl, "TextSubscriptAction" ) );
7266
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(textSubscriptAction), subscriptSet );
7270
EgeSelectOneAction* textAlignAction = EGE_SELECT_ONE_ACTION( g_object_get_data( tbl, "TextAlignAction" ) );
7272
// Note: SVG 1.1 doesn't include text-align, SVG 1.2 Tiny doesn't include text-align="justify"
7273
// text-align="justify" was a draft SVG 1.2 item (along with flowed text).
7274
// Only flowed text can be left and right justified at the same time.
7275
// Disable button if we don't have flowed text.
7277
// The GtkTreeModel class doesn't have a set function so we can't
7278
// simply add an ege_select_one_action_set_sensitive method!
7279
// We must set values directly with the GtkListStore and then
7280
// ask that the GtkAction update the sensitive parameters.
7281
GtkListStore * model = GTK_LIST_STORE( ege_select_one_action_get_model( textAlignAction ) );
7282
GtkTreePath * path = gtk_tree_path_new_from_string("3"); // Justify entry
7284
gtk_tree_model_get_iter( GTK_TREE_MODEL (model), &iter, path );
7285
gtk_list_store_set( model, &iter, /* column */ 3, isFlow, -1 );
7286
ege_select_one_action_update_sensitive( textAlignAction );
7287
// ege_select_one_action_set_sensitive( textAlignAction, 3, isFlow );
7289
int activeButton = 0;
7290
if (query->text_align.computed == SP_CSS_TEXT_ALIGN_JUSTIFY)
7294
if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_START) activeButton = 0;
7295
if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_MIDDLE) activeButton = 1;
7296
if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_END) activeButton = 2;
7298
ege_select_one_action_set_active( textAlignAction, activeButton );
7301
// Line height (spacing)
7303
if (query->line_height.normal) {
7304
height = Inkscape::Text::Layout::LINE_HEIGHT_NORMAL;
7306
if (query->line_height.unit == SP_CSS_UNIT_PERCENT) {
7307
height = query->line_height.value;
7309
height = query->line_height.computed;
7313
GtkAction* lineHeightAction = GTK_ACTION( g_object_get_data( tbl, "TextLineHeightAction" ) );
7314
GtkAdjustment *lineHeightAdjustment =
7315
ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION( lineHeightAction ));
7316
gtk_adjustment_set_value( lineHeightAdjustment, height );
7321
if (query->word_spacing.normal) wordSpacing = 0.0;
7322
else wordSpacing = query->word_spacing.computed; // Assume no units (change in desktop-style.cpp)
7324
GtkAction* wordSpacingAction = GTK_ACTION( g_object_get_data( tbl, "TextWordSpacingAction" ) );
7325
GtkAdjustment *wordSpacingAdjustment =
7326
ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION( wordSpacingAction ));
7327
gtk_adjustment_set_value( wordSpacingAdjustment, wordSpacing );
7331
double letterSpacing;
7332
if (query->letter_spacing.normal) letterSpacing = 0.0;
7333
else letterSpacing = query->letter_spacing.computed; // Assume no units (change in desktop-style.cpp)
7335
GtkAction* letterSpacingAction = GTK_ACTION( g_object_get_data( tbl, "TextLetterSpacingAction" ) );
7336
GtkAdjustment *letterSpacingAdjustment =
7337
ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION( letterSpacingAction ));
7338
gtk_adjustment_set_value( letterSpacingAdjustment, letterSpacing );
7342
int activeButton2 = (query->writing_mode.computed == SP_CSS_WRITING_MODE_LR_TB ? 0 : 1);
7344
EgeSelectOneAction* textOrientationAction =
7345
EGE_SELECT_ONE_ACTION( g_object_get_data( tbl, "TextOrientationAction" ) );
7346
ege_select_one_action_set_active( textOrientationAction, activeButton2 );
7349
} // if( query->text )
7352
std::cout << " GUI: fontfamily.value: "
7353
<< (query->text->font_family.value ? query->text->font_family.value : "No value")
7355
std::cout << " GUI: font_size.computed: " << query->font_size.computed << std::endl;
7356
std::cout << " GUI: font_weight.computed: " << query->font_weight.computed << std::endl;
7357
std::cout << " GUI: font_style.computed: " << query->font_style.computed << std::endl;
7358
std::cout << " GUI: text_anchor.computed: " << query->text_anchor.computed << std::endl;
7359
std::cout << " GUI: text_align.computed: " << query->text_align.computed << std::endl;
7360
std::cout << " GUI: line_height.computed: " << query->line_height.computed
7361
<< " line_height.value: " << query->line_height.value
7362
<< " line_height.unit: " << query->line_height.unit << std::endl;
7363
std::cout << " GUI: word_spacing.computed: " << query->word_spacing.computed
7364
<< " word_spacing.value: " << query->word_spacing.value
7365
<< " word_spacing.unit: " << query->word_spacing.unit << std::endl;
7366
std::cout << " GUI: letter_spacing.computed: " << query->letter_spacing.computed
7367
<< " letter_spacing.value: " << query->letter_spacing.value
7368
<< " letter_spacing.unit: " << query->letter_spacing.unit << std::endl;
7369
std::cout << " GUI: writing_mode.computed: " << query->writing_mode.computed << std::endl;
7372
sp_style_unref(query);
7374
// Kerning (xshift), yshift, rotation. NB: These are not CSS attributes.
7375
if( SP_IS_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context) ) {
7376
SPTextContext *const tc = SP_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context);
7378
unsigned char_index = -1;
7379
TextTagAttributes *attributes =
7380
text_tag_attributes_at_position( tc->text, std::min(tc->text_sel_start, tc->text_sel_end), &char_index );
7384
double dx = attributes->getDx( char_index );
7385
GtkAction* dxAction = GTK_ACTION( g_object_get_data( tbl, "TextDxAction" ));
7386
GtkAdjustment *dxAdjustment =
7387
ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION( dxAction ));
7388
gtk_adjustment_set_value( dxAdjustment, dx );
7391
double dy = attributes->getDy( char_index );
7392
GtkAction* dyAction = GTK_ACTION( g_object_get_data( tbl, "TextDyAction" ));
7393
GtkAdjustment *dyAdjustment =
7394
ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION( dyAction ));
7395
gtk_adjustment_set_value( dyAdjustment, dy );
7398
double rotation = attributes->getRotate( char_index );
7399
/* SVG value is between 0 and 360 but we're using -180 to 180 in widget */
7400
if( rotation > 180.0 ) rotation -= 360.0;
7401
GtkAction* rotationAction = GTK_ACTION( g_object_get_data( tbl, "TextRotationAction" ));
7402
GtkAdjustment *rotationAdjustment =
7403
ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION( rotationAction ));
7404
gtk_adjustment_set_value( rotationAdjustment, rotation );
7407
std::cout << " GUI: Dx: " << dx << std::endl;
7408
std::cout << " GUI: Dy: " << dy << std::endl;
7409
std::cout << " GUI: Rotation: " << rotation << std::endl;
7416
// Set these here as we don't always have kerning/rotating attributes
7417
GtkAction* dxAction = GTK_ACTION( g_object_get_data( tbl, "TextDxAction" ));
7418
gtk_action_set_sensitive( GTK_ACTION(dxAction), !isFlow );
7420
GtkAction* dyAction = GTK_ACTION( g_object_get_data( tbl, "TextDyAction" ));
7421
gtk_action_set_sensitive( GTK_ACTION(dyAction), !isFlow );
7423
GtkAction* rotationAction = GTK_ACTION( g_object_get_data( tbl, "TextRotationAction" ));
7424
gtk_action_set_sensitive( GTK_ACTION(rotationAction), !isFlow );
7428
std::cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << std::endl;
7429
std::cout << std::endl;
7432
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
7436
static void sp_text_toolbox_selection_modified(Inkscape::Selection *selection, guint /*flags*/, GObject *tbl)
7438
sp_text_toolbox_selection_changed (selection, tbl);
7442
sp_text_toolbox_subselection_changed (gpointer /*tc*/, GObject *tbl)
7444
sp_text_toolbox_selection_changed (NULL, tbl);
7447
// Define all the "widgets" in the toolbar.
7448
static void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
7450
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
7451
Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1);
7454
UnitTracker* tracker = new UnitTracker( SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE );
7455
tracker->setActiveUnit( sp_desktop_namedview(desktop)->doc_units );
7456
g_object_set_data( holder, "tracker", tracker );
7461
Glib::RefPtr<Gtk::ListStore> store = Inkscape::FontLister::get_instance()->get_font_list();
7462
GtkListStore* model = store->gobj();
7464
Ink_ComboBoxEntry_Action* act = ink_comboboxentry_action_new( "TextFontFamilyAction",
7466
_("Select Font Family (Alt-X to access)"),
7468
GTK_TREE_MODEL(model),
7470
50, // Extra list width
7471
(gpointer)cell_data_func ); // Cell layout
7472
ink_comboboxentry_action_popup_enable( act ); // Enable entry completion
7473
gchar *const warning = _("Font not found on system");
7474
ink_comboboxentry_action_set_warning( act, warning ); // Show icon with tooltip if missing font
7475
ink_comboboxentry_action_set_altx_name( act, "altx-text" ); // Set Alt-X keyboard shortcut
7476
g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(sp_text_fontfamily_value_changed), holder );
7477
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
7478
g_object_set_data( holder, "TextFontFamilyAction", act );
7480
// Change style of drop-down from menu to list
7481
gtk_rc_parse_string (
7482
"style \"dropdown-as-list-style\"\n"
7484
" GtkComboBox::appears-as-list = 1\n"
7486
"widget \"*.TextFontFamilyAction_combobox\" style \"dropdown-as-list-style\"");
7491
// List of font sizes for drop-down menu
7492
GtkListStore* model_size = gtk_list_store_new( 1, G_TYPE_STRING );
7493
gchar const *const sizes[] = {
7494
"4", "6", "8", "9", "10", "11", "12", "13", "14", "16",
7495
"18", "20", "22", "24", "28", "32", "36", "40", "48", "56",
7498
for( unsigned int i = 0; i < G_N_ELEMENTS(sizes); ++i ) {
7500
gtk_list_store_append( model_size, &iter );
7501
gtk_list_store_set( model_size, &iter, 0, sizes[i], -1 );
7504
Ink_ComboBoxEntry_Action* act = ink_comboboxentry_action_new( "TextFontSizeAction",
7506
_("Font size (px)"),
7508
GTK_TREE_MODEL(model_size),
7509
4 ); // Width in characters
7510
g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(sp_text_fontsize_value_changed), holder );
7511
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
7512
g_object_set_data( holder, "TextFontSizeAction", act );
7517
InkToggleAction* act = ink_toggle_action_new( "TextBoldAction", // Name
7518
_("Toggle Bold"), // Label
7519
_("Toggle bold or normal weight"), // Tooltip
7520
GTK_STOCK_BOLD, // Icon (inkId)
7521
secondarySize ); // Icon size
7522
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
7523
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_text_style_changed), holder );
7524
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/text/bold", false) );
7525
g_object_set_data( holder, "TextBoldAction", act );
7528
/* Style - Italic/Oblique */
7530
InkToggleAction* act = ink_toggle_action_new( "TextItalicAction", // Name
7531
_("Toggle Italic/Oblique"), // Label
7532
_("Toggle italic/oblique style"),// Tooltip
7533
GTK_STOCK_ITALIC, // Icon (inkId)
7534
secondarySize ); // Icon size
7535
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
7536
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_text_style_changed), holder );
7537
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/text/italic", false) );
7538
g_object_set_data( holder, "TextItalicAction", act );
7541
/* Style - Superscript */
7543
InkToggleAction* act = ink_toggle_action_new( "TextSuperscriptAction", // Name
7544
_("Toggle Superscript"), // Label
7545
_("Toggle superscript"), // Tooltip
7546
"text_superscript", // Icon (inkId)
7547
secondarySize ); // Icon size
7548
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
7549
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_text_script_changed), holder );
7550
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/text/super", false) );
7551
g_object_set_data( holder, "TextSuperscriptAction", act );
7554
/* Style - Subscript */
7556
InkToggleAction* act = ink_toggle_action_new( "TextSubscriptAction", // Name
7557
_("Toggle Subscript"), // Label
7558
_("Toggle subscript"), // Tooltip
7559
"text_subscript", // Icon (inkId)
7560
secondarySize ); // Icon size
7561
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
7562
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_text_script_changed), holder );
7563
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/text/sub", false) );
7564
g_object_set_data( holder, "TextSubscriptAction", act );
7569
GtkListStore* model = gtk_list_store_new( 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN );
7573
gtk_list_store_append( model, &iter );
7574
gtk_list_store_set( model, &iter,
7577
2, GTK_STOCK_JUSTIFY_LEFT,
7581
gtk_list_store_append( model, &iter );
7582
gtk_list_store_set( model, &iter,
7583
0, _("Align center"),
7584
1, _("Align center"),
7585
2, GTK_STOCK_JUSTIFY_CENTER,
7589
gtk_list_store_append( model, &iter );
7590
gtk_list_store_set( model, &iter,
7591
0, _("Align right"),
7592
1, _("Align right"),
7593
2, GTK_STOCK_JUSTIFY_RIGHT,
7597
gtk_list_store_append( model, &iter );
7598
gtk_list_store_set( model, &iter,
7600
1, _("Justify (only flowed text)"),
7601
2, GTK_STOCK_JUSTIFY_FILL,
7605
EgeSelectOneAction* act = ege_select_one_action_new( "TextAlignAction", // Name
7606
_("Alignment"), // Label
7607
_("Text alignment"), // Tooltip
7609
GTK_TREE_MODEL(model) ); // Model
7610
g_object_set( act, "short_label", "NotUsed", NULL );
7611
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
7612
g_object_set_data( holder, "TextAlignAction", act );
7614
ege_select_one_action_set_appearance( act, "full" );
7615
ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE );
7616
g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL );
7617
ege_select_one_action_set_icon_column( act, 2 );
7618
ege_select_one_action_set_icon_size( act, secondarySize );
7619
ege_select_one_action_set_tooltip_column( act, 1 );
7620
ege_select_one_action_set_sensitive_column( act, 3 );
7621
gint mode = prefs->getInt("/tools/text/align_mode", 0);
7622
ege_select_one_action_set_active( act, mode );
7623
g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_text_align_mode_changed), holder );
7626
/* Orientation (Left to Right, Top to Bottom */
7628
GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING );
7632
gtk_list_store_append( model, &iter );
7633
gtk_list_store_set( model, &iter,
7635
1, _("Horizontal text"),
7636
2, INKSCAPE_ICON_FORMAT_TEXT_DIRECTION_HORIZONTAL,
7639
gtk_list_store_append( model, &iter );
7640
gtk_list_store_set( model, &iter,
7642
1, _("Vertical text"),
7643
2, INKSCAPE_ICON_FORMAT_TEXT_DIRECTION_VERTICAL,
7646
EgeSelectOneAction* act = ege_select_one_action_new( "TextOrientationAction", // Name
7647
_("Orientation"), // Label
7648
_("Text orientation"), // Tooltip
7650
GTK_TREE_MODEL(model) ); // Model
7652
g_object_set( act, "short_label", "NotUsed", NULL );
7653
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
7654
g_object_set_data( holder, "TextOrientationAction", act );
7656
ege_select_one_action_set_appearance( act, "full" );
7657
ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE );
7658
g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL );
7659
ege_select_one_action_set_icon_column( act, 2 );
7660
ege_select_one_action_set_icon_size( act, secondarySize );
7661
ege_select_one_action_set_tooltip_column( act, 1 );
7663
gint mode = prefs->getInt("/tools/text/orientation", 0);
7664
ege_select_one_action_set_active( act, mode );
7665
g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_text_orientation_mode_changed), holder );
7671
gchar const* labels[] = {_("Smaller spacing"), 0, 0, 0, 0, _("Normal"), 0, 0, 0, 0, 0, _("Larger spacing")};
7672
gdouble values[] = { 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1,2, 1.3, 1.4, 1.5, 2.0};
7674
EgeAdjustmentAction *eact = create_adjustment_action(
7675
"TextLineHeightAction", /* name */
7676
_("Line Height"), /* label */
7677
_("Line:"), /* short label */
7678
_("Spacing between lines (times font size)"), /* tooltip */
7679
"/tools/text/lineheight", /* preferences path */
7681
GTK_WIDGET(desktop->canvas), /* focusTarget */
7682
NULL, /* unit selector */
7683
holder, /* dataKludge */
7684
FALSE, /* set alt-x keyboard shortcut? */
7685
NULL, /* altx_mark */
7686
0.0, 10.0, 0.01, 0.10, /* lower, upper, step (arrow up/down), page up/down */
7687
labels, values, G_N_ELEMENTS(labels), /* drop down menu */
7688
sp_text_lineheight_value_changed, /* callback */
7689
0.1, /* step (used?) */
7690
2, /* digits to show */
7691
1.0 /* factor (multiplies default) */
7693
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
7694
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
7695
g_object_set_data( holder, "TextLineHeightAction", eact );
7696
g_object_set( G_OBJECT(eact), "iconId", "text_line_spacing", NULL );
7702
gchar const* labels[] = {_("Negative spacing"), 0, 0, 0, _("Normal"), 0, 0, 0, 0, 0, 0, 0, _("Positive spacing")};
7703
gdouble values[] = {-2.0, -1.5, -1.0, -0.5, 0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0};
7705
EgeAdjustmentAction *eact = create_adjustment_action(
7706
"TextWordSpacingAction", /* name */
7707
_("Word spacing"), /* label */
7708
_("Word:"), /* short label */
7709
_("Spacing between words (px)"), /* tooltip */
7710
"/tools/text/wordspacing", /* preferences path */
7712
GTK_WIDGET(desktop->canvas), /* focusTarget */
7713
NULL, /* unit selector */
7714
holder, /* dataKludge */
7715
FALSE, /* set alt-x keyboard shortcut? */
7716
NULL, /* altx_mark */
7717
-100.0, 100.0, 0.01, 0.10, /* lower, upper, step (arrow up/down), page up/down */
7718
labels, values, G_N_ELEMENTS(labels), /* drop down menu */
7719
sp_text_wordspacing_value_changed, /* callback */
7720
0.1, /* step (used?) */
7721
2, /* digits to show */
7722
1.0 /* factor (multiplies default) */
7724
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
7725
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
7726
g_object_set_data( holder, "TextWordSpacingAction", eact );
7727
g_object_set( G_OBJECT(eact), "iconId", "text_word_spacing", NULL );
7730
/* Letter spacing */
7733
gchar const* labels[] = {_("Negative spacing"), 0, 0, 0, _("Normal"), 0, 0, 0, 0, 0, 0, 0, _("Positive spacing")};
7734
gdouble values[] = {-2.0, -1.5, -1.0, -0.5, 0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0};
7736
EgeAdjustmentAction *eact = create_adjustment_action(
7737
"TextLetterSpacingAction", /* name */
7738
_("Letter spacing"), /* label */
7739
_("Letter:"), /* short label */
7740
_("Spacing between letters (px)"), /* tooltip */
7741
"/tools/text/letterspacing", /* preferences path */
7743
GTK_WIDGET(desktop->canvas), /* focusTarget */
7744
NULL, /* unit selector */
7745
holder, /* dataKludge */
7746
FALSE, /* set alt-x keyboard shortcut? */
7747
NULL, /* altx_mark */
7748
-100.0, 100.0, 0.01, 0.10, /* lower, upper, step (arrow up/down), page up/down */
7749
labels, values, G_N_ELEMENTS(labels), /* drop down menu */
7750
sp_text_letterspacing_value_changed, /* callback */
7751
0.1, /* step (used?) */
7752
2, /* digits to show */
7753
1.0 /* factor (multiplies default) */
7755
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
7756
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
7757
g_object_set_data( holder, "TextLetterSpacingAction", eact );
7758
g_object_set( G_OBJECT(eact), "iconId", "text_letter_spacing", NULL );
7761
/* Character kerning (horizontal shift) */
7764
gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
7765
gdouble values[] = { -2.0, -1.5, -1.0, -0.5, 0, 0.5, 1.0, 1.5, 2.0, 2.5 };
7767
EgeAdjustmentAction *eact = create_adjustment_action(
7768
"TextDxAction", /* name */
7769
_("Kerning"), /* label */
7770
_("Kern:"), /* short label */
7771
_("Horizontal kerning (px)"), /* tooltip */
7772
"/tools/text/dx", /* preferences path */
7774
GTK_WIDGET(desktop->canvas), /* focusTarget */
7775
NULL, /* unit selector */
7776
holder, /* dataKludge */
7777
FALSE, /* set alt-x keyboard shortcut? */
7778
NULL, /* altx_mark */
7779
-100.0, 100.0, 0.01, 0.1, /* lower, upper, step (arrow up/down), page up/down */
7780
labels, values, G_N_ELEMENTS(labels), /* drop down menu */
7781
sp_text_dx_value_changed, /* callback */
7782
0.1, /* step (used?) */
7783
2, /* digits to show */
7784
1.0 /* factor (multiplies default) */
7786
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
7787
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
7788
g_object_set_data( holder, "TextDxAction", eact );
7789
g_object_set( G_OBJECT(eact), "iconId", "text_horz_kern", NULL );
7792
/* Character vertical shift */
7795
gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
7796
gdouble values[] = { -2.0, -1.5, -1.0, -0.5, 0, 0.5, 1.0, 1.5, 2.0, 2.5 };
7798
EgeAdjustmentAction *eact = create_adjustment_action(
7799
"TextDyAction", /* name */
7800
_("Vertical Shift"), /* label */
7801
_("Vert:"), /* short label */
7802
_("Vertical shift (px)"), /* tooltip */
7803
"/tools/text/dy", /* preferences path */
7805
GTK_WIDGET(desktop->canvas), /* focusTarget */
7806
NULL, /* unit selector */
7807
holder, /* dataKludge */
7808
FALSE, /* set alt-x keyboard shortcut? */
7809
NULL, /* altx_mark */
7810
-100.0, 100.0, 0.01, 0.1, /* lower, upper, step (arrow up/down), page up/down */
7811
labels, values, G_N_ELEMENTS(labels), /* drop down menu */
7812
sp_text_dy_value_changed, /* callback */
7813
0.1, /* step (used?) */
7814
2, /* digits to show */
7815
1.0 /* factor (multiplies default) */
7817
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
7818
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
7819
g_object_set_data( holder, "TextDyAction", eact );
7820
g_object_set( G_OBJECT(eact), "iconId", "text_vert_kern", NULL );
7823
/* Character rotation */
7826
gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
7827
gdouble values[] = { -90, -45, -30, -15, 0, 15, 30, 45, 90, 180 };
7829
EgeAdjustmentAction *eact = create_adjustment_action(
7830
"TextRotationAction", /* name */
7831
_("Letter rotation"), /* label */
7832
_("Rot:"), /* short label */
7833
_("Character rotation (degrees)"),/* tooltip */
7834
"/tools/text/rotation", /* preferences path */
7836
GTK_WIDGET(desktop->canvas), /* focusTarget */
7837
NULL, /* unit selector */
7838
holder, /* dataKludge */
7839
FALSE, /* set alt-x keyboard shortcut? */
7840
NULL, /* altx_mark */
7841
-180.0, 180.0, 0.1, 1.0, /* lower, upper, step (arrow up/down), page up/down */
7842
labels, values, G_N_ELEMENTS(labels), /* drop down menu */
7843
sp_text_rotation_value_changed, /* callback */
7844
0.1, /* step (used?) */
7845
2, /* digits to show */
7846
1.0 /* factor (multiplies default) */
7848
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
7849
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
7850
g_object_set_data( holder, "TextRotationAction", eact );
7851
g_object_set( G_OBJECT(eact), "iconId", "text_rotation", NULL );
7854
// Is this necessary to call? Shouldn't hurt.
7855
sp_text_toolbox_selection_changed(sp_desktop_selection(desktop), holder);
7858
Inkscape::ConnectionPool* pool = Inkscape::ConnectionPool::new_connection_pool ("ISTextToolboxGTK");
7860
sigc::connection *c_selection_changed =
7861
new sigc::connection (sp_desktop_selection (desktop)->connectChanged
7862
(sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_changed), (GObject*)holder)));
7863
pool->add_connection ("selection-changed", c_selection_changed);
7865
sigc::connection *c_selection_modified =
7866
new sigc::connection (sp_desktop_selection (desktop)->connectModified
7867
(sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_modified), (GObject*)holder)));
7868
pool->add_connection ("selection-modified", c_selection_modified);
7870
sigc::connection *c_subselection_changed =
7871
new sigc::connection (desktop->connectToolSubselectionChanged
7872
(sigc::bind (sigc::ptr_fun (sp_text_toolbox_subselection_changed), (GObject*)holder)));
7873
pool->add_connection ("tool-subselection-changed", c_subselection_changed);
7875
Inkscape::ConnectionPool::connect_destroy (G_OBJECT (holder), pool);
7877
g_signal_connect( holder, "destroy", G_CALLBACK(purge_repr_listener), holder );
7882
//#########################
7884
//#########################
7886
static void sp_connector_mode_toggled( GtkToggleAction* act, GtkObject * /*tbl*/ )
7888
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
7889
prefs->setBool("/tools/connector/mode",
7890
gtk_toggle_action_get_active( act ));
7893
static void sp_connector_path_set_avoid(void)
7895
cc_selection_set_avoid(true);
7899
static void sp_connector_path_set_ignore(void)
7901
cc_selection_set_avoid(false);
7904
static void sp_connector_orthogonal_toggled( GtkToggleAction* act, GObject *tbl )
7906
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
7907
Inkscape::Selection * selection = sp_desktop_selection(desktop);
7908
SPDocument *doc = sp_desktop_document(desktop);
7910
if (!sp_document_get_undo_sensitive(doc)) {
7915
// quit if run by the _changed callbacks
7916
if (g_object_get_data( tbl, "freeze" )) {
7920
// in turn, prevent callbacks from responding
7921
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
7923
bool is_orthog = gtk_toggle_action_get_active( act );
7924
gchar orthog_str[] = "orthogonal";
7925
gchar polyline_str[] = "polyline";
7926
gchar *value = is_orthog ? orthog_str : polyline_str ;
7928
bool modmade = false;
7929
GSList *l = (GSList *) selection->itemList();
7931
SPItem *item = (SPItem *) l->data;
7933
if (cc_item_is_connector(item)) {
7934
sp_object_setAttribute(item, "inkscape:connector-type",
7936
item->avoidRef->handleSettingChange();
7943
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
7944
prefs->setBool("/tools/connector/orthogonal", is_orthog);
7947
sp_document_done(doc, SP_VERB_CONTEXT_CONNECTOR,
7948
is_orthog ? _("Set connector type: orthogonal"): _("Set connector type: polyline"));
7951
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
7954
static void connector_curvature_changed(GtkAdjustment *adj, GObject* tbl)
7956
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
7957
Inkscape::Selection * selection = sp_desktop_selection(desktop);
7958
SPDocument *doc = sp_desktop_document(desktop);
7960
if (!sp_document_get_undo_sensitive(doc)) {
7965
// quit if run by the _changed callbacks
7966
if (g_object_get_data( tbl, "freeze" )) {
7970
// in turn, prevent callbacks from responding
7971
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
7973
gdouble newValue = gtk_adjustment_get_value(adj);
7974
gchar value[G_ASCII_DTOSTR_BUF_SIZE];
7975
g_ascii_dtostr(value, G_ASCII_DTOSTR_BUF_SIZE, newValue);
7977
bool modmade = false;
7978
GSList *l = (GSList *) selection->itemList();
7980
SPItem *item = (SPItem *) l->data;
7982
if (cc_item_is_connector(item)) {
7983
sp_object_setAttribute(item, "inkscape:connector-curvature",
7985
item->avoidRef->handleSettingChange();
7992
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
7993
prefs->setDouble(Glib::ustring("/tools/connector/curvature"), newValue);
7996
sp_document_done(doc, SP_VERB_CONTEXT_CONNECTOR,
7997
_("Change connector curvature"));
8000
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
8004
static void connector_spacing_changed(GtkAdjustment *adj, GObject* tbl)
8006
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
8007
SPDocument *doc = sp_desktop_document(desktop);
8009
if (!sp_document_get_undo_sensitive(doc)) {
8013
Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
8015
if ( !repr->attribute("inkscape:connector-spacing") &&
8016
( adj->value == defaultConnSpacing )) {
8017
// Don't need to update the repr if the attribute doesn't
8018
// exist and it is being set to the default value -- as will
8019
// happen at startup.
8023
// quit if run by the attr_changed listener
8024
if (g_object_get_data( tbl, "freeze" )) {
8028
// in turn, prevent listener from responding
8029
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE));
8031
sp_repr_set_css_double(repr, "inkscape:connector-spacing", adj->value);
8032
SP_OBJECT(desktop->namedview)->updateRepr();
8033
bool modmade = false;
8035
GSList *items = get_avoided_items(NULL, desktop->currentRoot(), desktop);
8036
for ( GSList const *iter = items ; iter != NULL ; iter = iter->next ) {
8037
SPItem *item = reinterpret_cast<SPItem *>(iter->data);
8038
Geom::Matrix m = Geom::identity();
8039
avoid_item_move(&m, item);
8044
g_slist_free(items);
8047
sp_document_done(doc, SP_VERB_CONTEXT_CONNECTOR,
8048
_("Change connector spacing"));
8050
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
8053
static void sp_connector_graph_layout(void)
8055
if (!SP_ACTIVE_DESKTOP) {
8058
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
8060
// hack for clones, see comment in align-and-distribute.cpp
8061
int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
8062
prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
8064
graphlayout(sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList());
8066
prefs->setInt("/options/clonecompensation/value", saved_compensation);
8068
sp_document_done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_DIALOG_ALIGN_DISTRIBUTE, _("Arrange connector network"));
8071
static void sp_directed_graph_layout_toggled( GtkToggleAction* act, GtkObject * /*tbl*/ )
8073
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
8074
prefs->setBool("/tools/connector/directedlayout",
8075
gtk_toggle_action_get_active( act ));
8078
static void sp_nooverlaps_graph_layout_toggled( GtkToggleAction* act, GtkObject * /*tbl*/ )
8080
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
8081
prefs->setBool("/tools/connector/avoidoverlaplayout",
8082
gtk_toggle_action_get_active( act ));
8086
static void connector_length_changed(GtkAdjustment *adj, GObject* /*tbl*/)
8088
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
8089
prefs->setDouble("/tools/connector/length", adj->value);
8092
static void connector_tb_event_attr_changed(Inkscape::XML::Node *repr,
8093
gchar const *name, gchar const * /*old_value*/, gchar const * /*new_value*/,
8094
bool /*is_interactive*/, gpointer data)
8096
GtkWidget *tbl = GTK_WIDGET(data);
8098
if ( !g_object_get_data(G_OBJECT(tbl), "freeze")
8099
&& (strcmp(name, "inkscape:connector-spacing") == 0) ) {
8100
GtkAdjustment *adj = static_cast<GtkAdjustment*>(gtk_object_get_data(GTK_OBJECT(tbl), "spacing"));
8101
gdouble spacing = defaultConnSpacing;
8102
sp_repr_get_double(repr, "inkscape:connector-spacing", &spacing);
8104
gtk_adjustment_set_value(adj, spacing);
8105
gtk_adjustment_value_changed(adj);
8107
spinbutton_defocus(GTK_OBJECT(tbl));
8111
static void sp_connector_new_connection_point(GtkWidget *, GObject *tbl)
8113
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
8114
SPConnectorContext* cc = SP_CONNECTOR_CONTEXT(desktop->event_context);
8116
if (cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE) {
8117
cc_create_connection_point(cc);
8121
static void sp_connector_remove_connection_point(GtkWidget *, GObject *tbl)
8123
SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
8124
SPConnectorContext* cc = SP_CONNECTOR_CONTEXT(desktop->event_context);
8126
if (cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE) {
8127
cc_remove_connection_point(cc);
8131
static Inkscape::XML::NodeEventVector connector_tb_repr_events = {
8132
NULL, /* child_added */
8133
NULL, /* child_removed */
8134
connector_tb_event_attr_changed,
8135
NULL, /* content_changed */
8136
NULL /* order_changed */
8139
static void sp_connector_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
8141
GtkAdjustment *adj = GTK_ADJUSTMENT( g_object_get_data( tbl, "curvature" ) );
8142
GtkToggleAction *act = GTK_TOGGLE_ACTION( g_object_get_data( tbl, "orthogonal" ) );
8143
SPItem *item = selection->singleItem();
8144
if (SP_IS_PATH(item))
8146
gdouble curvature = SP_PATH(item)->connEndPair.getCurvature();
8147
bool is_orthog = SP_PATH(item)->connEndPair.isOrthogonal();
8148
gtk_toggle_action_set_active(act, is_orthog);
8149
gtk_adjustment_set_value(adj, curvature);
8154
static void sp_connector_toolbox_prep( SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder )
8156
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
8157
Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1);
8159
// Editing mode toggle button
8161
InkToggleAction* act = ink_toggle_action_new( "ConnectorEditModeAction",
8163
_("Switch between connection point editing and connector drawing mode"),
8164
INKSCAPE_ICON_CONNECTOR_EDIT,
8165
Inkscape::ICON_SIZE_DECORATION );
8166
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
8168
bool tbuttonstate = prefs->getBool("/tools/connector/mode");
8169
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), ( tbuttonstate ? TRUE : FALSE ));
8170
g_object_set_data( holder, "mode", act );
8171
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_connector_mode_toggled), holder );
8176
InkAction* inky = ink_action_new( "ConnectorAvoidAction",
8178
_("Make connectors avoid selected objects"),
8179
INKSCAPE_ICON_CONNECTOR_AVOID,
8181
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_connector_path_set_avoid), holder );
8182
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
8186
InkAction* inky = ink_action_new( "ConnectorIgnoreAction",
8188
_("Make connectors ignore selected objects"),
8189
INKSCAPE_ICON_CONNECTOR_IGNORE,
8191
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_connector_path_set_ignore), holder );
8192
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
8195
// Orthogonal connectors toggle button
8197
InkToggleAction* act = ink_toggle_action_new( "ConnectorOrthogonalAction",
8199
_("Make connector orthogonal or polyline"),
8200
INKSCAPE_ICON_CONNECTOR_ORTHOGONAL,
8201
Inkscape::ICON_SIZE_DECORATION );
8202
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
8204
bool tbuttonstate = prefs->getBool("/tools/connector/orthogonal");
8205
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), ( tbuttonstate ? TRUE : FALSE ));
8206
g_object_set_data( holder, "orthogonal", act );
8207
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_connector_orthogonal_toggled), holder );
8210
EgeAdjustmentAction* eact = 0;
8211
// Curvature spinbox
8212
eact = create_adjustment_action( "ConnectorCurvatureAction",
8213
_("Connector Curvature"), _("Curvature:"),
8214
_("The amount of connectors curvature"),
8215
"/tools/connector/curvature", defaultConnCurvature,
8216
GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "inkscape:connector-curvature",
8219
connector_curvature_changed, 1, 0 );
8220
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
8223
eact = create_adjustment_action( "ConnectorSpacingAction",
8224
_("Connector Spacing"), _("Spacing:"),
8225
_("The amount of space left around objects by auto-routing connectors"),
8226
"/tools/connector/spacing", defaultConnSpacing,
8227
GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "inkscape:connector-spacing",
8230
connector_spacing_changed, 1, 0 );
8231
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
8233
// Graph (connector network) layout
8235
InkAction* inky = ink_action_new( "ConnectorGraphAction",
8237
_("Nicely arrange selected connector network"),
8238
INKSCAPE_ICON_DISTRIBUTE_GRAPH,
8240
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_connector_graph_layout), holder );
8241
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
8244
// Default connector length spinbox
8245
eact = create_adjustment_action( "ConnectorLengthAction",
8246
_("Connector Length"), _("Length:"),
8247
_("Ideal length for connectors when layout is applied"),
8248
"/tools/connector/length", 100,
8249
GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "inkscape:connector-length",
8250
10, 1000, 10.0, 100.0,
8252
connector_length_changed, 1, 0 );
8253
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
8256
// Directed edges toggle button
8258
InkToggleAction* act = ink_toggle_action_new( "ConnectorDirectedAction",
8260
_("Make connectors with end-markers (arrows) point downwards"),
8261
INKSCAPE_ICON_DISTRIBUTE_GRAPH_DIRECTED,
8262
Inkscape::ICON_SIZE_DECORATION );
8263
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
8265
bool tbuttonstate = prefs->getBool("/tools/connector/directedlayout");
8266
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), ( tbuttonstate ? TRUE : FALSE ));
8268
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_directed_graph_layout_toggled), holder );
8269
sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_connector_toolbox_selection_changed), (GObject *)holder));
8272
// Avoid overlaps toggle button
8274
InkToggleAction* act = ink_toggle_action_new( "ConnectorOverlapAction",
8275
_("Remove overlaps"),
8276
_("Do not allow overlapping shapes"),
8277
INKSCAPE_ICON_DISTRIBUTE_REMOVE_OVERLAPS,
8278
Inkscape::ICON_SIZE_DECORATION );
8279
gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
8281
bool tbuttonstate = prefs->getBool("/tools/connector/avoidoverlaplayout");
8282
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), (tbuttonstate ? TRUE : FALSE ));
8284
g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_nooverlaps_graph_layout_toggled), holder );
8288
// New connection point button
8290
InkAction* inky = ink_action_new( "ConnectorNewConnPointAction",
8291
_("New connection point"),
8292
_("Add a new connection point to the currently selected item"),
8293
INKSCAPE_ICON_CONNECTOR_NEW_CONNPOINT,
8295
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_connector_new_connection_point), holder );
8296
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
8299
// Remove selected connection point button
8302
InkAction* inky = ink_action_new( "ConnectorRemoveConnPointAction",
8303
_("Remove connection point"),
8304
_("Remove the currently selected connection point"),
8305
INKSCAPE_ICON_CONNECTOR_REMOVE_CONNPOINT,
8307
g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_connector_remove_connection_point), holder );
8308
gtk_action_group_add_action( mainActions, GTK_ACTION(inky) );
8312
// Code to watch for changes to the connector-spacing attribute in
8314
Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
8315
g_assert(repr != NULL);
8317
purge_repr_listener( holder, holder );
8320
g_object_set_data( holder, "repr", repr );
8321
Inkscape::GC::anchor(repr);
8322
sp_repr_add_listener( repr, &connector_tb_repr_events, holder );
8323
sp_repr_synthesize_events( repr, &connector_tb_repr_events, holder );
8325
} // end of sp_connector_toolbox_prep()
8328
//#########################
8330
//#########################
8332
static void paintbucket_channels_changed(EgeSelectOneAction* act, GObject* /*tbl*/)
8334
gint channels = ege_select_one_action_get_active( act );
8335
flood_channels_set_channels( channels );
8338
static void paintbucket_threshold_changed(GtkAdjustment *adj, GObject * /*tbl*/)
8340
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
8341
prefs->setInt("/tools/paintbucket/threshold", (gint)adj->value);
8344
static void paintbucket_autogap_changed(EgeSelectOneAction* act, GObject * /*tbl*/)
8346
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
8347
prefs->setBool("/tools/paintbucket/autogap", ege_select_one_action_get_active( act ));
8350
static void paintbucket_offset_changed(GtkAdjustment *adj, GObject *tbl)
8352
UnitTracker* tracker = static_cast<UnitTracker*>(g_object_get_data( tbl, "tracker" ));
8353
SPUnit const *unit = tracker->getActiveUnit();
8354
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
8356
// Don't adjust the offset value because we're saving the
8357
// unit and it'll be correctly handled on load.
8358
prefs->setDouble("/tools/paintbucket/offset", (gdouble)adj->value);
8359
prefs->setString("/tools/paintbucket/offsetunits", sp_unit_get_abbreviation(unit));
8362
static void paintbucket_defaults(GtkWidget *, GObject *tbl)
8364
// FIXME: make defaults settable via Inkscape Options
8368
} const key_values[] = {
8373
for (unsigned i = 0; i < G_N_ELEMENTS(key_values); ++i) {
8374
KeyValue const &kv = key_values[i];
8375
GtkAdjustment* adj = static_cast<GtkAdjustment *>(g_object_get_data(tbl, kv.key));
8377
gtk_adjustment_set_value(adj, kv.value);
8381
EgeSelectOneAction* channels_action = EGE_SELECT_ONE_ACTION( g_object_get_data (tbl, "channels_action" ) );
8382
ege_select_one_action_set_active( channels_action, FLOOD_CHANNELS_RGB );
8383
EgeSelectOneAction* autogap_action = EGE_SELECT_ONE_ACTION( g_object_get_data (tbl, "autogap_action" ) );
8384
ege_select_one_action_set_active( autogap_action, 0 );
8387
static void sp_paintbucket_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
8389
EgeAdjustmentAction* eact = 0;
8390
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
8393
GtkListStore* model = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_INT );
8397
for ( items = flood_channels_dropdown_items_list(); items ; items = g_list_next(items) )
8400
gtk_list_store_append( model, &iter );
8401
gtk_list_store_set( model, &iter, 0, reinterpret_cast<gchar*>(items->data), 1, count, -1 );
8404
g_list_free( items );
8406
EgeSelectOneAction* act1 = ege_select_one_action_new( "ChannelsAction", _("Fill by"), (""), NULL, GTK_TREE_MODEL(model) );
8407
g_object_set( act1, "short_label", _("Fill by:"), NULL );
8408
ege_select_one_action_set_appearance( act1, "compact" );
8409
ege_select_one_action_set_active( act1, prefs->getInt("/tools/paintbucket/channels", 0) );
8410
g_signal_connect( G_OBJECT(act1), "changed", G_CALLBACK(paintbucket_channels_changed), holder );
8411
gtk_action_group_add_action( mainActions, GTK_ACTION(act1) );
8412
g_object_set_data( holder, "channels_action", act1 );
8417
eact = create_adjustment_action(
8419
_("Fill Threshold"), _("Threshold:"),
8420
_("The maximum allowed difference between the clicked pixel and the neighboring pixels to be counted in the fill"),
8421
"/tools/paintbucket/threshold", 5, GTK_WIDGET(desktop->canvas), NULL, holder, TRUE,
8422
"inkscape:paintbucket-threshold", 0, 100.0, 1.0, 10.0,
8424
paintbucket_threshold_changed, 1, 0 );
8426
ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
8427
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
8430
// Create the units menu.
8431
UnitTracker* tracker = new UnitTracker( SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE );
8432
Glib::ustring stored_unit = prefs->getString("/tools/paintbucket/offsetunits");
8433
if (!stored_unit.empty()) {
8434
tracker->setActiveUnit(sp_unit_get_by_abbreviation(stored_unit.data()));
8436
g_object_set_data( holder, "tracker", tracker );
8438
GtkAction* act = tracker->createAction( "PaintbucketUnitsAction", _("Units"), ("") );
8439
gtk_action_group_add_action( mainActions, act );
8444
eact = create_adjustment_action(
8446
_("Grow/shrink by"), _("Grow/shrink by:"),
8447
_("The amount to grow (positive) or shrink (negative) the created fill path"),
8448
"/tools/paintbucket/offset", 0, GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, TRUE,
8449
"inkscape:paintbucket-offset", -1e4, 1e4, 0.1, 0.5,
8451
paintbucket_offset_changed, 1, 2);
8452
tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) );
8454
gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
8459
GtkListStore* model = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_INT );
8463
for ( items = flood_autogap_dropdown_items_list(); items ; items = g_list_next(items) )
8466
gtk_list_store_append( model, &iter );
8467
gtk_list_store_set( model, &iter, 0, reinterpret_cast<gchar*>(items->data), 1, count, -1 );
8470
g_list_free( items );
8472
EgeSelectOneAction* act2 = ege_select_one_action_new( "AutoGapAction", _("Close gaps"), (""), NULL, GTK_TREE_MODEL(model) );
8473
g_object_set( act2, "short_label", _("Close gaps:"), NULL );
8474
ege_select_one_action_set_appearance( act2, "compact" );
8475
ege_select_one_action_set_active( act2, prefs->getBool("/tools/paintbucket/autogap") );
8476
g_signal_connect( G_OBJECT(act2), "changed", G_CALLBACK(paintbucket_autogap_changed), holder );
8477
gtk_action_group_add_action( mainActions, GTK_ACTION(act2) );
8478
g_object_set_data( holder, "autogap_action", act2 );
8483
GtkAction* act = gtk_action_new( "PaintbucketResetAction",
8485
_("Reset paint bucket parameters to defaults (use Inkscape Preferences > Tools to change defaults)"),
8487
g_signal_connect_after( G_OBJECT(act), "activate", G_CALLBACK(paintbucket_defaults), holder );
8488
gtk_action_group_add_action( mainActions, act );
8489
gtk_action_set_sensitive( act, TRUE );
8497
c-file-style:"stroustrup"
8498
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
8499
indent-tabs-mode:nil
8503
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :