The Battle for Wesnoth  1.15.12+dev
text_box_base.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2018 by Mark de Wever <koraq@xs4all.nl>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #define GETTEXT_DOMAIN "wesnoth-lib"
16 
18 
19 #include "cursor.hpp"
20 #include "desktop/clipboard.hpp"
22 #include "gui/core/log.hpp"
23 #include "gui/core/timer.hpp"
25 
26 #include <functional>
27 
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  , ime_composing_(false)
43  , ime_start_point_(0)
44  , cursor_timer_(0)
45  , cursor_alpha_(0)
46  , cursor_blink_rate_ms_(750)
47  , text_changed_callback_()
48 {
49  auto cfg = get_control(control_type, builder.definition);
50  text_.set_family_class(cfg->text_font_family);
51 
52 #ifdef __unix__
53  // pastes on UNIX systems.
54  connect_signal<event::MIDDLE_BUTTON_CLICK>(std::bind(
55  &text_box_base::signal_handler_middle_button_click, this, std::placeholders::_2, std::placeholders::_3));
56 
57 #endif
58 
59  connect_signal<event::SDL_KEY_DOWN>(std::bind(
60  &text_box_base::signal_handler_sdl_key_down, this, std::placeholders::_2, std::placeholders::_3, std::placeholders::_5, std::placeholders::_6));
61  connect_signal<event::SDL_TEXT_INPUT>(std::bind(&text_box_base::handle_commit, this, std::placeholders::_3, std::placeholders::_5));
62  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));
63 
64  connect_signal<event::RECEIVE_KEYBOARD_FOCUS>(std::bind(
65  &text_box_base::signal_handler_receive_keyboard_focus, this, std::placeholders::_2));
66  connect_signal<event::LOSE_KEYBOARD_FOCUS>(
67  std::bind(&text_box_base::signal_handler_lose_keyboard_focus, this, std::placeholders::_2));
68 
69  connect_signal<event::MOUSE_ENTER>(
70  std::bind(&text_box_base::signal_handler_mouse_enter, this, std::placeholders::_2, std::placeholders::_3));
71  connect_signal<event::MOUSE_LEAVE>(
72  std::bind(&text_box_base::signal_handler_mouse_leave, this, std::placeholders::_2, std::placeholders::_3));
73 
74  toggle_cursor_timer(true);
75 }
76 
78 {
79  toggle_cursor_timer(false);
80  update_mouse_cursor(false);
81 }
82 
83 void text_box_base::set_active(const bool active)
84 {
85  if(get_active() != active) {
86  set_state(active ? ENABLED : DISABLED);
87  }
88 }
89 
91 {
92  return state_ != DISABLED;
93 }
94 
95 unsigned text_box_base::get_state() const
96 {
97  return state_;
98 }
99 
100 void text_box_base::set_maximum_length(const std::size_t maximum_length)
101 {
102  if(maximum_length == 0) {
103  return;
104  }
105 
106  const bool need_update = text_.get_length() > maximum_length;
107 
108  text_.set_maximum_length(maximum_length);
109 
110  if(need_update) {
111  if(selection_start_ > maximum_length) {
112  selection_start_ = maximum_length;
113  selection_length_ = 0;
114  } else if(selection_start_ + selection_length_ > maximum_length) {
115  selection_length_ = maximum_length - selection_start_;
116  }
117  update_canvas();
118  set_is_dirty(true);
119  }
120 }
121 
122 void text_box_base::set_value(const std::string& text)
123 {
124  if(text != text_.text()) {
125  text_.set_text(text, false);
126 
127  // default to put the cursor at the end of the buffer.
129  selection_length_ = 0;
130  update_canvas();
131  set_is_dirty(true);
132  }
133 }
134 
135 void text_box_base::set_cursor(const std::size_t offset, const bool select)
136 {
138 
139  if(select) {
140 
141  if(selection_start_ == offset) {
142  selection_length_ = 0;
143  } else {
144  selection_length_ = -static_cast<int>(selection_start_ - offset);
145  }
146 
147 #ifdef __unix__
148  // selecting copies on UNIX systems.
149  copy_selection(true);
150 #endif
151  update_canvas();
152  set_is_dirty(true);
153 
154  } else {
155  assert(offset <= text_.get_length());
156  selection_start_ = offset;
157  selection_length_ = 0;
158 
159  update_canvas();
160  set_is_dirty(true);
161  }
162 }
163 
164 void text_box_base::insert_char(const std::string& unicode)
165 {
167 
168  if(text_.insert_text(selection_start_, unicode)) {
169 
170  // Update status
171  set_cursor(selection_start_ + utf8::size(unicode), false);
172  update_canvas();
173  set_is_dirty(true);
174  }
175 }
176 
178 {
179  if(!is_composing()) {
180  return 0;
181  }
182 
183  size_t text_length = utf8::size(text_.text());
184  size_t text_cached_length = utf8::size(text_cached_);
185  if(text_length < text_cached_length) {
186  return 0;
187  }
188 
190 }
191 
193 {
194  ime_composing_ = false;
195  // We need to inform the IME that text input is no longer in progress.
196  SDL_StopTextInput();
197  SDL_StartTextInput();
198 }
199 
200 void text_box_base::copy_selection(const bool mouse)
201 {
202  if(selection_length_ == 0) {
203  return;
204  }
205 
206  unsigned end, start = selection_start_;
207  const std::string txt = text_.text();
208 
209  if(selection_length_ > 0) {
210  end = utf8::index(txt, start + selection_length_);
211  start = utf8::index(txt, start);
212  } else {
213  // inverse selection: selection_start_ is in fact the end
214  end = utf8::index(txt, start);
215  start = utf8::index(txt, start + selection_length_);
216  }
217  desktop::clipboard::copy_to_clipboard(txt.substr(start, end - start), mouse);
218 }
219 
220 void text_box_base::paste_selection(const bool mouse)
221 {
222  const std::string& text = desktop::clipboard::copy_from_clipboard(mouse);
223  if(text.empty()) {
224  return;
225  }
226 
228 
230 
231  update_canvas();
232  set_is_dirty(true);
233  fire(event::NOTIFY_MODIFIED, *this, nullptr);
234 }
235 
236 void text_box_base::set_selection_start(const std::size_t selection_start)
237 {
238  if(selection_start != selection_start_) {
239  selection_start_ = selection_start;
240  set_is_dirty(true);
241  }
242 }
243 
244 void text_box_base::set_selection_length(const int selection_length)
245 {
246  if(selection_length != selection_length_) {
247  selection_length_ = selection_length;
248  set_is_dirty(true);
249  }
250 }
251 
252 void text_box_base::set_selection(std::size_t start, int length)
253 {
254  const std::size_t text_size = text_.get_length();
255 
256  if(start >= text_size) {
257  start = text_size;
258  }
259 
260  if(length == 0) {
261  set_cursor(start, false);
262  return;
263  }
264 
265  // The text pos/size type differs in both signedness and size with the
266  // selection length. Such is life.
267  const int sel_start = std::min<std::size_t>(start, std::numeric_limits<int>::max());
268  const int sel_max_length = std::min<std::size_t>(text_size - start, std::numeric_limits<int>::max());
269 
270  const bool backwards = length < 0;
271 
272  if(backwards && -length > sel_start) {
273  length = -sel_start;
274  } else if(!backwards && length > sel_max_length) {
275  length = sel_max_length;
276  }
277 
278  set_selection_start(start);
279  set_selection_length(length);
280 
281  update_canvas();
282 }
283 
285 {
286  if(state != state_) {
287  state_ = state;
288  set_is_dirty(true);
289  }
290 }
291 
293 {
294  if(!cursor_blink_rate_ms_) {
295  return;
296  }
297 
298  if(cursor_timer_) {
300  }
301 
302  cursor_timer_ = enable
304  : 0;
305 }
306 
308 {
309  unsigned was_alpha = cursor_alpha_;
310  switch(state_) {
311  case DISABLED:
312  cursor_alpha_ = 0;
313  return;
314  case ENABLED:
315  cursor_alpha_ = 255;
316  return;
317  default:
318  if(get_window() != open_window_stack.back()) {
319  cursor_alpha_ = 0;
320  } else {
321  cursor_alpha_ = (~cursor_alpha_) & 0xFF;
322  }
323  }
324 
325  if(was_alpha == cursor_alpha_) {
326  return;
327  }
328 
329  for(auto& tmp : get_canvases()) {
330  tmp.set_variable("cursor_alpha", wfl::variant(cursor_alpha_));
331  }
332 
333  set_is_dirty(true);
334 }
335 
337 {
338  if(!cursor_blink_rate_ms_) {
339  return;
340  }
341 
342  cursor_alpha_ = 255;
343 
344  for(auto& tmp : get_canvases()) {
345  tmp.set_variable("cursor_alpha", wfl::variant(cursor_alpha_));
346  }
347 
348  // Restart the blink timer.
349  toggle_cursor_timer(true);
350 }
351 
352 void text_box_base::handle_key_left_arrow(SDL_Keymod modifier, bool& handled)
353 {
354  /** @todo implement the ctrl key. */
355  DBG_GUI_E << LOG_SCOPE_HEADER << '\n';
356 
357  handled = true;
358  const int offset = selection_start_ - 1 + selection_length_;
359  if(offset >= 0) {
360  set_cursor(offset, (modifier & KMOD_SHIFT) != 0);
361  }
362 }
363 
364 void text_box_base::handle_key_right_arrow(SDL_Keymod modifier, bool& handled)
365 {
366  /** @todo implement the ctrl key. */
367  DBG_GUI_E << LOG_SCOPE_HEADER << '\n';
368 
369  handled = true;
370  const std::size_t offset = selection_start_ + 1 + selection_length_;
371  if(offset <= text_.get_length()) {
372  set_cursor(offset, (modifier & KMOD_SHIFT) != 0);
373  }
374 }
375 
376 void text_box_base::handle_key_home(SDL_Keymod modifier, bool& handled)
377 {
378  DBG_GUI_E << LOG_SCOPE_HEADER << '\n';
379 
380  handled = true;
381  if(modifier & KMOD_CTRL) {
382  goto_start_of_data((modifier & KMOD_SHIFT) != 0);
383  } else {
384  goto_start_of_line((modifier & KMOD_SHIFT) != 0);
385  }
386 }
387 
388 void text_box_base::handle_key_end(SDL_Keymod modifier, bool& handled)
389 {
390  DBG_GUI_E << LOG_SCOPE_HEADER << '\n';
391 
392  handled = true;
393  if(modifier & KMOD_CTRL) {
394  goto_end_of_data((modifier & KMOD_SHIFT) != 0);
395  } else {
396  goto_end_of_line((modifier & KMOD_SHIFT) != 0);
397  }
398 }
399 
400 void text_box_base::handle_key_backspace(SDL_Keymod /*modifier*/, bool& handled)
401 {
402  DBG_GUI_E << LOG_SCOPE_HEADER << '\n';
403 
404  handled = true;
405  if(selection_length_ != 0) {
407  } else if(selection_start_) {
408  delete_char(true);
409  if(is_composing()) {
410  if(get_composition_length() == 0) {
411  ime_composing_ = false;
412  }
413  }
414  }
415  fire(event::NOTIFY_MODIFIED, *this, nullptr);
416 }
417 
418 void text_box_base::handle_key_delete(SDL_Keymod /*modifier*/, bool& handled)
419 {
420  DBG_GUI_E << LOG_SCOPE_HEADER << '\n';
421 
422  handled = true;
423  if(selection_length_ != 0) {
425  } else if(selection_start_ < text_.get_length()) {
426  delete_char(false);
427  if(is_composing()) {
428  if(get_composition_length() == 0) {
429  ime_composing_ = false;
430  }
431  }
432  }
433  fire(event::NOTIFY_MODIFIED, *this, nullptr);
434 }
435 
436 void text_box_base::handle_commit(bool& handled, const std::string& unicode)
437 {
438  DBG_GUI_E << LOG_SCOPE_HEADER << '\n';
439 
440  if(unicode.size() > 1 || unicode[0] != 0) {
441  handled = true;
442  if(is_composing()) {
444  ime_composing_ = false;
445  }
446  insert_char(unicode);
447  fire(event::NOTIFY_MODIFIED, *this, nullptr);
448 
450  text_changed_callback_(this, this->text());
451  }
452  }
453 }
454 
455 /**
456  * SDL_TEXTEDITING handler. See example at https://wiki.libsdl.org/Tutorials/TextInput
457  */
458 void text_box_base::handle_editing(bool& handled, const std::string& unicode, int32_t start, int32_t len)
459 {
460  if(unicode.size() > 1 || unicode[0] != 0) {
461  handled = true;
462  std::size_t new_len = utf8::size(unicode);
463  if(!is_composing()) {
464  ime_composing_ = true;
467  text_cached_ = text_.text();
468  SDL_Rect rect = get_rectangle();
469  if(new_len > 0) {
471  rect.w = get_cursor_position(ime_start_point_ + new_len).x - rect.x;
472  } else {
473  rect.x += get_cursor_position(ime_start_point_ + new_len).x;
474  rect.w = get_cursor_position(ime_start_point_).x - rect.x;
475  }
476  SDL_SetTextInputRect(&rect);
477  }
478 
479 #ifdef __unix__
480  // In SDL_TextEditingEvent, size of editing_text is limited
481  // If length of composition text is more than the limit,
482  // Linux (ibus) implementation of SDL separates it into multiple
483  // SDL_TextEditingEvent.
484  // start is start position of the separated event in entire composition text
485  if(start == 0) {
486  text_.set_text(text_cached_, false);
487  }
488  text_.insert_text(ime_start_point_ + start, unicode);
489 #else
490  std::string new_text(text_cached_);
491  utf8::insert(new_text, ime_start_point_, unicode);
492  text_.set_text(new_text, false);
493 
494 #endif
495  int maximum_length = text_.get_length();
496 
497  // Update status
498  set_cursor(std::min(maximum_length, ime_start_point_ + start), false);
499  if(len > 0) {
500  set_cursor(std::min(maximum_length, ime_start_point_ + start + len), true);
501  }
502  update_canvas();
503  set_is_dirty(true);
504  }
505 }
506 
508  bool& handled)
509 {
510  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
511 
512  paste_selection(true);
513 
514  handled = true;
515 }
516 
518  bool& handled,
519  const SDL_Keycode key,
520  SDL_Keymod modifier)
521 {
522 
523  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
524 
525 /*
526  * For copy, cut and paste we use a different key on the MAC. Even for 'select
527  * all', contradicting the comment in widgets/textbox.cpp:495.
528  *
529  * The reason for that is, by coupling 'select all' to the behavior for copy,
530  * cut and paste, the text box behavior as a whole gets consistent with default
531  * macOS hotkey idioms.
532  */
533 #ifdef __APPLE__
534  // Idiomatic modifier key in macOS computers.
535  const SDL_Keycode modifier_key = KMOD_GUI;
536 #else
537  // Idiomatic modifier key in Microsoft desktop environments. Common in
538  // GNU/Linux as well, to some extent.
539  const SDL_Keycode modifier_key = KMOD_CTRL;
540 #endif
541 
542  switch(key) {
543 
544  case SDLK_LEFT:
545  handle_key_left_arrow(modifier, handled);
546  break;
547 
548  case SDLK_RIGHT:
549  handle_key_right_arrow(modifier, handled);
550  break;
551 
552  case SDLK_UP:
553  handle_key_up_arrow(modifier, handled);
554  break;
555 
556  case SDLK_DOWN:
557  handle_key_down_arrow(modifier, handled);
558  break;
559 
560  case SDLK_PAGEUP:
561  handle_key_page_up(modifier, handled);
562  break;
563 
564  case SDLK_PAGEDOWN:
565  handle_key_page_down(modifier, handled);
566  break;
567 
568  case SDLK_a:
569  if(!(modifier & modifier_key)) {
570  return;
571  }
572 
573  select_all();
574  break;
575 
576  case SDLK_HOME:
577  handle_key_home(modifier, handled);
578  break;
579 
580  case SDLK_END:
581  handle_key_end(modifier, handled);
582  break;
583 
584  case SDLK_BACKSPACE:
585  handle_key_backspace(modifier, handled);
586  break;
587 
588  case SDLK_u:
589  if(!(modifier & KMOD_CTRL)) {
590  return;
591  }
592  handle_key_clear_line(modifier, handled);
593  break;
594 
595  case SDLK_DELETE:
596  handle_key_delete(modifier, handled);
597  break;
598 
599  case SDLK_c:
600  if(!(modifier & modifier_key)) {
601  return;
602  }
603 
604  // atm we don't care whether there is something to copy or paste
605  // if nothing is there we still don't want to be chained.
606  copy_selection(false);
607  handled = true;
608  break;
609 
610  case SDLK_x:
611  if(!(modifier & modifier_key)) {
612  return;
613  }
614 
615  copy_selection(false);
617  handled = true;
618  break;
619 
620  case SDLK_v:
621  if(!(modifier & modifier_key)) {
622  return;
623  }
624 
625  paste_selection(false);
626  handled = true;
627  break;
628 
629  case SDLK_RETURN:
630  case SDLK_KP_ENTER:
631  if(!is_composing() || (modifier & (KMOD_CTRL | KMOD_ALT | KMOD_GUI | KMOD_SHIFT))) {
632  return;
633  }
634  // The IME will handle it, we just need to make sure nothing else handles it too.
635  handled = true;
636  break;
637 
638  case SDLK_ESCAPE:
639  if(!is_composing() || (modifier & (KMOD_CTRL | KMOD_ALT | KMOD_GUI | KMOD_SHIFT))) {
640  return;
641  }
643  handled = true;
644  break;
645 
646  default:
647  // Don't call the text changed callback if nothing happened.
648  return;
649  }
650 
652  text_changed_callback_(this, this->text());
653  }
654 }
655 
657 {
658  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
659 
661 }
662 
664 {
665  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
666 
668 }
669 
671  bool& handled)
672 {
673  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
674 
675  if(state_ != FOCUSED) {
677  }
678 
679  update_mouse_cursor(true);
680 
681  handled = true;
682 }
683 
685  bool& handled)
686 {
687  DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
688 
689  if(state_ != FOCUSED) {
691  }
692 
693  update_mouse_cursor(false);
694 
695  handled = true;
696 }
697 
699 {
700  // Someone else may set the mouse cursor for us to something unusual (e.g.
701  // the WAIT cursor) so we ought to mess with that only if it's set to
702  // NORMAL or IBEAM.
703 
704  if(enable && cursor::get() == cursor::NORMAL) {
706  } else if(!enable && cursor::get() == cursor::IBEAM) {
708  }
709 }
710 
711 
712 } // 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:175
std::string copy_from_clipboard(const bool)
Copies text from the clipboard.
Definition: clipboard.cpp:38
std::size_t get_length() const
Gets the length of the text in bytes.
Definition: text.hpp:217
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:282
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:309
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:434
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:44
Generic file dialog.
Definition: field-fwd.hpp:22
Sent by a widget to notify others its contents or state are modified.
Definition: handler.hpp:88
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:86
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:465
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:131
void signal_handler_receive_keyboard_focus(const event::ui_event event)
pango_text & set_family_class(font::family_class fclass)
Definition: text.cpp:319
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:34
virtual void delete_char(const bool before_cursor)=0
Deletes the character.
window * get_window()
Get the parent window.
Definition: widget.cpp:116
#define LOG_SCOPE_HEADER
Contains the gui2 timer routines.
CURSOR_TYPE get()
Definition: cursor.cpp:215
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:126
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:99
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:71
Base class for all visible items.
const std::string & text() const
Definition: text.hpp:235
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:33
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:68
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:28
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:47
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:1103
bool remove_timer(const std::size_t id)
Removes a timer.
Definition: timer.cpp:167