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