Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
actions-tools.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Gio::Actions for switching tools.
4 *
5 * Copyright (C) 2020 Tavmjong Bah
6 *
7 * The contents of this file may be used under the GNU General Public License Version 2 or later.
8 *
9 */
10
11#include <giomm.h> // Not <gtkmm.h>! To eventually allow a headless version!
12#include <glibmm/i18n.h>
13
14#include "actions-tools.h"
15#include "actions-helper.h"
16
18#include "inkscape-window.h"
19#include "message-context.h"
20
21#include "object/box3d.h"
22#include "object/sp-ellipse.h"
23#include "object/sp-flowtext.h"
24#include "object/sp-offset.h"
25#include "object/sp-path.h"
26#include "object/sp-rect.h"
27#include "object/sp-spiral.h"
28#include "object/sp-star.h"
29#include "object/sp-text.h"
30#include "object/sp-marker.h"
31
36#include "ui/tools/text-tool.h"
37#include "ui/tools/tool-data.h"
38
39Glib::ustring
41{
42 Glib::ustring state;
43
44 auto action = win->lookup_action("tool-switch");
45 if (!action) {
46 show_output("get_active_tool: action 'tool-switch' missing!");
47 return state;
48 }
49
50 auto saction = std::dynamic_pointer_cast<Gio::SimpleAction>(action);
51 if (!saction) {
52 show_output("get_active_tool: action 'tool-switch' not SimpleAction!");
53 return state;
54 }
55
56 saction->get_state(state);
57
58 return state;
59}
60
61int
63{
64 return get_tool_data().at(get_active_tool(win)).tool;
65}
66
67void tool_switch(Glib::ustring const &tool, InkscapeWindow *win);
68
69void
70set_active_tool(InkscapeWindow *win, Glib::ustring const &tool)
71{
72 // Seems silly to have a function to just flip argument order... but it's consistent with other
73 // external functions.
74 tool_switch(tool, win);
75}
76
77void
78open_tool_preferences(InkscapeWindow *win, Glib::ustring const &tool)
79{
80 tool_preferences(tool, win);
81}
82
86void
88{
89 if (is<SPRect>(item)) {
90 tool_switch("Rect", win);
91 } else if (is<SPGenericEllipse>(item)) {
92 tool_switch("Arc", win);
93 } else if (is<SPStar>(item)) {
94 tool_switch("Star", win);
95 } else if (is<SPBox3D>(item)) {
96 tool_switch("3DBox", win);
97 } else if (is<SPSpiral>(item)) {
98 tool_switch("Spiral", win);
99 } else if (is<SPMarker>(item)) {
100 tool_switch("Marker", win);
101 } else if (is<SPPath>(item)) {
103 tool_switch("Connector", win);
104 }
105 else {
106 tool_switch("Node", win);
107 }
108 } else if (is<SPText>(item) || is<SPFlowtext>(item)) {
109 tool_switch("Text", win);
110 SPDesktop* dt = win->get_desktop();
111 if (!dt) {
112 show_output("set_active_tool: no desktop!");
113 return;
114 }
115 SP_TEXT_CONTEXT(dt->getTool())->placeCursorAt(item, p);
116 } else if (is<SPOffset>(item)) {
117 tool_switch("Node", win);
118 }
119}
120
124void
125tool_switch(Glib::ustring const &tool, InkscapeWindow *win)
126{
127 auto const &tool_data = get_tool_data();
128 // Valid tool?
129 auto tool_it = tool_data.find(tool);
130 if (tool_it == tool_data.end()) {
131 show_output(Glib::ustring("tool-switch: invalid tool name: ") + tool.raw());
132 return;
133 }
134
135 // Have desktop?
136 SPDesktop* dt = win->get_desktop();
137 if (!dt) {
138 show_output("tool_switch: no desktop!");
139 return;
140 }
141
142 auto action = win->lookup_action("tool-switch");
143 if (!action) {
144 show_output("tool-switch: action 'tool-switch' missing!");
145 return;
146 }
147
148 auto saction = std::dynamic_pointer_cast<Gio::SimpleAction>(action);
149 if (!saction) {
150 show_output("tool-switch: action 'tool-switch' not SimpleAction!");
151 return;
152 }
153
154 // Gtk sometimes fires multiple actions at us, including when switch 'away' from
155 // an option. So we catch duplications here and don't switch to ourselves.
156 Glib::ustring current_tool;
157 saction->get_state(current_tool);
158 if (current_tool == tool)
159 return;
160
161 // Update button states.
162 saction->set_enabled(false); // Avoid infinite loop when called by tool_toogle().
163 saction->change_state(tool);
164 saction->set_enabled(true);
165
166
167 // Switch to new tool. TODO: Clean this up. This should be one window function.
168 // Setting tool via preference path is a bit strange.
170 dt->setTool(tool_data.at(tool).pref_path);
171
172 if (auto new_tool = dt->getTool()) {
173 new_tool->set_last_active_tool(current_tool);
174 }
175}
176
180void
181tool_preferences(Glib::ustring const &tool, InkscapeWindow *win)
182{
183 auto const &tool_data = get_tool_data();
184 // Valid tool?
185 auto tool_it = tool_data.find(tool);
186 if (tool_it == tool_data.end()) {
187 show_output(Glib::ustring("tool-preferences: invalid tool name: ") + tool.raw());
188 return;
189 }
190
191 // Have desktop?
192 SPDesktop* dt = win->get_desktop();
193 if (!dt) {
194 show_output("tool-preferences: no desktop!");
195 return;
196 }
197
198 auto prefs = Inkscape::Preferences::get();
199 prefs->setInt("/dialogs/preferences/page", tool_it->second.pref);
201
202 // Create dialog if it doesn't exist (also sets page if dialog not already in opened tab).
203 container->new_floating_dialog("Preferences");
204
205 // Find dialog and explicitly set page (in case not set in previous line).
207 if (dialog) {
208 auto pref_dialog = dynamic_cast<Inkscape::UI::Dialog::InkscapePreferences *>(dialog);
209 if (pref_dialog) {
210 pref_dialog->showPage(); // Switch to page indicated in preferences file (set above).
211 }
212 }
213}
214
218void
219tool_toggle(Glib::ustring const &tool, InkscapeWindow *win)
220{
221 SPDesktop* dt = win->get_desktop();
222 if (!dt) {
223 show_output("tool_toggle: no desktop!");
224 return;
225 }
226
227 auto action = win->lookup_action("tool-switch");
228 if (!action) {
229 show_output("tool_toggle: action 'tool_switch' missing!");
230 return;
231 }
232
233 auto saction = std::dynamic_pointer_cast<Gio::SimpleAction>(action);
234 if (!saction) {
235 show_output("tool_toogle: action 'tool_switch' not SimpleAction!");
236 return;
237 }
238
239 static Glib::ustring old_tool = "Select";
240
241 Glib::ustring current_tool;
242 saction->get_state(current_tool);
243 if (current_tool == tool) {
244 current_tool = old_tool;
245 } else {
246 old_tool = current_tool;
247 current_tool = tool;
248 }
249
250 tool_switch(current_tool, win);
251}
252
254{
256 return get_active_tool(win);
257}
258
264
265void set_active_tool(SPDesktop *desktop, Glib::ustring const &tool)
266{
268 set_active_tool(win, tool);
269}
270
276
277const Glib::ustring SECTION = NC_("Action Section", "Tool Switch");
278
279std::vector<std::vector<Glib::ustring>> raw_data_tools =
280{
281 // clang-format off
282 {"win.tool-switch('Select')", N_("Selector Tool"), SECTION, N_("Select and transform objects") },
283 {"win.tool-switch('Node')", N_("Node Tool"), SECTION, N_("Edit paths by nodes") },
284 {"win.tool-switch('Booleans')", N_("Shape Builder Tool"), SECTION, N_("Build shapes with the Boolean tool") },
285
286 {"win.tool-switch('Rect')", N_("Rectangle Tool"), SECTION, N_("Create rectangles and squares") },
287 {"win.tool-switch('Arc')", N_("Ellipse/Arc Tool"), SECTION, N_("Create circles, ellipses and arcs") },
288 {"win.tool-switch('Star')", N_("Star/Polygon Tool"), SECTION, N_("Create stars and polygons") },
289 {"win.tool-switch('3DBox')", N_("3D Box Tool"), SECTION, N_("Create 3D Boxes") },
290 {"win.tool-switch('Spiral')", N_("Spiral Tool"), SECTION, N_("Create spirals") },
291 {"win.tool-switch('Marker')", N_("Marker Tool"), SECTION, N_("Edit markers") },
292
293 {"win.tool-switch('Pen')", N_("Pen Tool"), SECTION, N_("Draw Bezier curves and straight lines") },
294 {"win.tool-switch('Pencil')", N_("Pencil Tool"), SECTION, N_("Draw freehand lines") },
295 {"win.tool-switch('Calligraphic')", N_("Calligraphy Tool"), SECTION, N_("Draw calligraphic or brush strokes") },
296 {"win.tool-switch('Text')", N_("Text Tool"), SECTION, N_("Create and edit text objects") },
297
298 {"win.tool-switch('Gradient')", N_("Gradient Tool"), SECTION, N_("Create and edit gradients") },
299 {"win.tool-switch('Mesh')", N_("Mesh Tool"), SECTION, N_("Create and edit meshes") },
300 {"win.tool-switch('Dropper')", N_("Dropper Tool"), SECTION, N_("Pick colors from image") },
301 {"win.tool-switch('PaintBucket')", N_("Paint Bucket Tool"), SECTION, N_("Fill bounded areas") },
302
303 {"win.tool-switch('Tweak')", N_("Tweak Tool"), SECTION, N_("Tweak objects by sculpting or painting") },
304 {"win.tool-switch('Spray')", N_("Spray Tool"), SECTION, N_("Spray copies or clones of objects") },
305 {"win.tool-switch('Eraser')", N_("Eraser Tool"), SECTION, N_("Erase objects or paths") },
306 {"win.tool-switch('Connector')", N_("Connector Tool"), SECTION, N_("Create diagram connectors") },
307 {"win.tool-switch('LPETool')", N_("LPE Tool"), SECTION, N_("Do geometric constructions") },
308
309 {"win.tool-switch('Zoom')", N_("Zoom Tool"), SECTION, N_("Zoom in or out") },
310 {"win.tool-switch('Measure')", N_("Measure Tool"), SECTION, N_("Measure objects") },
311 {"win.tool-switch('Pages')", N_("Pages Tool"), SECTION, N_("Create and edit document pages") },
312
313 {"win.tool-toggle('Select')", N_("Toggle Selector Tool"), SECTION, N_("Toggle between Selector tool and last used tool") },
314 {"win.tool-toggle('Dropper')", N_("Toggle Dropper"), SECTION, N_("Toggle between Dropper tool and last used tool")},
315 // clang-format on
316};
317
318
319void
321{
322 // clang-format off
323 win->add_action_radio_string ( "tool-switch", sigc::bind(sigc::ptr_fun(&tool_switch), win), "Select");
324 win->add_action_radio_string ( "tool-toggle", sigc::bind(sigc::ptr_fun(&tool_toggle), win), "Select");
325 // clang-format on
326
328 if (!app) {
329 show_output("add_actions_tools: no app!");
330 return;
331 }
332
333 app->get_action_extra_data().add_data(raw_data_tools);
334}
335
336/*
337 Local Variables:
338 mode:c++
339 c-file-style:"stroustrup"
340 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
341 indent-tabs-mode:nil
342 fill-column:99
343 End:
344*/
345// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
void show_output(Glib::ustring const &data, bool const is_cerr)
void tool_switch(Glib::ustring const &tool, InkscapeWindow *win)
Set display mode.
const Glib::ustring SECTION
void tool_preferences(Glib::ustring const &tool, InkscapeWindow *win)
Open preferences page for tool.
Glib::ustring get_active_tool(InkscapeWindow *win)
int get_active_tool_enum(InkscapeWindow *win)
std::vector< std::vector< Glib::ustring > > raw_data_tools
void set_active_tool(InkscapeWindow *win, Glib::ustring const &tool)
void open_tool_preferences(InkscapeWindow *win, Glib::ustring const &tool)
void add_actions_tools(InkscapeWindow *win)
void tool_toggle(Glib::ustring const &tool, InkscapeWindow *win)
Toggle between "Selector" and last used tool.
Two-dimensional point that doubles as a vector.
Definition point.h:66
static InkscapeApplication * instance()
Singleton instance.
SPDesktop * get_desktop()
void set(MessageType type, char const *message)
pushes a message on the stack, replacing our old message
static Preferences * get()
Access the singleton Preferences object.
A widget that manages DialogNotebook's and other widgets inside a horizontal DialogMultipaned contain...
DialogWindow * new_floating_dialog(const Glib::ustring &dialog_type)
Add a new floating dialog (or reuse existing one if it's already up)
static DialogManager & singleton()
DialogBase * find_floating_dialog(const Glib::ustring &dialog_type)
To do: update description of desktop.
Definition desktop.h:149
void setTool(std::string const &toolName)
Replaces the currently active tool with a new one.
Definition desktop.cpp:308
InkscapeWindow const * getInkscapeWindow() const
Definition desktop.cpp:975
Inkscape::MessageContext * tipsMessageContext() const
Definition desktop.h:161
Inkscape::UI::Dialog::DialogContainer * getContainer()
Definition desktop.cpp:335
Inkscape::UI::Tools::ToolBase * getTool() const
Definition desktop.h:187
Base class for visual SVG elements.
Definition sp-item.h:109
A widget that manages DialogNotebook's and other widgets inside a horizontal DialogMultipaned.
SPItem * item
Inkscape Preferences dialog.
Inkscape - An SVG editor.
Interface for locally managing a current status message.
bool cc_item_is_connector(SPItem *item)
@ NORMAL_MESSAGE
Definition message.h:26
TODO: insert short description here.
SPDesktop * desktop
TextTool.
auto SP_TEXT_CONTEXT(Inkscape::UI::Tools::ToolBase *tool)
Definition text-tool.h:126
std::map< Glib::ustring, ToolData > const & get_tool_data()
Definition tool-data.cpp:7
std::map< Glib::ustring, Glib::ustring > const & get_tool_msg()
Definition tool-data.cpp:42