The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
stacked_widget.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2016 by Mark de Wever <[email protected]>
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 #define GETTEXT_DOMAIN "wesnoth-lib"
16 
18 
21 #include "gui/widgets/settings.hpp"
23 #include "gettext.hpp"
24 
25 #include "utils/functional.hpp"
26 
27 namespace gui2
28 {
29 
30 // ------------ WIDGET -----------{
31 
32 REGISTER_WIDGET(stacked_widget)
33 
35  : tcontainer_(1)
36  , generator_(
37  tgenerator_::build(false, false, tgenerator_::independent, false))
38  , selected_layer_(-1)
39 {
40 }
41 
43 {
44  return true;
45 }
46 
48 {
49  return 0;
50 }
51 
53 {
54  assert(generator_);
55  for(unsigned i = 0; i < generator_->get_item_count(); ++i) {
57  }
58 }
59 
60 namespace
61 {
62 
63 /**
64  * Swaps an item in a grid for another one.*/
65 void swap_grid(tgrid* grid,
66  tgrid* content_grid,
67  twidget* widget,
68  const std::string& id)
69 {
70  assert(content_grid);
71  assert(widget);
72 
73  // Make sure the new child has same id.
74  widget->set_id(id);
75 
76  // Get the container containing the wanted widget.
77  tgrid* parent_grid = nullptr;
78  if(grid) {
79  parent_grid = find_widget<tgrid>(grid, id, false, false);
80  }
81  if(!parent_grid) {
82  parent_grid = find_widget<tgrid>(content_grid, id, true, false);
83  }
84  parent_grid = dynamic_cast<tgrid*>(parent_grid->parent());
85  assert(parent_grid);
86 
87  // Replace the child.
88  widget = parent_grid->swap_child(id, widget, false);
89  assert(widget);
90 
91  delete widget;
92 }
93 
94 } // namespace
95 
96 void
97 tstacked_widget::finalize(std::vector<tbuilder_grid_const_ptr> widget_builder)
98 {
99  assert(generator_);
100  string_map empty_data;
101  for(const auto & builder : widget_builder)
102  {
103  generator_->create_item(-1, builder, empty_data, nullptr);
104  }
105  swap_grid(nullptr, &grid(), generator_, "_content_grid");
106 
107  select_layer(-1);
108 }
109 
111 {
112  static const std::string type = "stacked_widget";
113  return type;
114 }
115 
116 void tstacked_widget::set_self_active(const bool /*active*/)
117 {
118  /* DO NOTHING */
119 }
120 
121 void tstacked_widget::select_layer_internal(const unsigned int layer, const bool select) const
122 {
123  // Selecting a layer that's already selected appears to actually deselect
124  // it, so make sure to only perform changes we want.
125  if(generator_->is_selected(layer) != select) {
126  generator_->select_item(layer, select);
127  }
128 }
129 
131 {
132  const unsigned int num_layers = generator_->get_item_count();
133  selected_layer_ = std::max(-1, std::min<int>(layer, num_layers - 1));
134 
135  for(unsigned int i = 0; i < num_layers; ++i) {
136  if(selected_layer_ >= 0) {
137  const bool selected = i == static_cast<unsigned int>(selected_layer_);
138  // Select current layer, leave the rest unselected.
139  select_layer_internal(i, selected);
140  generator_->item(i).set_visible(selected
143  } else {
144  // Select everything.
145  select_layer_internal(i, true);
147  }
148  }
149 }
150 
152 {
153  return generator_->get_item_count();
154 }
155 
157 {
158  assert(generator_);
159  return &generator_->item(i);
160 }
161 
162 // }---------- DEFINITION ---------{
163 
165  : tcontrol_definition(cfg)
166 {
167  DBG_GUI_P << "Parsing stacked widget " << id << '\n';
168 
169  load_resolutions<tresolution>(cfg);
170 }
171 
172 /*WIKI
173  * @page = GUIWidgetDefinitionWML
174  * @order = 1_stacked_widget
175  *
176  * == Stacked widget ==
177  *
178  * A stacked widget holds several widgets on top of each other. This can be used
179  * for various effects; add an optional overlay to an image, stack it with a
180  * spacer to force a minimum size of a widget. The latter is handy to avoid
181  * making a separate definition for a single instance with a fixed size.
182  *
183  * A stacked widget has no states.
184  * @begin{parent}{name="gui/"}
185  * @begin{tag}{name="stacked_widget_definition"}{min=0}{max=-1}{super="generic/widget_definition"}
186  * @begin{tag}{name="resolution"}{min=0}{max=-1}{super="generic/widget_definition/resolution"}
187  * @allow{link}{name="gui/window/resolution/grid"}
188  * @end{tag}{name="resolution"}
189  * @end{tag}{name="stacked_widget_definition"}
190  * @end{parent}{name="gui/"}
191  */
193  : tresolution_definition_(cfg), grid(nullptr)
194 {
195  // Add a dummy state since every widget needs a state.
196  static config dummy("draw");
197  state.push_back(tstate_definition(dummy));
198 
199  const config& child = cfg.child("grid");
200  VALIDATE(child, _("No grid defined."));
201 
202  grid = new tbuilder_grid(child);
203 }
204 
205 // }---------- BUILDER -----------{
206 
207 /*WIKI
208  * @page = GUIToolkitWML
209  * @order = 2_stacked_widget
210  *
211  * == Stacked widget ==
212  *
213  * A stacked widget is a set of widget stacked on top of each other. The
214  * widgets are drawn in the layers, in the order defined in the the instance
215  * config. By default the last drawn item is also the 'active' layer for the
216  * event handling.
217  * @begin{parent}{name="gui/window/resolution/grid/row/column/"}
218  * @begin{tag}{name="stacked_widget"}{min="0"}{max="-1"}{super="generic/widget_instance"}
219  * @begin{table}{config}
220  * @end{table}
221  * @begin{tag}{name="stack"}{min=0}{max=-1}
222  * @begin{tag}{name="layer"}{min=0}{max=-1}{super="gui/window/resolution/grid"}
223  * @end{tag}{name="layer"}
224  * @end{tag}{name="stack"}
225  * @end{tag}{name="stacked_widget"}
226  * @end{parent}{name="gui/window/resolution/grid/row/column/"}
227  */
228 
229 namespace implementation
230 {
231 
232 tbuilder_stacked_widget::tbuilder_stacked_widget(const config& cfg)
233  : tbuilder_control(cfg), stack()
234 {
235  const config& s = cfg.child("stack");
236  VALIDATE(s, _("No stack defined."));
237  for(const auto & layer : s.child_range("layer"))
238  {
239  stack.push_back(new tbuilder_grid(layer));
240  }
241 }
242 
244 {
245  tstacked_widget* widget = new tstacked_widget();
246 
247  init_control(widget);
248 
249  DBG_GUI_G << "Window builder: placed stacked widget '" << id
250  << "' with definition '" << definition << "'.\n";
251 
253  conf = boost::
254  dynamic_pointer_cast<const tstacked_widget_definition::tresolution>(
255  widget->config());
256  assert(conf);
257 
258  widget->init_grid(conf->grid);
259 
260  widget->finalize(stack);
261 
262  return widget;
263 }
264 
265 } // namespace implementation
266 
267 // }------------ END --------------
268 
269 } // namespace gui2
#define DBG_GUI_P
Definition: log.hpp:69
child_itors child_range(const std::string &key)
Definition: config.cpp:613
Abstract base class for the generator.
Definition: generator.hpp:41
void finalize(std::vector< tbuilder_grid_const_ptr > widget_builder)
Finishes the building initialization of the widget.
virtual void select_item(const unsigned index, const bool select)=0
(De)selects an item.
const tgrid & grid() const
Definition: container.hpp:229
twindow * build(CVideo &video, const twindow_builder::tresolution *definition)
Builds a window.
virtual void layout_children() override
See twidget::layout_children.
Definition: grid.cpp:575
unsigned int get_layer_count() const
Gets the total number of layers.
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1221
Base container class.
Definition: grid.hpp:29
tresolution_definition_ptr config()
Definition: control.hpp:299
tgrid * get_layer_grid(unsigned int i)
virtual tgrid & item(const unsigned index)=0
Gets the grid of an item.
void select_layer(const int layer)
Selects and displays a particular layer.
std::vector< tbuilder_grid_const_ptr > stack
The builders for all layers of the stack .
Base class of a resolution, contains the common keys for a resolution.
A class inherited from ttext_box that displays its input as stars.
Definition: field-fwd.hpp:23
void init_control(tcontrol *control) const
Definition: control.cpp:675
std::string definition
Parameters for the control.
Definition: control.hpp:530
twidget * parent()
Definition: widget.cpp:155
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:82
#define VALIDATE(cond, message)
The macro to use for the validation of WML.
This file contains the settings handling of the widget library.
GLenum GLenum GLuint GLint GLint layer
Definition: glew.h:3455
virtual unsigned get_item_count() const =0
Returns the number of items.
virtual bool is_selected(const unsigned index) const =0
Returns whether the item is selected.
tstacked_widget_definition(const config &cfg)
std::string selected
Definition: game_config.cpp:84
virtual tgrid & create_item(const int index, tbuilder_grid_const_ptr list_builder, const string_map &item_data, const std::function< void(twidget &)> &callback)=0
Creates a new item.
void init_grid(const boost::intrusive_ptr< tbuilder_grid > &grid_builder)
Initializes and builds the grid.
Definition: container.cpp:209
The user sets the widget hidden, that means:
Definition: widget.hpp:91
void set_id(const std::string &id)
Definition: widget.cpp:97
static size_t id
Ids for the timers.
Definition: timer.cpp:39
int selected_layer_
The number of the current selected layer.
virtual bool get_active() const override
See tcontrol::get_active.
Contains the state info for a resolution.
#define REGISTER_WIDGET(id)
Wrapper for REGISTER_WIDGET3.
std::map< std::string, t_string > string_map
Definition: generator.hpp:23
virtual void set_self_active(const bool active) override
See tcontainer_::set_self_active.
The user sets the widget visible, that means:
Definition: widget.hpp:79
virtual void layout_children() override
See twidget::layout_children.
void select_layer_internal(const unsigned int layer, const bool select) const
Helper to ensure the correct state is set when selecting a layer.
size_t i
Definition: function.cpp:1057
twidget * swap_child(const std::string &id, twidget *widget, const bool recurse, twidget *new_parent=nullptr)
Exchanges a child in the grid.
Definition: grid.cpp:99
tgenerator_ * generator_
Contains a pointer to the generator.
virtual unsigned get_state() const override
See tcontrol::get_state.
A generic container base class.
Definition: container.hpp:32
std::vector< tstate_definition > state
config & child(const std::string &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:658
Base class for all widgets.
Definition: widget.hpp:49
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
GLdouble s
Definition: glew.h:1358
virtual const std::string & get_control_type() const override
See tcontrol::get_control_type.
#define DBG_GUI_G
Definition: log.hpp:41
void set_visible(const tvisible::scoped_enum visible)
Definition: widget.cpp:445
GLsizei const GLcharARB ** string
Definition: glew.h:4503
Contains the implementation details for lexical_cast and shouldn't be used directly.