Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
actions-canvas-snapping.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Gio::Actions for toggling snapping preferences. Not tied to a particular document.
4 *
5 * As preferences are stored per document, changes should be propagated to any window with same document.
6 *
7 * Copyright (C) 2019 Tavmjong Bah
8 *
9 * The contents of this file may be used under the GNU General Public License Version 2 or later.
10 */
11
13
14#include <unordered_map>
15#include <giomm/actionmap.h>
16#include <glibmm/i18n.h>
17#include <glibmm/ustring.h>
18
19#include "actions-helper.h"
22#include "inkscape.h"
23#include "inkscape-window.h"
24#include "desktop.h"
25#include "preferences.h"
26#include "snap-preferences.h"
27
28using namespace Inkscape;
29
30void set_actions_canvas_snapping(Gio::ActionMap& map);
31
32// There are two snapping lists that must be connected:
33// 1. The Inkscape::SNAPTARGET value: e.g. Inkscape::SNAPTARGET_BBOX_CATEGORY.
34// 2. The Gio::Action name: e.g. "snap-bbox"
35
36struct SnapInfo {
37 Glib::ustring action_name; // action name without "doc." prefix
38 SnapTargetType type; // corresponding snapping type
39 bool set; // this is default for when "simple snapping" is ON and also initial value when preferences are deleted
40};
41
42typedef std::vector<SnapInfo> SnapVector;
43typedef std::unordered_map<SnapTargetType, Glib::ustring> SnapMap;
44
46 { "snap-bbox", SNAPTARGET_BBOX_CATEGORY, true },
47 { "snap-bbox-edge", SNAPTARGET_BBOX_EDGE, true },
48 { "snap-bbox-corner", SNAPTARGET_BBOX_CORNER, true },
49 { "snap-bbox-edge-midpoint", SNAPTARGET_BBOX_EDGE_MIDPOINT, false },
50 { "snap-bbox-center", SNAPTARGET_BBOX_MIDPOINT, false },
51};
52
54 { "snap-node-category", SNAPTARGET_NODE_CATEGORY, true },
55 { "snap-path", SNAPTARGET_PATH, true },
56 { "snap-path-intersection", SNAPTARGET_PATH_INTERSECTION, false }, // Note: OFF by default, as it is extremely slow in large documents!
57 { "snap-node-cusp", SNAPTARGET_NODE_CUSP, true },
58 { "snap-node-smooth", SNAPTARGET_NODE_SMOOTH, true },
59 { "snap-line-midpoint", SNAPTARGET_LINE_MIDPOINT, true },
60 { "snap-line-tangential", SNAPTARGET_PATH_TANGENTIAL, false },
61 { "snap-line-perpendicular", SNAPTARGET_PATH_PERPENDICULAR, false },
62};
63
65 { "snap-alignment", SNAPTARGET_ALIGNMENT_CATEGORY, true },
66 { "snap-alignment-self", SNAPTARGET_ALIGNMENT_HANDLE, false },
67 // separate category:
68 { "snap-distribution", SNAPTARGET_DISTRIBUTION_CATEGORY, true },
69};
70
72 { "snap-others", SNAPTARGET_OTHERS_CATEGORY, true },
73 { "snap-object-midpoint", SNAPTARGET_OBJECT_MIDPOINT, false },
74 { "snap-rotation-center", SNAPTARGET_ROTATION_CENTER, false },
75 { "snap-text-baseline", SNAPTARGET_TEXT_BASELINE, true },
76 { "snap-path-mask", SNAPTARGET_PATH_MASK, true },
77 { "snap-path-clip", SNAPTARGET_PATH_CLIP, true },
78
79 { "snap-page-border", SNAPTARGET_PAGE_EDGE_BORDER, true },
80 { "snap-page-margin", SNAPTARGET_PAGE_MARGIN_BORDER, true },
81 { "snap-grid", SNAPTARGET_GRID, true },
82 { "snap-grid-line", SNAPTARGET_GRID_LINE, true },
83 { "snap-guide", SNAPTARGET_GUIDE, true },
84};
85
86const struct {const char* action_name; SimpleSnap option; bool set;} simple_snap_options[] = {
87 { "simple-snap-bbox", SimpleSnap::BBox, true },
88 { "simple-snap-nodes", SimpleSnap::Nodes, true },
89 { "simple-snap-alignment", SimpleSnap::Alignment, false }
90};
91
93 static SnapMap map;
94 if (map.empty()) {
95 for (auto&& snap : snap_bbox) { map[snap.type] = snap.action_name; }
96 for (auto&& snap : snap_node) { map[snap.type] = snap.action_name; }
97 for (auto&& snap : snap_alignment) { map[snap.type] = snap.action_name; }
98 for (auto&& snap : snap_all_the_rest) { map[snap.type] = snap.action_name; }
99 }
100 return map;
101}
102
104 static SnapVector vect;
105 if (vect.empty()) {
106 for (auto v : {&snap_bbox, &snap_node, &snap_alignment, &snap_all_the_rest}) {
107 vect.insert(vect.end(), v->begin(), v->end());
108 }
109 }
110 return vect;
111}
112
113const Glib::ustring snap_pref_path = "/options/snapping/";
114const Glib::ustring global_toggle = "snap-global-toggle";
115
116// global and single location of snapping preferences
118 static SnapPreferences preferences;
119 static bool initialized = false;
120
121 if (!initialized) {
122 // after starting up restore all snapping preferences:
123 auto prefs = Preferences::get();
124 for (auto&& info : get_snap_vect()) {
125 bool enabled = prefs->getBool(snap_pref_path + info.action_name, info.set);
126 preferences.setTargetSnappable(info.type, enabled);
127 }
128 for (auto&& info : simple_snap_options) {
129 bool enabled = prefs->getBool(snap_pref_path + info.action_name, info.set);
130 preferences.set_simple_snap(info.option, enabled);
131 }
132
133 auto simple = prefs->getEntry("/toolbox/simplesnap");
134 if (!simple.isSet()) {
135 // first time up after creating preferences; apply "simple" snapping defaults
136 prefs->setBool(simple.getPath(), true);
138 }
139
140 auto enabled = prefs->getEntry(snap_pref_path + global_toggle);
141 preferences.setSnapEnabledGlobally(enabled.getBool());
142
143 initialized = true;
144 }
145
146 return preferences;
147}
148
149void store_snapping_action(const Glib::ustring& action_name, bool enabled) {
151}
152
153// Turn requested snapping type on or off:
154// * type - snap target
155// * enabled - true to turn it on, false to turn it off
156//
157void set_canvas_snapping(SnapTargetType type, bool enabled) {
159
160 auto it = get_snap_map().find(type);
161 if (it == get_snap_map().end()) {
162 g_warning("No action for snap target type %d", int(type));
163 }
164 else {
165 auto&& action_name = it->second;
167 }
168}
169
170void update_actions(Gio::ActionMap& map) {
171 // Some actions depend on others... we need to update everything!
173}
174
175static void canvas_snapping_toggle(Gio::ActionMap& map, SnapTargetType type) {
176 bool enabled = get_snapping_preferences().isSnapButtonEnabled(type);
177 set_canvas_snapping(type, !enabled);
178 update_actions(map);
179}
180
182 const SnapVector* vect = nullptr;
183 switch (option) {
184 case SimpleSnap::BBox:
185 vect = &snap_bbox;
186 break;
187 case SimpleSnap::Nodes:
188 vect = &snap_node;
189 break;
190 case SimpleSnap::Alignment:
191 vect = &snap_alignment;
192 break;
193 case SimpleSnap::Rest:
194 vect = &snap_all_the_rest;
195 break;
196 default:
197 show_output(Glib::ustring("missing case statement in ") + __func__);
198 break;
199 }
200
201 if (vect) {
202 for (auto&& info : *vect) {
203 bool enable = value && info.set;
204 set_canvas_snapping(info.type, enable);
205 }
206
207 Glib::ustring action_name;
208 for (auto&& info : simple_snap_options) {
209 if (info.option == option) {
210 action_name = info.action_name;
211 break;
212 }
213 }
214 // simple snap option 'Rest' does not have an action; only save other ones
215 if (!action_name.empty()) {
218 }
219 }
220}
221
222void toggle_simple_snap_option(Gio::ActionMap& map, SimpleSnap option) {
223 // toggle desired option
225 set_simple_snap(option, enabled);
226
227 // reset others not visible / not exposed to their "simple" defaults
228 for (auto&& info : snap_all_the_rest) {
229 set_canvas_snapping(info.type, info.set);
230 }
231
232 update_actions(map);
233}
234
235void apply_simple_snap_defaults(Gio::ActionMap& map) {
236 set_simple_snap(SimpleSnap::BBox, true);
237 set_simple_snap(SimpleSnap::Nodes, true);
238 set_simple_snap(SimpleSnap::Alignment, false);
239 set_simple_snap(SimpleSnap::Rest, true);
240 update_actions(map);
241}
242
243const Glib::ustring SECTION = NC_("Action Section", "Snap");
244
245std::vector<std::vector<Glib::ustring>> raw_data_canvas_snapping =
246{
247 {"win.snap-global-toggle", N_("Snapping"), SECTION, N_("Toggle snapping on/off") },
248
249 {"win.snap-alignment", N_("Snap Objects that Align"), SECTION, N_("Toggle alignment snapping") },
250 {"win.snap-alignment-self", N_("Snap Nodes that Align"), SECTION, N_("Toggle alignment snapping to nodes in the same path")},
251
252 {"win.snap-distribution", N_("Snap Objects at Equal Distances"), SECTION, N_("Toggle snapping objects at equal distances")},
253
254 {"win.snap-bbox", N_("Snap Bounding Boxes"), SECTION, N_("Toggle snapping to bounding boxes (global)") },
255 {"win.snap-bbox-edge", N_("Snap Bounding Box Edges"), SECTION, N_("Toggle snapping to bounding-box edges") },
256 {"win.snap-bbox-corner", N_("Snap Bounding Box Corners"), SECTION, N_("Toggle snapping to bounding-box corners") },
257 {"win.snap-bbox-edge-midpoint", N_("Snap Bounding Box Edge Midpoints"), SECTION, N_("Toggle snapping to bounding-box edge mid-points") },
258 {"win.snap-bbox-center", N_("Snap Bounding Box Centers"), SECTION, N_("Toggle snapping to bounding-box centers") },
259
260 {"win.snap-node-category", N_("Snap Nodes"), SECTION, N_("Toggle snapping to nodes (global)") },
261 {"win.snap-path", N_("Snap Paths"), SECTION, N_("Toggle snapping to paths") },
262 {"win.snap-path-intersection", N_("Snap Path Intersections"), SECTION, N_("Toggle snapping to path intersections") },
263 {"win.snap-node-cusp", N_("Snap Cusp Nodes"), SECTION, N_("Toggle snapping to cusp nodes, including rectangle corners")},
264 {"win.snap-node-smooth", N_("Snap Smooth Node"), SECTION, N_("Toggle snapping to smooth nodes, including quadrant points of ellipses")},
265 {"win.snap-line-midpoint", N_("Snap Line Midpoints"), SECTION, N_("Toggle snapping to midpoints of lines") },
266 {"win.snap-line-perpendicular", N_("Snap Perpendicular Lines"), SECTION, N_("Toggle snapping to perpendicular lines") },
267 {"win.snap-line-tangential", N_("Snap Tangential Lines"), SECTION, N_("Toggle snapping to tangential lines") },
268
269 {"win.snap-others", N_("Snap Others"), SECTION, N_("Toggle snapping to misc. points (global)") },
270 {"win.snap-object-midpoint", N_("Snap Object Midpoint"), SECTION, N_("Toggle snapping to object midpoint") },
271 {"win.snap-rotation-center", N_("Snap Rotation Center"), SECTION, N_("Toggle snapping to object rotation center") },
272 {"win.snap-text-baseline", N_("Snap Text Baselines"), SECTION, N_("Toggle snapping to text baseline and text anchors") },
273
274 {"win.snap-page-border", N_("Snap Page Border"), SECTION, N_("Toggle snapping to page border") },
275 {"win.snap-page-margin", N_("Snap Page Margin"), SECTION, N_("Toggle snapping to page margin") },
276 {"win.snap-grid", N_("Snap Grids"), SECTION, N_("Toggle snapping to grids") },
277 {"win.snap-grid-line", N_("Snap Grid Lines"), SECTION, N_("Toggle snapping to grid lines") },
278 {"win.snap-guide", N_("Snap Guide Lines"), SECTION, N_("Toggle snapping to guide lines") },
279
280 {"win.snap-path-mask", N_("Snap Mask Paths"), SECTION, N_("Toggle snapping to mask paths") },
281 {"win.snap-path-clip", N_("Snap Clip Paths"), SECTION, N_("Toggle snapping to clip paths") },
282
283 {"win.simple-snap-bbox", N_("Simple Snap Bounding Box"), SECTION, N_("Toggle snapping to bounding boxes") },
284 {"win.simple-snap-nodes", N_("Simple Snap Nodes"), SECTION, N_("Toggle snapping to nodes") },
285 {"win.simple-snap-alignment", N_("Simple Snap Alignment"), SECTION, N_("Toggle alignment snapping") },
286};
287
288void add_actions_canvas_snapping(Gio::ActionMap* map) {
289 assert(map != nullptr);
290
291 map->add_action_bool(global_toggle, [=]() {
292 auto& pref = get_snapping_preferences();
293 bool enabled = !pref.getSnapEnabledGlobally();
294 pref.setSnapEnabledGlobally(enabled);
296 update_actions(*map);
297 });
298
299 for (auto&& info : get_snap_vect()) {
300 map->add_action_bool(info.action_name, [=](){ canvas_snapping_toggle(*map, info.type); });
301 }
302
303 // Simple snapping popover
304 for (auto&& info : simple_snap_options) {
305 map->add_action_bool(info.action_name, [=](){ toggle_simple_snap_option(*map, info.option); });
306 }
307
308 // Check if there is already an application instance (GUI or non-GUI).
310 if (!app) {
311 show_output("add_actions_canvas_snapping: no app!");
312 return;
313 }
314 app->get_action_extra_data().add_data(raw_data_canvas_snapping);
315
316 update_actions(*map);
317}
318
319
320void
321set_actions_canvas_snapping_helper(Gio::ActionMap& map, Glib::ustring action_name, bool state, bool enabled)
322{
323 // Glib::RefPtr<Gio::SimpleAction> saction = map->lookup_action(action_name); NOT POSSIBLE!
324
325 // We can't enable/disable action directly! (Gio::Action can "get" enabled value but can not
326 // "set" it! We need to cast to Gio::SimpleAction)
327 Glib::RefPtr<Gio::Action> action = map.lookup_action(action_name);
328 if (!action) {
329 show_output(Glib::ustring("set_actions_canvas_snapping_helper: action ") + action_name.raw() + " missing!");
330 return;
331 }
332
333 auto simple = std::dynamic_pointer_cast<Gio::SimpleAction>(action);
334 if (!simple) {
335 show_output(Glib::ustring("set_actions_canvas_snapping_helper: action ") + action_name.raw() + " not SimpleAction!");
336 return;
337 }
338
339 simple->change_state(state);
340 simple->set_enabled(enabled);
341}
342
343void set_actions_canvas_snapping(Gio::ActionMap& map) {
344 auto& snapprefs = get_snapping_preferences();
345 bool global = snapprefs.getSnapEnabledGlobally();
346 bool alignment = snapprefs.isTargetSnappable(SNAPTARGET_ALIGNMENT_CATEGORY);
347 bool distribution = snapprefs.isTargetSnappable(SNAPTARGET_DISTRIBUTION_CATEGORY);
348 bool bbox = snapprefs.isTargetSnappable(SNAPTARGET_BBOX_CATEGORY);
349 bool node = snapprefs.isTargetSnappable(SNAPTARGET_NODE_CATEGORY);
350 bool other = snapprefs.isTargetSnappable(SNAPTARGET_OTHERS_CATEGORY);
351 bool grid = snapprefs.isTargetSnappable(SNAPTARGET_GRID);
352
353 struct { const char* action; bool state; bool enabled; } snap_options[] = {
354 { "snap-global-toggle", global, true }, // Always enabled
355
356 { "snap-alignment", alignment, global },
357 { "snap-alignment-self", snapprefs.isSnapButtonEnabled(SNAPTARGET_ALIGNMENT_HANDLE), global && alignment },
358 { "snap-distribution", distribution, global && alignment},
359
360 { "snap-bbox", bbox, global },
361 { "snap-bbox-edge", snapprefs.isSnapButtonEnabled(SNAPTARGET_BBOX_EDGE), global && bbox },
362 { "snap-bbox-corner", snapprefs.isSnapButtonEnabled(SNAPTARGET_BBOX_CORNER), global && bbox },
363 { "snap-bbox-edge-midpoint", snapprefs.isSnapButtonEnabled(SNAPTARGET_BBOX_EDGE_MIDPOINT), global && bbox },
364 { "snap-bbox-center", snapprefs.isSnapButtonEnabled(SNAPTARGET_BBOX_MIDPOINT), global && bbox },
365
366 { "snap-node-category", node, global },
367 { "snap-path", snapprefs.isSnapButtonEnabled(SNAPTARGET_PATH), global && node },
368 { "snap-path-intersection", snapprefs.isSnapButtonEnabled(SNAPTARGET_PATH_INTERSECTION), global && node },
369 { "snap-node-cusp", snapprefs.isSnapButtonEnabled(SNAPTARGET_NODE_CUSP), global && node },
370 { "snap-node-smooth", snapprefs.isSnapButtonEnabled(SNAPTARGET_NODE_SMOOTH), global && node },
371 { "snap-line-midpoint", snapprefs.isSnapButtonEnabled(SNAPTARGET_LINE_MIDPOINT), global && node },
372 { "snap-line-tangential", snapprefs.isSnapButtonEnabled(SNAPTARGET_PATH_TANGENTIAL), global && node },
373 { "snap-line-perpendicular", snapprefs.isSnapButtonEnabled(SNAPTARGET_PATH_PERPENDICULAR), global && node },
374
375 { "snap-others", other, global },
376 { "snap-object-midpoint", snapprefs.isSnapButtonEnabled(SNAPTARGET_OBJECT_MIDPOINT), global && other },
377 { "snap-rotation-center", snapprefs.isSnapButtonEnabled(SNAPTARGET_ROTATION_CENTER), global && other },
378 { "snap-text-baseline", snapprefs.isSnapButtonEnabled(SNAPTARGET_TEXT_BASELINE), global && other },
379
380 { "snap-path-clip", snapprefs.isSnapButtonEnabled(SNAPTARGET_PATH_CLIP), global && other},
381 { "snap-path-mask", snapprefs.isSnapButtonEnabled(SNAPTARGET_PATH_MASK), global && other},
382
383 { "snap-page-border", snapprefs.isSnapButtonEnabled(SNAPTARGET_PAGE_EDGE_BORDER), global },
384 { "snap-page-margin", snapprefs.isSnapButtonEnabled(SNAPTARGET_PAGE_MARGIN_BORDER), global },
385 { "snap-grid", snapprefs.isSnapButtonEnabled(SNAPTARGET_GRID), global },
386 { "snap-grid-line", snapprefs.isSnapButtonEnabled(SNAPTARGET_GRID_LINE), global && grid},
387 { "snap-guide", snapprefs.isSnapButtonEnabled(SNAPTARGET_GUIDE), global },
388
389 { "simple-snap-bbox", bbox, global },
390 { "simple-snap-nodes", node, global },
391 { "simple-snap-alignment", alignment, global },
392 };
393
394 for (auto&& snap : snap_options) {
395 set_actions_canvas_snapping_helper(map, snap.action, snap.state, snap.enabled);
396 }
397}
398
405 if (auto* dt = SP_ACTIVE_DESKTOP) {
406 if (Gio::ActionMap* map = dt->getInkscapeWindow()) {
408 }
409 }
410}
411
412/*
413 Local Variables:
414 mode:c++
415 c-file-style:"stroustrup"
416 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
417 indent-tabs-mode:nil
418 fill-column:99
419 End:
420*/
421// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
static void canvas_snapping_toggle(Gio::ActionMap &map, SnapTargetType type)
std::vector< SnapInfo > SnapVector
void transition_to_simple_snapping()
Simple snapping groups existing "advanced" options into three easy to understand choices (bounding bo...
void set_actions_canvas_snapping(Gio::ActionMap &map)
const Glib::ustring snap_pref_path
const struct @10 simple_snap_options[]
const Glib::ustring SECTION
void set_canvas_snapping(SnapTargetType type, bool enabled)
const char * action_name
void set_actions_canvas_snapping_helper(Gio::ActionMap &map, Glib::ustring action_name, bool state, bool enabled)
void apply_simple_snap_defaults(Gio::ActionMap &map)
const SnapMap & get_snap_map()
void add_actions_canvas_snapping(Gio::ActionMap *map)
const Glib::ustring global_toggle
SnapVector snap_bbox
void store_snapping_action(const Glib::ustring &action_name, bool enabled)
SnapVector snap_node
SnapPreferences & get_snapping_preferences()
void toggle_simple_snap_option(Gio::ActionMap &map, SimpleSnap option)
const SnapVector & get_snap_vect()
SnapVector snap_all_the_rest
SnapVector snap_alignment
std::vector< std::vector< Glib::ustring > > raw_data_canvas_snapping
void set_simple_snap(SimpleSnap option, bool value)
SimpleSnap option
void update_actions(Gio::ActionMap &map)
std::unordered_map< SnapTargetType, Glib::ustring > SnapMap
void show_output(Glib::ustring const &data, bool const is_cerr)
static InkscapeApplication * instance()
Singleton instance.
static Preferences * get()
Access the singleton Preferences object.
void setBool(Glib::ustring const &pref_path, bool value)
Set a Boolean value.
Storing of snapping preferences.
void setSnapEnabledGlobally(bool enabled)
void setTargetSnappable(Inkscape::SnapTargetType const target, bool enabled)
bool get_simple_snap(Inkscape::SimpleSnap option) const
bool isSnapButtonEnabled(Inkscape::SnapTargetType const target) const
void set_simple_snap(Inkscape::SimpleSnap option, bool enable)
Editable view implementation.
Inkscape::XML::Node * node
Inkscape - An SVG editor.
Geom::Point end
GType type()
Returns the type used for storing an object of type T inside a value.
Definition value-utils.h:29
Helper class to stream background task notifications as a series of messages.
@ SNAPTARGET_BBOX_EDGE_MIDPOINT
Definition snap-enums.h:78
@ SNAPTARGET_PAGE_MARGIN_BORDER
Definition snap-enums.h:108
@ SNAPTARGET_PATH
Definition snap-enums.h:85
@ SNAPTARGET_NODE_CUSP
Definition snap-enums.h:83
@ SNAPTARGET_ROTATION_CENTER
Definition snap-enums.h:117
@ SNAPTARGET_LINE_MIDPOINT
Definition snap-enums.h:84
@ SNAPTARGET_OTHERS_CATEGORY
Definition snap-enums.h:114
@ SNAPTARGET_BBOX_MIDPOINT
Definition snap-enums.h:79
@ SNAPTARGET_NODE_SMOOTH
Definition snap-enums.h:82
@ SNAPTARGET_ALIGNMENT_CATEGORY
Definition snap-enums.h:125
@ SNAPTARGET_PATH_CLIP
Definition snap-enums.h:90
@ SNAPTARGET_GUIDE
Definition snap-enums.h:100
@ SNAPTARGET_DISTRIBUTION_CATEGORY
Definition snap-enums.h:139
@ SNAPTARGET_NODE_CATEGORY
Definition snap-enums.h:81
@ SNAPTARGET_PAGE_EDGE_BORDER
Definition snap-enums.h:105
@ SNAPTARGET_GRID
Definition snap-enums.h:96
@ SNAPTARGET_ALIGNMENT_HANDLE
Definition snap-enums.h:134
@ SNAPTARGET_TEXT_BASELINE
Definition snap-enums.h:119
@ SNAPTARGET_BBOX_EDGE
Definition snap-enums.h:77
@ SNAPTARGET_PATH_MASK
Definition snap-enums.h:91
@ SNAPTARGET_OBJECT_MIDPOINT
Definition snap-enums.h:115
@ SNAPTARGET_BBOX_CORNER
Definition snap-enums.h:76
@ SNAPTARGET_GRID_LINE
Definition snap-enums.h:97
@ SNAPTARGET_PATH_TANGENTIAL
Definition snap-enums.h:87
@ SNAPTARGET_PATH_PERPENDICULAR
Definition snap-enums.h:86
@ SNAPTARGET_PATH_INTERSECTION
Definition snap-enums.h:88
@ SNAPTARGET_BBOX_CATEGORY
Definition snap-enums.h:73
Singleton class to access the preferences file in a convenient way.