The Battle for Wesnoth  1.19.0-dev
toggle_button.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 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 
21 #include "gui/widgets/settings.hpp"
22 #include "gui/widgets/window.hpp"
23 #include "gui/core/log.hpp"
25 #include "sound.hpp"
26 #include "wml_exception.hpp"
27 
28 #include <functional>
29 
30 #define LOG_SCOPE_HEADER get_control_type() + " [" + id() + "] " + __func__
31 #define LOG_HEADER LOG_SCOPE_HEADER + ':'
32 
33 namespace gui2
34 {
35 
36 // ------------ WIDGET -----------{
37 
38 REGISTER_WIDGET(toggle_button)
39 
40 toggle_button::toggle_button(const implementation::builder_toggle_button& builder)
41  : styled_widget(builder, type())
42  , state_(ENABLED)
43  , state_num_(0)
44  , retval_(retval::NONE)
45  , icon_name_()
46 {
47  connect_signal<event::MOUSE_ENTER>(std::bind(
48  &toggle_button::signal_handler_mouse_enter, this, std::placeholders::_2, std::placeholders::_3));
49  connect_signal<event::MOUSE_LEAVE>(std::bind(
50  &toggle_button::signal_handler_mouse_leave, this, std::placeholders::_2, std::placeholders::_3));
51 
52  connect_signal<event::LEFT_BUTTON_CLICK>(std::bind(
53  &toggle_button::signal_handler_left_button_click, this, std::placeholders::_2, std::placeholders::_3));
54  connect_signal<event::LEFT_BUTTON_DOUBLE_CLICK>(std::bind(
56  this,
57  std::placeholders::_2,
58  std::placeholders::_3));
59 }
60 
61 unsigned toggle_button::num_states() const
62 {
63  std::div_t res = std::div(this->get_config()->state.size(), COUNT);
64  assert(res.rem == 0);
65  assert(res.quot > 0);
66  return res.quot;
67 }
68 
70 {
71  // Inherit
73 
74  widget_item::const_iterator itor = data.find("icon");
75  if(itor != data.end()) {
76  set_icon_name(itor->second);
77  }
78 }
79 
80 void toggle_button::set_active(const bool active)
81 {
82  if(active) {
84  } else {
86  }
87 }
88 
90 {
91  return state_ != DISABLED;
92 }
93 
94 unsigned toggle_button::get_state() const
95 {
96  return state_ + COUNT * state_num_;
97 }
98 
100 {
101  // Inherit.
103 
104  // set icon in canvases
105  std::vector<canvas>& canvases = styled_widget::get_canvases();
106  for(auto & canvas : canvases)
107  {
109  }
110 
111  queue_redraw();
112 }
113 
115 {
117  if(selected == get_value()) {
118  return;
119  }
121  queue_redraw();
122 
123  // Check for get_window() is here to prevent the callback from
124  // being called when the initial value is set.
125  if(!get_window()) {
126  return;
127  }
128  if (fire_event) {
129  fire(event::NOTIFY_MODIFIED, *this, nullptr);
130  }
131 }
132 
134 {
135  if(retval == retval_) {
136  return;
137  }
138 
139  retval_ = retval;
141 }
142 
144 {
145  if(state != state_) {
146  state_ = state;
147  queue_redraw();
148  }
149 }
150 
152  bool& handled)
153 {
154  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
156  handled = true;
157 }
158 
160  bool& handled)
161 {
162  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
164  handled = true;
165 }
166 
168  bool& handled)
169 {
170  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
171 
173 
174  set_value(get_value() + 1, true);
175 
176  handled = true;
177 }
178 
180  const event::ui_event event, bool& handled)
181 {
182  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
183 
184  if(retval_ == retval::NONE) {
185  return;
186  }
187 
188  window* window = get_window();
189  assert(window);
190 
192 
193  handled = true;
194 }
195 
196 // }---------- DEFINITION ---------{
197 
200 {
201  DBG_GUI_P << "Parsing toggle button " << id;
202 
203  load_resolutions<resolution>(cfg);
204 }
205 
207  : resolution_definition(cfg)
208 {
209  // Note the order should be the same as the enum state_t in
210  // toggle_button.hpp.
211  for(const auto& c : cfg.child_range("state"))
212  {
213  state.emplace_back(VALIDATE_WML_CHILD(c, "enabled", missing_mandatory_wml_tag("toggle_button_definition][resolution][state", "enabled")));
214  state.emplace_back(VALIDATE_WML_CHILD(c, "disabled", missing_mandatory_wml_tag("toggle_button_definition][resolution][state", "disabled")));
215  state.emplace_back(VALIDATE_WML_CHILD(c, "focused", missing_mandatory_wml_tag("toggle_button_definition][resolution][state", "focused")));
216  }
217 }
218 
219 // }---------- BUILDER -----------{
220 
221 namespace implementation
222 {
223 
224 builder_toggle_button::builder_toggle_button(const config& cfg)
225  : builder_styled_widget(cfg)
226  , icon_name_(cfg["icon"])
227  , retval_id_(cfg["return_value_id"])
228  , retval_(cfg["return_value"])
229 {
230 }
231 
232 std::unique_ptr<widget> builder_toggle_button::build() const
233 {
234  auto widget = std::make_unique<toggle_button>(*this);
235 
236  widget->set_icon_name(icon_name_);
237  widget->set_retval(get_retval(retval_id_, retval_, id));
238 
239  DBG_GUI_G << "Window builder: placed toggle button '" << id
240  << "' with definition '" << definition << "'.";
241 
242  return widget;
243 }
244 
245 } // namespace implementation
246 
247 // }------------ END --------------
248 
249 } // namespace gui2
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:159
child_itors child_range(config_key_type key)
Definition: config.cpp:273
A simple canvas which can be drawn upon.
Definition: canvas.hpp:44
void set_variable(const std::string &key, wfl::variant &&value)
Definition: canvas.hpp:153
bool fire(const ui_event event, widget &target)
Fires an event which has no extra parameters.
Definition: dispatcher.cpp:74
void set_wants_mouse_left_double_click(const bool click=true)
Base class for all visible items.
std::vector< canvas > & get_canvases()
virtual void update_canvas()
Updates the canvas(ses).
virtual void set_members(const widget_item &data)
Sets the members of the styled_widget.
resolution_definition_ptr get_config()
Class for a toggle button.
void set_state(const state_t state)
virtual void set_value(unsigned selected, bool fire_event=false) override
Inherited from selectable_item.
void signal_handler_mouse_enter(const event::ui_event event, bool &handled)
void signal_handler_mouse_leave(const event::ui_event event, bool &handled)
virtual void set_active(const bool active) override
See styled_widget::set_active.
virtual unsigned get_state() const override
See styled_widget::get_state.
void set_members(const widget_item &data) override
See styled_widget::set_members.
unsigned state_num_
Usually 1 for selected and 0 for not selected, can also have higher values in tristate buttons.
state_t
Possible states of the widget.
virtual void update_canvas() override
Inherited from styled_widget.
virtual unsigned get_value() const override
Inherited from selectable_item.
void signal_handler_left_button_click(const event::ui_event event, bool &handled)
std::string icon_name_
The toggle button can contain an icon next to the text.
int retval_
The return value of the button.
void signal_handler_left_button_double_click(const event::ui_event event, bool &handled)
virtual unsigned num_states() const override
Inherited from selectable_item.
void set_retval(const int retval)
virtual bool get_active() const override
See styled_widget::get_active.
state_t state_
Current state of the widget.
void set_icon_name(const std::string &icon_name)
Base class for all widgets.
Definition: widget.hpp:53
void queue_redraw()
Indicates that this widget should be redrawn.
Definition: widget.cpp:455
window * get_window()
Get the parent window.
Definition: widget.cpp:117
base class of top level items, the only item which needs to store the final canvases to draw on.
Definition: window.hpp:63
void set_retval(const int retval, const bool close_window=true)
Sets there return value of the window.
Definition: window.hpp:399
Define the common log macros for the gui toolkit.
#define DBG_GUI_G
Definition: log.hpp:41
#define DBG_GUI_P
Definition: log.hpp:66
#define DBG_GUI_E
Definition: log.hpp:35
This file contains the window object, this object is a top level container which has the event manage...
std::string selected
bool fire_event(const ui_event event, const std::vector< std::pair< widget *, ui_event >> &event_chain, widget *dispatcher, widget *w, F &&... params)
Helper function for fire_event.
ui_event
The event sent to the dispatcher.
Definition: handler.hpp:115
@ NOTIFY_MODIFIED
Definition: handler.hpp:158
int get_retval(const std::string &retval_id, const int retval, const std::string &id)
Returns the return value for a widget.
Definition: helper.cpp:137
std::string sound_toggle_button_click
Definition: settings.cpp:49
Generic file dialog.
std::map< std::string, t_string > widget_item
Definition: widget.hpp:31
retval
Default window/dialog return values.
Definition: retval.hpp:30
@ NONE
Default, unset return value.
Definition: retval.hpp:32
Contains the implementation details for lexical_cast and shouldn't be used directly.
void play_UI_sound(const std::string &files)
Definition: sound.cpp:1064
std::string_view data
Definition: picture.cpp:194
#define REGISTER_WIDGET(id)
Wrapper for REGISTER_WIDGET3.
This file contains the settings handling of the widget library.
std::string definition
Parameters for the styled_widget.
virtual std::unique_ptr< widget > build() const override
Base class of a resolution, contains the common keys for a resolution.
std::vector< state_definition > state
toggle_button_definition(const config &cfg)
mock_char c
#define LOG_HEADER
std::string missing_mandatory_wml_tag(const std::string &section, const std::string &tag)
Returns a standard message for a missing wml child (tag).
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
#define VALIDATE_WML_CHILD(cfg, key, message)