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/widgets/text_box_base.hpp" 18 19 namespace gui2 20 { 21 namespace implementation 22 { 23 struct builder_text_box; 24 } 25 26 // ------------ WIDGET -----------{ 27 28 /** 29 * Class for text input history. 30 * 31 * The history of text items can be stored in the preferences. This class 32 * handles that. Every item needs an id by which the history is loaded and 33 * saved. 34 */ 35 class text_history 36 { 37 public: 38 /** 39 * Gets history that matches id. 40 * 41 * @param id The id of the history to look for. 42 * @param enabled The enabled state of the history. 43 * 44 * @returns The history object. 45 */ 46 static text_history get_history(const std::string& id, const bool enabled); 47 text_history()48 text_history() : history_(0), pos_(0), enabled_(false) 49 { 50 } 51 52 /** 53 * Push string into the history. 54 * 55 * If the string is empty or the same as the last item in the history this 56 * function is a nop. 57 * 58 * @param text The text to push in the history. 59 */ 60 void push(const std::string& text); 61 62 /** 63 * One step up in the history. 64 * 65 * Pushes text to the history if at the end. 66 * 67 * @param text The text to push in the history. 68 * 69 * @returns The current value of the history. 70 */ 71 std::string up(const std::string& text = ""); 72 73 /** 74 * One step down in the history. 75 * 76 * Pushes text to the history if at the end. 77 * 78 * @param text The text to push in the history. 79 * 80 * @returns The current value of the history. 81 */ 82 std::string down(const std::string& text = ""); 83 84 /** 85 * Gets the current history value. 86 * 87 * @returns If enabled return the current history 88 * position, otherwise an empty string is 89 * returned. 90 */ 91 std::string get_value() const; 92 93 /***** ***** ***** setters / getters for members ***** ****** *****/ 94 set_enabled(bool enabled=true)95 void set_enabled(bool enabled = true) 96 { 97 enabled_ = enabled; 98 } get_enabled() const99 bool get_enabled() const 100 { 101 return enabled_; 102 } 103 104 private: text_history(std::vector<std::string> * history,const bool enabled)105 text_history(std::vector<std::string>* history, const bool enabled) 106 : history_(history), pos_(history->size()), enabled_(enabled) 107 { 108 } 109 110 /** The items in the history. */ 111 std::vector<std::string>* history_; 112 113 /** The current position in the history. */ 114 unsigned pos_; 115 116 /** Is the history enabled. */ 117 bool enabled_; 118 }; 119 120 /** Class for a single line text area. */ 121 class text_box : public text_box_base 122 { 123 friend struct implementation::builder_text_box; 124 125 public: 126 explicit text_box(const implementation::builder_styled_widget& builder); 127 128 /** Saves the text in the widget to the history. */ save_to_history()129 void save_to_history() 130 { 131 history_.push(get_value()); 132 } 133 134 /***** ***** ***** setters / getters for members ***** ****** *****/ 135 set_history(const std::string & id)136 void set_history(const std::string& id) 137 { 138 history_ = text_history::get_history(id, true); 139 } 140 set_max_input_length(const size_t length)141 void set_max_input_length(const size_t length) 142 { 143 max_input_length_ = length; 144 } 145 set_hint_data(const std::string & text,const std::string & image)146 void set_hint_data(const std::string& text, const std::string& image) 147 { 148 hint_text_ = text; 149 hint_image_ = image; 150 151 update_canvas(); 152 } 153 clear()154 void clear() 155 { 156 set_value(""); 157 } 158 159 protected: 160 /***** ***** ***** ***** layout functions ***** ***** ***** *****/ 161 162 /** See @ref widget::place. */ 163 virtual void place(const point& origin, const point& size) override; 164 165 /***** ***** ***** ***** Inherited ***** ***** ***** *****/ 166 167 /** See @ref styled_widget::update_canvas. */ 168 virtual void update_canvas() override; 169 170 /** Inherited from text_box_base. */ goto_end_of_line(const bool select=false)171 void goto_end_of_line(const bool select = false) override 172 { 173 goto_end_of_data(select); 174 } 175 176 /** Inherited from text_box_base. */ goto_start_of_line(const bool select=false)177 void goto_start_of_line(const bool select = false) override 178 { 179 goto_start_of_data(select); 180 } 181 182 /** Inherited from text_box_base. */ 183 void delete_char(const bool before_cursor) override; 184 185 /** Inherited from text_box_base. */ 186 void delete_selection() override; 187 188 void handle_mouse_selection(point mouse, const bool start_selection); 189 190 private: 191 /** The history text for this widget. */ 192 text_history history_; 193 194 /** The maximum length of the text input. */ 195 size_t max_input_length_; 196 197 /** 198 * The x offset in the widget where the text starts. 199 * 200 * This value is needed to translate a location in the widget to a location 201 * in the text. 202 */ 203 unsigned text_x_offset_; 204 205 /** 206 * The y offset in the widget where the text starts. 207 * 208 * Needed to determine whether a click is on the text. 209 */ 210 unsigned text_y_offset_; 211 212 /** 213 * The height of the text itself. 214 * 215 * Needed to determine whether a click is on the text. 216 */ 217 unsigned text_height_; 218 219 /** Updates text_x_offset_ and text_y_offset_. */ 220 void update_offsets(); 221 222 /** Is the mouse in dragging mode, this affects selection in mouse move */ 223 bool dragging_; 224 225 /** Helper text to display (such as "Search") if the text box is empty. */ 226 std::string hint_text_; 227 228 /** Image (such as a magnifying glass) that accompanies the help text. */ 229 std::string hint_image_; 230 231 /** 232 * Inherited from text_box_base. 233 * 234 * Unmodified Unhandled. 235 * Control Ignored. 236 * Shift Ignored. 237 * Alt Ignored. 238 */ handle_key_up_arrow(SDL_Keymod,bool &)239 void handle_key_up_arrow(SDL_Keymod /*modifier*/, bool& /*handled*/) override 240 { 241 } 242 243 /** 244 * Inherited from text_box_base. 245 * 246 * Unmodified Unhandled. 247 * Control Ignored. 248 * Shift Ignored. 249 * Alt Ignored. 250 */ handle_key_down_arrow(SDL_Keymod,bool &)251 void handle_key_down_arrow(SDL_Keymod /*modifier*/, bool& /*handled*/) override 252 { 253 } 254 255 /** 256 * Goes one item up in the history. 257 * 258 * @returns True if there's a history, false otherwise. 259 */ 260 bool history_up(); 261 262 /** 263 * Goes one item down in the history. 264 * 265 * @returns True if there's a history, false otherwise. 266 */ 267 bool history_down(); 268 269 /** Inherited from text_box_base. */ 270 void handle_key_tab(SDL_Keymod modifier, bool& handled) override; 271 272 /** Inherited from text_box_base. */ 273 void handle_key_clear_line(SDL_Keymod modifier, bool& handled) override; 274 275 public: 276 /** Static type getter that does not rely on the widget being constructed. */ 277 static const std::string& type(); 278 279 private: 280 /** Inherited from styled_widget, implemented by REGISTER_WIDGET. */ 281 virtual const std::string& get_control_type() const override; 282 283 /***** ***** ***** signal handlers ***** ****** *****/ 284 285 void signal_handler_mouse_motion(const event::ui_event event, 286 bool& handled, 287 const point& coordinate); 288 289 void signal_handler_left_button_down(const event::ui_event event, 290 bool& handled); 291 292 void signal_handler_left_button_up(const event::ui_event event, 293 bool& handled); 294 295 void signal_handler_left_button_double_click(const event::ui_event event, 296 bool& handled); 297 }; 298 299 // }---------- DEFINITION ---------{ 300 301 struct text_box_definition : public styled_widget_definition 302 { 303 explicit text_box_definition(const config& cfg); 304 305 struct resolution : public resolution_definition 306 { 307 explicit resolution(const config& cfg); 308 309 typed_formula<unsigned> text_x_offset; 310 typed_formula<unsigned> text_y_offset; 311 }; 312 }; 313 314 // }---------- BUILDER -----------{ 315 316 namespace implementation 317 { 318 319 struct builder_text_box : public builder_styled_widget 320 { 321 public: 322 explicit builder_text_box(const config& cfg); 323 324 using builder_styled_widget::build; 325 326 widget* build() const; 327 328 std::string history; 329 330 size_t max_input_length; 331 332 t_string hint_text; 333 std::string hint_image; 334 }; 335 336 } // namespace implementation 337 338 // }------------ END -------------- 339 340 } // namespace gui2 341