The Battle for Wesnoth  1.17.23+dev
toggle_button.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2023
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 #include "gettext.hpp"
28 
29 #include <functional>
30 
31 #define LOG_SCOPE_HEADER get_control_type() + " [" + id() + "] " + __func__
32 #define LOG_HEADER LOG_SCOPE_HEADER + ':'
33 
34 namespace gui2
35 {
36 
37 // ------------ WIDGET -----------{
38 
39 REGISTER_WIDGET(toggle_button)
40 
41 toggle_button::toggle_button(const implementation::builder_toggle_button& builder)
42  : styled_widget(builder, type())
43  , state_(ENABLED)
44  , state_num_(0)
45  , retval_(retval::NONE)
46  , icon_name_()
47 {
48  connect_signal<event::MOUSE_ENTER>(std::bind(
49  &toggle_button::signal_handler_mouse_enter, this, std::placeholders::_2, std::placeholders::_3));
50  connect_signal<event::MOUSE_LEAVE>(std::bind(
51  &toggle_button::signal_handler_mouse_leave, this, std::placeholders::_2, std::placeholders::_3));
52 
53  connect_signal<event::LEFT_BUTTON_CLICK>(std::bind(
54  &toggle_button::signal_handler_left_button_click, this, std::placeholders::_2, std::placeholders::_3));
55  connect_signal<event::LEFT_BUTTON_DOUBLE_CLICK>(std::bind(
57  this,
58  std::placeholders::_2,
59  std::placeholders::_3));
60 }
61 
62 unsigned toggle_button::num_states() const
63 {
64  std::div_t res = std::div(this->get_config()->state.size(), COUNT);
65  assert(res.rem == 0);
66  assert(res.quot > 0);
67  return res.quot;
68 }
69 
71 {
72  // Inherit
74 
75  widget_item::const_iterator itor = data.find("icon");
76  if(itor != data.end()) {
77  set_icon_name(itor->second);
78  }
79 }
80 
81 void toggle_button::set_active(const bool active)
82 {
83  if(active) {
85  } else {
87  }
88 }
89 
91 {
92  return state_ != DISABLED;
93 }
94 
95 unsigned toggle_button::get_state() const
96 {
97  return state_ + COUNT * state_num_;
98 }
99 
101 {
102  // Inherit.
104 
105  // set icon in canvases
106  std::vector<canvas>& canvases = styled_widget::get_canvases();
107  for(auto & canvas : canvases)
108  {
110  }
111 
112  queue_redraw();
113 }
114 
116 {
118  if(selected == get_value()) {
119  return;
120  }
122  queue_redraw();
123 
124  // Check for get_window() is here to prevent the callback from
125  // being called when the initial value is set.
126  if(!get_window()) {
127  return;
128  }
129  if (fire_event) {
130  fire(event::NOTIFY_MODIFIED, *this, nullptr);
131  }
132 }
133 
135 {
136  if(retval == retval_) {
137  return;
138  }
139 
140  retval_ = retval;
142 }
143 
145 {
146  if(state != state_) {
147  state_ = state;
148  queue_redraw();
149  }
150 }
151 
153  bool& handled)
154 {
155  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
157  handled = true;
158 }
159 
161  bool& handled)
162 {
163  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
165  handled = true;
166 }
167 
169  bool& handled)
170 {
171  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
172 
174 
175  set_value(get_value() + 1, true);
176 
177  handled = true;
178 }
179 
181  const event::ui_event event, bool& handled)
182 {
183  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
184 
185  if(retval_ == retval::NONE) {
186  return;
187  }
188 
189  window* window = get_window();
190  assert(window);
191 
193 
194  handled = true;
195 }
196 
197 // }---------- DEFINITION ---------{
198 
201 {
202  DBG_GUI_P << "Parsing toggle button " << id;
203 
204  load_resolutions<resolution>(cfg);
205 }
206 
208  : resolution_definition(cfg)
209 {
210  // Note the order should be the same as the enum state_t in
211  // toggle_button.hpp.
212  for(const auto& c : cfg.child_range("state"))
213  {
214  state.emplace_back(VALIDATE_WML_CHILD(c, "enabled", _("Missing required state for toggle button")));
215  state.emplace_back(VALIDATE_WML_CHILD(c, "disabled", _("Missing required state for toggle button")));
216  state.emplace_back(VALIDATE_WML_CHILD(c, "focused", _("Missing required state for toggle button")));
217  }
218 }
219 
220 // }---------- BUILDER -----------{
221 
222 namespace implementation
223 {
224 
225 builder_toggle_button::builder_toggle_button(const config& cfg)
226  : builder_styled_widget(cfg)
227  , icon_name_(cfg["icon"])
228  , retval_id_(cfg["return_value_id"])
229  , retval_(cfg["return_value"])
230 {
231 }
232 
233 std::unique_ptr<widget> builder_toggle_button::build() const
234 {
235  auto widget = std::make_unique<toggle_button>(*this);
236 
237  widget->set_icon_name(icon_name_);
238  widget->set_retval(get_retval(retval_id_, retval_, id));
239 
240  DBG_GUI_G << "Window builder: placed toggle button '" << id
241  << "' with definition '" << definition << "'.";
242 
243  return widget;
244 }
245 
246 } // namespace implementation
247 
248 // }------------ END --------------
249 
250 } // namespace gui2
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:161
child_itors child_range(config_key_type key)
Definition: config.cpp:277
A simple canvas which can be drawn upon.
Definition: canvas.hpp:45
void set_variable(const std::string &key, wfl::variant &&value)
Definition: canvas.hpp:154
bool fire(const ui_event event, widget &target)
Fires an event which has no extra parameters.
Definition: dispatcher.cpp:76
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:54
void queue_redraw()
Indicates that this widget should be redrawn.
Definition: widget.cpp:456
window * get_window()
Get the parent window.
Definition: widget.cpp:118
base class of top level items, the only item which needs to store the final canvases to draw on.
Definition: window.hpp:67
void set_retval(const int retval, const bool close_window=true)
Sets there return value of the window.
Definition: window.hpp:403
static std::string _(const char *str)
Definition: gettext.hpp:93
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:32
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:1066
std::string_view data
Definition: picture.cpp:199
#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
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)