Code

remove deprecation warnings
[inkscape.git] / src / object-hierarchy.cpp
1 /** \file
2  * Object hierarchy implementation.
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 #include "sp-object.h"
13 #include "object-hierarchy.h"
15 namespace Inkscape {
17 /**
18  * Create new object hierarchy.
19  * \param top The first entry if non-NULL.
20  */
21 ObjectHierarchy::ObjectHierarchy(SPObject *top) {
22     if (top) {
23         _addBottom(top);
24     }
25 }
27 ObjectHierarchy::~ObjectHierarchy() {
28     _clear();
29 }
31 /**
32  * Remove all entries.
33  */
34 void ObjectHierarchy::clear() {
35     _clear();
36     _changed_signal.emit(NULL, NULL);
37 }
39 /**
40  * Trim or expand hierarchy on top such that object becomes top entry.
41  */
42 void ObjectHierarchy::setTop(SPObject *object) {
43     g_return_if_fail(object != NULL);
45     if ( top() == object ) {
46         return;
47     }
49     if (!top()) {
50         _addTop(object);
51     } else if (object->isAncestorOf(top())) {
52         _addTop(object, top());
53     } else if ( object == bottom() || object->isAncestorOf(bottom()) ) {
54         _trimAbove(object);
55     } else {
56         _clear();
57         _addTop(object);
58     }
60     _changed_signal.emit(top(), bottom());
61 }
63 /**
64  * Add hierarchy from junior's parent to senior to this
65  * hierarchy's top.
66  */
67 void ObjectHierarchy::_addTop(SPObject *senior, SPObject *junior) {
68     g_assert(junior != NULL);
69     g_assert(senior != NULL);
71     SPObject *object=SP_OBJECT_PARENT(junior);
72     do {
73         _addTop(object);
74         object = SP_OBJECT_PARENT(object);
75     } while ( object != senior );
76 }
78 /**
79  * Add object to top of hierarchy.
80  * \pre object!=NULL
81  */
82 void ObjectHierarchy::_addTop(SPObject *object) {
83     g_assert(object != NULL);
84     _hierarchy.push_back(_attach(object));
85     _added_signal.emit(object);
86 }
88 /**
89  * Remove all objects above limit from hierarchy.
90  */
91 void ObjectHierarchy::_trimAbove(SPObject *limit) {
92     while ( !_hierarchy.empty() && _hierarchy.back().object != limit ) {
93         SPObject *object=_hierarchy.back().object;
95         sp_object_ref(object, NULL);
96         _detach(_hierarchy.back());
97         _hierarchy.pop_back();
98         _removed_signal.emit(object);
99         sp_object_unref(object, NULL);
100     }
103 /**
104  * Trim or expand hierarchy at bottom such that object becomes bottom entry.
105  */
106 void ObjectHierarchy::setBottom(SPObject *object) {
107     g_return_if_fail(object != NULL);
109     if ( bottom() == object ) {
110         return;
111     }
113     if (!top()) {
114         _addBottom(object);
115     } else if (bottom()->isAncestorOf(object)) {
116         _addBottom(bottom(), object);
117     } else if ( top() == object ) {
118         _trimBelow(top());
119     } else if (top()->isAncestorOf(object)) {
120         if (object->isAncestorOf(bottom())) {
121             _trimBelow(object);
122         } else { // object is a sibling or cousin of bottom()
123             SPObject *saved_top=top();
124             sp_object_ref(saved_top, NULL);
125             _clear();
126             _addBottom(saved_top);
127             _addBottom(saved_top, object);
128             sp_object_unref(saved_top, NULL);
129         }
130     } else {
131         _clear();
132         _addBottom(object);
133     }
135     _changed_signal.emit(top(), bottom());
138 /**
139  * Remove all objects under given object.
140  * \param limit If NULL, remove all.
141  */
142 void ObjectHierarchy::_trimBelow(SPObject *limit) {
143     while ( !_hierarchy.empty() && _hierarchy.front().object != limit ) {
144         SPObject *object=_hierarchy.front().object;
145         sp_object_ref(object, NULL);
146         _detach(_hierarchy.front());
147         _hierarchy.pop_front();
148         _removed_signal.emit(object);
149         sp_object_unref(object, NULL);
150     }
153 /**
154  * Add hierarchy from senior to junior to this hierarchy's bottom.
155  */
156 void ObjectHierarchy::_addBottom(SPObject *senior, SPObject *junior) {
157     g_assert(junior != NULL);
158     g_assert(senior != NULL);
160     if ( junior != senior ) {
161         _addBottom(senior, SP_OBJECT_PARENT(junior));
162         _addBottom(junior);
163     }
166 /**
167  * Add object at bottom of hierarchy.
168  * \pre object!=NULL
169  */
170 void ObjectHierarchy::_addBottom(SPObject *object) {
171     g_assert(object != NULL);
172     _hierarchy.push_front(_attach(object));
173     _added_signal.emit(object);
176 void ObjectHierarchy::_trim_for_release(SPObject *object, ObjectHierarchy *hier)
178     hier->_trimBelow(object);
179     g_assert(!hier->_hierarchy.empty());
180     g_assert(hier->_hierarchy.front().object == object);
182     sp_object_ref(object, NULL);
183     hier->_detach(hier->_hierarchy.front());
184     hier->_hierarchy.pop_front();
185     hier->_removed_signal.emit(object);
186     sp_object_unref(object, NULL);
188     hier->_changed_signal.emit(hier->top(), hier->bottom());
191 ObjectHierarchy::Record ObjectHierarchy::_attach(SPObject *object) {
192     sp_object_ref(object, NULL);
193     gulong id = g_signal_connect(G_OBJECT(object), "release", GCallback(&ObjectHierarchy::_trim_for_release), this);
194     return Record(object, id);
197 void ObjectHierarchy::_detach(ObjectHierarchy::Record const &rec) {
198     g_signal_handler_disconnect(G_OBJECT(rec.object), rec.handler_id);
199     sp_object_unref(rec.object, NULL);
204 /*
205   Local Variables:
206   mode:c++
207   c-file-style:"stroustrup"
208   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
209   indent-tabs-mode:nil
210   fill-column:99
211   End:
212 */
213 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :