lxgui
Loading...
Searching...
No Matches
gui_button.cpp
1#include "lxgui/gui_button.hpp"
2
3#include "lxgui/gui_alive_checker.hpp"
4#include "lxgui/gui_font_string.hpp"
5#include "lxgui/gui_frame.hpp"
6#include "lxgui/gui_manager.hpp"
7#include "lxgui/gui_out.hpp"
8#include "lxgui/gui_region_tpl.hpp"
9#include "lxgui/gui_texture.hpp"
10
11namespace lxgui::gui {
12
13button::button(utils::control_block& block, manager& mgr, const frame_core_attributes& attr) :
14 frame(block, mgr, attr) {
15
16 initialize_(*this, attr);
17
20}
21
22std::string button::serialize(const std::string& tab) const {
23 return base::serialize(tab);
24}
25
26bool button::can_use_script(const std::string& script_name) const {
27 return base::can_use_script(script_name) || script_name == "OnClick" ||
28 script_name == "OnEnable" || script_name == "OnDisable";
29}
30
31void button::fire_script(const std::string& script_name, const event_data& data) {
32 alive_checker checker(*this);
33 base::fire_script(script_name, data);
34 if (!checker.is_alive())
35 return;
36
37 if (!is_enabled())
38 return;
39
40 if (script_name == "OnEnter")
41 highlight();
42
43 if (script_name == "OnLeave") {
44 unlight();
45
46 if (state_ == state::down)
47 release();
48 }
49
50 bool try_handle_click = false;
51 if (script_name == "OnMouseDown" || script_name == "OnMouseUp" ||
52 script_name == "OnDoubleClick") {
53
54 try_handle_click = true;
55
56 // If reacting to a "mouse up" event, only handle as a click if
57 // the mouse was pressed down on this button.
58 if (script_name == "OnMouseUp" && !data.get<bool>(5)) {
59 try_handle_click = false;
60 }
61 }
62
63 if (try_handle_click) {
64 const input::mouse_button button_id = data.get<input::mouse_button>(0);
65 const input::mouse_button_event event_id =
66 script_name == "OnMouseDown" ? input::mouse_button_event::down
67 : script_name == "OnMouseUp" ? input::mouse_button_event::up
69
70 if (is_button_clicks_enabled_(button_id)) {
71 if (event_id == input::mouse_button_event::down)
72 push();
73 else if (event_id == input::mouse_button_event::up)
74 release();
75 }
76
77 float mx = data.get<float>(2);
78 float my = data.get<float>(3);
79
80 click_(button_id, event_id, mx, my);
81 if (!checker.is_alive())
82 return;
83 }
84}
85
86void button::copy_from(const region& obj) {
87 base::copy_from(obj);
88
89 const button* button_obj = down_cast<button>(&obj);
90 if (!button_obj)
91 return;
92
93 this->set_text(button_obj->get_text());
94
95 if (const texture* other_texture = button_obj->get_normal_texture().get()) {
97 attr.name = other_texture->get_raw_name();
98 attr.inheritance = {button_obj->get_normal_texture()};
99
100 auto tex =
101 this->create_layered_region<texture>(other_texture->get_draw_layer(), std::move(attr));
102
103 if (tex) {
104 tex->set_manually_inherited(true);
105 tex->notify_loaded();
106 this->set_normal_texture(tex);
107 }
108 }
109
110 if (const texture* other_texture = button_obj->get_pushed_texture().get()) {
112 attr.name = other_texture->get_raw_name();
113 attr.inheritance = {button_obj->get_pushed_texture()};
114
115 auto tex =
116 this->create_layered_region<texture>(other_texture->get_draw_layer(), std::move(attr));
117
118 if (tex) {
119 tex->set_manually_inherited(true);
120 tex->notify_loaded();
121 this->set_pushed_texture(tex);
122 }
123 }
124
125 if (const texture* other_texture = button_obj->get_highlight_texture().get()) {
127 attr.name = other_texture->get_raw_name();
128 attr.inheritance = {button_obj->get_highlight_texture()};
129
130 auto tex =
131 this->create_layered_region<texture>(other_texture->get_draw_layer(), std::move(attr));
132
133 if (tex) {
134 tex->set_manually_inherited(true);
135 tex->notify_loaded();
136 this->set_highlight_texture(tex);
137 }
138 }
139
140 if (const texture* other_texture = button_obj->get_disabled_texture().get()) {
142 attr.name = other_texture->get_raw_name();
143 attr.inheritance = {button_obj->get_disabled_texture()};
144
145 auto tex =
146 this->create_layered_region<texture>(other_texture->get_draw_layer(), std::move(attr));
147
148 if (tex) {
149 tex->set_manually_inherited(true);
150 tex->notify_loaded();
151 this->set_disabled_texture(tex);
152 }
153 }
154
155 if (const font_string* other_text = button_obj->get_normal_text().get()) {
157 attr.name = other_text->get_raw_name();
158 attr.inheritance = {button_obj->get_normal_text()};
159
160 auto fstr =
161 this->create_layered_region<font_string>(other_text->get_draw_layer(), std::move(attr));
162
163 if (fstr) {
164 fstr->set_manually_inherited(true);
165 fstr->notify_loaded();
166 this->set_normal_text(fstr);
167 }
168 }
169
170 if (const font_string* other_text = button_obj->get_highlight_text().get()) {
172 attr.name = other_text->get_raw_name();
173 attr.inheritance = {button_obj->get_highlight_text()};
174
175 auto fstr =
176 this->create_layered_region<font_string>(other_text->get_draw_layer(), std::move(attr));
177
178 if (fstr) {
179 fstr->set_manually_inherited(true);
180 fstr->notify_loaded();
181 this->set_highlight_text(fstr);
182 }
183 }
184
185 if (const font_string* other_text = button_obj->get_disabled_text().get()) {
187 attr.name = other_text->get_raw_name();
188 attr.inheritance = {button_obj->get_disabled_text()};
189
190 auto fstr =
191 this->create_layered_region<font_string>(other_text->get_draw_layer(), std::move(attr));
192
193 if (fstr) {
194 fstr->set_manually_inherited(true);
195 fstr->notify_loaded();
196 this->set_disabled_text(fstr);
197 }
198 }
199
201
202 if (!button_obj->is_enabled())
203 this->disable();
204}
205
206void button::set_text(const utils::ustring& content) {
207 content_ = content;
208
209 if (normal_text_)
210 normal_text_->set_text(content);
211
212 if (highlight_text_)
213 highlight_text_->set_text(content);
214
215 if (disabled_text_)
216 disabled_text_->set_text(content);
217}
218
219const utils::ustring& button::get_text() const {
220 return content_;
221}
222
223void button::set_normal_texture(utils::observer_ptr<texture> tex) {
224 normal_texture_ = std::move(tex);
225 if (!normal_texture_)
226 return;
227
228 normal_texture_->set_shown(state_ == state::up);
229}
230
231void button::set_pushed_texture(utils::observer_ptr<texture> tex) {
232 pushed_texture_ = std::move(tex);
233 if (!pushed_texture_)
234 return;
235
236 pushed_texture_->set_shown(state_ == state::down);
237}
238
239void button::set_disabled_texture(utils::observer_ptr<texture> tex) {
240 disabled_texture_ = std::move(tex);
242 return;
243
245}
246
247void button::set_highlight_texture(utils::observer_ptr<texture> tex) {
248 highlight_texture_ = std::move(tex);
250 return;
251
253}
254
255void button::set_normal_text(utils::observer_ptr<font_string> fstr) {
258
259 normal_text_ = std::move(fstr);
260 if (!normal_text_)
261 return;
262
263 normal_text_->set_shown(state_ == state::up);
264 normal_text_->set_text(content_);
265}
266
267void button::set_highlight_text(utils::observer_ptr<font_string> fstr) {
270
271 highlight_text_ = std::move(fstr);
272 if (!highlight_text_)
273 return;
274
276 highlight_text_->set_text(content_);
277}
278
279void button::set_disabled_text(utils::observer_ptr<font_string> fstr) {
282
283 disabled_text_ = std::move(fstr);
284 if (!disabled_text_)
285 return;
286
288 disabled_text_->set_text(content_);
289}
290
292 if (!is_enabled())
293 return;
294
296 if (disabled_texture_) {
297 if (normal_texture_)
298 normal_texture_->hide();
299 if (pushed_texture_)
300 pushed_texture_->hide();
301
302 disabled_texture_->show();
303 } else {
304 if (normal_texture_)
305 normal_texture_->show();
306 if (pushed_texture_)
307 pushed_texture_->hide();
308 }
309
310 if (disabled_text_) {
311 if (normal_text_)
312 normal_text_->hide();
313
314 disabled_text_->show();
316 } else {
317 if (normal_text_)
318 normal_text_->show();
319
321 }
322
323 unlight();
324
325 fire_script("OnDisable");
326}
327
329 if (is_enabled())
330 return;
331
333 if (disabled_texture_) {
334 if (normal_texture_)
335 normal_texture_->show();
336 if (pushed_texture_)
337 pushed_texture_->hide();
338
339 disabled_texture_->hide();
340 } else {
341 if (normal_texture_)
342 normal_texture_->show();
343 if (pushed_texture_)
344 pushed_texture_->hide();
345 }
346
347 if (normal_text_)
348 normal_text_->show();
349
351
352 if (disabled_text_)
353 disabled_text_->hide();
354
355 fire_script("OnEnable");
356}
357
358bool button::is_enabled() const {
359 return state_ != state::disabled;
360}
361
363 if (!is_enabled())
364 return;
365
366 if (pushed_texture_) {
367 pushed_texture_->show();
368 if (normal_texture_)
369 normal_texture_->hide();
370 }
371
372 if (highlight_text_)
374 if (normal_text_)
376
378}
379
381 if (!is_enabled())
382 return;
383
384 if (pushed_texture_) {
385 pushed_texture_->hide();
386 if (normal_texture_)
387 normal_texture_->show();
388 }
389
390 if (highlight_text_)
391 highlight_text_->set_offset(vector2f(0, 0));
392 if (normal_text_)
393 normal_text_->set_offset(vector2f(0, 0));
394
396}
397
398void button::click(const std::string& mouse_event) {
399 auto mouse_event_id = input::get_mouse_button_and_event_from_codename(mouse_event);
400 if (!mouse_event_id.has_value()) {
401 return;
402 }
403
404 click(mouse_event_id.value().first, mouse_event_id.value().second);
405}
406
409 click_(button_id, button_event, center.x, center.y);
410}
411
413 input::mouse_button button_id, input::mouse_button_event button_event, float mx, float my) {
414
415 if (!is_button_clicks_enabled(button_id, button_event)) {
416 return;
417 }
418
419 std::string event_name =
420 std::string{input::get_mouse_button_and_event_codename(button_id, button_event)};
421
422 event_data new_data;
423 new_data.add(static_cast<std::underlying_type_t<input::mouse_button>>(button_id));
424 new_data.add(static_cast<std::underlying_type_t<input::mouse_button_event>>(button_event));
425 new_data.add(event_name);
426 new_data.add(mx);
427 new_data.add(my);
428 fire_script("OnClick", new_data);
429}
430
432 if (is_highlighted_)
433 return;
434
435 if (highlight_texture_) {
436 highlight_texture_->show();
437 }
438
439 if (highlight_text_) {
441 current_font_string_->hide();
443 current_font_string_->show();
444 }
445
446 is_highlighted_ = true;
447}
448
451 return;
452
453 if (highlight_texture_) {
454 highlight_texture_->hide();
455 }
456
457 if (highlight_text_) {
459 current_font_string_->hide();
460
461 switch (state_) {
465 }
466
468 current_font_string_->show();
469 }
470
471 is_highlighted_ = false;
472}
473
477
482
485 unlight();
486
487 is_highlight_locked_ = false;
488}
489
494
498
499void button::enable_button_clicks(const std::string& mouse_state) {
500 reg_click_list_.insert(mouse_state);
501}
502
504 input::mouse_button button_id, input::mouse_button_event button_event) {
505 reg_click_list_.insert(
506 std::string{input::get_mouse_button_and_event_codename(button_id, button_event)});
507}
508
509void button::disable_button_clicks(const std::string& mouse_state) {
510 reg_click_list_.erase(mouse_state);
511}
512
514 input::mouse_button button_id, input::mouse_button_event button_event) {
515 reg_click_list_.erase(
516 std::string{input::get_mouse_button_and_event_codename(button_id, button_event)});
517}
518
522
523bool button::is_button_clicks_enabled(const std::string& mouse_event) const {
524 return reg_click_list_.find(mouse_event) != reg_click_list_.end();
525}
526
528 input::mouse_button button_id, input::mouse_button_event button_event) const {
530 button_id, button_event)}) != reg_click_list_.end();
531}
532
534 auto button_name = input::get_mouse_button_codename(button_id);
535 for (const auto& click : reg_click_list_) {
536 if (click.find(button_name) == 0) {
537 return true;
538 }
539 }
540
541 return false;
542}
543
544const std::vector<std::string>& button::get_type_list_() const {
545 return get_type_list_impl_<button>();
546}
547
548} // namespace lxgui::gui
Utility class for safe checking of region validity.
bool is_alive() const
Check if the wrapped region is still alive.
A frame with a button that can be clicked.
bool is_button_clicks_enabled(const std::string &mouse_event) const
Checks if this button can generate OnClick events when a specific mouse event occurs over the button.
const utils::observer_ptr< texture > & get_highlight_texture()
Returns this button's highlight texture.
void enable_button_clicks(const std::string &mouse_event)
Make this button generate OnClick events when a specific mouse event occurs over the button.
void set_highlight_text(utils::observer_ptr< font_string > fstr)
Sets this button's highlight text.
void set_normal_texture(utils::observer_ptr< texture > tex)
Sets this button's normal texture.
utils::observer_ptr< texture > highlight_texture_
void click(const std::string &mouse_event)
Handle a mouse click over this button.
void set_pushed_texture(utils::observer_ptr< texture > tex)
Sets this button's pushed texture.
utils::observer_ptr< texture > disabled_texture_
const utils::observer_ptr< texture > & get_disabled_texture()
Returns this button's disabled texture.
void set_disabled_texture(utils::observer_ptr< texture > tex)
Sets this button's disabled texture.
state get_button_state() const
Returns this button's state.
std::string serialize(const std::string &tab) const override
Prints all relevant information about this region in a string.
bool is_button_clicks_enabled_(input::mouse_button button_id) const
utils::observer_ptr< font_string > current_font_string_
std::set< std::string > reg_click_list_
virtual void disable()
Disables this button.
void set_highlight_texture(utils::observer_ptr< texture > tex)
Sets this button's highlight texture.
utils::observer_ptr< font_string > normal_text_
virtual void click_(input::mouse_button button_id, input::mouse_button_event button_event, float mx, float my)
const utils::observer_ptr< font_string > & get_normal_text()
Returns this button's normal text.
bool is_enabled() const
Checks if this button is enabled.
const utils::observer_ptr< texture > & get_pushed_texture()
Returns this button's pushed texture.
virtual void highlight()
Highlights this button.
const utils::ustring & get_text() const
Returns this button's text.
utils::observer_ptr< font_string > disabled_text_
virtual void release()
Releases this button.
virtual void enable()
Enables this button.
void lock_highlight()
Locks this button's highlighting.
button(utils::control_block &block, manager &mgr, const frame_core_attributes &attr)
Constructor.
void disable_button_clicks()
Stop this button from generating OnClick events.
void set_text(const utils::ustring &content)
Sets this button's text.
void copy_from(const region &obj) override
Copies a region's parameters into this button (inheritance).
const std::vector< std::string > & get_type_list_() const override
void set_pushed_text_offset(const vector2f &offset)
Sets this button's pushed text offset.
void set_disabled_text(utils::observer_ptr< font_string > fstr)
Sets this button's disabled text.
utils::ustring content_
utils::observer_ptr< font_string > highlight_text_
utils::observer_ptr< texture > pushed_texture_
const utils::observer_ptr< font_string > & get_disabled_text()
Returns this button's disabled text.
vector2f pushed_text_offset_
void set_normal_text(utils::observer_ptr< font_string > fstr)
Sets this button's normal text.
virtual void push()
Pushed this button.
bool can_use_script(const std::string &script_name) const override
Returns 'true' if this button can use a script.
const vector2f & get_pushed_text_offset() const
Returns this button's pushed text offset.
void unlock_highlight()
Unlocks this button's highlighting.
virtual void unlight()
Unlights this button.
const utils::observer_ptr< texture > & get_normal_texture()
Returns this button's normal texture.
void fire_script(const std::string &script_name, const event_data &data=event_data{}) override
Calls a script.
utils::observer_ptr< texture > normal_texture_
const utils::observer_ptr< font_string > & get_highlight_text()
Returns this button's highlight text.
Stores a variable number of arguments for an event.
const utils::variant & get(std::size_t index) const
Returns a parameter of this event.
void add(T &&value)
Adds a parameter to this event.
A layered_region that can draw text on the screen.
A region that can contain other regions and react to events.
std::string serialize(const std::string &tab) const override
Prints all relevant information about this region in a string.
Definition gui_frame.cpp:84
void copy_from(const region &obj) override
Copies a region's parameters into this frame (inheritance).
void enable_mouse()
Marks this frame as able to receive mouse input (click & move).
virtual void fire_script(const std::string &script_name, const event_data &data=event_data{})
Calls a script.
void notify_renderer_need_redraw() override
Notifies the renderer of this region that it needs to be redrawn.
virtual bool can_use_script(const std::string &script_name) const
Returns 'true' if this frame can use a script.
Manages the user interface.
The base class of all elements in the GUI.
void initialize_(T &self, const region_core_attributes &attr)
Set up function to call in all derived class constructors.
vector2f get_center() const
Returns the position of this region's center.
A layered_region that can draw images and colored rectangles.
vector2< float > vector2f
Holds 2D coordinates (as floats)
std::optional< std::pair< mouse_button, mouse_button_event > > get_mouse_button_and_event_from_codename(std::string_view button_and_event_name)
Returns a mouse button and a button event ID from a string formatted as "<button>:<event>".
std::string_view get_mouse_button_codename(mouse_button button_id)
Returns a standard English name for the provided mouse button.
Definition input_keys.cpp:7
std::string_view get_mouse_button_and_event_codename(mouse_button button_id, mouse_button_event button_event)
Returns a standard Engilsh name for the provided mouse button and event.
Struct holding all the core information about a frame necessary for its creation.
Struct holding all the core information about a region necessary for its creation.
std::vector< utils::observer_ptr< const region > > inheritance