The Battle for Wesnoth  1.17.0-dev
text_box_base.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2021
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  , 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  text_.set_family_class(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  set_is_dirty(true);
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  set_is_dirty(true);
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  set_is_dirty(true);
154 
155  } else {
156  assert(offset <= text_.get_length());
157  selection_start_ = offset;
158  selection_length_ = 0;
159 
160  update_canvas();
161  set_is_dirty(true);
162  }
163 }
164 
165 void text_box_base::insert_char(const std::string& unicode)
166 {
168 
169  if(text_.insert_text(selection_start_, unicode)) {
170 
171  // Update status
172  set_cursor(selection_start_ + utf8::size(unicode), false);
173  update_canvas();
174  set_is_dirty(true);
175  }
176 }
177 
179 {
180  if(!is_composing()) {
181  return 0;
182  }
183 
184  size_t text_length = utf8::size(text_.text());
185  size_t text_cached_length = utf8::size(text_cached_);
186  if(text_length < text_cached_length) {
187  return 0;
188  }
189 
191 }
192 
194 {
195  ime_composing_ = false;
196  // We need to inform the IME that text input is no longer in progress.
197  SDL_StopTextInput();
198  SDL_StartTextInput();
199 }
200 
201 void text_box_base::copy_selection(const bool mouse)
202 {
203  if(selection_length_ == 0) {
204  return;
205  }
206 
207  unsigned end, start = selection_start_;
208  const std::string txt = text_.text();
209 
210  if(selection_length_ > 0) {
211  end = utf8::index(txt, start + selection_length_);
212  start = utf8::index(txt, start);
213  } else {
214  // inverse selection: selection_start_ is in fact the end
215  end = utf8::index(txt, start);
216  start = utf8::index(txt, start + selection_length_);
217  }
218  desktop::clipboard::copy_to_clipboard(txt.substr(start, end - start), mouse);
219 }
220 
221 void text_box_base::paste_selection(const bool mouse)
222 {
223  const std::string& text = desktop::clipboard::copy_from_clipboard(mouse);
224  if(text.empty()) {
225  return;
226  }
227 
229 
231 
232  update_canvas();
233  set_is_dirty(true);
234  fire(event::NOTIFY_MODIFIED, *this, nullptr);
235 }
236 
237 void text_box_base::set_selection_start(const std::size_t selection_start)
238 {
239  if(selection_start != selection_start_) {
240  selection_start_ = selection_start;
241  set_is_dirty(true);
242  }
243 }
244 
245 void text_box_base::set_selection_length(const int selection_length)
246 {
247  if(selection_length != selection_length_) {
248  selection_length_ = selection_length;
249  set_is_dirty(true);
250  }
251 }
252 
253 void text_box_base::set_selection(std::size_t start, int length)
254 {
255  const std::size_t text_size = text_.get_length();
256 
257  if(start >= text_size) {
258  start = text_size;
259  }
260 
261  if(length == 0) {
262  set_cursor(start, false);
263  return;
264  }
265 
266  // The text pos/size type differs in both signedness and size with the
267  // selection length. Such is life.
268  const int sel_start = std::min<std::size_t>(start, std::numeric_limits<int>::max());
269  const int sel_max_length = std::min<std::size_t>(text_size - start, std::numeric_limits<int>::max());
270 
271  const bool backwards = length < 0;
272 
273  if(backwards && -length > sel_start) {
274  length = -sel_start;
275  } else if(!backwards && length > sel_max_length) {
276  length = sel_max_length;
277  }
278 
279  set_selection_start(start);
280  set_selection_length(length);
281 
282  update_canvas();
283 }
284 
286 {
287  if(state != state_) {
288  state_ = state;
289  set_is_dirty(true);
290  }
291 }
292 
294 {
295  if(!cursor_blink_rate_ms_) {
296  return;
297  }
298 
299  if(cursor_timer_) {
301  }
302 
303  cursor_timer_ = enable
305  : 0;
306 }
307 
309 {
310  unsigned was_alpha = cursor_alpha_;
311  switch(state_) {
312  case DISABLED:
313  cursor_alpha_ = 0;
314  return;
315  case ENABLED:
316  cursor_alpha_ = 255;
317  return;
318  default:
319  if(get_window() != open_window_stack.back()) {
320  cursor_alpha_ = 0;
321  } else {
322  cursor_alpha_ = (~cursor_alpha_) & 0xFF;
323  }
324  }
325 
326  if(was_alpha == cursor_alpha_) {
327  return;
328  }
329 
330  for(auto& tmp : get_canvases()) {
331  tmp.set_variable("cursor_alpha", wfl::variant(cursor_alpha_));
332  }
333 
334  set_is_dirty(true);
335 }
336 
338 {
339  if(!cursor_blink_rate_ms_) {
340  return;
341  }
342 
343  cursor_alpha_ = 255;
344 
345  for(auto& tmp : get_canvases()) {
346  tmp.set_variable("cursor_alpha", wfl::variant(cursor_alpha_));
347  }
348 
349  // Restart the blink timer.
350  toggle_cursor_timer(true);
351 }
352 
353 void text_box_base::handle_key_left_arrow(SDL_Keymod modifier, bool& handled)
354 {
355  /** @todo implement the ctrl key. */
356  DBG_GUI_E << LOG_SCOPE_HEADER << '\n';
357 
358  handled = true;
359  const int offset = selection_start_ - 1 + selection_length_;
360  if(offset >= 0) {
361  set_cursor(offset, (modifier & KMOD_SHIFT) != 0);
362  }
363 }
364 
365 void text_box_base::handle_key_right_arrow(SDL_Keymod modifier, bool& handled)
366 {
367  /** @todo implement the ctrl key. */
368  DBG_GUI_E << LOG_SCOPE_HEADER << '\n';
369 
370  handled = true;
371  const std::size_t offset = selection_start_ + 1 + selection_length_;
372  if(offset <= text_.get_length()) {
373  set_cursor(offset, (modifier & KMOD_SHIFT) != 0);
374  }
375 }
376 
377 void text_box_base::handle_key_home(SDL_Keymod modifier, bool& handled)
378 {
379  DBG_GUI_E << LOG_SCOPE_HEADER << '\n';
380 
381  handled = true;
382  if(modifier & KMOD_CTRL) {
383  goto_start_of_data((modifier & KMOD_SHIFT) != 0);
384  } else {
385  goto_start_of_line((modifier & KMOD_SHIFT) != 0);
386  }
387 }
388 
389 void text_box_base::handle_key_end(SDL_Keymod modifier, bool& handled)
390 {
391  DBG_GUI_E << LOG_SCOPE_HEADER << '\n';
392 
393  handled = true;
394  if(modifier & KMOD_CTRL) {
395  goto_end_of_data((modifier & KMOD_SHIFT) != 0);
396  } else {
397  goto_end_of_line((modifier & KMOD_SHIFT) != 0);
398  }
399 }
400 
401 void text_box_base::handle_key_backspace(SDL_Keymod /*modifier*/, bool& handled)
402 {
403  DBG_GUI_E << LOG_SCOPE_HEADER << '\n';
404 
405  handled = true;
406  if(selection_length_ != 0) {
408  } else if(selection_start_) {
409  delete_char(true);
410  if(is_composing()) {
411  if(get_composition_length() == 0) {
412  ime_composing_ = false;
413  }
414  }
415  }
416  fire(event::NOTIFY_MODIFIED, *this, nullptr);
417 }
418 
419 void text_box_base::handle_key_delete(SDL_Keymod /*modifier*/, bool& handled)
420 {
421  DBG_GUI_E << LOG_SCOPE_HEADER << '\n';
422 
423  handled = true;
424  if(selection_length_ != 0) {
426  } else if(selection_start_ < text_.get_length()) {
427  delete_char(false);
428  if(is_composing()) {
429  if(get_composition_length() == 0) {
430  ime_composing_ = false;
431  }
432  }
433  }
434  fire(event::NOTIFY_MODIFIED, *this, nullptr);
435 }
436 
437 void text_box_base::handle_commit(bool& handled, const std::string& unicode)
438 {
439  DBG_GUI_E << LOG_SCOPE_HEADER << '\n';
440 
441  if(unicode.size() > 1 || unicode[0] != 0) {
442  handled = true;
443  if(is_composing()) {
445  ime_composing_ = false;
446  }
447  insert_char(unicode);
448  fire(event::NOTIFY_MODIFIED, *this, nullptr);
449 
451  text_changed_callback_(this, this->text());
452  }
453  }
454 }
455 
456 /**
457  * SDL_TEXTEDITING handler. See example at https://wiki.libsdl.org/Tutorials/TextInput
458  */
459 void text_box_base::handle_editing(bool& handled, const std::string& unicode, int32_t start, int32_t len)
460 {
461  if(unicode.size() > 1 || unicode[0] != 0) {
462  handled = true;
463  std::size_t new_len = utf8::size(unicode);
464  if(!is_composing()) {
465  ime_composing_ = true;
468  text_cached_ = text_.text();
469  SDL_Rect rect = get_rectangle();
470  if(new_len > 0) {
472  rect.w = get_cursor_position(ime_start_point_ + new_len).x - rect.x;
473  } else {
474  rect.x += get_cursor_position(ime_start_point_ + new_len).x;
475  rect.w = get_cursor_position(ime_start_point_).x - rect.x;
476  }
477  SDL_SetTextInputRect(&rect);
478  }
479 
480 #ifdef __unix__
481  // In SDL_TextEditingEvent, size of editing_text is limited
482  // If length of composition text is more than the limit,
483  // Linux (ibus) implementation of SDL separates it into multiple
484  // SDL_TextEditingEvent.
485  // start is start position of the separated event in entire composition text
486  if(start == 0) {
487  text_.set_text(text_cached_, false);
488  }
489  text_.insert_text(ime_start_point_ + start, unicode);
490 #else
491  std::string new_text(text_cached_);
492  utf8::insert(new_text, ime_start_point_, unicode);
493  text_.set_text(new_text, false);
494 
495 #endif
496  int maximum_length = text_.get_length();
497 
498  // Update status
499  set_cursor(std::min(maximum_length, ime_start_point_ + start), false);
500  if(len > 0) {
501  set_cursor(std::min(maximum_length, ime_start_point_ + start + len), true);
502  }
503  update_canvas();
504  set_is_dirty(true);
505  }
506 }
507 
509  bool& handled)
510 {
511  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
512 
513  paste_selection(true);
514 
515  handled = true;
516 }
517 
519  bool& handled,
520  const SDL_Keycode key,
521  SDL_Keymod modifier)
522 {
523 
524  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
525 
526 /*
527  * For copy, cut and paste we use a different key on the MAC. Even for 'select
528  * all', contradicting the comment in widgets/textbox.cpp:495.
529  *
530  * The reason for that is, by coupling 'select all' to the behavior for copy,
531  * cut and paste, the text box behavior as a whole gets consistent with default
532  * macOS hotkey idioms.
533  */
534 #ifdef __APPLE__
535  // Idiomatic modifier key in macOS computers.
536  const SDL_Keycode modifier_key = KMOD_GUI;
537 #else
538  // Idiomatic modifier key in Microsoft desktop environments. Common in
539  // GNU/Linux as well, to some extent.
540  const SDL_Keycode modifier_key = KMOD_CTRL;
541 #endif
542 
543  switch(key) {
544 
545  case SDLK_LEFT:
546  handle_key_left_arrow(modifier, handled);
547  break;
548 
549  case SDLK_RIGHT:
550  handle_key_right_arrow(modifier, handled);
551  break;
552 
553  case SDLK_UP:
554  handle_key_up_arrow(modifier, handled);
555  break;
556 
557  case SDLK_DOWN:
558  handle_key_down_arrow(modifier, handled);
559  break;
560 
561  case SDLK_PAGEUP:
562  handle_key_page_up(modifier, handled);
563  break;
564 
565  case SDLK_PAGEDOWN:
566  handle_key_page_down(modifier, handled);
567  break;
568 
569  case SDLK_a:
570  if(!(modifier & modifier_key)) {
571  return;
572  }
573 
574  select_all();
575  break;
576 
577  case SDLK_HOME:
578  handle_key_home(modifier, handled);
579  break;
580 
581  case SDLK_END:
582  handle_key_end(modifier, handled);
583  break;
584 
585  case SDLK_BACKSPACE:
586  handle_key_backspace(modifier, handled);
587  break;
588 
589  case SDLK_u:
590  if(!(modifier & KMOD_CTRL)) {
591  return;
592  }
593  handle_key_clear_line(modifier, handled);
594  break;
595 
596  case SDLK_DELETE:
597  handle_key_delete(modifier, handled);
598  break;
599 
600  case SDLK_c:
601  if(!(modifier & modifier_key)) {
602  return;
603  }
604 
605  // atm we don't care whether there is something to copy or paste
606  // if nothing is there we still don't want to be chained.
607  copy_selection(false);
608  handled = true;
609  break;
610 
611  case SDLK_x:
612  if(!(modifier & modifier_key)) {
613  return;
614  }
615 
616  copy_selection(false);
618  handled = true;
619  break;
620 
621  case SDLK_v:
622  if(!(modifier & modifier_key)) {
623  return;
624  }
625 
626  paste_selection(false);
627  handled = true;
628  break;
629 
630  case SDLK_RETURN:
631  case SDLK_KP_ENTER:
632  if(!is_composing() || (modifier & (KMOD_CTRL | KMOD_ALT | KMOD_GUI | KMOD_SHIFT))) {
633  return;
634  }
635  // The IME will handle it, we just need to make sure nothing else handles it too.
636  handled = true;
637  break;
638 
639  case SDLK_ESCAPE:
640  if(!is_composing() || (modifier & (KMOD_CTRL | KMOD_ALT | KMOD_GUI | KMOD_SHIFT))) {
641  return;
642  }
644  handled = true;
645  break;
646 
647  default:
648  // Don't call the text changed callback if nothing happened.
649  return;
650  }
651 
653  text_changed_callback_(this, this->text());
654  }
655 }
656 
658 {
659  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
660 
662 }
663 
665 {
666  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
667 
669 }
670 
672  bool& handled)
673 {
674  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
675 
676  if(state_ != FOCUSED) {
678  }
679 
680  update_mouse_cursor(true);
681 
682  handled = true;
683 }
684 
686  bool& handled)
687 {
688  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
689 
690  if(state_ != FOCUSED) {
692  }
693 
694  update_mouse_cursor(false);
695 
696  handled = true;
697 }
698 
700 {
701  // Someone else may set the mouse cursor for us to something unusual (e.g.
702  // the WAIT cursor) so we ought to mess with that only if it's set to
703  // NORMAL or IBEAM.
704 
705  if(enable && cursor::get() == cursor::NORMAL) {
707  } else if(!enable && cursor::get() == cursor::IBEAM) {
709  }
710 }
711 
712 
713 } // namespace gui2
Define the common log macros for the gui toolkit.
bool is_composing() const
virtual void handle_key_left_arrow(SDL_Keymod modifier, bool &handled)
Left arrow key pressed.
virtual unsigned get_state() const override
See styled_widget::get_state.
virtual void goto_start_of_line(const bool select=false)=0
Moves the cursor to the beginning of the line.
state_t
Note the order of the states must be the same as defined in settings.hpp.
text_box_base(const implementation::builder_styled_widget &builder, const std::string &control_type)
void select_all()
Selects all text.
virtual void handle_editing(bool &handled, const std::string &unicode, int32_t start, int32_t length)
SDL_TEXTEDITING handler.
virtual void goto_end_of_line(const bool select=false)=0
Moves the cursor to the end of the line.
virtual void paste_selection(const bool mouse)
Pastes the current selection.
void set_selection(std::size_t start, int length)
Sets or clears the text selection.
std::size_t cursor_timer_
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:39
std::size_t get_length() const
Gets the length of the text in bytes.
Definition: text.hpp:218
virtual void handle_commit(bool &handled, const std::string &unicode)
bool set_text(const std::string &text, const bool markedup)
Sets the text to render.
Definition: text.cpp:283
virtual bool get_active() const override
See styled_widget::get_active.
virtual void handle_key_end(SDL_Keymod modifier, bool &handled)
End key pressed.
void set_maximum_length(const std::size_t maximum_length)
virtual void handle_key_backspace(SDL_Keymod modifier, bool &handled)
Backspace key pressed.
void set_selection_length(const int selection_length)
SDL_Rect get_rectangle() const
Gets the bounding rectangle of the widget on the screen.
Definition: widget.cpp:310
void goto_start_of_data(const bool select=false)
Moves the cursor to the beginning of the data.
virtual void copy_selection(const bool mouse)
Copies the current selection.
virtual void toggle_cursor_timer(bool enable)
void signal_handler_mouse_leave(const event::ui_event event, bool &handled)
void signal_handler_sdl_key_down(const event::ui_event event, bool &handled, const SDL_Keycode key, SDL_Keymod modifier)
pango_text & set_maximum_length(const std::size_t maximum_length)
Definition: text.cpp:435
void signal_handler_middle_button_click(const event::ui_event event, bool &handled)
virtual void handle_key_up_arrow(SDL_Keymod modifier, bool &handled)=0
Every key can have several behaviors.
size_t get_composition_length() const
Get length of composition text by IME.
unsigned short cursor_blink_rate_ms_
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.
int x
x coordinate.
Definition: point.hpp:45
Generic file dialog.
Definition: field-fwd.hpp:23
Sent by a widget to notify others its contents or state are modified.
Definition: handler.hpp:89
void goto_end_of_data(const bool select=false)
Moves the cursor to the end of all text.
void set_selection_start(const std::size_t selection_start)
virtual void handle_key_down_arrow(SDL_Keymod modifier, bool &handled)=0
Down arrow key pressed.
void signal_handler_mouse_enter(const event::ui_event event, bool &handled)
std::string definition
Parameters for the styled_widget.
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:87
std::size_t selection_start_
Start of the selected text.
virtual void handle_key_delete(SDL_Keymod modifier, bool &handled)
Delete key pressed.
unsigned short cursor_alpha_
std::string text_cached_
Cached version of the text without any pending IME modifications.
void set_is_dirty(const bool is_dirty)
Definition: widget.cpp:466
std::function< void(text_box_base *textbox, const std::string text)> text_changed_callback_
Text changed callback.
virtual void update_canvas()
Updates the canvas(ses).
std::vector< canvas > & get_canvases()
int selection_length_
Length of the selected text.
virtual void handle_key_page_down(SDL_Keymod, bool &)
Page down key.
point get_cursor_position(const unsigned column, const unsigned line=0) const
unsigned insert_text(const unsigned offset, const std::string &text)
Inserts UTF-8 text.
Definition: text.cpp:132
void signal_handler_receive_keyboard_focus(const event::ui_event event)
pango_text & set_family_class(font::family_class fclass)
Definition: text.cpp:320
virtual void handle_key_page_up(SDL_Keymod, bool &)
Page up key.
void signal_handler_lose_keyboard_focus(const event::ui_event event)
virtual void insert_char(const std::string &unicode)
Inserts a character at the cursor.
#define DBG_GUI_E
Definition: log.hpp:35
virtual void delete_char(const bool before_cursor)=0
Deletes the character.
window * get_window()
Get the parent window.
Definition: widget.cpp:117
#define LOG_SCOPE_HEADER
Contains the gui2 timer routines.
CURSOR_TYPE get()
Definition: cursor.cpp:216
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 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
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
font::pango_text text_
The text entered in the widget.
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:72
Base class for all visible items.
const std::string & text() const
Definition: text.hpp:236
virtual void set_value(const std::string &text)
The set_value is virtual for the password_box class.
void copy_to_clipboard(const std::string &text, const bool)
Copies text to the clipboard.
Definition: clipboard.cpp:34
state_t state_
Current state of the widget.
const std::string & text() const
virtual void cursor_timer_callback()
Implements blinking cursor functionality.
void update_mouse_cursor(bool enable)
bool fire(const ui_event event, widget &target)
Fires an event which has no extra parameters.
Definition: dispatcher.cpp:69
EXIT_STATUS start(const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
Definition: editor_main.cpp:30
void set_state(const state_t state)
void set_cursor(const std::size_t offset, const bool select)
Moves the cursor at the wanted position.
virtual void reset_cursor_state()
virtual void delete_selection()=0
Deletes the current selection.
#define LOG_HEADER
ui_event
The event send to the dispatcher.
Definition: handler.hpp:48
virtual void set_active(const bool active) override
See styled_widget::set_active.
virtual void handle_key_home(SDL_Keymod modifier, bool &handled)
Home key pressed.
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:1104
bool remove_timer(const std::size_t id)
Removes a timer.
Definition: timer.cpp:168