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