cgv
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
traverser.cxx
1#include "traverser.h"
2#include <iostream>
3
4namespace cgv {
5 namespace base {
6
8 : policy((TraversePolicy)_policy), active(_active), focus(_focus)
9{
10}
12{
13 return policy & ~(TP_STOP_ON_SUCCESS|TP_STOP_ON_FAILURE);
14}
17{
18 return (policy & TP_STOP_ON_SUCCESS) != 0;
19}
20
23{
24 return (policy & TP_STOP_ON_FAILURE) != 0;
25}
26
32{
33 return focus;
34}
36{
37 focus = _focus;
38}
40{
41 return active;
42}
44{
45 active = _active;
46}
47
48
79
80/*
81
82private:
83 struct queue_entry {
84 base_ptr dest;
85 base_ptr src;
86 int visit_order_loc;
87 queue_entry(base_ptr _dest,base_ptr _src = base_ptr(), int _visit_order_loc = 0);
88 };
89 std::deque<queue_entry> queue;
90 bool success;
91 bool process_entry(queue_entry& e);
92
93
94
95traverser::queue_entry::queue_entry(base_ptr _dest,base_ptr _src, int _visit_order_loc)
96{
97 dest = _dest;
98 src = _src;
99 visit_order_loc = _visit_order_loc;
100}
101
102bool traverser::traverse(base_ptr start)
103{
104 queue.clear();
105 queue.push_back(queue_entry(start));
106 success = false;
107 while (!queue.empty()) {
108 std::pair<base_ptr,base_ptr> p;
109 if (strategy == TS_DEPTH_FIRST) {
110 if (!process_entry(queue.back()))
111 queue.pop_back();
112 }
113 else {
114 if (!process_entry(queue.front()))
115 queue.pop_front();
116 }
117 }
118 return success;
119}
120
121bool traverser::process_entry(queue_entry& e)
122{
123 // check if we finished processing
124 if (e.visit_order_loc >= visit_order.size())
125 return true;
126
127
128
129
130
131 switch (visit_order[e.visit_order_loc]) {
132 case 'p' :
133 {
134 node* n = dynamic_cast<node*>(e.dest.ref());
135 if (!n)
136 break;
137 base_ptr p = n->get_parent();
138 if (p.ref() != e.src.ref())
139 add_entry(queue_entry(p, e.dest));
140 break;
141 }
142 case 'c' :
143 {
144 group* g = dynamic_cast<group*>(e.dest.ref());
145 if (!g)
146 break;
147 a.select(e.dest);
148 traverse_policy* tp = a.get_policy();
149 int focus = (tp != 0) ? tp->get_focus() : -1;
150 if (focus != -1 && focus < (int)g->get_nr_children() && tp->get_policy() != TP_ALL) {
151 base_ptr c = g->get_child(focus);
152 if (c.ref() != src.ref())
153 add_entry(queue_entry(c, e.dest));
154 }
155 for (int i=0; i < (int)g->get_nr_children(); ++i) if (i != focus) {
156 base_ptr c = g->get_child(i);
157 if (c.ref() != src.ref())
158 add_entry(queue_entry(c, e.dest));
159
160 if (traverse<T1>(c, mp, v, dest)) {
161 success = true;
162 if (tp && tp->stop_on_success()) {
163 if (tp->get_policy() == TP_AUTO_FOCUS)
164 tp->set_focus(i);
165 return true;
166 }
167 }
168 }
169 }
170 }
171 break;
172 case 'n' :
173 {
174 if (x && (x->*mp)(v)) {
175 success = true;
176 if (tp && tp->stop_on_success()) {
177 if (tp->get_policy() == TP_AUTO_FOCUS)
178 tp->set_focus(i);
179 return true;
180 }
181 }
182 }
183 break;
184 default:
185 std::cerr << "unknown character " << traversal_order[i] << " in traversal order" << std::endl;
186 }
187
188
189 // s
190 a.select(dest);
191 traverse_policy* tp = a.get_policy();
192 if (tp && !tp->get_active())
193 return false;
194
195 bool success = false;
196 for (int i=0; i<(int)traversal_order.size(); ++i) {
197 }
198 return success;
199}
200*/
201
204 : a(_a), strategy(_strategy), visit_order(_visit_order), stop_if_not_implemented(_stop_if_not_implemented), ignore_activation_state(_ignore_activation_state)
205{
206}
207
209{
212 inline bool on_enter_node(base_ptr b) { return tch->on_enter_node(b); }
213 inline bool on_leave_node(base_ptr b) { return tch->on_leave_node(b); }
214 inline bool on_enter_children(group_ptr g) { return tch->on_enter_children(g); }
215 inline bool on_leave_children(group_ptr g) { return tch->on_leave_children(g); }
216 inline bool on_enter_parent(node_ptr n) { return tch->on_enter_parent(n); }
217 inline bool on_leave_parent(node_ptr n) { return tch->on_leave_parent(n); }
218};
219
221{
222 no_handler() {}
223 inline bool on_enter_node(base_ptr) { return false; }
224 inline bool on_leave_node(base_ptr) { return false; }
225 inline bool on_enter_children(group_ptr) { return false; }
226 inline bool on_leave_children(group_ptr) { return false; }
227 inline bool on_enter_parent(node_ptr) { return false; }
228 inline bool on_leave_parent(node_ptr) { return false; }
229};
230
231
232template <typename TCH>
234{
235 if (tch.on_enter_node(dest)) {
236 force_termination = true;
237 return false;
238 }
239 a.select(dest);
240 if (stop_if_not_implemented && !a.implements_action()) {
241 force_termination = true;
242 return false;
243 }
244 traverse_policy* tp = a.get_policy();
245 if (!ignore_activation_state && tp && !tp->get_active())
246 return false;
247
248 bool success = false;
249 bool node_success = false;
250 bool node_entered = false;
251 for (int i=0; !force_termination && i<(int)visit_order.size(); ++i) {
252 switch (visit_order[i]) {
253 case 'p' :
254 {
255 node_ptr n = dest->cast<node>();
256 if (n.empty() || n->get_parent().empty())
257 break;
258 if (!tch.on_enter_parent(n))
259 success |= traverse_tmp_2(n->get_parent(), dest, src, tp, force_termination, tch);
260 if (tch.on_leave_parent(n))
261 force_termination = true;
262 break;
263 }
264 case 'c' :
265 {
266 group_ptr g = dest->cast<group>();
267 if (g.empty())
268 break;
269 if (!tch.on_enter_children(g)) {
270 int focus = (tp != 0) ? tp->get_focused_child() : -1;
271 if (focus != -1 && focus < (int)g->get_nr_children() && tp->get_policy() != TP_ALL) {
272 success |= traverse_tmp_2(g->get_child(focus), dest, src, tp, force_termination, tch);
273 }
274
275 if (!force_termination) {
276 for (int i=0; i < (int)g->get_nr_children(); ++i)
277 if (i != focus) {
278 bool child_success = traverse_tmp_2(g->get_child(i), dest, src, tp, force_termination, tch);
279 success |= child_success;
280 if (child_success && tp && tp->get_focused_child() == TP_AUTO_FOCUS)
281 tp->set_focused_child(i);
283 break;
284 }
285 }
286 }
287 if (tch.on_leave_children(g))
288 force_termination = true;
289 break;
290 }
291 case 'n' :
292 {
293 a.select(dest);
294 if (a.implements_action()) {
295 node_success = a.begin();
296 if (!a.has_begin_only()) {
297 node_entered = true;
298 break;
299 }
300 if (node_success) {
301 success = true;
302 if (tp && tp->stop_on_success())
303 force_termination = true;
304 }
305 else {
306 if (tp && tp->stop_on_failure())
307 force_termination = true;
308 }
309 }
310 break;
311 }
312 case 'N' :
313 {
314 if (node_entered) {
315 a.select(dest);
316 if (a.end() && node_success) {
317 success = true;
318 if (tp && tp->stop_on_success())
319 force_termination = true;
320 }
321 else {
322 if (tp && tp->stop_on_failure())
323 force_termination = true;
324 }
325 node_entered = false;
326 }
327 else {
328 std::cerr << "attempt to call end method before begin in tree traversal ignored!" << std::endl;
329 }
330 }
331 default:
332 std::cerr << "unknown character " << visit_order[i] << " in traversal order" << std::endl;
333 }
334 }
335
336 if (node_entered) {
337 a.select(dest);
338 if (a.end() && node_success) {
339 success = true;
340 if (tp && tp->stop_on_success())
341 force_termination = true;
342 }
343 else {
344 if (tp && tp->stop_on_failure())
345 force_termination = true;
346 }
347 }
348 if (tch.on_leave_node(dest))
349 force_termination = true;
350
351 return success;
352}
353
354template <typename TCH>
356{
357 if (p == src)
358 return false;
359 if (traverse_tmp_1(p, dest, force_termination, tch)) {
360 if (tp && tp->stop_on_success())
361 force_termination = true;
362 return true;
363 }
364 else {
365 if (tp && tp->stop_on_failure())
366 force_termination = true;
367 return false;
368 }
369}
370
371
374{
375 bool force_termination = false;
376 if (tch) {
377 use_handler uh(tch);
378 return traverse_tmp_1(start, base_ptr(), force_termination, uh);
379 }
380 else {
382 return traverse_tmp_1(start, base_ptr(), force_termination, nh);
383 }
384}
385
386 }
387}
The action class is used in tree traversals together with the traverser.
Definition action.h:17
virtual bool implements_action() const
check if the current object implements the interface needed for this action
Definition action.cxx:33
virtual bool has_begin_only() const
check whether the action has registered a single begin method or both begin and end methods
Definition action.cxx:54
virtual bool end()
perform the leave part of the action on the current object
Definition action.cxx:48
virtual bool begin()
perform the enter part of the action on the current object
Definition action.cxx:43
virtual traverse_policy * get_policy() const
return the traverse_policy of the current object if available or 0 otherwise
Definition action.cxx:38
virtual void select(base_ptr p)
make the passed object current
Definition action.cxx:29
The group class is a node with children.
Definition group.h:20
The node class keeps a pointer to its parent.
Definition node.h:19
complete implementation of method actions that only call one method when entering a node
Definition action.h:113
interface of a handler for traverse callbacks
Definition traverser.h:77
virtual bool on_enter_children(group_ptr g)
called before the children of a group node g are processed, return whether these should be skipped....
Definition traverser.cxx:60
virtual bool on_enter_parent(node_ptr n)
called before the parent of a node n is processed, return whether this should be skipped....
Definition traverser.cxx:70
virtual bool on_enter_node(base_ptr b)
called before a node b is processed, return, whether to skip this node. If the node is skipped,...
Definition traverser.cxx:50
virtual bool on_leave_node(base_ptr b)
called when a node b is left, return whether to terminate traversal
Definition traverser.cxx:55
virtual bool on_leave_parent(node_ptr n)
called when the parent of a node n has been left, return whether to terminate traversal
Definition traverser.cxx:75
virtual bool on_leave_children(group_ptr g)
called when the children of a group node g have been left, return whether to terminate traversal
Definition traverser.cxx:65
nodes should inherit from this policy class to allow selective tree traversals
Definition traverser.h:24
bool get_active() const
return whether the current node is active
Definition traverser.cxx:39
int get_policy() const
return the policy without the stop on success flag
Definition traverser.cxx:11
void set_policy(int _policy)
set a new policy, always add stop on success flag if needed
Definition traverser.cxx:27
bool stop_on_failure() const
return whether to stop on failure
Definition traverser.cxx:22
void set_focused_child(int _focused_child)
set the focused child
Definition traverser.cxx:35
void set_active(bool _active)
set the active flag of the current node
Definition traverser.cxx:43
bool stop_on_success() const
return whether to stop on success
Definition traverser.cxx:16
int get_focused_child() const
return the focused child or -1 if none is focused
Definition traverser.cxx:31
traverse_policy(int _policy=TP_ALL+TP_STOP_ON_SUCCESS, bool _active=true, int _focus=-1)
construct default traverse policy that visits everything
Definition traverser.cxx:7
bool traverse_tmp_1(base_ptr dest, base_ptr src, bool &force_termination, TCH &tch)
traverse a single object, template over a static traverse callback handler interface
traverser(action &_a, const std::string &_visit_order="pnc", TraverseStrategy _strategy=TS_DEPTH_FIRST, bool _stop_if_not_implemented=false, bool _ignore_activation_state=false)
construct from reference on action and traversal order string
bool ignore_activation_state
whether to ignore the active flag of the traverse policy of the traversed object
Definition traverser.h:109
bool traverse(base_ptr start, traverse_callback_handler *tch=0)
traverse a tree starting at given node according to set strategy, order and dest and previously comin...
bool traverse_tmp_2(base_ptr p, base_ptr dest, base_ptr src, traverse_policy *tp, bool &force_termination, TCH &tch)
helper method encapsulating common functionality
bool empty() const
check if pointer is not yet set
Definition ref_ptr.h:230
TraverseStrategy
not yet implemented
Definition traverser.h:95
data::ref_ptr< base, true > base_ptr
ref counted pointer to base
Definition base.h:37
TraversePolicy
different traversal policies
Definition traverser.h:13
@ TP_AUTO_FOCUS
first traverse focused and then the remaining children
Definition traverser.h:17
@ TP_STOP_ON_FAILURE
this is an optional flag for traversals with methods that return a bool. If the returned bool is true...
Definition traverser.h:19
@ TP_STOP_ON_SUCCESS
like previous but change focus to the child, where traversal succeeded
Definition traverser.h:18
the cgv namespace
Definition print.h:11