The Battle for Wesnoth  1.19.7+dev
text_box_base.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 
20 #include "cursor.hpp"
21 #include "desktop/clipboard.hpp"
23 #include "gui/core/log.hpp"
24 #include "gui/core/timer.hpp"
26 
27 #include <functional>
28 #include <limits>
29 
30 #define LOG_SCOPE_HEADER get_control_type() + " [" + id() + "] " + __func__
31 #define LOG_HEADER LOG_SCOPE_HEADER + ':'
32 
33 using namespace std::chrono_literals;
34 
35 namespace gui2
36 {
37 
38 text_box_base::text_box_base(const implementation::builder_styled_widget& builder, const std::string& control_type)
39  : styled_widget(builder, control_type)
40  , state_(ENABLED)
41  , text_()
42  , selection_start_(0)
43  , selection_length_(0)
44  , editable_(true)
45  , ime_composing_(false)
46  , ime_start_point_(0)
47  , cursor_timer_(0)
48  , cursor_alpha_(0)
49  , cursor_blink_rate_(750ms)
50  , text_changed_callback_()
51 {
52  auto cfg = get_control(control_type, builder.definition);
53  set_font_family(cfg->text_font_family);
54 
55 #ifdef __unix__
56  // pastes on UNIX systems.
57  connect_signal<event::MIDDLE_BUTTON_CLICK>(std::bind(
58  &text_box_base::signal_handler_middle_button_click, this, std::placeholders::_2, std::placeholders::_3));
59 
60 #endif
61 
62  connect_signal<event::SDL_KEY_DOWN>(std::bind(
63  &text_box_base::signal_handler_sdl_key_down, this, std::placeholders::_2, std::placeholders::_3, std::placeholders::_5, std::placeholders::_6));
64  connect_signal<event::SDL_TEXT_INPUT>(std::bind(&text_box_base::handle_commit, this, std::placeholders::_3, std::placeholders::_5));
65  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));
66 
67  connect_signal<event::RECEIVE_KEYBOARD_FOCUS>(std::bind(
68  &text_box_base::signal_handler_receive_keyboard_focus, this, std::placeholders::_2));
69  connect_signal<event::LOSE_KEYBOARD_FOCUS>(
70  std::bind(&text_box_base::signal_handler_lose_keyboard_focus, this, std::placeholders::_2));
71 
72  connect_signal<event::MOUSE_ENTER>(
73  std::bind(&text_box_base::signal_handler_mouse_enter, this, std::placeholders::_2, std::placeholders::_3));
74  connect_signal<event::MOUSE_LEAVE>(
75  std::bind(&text_box_base::signal_handler_mouse_leave, this, std::placeholders::_2, std::placeholders::_3));
76 
77  toggle_cursor_timer(true);
78 }
79 
81 {
82  toggle_cursor_timer(false);
83  update_mouse_cursor(false);
84 }
85 
86 void text_box_base::set_active(const bool active)
87 {
88  if(get_active() != active) {
89  set_state(active ? ENABLED : DISABLED);
90  }
91 }
92 
94 {
95  return state_ != DISABLED;
96 }
97 
98 unsigned text_box_base::get_state() const
99 {
100  return state_;
101 }
102 
103 void text_box_base::set_maximum_length(const std::size_t maximum_length)
104 {
105  if(maximum_length == 0) {
106  return;
107  }
108 
109  const bool need_update = text_.get_length() > maximum_length;
110 
111  text_.set_maximum_length(maximum_length);
112 
113  if(need_update) {
114  if(selection_start_ > maximum_length) {
115  selection_start_ = maximum_length;
116  selection_length_ = 0;
117  } else if(selection_start_ + selection_length_ > maximum_length) {
118  selection_length_ = maximum_length - selection_start_;
119  }
120  update_canvas();
121  queue_redraw();
122  }
123 }
124 
125 void text_box_base::set_value(const std::string& text)
126 {
127  if(text != text_.text()) {
129 
130  // default to put the cursor at the end of the buffer.
132  selection_length_ = 0;
133  update_canvas();
134  queue_redraw();
135  }
136 }
137 
138 void text_box_base::set_cursor(const std::size_t offset, const bool select)
139 {
141 
142  if(select) {
143  selection_length_ = (selection_start_ == offset) ? 0 : -static_cast<int>(selection_start_ - offset);
144  } else {
145  selection_start_ = (offset <= text_.get_length()) ? offset : 0;
146  selection_length_ = 0;
147  }
148 
149  update_canvas();
150  queue_redraw();
151 }
152 
153 void text_box_base::insert_char(const std::string& unicode)
154 {
155  if(!editable_)
156  {
157  return;
158  }
159 
161 
163  // Update status
164  size_t plain_text_len = utf8::size(plain_text());
165  size_t cursor_pos = selection_start_ + utf8::size(unicode);
166  if (get_use_markup() && (selection_start_ + utf8::size(unicode) > plain_text_len + 1)) {
167  cursor_pos = plain_text_len;
168  }
169  set_cursor(cursor_pos, false);
170  update_canvas();
171  queue_redraw();
172  }
173 }
174 
176 {
177  if(!is_composing()) {
178  return 0;
179  }
180 
181  size_t text_length = utf8::size(text_.text());
182  size_t text_cached_length = utf8::size(text_cached_);
183  if(text_length < text_cached_length) {
184  return 0;
185  }
186 
188 }
189 
191 {
192  ime_composing_ = false;
193  // We need to inform the IME that text input is no longer in progress.
194  SDL_StopTextInput();
195  SDL_StartTextInput();
196 }
197 
199 {
200  if(selection_length_ == 0) {
201  return;
202  }
203 
204  unsigned end, start = selection_start_;
205  const std::string txt = get_use_markup() ? plain_text() : text_.text();
206 
207  if(selection_length_ > 0) {
208  end = utf8::index(txt, start + selection_length_);
209  start = utf8::index(txt, start);
210  } else {
211  // inverse selection: selection_start_ is in fact the end
212  end = utf8::index(txt, start);
214  }
216 }
217 
219 {
220  if(!editable_)
221  {
222  return;
223  }
224 
225  const std::string& text = desktop::clipboard::copy_from_clipboard();
226  if(text.empty()) {
227  return;
228  }
229 
231 
233 
234  update_canvas();
235  queue_redraw();
236  fire(event::NOTIFY_MODIFIED, *this, nullptr);
237 }
238 
239 void text_box_base::set_selection_start(const std::size_t selection_start)
240 {
241  if(selection_start != selection_start_) {
242  selection_start_ = selection_start;
243  queue_redraw();
244  }
245 }
246 
247 void text_box_base::set_selection_length(const int selection_length)
248 {
249  if(selection_length != selection_length_) {
250  selection_length_ = selection_length;
251  queue_redraw();
252  }
253 }
254 
255 void text_box_base::set_selection(std::size_t start, int length)
256 {
257  const std::size_t text_size = text_.get_length();
258 
259  if(start >= text_size) {
260  start = text_size;
261  }
262 
263  if(length == 0) {
264  set_cursor(start, false);
265  return;
266  }
267 
268  // The text pos/size type differs in both signedness and size with the
269  // selection length. Such is life.
270  const int sel_start = std::min<std::size_t>(start, std::numeric_limits<int>::max());
271  const int sel_max_length = std::min<std::size_t>(text_size - start, std::numeric_limits<int>::max());
272 
273  const bool backwards = length < 0;
274 
275  if(backwards && -length > sel_start) {
276  length = -sel_start;
277  } else if(!backwards && length > sel_max_length) {
278  length = sel_max_length;
279  }
280 
282  set_selection_length(length);
283 
284  update_canvas();
285 }
286 
288 {
289  if(state != state_) {
290  state_ = state;
291  queue_redraw();
292  }
293 }
294 
296 {
297  if(cursor_blink_rate_ == 0ms) {
298  return;
299  }
300 
301  if(cursor_timer_) {
303  }
304 
305  cursor_timer_ = enable
307  : 0;
308 }
309 
311 {
312  unsigned was_alpha = cursor_alpha_;
313  switch(state_) {
314  case DISABLED:
315  cursor_alpha_ = 0;
316  return;
317  case ENABLED:
318  cursor_alpha_ = 255;
319  return;
320  default:
321  // back() on an empty vector is UB and was causing a crash when run on Wayland (see #7104 on github)
322  if(!open_window_stack.empty() && get_window() != open_window_stack.back()) {
323  cursor_alpha_ = 0;
324  } else {
325  cursor_alpha_ = (~cursor_alpha_) & 0xFF;
326  }
327  }
328 
329  if(was_alpha == cursor_alpha_) {
330  return;
331  }
332 
333  for(auto& tmp : get_canvases()) {
334  tmp.set_variable("cursor_alpha", wfl::variant(cursor_alpha_));
335  }
336 
337  queue_redraw();
338 }
339 
341 {
342  if(cursor_blink_rate_ == 0ms) {
343  return;
344  }
345 
346  cursor_alpha_ = 255;
347 
348  for(auto& tmp : get_canvases()) {
349  tmp.set_variable("cursor_alpha", wfl::variant(cursor_alpha_));
350  }
351 
352  // Restart the blink timer.
353  toggle_cursor_timer(true);
354 }
355 
356 void text_box_base::handle_key_left_arrow(SDL_Keymod modifier, bool& handled)
357 {
358  /** @todo implement the ctrl key. */
360 
361  handled = true;
362  const int offset = selection_start_ - 1 + selection_length_;
363  if(offset >= 0) {
364  set_cursor(offset, (modifier & KMOD_SHIFT) != 0);
365  }
366 }
367 
368 void text_box_base::handle_key_right_arrow(SDL_Keymod modifier, bool& handled)
369 {
370  /** @todo implement the ctrl key. */
372 
373  handled = true;
374  const std::size_t offset = selection_start_ + 1 + selection_length_;
375  if(offset <= (get_use_markup() ? utf8::size(plain_text()) : text_.get_length())) {
376  set_cursor(offset, (modifier & KMOD_SHIFT) != 0);
377  }
378 }
379 
380 void text_box_base::handle_key_home(SDL_Keymod modifier, bool& handled)
381 {
383 
384  handled = true;
385  if(modifier & KMOD_CTRL) {
386  goto_start_of_data((modifier & KMOD_SHIFT) != 0);
387  } else {
388  goto_start_of_line((modifier & KMOD_SHIFT) != 0);
389  }
390 }
391 
392 void text_box_base::handle_key_end(SDL_Keymod modifier, bool& handled)
393 {
395 
396  handled = true;
397  if(modifier & KMOD_CTRL) {
398  goto_end_of_data((modifier & KMOD_SHIFT) != 0);
399  } else {
400  goto_end_of_line((modifier & KMOD_SHIFT) != 0);
401  }
402 }
403 
404 void text_box_base::handle_key_backspace(SDL_Keymod /*modifier*/, bool& handled)
405 {
407 
408  handled = true;
409  if(selection_length_ != 0) {
411  } else if(selection_start_) {
412  delete_char(true);
413  if(is_composing()) {
414  if(get_composition_length() == 0) {
415  ime_composing_ = false;
416  }
417  }
418  }
419  fire(event::NOTIFY_MODIFIED, *this, nullptr);
420 }
421 
422 void text_box_base::handle_key_delete(SDL_Keymod /*modifier*/, bool& handled)
423 {
425 
426  handled = true;
427  if(selection_length_ != 0) {
429  } else if(selection_start_ < text_.get_length()) {
430  delete_char(false);
431  if(is_composing()) {
432  if(get_composition_length() == 0) {
433  ime_composing_ = false;
434  }
435  }
436  }
437  fire(event::NOTIFY_MODIFIED, *this, nullptr);
438 }
439 
440 void text_box_base::handle_commit(bool& handled, const std::string& unicode)
441 {
443 
444  if(unicode.size() > 1 || unicode[0] != 0) {
445  handled = true;
446  if(is_composing()) {
448  ime_composing_ = false;
449  }
450  insert_char(unicode);
451  fire(event::NOTIFY_MODIFIED, *this, nullptr);
452 
454  text_changed_callback_(this, this->text());
455  }
456  }
457 }
458 
459 /**
460  * SDL_TEXTEDITING handler. See example at https://wiki.libsdl.org/Tutorials/TextInput
461  */
462 void text_box_base::handle_editing(bool& handled, const std::string& unicode, int32_t start, int32_t len)
463 {
464  if(unicode.size() > 1 || unicode[0] != 0) {
465  handled = true;
466  std::size_t new_len = utf8::size(unicode);
467  if(!is_composing()) {
468  ime_composing_ = true;
471  text_cached_ = text_.text();
472  SDL_Rect rect = get_rectangle();
473  if(new_len > 0) {
475  rect.w = get_cursor_position(ime_start_point_ + new_len).x - rect.x;
476  } else {
477  rect.x += get_cursor_position(ime_start_point_ + new_len).x;
479  }
480  SDL_SetTextInputRect(&rect);
481  }
482 
483 #ifdef __unix__
484  // In SDL_TextEditingEvent, size of editing_text is limited
485  // If length of composition text is more than the limit,
486  // Linux (ibus) implementation of SDL separates it into multiple
487  // SDL_TextEditingEvent.
488  // start is start position of the separated event in entire composition text
489  if(start == 0) {
491  }
493 #else
494  std::string new_text(text_cached_);
495  utf8::insert(new_text, ime_start_point_, unicode);
496  text_.set_text(new_text, get_use_markup());
497 
498 #endif
499  int maximum_length = text_.get_length();
500 
501  // Update status
502  set_cursor(std::min(maximum_length, ime_start_point_ + start), false);
503  if(len > 0) {
504  set_cursor(std::min(maximum_length, ime_start_point_ + start + len), true);
505  }
506  update_canvas();
507  queue_redraw();
508  }
509 }
510 
512  bool& handled)
513 {
514  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
515 
516  paste_selection();
517 
518  handled = true;
519 }
520 
522  bool& handled,
523  const SDL_Keycode key,
524  SDL_Keymod modifier)
525 {
526 
527  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
528 
529 /*
530  * For copy, cut and paste we use a different key on the MAC. Even for 'select
531  * all', contradicting the comment in widgets/textbox.cpp:495.
532  *
533  * The reason for that is, by coupling 'select all' to the behavior for copy,
534  * cut and paste, the text box behavior as a whole gets consistent with default
535  * macOS hotkey idioms.
536  */
537 #ifdef __APPLE__
538  // Idiomatic modifier key in macOS computers.
539  const SDL_Keycode modifier_key = KMOD_GUI;
540 #else
541  // Idiomatic modifier key in Microsoft desktop environments. Common in
542  // GNU/Linux as well, to some extent.
543  const SDL_Keycode modifier_key = KMOD_CTRL;
544 #endif
545 
546  switch(key) {
547 
548  case SDLK_LEFT:
549  handle_key_left_arrow(modifier, handled);
550  break;
551 
552  case SDLK_RIGHT:
553  handle_key_right_arrow(modifier, handled);
554  break;
555 
556  case SDLK_UP:
557  handle_key_up_arrow(modifier, handled);
558  break;
559 
560  case SDLK_DOWN:
561  handle_key_down_arrow(modifier, handled);
562  break;
563 
564  case SDLK_PAGEUP:
565  handle_key_page_up(modifier, handled);
566  break;
567 
568  case SDLK_PAGEDOWN:
569  handle_key_page_down(modifier, handled);
570  break;
571 
572  case SDLK_a:
573  if(!(modifier & modifier_key)) {
574  return;
575  }
576 
577  select_all();
578  break;
579 
580  case SDLK_HOME:
581  handle_key_home(modifier, handled);
582  break;
583 
584  case SDLK_END:
585  handle_key_end(modifier, handled);
586  break;
587 
588  case SDLK_BACKSPACE:
589  if (!is_editable())
590  {
591  return;
592  }
593 
594  handle_key_backspace(modifier, handled);
595  break;
596 
597  case SDLK_u:
598  if( !(modifier & KMOD_CTRL) || !is_editable() ) {
599  return;
600  }
601 
602  handle_key_clear_line(modifier, handled);
603  break;
604 
605  case SDLK_DELETE:
606  if (!is_editable())
607  {
608  return;
609  }
610 
611  handle_key_delete(modifier, handled);
612  break;
613 
614  case SDLK_c:
615  if(!(modifier & modifier_key)) {
616  return;
617  }
618 
619  // atm we don't care whether there is something to copy or paste
620  // if nothing is there we still don't want to be chained.
621  copy_selection();
622  handled = true;
623  break;
624 
625  case SDLK_x:
626  if( !(modifier & modifier_key) ) {
627  return;
628  }
629 
630  copy_selection();
631 
632  if ( is_editable() ) {
634  }
635  handled = true;
636  break;
637 
638  case SDLK_v:
639  if( !(modifier & modifier_key) || !is_editable() ) {
640  return;
641  }
642 
643  paste_selection();
644  handled = true;
645  break;
646 
647  case SDLK_RETURN:
648  case SDLK_KP_ENTER:
649 
650 // TODO: check if removing the following check causes any side effects
651 // To be removed if there aren't any text rendering problems.
652 // if(!is_composing()) {
653 // return;
654 // }
655 
656  handle_key_enter(modifier, handled);
657  break;
658 
659  case SDLK_ESCAPE:
660  if(!is_composing() || (modifier & (KMOD_CTRL | KMOD_ALT | KMOD_GUI | KMOD_SHIFT))) {
661  return;
662  }
664  handled = true;
665  break;
666 
667  case SDLK_TAB:
668  handle_key_tab(modifier, handled);
669  break;
670 
671  default:
672  // Don't call the text changed callback if nothing happened.
673  return;
674  }
675 
677  text_changed_callback_(this, this->text());
678  }
679 }
680 
682 {
683  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
684 
686 }
687 
689 {
690  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
691 
693 }
694 
696  bool& handled)
697 {
698  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
699 
700  if(state_ != FOCUSED) {
702  }
703 
704  update_mouse_cursor(true);
705 
706  handled = true;
707 }
708 
710  bool& handled)
711 {
712  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
713 
714  if(state_ != FOCUSED) {
716  }
717 
718  update_mouse_cursor(false);
719 
720  handled = true;
721 }
722 
724 {
725  // Someone else may set the mouse cursor for us to something unusual (e.g.
726  // the WAIT cursor) so we ought to mess with that only if it's set to
727  // NORMAL or IBEAM.
728 
729  if(enable && cursor::get() == cursor::NORMAL) {
731  } else if(!enable && cursor::get() == cursor::IBEAM) {
733  }
734 }
735 
736 
737 } // namespace gui2
std::size_t get_length() const
Gets the length of the text in bytes.
Definition: text.hpp:273
pango_text & set_maximum_length(const std::size_t maximum_length)
Definition: text.cpp:645
unsigned insert_text(const unsigned offset, const std::string &text, const bool use_markup=false)
Inserts UTF-8 text.
Definition: text.cpp:165
bool set_text(const std::string &text, const bool markedup)
Sets the text to render.
Definition: text.cpp:484
const std::string & text() const
Definition: text.hpp:291
bool fire(const ui_event event, widget &target)
Fires an event which has no extra parameters.
Definition: dispatcher.cpp:74
std::vector< canvas > & get_canvases()
virtual void update_canvas()
Updates the canvas(ses).
bool get_use_markup() const
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.
std::function< void(text_box_base *textbox, const std::string text)> text_changed_callback_
Text changed callback.
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_TEXTEDITING handler.
void set_state(const state_t state)
std::chrono::milliseconds cursor_blink_rate_
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)
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.
size_t get_composition_length() const
Get length of composition text by IME.
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_
std::size_t cursor_timer_
virtual void handle_key_up_arrow(SDL_Keymod modifier, bool &handled)=0
Every key can have several behaviors.
const std::string & text() const
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 the common log macros for the gui toolkit.
#define DBG_GUI_E
Definition: log.hpp:35
CURSOR_TYPE get()
Definition: cursor.cpp:216
@ 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:176
void copy_to_clipboard(const std::string &text)
Copies text to the clipboard.
Definition: clipboard.cpp:27
std::string copy_from_clipboard()
Copies text from the clipboard.
Definition: clipboard.cpp:32
EXIT_STATUS start(bool clear_id, const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
ui_event
The event sent to the dispatcher.
Definition: handler.hpp:115
@ NOTIFY_MODIFIED
Definition: handler.hpp:158
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::vector< window * > open_window_stack
Keeps track of any open windows of any type (modal, non-modal, or tooltip) in the order in which they...
Definition: handler.cpp:1072
resolution_definition_ptr get_control(const std::string &control_type, const std::string &definition)
Returns the appropriate config data for a widget instance fom the active GUI definition.
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:98
std::size_t size(std::string_view str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:85
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
std::string definition
Parameters for the styled_widget.
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:47
#define LOG_HEADER
#define LOG_SCOPE_HEADER
Contains the gui2 timer routines.