1 // SPDX-License-Identifier: GPL-2.0-or-later 2 #ifndef SEEN_INKSCAPE_SELECTION_H 3 #define SEEN_INKSCAPE_SELECTION_H 4 /* 5 * Authors: 6 * Lauris Kaplinski <lauris@kaplinski.com> 7 * MenTaLguY <mental@rydia.net> 8 * bulia byak <buliabyak@users.sf.net> 9 * Adrian Boguszewski 10 * 11 * Copyright (C) 2016 Adrian Boguszewski 12 * Copyright (C) 2004-2005 MenTaLguY 13 * Copyright (C) 1999-2002 Lauris Kaplinski 14 * Copyright (C) 2001-2002 Ximian, Inc. 15 * 16 * Released under GNU GPL v2+, read the file 'COPYING' for more information. 17 */ 18 19 #include <vector> 20 #include <map> 21 #include <cstddef> 22 #include <sigc++/sigc++.h> 23 24 #include "inkgc/gc-managed.h" 25 #include "gc-finalized.h" 26 #include "gc-anchored.h" 27 #include "object/object-set.h" 28 29 30 namespace Inkscape { 31 class LayerModel; 32 namespace XML { 33 class Node; 34 } 35 } 36 37 namespace Inkscape { 38 39 /** 40 * The set of selected SPObjects for a given document and layer model. 41 * 42 * This class represents the set of selected SPItems for a given 43 * document (referenced in LayerModel). 44 * 45 * An SPObject and its parent cannot be simultaneously selected; 46 * selecting an SPObjects has the side-effect of unselecting any of 47 * its children which might have been selected. 48 * 49 * This is a per-desktop object that keeps the list of selected objects 50 * at the given desktop. Both SPItem and SPRepr lists can be retrieved 51 * from the selection. Many actions operate on the selection, so it is 52 * widely used throughout the code. 53 * It also implements its own asynchronous notification signals that 54 * UI elements can listen to. 55 */ 56 class Selection : public Inkscape::GC::Managed<>, 57 public Inkscape::GC::Finalized, 58 public Inkscape::GC::Anchored, 59 public ObjectSet 60 { 61 friend class ObjectSet; 62 public: 63 /** 64 * Constructs an selection object, bound to a particular 65 * layer model 66 * 67 * @param layers the layer model (for the SPDesktop, if GUI) 68 * @param desktop the desktop associated with the layer model, or NULL if in console mode 69 */ 70 Selection(LayerModel *layers, SPDesktop *desktop); 71 ~Selection() override; 72 73 /** no copy. */ 74 Selection(Selection const &) = delete; 75 /** no assign. */ 76 void operator=(Selection const &) = delete; 77 78 /** 79 * Returns the layer model the selection is bound to (works in console or GUI mode) 80 * 81 * @return the layer model the selection is bound to, which is the same as the desktop 82 * layer model for GUI mode 83 */ layers()84 LayerModel *layers() { return _layers; } 85 86 /** 87 * Returns active layer for selection (currentLayer or its parent). 88 * 89 * @return layer item the selection is bound to 90 */ 91 SPObject *activeContext(); 92 93 using ObjectSet::add; 94 95 /** 96 * Add an XML node's SPObject to the set of selected objects. 97 * 98 * @param the xml node of the item to add 99 */ add(XML::Node * repr)100 void add(XML::Node *repr) { 101 add(_objectForXMLNode(repr)); 102 } 103 104 using ObjectSet::set; 105 106 /** 107 * Set the selection to an XML node's SPObject. 108 * 109 * @param repr the xml node of the item to select 110 */ set(XML::Node * repr)111 void set(XML::Node *repr) { 112 set(_objectForXMLNode(repr)); 113 } 114 115 using ObjectSet::remove; 116 117 /** 118 * Removes an item from the set of selected objects. 119 * 120 * It is ok to call this method for an unselected item. 121 * 122 * @param repr the xml node of the item to remove 123 */ remove(XML::Node * repr)124 void remove(XML::Node *repr) { 125 remove(_objectForXMLNode(repr)); 126 } 127 128 using ObjectSet::includes; 129 130 /** 131 * Returns true if the given item is selected. 132 */ includes(XML::Node * repr)133 bool includes(XML::Node *repr) { 134 return includes(_objectForXMLNode(repr)); 135 } 136 137 /** Returns the number of layers in which there are selected objects. */ 138 size_t numberOfLayers(); 139 140 /** Returns the number of parents to which the selected objects belong. */ 141 size_t numberOfParents(); 142 143 /** 144 * Compute the list of points in the selection that are to be considered for snapping from. 145 * 146 * @return Selection's snap points 147 */ 148 std::vector<Inkscape::SnapCandidatePoint> getSnapPoints(SnapPreferences const *snapprefs) const; 149 150 /** 151 * Connects a slot to be notified of selection changes. 152 * 153 * This method connects the given slot such that it will 154 * be called upon any change in the set of selected objects. 155 * 156 * @param slot the slot to connect 157 * 158 * @return the resulting connection 159 */ emitModified()160 void emitModified(){ _emitModified(this->_flags); }; connectChanged(sigc::slot<void,Selection * > const & slot)161 sigc::connection connectChanged(sigc::slot<void, Selection *> const &slot) { 162 return _changed_signal.connect(slot); 163 } connectChangedFirst(sigc::slot<void,Selection * > const & slot)164 sigc::connection connectChangedFirst(sigc::slot<void, Selection *> const &slot) 165 { 166 return _changed_signal.slots().insert(_changed_signal.slots().begin(), slot); 167 } 168 169 /** 170 * Connects a slot to be notified of selected object modifications. 171 * 172 * This method connects the given slot such that it will 173 * receive notifications whenever any selected item is 174 * modified. 175 * 176 * @param slot the slot to connect 177 * 178 * @return the resulting connection 179 * 180 */ connectModified(sigc::slot<void,Selection *,unsigned int> const & slot)181 sigc::connection connectModified(sigc::slot<void, Selection *, unsigned int> const &slot) 182 { 183 return _modified_signal.connect(slot); 184 } connectModifiedFirst(sigc::slot<void,Selection *,unsigned int> const & slot)185 sigc::connection connectModifiedFirst(sigc::slot<void, Selection *, unsigned int> const &slot) 186 { 187 return _modified_signal.slots().insert(_modified_signal.slots().begin(), slot); 188 } 189 190 /** 191 * Set a backup of current selection and store it also to be command line readable by extension system 192 */ 193 void setBackup(); 194 /** 195 * Clear backup of current selection 196 */ 197 void emptyBackup(); 198 /** 199 * Restore a selection from a existing backup 200 */ 201 void restoreBackup(); 202 /** 203 * Here store a paramlist when set backup 204 */ 205 std::list<std::string> params; 206 207 protected: 208 void _connectSignals(SPObject* object) override; 209 void _releaseSignals(SPObject* object) override; 210 211 private: 212 /** Issues modification notification signals. */ 213 static int _emit_modified(Selection *selection); 214 /** Schedules an item modification signal to be sent. */ 215 void _schedule_modified(SPObject *obj, unsigned int flags); 216 217 /** Issues modified selection signal. */ 218 void _emitModified(unsigned int flags); 219 /** Issues changed selection signal. */ 220 void _emitChanged(bool persist_selection_context = false) override; 221 /** returns the SPObject corresponding to an xml node (if any). */ 222 SPObject *_objectForXMLNode(XML::Node *repr) const; 223 /** Releases an active layer object that is being removed. */ 224 void _releaseContext(SPObject *obj); 225 226 LayerModel *_layers; 227 SPObject* _selection_context; 228 unsigned int _flags; 229 unsigned int _idle; 230 std::vector<std::pair<std::string, std::pair<int, int> > > _seldata; 231 std::vector<std::string> _selected_ids; 232 std::map<SPObject *, sigc::connection> _modified_connections; 233 sigc::connection _context_release_connection; 234 235 sigc::signal<void, Selection *> _changed_signal; 236 sigc::signal<void, Selection *, unsigned int> _modified_signal; 237 }; 238 239 } 240 241 #endif 242 /* 243 Local Variables: 244 mode:c++ 245 c-file-style:"stroustrup" 246 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) 247 indent-tabs-mode:nil 248 fill-column:99 249 End: 250 */ 251 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : 252