The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
policy_order.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 - 2017 by Mark de Wever <koraq@xs4all.nl>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
19 #include "gui/core/log.hpp"
20 #include "gui/widgets/widget.hpp"
21 
22 #include <iostream>
23 
24 namespace gui2
25 {
26 
27 namespace iteration
28 {
29 
30 namespace policy
31 {
32 
33 namespace order
34 {
35 
36 template <bool VW, bool VG, bool VC>
37 class bottom_up : public visit_level<VW, walker_base::self>,
38  public visit_level<VG, walker_base::internal>,
39  public visit_level<VC, walker_base::child>
40 {
44 
45 public:
46  explicit bottom_up(widget& root) : root_(root.create_walker()), stack_()
47  {
48  TST_GUI_I << "Constructor: ";
49  while(!visit_child::at_end(*root_)) {
50  stack_.push_back(root_);
51  root_ = visit_child::get(*root_)->create_walker();
52  TST_GUI_I << " Down widget '" << operator*().id() << "'.";
53  }
54 
55  if(!at_end()) {
56  TST_GUI_I << " Finished at '" << operator*().id() << "'.\n";
57  } else {
58  TST_GUI_I << " Finished at the end.\n";
59  }
60  }
61 
63  {
64  delete root_;
66  itor != stack_.end();
67  ++itor) {
68 
69  delete *itor;
70  }
71  }
72 
73  bool at_end() const
74  {
75  return visit_widget::at_end(*root_) && visit_grid::at_end(*root_)
76  && visit_child::at_end(*root_);
77  }
78 
79  bool next()
80  {
81  if(at_end()) {
82  ERR_GUI_I << "Tried to move beyond end of the iteration range."
83  << std::endl;
84  throw range_error("Tried to move beyond end of range.");
85  }
86 
87  TST_GUI_I << "At '" << operator*().id() << "'.";
88 
89  /***** WIDGET *****/
90  TST_GUI_I << " Iterate widget:";
91  if(!visit_widget::at_end(*root_)) {
92  switch(visit_widget::next(*root_)) {
93  case walker_base::valid:
94  TST_GUI_I << " visit '" << operator*().id() << "'.\n";
95  return true;
97  TST_GUI_I << " reached the end.";
98  break;
99  case walker_base::fail:
100  TST_GUI_I << "\n";
101  ERR_GUI_E << "Tried to move beyond end of "
102  "the widget iteration range.\n";
103  throw range_error("Tried to move beyond end of range.");
104  }
105  } else {
106  TST_GUI_I << " failed.";
107  }
108 
109  /***** GRID *****/
110  TST_GUI_I << " Iterate grid:";
111  if(!visit_grid::at_end(*root_)) {
112  switch(visit_grid::next(*root_)) {
113  case walker_base::valid:
114  TST_GUI_I << " visit '" << operator*().id() << "'.\n";
115  return true;
117  TST_GUI_I << " reached the end.";
118  break;
119  case walker_base::fail:
120  TST_GUI_I << "\n";
121  ERR_GUI_E << "Tried to move beyond end of "
122  "the grid iteration range.\n";
123  throw range_error("Tried to move beyond end of range.");
124  }
125  } else {
126  TST_GUI_I << " failed.";
127  }
128 
129  /***** TRAVERSE CHILDREN *****/
130 
131  TST_GUI_I << " Iterate child:";
132  if(visit_child::at_end(*root_)) {
133  if(stack_.empty()) {
134  TST_GUI_I << " Finished iteration.\n";
135  return false;
136  } else {
137  delete root_;
138 
139  root_ = stack_.back();
140  stack_.pop_back();
141  TST_GUI_I << " Up '" << operator*().id() << "'.";
142  }
143  }
144  TST_GUI_I << " Iterate child:";
145  if(!visit_child::at_end(*root_)) {
146  switch(visit_child::next(*root_)) {
147  case walker_base::valid:
148  TST_GUI_I << " visit '" << operator*().id() << "'.";
149  break;
151  TST_GUI_I << " reached the end.";
152  break;
153  case walker_base::fail:
154  TST_GUI_I << "\n";
155  ERR_GUI_E << "Tried to move beyond end of "
156  "the child iteration range.\n";
157  throw range_error("Tried to move beyond end of range.");
158  }
159  } else {
160  TST_GUI_I << " already at the end.";
161  }
162 
163  while(!visit_child::at_end(*root_)) {
164  stack_.push_back(root_);
165  root_ = visit_child::get(*root_)->create_walker();
166  TST_GUI_I << " Down widget '" << operator*().id() << "'.";
167  }
168  TST_GUI_I << " Visit '" << operator*().id() << "'.\n";
169  return true;
170  }
171 
173  {
174  if(at_end()) {
175  ERR_GUI_I << "Tried to defer beyond end its "
176  "iteration range iterator.\n";
177  throw logic_error("Tried to defer an invalid iterator.");
178  }
179  if(!visit_widget::at_end(*root_)) {
180  return *visit_widget::get(*root_);
181  }
182  if(!visit_grid::at_end(*root_)) {
183  return *visit_grid::get(*root_);
184  }
185  if(!visit_child::at_end(*root_)) {
186  return *visit_child::get(*root_);
187  }
188  ERR_GUI_I << "The iterator ended in an unknown "
189  "state while deferring itself.\n";
190  throw logic_error("Tried to defer an invalid iterator.");
191  }
192 
193 private:
195 
196  std::vector<iteration::walker_base*> stack_;
197 };
198 
199 template <bool VW, bool VG, bool VC>
200 class top_down : public visit_level<VW, walker_base::self>,
201  public visit_level<VG, walker_base::internal>,
202  public visit_level<VC, walker_base::child>
203 {
207 
208 public:
209  explicit top_down(widget& root) : root_(root.create_walker()), stack_()
210  {
211  }
212 
214  {
215  delete root_;
217  itor != stack_.end();
218  ++itor) {
219 
220  delete *itor;
221  }
222  }
223 
224  bool at_end() const
225  {
226  return visit_widget::at_end(*root_) && visit_grid::at_end(*root_)
227  && visit_child::at_end(*root_);
228  }
229 
230  bool next()
231  {
232  if(at_end()) {
233  ERR_GUI_I << "Tried to move beyond end of the iteration range."
234  << std::endl;
235  throw range_error("Tried to move beyond end of range.");
236  }
237 
238  TST_GUI_I << "At '" << operator*().id() << "'.";
239 
240  /***** WIDGET *****/
241  TST_GUI_I << " Iterate widget:";
242  if(!visit_widget::at_end(*root_)) {
243  switch(visit_widget::next(*root_)) {
244  case walker_base::valid:
245  TST_GUI_I << " visit '" << operator*().id() << "'.\n";
246  return true;
248  TST_GUI_I << " reached the end.";
249  break;
250  case walker_base::fail:
251  TST_GUI_I << "\n";
252  ERR_GUI_E << "Tried to move beyond end of the "
253  "widget iteration range.\n";
254  throw range_error("Tried to move beyond end of range.");
255  }
256  } else {
257  TST_GUI_I << " failed.";
258  }
259 
260  /***** GRID *****/
261  TST_GUI_I << " Iterate grid:";
262  if(!visit_grid::at_end(*root_)) {
263  switch(visit_grid::next(*root_)) {
264  case walker_base::valid:
265  TST_GUI_I << " visit '" << operator*().id() << "'.\n";
266  return true;
268  TST_GUI_I << " reached the end.";
269  break;
270  case walker_base::fail:
271  TST_GUI_I << "\n";
272  ERR_GUI_E << "Tried to move beyond end of the grid "
273  "iteration range.\n";
274  throw range_error("Tried to move beyond end of range.");
275  }
276  } else {
277  TST_GUI_I << " failed.";
278  }
279 
280  /***** TRAVERSE CHILDREN *****/
281 
282  TST_GUI_I << " Iterate child:";
283  if(visit_child::at_end(*root_)) {
284  TST_GUI_I << " reached the end.";
285  up();
286  } else {
287  TST_GUI_I << " proceed.";
288  }
289 
290  if(!visit_child::at_end(*root_)) {
291  stack_.push_back(root_);
292  root_ = visit_child::get(*root_)->create_walker();
293 
294  assert(root_);
295  assert(!at_end());
296  TST_GUI_I << " Down and visit '" << operator*().id() << "'.\n";
297  return true;
298  }
299 
300  TST_GUI_I << " Finished iteration.\n";
301  return false;
302  }
303 
305  {
306  if(at_end()) {
307  ERR_GUI_I << "Tried to defer beyond end of the iteration "
308  "range iterator.\n";
309  throw logic_error("Tried to defer an invalid iterator.");
310  }
311  if(!visit_widget::at_end(*root_)) {
312  return *visit_widget::get(*root_);
313  }
314  if(!visit_grid::at_end(*root_)) {
315  return *visit_grid::get(*root_);
316  }
317  if(!visit_child::at_end(*root_)) {
318  return *visit_child::get(*root_);
319  }
320  ERR_GUI_I << "The iterator ended in an unknown "
321  "state while deferring iteself.\n";
322  throw logic_error("Tried to defer an invalid iterator.");
323  }
324 
325 private:
326  bool up()
327  {
328  while(!stack_.empty()) {
329  delete root_;
330 
331  root_ = stack_.back();
332  stack_.pop_back();
333  TST_GUI_I << " Up widget '" << operator*().id() << "'. Iterate:";
334  switch(visit_child::next(*root_)) {
335  case walker_base::valid:
336  TST_GUI_I << " reached '" << operator*().id() << "'.";
337  return true;
339  TST_GUI_I << " failed.";
340  break;
341  case walker_base::fail:
342  throw range_error("Tried to move beyond end of range.");
343  }
344  }
345  return true;
346  }
347 
349 
350  std::vector<iteration::walker_base*> stack_;
351 };
352 
353 } // namespace order
354 
355 } // namespace policy
356 
357 } // namespace iteration
358 
359 } // namespace gui2
Define the common log macros for the gui toolkit.
#define ERR_GUI_E
Definition: log.hpp:37
When calling next the following it has the following results.
Definition: walker.hpp:68
When calling next the following it has the following results.
Definition: walker.hpp:57
std::vector< iteration::walker_base * > stack_
const std::string & id() const
Definition: widget.cpp:107
Helper class to select to visit or skip a level.
Base class for all widgets.
Definition: widget.hpp:48
Contains the exceptions thrown by the gui2::iteration::iterator classes.
Generic file dialog.
Definition: field-fwd.hpp:22
visit_level< VW, walker_base::self > visit_widget
visit_level< VC, walker_base::child > visit_child
The walker abstract base class.
Definition: walker.hpp:26
std::vector< iteration::walker_base * > stack_
visit_level< VW, walker_base::self > visit_widget
Thrown when moving an invalid iterator.
Definition: exception.hpp:56
#define TST_GUI_I
Definition: log.hpp:46
visit_level< VC, walker_base::child > visit_child
CURSOR_TYPE get()
Definition: cursor.cpp:194
visit_level< VG, walker_base::internal > visit_grid
#define ERR_GUI_I
Definition: log.hpp:54
#define next(ls)
Definition: llex.cpp:32
Thrown when deferring an invalid iterator.
Definition: exception.hpp:38
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
visit_level< VG, walker_base::internal > visit_grid