The Battle for Wesnoth  1.19.0-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 namespace gui2
34 {
35 
36 text_box_base::text_box_base(const implementation::builder_styled_widget& builder, const std::string& control_type)
37  : styled_widget(builder, control_type)
38  , state_(ENABLED)
39  , text_()
40  , selection_start_(0)
41  , selection_length_(0)
42  , editable_(true)
43  , ime_composing_(false)
44  , ime_start_point_(0)
45  , cursor_timer_(0)
46  , cursor_alpha_(0)
47  , cursor_blink_rate_ms_(750)
48  , text_changed_callback_()
49 {
50  auto cfg = get_control(control_type, builder.definition);
51  set_font_family(cfg->text_font_family);
52 
53 #ifdef __unix__
54  // pastes on UNIX systems.
55  connect_signal<event::MIDDLE_BUTTON_CLICK>(std::bind(
56  &text_box_base::signal_handler_middle_button_click, this, std::placeholders::_2, std::placeholders::_3));
57 
58 #endif
59 
60  connect_signal<event::SDL_KEY_DOWN>(std::bind(
61  &text_box_base::signal_handler_sdl_key_down, this, std::placeholders::_2, std::placeholders::_3, std::placeholders::_5, std::placeholders::_6));
62  connect_signal<event::SDL_TEXT_INPUT>(std::bind(&text_box_base::handle_commit, this, std::placeholders::_3, std::placeholders::_5));
63  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));
64 
65  connect_signal<event::RECEIVE_KEYBOARD_FOCUS>(std::bind(
66  &text_box_base::signal_handler_receive_keyboard_focus, this, std::placeholders::_2));
67  connect_signal<event::LOSE_KEYBOARD_FOCUS>(
68  std::bind(&text_box_base::signal_handler_lose_keyboard_focus, this, std::placeholders::_2));
69 
70  connect_signal<event::MOUSE_ENTER>(
71  std::bind(&text_box_base::signal_handler_mouse_enter, this, std::placeholders::_2, std::placeholders::_3));
72  connect_signal<event::MOUSE_LEAVE>(
73  std::bind(&text_box_base::signal_handler_mouse_leave, this, std::placeholders::_2, std::placeholders::_3));
74 
75  toggle_cursor_timer(true);
76 }
77 
79 {
80  toggle_cursor_timer(false);
81  update_mouse_cursor(false);
82 }
83 
84 void text_box_base::set_active(const bool active)
85 {
86  if(get_active() != active) {
87  set_state(active ? ENABLED : DISABLED);
88  }
89 }
90 
92 {
93  return state_ != DISABLED;
94 }
95 
96 unsigned text_box_base::get_state() const
97 {
98  return state_;
99 }
100 
101 void text_box_base::set_maximum_length(const std::size_t maximum_length)
102 {
103  if(maximum_length == 0) {
104  return;
105  }
106 
107  const bool need_update = text_.get_length() > maximum_length;
108 
109  text_.set_maximum_length(maximum_length);
110 
111  if(need_update) {
112  if(selection_start_ > maximum_length) {
113  selection_start_ = maximum_length;
114  selection_length_ = 0;
115  } else if(selection_start_ + selection_length_ > maximum_length) {
116  selection_length_ = maximum_length - selection_start_;
117  }
118  update_canvas();
119  queue_redraw();
120  }
121 }
122 
123 void text_box_base::set_value(const std::string& text)
124 {
125  if(text != text_.text()) {
126  text_.set_text(text, false);
127 
128  // default to put the cursor at the end of the buffer.
130  selection_length_ = 0;
131  update_canvas();
132  queue_redraw();
133  }
134 }
135 
136 void text_box_base::set_cursor(const std::size_t offset, const bool select)
137 {
139 
140  if(select) {
141 
142  if(selection_start_ == offset) {
143  selection_length_ = 0;
144  } else {
145  selection_length_ = -static_cast<int>(selection_start_ - offset);
146  }
147 
148 #ifdef __unix__
149  // selecting copies on UNIX systems.
150  copy_selection(true);
151 #endif
152  update_canvas();
153  queue_redraw();
154 
155  } else {
156  if (offset <= text_.get_length()) {
157  selection_start_ = offset;
158  } else {
159  selection_start_ = 0;
160  }
161  selection_length_ = 0;
162 
163  update_canvas();
164  queue_redraw();
165  }
166 }
167 
168 void text_box_base::insert_char(const std::string& unicode)
169 {
170  if(!editable_)
171  {
172  return;
173  }
174 
176 
177  if(text_.insert_text(selection_start_, unicode)) {
178 
179  // Update status
180  set_cursor(selection_start_ + utf8::size(unicode), false);
181  update_canvas();
182  queue_redraw();
183  }
184 }
185 
187 {
188  if(!is_composing()) {
189  return 0;
190  }
191 
192  size_t text_length = utf8::size(text_.text());
193  size_t text_cached_length = utf8::size(text_cached_);
194  if(text_length < text_cached_length) {
195  return 0;
196  }
197 
199 }
200 
202 {
203  ime_composing_ = false;
204  // We need to inform the IME that text input is no longer in progress.
205  SDL_StopTextInput();
206  SDL_StartTextInput();
207 }
208 
209 void text_box_base::copy_selection(const bool mouse)
210 {
211  if(selection_length_ == 0) {
212  return;
213  }
214 
215  unsigned end, start = selection_start_;
216  const std::string txt = 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);
225  }
226  desktop::clipboard::copy_to_clipboard(txt.substr(start, end - start), mouse);
227 }
228 
229 void text_box_base::paste_selection(const bool mouse)
230 {
231  if(!editable_)
232  {
233  return;
234  }
235 
236  const std::string& text = desktop::clipboard::copy_from_clipboard(mouse);
237  if(text.empty()) {
238  return;
239  }
240 
242 
244 
245  update_canvas();
246  queue_redraw();
247  fire(event::NOTIFY_MODIFIED, *this, nullptr);
248 }
249 
250 void 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 
258 void 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 
266 void 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 
293  set_selection_length(length);
294 
295  update_canvas();
296 }
297 
299 {
300  if(state != state_) {
301  state_ = state;
302  queue_redraw();
303  }
304 }
305 
307 {
308  if(!cursor_blink_rate_ms_) {
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  // back() on an empty vector is UB and was causing a crash when run on Wayland (see #7104 on github)
333  if(!open_window_stack.empty() && get_window() != open_window_stack.back()) {
334  cursor_alpha_ = 0;
335  } else {
336  cursor_alpha_ = (~cursor_alpha_) & 0xFF;
337  }
338  }
339 
340  if(was_alpha == cursor_alpha_) {
341  return;
342  }
343 
344  for(auto& tmp : get_canvases()) {
345  tmp.set_variable("cursor_alpha", wfl::variant(cursor_alpha_));
346  }
347 
348  queue_redraw();
349 }
350 
352 {
353  if(!cursor_blink_rate_ms_) {
354  return;
355  }
356 
357  cursor_alpha_ = 255;
358 
359  for(auto& tmp : get_canvases()) {
360  tmp.set_variable("cursor_alpha", wfl::variant(cursor_alpha_));
361  }
362 
363  // Restart the blink timer.
364  toggle_cursor_timer(true);
365 }
366 
367 void text_box_base::handle_key_left_arrow(SDL_Keymod modifier, bool& handled)
368 {
369  /** @todo implement the ctrl key. */
371 
372  handled = true;
373  const int offset = selection_start_ - 1 + selection_length_;
374  if(offset >= 0) {
375  set_cursor(offset, (modifier & KMOD_SHIFT) != 0);
376  }
377 }
378 
379 void text_box_base::handle_key_right_arrow(SDL_Keymod modifier, bool& handled)
380 {
381  /** @todo implement the ctrl key. */
383 
384  handled = true;
385  const std::size_t offset = selection_start_ + 1 + selection_length_;
386  if(offset <= text_.get_length()) {
387  set_cursor(offset, (modifier & KMOD_SHIFT) != 0);
388  }
389 }
390 
391 void text_box_base::handle_key_home(SDL_Keymod modifier, bool& handled)
392 {
394 
395  handled = true;
396  if(modifier & KMOD_CTRL) {
397  goto_start_of_data((modifier & KMOD_SHIFT) != 0);
398  } else {
399  goto_start_of_line((modifier & KMOD_SHIFT) != 0);
400  }
401 }
402 
403 void text_box_base::handle_key_end(SDL_Keymod modifier, bool& handled)
404 {
406 
407  handled = true;
408  if(modifier & KMOD_CTRL) {
409  goto_end_of_data((modifier & KMOD_SHIFT) != 0);
410  } else {
411  goto_end_of_line((modifier & KMOD_SHIFT) != 0);
412  }
413 }
414 
415 void text_box_base::handle_key_backspace(SDL_Keymod /*modifier*/, bool& handled)
416 {
418 
419  handled = true;
420  if(selection_length_ != 0) {
422  } else if(selection_start_) {
423  delete_char(true);
424  if(is_composing()) {
425  if(get_composition_length() == 0) {
426  ime_composing_ = false;
427  }
428  }
429  }
430  fire(event::NOTIFY_MODIFIED, *this, nullptr);
431 }
432 
433 void text_box_base::handle_key_delete(SDL_Keymod /*modifier*/, bool& handled)
434 {
436 
437  handled = true;
438  if(selection_length_ != 0) {
440  } else if(selection_start_ < text_.get_length()) {
441  delete_char(false);
442  if(is_composing()) {
443  if(get_composition_length() == 0) {
444  ime_composing_ = false;
445  }
446  }
447  }
448  fire(event::NOTIFY_MODIFIED, *this, nullptr);
449 }
450 
451 void text_box_base::handle_commit(bool& handled, const std::string& unicode)
452 {
454 
455  if(unicode.size() > 1 || unicode[0] != 0) {
456  handled = true;
457  if(is_composing()) {
459  ime_composing_ = false;
460  }
461  insert_char(unicode);
462  fire(event::NOTIFY_MODIFIED, *this, nullptr);
463 
465  text_changed_callback_(this, this->text());
466  }
467  }
468 }
469 
470 /**
471  * SDL_TEXTEDITING handler. See example at https://wiki.libsdl.org/Tutorials/TextInput
472  */
473 void text_box_base::handle_editing(bool& handled, const std::string& unicode, int32_t start, int32_t len)
474 {
475  if(unicode.size() > 1 || unicode[0] != 0) {
476  handled = true;
477  std::size_t new_len = utf8::size(unicode);
478  if(!is_composing()) {
479  ime_composing_ = true;
482  text_cached_ = text_.text();
483  SDL_Rect rect = get_rectangle();
484  if(new_len > 0) {
486  rect.w = get_cursor_position(ime_start_point_ + new_len).x - rect.x;
487  } else {
488  rect.x += get_cursor_position(ime_start_point_ + new_len).x;
490  }
491  SDL_SetTextInputRect(&rect);
492  }
493 
494 #ifdef __unix__
495  // In SDL_TextEditingEvent, size of editing_text is limited
496  // If length of composition text is more than the limit,
497  // Linux (ibus) implementation of SDL separates it into multiple
498  // SDL_TextEditingEvent.
499  // start is start position of the separated event in entire composition text
500  if(start == 0) {
501  text_.set_text(text_cached_, false);
502  }
504 #else
505  std::string new_text(text_cached_);
506  utf8::insert(new_text, ime_start_point_, unicode);
507  text_.set_text(new_text, false);
508 
509 #endif
510  int maximum_length = text_.get_length();
511 
512  // Update status
513  set_cursor(std::min(maximum_length, ime_start_point_ + start), false);
514  if(len > 0) {
515  set_cursor(std::min(maximum_length, ime_start_point_ + start + len), true);
516  }
517  update_canvas();
518  queue_redraw();
519  }
520 }
521 
523  bool& handled)
524 {
525  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
526 
527  paste_selection(true);
528 
529  handled = true;
530 }
531 
533  bool& handled,
534  const SDL_Keycode key,
535  SDL_Keymod modifier)
536 {
537 
538  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
539 
540 /*
541  * For copy, cut and paste we use a different key on the MAC. Even for 'select
542  * all', contradicting the comment in widgets/textbox.cpp:495.
543  *
544  * The reason for that is, by coupling 'select all' to the behavior for copy,
545  * cut and paste, the text box behavior as a whole gets consistent with default
546  * macOS hotkey idioms.
547  */
548 #ifdef __APPLE__
549  // Idiomatic modifier key in macOS computers.
550  const SDL_Keycode modifier_key = KMOD_GUI;
551 #else
552  // Idiomatic modifier key in Microsoft desktop environments. Common in
553  // GNU/Linux as well, to some extent.
554  const SDL_Keycode modifier_key = KMOD_CTRL;
555 #endif
556 
557  switch(key) {
558 
559  case SDLK_LEFT:
560  handle_key_left_arrow(modifier, handled);
561  break;
562 
563  case SDLK_RIGHT:
564  handle_key_right_arrow(modifier, handled);
565  break;
566 
567  case SDLK_UP:
568  handle_key_up_arrow(modifier, handled);
569  break;
570 
571  case SDLK_DOWN:
572  handle_key_down_arrow(modifier, handled);
573  break;
574 
575  case SDLK_PAGEUP:
576  handle_key_page_up(modifier, handled);
577  break;
578 
579  case SDLK_PAGEDOWN:
580  handle_key_page_down(modifier, handled);
581  break;
582 
583  case SDLK_a:
584  if(!(modifier & modifier_key)) {
585  return;
586  }
587 
588  select_all();
589  break;
590 
591  case SDLK_HOME:
592  handle_key_home(modifier, handled);
593  break;
594 
595  case SDLK_END:
596  handle_key_end(modifier, handled);
597  break;
598 
599  case SDLK_BACKSPACE:
600  if (!is_editable())
601  {
602  return;
603  }
604 
605  handle_key_backspace(modifier, handled);
606  break;
607 
608  case SDLK_u:
609  if( !(modifier & KMOD_CTRL) || !is_editable() ) {
610  return;
611  }
612 
613  handle_key_clear_line(modifier, handled);
614  break;
615 
616  case SDLK_DELETE:
617  if (!is_editable())
618  {
619  return;
620  }
621 
622  handle_key_delete(modifier, handled);
623  break;
624 
625  case SDLK_c:
626  if(!(modifier & modifier_key)) {
627  return;
628  }
629 
630  // atm we don't care whether there is something to copy or paste
631  // if nothing is there we still don't want to be chained.
632  copy_selection(false);
633  handled = true;
634  break;
635 
636  case SDLK_x:
637  if( !(modifier & modifier_key) ) {
638  return;
639  }
640 
641  copy_selection(false);
642 
643  if ( is_editable() ) {
645  }
646  handled = true;
647  break;
648 
649  case SDLK_v:
650  if( !(modifier & modifier_key) || !is_editable() ) {
651  return;
652  }
653 
654  paste_selection(false);
655  handled = true;
656  break;
657 
658  case SDLK_RETURN:
659  case SDLK_KP_ENTER:
660 
661 // TODO: check if removing the following check causes any side effects
662 // To be removed if there aren't any text rendering problems.
663 // if(!is_composing()) {
664 // return;
665 // }
666 
667  handle_key_enter(modifier, handled);
668  break;
669 
670  case SDLK_ESCAPE:
671  if(!is_composing() || (modifier & (KMOD_CTRL | KMOD_ALT | KMOD_GUI | KMOD_SHIFT))) {
672  return;
673  }
675  handled = true;
676  break;
677 
678  case SDLK_TAB:
679  handle_key_tab(modifier, handled);
680  break;
681 
682  default:
683  // Don't call the text changed callback if nothing happened.
684  return;
685  }
686 
688  text_changed_callback_(this, this->text());
689  }
690 }
691 
693 {
694  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
695 
697 }
698 
700 {
701  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
702 
704 }
705 
707  bool& handled)
708 {
709  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
710 
711  if(state_ != FOCUSED) {
713  }
714 
715  update_mouse_cursor(true);
716 
717  handled = true;
718 }
719 
721  bool& handled)
722 {
723  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
724 
725  if(state_ != FOCUSED) {
727  }
728 
729  update_mouse_cursor(false);
730 
731  handled = true;
732 }
733 
735 {
736  // Someone else may set the mouse cursor for us to something unusual (e.g.
737  // the WAIT cursor) so we ought to mess with that only if it's set to
738  // NORMAL or IBEAM.
739 
740  if(enable && cursor::get() == cursor::NORMAL) {
742  } else if(!enable && cursor::get() == cursor::IBEAM) {
744  }
745 }
746 
747 
748 } // namespace gui2
std::size_t get_length() const
Gets the length of the text in bytes.
Definition: text.hpp:252
pango_text & set_maximum_length(const std::size_t maximum_length)
Definition: text.cpp:525
unsigned insert_text(const unsigned offset, const std::string &text)
Inserts UTF-8 text.
Definition: text.cpp:172
bool set_text(const std::string &text, const bool markedup)
Sets the text to render.
Definition: text.cpp:345
const std::string & text() const
Definition: text.hpp:270
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).
unsigned short cursor_blink_rate_ms_
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.
virtual void paste_selection(const bool mouse)
Pastes the current selection.
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)
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)
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.
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.
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.
virtual void handle_key_down_arrow(SDL_Keymod modifier, bool &handled)=0
Down arrow key pressed.
bool is_editable()
Check whether text can be edited or not.
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)
virtual void copy_selection(const bool mouse)
Copies the current selection.
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:454
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:311
Define the common log macros for the gui toolkit.
#define DBG_GUI_E
Definition: log.hpp:35
CURSOR_TYPE get()
Definition: cursor.cpp:217
@ 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:177
std::string copy_from_clipboard(const bool)
Copies text from the clipboard.
Definition: clipboard.cpp:37
void copy_to_clipboard(const std::string &text, const bool)
Copies text to 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 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
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:1073
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::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:70
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(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:85
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.