Code

92da163ea3185103e7f128baa3763d8478af20f7
[inkscape.git] / src / object-hierarchy.h
1 /** \file
2  * Inkscape::ObjectHierarchy - tracks a hierarchy of active SPObjects
3  *
4  * Authors:
5  *   MenTaLguY <mental@rydia.net>
6  *
7  * Copyright (C) 2004 MenTaLguY
8  *
9  * Released under GNU GPL, read the file 'COPYING' for more information
10  */
12 #ifndef SEEN_INKSCAPE_OBJECT_HIERARCHY_H
13 #define SEEN_INKSCAPE_OBJECT_HIERARCHY_H
15 #include <exception>
16 #include <list>
17 #include <sigc++/connection.h>
18 #include <sigc++/signal.h>
19 #include <glib/gmessages.h>
21 class SPObject;
23 namespace Inkscape {
25 /**
26  * An Inkscape::ObjectHierarchy is useful for situations where one wishes
27  * to keep a reference to an SPObject, but fall back on one of its ancestors
28  * when that object is removed.
29  *
30  * That cannot be accomplished simply by hooking the "release" signal of the
31  * SPObject, as by the time that signal is emitted, the object's parent
32  * field has already been cleared.
33  *
34  * There are also some subtle refcounting issues to take into account.
35  *
36  * @see SPObject
37  */
39 class ObjectHierarchy {
40 public:
41     ObjectHierarchy(SPObject *top=NULL);
42     ~ObjectHierarchy();
44     bool contains(SPObject *object);
46     sigc::connection connectAdded(const sigc::slot<void, SPObject *> &slot) {
47         return _added_signal.connect(slot);
48     }
49     sigc::connection connectRemoved(const sigc::slot<void, SPObject *> &slot) {
50         return _removed_signal.connect(slot);
51     }
52     sigc::connection connectChanged(const sigc::slot<void, SPObject *, SPObject *> &slot)
53     {
54         return _changed_signal.connect(slot);
55     }
57     void clear();
59     SPObject *top() {
60         return !_hierarchy.empty() ? _hierarchy.back().object : NULL;
61     }
62     void setTop(SPObject *object);
64     SPObject *bottom() {
65         return !_hierarchy.empty() ? _hierarchy.front().object : NULL;
66     }
67     void setBottom(SPObject *object);
69 private:
70     struct Record {
71         Record(SPObject *o, gulong id) : object(o), handler_id(id) {}
73         SPObject *object;
74         gulong handler_id;
75     };
77     ObjectHierarchy(ObjectHierarchy const &); // no copy
78     void operator=(ObjectHierarchy const &); // no assign
80     /// @brief adds objects in range [senior, junior) to the top
81     void _addTop(SPObject *senior, SPObject *junior);
82     /// @brief adds one object to the top
83     void _addTop(SPObject *object);
84     /// @brief removes all objects above the limit object
85     void _trimAbove(SPObject *limit);
87     /// @brief adds objects in range (senior, junior] to the bottom
88     void _addBottom(SPObject *senior, SPObject *junior);
89     /// @brief adds one object to the bottom
90     void _addBottom(SPObject *object);
91     /// @brief removes all objects below the limit object
92     void _trimBelow(SPObject *limit);
94     Record _attach(SPObject *object);
95     void _detach(Record const &record);
97     void _clear() { _trimBelow(NULL); }
99     static void _trim_for_release(SPObject *released, ObjectHierarchy *hier);
101     std::list<Record> _hierarchy;
102     sigc::signal<void, SPObject *> _added_signal;
103     sigc::signal<void, SPObject *> _removed_signal;
104     sigc::signal<void, SPObject *, SPObject *> _changed_signal;
105 };
109 #endif
110 /*
111   Local Variables:
112   mode:c++
113   c-file-style:"stroustrup"
114   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
115   indent-tabs-mode:nil
116   fill-column:99
117   End:
118 */
119 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :