Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
object-set.h
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Multiindex container for selection
4 *
5 * Authors:
6 * Adrian Boguszewski
7 * Marc Jeanmougin
8 *
9 * Copyright (C) 2016 Adrian Boguszewski
10 *
11 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
12 */
13
14#ifndef INKSCAPE_PROTOTYPE_OBJECTSET_H
15#define INKSCAPE_PROTOTYPE_OBJECTSET_H
16
17#include <string>
18#include <unordered_map>
19
20#include <boost/multi_index_container.hpp>
21#include <boost/multi_index/identity.hpp>
22#include <boost/multi_index/sequenced_index.hpp>
23#include <boost/multi_index/hashed_index.hpp>
24#include <boost/multi_index/random_access_index.hpp>
25#include <boost/range/adaptor/filtered.hpp>
26#include <boost/range/adaptor/transformed.hpp>
27#include <boost/range/sub_range.hpp>
28#include <boost/range/any_range.hpp>
29#include <boost/type_traits.hpp>
30#include <boost/utility/enable_if.hpp>
31
32#include <sigc++/connection.h>
33
34#include "sp-object.h"
35#include "sp-item.h"
36#include "sp-item-group.h"
37#include "livarot/LivarotDefs.h"
38
45enum class SiblingState {
46 SIBLING_NONE, // no relation to item
47 SIBLING_CLONE_ORIGINAL, // moving both a clone and its original or any ancestor
48 SIBLING_OFFSET_SOURCE, // moving both an offset and its source
49 SIBLING_TEXT_PATH, // moving both a text-on-path and its path
50 SIBLING_TEXT_FLOW_FRAME, // moving both a flowtext and its frame
51 SIBLING_TEXT_SHAPE_INSIDE, // moving object containing sub object
52};
53
54class SPDocument;
55class SPDesktop;
56
57class SPBox3D;
58class Persp3D;
59
60namespace Inkscape {
61
62namespace XML {
63class Node;
64}
65
66struct hashed{};
68
69struct is_item {
70 bool operator()(SPObject* obj) {
71 return is<SPItem>(obj);
72 }
73};
74
75struct is_group {
76 bool operator()(SPObject* obj) {
77 return is<SPGroup>(obj);
78 }
79};
80
83 SPItem* operator()(SPObject* obj) const {
84 return cast<SPItem>(obj);
85 }
86};
87
91 return obj->getRepr();
92 }
93};
94
98 return cast<SPGroup>(obj);
99 }
100};
101
102typedef boost::multi_index_container<
103 SPObject*,
104 boost::multi_index::indexed_by<
105 boost::multi_index::sequenced<>,
106 boost::multi_index::random_access<
107 boost::multi_index::tag<random_access>>,
108 boost::multi_index::hashed_unique<
109 boost::multi_index::tag<hashed>,
110 boost::multi_index::identity<SPObject*>>
112
113typedef boost::any_range<
114 SPObject*,
115 boost::random_access_traversal_tag,
116 SPObject* const&,
117 std::ptrdiff_t> SPObjectRange;
118
120public:
122 typedef decltype(MultiIndexContainer().get<random_access>() | boost::adaptors::filtered(is_item()) | boost::adaptors::transformed(object_to_item())) SPItemRange;
123 typedef decltype(MultiIndexContainer().get<random_access>() | boost::adaptors::filtered(is_group()) | boost::adaptors::transformed(object_to_group())) SPGroupRange;
124 typedef decltype(MultiIndexContainer().get<random_access>() | boost::adaptors::filtered(is_item()) | boost::adaptors::transformed(object_to_node())) XMLNodeRange;
125
127 ObjectSet(SPDocument* doc): _desktop(nullptr), _document(doc) {};
128 ObjectSet(): _desktop(nullptr), _document(nullptr) {}; // Used in spray-tool.h.
129 virtual ~ObjectSet();
130
131 ObjectSet(ObjectSet const &) = delete;
132 ObjectSet &operator=(ObjectSet const &) = delete;
133
135 _document = doc;
136 }
137
138
145 bool add(SPObject *object, bool nosignal = false);
146
152 void add(XML::Node *repr);
153
158 template <typename InputIterator>
159 void add(InputIterator from, InputIterator to) {
160 for(auto it = from; it != to; ++it) {
161 _add(*it);
162 }
163 _emitChanged();
164 }
165
175 bool remove(SPObject* object);
176
180 bool includes(SPObject *object, bool anyAncestor = false);
181 bool includes(Inkscape::XML::Node *node, bool anyAncestor = false);
182
187
193 void set(SPObject *object, bool persist_selection_context = false);
194 void set(XML::Node *repr);
198 void clear();
199
203 int size();
204
208 bool isEmpty();
209
215 void toggle(SPObject *obj);
216
222 SPObject *single();
223
230
234 SPItem *firstItem() const;
235
239 SPItem *lastItem() const;
240
245
250
253
257 | boost::adaptors::filtered(is_item())
258 | boost::adaptors::transformed(object_to_item()));
259 };
260
261 std::vector<SPItem*> items_vector() {
262 auto i = items();
263 return {i.begin(), i.end()};
264 }
265
269 | boost::adaptors::filtered(is_group())
270 | boost::adaptors::transformed(object_to_group()));
271 }
272
276 | boost::adaptors::filtered(is_item())
277 | boost::adaptors::transformed(object_to_node()));
278 }
279
286
290 XML::Node *topRepr() const;
291
297 template <class T>
298 typename boost::enable_if<boost::is_base_of<SPObject, T>, void>::type
299 setList(const std::vector<T*> &objs) {
300 _clear();
301 addList(objs);
302 }
303
311 void setReprList(std::vector<XML::Node*> const &list);
312
317 void enforceIds();
318
324 template <class T>
325 typename boost::enable_if<boost::is_base_of<SPObject, T>, void>::type
326 addList(const std::vector<T*> &objs) {
327 for (auto obj: objs) {
328 if (!includes(obj)) {
329 add(obj, true);
330 }
331 }
332 _emitChanged();
333 }
334
340
346
347 /* Returns the bounding rectangle of the selectionin document coordinates.*/
349
355
359 std::optional<Geom::Point> center() const;
360
363 std::list<Persp3D *> const perspList();
364
369 std::list<SPBox3D *> const box3DList(Persp3D *persp = nullptr);
370
377
384
385 //item groups operations
386 //in selection-chemistry.cpp
387 void deleteItems(bool skip_undo = false);
388 void duplicate(bool suppressDone = false, bool duplicateLayer = false);
389 void clone(bool skip_undo = false);
390
396 bool unlink(const bool skip_undo = false, const bool silent = false);
402 bool unlinkRecursive(const bool skip_undo = false, const bool force = false, const bool silent = false);
403 void removeLPESRecursive(bool keep_paths);
404 void relink();
405 void cloneOriginal();
406 void cloneOriginalPathLPE(bool allow_transforms = false, bool sync = false, bool skip_undo = false);
407 Inkscape::XML::Node* group(bool is_anchor = false);
408 void popFromGroup();
409 void ungroup(bool skip_undo = false);
410 void ungroup_all(bool skip_undo = false);
411
412 //z-order management
413 //in selection-chemistry.cpp
414 void stackUp(bool skip_undo = false);
415 void raise(bool skip_undo = false);
416 void raiseToTop(bool skip_undo = false);
417 void stackDown(bool skip_undo = false);
418 void lower(bool skip_undo = false);
419 void lowerToBottom(bool skip_undo = false);
420 void toNextLayer(bool skip_undo = false);
421 void toPrevLayer(bool skip_undo = false);
422 void toLayer(SPObject *layer);
423 void toLayer(SPObject *layer, Inkscape::XML::Node *after);
424
425 //clipboard management
426 //in selection-chemistry.cpp
427 void copy();
428 void cut();
429 void pasteStyle();
430 void pasteSize(bool apply_x, bool apply_y);
431 void pasteSizeSeparately(bool apply_x, bool apply_y);
432 void pastePathEffect();
433
434 //path operations
435 //in path-chemistry.cpp
436 void combine(bool skip_undo = false, bool silent = false);
437 void breakApart(bool skip_undo = false, bool overlapping = true, bool silent = false);
438 void toCurves(bool skip_undo = false, bool clonesjustunlink = false);
439 void toLPEItems();
440 void pathReverse();
441
442 // path operations
443 // in path/path-object-set.cpp
444 bool strokesToPaths(bool legacy = false, bool skip_undo = false);
445 bool simplifyPaths(bool skip_undo = false);
446
447 // Boolean operations
448 void pathUnion (bool skip_undo = false, bool silent = false);
449 void pathIntersect(bool skip_undo = false, bool silent = false);
450 void pathDiff (bool skip_undo = false, bool silent = false);
451 void pathSymDiff (bool skip_undo = false, bool silent = false);
452 void pathCut (bool skip_undo = false, bool silent = false);
453 void pathSlice (bool skip_undo = false, bool silent = false);
454
455 // Other path operations
456 // in selection-chemistry.cpp
457 void toMarker(bool apply = true);
458 void toGuides();
459 void toSymbol();
460 void unSymbol();
461 void tile(bool apply = true); //"Object to Pattern"
462 void untile();
463 void createBitmapCopy();
464 void setMask(bool apply_clip_path, bool apply_to_layer, bool remove_original);
465 void editMask(bool clip);
466 void unsetMask(const bool apply_clip_path, const bool delete_helper_group, bool remove_original);
467 void setClipGroup();
468 void chameleonFill();
469
470 // moves
471 // in selection-chemistry.cpp
472 void removeLPE();
473 void removeFilter();
474 void reapplyAffine();
475 void clearLastAffine();
476 void applyAffine(Geom::Affine const &affine, bool set_i2d=true,bool compensate=true, bool adjust_transf_center=true);
478 void removeTransform();
479 void setScaleAbsolute(double, double, double, double);
480 void scaleRelative(const Geom::Point&, const Geom::Scale&);
481 void rotateRelative(const Geom::Point&, double);
482 void skewRelative(const Geom::Point&, double, double);
483 void moveRelative(const Geom::Point &move, bool compensate = true);
484 void moveRelative(double dx, double dy);
485 void move(double dx, double dy);
486 void moveScreen(double dx, double dy);
487 void move(double dx, double dy, bool rotated);
488 void move(double dx, double dy, bool rotated, bool screen);
489 void moveScreen(double dx, double dy, bool rotated);
490
491 // various
492 bool fitCanvas(bool with_margins, bool skip_undo = false);
493 void swapFillStroke();
494 void fillBetweenMany();
495
498 void clearSiblingStates();
499
500protected:
501 virtual void _connectSignals(SPObject* object) {};
502 virtual void _releaseSignals(SPObject* object) {};
503 virtual void _emitChanged(bool persist_selection_context = false);
504 void _add(SPObject* object);
505 void _clear();
506 void _remove(SPObject* object);
507 bool _anyAncestorIsInSet(SPObject *object);
509 void _removeAncestorsFromSet(SPObject *object);
510 SPItem *_sizeistItem(bool sml, CompareSize compare);
512 virtual void _add3DBoxesRecursively(SPObject *obj);
513 virtual void _remove3DBoxesRecursively(SPObject *obj);
514
516 SPDesktop * _desktop = nullptr;
518 std::list<SPBox3D *> _3dboxes;
519 std::unordered_map<SPObject*, sigc::connection> _releaseConnections;
520
521private:
522 void _pathBoolOp(BooleanOp bop, char const *icon_name, char const *description, bool skip_undo, bool silent);
523 void _pathBoolOp(BooleanOp bop);
524
525 void _disconnect(SPObject* object);
526 std::map<SPObject *, SiblingState> _sibling_state;
527
529};
530
534
535} // namespace Inkscape
536
537#endif // INKSCAPE_PROTOTYPE_OBJECTSET_H
538
539/*
540 Local Variables:
541 mode:c++
542 c-file-style:"stroustrup"
543 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
544 indent-tabs-mode:nil
545 fill-column:99
546 End:
547*/
548// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
TODO: insert short description here.
BooleanOp
Definition LivarotDefs.h:76
Geom::IntRect bounds
Definition canvas.cpp:182
3x3 matrix representing an affine transformation.
Definition affine.h:70
Axis-aligned rectangle that can be empty.
Definition rect.h:203
Two-dimensional point that doubles as a vector.
Definition point.h:66
Scaling from the origin.
Definition transforms.h:150
void enforceIds()
Assign IDs to selected objects that don't have an ID attribute Checks if the object's id attribute is...
SPItem * smallestItem(CompareSize compare)
Returns the smallest item from this selection.
void moveScreen(double dx, double dy)
SPObject * includesAncestor(SPObject *object)
Returns ancestor if the given object has ancestor selected.
void pasteSize(bool apply_x, bool apply_y)
void _remove(SPObject *object)
SPGroupRange groups()
Returns a range of selected groups.
Definition object-set.h:267
Inkscape::XML::Node * group(bool is_anchor=false)
void stackDown(bool skip_undo=false)
void pasteSizeSeparately(bool apply_x, bool apply_y)
SPItem * lastItem() const
Returns the last selected item, returns nullptr if no items selected.
SPDesktop * desktop()
Returns the desktop the selection is bound to.
Definition object-set.h:376
void toNextLayer(bool skip_undo=false)
bool remove(SPObject *object)
Removes an item from the set of selected objects.
bool unlink(const bool skip_undo=false, const bool silent=false)
Unlink all directly selected clones.
void breakApart(bool skip_undo=false, bool overlapping=true, bool silent=false)
void move(double dx, double dy)
SPItemRange items()
Returns a range of selected SPItems.
Definition object-set.h:255
void pathUnion(bool skip_undo=false, bool silent=false)
void removeLPESRecursive(bool keep_paths)
void _disconnect(SPObject *object)
void unsetMask(const bool apply_clip_path, const bool delete_helper_group, bool remove_original)
Geom::OptRect preferredBounds() const
Returns either the visual or geometric bounding rectangle of the selection, based on the preferences ...
void cloneOriginalPathLPE(bool allow_transforms=false, bool sync=false, bool skip_undo=false)
This applies the Fill Between Many LPE, and has it refer to the selection.
void rotateRelative(const Geom::Point &, double)
virtual void _remove3DBoxesRecursively(SPObject *obj)
void pathCut(bool skip_undo=false, bool silent=false)
bool add(SPObject *object, bool nosignal=false)
Add an SPObject to the set of selected objects.
boost::enable_if< boost::is_base_of< SPObject, T >, void >::type setList(const std::vector< T * > &objs)
Selects exactly the specified objects.
Definition object-set.h:299
XMLNodeRange xmlNodes()
Returns a range of the xml nodes of all selected objects.
Definition object-set.h:274
void raiseToTop(bool skip_undo=false)
void stackUp(bool skip_undo=false)
void setReprList(std::vector< XML::Node * > const &list)
Selects the objects with the same IDs as those in list.
void applyAffine(Geom::Affine const &affine, bool set_i2d=true, bool compensate=true, bool adjust_transf_center=true)
Apply matrix to the selection.
SPItem * largestItem(CompareSize compare)
Returns the largest item from this selection.
void add(InputIterator from, InputIterator to)
Add items from an STL iterator range to the selection.
Definition object-set.h:159
bool strokesToPaths(bool legacy=false, bool skip_undo=false)
Geom::OptRect documentPreferredBounds() const
Returns either the visual or geometric bounding rectangle of selection in document coordinates based ...
void pathDiff(bool skip_undo=false, bool silent=false)
std::list< SPBox3D * > _3dboxes
Definition object-set.h:518
SPDocument * _document
Definition object-set.h:517
decltype(MultiIndexContainer().get< random_access >()|boost::adaptors::filtered(is_item())|boost::adaptors::transformed(object_to_item())) SPItemRange
Definition object-set.h:122
void moveRelative(const Geom::Point &move, bool compensate=true)
Geom::Affine _last_affine
Definition object-set.h:528
void duplicate(bool suppressDone=false, bool duplicateLayer=false)
SPItem * _sizeistItem(bool sml, CompareSize compare)
void setDocument(SPDocument *doc)
Definition object-set.h:134
void pathIntersect(bool skip_undo=false, bool silent=false)
void toMarker(bool apply=true)
std::unordered_map< SPObject *, sigc::connection > _releaseConnections
Definition object-set.h:519
void pathSymDiff(bool skip_undo=false, bool silent=false)
void toPrevLayer(bool skip_undo=false)
void reapplyAffine()
Reapply the same transform again.
std::optional< Geom::Point > center() const
Returns the rotation/skew center of the selection.
void _add(SPObject *object)
Geom::OptRect strokedBounds() const
void clear()
Unselects all selected objects.
virtual void _emitChanged(bool persist_selection_context=false)
std::list< SPBox3D * > const box3DList(Persp3D *persp=nullptr)
Returns a list of all 3D boxes in the current selection which are associated to persp.
Geom::OptRect geometricBounds() const
virtual void _add3DBoxesRecursively(SPObject *obj)
virtual void _releaseSignals(SPObject *object)
Definition object-set.h:502
ObjectSet & operator=(ObjectSet const &)=delete
void ungroup_all(bool skip_undo=false)
Keep ungrouping until there are no more groups.
boost::enable_if< boost::is_base_of< SPObject, T >, void >::type addList(const std::vector< T * > &objs)
Adds the specified objects to selection, without deselecting first.
Definition object-set.h:326
void deleteItems(bool skip_undo=false)
SPObject * single()
Returns a single selected object.
void ungroup(bool skip_undo=false)
void skewRelative(const Geom::Point &, double, double)
void toLPEItems()
Converts the selected items to LPEItems if they are not already so; e.g.
bool isEmpty()
Returns true if no items are selected.
void tile(bool apply=true)
std::map< SPObject *, SiblingState > _sibling_state
Definition object-set.h:526
Geom::OptRect documentBounds(SPItem::BBoxType type) const
int size()
Returns size of the selection.
SPDesktop * _desktop
Definition object-set.h:516
void scaleRelative(const Geom::Point &, const Geom::Scale &)
SPDocument * document()
Returns the document the selection is bound to.
Definition object-set.h:383
void _removeAncestorsFromSet(SPObject *object)
void raise(bool skip_undo=false)
bool _anyAncestorIsInSet(SPObject *object)
SPItem * firstItem() const
Returns the first selected item, returns nullptr if no items selected.
void toCurves(bool skip_undo=false, bool clonesjustunlink=false)
void combine(bool skip_undo=false, bool silent=false)
void lowerToBottom(bool skip_undo=false)
void lower(bool skip_undo=false)
void toggle(SPObject *obj)
Removes an item if selected, adds otherwise.
void _removeDescendantsFromSet(SPObject *object)
bool includes(SPObject *object, bool anyAncestor=false)
Returns true if the given object is selected.
SPItem * singleItem()
Returns a single selected item.
void setScaleAbsolute(double, double, double, double)
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...
SPObjectRange objects()
Returns the list of selected objects.
void insertSiblingState(SPObject *object, SiblingState state)
virtual void _connectSignals(SPObject *object)
Definition object-set.h:501
decltype(MultiIndexContainer().get< random_access >()|boost::adaptors::filtered(is_item())|boost::adaptors::transformed(object_to_node())) XMLNodeRange
Definition object-set.h:124
void clone(bool skip_undo=false)
decltype(MultiIndexContainer().get< random_access >()|boost::adaptors::filtered(is_group())|boost::adaptors::transformed(object_to_group())) SPGroupRange
Definition object-set.h:123
void toLayer(SPObject *layer)
Move selection to group moveto, after the last child of moveto (if it has any children).
void setMask(bool apply_clip_path, bool apply_to_layer, bool remove_original)
Creates a mask or clipPath from selection.
XML::Node * singleRepr()
Returns a single selected object's xml node.
bool simplifyPaths(bool skip_undo=false)
std::vector< SPItem * > items_vector()
Definition object-set.h:261
bool fitCanvas(bool with_margins, bool skip_undo=false)
XML::Node * topRepr() const
The top-most item, or NULL if the selection is empty.
MultiIndexContainer _container
Definition object-set.h:515
void _pathBoolOp(BooleanOp bop, char const *icon_name, char const *description, bool skip_undo, bool silent)
Geom::OptRect visualBounds() const
void pathSlice(bool skip_undo=false, bool silent=false)
SPObject * _getMutualAncestor(SPObject *object)
std::list< Persp3D * > const perspList()
Returns a list of all perspectives which have a 3D box in the current selection.
ObjectSet(ObjectSet const &)=delete
void fillBetweenMany()
Creates a linked fill between all the objects in the current selection using the "Fill Between Many" ...
SiblingState getSiblingState(SPItem *item)
Associates the given SPItem with a SiblingState enum Needed for handling special cases while transfor...
Interface for refcounted XML nodes.
Definition node.h:80
To do: update description of desktop.
Definition desktop.h:149
Typed SVG document implementation.
Definition document.h:103
Base class for visual SVG elements.
Definition sp-item.h:109
SPObject is an abstract base class of all of the document nodes at the SVG document level.
Definition sp-object.h:160
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
SPItem * item
Inkscape::XML::Node * node
Helper class to stream background task notifications as a series of messages.
boost::multi_index_container< SPObject *, boost::multi_index::indexed_by< boost::multi_index::sequenced<>, boost::multi_index::random_access< boost::multi_index::tag< random_access > >, boost::multi_index::hashed_unique< boost::multi_index::tag< hashed >, boost::multi_index::identity< SPObject * > > > > MultiIndexContainer
Definition object-set.h:111
ObjectSet::SPGroupRange SPGroupRange
Definition object-set.h:532
ObjectSet::XMLNodeRange XMLNodeRange
Definition object-set.h:533
ObjectSet::SPItemRange SPItemRange
Definition object-set.h:531
boost::any_range< SPObject *, boost::random_access_traversal_tag, SPObject *const &, std::ptrdiff_t > SPObjectRange
Definition object-set.h:117
static T clip(T const &v, T const &a, T const &b)
SiblingState
SiblingState enums are used to associate the current state while grabbing objects.
Definition object-set.h:45
@ SIBLING_CLONE_ORIGINAL
@ SIBLING_TEXT_SHAPE_INSIDE
@ SIBLING_TEXT_FLOW_FRAME
GLsync sync
Some things pertinent to all visible shapes: SPItem, SPItemView, SPItemCtx.
bool operator()(SPObject *obj)
Definition object-set.h:76
bool operator()(SPObject *obj)
Definition object-set.h:70
SPGroup * operator()(SPObject *obj) const
Definition object-set.h:97
SPItem * operator()(SPObject *obj) const
Definition object-set.h:83
XML::Node * operator()(SPObject *obj) const
Definition object-set.h:90