The Battle for Wesnoth  1.19.0-dev
iterator.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 - 2024
3  by Mark de Wever <koraq@xs4all.nl>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #define GETTEXT_DOMAIN "wesnoth-lib"
17 
19 
20 namespace gui2::iteration
21 {
22 } // namespace gui2::iteration
23 
24 /**
25  * @page gui2_iterator GUI2 Iterator.
26  *
27  * The iterator class allows the user to iterate over a group of widgets.
28  * The idea is to add a visitor class later as well, where the two classes
29  * can be combined.
30  *
31  * This page describes how the iterator class works. The iterator is build
32  * from several parts:
33  * - level, the part and subparts of the widget to visit.
34  * - walker, iterates over a single widget at several levels.
35  * - visit policy, whether a level should be visited or not.
36  * - order policy, the order in which the several levels are traversed.
37  * - iterator, the user interface for iteration.
38  *
39  *
40  * @section gui2_iterator_level Level
41  *
42  * The levels are defined in @ref gui2::iteration::walker_base::level. The
43  * level allows the user to only visit a part of the widget tree.
44  *
45  * @note At the moment when gui2::iteration::walker_base::widget is skipped the
46  * child class also skips its children. This behavior might change.
47  *
48  *
49  * @section gui2_iterator_walker Walker
50  *
51  * The is a group of classes inheriting from @ref gui2::iteration::walker_base
52  * the objects are created from @ref gui2::widget::create_walker. The
53  * walker allows to visit the several levels of the widget. This means
54  * several widgets need to override the function in a subclass. For example
55  * most @em simple widgets don't have a grid or children so they can use the
56  * walker created from @ref gui2::styled_widget. But containers need to create a
57  * different walker.
58  *
59  *
60  * @section gui2_iterator_visit_policy Visit policy
61  *
62  * This policy simply defines whether or not to visit the widgets at a
63  * certain level. There are two visit policies:
64  * - @ref gui2::iteration::policy::visit::visit_level visits the widget at the level.
65  * - @ref gui2::iteration::policy::visit::skip_level skips the widget at the level.
66  *
67  * There are no more visit policies expected for the future. These policies
68  * are normally not used directly, but set from the @ref
69  * gui2_iterator_order_policy.
70  *
71  *
72  * @section gui2_iterator_order_policy Order policy
73  *
74  * This policy determines in which order the widgets are traversed, children
75  * first, this level before diving down etc. @ref tests/gui/iterator.cpp
76  * shows more information.
77  * The following policies have been defined:
78  * - @ref gui2::iteration::policy::order::top_down
79  * - @ref gui2::iteration::policy::order::bottom_up
80  *
81  * The next sections describe in which order the widgets are visited. In the
82  * description we use the following widget tree.
83  *
84  * [0] @n
85  * \ @n
86  * [1|2|3|4] @n
87  * \ @n
88  * [5|6|7|8] @n
89  *
90  * The types are:
91  * - grid 0, 1
92  * - styled_widget 2, 3, 4, 6, 7, 8
93  *
94  * The examples assume all levels will be visited.
95  *
96  *
97  * @subsection gui2_iterator_visit_policy_top_down Top down
98  *
99  * The widgets visited first is the initial widget. After that it tries to go
100  * down to a child widget and will continue down. Once that fails it will visit
101  * the siblings at that level before going up again.
102  *
103  * @todo Write the entire visiting algorithm.
104  *
105  * The visiting order in our example is:
106  * 0, 1, 5, 6, 7, 8, 2, 3, 4
107  *
108  *
109  * @subsection gui2_iterator_visit_policy_bottom_up Bottom up
110  *
111  * When the iterator is created the iterator tries to go down all the child
112  * widgets to get at the bottom level. That widget will be visited first. Then
113  * it will first visit all siblings before going up the the next layer.
114  *
115  * @todo Write the entire visiting algorithm.
116  *
117  * The visiting order in our example is:
118  * 5, 6, 7, 8, 1, 2, 3, 4, 0
119  *
120  *
121  * @section gui2_iterator_iterator Iterator
122  *
123  * The iterator is the class the users should care about. The user creates the
124  * iterator with the selected policy and the root widget. Then the user can
125  * visit the widgets.
126  *
127  * When during the iteration a widget is added to or removed from the
128  * widget-tree being walked the iterator becomes invalid. Using the iterator
129  * when it is invalid results in Undefined Behavior.
130  *
131  * When it's certain there's at least one widget to visit a simple do while loop
132  * can be used. It the policy visits the widget, it's certain there is at least
133  * one widget to visit. Below some sample code:
134 @code
135 iterator<policy> itor(root);
136 assert(!itor.at_end());
137 do {
138  ...
139  ...
140 } while(itor.next());
141 @endcode
142  *
143  * When there might be no widget to visit a simple for loop can be used:
144 @code
145 for(iterator<policy> itor(root); !itor.at_end(); ++itor) {
146  ...
147  ...
148 }
149 @endcode
150  *
151  *
152  * @subsection gui2_iterator_iterator_design Design
153  *
154  * As seen in the examples above the iterator doesn't look like a iterator in
155  * the C++ standard library. The iterator is more designed after the iterator
156  * design of the Gang of Four [GoF]. The reason for the different design is that
157  * GoF design fits better to the classes as a normal C++ iterator. The rest of
158  * this section explains some of the reasons why this design is chosen. The main
159  * reason is simple; the iteration of the widgets feels better suited for the
160  * GoF-style iteration as the C++-style iteration.
161  *
162  * The iterator is not lightweight like most C++ iterators, therefore the class
163  * in non-copyable. (This is for example also the reason why a std::list has no
164  * operator[].) Since operator++(int) should return a copy of the original
165  * object it's also omitted.
166  *
167  * The design makes it hard to back-track the iteration (or costs more memory),
168  * so the iterator is forward only. The order policy is added to allow the
169  * wanted walking direction, but one-way only.
170  *
171  * The iterator has a begin, but it's not easy to go back to it and the
172  * operation involves rewinding the state, which might be costly. Therefore no
173  * begin() function.
174  *
175  * The end is known at the moment it's reached, but not upfront. That combined
176  * with the forward only, makes implementing an end() hard and therefore it is
177  * omitted.
178  *
179  *
180  * [GoF] http://en.wikipedia.org/wiki/Design_Patterns_%28book%29
181  */
Contains the base iterator class for the gui2 widgets.