The Battle for Wesnoth  1.15.0-dev
multi_page.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2018 by Mark de Wever <koraq@xs4all.nl>
3  Part of the Battle for Wesnoth Project https://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 #define GETTEXT_DOMAIN "wesnoth-lib"
16 
18 
23 
24 #include "gettext.hpp"
25 
26 #include "utils/functional.hpp"
27 
28 namespace gui2
29 {
30 
31 // ------------ WIDGET -----------{
32 
33 REGISTER_WIDGET(multi_page)
34 
35 multi_page::multi_page(const implementation::builder_multi_page& builder)
36  : container_base(builder, type())
37  , generator_(generator_base::build(true, true, generator_base::independent, false))
38  , page_builders_()
39 {
40 }
41 
43 {
44  assert(generator_);
45  grid& page = generator_->create_item(-1, page_builders_.begin()->second, item, nullptr);
46 
47  return page;
48 }
49 
50 grid& multi_page::add_page(const std::string& type, int insert_pos, const widget_item& item)
51 {
52  assert(generator_);
53  auto it_builder = page_builders_.find(type);
54  VALIDATE(it_builder != page_builders_.end(), "invalid page type '" + type + "'");
55  return generator_->create_item(insert_pos, it_builder->second, item, nullptr);
56 }
57 
59  const widget_data& data)
60 {
61  assert(generator_);
62  grid& page = generator_->create_item(-1, page_builders_.begin()->second, data, nullptr);
63 
64  return page;
65 }
66 
68  const std::string& type, int insert_pos, const widget_data& data)
69 {
70  assert(generator_);
71  auto it_builder = page_builders_.find(type);
72  VALIDATE(it_builder != page_builders_.end(), "invalid page type '" + type + "'");
73  return generator_->create_item(insert_pos, it_builder->second, data, nullptr);
74 }
75 
76 void multi_page::remove_page(const unsigned page, unsigned count)
77 {
78  assert(generator_);
79 
80  if(page >= get_page_count()) {
81  return;
82  }
83 
84  if(!count || count > get_page_count()) {
85  count = get_page_count();
86  }
87 
88  for(; count; --count) {
89  generator_->delete_item(page);
90  }
91 }
92 
94 {
95  assert(generator_);
96  generator_->clear();
97 }
98 
100 {
101  assert(generator_);
102  return generator_->get_item_count();
103 }
104 
105 void multi_page::select_page(const unsigned page, const bool select)
106 {
107  assert(generator_);
108  generator_->select_item(page, select);
109 }
110 
112 {
113  assert(generator_);
114  return generator_->get_selected_item();
115 }
116 
117 const grid& multi_page::page_grid(const unsigned page) const
118 {
119  assert(generator_);
120  return generator_->item(page);
121 }
122 
123 grid& multi_page::page_grid(const unsigned page)
124 {
125  assert(generator_);
126  return generator_->item(page);
127 }
128 
130 {
131  return true;
132 }
133 
134 unsigned multi_page::get_state() const
135 {
136  return 0;
137 }
138 
139 void multi_page::finalize(const std::vector<widget_item>& page_data)
140 {
141  assert(generator_);
142  generator_->create_items(-1, page_builders_.begin()->second, page_data, nullptr);
143  swap_grid(nullptr, &get_grid(), generator_, "_content_grid");
144 }
145 
147 {
148  /* DO NOTHING */
149 }
150 
151 void multi_page::set_self_active(const bool /*active*/)
152 {
153  /* DO NOTHING */
154 }
155 
156 // }---------- DEFINITION ---------{
157 
160 {
161  DBG_GUI_P << "Parsing multipage " << id << '\n';
162 
163  load_resolutions<resolution>(cfg);
164 }
165 
166 /*WIKI
167  * @page = GUIWidgetDefinitionWML
168  * @order = 1_multi_page
169  *
170  * == Multi page ==
171  *
172  * @begin{parent}{name="gui/"}
173  * @begin{tag}{name="multi_page_definition"}{min=0}{max=-1}{super="generic/widget_definition"}
174  * @macro = multi_page_description
175  *
176  * @begin{tag}{name="resolution"}{min=0}{max=-1}{super="generic/widget_definition/resolution"}
177  * @begin{table}{config}
178  * grid & grid & & A grid containing the widgets for main
179  * widget. $
180  * @end{table}
181  * @allow{link}{name="gui/window/resolution/grid"}
182  * @end{tag}{name="resolution"}
183  * @end{tag}{name="multi_page_definition"}
184  * @end{parent}{name="gui/"}
185  * A multipage has no states.
186  */
188  : resolution_definition(cfg), grid(nullptr)
189 {
190  const config& child = cfg.child("grid");
191  VALIDATE(child, _("No grid defined."));
192 
193  grid = std::make_shared<builder_grid>(child);
194 }
195 
196 // }---------- BUILDER -----------{
197 
198 /*WIKI_MACRO
199  * @begin{macro}{multi_page_description}
200  *
201  * A multi page is a styled_widget that contains several 'pages' of which
202  * only one is visible. The pages can contain the same widgets containing
203  * the same 'kind' of data or look completely different.
204  * @end{macro}
205  */
206 
207 /*WIKI
208  * @page = GUIWidgetInstanceWML
209  * @order = 2_multi_page
210  * @begin{parent}{name="gui/window/resolution/grid/row/column/"}
211  * @begin{tag}{name="multi_page"}{min=0}{max=-1}{super="generic/widget_instance"}
212  * == Multi page ==
213  *
214  * @macro = multi_page_description
215  *
216  * List with the multi page specific variables:
217  * @begin{table}{config}
218  * page_definition & section & & This defines how a multi page item
219  * looks. It must contain the grid
220  * definition for at least one page. $
221  *
222  * page_data & section & [] & A grid alike section which stores the
223  * initial data for the multi page. Every
224  * row must have the same number of columns
225  * as the 'page_definition'. $
226  * horizontal_scrollbar_mode & scrollbar_mode & initial_auto &
227  * Determines whether or not to show the
228  * scrollbar.
229  * vertical_scrollbar_mode & scrollbar_mode & initial_auto &
230  * Determines whether or not to show the
231  * scrollbar.
232  * @end{table}
233  * @begin{tag}{name="page_definition"}{min=0}{max=1}{super="gui/window/resolution/grid"}
234  * @end{tag}{name="page_definition"}
235  * @begin{tag}{name="page_data"}{min=0}{max=1}{super="gui/window/resolution/grid"}
236  * @end{tag}{name="page_data"}
237  * @end{tag}{name="multi_page"}
238  * @end{parent}{name="gui/window/resolution/grid/row/column/"}
239  */
240 
241 namespace implementation
242 {
243 
244 builder_multi_page::builder_multi_page(const config& cfg)
245  : implementation::builder_styled_widget(cfg), builders(), data()
246 {
247  for (const config& page : cfg.child_range("page_definition"))
248  {
249  auto builder = std::make_shared<builder_grid>(page);
250  assert(builder);
251  builders[page["id"]] = builder;
252  }
253  VALIDATE(!builders.empty(), _("No page defined."));
254 
255  /** @todo This part is untested. */
256  const config& d = cfg.child("page_data");
257  if(!d) {
258  return;
259  }
260 
261  auto builder = builders.begin()->second;
262  for(const auto & row : d.child_range("row"))
263  {
264  unsigned col = 0;
265 
266  for(const auto & column : row.child_range("column"))
267  {
268  data.emplace_back();
269  for(const auto & i : column.attribute_range())
270  {
271  data.back()[i.first] = i.second;
272  }
273  ++col;
274  }
275 
276  VALIDATE(col == builder->cols,
277  _("'list_data' must have "
278  "the same number of columns as the 'list_definition'."));
279  }
280 }
281 
283 {
284  auto widget = std::make_shared<multi_page>(*this);
285 
286  widget->set_page_builders(builders);
287 
288  DBG_GUI_G << "Window builder: placed multi_page '" << id
289  << "' with definition '" << definition << "'.\n";
290 
291  const auto conf = widget->cast_config_to<multi_page_definition>();
292  assert(conf);
293 
294  widget->init_grid(conf->grid);
295 
296  widget->finalize(data);
297 
298  return widget;
299 }
300 
301 } // namespace implementation
302 
303 // }------------ END --------------
304 
305 } // namespace gui2
Base class of a resolution, contains the common keys for a resolution.
#define DBG_GUI_P
Definition: log.hpp:68
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:423
const grid & get_grid() const
virtual widget_ptr build() const override
Definition: multi_page.cpp:282
builder_grid_map page_builders_
Contains the builder for the new items.
Definition: multi_page.hpp:201
child_itors child_range(config_key_type key)
Definition: config.cpp:366
void swap_grid(grid *g, grid *content_grid, widget_ptr widget, const std::string &id)
Swaps an item in a grid for another one.
void clear()
Removes all pages in the multi page, clearing it.
Definition: multi_page.cpp:93
Base class for all widgets.
Definition: widget.hpp:48
virtual void set_self_active(const bool active) override
See container_base::set_self_active.
Definition: multi_page.cpp:151
void remove_page(const unsigned page, unsigned count=1)
Removes a page in the multi page.
Definition: multi_page.cpp:76
std::vector< std::map< std::string, t_string > > data
Multi page data.
Definition: multi_page.hpp:253
#define d
int get_selected_page() const
Returns the selected page.
Definition: multi_page.cpp:111
Generic file dialog.
Definition: field-fwd.hpp:22
Base container class.
Definition: grid.hpp:30
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:89
std::string definition
Parameters for the styled_widget.
std::map< std::string, t_string > widget_item
Definition: widget.hpp:27
Abstract base class for the generator.
Definition: generator.hpp:42
#define VALIDATE(cond, message)
The macro to use for the validation of WML.
const grid & page_grid(const unsigned page) const
Returns the grid for the page.
Definition: multi_page.cpp:117
std::shared_ptr< widget > widget_ptr
Definition: widget.hpp:732
generator_ptr generator_
Contains a pointer to the generator.
Definition: multi_page.hpp:198
#define REGISTER_WIDGET(id)
Wrapper for REGISTER_WIDGET3.
std::size_t i
Definition: function.cpp:933
void select_page(const unsigned page, const bool select=true)
Selectes a page.
Definition: multi_page.cpp:105
grid & add_page(const widget_item &item)
Adds single page to the grid.
Definition: multi_page.cpp:42
virtual bool get_active() const override
See styled_widget::get_active.
Definition: multi_page.cpp:129
A generic container base class.
void finalize(const std::vector< widget_item > &page_data)
Finishes the building initialization of the widget.
Definition: multi_page.cpp:139
virtual void impl_draw_background() override
See widget::impl_draw_background.
Definition: multi_page.cpp:146
multi_page_definition(const config &cfg)
Definition: multi_page.cpp:158
unsigned get_page_count() const
Returns the number of pages.
Definition: multi_page.cpp:99
static const std::string & type()
Static type getter that does not rely on the widget being constructed.
The multi page class.
Definition: multi_page.hpp:35
std::map< std::string, widget_item > widget_data
Definition: widget.hpp:30
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:68
#define DBG_GUI_G
Definition: log.hpp:40
Contains the implementation details for lexical_cast and shouldn&#39;t be used directly.
virtual unsigned get_state() const override
See styled_widget::get_state.
Definition: multi_page.cpp:134