The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
text_box_base.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2008 - 2025
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 "cursor.hpp"
21#include "desktop/clipboard.hpp"
22#include "font/attributes.hpp"
24#include "gui/core/log.hpp"
25#include "gui/core/timer.hpp"
28#include "video.hpp"
29
30#include <SDL3/SDL_keyboard.h>
31#include <functional>
32#include <limits>
33
34#define LOG_SCOPE_HEADER get_control_type() + " [" + id() + "] " + __func__
35#define LOG_HEADER LOG_SCOPE_HEADER + ':'
36
37using namespace std::chrono_literals;
38
39namespace gui2
40{
41
42text_box_base::text_box_base(const implementation::builder_styled_widget& builder, const std::string& control_type)
43 : styled_widget(builder, control_type)
44 , state_(ENABLED)
45 , text_()
46 , selection_start_(0)
47 , selection_length_(0)
48 , editable_(true)
49 , ime_composing_(false)
50 , ime_start_point_(0)
51 , cursor_timer_(0)
52 , cursor_alpha_(0)
53 , cursor_blink_rate_(750ms)
54{
55 set_font_family(get_config()->text_font_family);
56
57#ifdef __unix__
58 // pastes on UNIX systems.
59 connect_signal<event::MIDDLE_BUTTON_CLICK>(std::bind(
60 &text_box_base::signal_handler_middle_button_click, this, std::placeholders::_2, std::placeholders::_3));
61
62#endif
63
64 connect_signal<event::SDL_KEY_DOWN>(std::bind(
65 &text_box_base::signal_handler_sdl_key_down, this, std::placeholders::_2, std::placeholders::_3, std::placeholders::_5, std::placeholders::_6));
66 connect_signal<event::SDL_TEXT_INPUT>(std::bind(&text_box_base::handle_commit, this, std::placeholders::_3, std::placeholders::_5));
67 connect_signal<event::SDL_TEXT_EDITING>(std::bind(&text_box_base::handle_editing, this, std::placeholders::_3, std::placeholders::_5, std::placeholders::_6, std::placeholders::_7));
68
69 connect_signal<event::RECEIVE_KEYBOARD_FOCUS>(std::bind(
70 &text_box_base::signal_handler_receive_keyboard_focus, this, std::placeholders::_2));
71 connect_signal<event::LOSE_KEYBOARD_FOCUS>(
72 std::bind(&text_box_base::signal_handler_lose_keyboard_focus, this, std::placeholders::_2));
73
74 connect_signal<event::MOUSE_ENTER>(
75 std::bind(&text_box_base::signal_handler_mouse_enter, this, std::placeholders::_2, std::placeholders::_3));
76 connect_signal<event::MOUSE_LEAVE>(
77 std::bind(&text_box_base::signal_handler_mouse_leave, this, std::placeholders::_2, std::placeholders::_3));
78
80}
81
87
88void text_box_base::set_active(const bool active)
89{
90 if(get_active() != active) {
91 set_state(active ? ENABLED : DISABLED);
92 }
93}
94
96{
97 return state_ != DISABLED;
98}
99
101{
102 return state_;
103}
104
105void text_box_base::set_maximum_length(const std::size_t maximum_length)
106{
107 if(maximum_length == 0) {
108 return;
109 }
110
111 const bool need_update = text_.get_length() > maximum_length;
112
113 text_.set_maximum_length(maximum_length);
114
115 if(need_update) {
116 if(selection_start_ > maximum_length) {
117 selection_start_ = maximum_length;
119 } else if(selection_start_ + selection_length_ > maximum_length) {
120 selection_length_ = maximum_length - selection_start_;
121 }
123 queue_redraw();
124 }
125}
126
127void text_box_base::set_highlight_area(const unsigned start_offset, const unsigned end_offset, const color_t& color)
128{
130 add_attribute_bg_color(attrs, start_offset, end_offset, color);
131 text_.apply_attributes(attrs);
132}
133
134void text_box_base::set_value(const std::string& text)
135{
136 if(text != text_.text()) {
138
139 // default to put the cursor at the end of the buffer.
143 queue_redraw();
144 }
145}
146
147void text_box_base::set_cursor(const std::size_t offset, const bool select)
148{
150
151 if(select) {
152 selection_length_ = (selection_start_ == offset) ? 0 : -static_cast<int>(selection_start_ - offset);
153 } else {
154 selection_start_ = (offset <= text_.get_length()) ? offset : 0;
156 }
157
159 queue_redraw();
160}
161
162void text_box_base::insert_char(const std::string& unicode)
163{
164 if(!editable_)
165 {
166 return;
167 }
168
170
172 // Update status
173 std::size_t plain_text_len = utf8::size(plain_text());
174 std::size_t cursor_pos = selection_start_ + utf8::size(unicode);
175 if (get_use_markup() && (selection_start_ + utf8::size(unicode) > plain_text_len + 1)) {
176 cursor_pos = plain_text_len;
177 }
178 set_cursor(cursor_pos, false);
180 queue_redraw();
181 }
182}
183
185{
186 if(!is_composing()) {
187 return 0;
188 }
189
190 std::size_t text_length = utf8::size(text_.text());
191 std::size_t text_cached_length = utf8::size(text_cached_);
192 if(text_length < text_cached_length) {
193 return 0;
194 }
195
197}
198
200{
201 ime_composing_ = false;
202#ifndef __ANDROID__
203 // We need to inform the IME that text input is no longer in progress.
204 SDL_StopTextInput(video::get_window());
205 SDL_StartTextInput(video::get_window());
206#endif
207}
208
210{
211 if(selection_length_ == 0) {
212 return;
213 }
214
215 unsigned end, start = selection_start_;
216 const std::string txt = get_use_markup() ? plain_text() : text_.text();
217
218 if(selection_length_ > 0) {
219 end = utf8::index(txt, start + selection_length_);
220 start = utf8::index(txt, start);
221 } else {
222 // inverse selection: selection_start_ is in fact the end
223 end = utf8::index(txt, start);
224 start = utf8::index(txt, start + selection_length_);
225 }
226 desktop::clipboard::copy_to_clipboard(txt.substr(start, end - start));
227}
228
230{
231 if(!editable_)
232 {
233 return;
234 }
235
236 const std::string& text = desktop::clipboard::copy_from_clipboard();
237 if(text.empty()) {
238 return;
239 }
240
242
244
246 queue_redraw();
247 fire(event::NOTIFY_MODIFIED, *this, nullptr);
248}
249
250void text_box_base::set_selection_start(const std::size_t selection_start)
251{
252 if(selection_start != selection_start_) {
253 selection_start_ = selection_start;
254 queue_redraw();
255 }
256}
257
258void text_box_base::set_selection_length(const int selection_length)
259{
260 if(selection_length != selection_length_) {
261 selection_length_ = selection_length;
262 queue_redraw();
263 }
264}
265
266void text_box_base::set_selection(std::size_t start, int length)
267{
268 const std::size_t text_size = text_.get_length();
269
270 if(start >= text_size) {
271 start = text_size;
272 }
273
274 if(length == 0) {
275 set_cursor(start, false);
276 return;
277 }
278
279 // The text pos/size type differs in both signedness and size with the
280 // selection length. Such is life.
281 const int sel_start = std::min<std::size_t>(start, std::numeric_limits<int>::max());
282 const int sel_max_length = std::min<std::size_t>(text_size - start, std::numeric_limits<int>::max());
283
284 const bool backwards = length < 0;
285
286 if(backwards && -length > sel_start) {
287 length = -sel_start;
288 } else if(!backwards && length > sel_max_length) {
289 length = sel_max_length;
290 }
291
292 set_selection_start(start);
293 set_selection_length(length);
294
296}
297
299{
300 if(state != state_) {
301 state_ = state;
302 queue_redraw();
303 }
304}
305
307{
308 if(cursor_blink_rate_ == 0ms) {
309 return;
310 }
311
312 if(cursor_timer_) {
314 }
315
316 cursor_timer_ = enable
318 : 0;
319}
320
322{
323 unsigned was_alpha = cursor_alpha_;
324 switch(state_) {
325 case DISABLED:
326 cursor_alpha_ = 0;
327 return;
328 case ENABLED:
329 cursor_alpha_ = 255;
330 return;
331 default:
332 // FIXME: very hacky way to check if the widget's owner is the top window
333 // back() on an empty vector is UB and was causing a crash when run on Wayland (see #7104 on github)
334 const auto& dispatchers = event::get_all_dispatchers();
335 if(!dispatchers.empty() && static_cast<event::dispatcher*>(get_window()) != dispatchers.back()) {
336 cursor_alpha_ = 0;
337 } else {
338 cursor_alpha_ = (~cursor_alpha_) & 0xFF;
339 }
340 }
341
342 if(was_alpha == cursor_alpha_) {
343 return;
344 }
345
346 for(auto& tmp : get_canvases()) {
347 tmp.set_variable("cursor_alpha", wfl::variant(cursor_alpha_));
348 }
349
350 queue_redraw();
351}
352
354{
355 if(cursor_blink_rate_ == 0ms) {
356 return;
357 }
358
359 cursor_alpha_ = 255;
360
361 for(auto& tmp : get_canvases()) {
362 tmp.set_variable("cursor_alpha", wfl::variant(cursor_alpha_));
363 }
364
365 // Restart the blink timer.
367}
368
369void text_box_base::handle_key_left_arrow(SDL_Keymod modifier, bool& handled)
370{
371 /** @todo implement the ctrl key. */
373
374 handled = true;
375 const int offset = selection_start_ - 1 + selection_length_;
376 if(offset >= 0) {
377 set_cursor(offset, (modifier & SDL_KMOD_SHIFT) != 0);
378 }
379}
380
381void text_box_base::handle_key_right_arrow(SDL_Keymod modifier, bool& handled)
382{
383 /** @todo implement the ctrl key. */
385
386 handled = true;
387 const std::size_t offset = selection_start_ + 1 + selection_length_;
388 if(offset <= (get_use_markup() ? utf8::size(plain_text()) : text_.get_length())) {
389 set_cursor(offset, (modifier & SDL_KMOD_SHIFT) != 0);
390 }
391}
392
393void text_box_base::handle_key_home(SDL_Keymod modifier, bool& handled)
394{
396
397 handled = true;
398 if(modifier & SDL_KMOD_CTRL) {
399 goto_start_of_data((modifier & SDL_KMOD_SHIFT) != 0);
400 } else {
401 goto_start_of_line((modifier & SDL_KMOD_SHIFT) != 0);
402 }
403}
404
405void text_box_base::handle_key_end(SDL_Keymod modifier, bool& handled)
406{
408
409 handled = true;
410 if(modifier & SDL_KMOD_CTRL) {
411 goto_end_of_data((modifier & SDL_KMOD_SHIFT) != 0);
412 } else {
413 goto_end_of_line((modifier & SDL_KMOD_SHIFT) != 0);
414 }
415}
416
417void text_box_base::handle_key_backspace(SDL_Keymod /*modifier*/, bool& handled)
418{
420
421 handled = true;
422 if(selection_length_ != 0) {
424 } else if(selection_start_) {
425 delete_char(true);
426 if(is_composing()) {
427 if(get_composition_length() == 0) {
428 ime_composing_ = false;
429 }
430 }
431 }
432 fire(event::NOTIFY_MODIFIED, *this, nullptr);
433}
434
435void text_box_base::handle_key_delete(SDL_Keymod /*modifier*/, bool& handled)
436{
438
439 handled = true;
440 if(selection_length_ != 0) {
442 } else if(selection_start_ < text_.get_length()) {
443 delete_char(false);
444 if(is_composing()) {
445 if(get_composition_length() == 0) {
446 ime_composing_ = false;
447 }
448 }
449 }
450 fire(event::NOTIFY_MODIFIED, *this, nullptr);
451}
452
453void text_box_base::handle_commit(bool& handled, const std::string& unicode)
454{
456
457 if(unicode.size() > 1 || unicode[0] != 0) {
458 handled = true;
459 if(is_composing()) {
461 ime_composing_ = false;
462 }
463 insert_char(unicode);
464 fire(event::NOTIFY_MODIFIED, *this, nullptr);
465 }
466}
467
468/**
469 * SDL_EVENT_TEXT_EDITING handler. See example at https://wiki.libsdl.org/Tutorials/TextInput
470 */
471void text_box_base::handle_editing(bool& handled, const std::string& unicode, int32_t start, int32_t len)
472{
473 if(unicode.size() > 1 || unicode[0] != 0) {
474 handled = true;
475 std::size_t new_len = utf8::size(unicode);
476 if(!is_composing()) {
477 ime_composing_ = true;
482 if(new_len > 0) {
484 rect.w = get_cursor_position(ime_start_point_ + new_len).x - rect.x;
485 } else {
486 rect.x += get_cursor_position(ime_start_point_ + new_len).x;
488 }
489 SDL_SetTextInputArea(video::get_window(), &rect, 0);
490 }
491
492#ifdef __unix__
493 // In SDL_TextEditingEvent, size of editing_text is limited
494 // If length of composition text is more than the limit,
495 // Linux (ibus) implementation of SDL separates it into multiple
496 // SDL_TextEditingEvent.
497 // start is start position of the separated event in entire composition text
498 if(start == 0) {
500 }
502#else
503 std::string new_text(text_cached_);
504 utf8::insert(new_text, ime_start_point_, unicode);
505 text_.set_text(new_text, get_use_markup());
506
507#endif
508 int maximum_length = text_.get_length();
509
510 // Update status
511 set_cursor(std::min(maximum_length, ime_start_point_ + start), false);
512 if(len > 0) {
513 set_cursor(std::min(maximum_length, ime_start_point_ + start + len), true);
514 }
516 queue_redraw();
517 }
518}
519
521 bool& handled)
522{
523 DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
524
526
527 handled = true;
528}
529
531 bool& handled,
532 const SDL_Keycode key,
533 SDL_Keymod modifier)
534{
535
536 DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
537
538/*
539 * For copy, cut and paste we use a different key on the MAC. Even for 'select
540 * all', contradicting the comment in widgets/textbox.cpp:495.
541 *
542 * The reason for that is, by coupling 'select all' to the behavior for copy,
543 * cut and paste, the text box behavior as a whole gets consistent with default
544 * macOS hotkey idioms.
545 */
546#ifdef __APPLE__
547 // Idiomatic modifier key in macOS computers.
548 const SDL_Keycode modifier_key = SDL_KMOD_GUI;
549#else
550 // Idiomatic modifier key in Microsoft desktop environments. Common in
551 // GNU/Linux as well, to some extent.
552 const SDL_Keycode modifier_key = SDL_KMOD_CTRL;
553#endif
554
555 switch(key) {
556
557 case SDLK_LEFT:
558 handle_key_left_arrow(modifier, handled);
559 break;
560
561 case SDLK_RIGHT:
562 handle_key_right_arrow(modifier, handled);
563 break;
564
565 case SDLK_UP:
566 handle_key_up_arrow(modifier, handled);
567 break;
568
569 case SDLK_DOWN:
570 handle_key_down_arrow(modifier, handled);
571 break;
572
573 case SDLK_PAGEUP:
574 handle_key_page_up(modifier, handled);
575 break;
576
577 case SDLK_PAGEDOWN:
578 handle_key_page_down(modifier, handled);
579 break;
580
581 case SDLK_A:
582 if(!(modifier & modifier_key)) {
583 return;
584 }
585
586 select_all();
587 break;
588
589 case SDLK_HOME:
590 handle_key_home(modifier, handled);
591 break;
592
593 case SDLK_END:
594 handle_key_end(modifier, handled);
595 break;
596
597 case SDLK_BACKSPACE:
598 if (!is_editable())
599 {
600 return;
601 }
602
603 handle_key_backspace(modifier, handled);
604 break;
605
606 case SDLK_U:
607 if( !(modifier & SDL_KMOD_CTRL) || !is_editable() ) {
608 return;
609 }
610
611 handle_key_clear_line(modifier, handled);
612 break;
613
614 case SDLK_DELETE:
615 if (!is_editable())
616 {
617 return;
618 }
619
620 handle_key_delete(modifier, handled);
621 break;
622
623 case SDLK_C:
624 if(!(modifier & modifier_key)) {
625 return;
626 }
627
628 // atm we don't care whether there is something to copy or paste
629 // if nothing is there we still don't want to be chained.
631 handled = true;
632 break;
633
634 case SDLK_X:
635 if( !(modifier & modifier_key) ) {
636 return;
637 }
638
640
641 if ( is_editable() ) {
643 }
644 handled = true;
645 break;
646
647 case SDLK_V:
648 if( !(modifier & modifier_key) || !is_editable() ) {
649 return;
650 }
651
653 handled = true;
654 break;
655
656 case SDLK_RETURN:
657 case SDLK_KP_ENTER:
658
659// TODO: check if removing the following check causes any side effects
660// To be removed if there aren't any text rendering problems.
661// if(!is_composing()) {
662// return;
663// }
664
665 handle_key_enter(modifier, handled);
666 break;
667
668 case SDLK_AC_BACK:
669 case SDLK_ESCAPE:
670 if(!is_composing() || (modifier & (SDL_KMOD_CTRL | SDL_KMOD_ALT | SDL_KMOD_GUI | SDL_KMOD_SHIFT))) {
671 return;
672 }
674 handled = true;
675 break;
676
677 case SDLK_TAB:
678 handle_key_tab(modifier, handled);
679 break;
680
681 default:
682 return;
683 }
684}
685
687{
688 DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
689#if defined(__ANDROID__) || defined(__IPHONEOS__)
690 SDL_StartTextInput(video::get_window());
691#endif
693}
694
696{
697 DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
698#if defined(__ANDROID__) || defined(__IPHONEOS__)
699 SDL_StopTextInput(video::get_window());
700#endif
702}
703
705 bool& handled)
706{
707 DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
708 if(state_ != FOCUSED) {
710 }
711
713
714 handled = true;
715}
716
718 bool& handled)
719{
720 DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
721
722 if(state_ != FOCUSED) {
724 }
725
726 update_mouse_cursor(false);
727
728 handled = true;
729}
730
732{
733 // Someone else may set the mouse cursor for us to something unusual (e.g.
734 // the WAIT cursor) so we ought to mess with that only if it's set to
735 // NORMAL or IBEAM.
736
737 if(enable && cursor::get() == cursor::NORMAL) {
739 } else if(!enable && cursor::get() == cursor::IBEAM) {
741 }
742}
743
744
745} // namespace gui2
Helper class to encapsulate the management of a PangoAttrList.
const std::string & text() const
Definition text.hpp:322
std::size_t get_length() const
Gets the length of the text in bytes.
Definition text.hpp:304
pango_text & set_maximum_length(const std::size_t maximum_length)
Definition text.cpp:482
unsigned insert_text(const unsigned offset, const std::string &text, const bool use_markup=false)
Inserts UTF-8 text.
Definition text.cpp:169
void apply_attributes(const font::attribute_list &attrs)
Definition text.cpp:324
bool set_text(const std::string &text, const bool markedup)
Sets the text to render.
Definition text.cpp:333
Base class for event handling.
bool fire(const ui_event event, widget &target)
Fires an event which has no extra parameters.
virtual void update_canvas()
Updates the canvas(ses).
std::vector< canvas > & get_canvases()
resolution_definition_ptr get_config()
bool get_use_markup() const
std::size_t get_composition_length() const
Get length of composition text by IME.
virtual void handle_key_backspace(SDL_Keymod modifier, bool &handled)
Backspace key pressed.
virtual void handle_commit(bool &handled, const std::string &unicode)
virtual bool get_active() const override
See styled_widget::get_active.
virtual unsigned get_state() const override
See styled_widget::get_state.
void update_mouse_cursor(bool enable)
virtual void goto_start_of_line(const bool select=false)=0
Moves the cursor to the beginning of the line.
virtual void handle_key_delete(SDL_Keymod modifier, bool &handled)
Delete key pressed.
virtual void insert_char(const std::string &unicode)
Inserts a character at the cursor.
virtual void handle_editing(bool &handled, const std::string &unicode, int32_t start, int32_t length)
SDL_EVENT_TEXT_EDITING handler.
void set_state(const state_t state)
std::chrono::milliseconds cursor_blink_rate_
const std::string & text() const
virtual void copy_selection()
Copies the current selection.
virtual void handle_key_left_arrow(SDL_Keymod modifier, bool &handled)
Left arrow key pressed.
virtual void toggle_cursor_timer(bool enable)
text_box_base(const implementation::builder_styled_widget &builder, const std::string &control_type)
void set_highlight_area(const unsigned start_offset, const unsigned end_offset, const color_t &color)
Wrapper function, sets the area between column start and end offset to be highlighted in a specific c...
state_t state_
Current state of the widget.
virtual void goto_end_of_line(const bool select=false)=0
Moves the cursor to the end of the line.
void signal_handler_mouse_leave(const event::ui_event event, bool &handled)
void set_selection(std::size_t start, int length)
Sets or clears the text selection.
std::size_t selection_start_
Start of the selected text.
std::string plain_text()
virtual void handle_key_enter(SDL_Keymod, bool &)
Enter key.
int selection_length_
Length of the selected text.
unsigned short cursor_alpha_
virtual void handle_key_up_arrow(SDL_Keymod modifier, bool &handled)=0
Every key can have several behaviors.
point get_cursor_position(const unsigned column, const unsigned line=0) const
void signal_handler_mouse_enter(const event::ui_event event, bool &handled)
virtual void handle_key_tab(SDL_Keymod, bool &)
Tab key.
std::string text_cached_
Cached version of the text without any pending IME modifications.
void set_font_family(font::family_class fclass)
virtual void set_value(const std::string &text)
The set_value is virtual for the password_box class.
virtual void paste_selection()
Pastes the current selection.
state_t
Note the order of the states must be the same as defined in settings.hpp.
font::pango_text text_
The text entered in the widget.
void signal_handler_lose_keyboard_focus(const event::ui_event event)
void signal_handler_sdl_key_down(const event::ui_event event, bool &handled, const SDL_Keycode key, SDL_Keymod modifier)
virtual void handle_key_right_arrow(SDL_Keymod modifier, bool &handled)
Right arrow key pressed.
virtual void handle_key_clear_line(SDL_Keymod modifier, bool &handled)=0
Clears the current line.
void set_selection_start(const std::size_t selection_start)
virtual void set_cursor(const std::size_t offset, const bool select)
Moves the cursor at the wanted position.
virtual void handle_key_page_up(SDL_Keymod, bool &)
Page up key.
virtual void handle_key_home(SDL_Keymod modifier, bool &handled)
Home key pressed.
bool is_editable() const
Check whether text can be edited or not.
virtual void handle_key_down_arrow(SDL_Keymod modifier, bool &handled)=0
Down arrow key pressed.
void signal_handler_receive_keyboard_focus(const event::ui_event event)
virtual void goto_end_of_data(const bool select=false)
Moves the cursor to the end of all text.
void signal_handler_middle_button_click(const event::ui_event event, bool &handled)
virtual void handle_key_end(SDL_Keymod modifier, bool &handled)
End key pressed.
virtual void handle_key_page_down(SDL_Keymod, bool &)
Page down key.
virtual void set_active(const bool active) override
See styled_widget::set_active.
void set_selection_length(const int selection_length)
bool is_composing() const
bool editable_
If this text_box_base is editable.
virtual void goto_start_of_data(const bool select=false)
Moves the cursor to the beginning of the data.
virtual void cursor_timer_callback()
Implements blinking cursor functionality.
virtual void reset_cursor_state()
void set_maximum_length(const std::size_t maximum_length)
virtual void delete_selection()=0
Deletes the current selection.
virtual void delete_char(const bool before_cursor)=0
Deletes the character.
void select_all()
Selects all text.
void queue_redraw()
Indicates that this widget should be redrawn.
Definition widget.cpp:464
window * get_window()
Get the parent window.
Definition widget.cpp:117
rect get_rectangle() const
Gets the bounding rectangle of the widget on the screen.
Definition widget.cpp:321
#define LOG_HEADER
Define the common log macros for the gui toolkit.
#define DBG_GUI_E
Definition log.hpp:35
#define LOG_SCOPE_HEADER
Definition button.cpp:34
This file contains the window object, this object is a top level container which has the event manage...
CURSOR_TYPE get()
Definition cursor.cpp:185
@ NORMAL
Definition cursor.hpp:28
@ IBEAM
Definition cursor.hpp:28
void set(CURSOR_TYPE type)
Use the default parameter to reset cursors.
Definition cursor.cpp:151
void copy_to_clipboard(const std::string &text)
Copies text to the clipboard.
Definition clipboard.cpp:24
std::string copy_from_clipboard()
Copies text from the clipboard.
Definition clipboard.cpp:29
ui_event
The event sent to the dispatcher.
Definition handler.hpp:115
std::vector< dispatcher * > & get_all_dispatchers()
Gets all event dispatchers in the Z order.
Definition handler.cpp:885
Generic file dialog.
std::size_t add_timer(const std::chrono::milliseconds &interval, const std::function< void(std::size_t id)> &callback, const bool repeat)
Adds a new timer.
Definition timer.cpp:123
bool remove_timer(const std::size_t id)
Removes a timer.
Definition timer.cpp:164
std::string & insert(std::string &str, const std::size_t pos, const std::string &insert)
Insert a UTF-8 string at the specified position.
Definition unicode.cpp:100
std::size_t size(std::string_view str)
Length in characters of a UTF-8 string.
Definition unicode.cpp:81
std::size_t index(std::string_view str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition unicode.cpp:70
SDL_Window * get_window()
Definition video.cpp:712
The basic class for representing 8-bit RGB or RGBA colour values.
Definition color.hpp:51
An abstract description of a rectangle with integer coordinates.
Definition rect.hpp:49
Contains the gui2 timer routines.