The Battle for Wesnoth  1.19.0-dev
repeating_button.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 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 
20 #include "gui/core/log.hpp"
21 #include "gui/core/timer.hpp"
23 #include "gui/widgets/settings.hpp"
24 #include "gui/widgets/window.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(repeating_button)
39 
40 repeating_button::repeating_button(const implementation::builder_repeating_button& builder)
41  : styled_widget(builder, type())
42  , clickable_item()
43  , state_(ENABLED)
44  , repeat_timer_(0)
45 {
46  connect_signal<event::MOUSE_ENTER>(std::bind(
47  &repeating_button::signal_handler_mouse_enter, this, std::placeholders::_2, std::placeholders::_3));
48  connect_signal<event::MOUSE_LEAVE>(std::bind(
49  &repeating_button::signal_handler_mouse_leave, this, std::placeholders::_2, std::placeholders::_3));
50 
51  connect_signal<event::LEFT_BUTTON_DOWN>(std::bind(
52  &repeating_button::signal_handler_left_button_down, this, std::placeholders::_2, std::placeholders::_3));
53  connect_signal<event::LEFT_BUTTON_UP>(std::bind(
54  &repeating_button::signal_handler_left_button_up, this, std::placeholders::_2, std::placeholders::_3));
55 }
56 
58 {
59  if(repeat_timer_) {
61  }
62 }
63 
65  const event::signal& signal)
66 {
67  connect_signal<event::LEFT_BUTTON_DOWN>(signal);
68 }
69 
71  const event::signal& signal)
72 {
73  disconnect_signal<event::LEFT_BUTTON_DOWN>(signal);
74 }
75 
76 void repeating_button::set_active(const bool active)
77 {
78  if(get_active() != active) {
79  set_state(active ? ENABLED : DISABLED);
80  }
81 }
82 
84 {
85  return state_ != DISABLED;
86 }
87 
89 {
90  return state_;
91 }
92 
94 {
95  if(state != state_) {
96  state_ = state;
97  queue_redraw();
98 
99  if(state_ == DISABLED && repeat_timer_) {
101  repeat_timer_ = 0;
102  }
103  }
104 }
105 
107  bool& handled)
108 {
109  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
110 
112  handled = true;
113 }
114 
116  bool& handled)
117 {
118  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
119 
121  handled = true;
122 }
123 
124 void
126  bool& handled)
127 {
128  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
129 
130  // If the timer isn't set it's the initial down event.
131  if(!repeat_timer_) {
132 
133  // mimic the old gui and only play the sound once.
135 
136  window* window = get_window();
137  if(window) {
139  [this, window](unsigned int) {
141  },true);
142 
144  }
145 
147  }
148 
149  handled = true;
150 }
151 
153  bool& handled)
154 {
155  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
156 
157  if(repeat_timer_) {
159  repeat_timer_ = 0;
160  }
161 
162  if(get_active()) {
164  }
165  handled = true;
166 }
167 
168 // }---------- DEFINITION ---------{
169 
172 {
173  DBG_GUI_P << "Parsing repeating button " << id;
174 
175  load_resolutions<resolution>(cfg);
176 }
177 
179  : resolution_definition(cfg)
180 {
181  // Note the order should be the same as the enum state_t in
182  // repeating_button.hpp.
183  state.emplace_back(VALIDATE_WML_CHILD(cfg, "state_enabled", missing_mandatory_wml_tag("repeating_button_definition][resolution", "state_enabled")));
184  state.emplace_back(VALIDATE_WML_CHILD(cfg, "state_disabled", missing_mandatory_wml_tag("repeating_button_definition][resolution", "state_disabled")));
185  state.emplace_back(VALIDATE_WML_CHILD(cfg, "state_pressed", missing_mandatory_wml_tag("repeating_button_definition][resolution", "state_pressed")));
186  state.emplace_back(VALIDATE_WML_CHILD(cfg, "state_focused", missing_mandatory_wml_tag("repeating_button_definition][resolution", "state_focused")));
187 }
188 
189 // }---------- BUILDER -----------{
190 
191 namespace implementation
192 {
193 
194 builder_repeating_button::builder_repeating_button(const config& cfg)
195  : builder_styled_widget(cfg)
196 {
197 }
198 
199 std::unique_ptr<widget> builder_repeating_button::build() const
200 {
201  auto widget = std::make_unique<repeating_button>(*this);
202 
203  DBG_GUI_G << "Window builder: placed repeating button '" << id
204  << "' with definition '" << definition << "'.";
205 
206  return widget;
207 }
208 
209 } // namespace implementation
210 
211 // }------------ END --------------
212 
213 } // namespace gui2
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:159
Small concept class.
bool fire(const ui_event event, widget &target)
Fires an event which has no extra parameters.
Definition: dispatcher.cpp:74
A repeating_button is a control that can be pushed down and repeat a certain action.
void set_state(const state_t state)
virtual unsigned get_state() const override
See styled_widget::get_state.
state_t state_
Current state of the widget.
std::size_t repeat_timer_
The timer for the repeating events.
virtual void set_active(const bool active) override
See styled_widget::set_active.
state_t
Possible states of the widget.
void signal_handler_left_button_down(const event::ui_event event, bool &handled)
void connect_signal_mouse_left_down(const event::signal &signal)
Connects a signal handler for a left mouse button down.
virtual bool get_active() const override
See styled_widget::get_active.
void disconnect_signal_mouse_left_down(const event::signal &signal)
Disconnects a signal handler for a left mouse button down.
void signal_handler_mouse_leave(const event::ui_event event, bool &handled)
void signal_handler_left_button_up(const event::ui_event event, bool &handled)
void signal_handler_mouse_enter(const event::ui_event event, bool &handled)
Base class for all visible items.
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 mouse_capture(const bool capture=true)
Definition: window.cpp:1209
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...
ui_event
The event sent to the dispatcher.
Definition: handler.hpp:115
@ LEFT_BUTTON_DOWN
Definition: handler.hpp:120
dispatcher_callback<> signal
Used for events in event_category::general.
Definition: dispatcher.hpp:56
std::string sound_button_click
Definition: settings.cpp:48
unsigned repeat_button_repeat_time
Definition: settings.cpp:46
Generic file dialog.
std::size_t add_timer(const uint32_t interval, const std::function< void(std::size_t id)> &callback, const bool repeat)
Adds a new timer.
Definition: timer.cpp:127
bool remove_timer(const std::size_t id)
Removes a timer.
Definition: timer.cpp:168
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
#define REGISTER_WIDGET(id)
Wrapper for REGISTER_WIDGET3.
#define LOG_HEADER
This file contains the settings handling of the widget library.
virtual std::unique_ptr< widget > build() const override
std::string definition
Parameters for the styled_widget.
repeating_button_definition(const config &cfg)
Base class of a resolution, contains the common keys for a resolution.
std::vector< state_definition > state
Contains the gui2 timer routines.
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)