~centralelyon2010/inkscape/imagelinks2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
#ifndef SEEN_INKSCAPE_SELECTION_H
#define SEEN_INKSCAPE_SELECTION_H

/** \file
 * Inkscape::Selection: per-desktop selection container
 *
 * Authors:
 *   Lauris Kaplinski <lauris@kaplinski.com>
 *   MenTaLguY <mental@rydia.net>
 *   bulia byak <buliabyak@users.sf.net>
 *
 * Copyright (C) 2004-2005 MenTaLguY
 * Copyright (C) 1999-2002 Lauris Kaplinski
 * Copyright (C) 2001-2002 Ximian, Inc.
 *
 * Released under GNU GPL, read the file 'COPYING' for more information
 */

#include <vector>
#include <map>
#include <list>
#include <stddef.h>
#include <sigc++/sigc++.h>

#include "forward.h"
#include "gc-managed.h"
#include "gc-finalized.h"
#include "gc-anchored.h"
#include "gc-soft-ptr.h"
#include "util/list.h"
#include "sp-item.h"
#include "snapped-point.h"

class SPItem;
class SPBox3D;
class Persp3D;

namespace Inkscape {
namespace XML {
class Node;
}
}

namespace Inkscape {

/**
 * @brief The set of selected SPObjects for a given desktop.
 *
 * This class represents the set of selected SPItems for a given
 * SPDesktop.
 *
 * An SPObject and its parent cannot be simultaneously selected;
 * selecting an SPObjects has the side-effect of unselecting any of
 * its children which might have been selected.
 *
 * This is a per-desktop object that keeps the list of selected objects
 * at the given desktop. Both SPItem and SPRepr lists can be retrieved
 * from the selection. Many actions operate on the selection, so it is
 * widely used throughout the code.
 * It also implements its own asynchronous notification signals that
 * UI elements can listen to.
 */
class Selection : public Inkscape::GC::Managed<>,
                  public Inkscape::GC::Finalized,
                  public Inkscape::GC::Anchored
{
public:
    /**
     * Constructs an selection object, bound to a particular
     * SPDesktop
     *
     * @param desktop the desktop in question
     */
    Selection(SPDesktop *desktop);
    ~Selection();

    /**
     * @brief Returns the desktop the selection is bound to
     *
     * @return the desktop the selection is bound to
     */
    SPDesktop *desktop() { return _desktop; }

    /**
     * @brief Returns active layer for selection (currentLayer or its parent)
     *
     * @return layer item the selection is bound to
     */
    SPObject *activeContext();

    /**
     * @brief Add an SPObject to the set of selected objects
     *
     * @param obj the SPObject to add
     */
    void add(SPObject *obj, bool persist_selection_context = false);

    /**
     * @brief Add an XML node's SPObject to the set of selected objects
     *
     * @param the xml node of the item to add
     */
    void add(XML::Node *repr) { add(_objectForXMLNode(repr)); }

    /**
     * @brief Set the selection to a single specific object
     *
     * @param obj the object to select
     */
    void set(SPObject *obj, bool persist_selection_context = false);

    /**
     * @brief Set the selection to an XML node's SPObject
     *
     * @param repr the xml node of the item to select
     */
    void set(XML::Node *repr) { set(_objectForXMLNode(repr)); }

    /**
     * @brief Removes an item from the set of selected objects
     *
     * It is ok to call this method for an unselected item.
     *
     * @param item the item to unselect
     */
    void remove(SPObject *obj);

    /**
     * @brief Removes an item if selected, adds otherwise
     *
     * @param item the item to unselect
     */
    void toggle(SPObject *obj);

    /**
     * @brief Removes an item from the set of selected objects
     *
     * It is ok to call this method for an unselected item.
     *
     * @param repr the xml node of the item to remove
     */
    void remove(XML::Node *repr) { remove(_objectForXMLNode(repr)); }

    /**
     * @brief Selects exactly the specified objects
     *
     * @param objs the objects to select
     */
    void setList(GSList const *objs);

    /**
     * @brief Adds the specified objects to selection, without deselecting first
     *
     * @param objs the objects to select
     */
    void addList(GSList const *objs);

    /**
     * @brief Clears the selection and selects the specified objects
     *
     * @param repr a list of xml nodes for the items to select
     */
    void setReprList(GSList const *reprs);

    /** \brief  Add items from an STL iterator range to the selection
     *  \param  from the begin iterator
     *  \param  to   the end iterator
     */
    template <typename InputIterator>
    void add(InputIterator from, InputIterator to) {
        _invalidateCachedLists();
        while ( from != to ) {
            _add(*from);
            ++from;
        }
        _emitChanged();
    }

    /**
     * @brief Unselects all selected objects.
     */
    void clear();

    /**
     * @brief Returns true if no items are selected
     */
    bool isEmpty() const { return _objs == NULL; }

    /**
     * @brief Returns true if the given object is selected
     */
    bool includes(SPObject *obj) const;

    /**
     * @brief Returns true if the given item is selected
     */
    bool includes(XML::Node *repr) const {
        return includes(_objectForXMLNode(repr));
    }

    /**
     * @brief Returns a single selected object
     *
     * @return NULL unless exactly one object is selected
     */
    SPObject *single();

    /**
     * @brief Returns a single selected item
     *
     * @return NULL unless exactly one object is selected
     */
    SPItem *singleItem();

    /**
     * @brief Returns a single selected object's xml node
     *
     * @return NULL unless exactly one object is selected
     */
    XML::Node *singleRepr();

    /** @brief Returns the list of selected objects */
    GSList const *list();
    /** @brief Returns the list of selected SPItems */
    GSList const *itemList();
    /** @brief Returns a list of the xml nodes of all selected objects */
    /// \todo only returns reprs of SPItems currently; need a separate
    ///      method for that
    GSList const *reprList();

    /** @brief Returns a list of all perspectives which have a 3D box in the current selection
       (these may also be nested in groups) */
    std::list<Persp3D *> const perspList();

    /** @brief Returns a list of all 3D boxes in the current selection which are associated to @c
       persp. If @c pers is @c NULL, return all selected boxes.
    */
    std::list<SPBox3D *> const box3DList(Persp3D *persp = NULL);

    /** @brief Returns the number of layers in which there are selected objects */
    guint numberOfLayers();

    /** @brief Returns the number of parents to which the selected objects belong */
    guint numberOfParents();

    /** @brief Returns the bounding rectangle of the selection */
    Geom::OptRect bounds(SPItem::BBoxType type) const;
    Geom::OptRect visualBounds() const;
    Geom::OptRect geometricBounds() const;

    /// Returns the bounding rectangle of the selectionin document coordinates.
    Geom::OptRect documentBounds(SPItem::BBoxType type) const;

    /**
     * @brief Returns the rotation/skew center of the selection
     */
    boost::optional<Geom::Point> center() const;

    /**
     * @brief Gets the selection's snap points.
     * @return Selection's snap points
     */
    std::vector<Inkscape::SnapCandidatePoint> getSnapPoints(SnapPreferences const *snapprefs) const;

    /**
     * @brief Gets the snap points of a selection that form a convex hull.
     * @return Selection's convex hull points
     */
    std::vector<Inkscape::SnapCandidatePoint> getSnapPointsConvexHull(SnapPreferences const *snapprefs) const;

    /**
     * @brief Connects a slot to be notified of selection changes
     *
     * This method connects the given slot such that it will
     * be called upon any change in the set of selected objects.
     *
     * @param slot the slot to connect
     *
     * @return the resulting connection
     */
    sigc::connection connectChanged(sigc::slot<void, Selection *> const &slot) {
        return _changed_signal.connect(slot);
    }

    /**
     * @brief Connects a slot to be notified of selected
     *        object modifications
     *
     * This method connects the given slot such that it will
     * receive notifications whenever any selected item is
     * modified.
     *
     * @param slot the slot to connect
     *
     * @return the resulting connection
     *
     */
    sigc::connection connectModified(sigc::slot<void, Selection *, guint> const &slot)
    {
        return _modified_signal.connect(slot);
    }

private:
    /** @brief no copy */
    Selection(Selection const &);
    /** @brief no assign */
    void operator=(Selection const &);

    /** @brief Issues modification notification signals */
    static gboolean _emit_modified(Selection *selection);
    /** @brief Schedules an item modification signal to be sent */
    void _schedule_modified(SPObject *obj, guint flags);

    /** @brief Issues modified selection signal */
    void _emitModified(guint flags);
    /** @brief Issues changed selection signal */
    void _emitChanged(bool persist_selection_context = false);

    void _invalidateCachedLists();

    /** @brief unselect all descendants of the given item */
    void _removeObjectDescendants(SPObject *obj);
    /** @brief unselect all ancestors of the given item */
    void _removeObjectAncestors(SPObject *obj);
    /** @brief clears the selection (without issuing a notification) */
    void _clear();
    /** @brief adds an object (without issuing a notification) */
    void _add(SPObject *obj);
    /** @brief removes an object (without issuing a notification) */
    void _remove(SPObject *obj);
    /** @brief returns the SPObject corresponding to an xml node (if any) */
    SPObject *_objectForXMLNode(XML::Node *repr) const;
    /** @brief Releases an active layer object that is being removed */
    void _releaseContext(SPObject *obj);

    mutable GSList *_objs;
    mutable GSList *_reprs;
    mutable GSList *_items;

    void add_box_perspective(SPBox3D *box);
    void add_3D_boxes_recursively(SPObject *obj);
    void remove_box_perspective(SPBox3D *box);
    void remove_3D_boxes_recursively(SPObject *obj);

    std::list<SPBox3D *> _3dboxes;

    GC::soft_ptr<SPDesktop> _desktop;
    SPObject* _selection_context;
    guint _flags;
    guint _idle;

    std::map<SPObject *, sigc::connection> _modified_connections;
    std::map<SPObject *, sigc::connection> _release_connections;
    sigc::connection _context_release_connection;

    sigc::signal<void, Selection *> _changed_signal;
    sigc::signal<void, Selection *, guint> _modified_signal;
};

}

#endif
/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :