Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
actions-paths.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Gio::Actions for Path Actions
4 *
5 * Copyright (C) 2021 Sushant A.A.
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 "actions-paths.h"
12
13#include <iostream>
14
15#include <giomm.h> // Not <gtkmm.h>! To eventually allow a headless version!
16#include <glibmm/i18n.h>
17
18#include "actions-tools.h"
19#include "desktop.h"
20#include "document-undo.h"
22#include "inkscape-window.h"
23#include "preferences.h"
24#include "selection.h" // Selection
25#include "selection-chemistry.h" // SelectionHelper
26#include "path/path-offset.h"
27#include "ui/icon-names.h"
29
30void
32{
33 auto selection = app->get_active_selection();
34 selection->removeLPESRecursive(true);
35 selection->unlinkRecursive(true);
36 selection->pathUnion();
37}
38
39void
41{
42 auto selection = app->get_active_selection();
43 selection->removeLPESRecursive(true);
44 selection->unlinkRecursive(true);
45 selection->pathDiff();
46}
47
48void
50{
51 auto selection = app->get_active_selection();
52 selection->removeLPESRecursive(true);
53 selection->unlinkRecursive(true);
54 selection->pathIntersect();
55}
56
57void
59{
60 auto selection = app->get_active_selection();
61 selection->removeLPESRecursive(true);
62 selection->unlinkRecursive(true);
63 selection->pathSymDiff();
64}
65
66void
68{
69 auto selection = app->get_active_selection();
70 selection->removeLPESRecursive(true);
71 selection->unlinkRecursive(true);
72 selection->pathCut();
73}
74
75void
77{
78 auto selection = app->get_active_selection();
79 selection->removeLPESRecursive(true);
80 selection->unlinkRecursive(true);
81 selection->pathSlice();
82}
83
84void
86{
87 auto selection = app->get_active_selection();
88 selection->unlinkRecursive(true);
89 selection->combine();
90}
91
92void
94{
95 auto selection = app->get_active_selection();
96 selection->breakApart();
97}
98
99void
101{
102 auto selection = app->get_active_selection();
103 selection->breakApart(false, false);
104}
105
106void
108{
109 auto selection = app->get_active_selection();
110 auto boolean_builder = Inkscape::BooleanBuilder(selection);
111 selection->setList(boolean_builder.shape_commit(true, true));
112 Inkscape::DocumentUndo::done(selection->document(), "Fracture", INKSCAPE_ICON("path-fracture"));
113}
114
116{
117 auto selection = app->get_active_selection();
118 selection->strokesToPaths(false, true);
119 auto boolean_builder = Inkscape::BooleanBuilder(selection, true);
120 selection->setList(boolean_builder.shape_commit(true, true));
121 Inkscape::DocumentUndo::done(selection->document(), "Flatten", INKSCAPE_ICON("path-flatten"));
122}
123
124void
126{
127 auto selection = app->get_active_selection();
128 selection->fillBetweenMany();
129}
130
131void
133{
134 auto selection = app->get_active_selection();
135 selection->simplifyPaths();
136}
137
138void
140{
141 SPDesktop* dt = win->get_desktop();
142
143 // Inset selected paths
145 dt->getSelection()->unlinkRecursive(true);
147}
148
149void
151{
152 SPDesktop* dt = win->get_desktop();
153
154 // Offset selected paths
156 dt->getSelection()->unlinkRecursive(true);
158}
159
160void
161select_path_inset_screen(const Glib::VariantBase& value, InkscapeWindow *win)
162{
163 Glib::Variant<double> d = Glib::VariantBase::cast_dynamic<Glib::Variant<double> >(value);
164
165 SPDesktop* dt = win->get_desktop();
166
167 // Offset selected paths
169 dt->getSelection()->unlinkRecursive(true);
171}
172
173void
174select_path_offset_screen(const Glib::VariantBase& value, InkscapeWindow *win)
175{
176 Glib::Variant<double> d = Glib::VariantBase::cast_dynamic<Glib::Variant<double> >(value);
177
178 SPDesktop* dt = win->get_desktop();
179
180 // Offset selected paths
182 dt->getSelection()->unlinkRecursive(true);
184}
185
186void
188{
189 SPDesktop* dt = win->get_desktop();
190
191 // Dynamic Offset
193 dt->getSelection()->unlinkRecursive(true);
195 set_active_tool(dt, "Node");
196}
197
198void
200{
201 SPDesktop* dt = win->get_desktop();
202
203 // Linked Offset
205 dt->getSelection()->unlinkRecursive(true);
207 set_active_tool(dt, "Node");
208}
209
210void
212{
213 SPDesktop* dt = win->get_desktop();
214
215 // Reverse
217}
218
219void
221{
223
224 auto action = win->lookup_action("shape-builder-mode");
225 auto saction = std::dynamic_pointer_cast<Gio::SimpleAction>(action);
226 saction->change_state((int)value);
227 pref->setInt("/tools/booleans/mode", value);
228}
229
230void
232{
234 if (auto action = win->lookup_action("shape-builder-replace")) {
235 bool active = false;
236 action->get_state(active);
237 active = !active; // toggle
238 action->change_state(active);
239 pref->setBool("/tools/booleans/replace", active);
240 }
241
242}
243
244const Glib::ustring SECTION = NC_("Action Section", "Path");
245
246static const std::vector<std::vector<Glib::ustring>> raw_data_path =
247{
248 // clang-format offs
249 {"app.path-union", N_("Union"), SECTION, N_("Create union of selected paths")},
250 {"app.path-difference", N_("Difference"), SECTION, N_("Create difference of selected paths (bottom minus top)")},
251 {"app.path-intersection", N_("Intersection"), SECTION, N_("Create intersection of selected paths")},
252 {"app.path-exclusion", N_("Exclusion"), SECTION, N_("Create exclusive OR of selected paths (those parts that belong to only one path)")},
253 {"app.path-division", N_("Division"), SECTION, N_("Cut the bottom path into pieces")},
254 {"app.path-cut", N_("Cut Path"), SECTION, N_("Cut the bottom path's stroke into pieces, removing fill")},
255 {"app.path-combine", N_("Combine"), SECTION, N_("Combine several paths into one")},
256 {"app.path-break-apart", N_("Break Apart"), SECTION, N_("Break selected paths into subpaths")},
257 {"app.path-split", N_("Split Apart"), SECTION, N_("Split selected paths into non-overlapping sections")},
258 {"app.path-fracture", N_("Fracture"), SECTION, N_("Fracture one or more overlapping objects into all possible segments")},
259 {"app.path-flatten", NC_("Path flatten", "Flatten"), SECTION, N_("Flatten one or more overlapping objects into their visible parts")},
260 {"app.path-fill-between-paths", N_("Fill between paths"), SECTION, N_("Create a fill object using the selected paths")},
261 {"app.path-simplify", N_("Simplify"), SECTION, N_("Simplify selected paths (remove extra nodes)")},
262
263 {"win.path-inset", N_("Inset"), SECTION, N_("Inset selected paths")},
264 {"win.path-offset", N_("Offset"), SECTION, N_("Offset selected paths")},
265 {"win.path-offset-dynamic", N_("Dynamic Offset"), SECTION, N_("Create a dynamic offset object")},
266 {"win.path-offset-linked", N_("Linked Offset"), SECTION, N_("Create a dynamic offset object linked to the original path")},
267 {"win.path-reverse", N_("Reverse"), SECTION, N_("Reverse the direction of selected paths (useful for flipping markers)")},
268 {"win.path-inset-screen", N_("Inset Screen"), SECTION, N_("Inset selected paths by screen pixels")},
269 {"win.path-offset-screen", N_("Offset Screen"), SECTION, N_("Offset selected paths by screen pixels")},
270
271 {"win.shape-builder-mode(0)", N_("Shape Builder: Add"), SECTION, N_("Add shapes by clicking or clicking and dragging")},
272 {"win.shape-builder-mode(1)", N_("Shape Builder: Delete"), SECTION, N_("Remove shapes by clicking or clicking and dragging")},
273 {"win.shape-builder-replace", N_("Replace Objects"), SECTION, N_("Remove selected objects when shape building is completed")},
274 // clang-format on
275};
276
278{
279 auto *gapp = app->gio_app();
280
281 // clang-format off
282 gapp->add_action( "path-union", sigc::bind(sigc::ptr_fun(&object_path_union), app));
283 gapp->add_action( "path-difference", sigc::bind(sigc::ptr_fun(&select_path_difference), app));
284 gapp->add_action( "path-intersection", sigc::bind(sigc::ptr_fun(&select_path_intersection), app));
285 gapp->add_action( "path-exclusion", sigc::bind(sigc::ptr_fun(&select_path_exclusion), app));
286 gapp->add_action( "path-division", sigc::bind(sigc::ptr_fun(&select_path_division), app));
287 gapp->add_action( "path-cut", sigc::bind(sigc::ptr_fun(&select_path_cut), app));
288 gapp->add_action( "path-combine", sigc::bind(sigc::ptr_fun(&select_path_combine), app));
289 gapp->add_action( "path-break-apart", sigc::bind(sigc::ptr_fun(&select_path_break_apart), app));
290 gapp->add_action( "path-split", sigc::bind(sigc::ptr_fun(&select_path_split), app));
291 gapp->add_action( "path-fracture", sigc::bind(sigc::ptr_fun(&select_path_fracture), app));
292 gapp->add_action( "path-flatten", sigc::bind(sigc::ptr_fun(&select_path_flatten) , app));
293 gapp->add_action( "path-fill-between-paths", sigc::bind(sigc::ptr_fun(&fill_between_paths), app));
294 gapp->add_action( "path-simplify", sigc::bind(sigc::ptr_fun(&select_path_simplify), app));
295 // clang-format on
296
298}
299
300// TODO: Remove desktop dependencies and convert to app actions.
302{
303 auto const Double = Glib::VariantType(Glib::VARIANT_TYPE_DOUBLE);
304
305 auto prefs = Inkscape::Preferences::get();
306 int current_mode = prefs->getInt("/tools/booleans/mode", 0);
307 bool replace = prefs->getBool("/tools/booleans/replace", true);
308
309 // clang-format off
310 win->add_action( "path-inset", sigc::bind(sigc::ptr_fun(&select_path_inset), win));
311 win->add_action( "path-offset", sigc::bind(sigc::ptr_fun(&select_path_offset), win));
312 win->add_action_with_parameter( "path-inset-screen", Double, sigc::bind(sigc::ptr_fun(&select_path_inset_screen), win));
313 win->add_action_with_parameter( "path-offset-screen", Double, sigc::bind(sigc::ptr_fun(&select_path_offset_screen), win));
314 win->add_action( "path-offset-dynamic", sigc::bind(sigc::ptr_fun(&select_path_offset_dynamic), win));
315 win->add_action( "path-offset-linked", sigc::bind(sigc::ptr_fun(&select_path_offset_linked), win));
316 win->add_action( "path-reverse", sigc::bind(sigc::ptr_fun(&select_path_reverse), win));
317 win->add_action_radio_integer( "shape-builder-mode", sigc::bind(sigc::ptr_fun(&shape_builder_mode), win), current_mode);
318 win->add_action_bool( "shape-builder-replace", sigc::bind(sigc::ptr_fun(&shape_builder_replace), win), replace);
319 // clang-format on
320}
321
322/*
323 Local Variables:
324 mode:c++
325 c-file-style:"stroustrup"
326 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
327 indent-tabs-mode:nil
328 fill-column:99
329 End:
330*/
331// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
void select_path_inset(InkscapeWindow *win)
void select_path_offset_dynamic(InkscapeWindow *win)
void select_path_reverse(InkscapeWindow *win)
const Glib::ustring SECTION
void select_path_exclusion(InkscapeApplication *app)
void select_path_fracture(InkscapeApplication *app)
void select_path_simplify(InkscapeApplication *app)
void select_path_intersection(InkscapeApplication *app)
void select_path_offset(InkscapeWindow *win)
void select_path_offset_screen(const Glib::VariantBase &value, InkscapeWindow *win)
void select_path_inset_screen(const Glib::VariantBase &value, InkscapeWindow *win)
void select_path_division(InkscapeApplication *app)
void select_path_flatten(InkscapeApplication *app)
void fill_between_paths(InkscapeApplication *app)
void shape_builder_replace(InkscapeWindow *win)
void select_path_cut(InkscapeApplication *app)
void select_path_combine(InkscapeApplication *app)
void object_path_union(InkscapeApplication *app)
void select_path_split(InkscapeApplication *app)
static const std::vector< std::vector< Glib::ustring > > raw_data_path
void select_path_offset_linked(InkscapeWindow *win)
void select_path_break_apart(InkscapeApplication *app)
void shape_builder_mode(int value, InkscapeWindow *win)
void select_path_difference(InkscapeApplication *app)
void add_actions_path(InkscapeApplication *app)
void set_active_tool(InkscapeWindow *win, Glib::ustring const &tool)
void add_data(std::vector< std::vector< Glib::ustring > > const &raw_data)
InkActionExtraData & get_action_extra_data()
Gio::Application * gio_app()
The Gio application instance, never NULL.
Inkscape::Selection * get_active_selection()
SPDesktop * get_desktop()
static void done(SPDocument *document, Glib::ustring const &event_description, Glib::ustring const &undo_icon, unsigned int object_modified_tag=0)
void breakApart(bool skip_undo=false, bool overlapping=true, bool silent=false)
void removeLPESRecursive(bool keep_paths)
bool strokesToPaths(bool legacy=false, bool skip_undo=false)
bool unlinkRecursive(const bool skip_undo=false, const bool force=false, const bool silent=false)
Recursively unlink any clones present in the current selection, including clones which are used to cl...
bool simplifyPaths(bool skip_undo=false)
void fillBetweenMany()
Creates a linked fill between all the objects in the current selection using the "Fill Between Many" ...
Preference storage class.
Definition preferences.h:61
static Preferences * get()
Access the singleton Preferences object.
void setInt(Glib::ustring const &pref_path, int value)
Set an integer value.
void setBool(Glib::ustring const &pref_path, bool value)
Set a Boolean value.
To do: update description of desktop.
Definition desktop.h:149
Inkscape::Selection * getSelection() const
Definition desktop.h:188
Editable view implementation.
TODO: insert short description here.
Macro for icon names used in Inkscape.
Inkscape - An SVG editor.
void sp_selected_path_create_updating_offset_object_zero(SPDesktop *desktop)
void sp_selected_path_offset(SPDesktop *desktop)
void sp_selected_path_inset_screen(SPDesktop *desktop, double pixels)
void sp_selected_path_create_offset_object_zero(SPDesktop *desktop)
void sp_selected_path_offset_screen(SPDesktop *desktop, double pixels)
void sp_selected_path_inset(SPDesktop *desktop)
Path offsets.
Singleton class to access the preferences file in a convenient way.