The Battle for Wesnoth  1.15.1+dev
text_box_base.hpp
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 #pragma once
16 
17 //#include "gui/core/event/dispatcher.hpp"
19 #include "font/text.hpp" // We want the file in src/
20 
21 #include <string>
22 
23 #include "utils/functional.hpp"
24 
25 namespace gui2
26 {
27 namespace implementation
28 {
29  struct builder_styled_widget;
30 }
31 
32 /**
33  * Abstract base class for text items.
34  *
35  * All other text classes should inherit from this base class.
36  *
37  * The NOTIFY_MODIFIED event is send when the text is modified.
38  *
39  * @todo Validate whether the NOTIFY_MODIFIED is always fired properly. The
40  * current implementation is added for some quick testing so some cases might
41  * be forgotten.
42  *
43  * Common signal handlers:
44  * - connect_signal_pre_key_press
45  */
47 {
48 
49 public:
50  text_box_base(const implementation::builder_styled_widget& builder, const std::string& control_type);
51 
52  ~text_box_base();
53 
54  /** See @ref styled_widget::set_active. */
55  virtual void set_active(const bool active) override;
56 
57  /** See @ref styled_widget::get_active. */
58  virtual bool get_active() const override;
59 
60  /** See @ref styled_widget::get_state. */
61  virtual unsigned get_state() const override;
62 
63  /***** ***** ***** ***** expose some functions ***** ***** ***** *****/
64 
65  void set_maximum_length(const std::size_t maximum_length);
66 
67  std::size_t get_length() const
68  {
69  return text_.get_length();
70  }
71 
72  /***** ***** ***** setters / getters for members ***** ****** *****/
73 
74  /**
75  * The set_value is virtual for the @ref password_box class.
76  *
77  * That class overrides the set_value function to replace it with asterisk.
78  * There might be more generic way to do it when more classes are needed.
79  */
80  virtual void set_value(const std::string& text);
81  std::string get_value() const
82  {
83  return text_.text();
84  }
85 
86  const std::string& text() const
87  {
88  return text_.text();
89  }
90 
91  /** Set the text_changed callback. */
93  std::function<void(text_box_base* textbox, const std::string text)> cb)
94  {
95  text_changed_callback_ = cb;
96  }
97 
98  /**
99  * Sets or clears the text selection.
100  *
101  * Setting the selection range will re-position the cursor depending on the
102  * selection direction, specified by the length's sign. Selecting beyond the
103  * start or end of the text is safe; the final selection will be limited
104  * accordingly.
105  *
106  * @note The range extents are measured in Unicode characters, not bytes.
107  * Using byte offsets may produce unexpected results depending on the
108  * text contents.
109  *
110  * @param start Start offset, in characters.
111  * @param length Selection length, in characters. If zero, the
112  * current selection is canceled. If negative, the
113  * selection extends towards the start of the text
114  * and the cursor will be re-positioned in that
115  * direction as well; otherwise the selection and
116  * cursor extend towards the end.
117  */
118  void set_selection(std::size_t start, int length);
119 
120 protected:
121  /** Get length of composition text by IME **/
122  size_t get_composition_length() const;
123 
124  /**
125  * Moves the cursor to the end of the line.
126  *
127  * @param select Select the text from the original cursor
128  * position till the end of the line?
129  */
130  virtual void goto_end_of_line(const bool select = false) = 0;
131 
132  /**
133  * Moves the cursor to the end of all text.
134  *
135  * For a single line text this is the same as goto_end_of_line().
136  *
137  * @param select Select the text from the original cursor
138  * position till the end of the data?
139  */
140  void goto_end_of_data(const bool select = false)
141  {
142  set_cursor(text_.get_length(), select);
143  }
144 
145  /**
146  * Moves the cursor to the beginning of the line
147  *
148  * @param select Select the text from the original cursor
149  * position till the beginning of the line?
150  */
151  virtual void goto_start_of_line(const bool select = false) = 0;
152 
153  /**
154  * Moves the cursor to the beginning of the data.
155  *
156  * @param select Select the text from the original cursor
157  * position till the beginning of the data?
158  */
159  void goto_start_of_data(const bool select = false)
160  {
161  set_cursor(0, select);
162  }
163 
164  /** Selects all text. */
165  void select_all()
166  {
167  selection_start_ = 0;
168  goto_end_of_data(true);
169  }
170 
171  /**
172  * Moves the cursor at the wanted position.
173  *
174  * @param offset The wanted new cursor position.
175  * @param select Select the text from the original cursor
176  * position till the new position?
177  */
178  void set_cursor(const std::size_t offset, const bool select);
179 
180  /**
181  * Inserts a character at the cursor.
182  *
183  * This function is preferred over set_text since it's optimized for
184  * updating the internal bookkeeping.
185  *
186  * @param unicode The unicode value of the character to insert.
187  */
188  virtual void insert_char(const std::string& unicode);
189 
190  /**
191  * Deletes the character.
192  *
193  * @param before_cursor If true it deletes the character before the
194  * cursor (backspace) else the character after
195  * the cursor (delete).
196  */
197  virtual void delete_char(const bool before_cursor) = 0;
198 
199  /** Deletes the current selection. */
200  virtual void delete_selection() = 0;
201 
202  /** Copies the current selection. */
203  virtual void copy_selection(const bool mouse);
204 
205  /** Pastes the current selection. */
206  virtual void paste_selection(const bool mouse);
207 
208  /***** ***** ***** ***** expose some functions ***** ***** ***** *****/
209 
210  point get_cursor_position(const unsigned column,
211  const unsigned line = 0) const
212  {
213  return text_.get_cursor_position(column, line);
214  }
215 
216  point get_column_line(const point& position) const
217  {
218  return text_.get_column_line(position);
219  }
220 
221  void set_font_size(const unsigned font_size)
222  {
223  text_.set_font_size(font_size);
224  }
225 
227  {
228  text_.set_font_style(font_style);
229  }
230 
231  void set_maximum_width(const int width)
232  {
233  text_.set_maximum_width(width);
234  }
235 
236  void set_maximum_height(const int height, const bool multiline)
237  {
238  text_.set_maximum_height(height, multiline);
239  }
240 
241  void set_ellipse_mode(const PangoEllipsizeMode ellipse_mode)
242  {
243  text_.set_ellipse_mode(ellipse_mode);
244  }
245 
246  /***** ***** ***** setters / getters for members ***** ****** *****/
247 
248  std::size_t get_selection_start() const
249  {
250  return selection_start_;
251  }
252  void set_selection_start(const std::size_t selection_start);
253 
254  std::size_t get_selection_length() const
255  {
256  return selection_length_;
257  }
258  void set_selection_length(const int selection_length);
259 
260  std::size_t get_composition_start() const
261  {
262  return ime_start_point_;
263  }
264 
265 public:
266  bool is_composing() const
267  {
268  return ime_composing_;
269  }
270 
271  void interrupt_composition();
272 
273  /** Note the order of the states must be the same as defined in
274  * settings.hpp. */
275  enum state_t {
279  };
280 
281 private:
282  void set_state(const state_t state);
283 
284  virtual void toggle_cursor_timer(bool enable);
285 
286  /** Implements blinking cursor functionality. */
287  virtual void cursor_timer_callback();
288 
289  virtual void reset_cursor_state();
290 
291  /**
292  * Current state of the widget.
293  *
294  * The state of the widget determines what to render and how the widget
295  * reacts to certain 'events'.
296  */
298 
299  /** The text entered in the widget. */
301 
302  /** Cached version of the text without any pending IME modifications. */
303  std::string text_cached_;
304 
305  /** Start of the selected text. */
306  std::size_t selection_start_;
307 
308  /**
309  * Length of the selected text.
310  *
311  * * positive selection_len_ means selection to the right.
312  * * negative selection_len_ means selection to the left.
313  * * selection_len_ == 0 means no selection.
314  */
316 
317  // Values to support input method editors
320 
321  std::size_t cursor_timer_;
322 
323  unsigned short cursor_alpha_;
324  unsigned short cursor_blink_rate_ms_;
325 
326  /****** handling of special keys first the pure virtuals *****/
327 
328  /**
329  * Every key can have several behaviors.
330  *
331  * Unmodified No modifier is pressed.
332  * Control The control key is pressed.
333  * Shift The shift key is pressed.
334  * Alt The alt key is pressed.
335  *
336  * If modifiers together do something else as the sum of the modifiers
337  * it's listed separately eg.
338  *
339  * Control Moves 10 steps at the time.
340  * Shift Selects the text.
341  * Control + Shift Inserts 42 in the text.
342  *
343  * There are some predefined actions for results.
344  * Unhandled The key/modifier is ignored and also reported
345  * unhandled.
346  * Ignored The key/modifier is ignored and it's
347  * _expected_ the inherited classes do the same.
348  * Implementation defined The key/modifier is ignored and it's expected
349  * the inherited classes will define some meaning
350  * to it.
351  */
352 
353  /**
354  * Up arrow key pressed.
355  *
356  * The behavior is implementation defined.
357  */
358  virtual void handle_key_up_arrow(SDL_Keymod modifier, bool& handled) = 0;
359 
360  /**
361  * Down arrow key pressed.
362  *
363  * The behavior is implementation defined.
364  */
365  virtual void handle_key_down_arrow(SDL_Keymod modifier, bool& handled) = 0;
366 
367  /**
368  * Clears the current line.
369  *
370  * Unmodified Clears the current line.
371  * Control Ignored.
372  * Shift Ignored.
373  * Alt Ignored.
374  */
375  virtual void handle_key_clear_line(SDL_Keymod modifier, bool& handled) = 0;
376 
377  /**
378  * Left arrow key pressed.
379  *
380  * Unmodified Moves the cursor a character to the left.
381  * Control Like unmodified but a word instead of a letter
382  * at the time.
383  * Shift Selects the text while moving.
384  * Alt Ignored.
385  */
386  virtual void handle_key_left_arrow(SDL_Keymod modifier, bool& handled);
387 
388  /**
389  * Right arrow key pressed.
390  *
391  * Unmodified Moves the cursor a character to the right.
392  * Control Like unmodified but a word instead of a letter
393  * at the time.
394  * Shift Selects the text while moving.
395  * Alt Ignored.
396  */
397  virtual void handle_key_right_arrow(SDL_Keymod modifier, bool& handled);
398 
399  /**
400  * Home key pressed.
401  *
402  * Unmodified Moves the cursor a to the beginning of the
403  * line.
404  * Control Like unmodified but to the beginning of the
405  * data.
406  * Shift Selects the text while moving.
407  * Alt Ignored.
408  */
409  virtual void handle_key_home(SDL_Keymod modifier, bool& handled);
410 
411  /**
412  * End key pressed.
413  *
414  * Unmodified Moves the cursor a to the end of the line.
415  * Control Like unmodified but to the end of the data.
416  * Shift Selects the text while moving.
417  * Alt Ignored.
418  */
419  virtual void handle_key_end(SDL_Keymod modifier, bool& handled);
420 
421  /**
422  * Backspace key pressed.
423  *
424  * Unmodified Deletes the character before the cursor,
425  * ignored if at the beginning of the data.
426  * Control Ignored.
427  * Shift Ignored.
428  * Alt Ignored.
429  */
430  virtual void handle_key_backspace(SDL_Keymod modifier, bool& handled);
431 
432  /**
433  * Delete key pressed.
434  *
435  * Unmodified If there is a selection that's deleted.
436  * Else if not at the end of the data the
437  * character after the cursor is deleted.
438  * Else the key is ignored.
439  * ignored if at the beginning of the data.
440  * Control Ignored.
441  * Shift Ignored.
442  * Alt Ignored.
443  */
444  virtual void handle_key_delete(SDL_Keymod modifier, bool& handled);
445 
446  /**
447  * Page up key.
448  *
449  * Unmodified Unhandled.
450  * Control Ignored.
451  * Shift Ignored.
452  * Alt Ignored.
453  */
454  virtual void handle_key_page_up(SDL_Keymod /*modifier*/, bool& /*handled*/)
455  {
456  }
457 
458  /**
459  * Page down key.
460  *
461  * Unmodified Unhandled.
462  * Control Ignored.
463  * Shift Ignored.
464  * Alt Ignored.
465  */
466  virtual void handle_key_page_down(SDL_Keymod /*modifier*/, bool& /*handled*/)
467  {
468  }
469 
470  /**
471  * Tab key.
472  *
473  * Unmodified Implementation defined.
474  * Control Implementation defined.
475  * Shift Implementation defined.
476  * Alt Implementation defined.
477  */
478  virtual void handle_key_tab(SDL_Keymod /*modifier*/, bool& /*handled*/)
479  {
480  }
481 
482 protected:
483  virtual void handle_commit(bool& handled,
484  const std::string& unicode);
485  virtual void handle_editing(bool& handled,
486  const std::string& unicode,
487  int32_t start,
488  int32_t length);
489 
490 private:
491  /**
492  * Text changed callback.
493  *
494  * This callback is called in key_press after the key_press event has been
495  * handled by the styled_widget. The parameters to the function are:
496  * - The widget invoking the callback
497  * - The new text of the textbox.
498  */
499  std::function<void(text_box_base* textbox, const std::string text)>
501 
502  /***** ***** ***** signal handlers ***** ****** *****/
503 
504  void signal_handler_middle_button_click(const event::ui_event event,
505  bool& handled);
506 
507  void signal_handler_sdl_key_down(const event::ui_event event,
508  bool& handled,
509  const SDL_Keycode key,
510  SDL_Keymod modifier);
511 
512  void signal_handler_sdl_text_input(const event::ui_event event,
513  bool& handled,
514  const std::string& unicode,
515  int32_t start,
516  int32_t len);
517 
518  void signal_handler_receive_keyboard_focus(const event::ui_event event);
519  void signal_handler_lose_keyboard_focus(const event::ui_event event);
520 };
521 
522 } // namespace gui2
bool is_composing() const
virtual void handle_key_tab(SDL_Keymod, bool &)
Tab key.
state_t
Note the order of the states must be the same as defined in settings.hpp.
void select_all()
Selects all text.
void set_text_changed_callback(std::function< void(text_box_base *textbox, const std::string text)> cb)
Set the text_changed callback.
Abstract base class for text items.
std::size_t cursor_timer_
point get_column_line(const point &position) const
std::string get_value() const
void goto_start_of_data(const bool select=false)
Moves the cursor to the beginning of the data.
unsigned short cursor_blink_rate_ms_
std::size_t get_selection_length() const
Generic file dialog.
Definition: field-fwd.hpp:22
void goto_end_of_data(const bool select=false)
Moves the cursor to the end of all text.
void set_font_style(const font::pango_text::FONT_STYLE font_style)
void set_maximum_width(const int width)
std::size_t selection_start_
Start of the selected text.
unsigned short cursor_alpha_
std::string text_cached_
Cached version of the text without any pending IME modifications.
std::size_t get_composition_start() const
std::function< void(text_box_base *textbox, const std::string text)> text_changed_callback_
Text changed callback.
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
void set_font_size(const unsigned font_size)
void set_ellipse_mode(const PangoEllipsizeMode ellipse_mode)
virtual void handle_key_page_up(SDL_Keymod, bool &)
Page up key.
std::size_t get_length() const
Holds a 2D point.
Definition: point.hpp:23
font::pango_text text_
The text entered in the widget.
Base class for all visible items.
Text class.
Definition: text.hpp:74
state_t state_
Current state of the widget.
const std::string & text() const
void set_maximum_height(const int height, const bool multiline)
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
std::size_t get_selection_start() const
const int font_size
Definition: button.cpp:40
Contains the implementation details for lexical_cast and shouldn&#39;t be used directly.
ui_event
The event send to the dispatcher.
Definition: handler.hpp:55