Code

moving trunk for module inkscape
[inkscape.git] / src / selection.h
1 #ifndef SEEN_INKSCAPE_SELECTION_H
2 #define SEEN_INKSCAPE_SELECTION_H
4 /** \file
5  * Inkscape::Selection: per-desktop selection container
6  *
7  * Authors:
8  *   Lauris Kaplinski <lauris@kaplinski.com>
9  *   MenTaLguY <mental@rydia.net>
10  *   bulia byak <buliabyak@users.sf.net>
11  *
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, read the file 'COPYING' for more information
17  */
19 #include <vector>
20 #include <sigc++/sigc++.h>
22 #include "libnr/nr-rect.h"
23 #include "libnr/nr-convex-hull.h"
24 #include "forward.h"
25 #include "gc-managed.h"
26 #include "gc-finalized.h"
27 #include "gc-anchored.h"
28 #include "util/list.h"
30 class SPItem;
32 namespace Inkscape {
33 namespace XML {
34 class Node;
35 }
36 }
38 namespace Inkscape {
40 /**
41  * @brief The set of selected SPObjects for a given desktop.
42  *
43  * This class represents the set of selected SPItems for a given
44  * SPDesktop.
45  *
46  * An SPObject and its parent cannot be simultaneously selected;
47  * selecting an SPObjects has the side-effect of unselecting any of
48  * its children which might have been selected.
49  *
50  * This is a per-desktop object that keeps the list of selected objects
51  * at the given desktop. Both SPItem and SPRepr lists can be retrieved
52  * from the selection. Many actions operate on the selection, so it is
53  * widely used throughout the code.
54  * It also implements its own asynchronous notification signals that 
55  * UI elements can listen to.
56  */
57 class Selection : public Inkscape::GC::Managed<>,
58                   public Inkscape::GC::Finalized,
59                   public Inkscape::GC::Anchored
60 {
61 public:
62     /**
63      * Constructs an selection object, bound to a particular
64      * SPDesktop
65      *
66      * @param desktop the desktop in question
67      */
68     Selection(SPDesktop *desktop);
69     ~Selection();
71     /**
72      * @brief Returns the desktop the seoection is bound to
73      *
74      * @return the desktop the selection is bound to
75      */
76     SPDesktop *desktop() { return _desktop; }
78     /**
79      * @brief Add an SPObject to the set of selected objects
80      *
81      * @param obj the SPObject to add
82      */
83     void add(SPObject *obj);
85     /**
86      * @brief Add an XML node's SPObject to the set of selected objects
87      *
88      * @param the xml node of the item to add
89      */
90     void add(XML::Node *repr) { add(_objectForXMLNode(repr)); }
92     /**
93      * @brief Set the selection to a single specific object
94      *
95      * @param obj the object to select
96      */
97     void set(SPObject *obj);
99     /**
100      * @brief Set the selection to an XML node's SPObject
101      *
102      * @param repr the xml node of the item to select
103      */
104     void set(XML::Node *repr) { set(_objectForXMLNode(repr)); }
106     /**
107      * @brief Removes an item from the set of selected objects
108      *
109      * It is ok to call this method for an unselected item.
110      *
111      * @param item the item to unselect
112      */
113     void remove(SPObject *obj);
115     /**
116      * @brief Removes an item if selected, adds otherwise
117      *
118      * @param item the item to unselect
119      */
120     void toggle(SPObject *obj);
122     /**
123      * @brief Removes an item from the set of selected objects
124      *
125      * It is ok to call this method for an unselected item.
126      *
127      * @param repr the xml node of the item to remove
128      */
129     void remove(XML::Node *repr) { remove(_objectForXMLNode(repr)); }
131     /**
132      * @brief Selects exactly the specified objects
133      *
134      * @param objs the objects to select
135      */
136     void setList(GSList const *objs);
138     /**
139      * @brief Adds the specified objects to selection, without deselecting first
140      *
141      * @param objs the objects to select
142      */
143     void addList(GSList const *objs);
145     /**
146      * @brief Clears the selection and selects the specified objects
147      *
148      * @param repr a list of xml nodes for the items to select
149      */
150     void setReprList(GSList const *reprs);
152     /** \brief  Add items from an STL iterator range to the selection
153      *  \param  from the begin iterator
154      *  \param  to   the end iterator
155      */
156     template <typename InputIterator>
157     void add(InputIterator from, InputIterator to) {
158         _invalidateCachedLists();
159         while ( from != to ) {
160             _add(*from);
161             ++from;
162         }
163         _emitChanged();
164     }
166     /**
167      * @brief Unselects all selected objects.
168      */
169     void clear();
171     /**
172      * @brief Returns true if no items are selected
173      */
174     bool isEmpty() const { return _objs == NULL; }
176     /**
177      * @brief Returns true if the given object is selected
178      */
179     bool includes(SPObject *obj) const;
181     /**
182      * @brief Returns true if the given item is selected
183      */
184     bool includes(XML::Node *repr) const {
185         return includes(_objectForXMLNode(repr));
186     }
188     /**
189      * @brief Returns a single selected object
190      *
191      * @return NULL unless exactly one object is selected
192      */
193     SPObject *single();
195     /**
196      * @brief Returns a single selected item
197      *
198      * @return NULL unless exactly one object is selected
199      */
200     SPItem *singleItem();
202     /**
203      * @brief Returns a single selected object's xml node
204      *
205      * @return NULL unless exactly one object is selected
206      */
207     XML::Node *singleRepr();
209     /** @brief Returns the list of selected objects */
210     GSList const *list();
211     /** @brief Returns the list of selected SPItems */
212     GSList const *itemList();
213     /** @brief Returns a list of the xml nodes of all selected objects */
214     /// \todo only returns reprs of SPItems currently; need a separate
215     ///      method for that
216     GSList const *reprList();
218     /** @brief Returns the number of layers in which there are selected objects */
219     guint numberOfLayers();
221     /** @brief Returns the bounding rectangle of the selection */
222     NRRect *bounds(NRRect *dest) const;
223     /** @brief Returns the bounding rectangle of the selection */
224     NR::Rect bounds() const;
226     /**
227      * @brief Returns the bounding rectangle of the selection
228      *
229      * \todo how is this different from bounds()?
230      */ 
231     NRRect *boundsInDocument(NRRect *dest) const;
233     /**
234      * @brief Returns the bounding rectangle of the selection
235      *
236      * \todo how is this different from bounds()?
237      */
238     NR::Rect boundsInDocument() const;
240     /**
241      * @brief Gets the selection's snap points.
242      * @return Selection's snap points
243      */
244     std::vector<NR::Point> getSnapPoints() const;
246     /**
247      * @brief Gets the snap points of a selection that form a convex hull.
248      * @return Selection's convex hull points
249      */
250     std::vector<NR::Point> getSnapPointsConvexHull() const;
252     /**
253      * @return A vector containing the top-left and bottom-right
254      * corners of each selected object's bounding box.
255      */
256     std::vector<NR::Point> getBBoxPoints() const;
258     /**
259      * @brief Connects a slot to be notified of selection changes
260      *
261      * This method connects the given slot such that it will
262      * be called upon any change in the set of selected objects.
263      *
264      * @param slot the slot to connect
265      *
266      * @return the resulting connection
267      */
268     sigc::connection connectChanged(sigc::slot<void, Selection *> const &slot) {
269         return _changed_signal.connect(slot);
270     }
272     /**
273      * @brief Connects a slot to be notified of selected 
274      *        object modifications 
275      *
276      * This method connects the given slot such that it will
277      * receive notifications whenever any selected item is
278      * modified.
279      *
280      * @param slot the slot to connect
281      *
282      * @return the resulting connection
283      *
284      */
285     sigc::connection connectModified(sigc::slot<void, Selection *, guint> const &slot)
286     {
287         return _modified_signal.connect(slot);
288     }
290 private:
291     /** @brief no copy */
292     Selection(Selection const &);
293     /** @brief no assign */
294     void operator=(Selection const &);
296     /** @brief Issues modification notification signals */
297     static gboolean _emit_modified(Selection *selection);
298     /** @brief Schedules an item modification signal to be sent */
299     static void _schedule_modified(SPObject *obj, guint flags, Selection *selection);
300     /** @brief Releases a selected object that is being removed */
301     static void _release(SPObject *obj, Selection *selection);
303     /** @brief Issues modified selection signal */
304     void _emitModified(guint flags);
305     /** @brief Issues changed selection signal */
306     void _emitChanged();
308     void _invalidateCachedLists();
310     /** @brief unselect all descendants of the given item */
311     void _removeObjectDescendants(SPObject *obj);
312     /** @brief unselect all ancestors of the given item */
313     void _removeObjectAncestors(SPObject *obj);
314     /** @brief clears the selection (without issuing a notification) */
315     void _clear();
316     /** @brief adds an object (without issuing a notification) */
317     void _add(SPObject *obj);
318     /** @brief removes an object (without issuing a notification) */
319     void _remove(SPObject *obj);
320     /** @brief returns the SPObject corresponding to an xml node (if any) */
321     SPObject *_objectForXMLNode(XML::Node *repr) const;
323     mutable GSList *_objs;
324     mutable GSList *_reprs;
325     mutable GSList *_items;
327     SPDesktop *_desktop;
328     guint _flags;
329     guint _idle;
331     sigc::signal<void, Selection *> _changed_signal;
332     sigc::signal<void, Selection *, guint> _modified_signal;
333 };
337 #endif
338 /*
339   Local Variables:
340   mode:c++
341   c-file-style:"stroustrup"
342   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
343   indent-tabs-mode:nil
344   fill-column:99
345   End:
346 */
347 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :