Code

make win32 compile using libxslt
[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 <map>
21 #include <sigc++/sigc++.h>
23 #include "libnr/nr-rect.h"
24 #include "libnr/nr-convex-hull.h"
25 #include "forward.h"
26 #include "gc-managed.h"
27 #include "gc-finalized.h"
28 #include "gc-anchored.h"
29 #include "gc-soft-ptr.h"
30 #include "util/list.h"
31 #include "sp-item.h"
33 class SPItem;
35 namespace Inkscape {
36 namespace XML {
37 class Node;
38 }
39 }
41 namespace Inkscape {
43 /**
44  * @brief The set of selected SPObjects for a given desktop.
45  *
46  * This class represents the set of selected SPItems for a given
47  * SPDesktop.
48  *
49  * An SPObject and its parent cannot be simultaneously selected;
50  * selecting an SPObjects has the side-effect of unselecting any of
51  * its children which might have been selected.
52  *
53  * This is a per-desktop object that keeps the list of selected objects
54  * at the given desktop. Both SPItem and SPRepr lists can be retrieved
55  * from the selection. Many actions operate on the selection, so it is
56  * widely used throughout the code.
57  * It also implements its own asynchronous notification signals that 
58  * UI elements can listen to.
59  */
60 class Selection : public Inkscape::GC::Managed<>,
61                   public Inkscape::GC::Finalized,
62                   public Inkscape::GC::Anchored
63 {
64 public:
65     /**
66      * Constructs an selection object, bound to a particular
67      * SPDesktop
68      *
69      * @param desktop the desktop in question
70      */
71     Selection(SPDesktop *desktop);
72     ~Selection();
74     /**
75      * @brief Returns the desktop the selection is bound to
76      *
77      * @return the desktop the selection is bound to
78      */
79     SPDesktop *desktop() { return _desktop; }
81     /**
82      * @brief Returns active layer for selection (currentLayer or its parent)
83      *
84      * @return layer item the selection is bound to
85      */
86     SPObject *activeContext();
88     /**
89      * @brief Add an SPObject to the set of selected objects
90      *
91      * @param obj the SPObject to add
92      */
93     void add(SPObject *obj, bool persist_selection_context = false);
95     /**
96      * @brief Add an XML node's SPObject to the set of selected objects
97      *
98      * @param the xml node of the item to add
99      */
100     void add(XML::Node *repr) { add(_objectForXMLNode(repr)); }
102     /**
103      * @brief Set the selection to a single specific object
104      *
105      * @param obj the object to select
106      */
107     void set(SPObject *obj, bool persist_selection_context = false);
109     /**
110      * @brief Set the selection to an XML node's SPObject
111      *
112      * @param repr the xml node of the item to select
113      */
114     void set(XML::Node *repr) { set(_objectForXMLNode(repr)); }
116     /**
117      * @brief Removes an item from the set of selected objects
118      *
119      * It is ok to call this method for an unselected item.
120      *
121      * @param item the item to unselect
122      */
123     void remove(SPObject *obj);
125     /**
126      * @brief Removes an item if selected, adds otherwise
127      *
128      * @param item the item to unselect
129      */
130     void toggle(SPObject *obj);
132     /**
133      * @brief Removes an item from the set of selected objects
134      *
135      * It is ok to call this method for an unselected item.
136      *
137      * @param repr the xml node of the item to remove
138      */
139     void remove(XML::Node *repr) { remove(_objectForXMLNode(repr)); }
141     /**
142      * @brief Selects exactly the specified objects
143      *
144      * @param objs the objects to select
145      */
146     void setList(GSList const *objs);
148     /**
149      * @brief Adds the specified objects to selection, without deselecting first
150      *
151      * @param objs the objects to select
152      */
153     void addList(GSList const *objs);
155     /**
156      * @brief Clears the selection and selects the specified objects
157      *
158      * @param repr a list of xml nodes for the items to select
159      */
160     void setReprList(GSList const *reprs);
162     /** \brief  Add items from an STL iterator range to the selection
163      *  \param  from the begin iterator
164      *  \param  to   the end iterator
165      */
166     template <typename InputIterator>
167     void add(InputIterator from, InputIterator to) {
168         _invalidateCachedLists();
169         while ( from != to ) {
170             _add(*from);
171             ++from;
172         }
173         _emitChanged();
174     }
176     /**
177      * @brief Unselects all selected objects.
178      */
179     void clear();
181     /**
182      * @brief Returns true if no items are selected
183      */
184     bool isEmpty() const { return _objs == NULL; }
186     /**
187      * @brief Returns true if the given object is selected
188      */
189     bool includes(SPObject *obj) const;
191     /**
192      * @brief Returns true if the given item is selected
193      */
194     bool includes(XML::Node *repr) const {
195         return includes(_objectForXMLNode(repr));
196     }
198     /**
199      * @brief Returns a single selected object
200      *
201      * @return NULL unless exactly one object is selected
202      */
203     SPObject *single();
205     /**
206      * @brief Returns a single selected item
207      *
208      * @return NULL unless exactly one object is selected
209      */
210     SPItem *singleItem();
212     /**
213      * @brief Returns a single selected object's xml node
214      *
215      * @return NULL unless exactly one object is selected
216      */
217     XML::Node *singleRepr();
219     /** @brief Returns the list of selected objects */
220     GSList const *list();
221     /** @brief Returns the list of selected SPItems */
222     GSList const *itemList();
223     /** @brief Returns a list of the xml nodes of all selected objects */
224     /// \todo only returns reprs of SPItems currently; need a separate
225     ///      method for that
226     GSList const *reprList();
228     /** @brief Returns the number of layers in which there are selected objects */
229     guint numberOfLayers();
231     /** @brief Returns the number of parents to which the selected objects belong */
232     guint numberOfParents();
234     /** @brief Returns the bounding rectangle of the selection */
235     NRRect *bounds(NRRect *dest, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) const;
236     /** @brief Returns the bounding rectangle of the selection */
237     NR::Maybe<NR::Rect> bounds(SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) const;
239     /**
240      * @brief Returns the bounding rectangle of the selection
241      *
242      * \todo how is this different from bounds()?
243      */ 
244     NRRect *boundsInDocument(NRRect *dest, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) const;
246     /**
247      * @brief Returns the bounding rectangle of the selection
248      *
249      * \todo how is this different from bounds()?
250      */
251     NR::Maybe<NR::Rect> boundsInDocument(SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) const;
253     /**
254      * @brief Returns the rotation/skew center of the selection
255      */
256     NR::Maybe<NR::Point> center() const;
258     /**
259      * @brief Gets the selection's snap points.
260      * @return Selection's snap points
261      */
262     std::vector<NR::Point> getSnapPoints(bool includeItemCenter) const;
264     /**
265      * @brief Gets the snap points of a selection that form a convex hull.
266      * @return Selection's convex hull points
267      */
268     std::vector<NR::Point> getSnapPointsConvexHull() const;
270     /**
271      * @brief Connects a slot to be notified of selection changes
272      *
273      * This method connects the given slot such that it will
274      * be called upon any change in the set of selected objects.
275      *
276      * @param slot the slot to connect
277      *
278      * @return the resulting connection
279      */
280     sigc::connection connectChanged(sigc::slot<void, Selection *> const &slot) {
281         return _changed_signal.connect(slot);
282     }
284     /**
285      * @brief Connects a slot to be notified of selected 
286      *        object modifications 
287      *
288      * This method connects the given slot such that it will
289      * receive notifications whenever any selected item is
290      * modified.
291      *
292      * @param slot the slot to connect
293      *
294      * @return the resulting connection
295      *
296      */
297     sigc::connection connectModified(sigc::slot<void, Selection *, guint> const &slot)
298     {
299         return _modified_signal.connect(slot);
300     }
302 private:
303     /** @brief no copy */
304     Selection(Selection const &);
305     /** @brief no assign */
306     void operator=(Selection const &);
308     /** @brief Issues modification notification signals */
309     static gboolean _emit_modified(Selection *selection);
310     /** @brief Schedules an item modification signal to be sent */
311     void _schedule_modified(SPObject *obj, guint flags);
313     /** @brief Issues modified selection signal */
314     void _emitModified(guint flags);
315     /** @brief Issues changed selection signal */
316     void _emitChanged(bool persist_selection_context = false);
318     void _invalidateCachedLists();
320     /** @brief unselect all descendants of the given item */
321     void _removeObjectDescendants(SPObject *obj);
322     /** @brief unselect all ancestors of the given item */
323     void _removeObjectAncestors(SPObject *obj);
324     /** @brief clears the selection (without issuing a notification) */
325     void _clear();
326     /** @brief adds an object (without issuing a notification) */
327     void _add(SPObject *obj);
328     /** @brief removes an object (without issuing a notification) */
329     void _remove(SPObject *obj);
330     /** @brief returns the SPObject corresponding to an xml node (if any) */
331     SPObject *_objectForXMLNode(XML::Node *repr) const;
332     /** @brief Releases an active layer object that is being removed */
333     void _releaseContext(SPObject *obj);
335     mutable GSList *_objs;
336     mutable GSList *_reprs;
337     mutable GSList *_items;
339     GC::soft_ptr<SPDesktop> _desktop;
340     SPObject* _selection_context;
341     guint _flags;
342     guint _idle;
344     std::map<SPObject *, sigc::connection> _modified_connections;
345     std::map<SPObject *, sigc::connection> _release_connections;
346     sigc::connection _context_release_connection;
348     sigc::signal<void, Selection *> _changed_signal;
349     sigc::signal<void, Selection *, guint> _modified_signal;
350 };
354 #endif
355 /*
356   Local Variables:
357   mode:c++
358   c-file-style:"stroustrup"
359   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
360   indent-tabs-mode:nil
361   fill-column:99
362   End:
363 */
364 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :