1 /*
2  * This source file is part of libRocket, the HTML/CSS Interface Middleware
3  *
4  * For the latest information, see http://www.librocket.com
5  *
6  * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  *
26  */
27 
28 #ifndef ROCKETCONTROLSWIDGETTEXTINPUT_H
29 #define ROCKETCONTROLSWIDGETTEXTINPUT_H
30 
31 #include "../../Include/Rocket/Core/EventListener.h"
32 #include "../../Include/Rocket/Core/Geometry.h"
33 #include "../../Include/Rocket/Core/WString.h"
34 #include "../../Include/Rocket/Core/Vertex.h"
35 
36 namespace Rocket {
37 namespace Core {
38 
39 class ElementText;
40 
41 }
42 
43 namespace Controls {
44 
45 class ElementFormControl;
46 
47 /**
48 	An abstract widget for editing and navigating around a text field.
49 
50 	@author Peter Curry
51  */
52 
53 class WidgetTextInput : public Core::EventListener
54 {
55 public:
56 	WidgetTextInput(ElementFormControl* parent);
57 	virtual ~WidgetTextInput();
58 
59 	/// Sets the value of the text field.
60 	/// @param[in] value The new value to set on the text field.
61 	virtual void SetValue(const Core::String& value);
62 
63 	/// Sets the maximum length (in characters) of this text field.
64 	/// @param[in] max_length The new maximum length of the text field. A number lower than zero will mean infinite characters.
65 	void SetMaxLength(int max_length);
66 	/// Returns the maximum length (in characters) of this text field.
67 	/// @return The maximum number of characters allowed in this text field.
68 	int GetMaxLength() const;
69 
70 	/// Update the colours of the selected text.
71 	void UpdateSelectionColours();
72 
73 	/// Updates the cursor, if necessary.
74 	void OnUpdate();
75 	/// Renders the cursor, if it is visible.
76 	void OnRender();
77 	/// Formats the widget's internal content.
78 	void OnLayout();
79 
80 	/// Returns the input element's underlying text element.
81 	Core::ElementText* GetTextElement();
82 	/// Returns the input element's maximum allowed text dimensions.
83 	const Rocket::Core::Vector2f& GetTextDimensions() const;
84 
85 protected:
86 	/// Processes the "keydown" and "textinput" event to write to the input field, and the "focus" and
87 	/// "blur" to set the state of the cursor.
88 	virtual void ProcessEvent(Core::Event& event);
89 
90 	/// Adds a new character to the string at the cursor position.
91 	/// @param[in] character The character to add to the string.
92 	/// @return True if the character was successfully added, false otherwise.
93 	bool AddCharacter(Rocket::Core::word character);
94 	/// Deletes a character from the string.
95 	/// @param[in] backward True to delete a character behind the cursor, false for in front of the cursor.
96 	/// @return True if a character was deleted, false otherwise.
97 	bool DeleteCharacter(bool back);
98 	/// Returns true if the given character is permitted in the input field, false if not.
99 	/// @param[in] character The character to validate.
100 	/// @return True if the character is allowed, false if not.
101 	virtual bool IsCharacterValid(Rocket::Core::word character) = 0;
102 	/// Called when the user pressed enter.
103 	virtual void LineBreak() = 0;
104 
105 	/// Returns the absolute index of the cursor.
106 	int GetCursorIndex() const;
107 
108 	/// Gets the parent element containing the widget.
109 	Core::Element* GetElement();
110 
111 	/// Dispatches a change event to the widget's element.
112 	void DispatchChangeEvent(bool linebreak = false);
113 
114 private:
115 	/// Moves the cursor along the current line.
116 	/// @param[in] x How far to move the cursor.
117 	/// @param[in] select True if the movement will also move the selection cursor, false if not.
118 	void MoveCursorHorizontal(int distance, bool select);
119 	/// Moves the cursor up and down the text field.
120 	/// @param[in] x How far to move the cursor.
121 	/// @param[in] select True if the movement will also move the selection cursor, false if not.
122 	void MoveCursorVertical(int distance, bool select);
123 
124 	/// Updates the absolute cursor index from the relative cursor indices.
125 	void UpdateAbsoluteCursor();
126 	/// Updates the relative cursor indices from the absolute cursor index.
127 	void UpdateRelativeCursor();
128 
129 	/// Calculates the line index under a specific vertical position.
130 	/// @param[in] position The position to query.
131 	/// @return The index of the line under the mouse cursor.
132 	int CalculateLineIndex(float position);
133 	/// Calculates the character index along a line under a specific horizontal position.
134 	/// @param[in] line_index The line to query.
135 	/// @param[in] position The position to query.
136 	/// @return The index of the character under the mouse cursor.
137 	int CalculateCharacterIndex(int line_index, float position);
138 
139 	/// Shows or hides the cursor.
140 	/// @param[in] show True to show the cursor, false to hide it.
141 	/// @param[in] move_to_cursor True to force the cursor to be visible, false to not scroll the widget.
142 	void ShowCursor(bool show, bool move_to_cursor = true);
143 
144 	/// Formats the element, laying out the text and inserting scrollbars as appropriate.
145 	void FormatElement();
146 	/// Formats the input element's text field.
147 	/// @return The content area of the element.
148 	Rocket::Core::Vector2f FormatText();
149 
150 	/// Generates the text cursor.
151 	void GenerateCursor();
152 	/// Updates the position to render the cursor.
153 	void UpdateCursorPosition();
154 
155 	/// Expand or shrink the text selection to the position of the cursor.
156 	/// @param[in] selecting True if the new position of the cursor should expand / contract the selection area, false if it should only set the anchor for future selections.
157 	void UpdateSelection(bool selecting);
158 	/// Removes the selection of text.
159 	void ClearSelection();
160 	/// Deletes all selected text and removes the selection.
161 	void DeleteSelection();
162 	/// Copies the selection (if any) to the clipboard.
163 	void CopySelection();
164 
165 	/// Split one line of text into three parts, based on the current selection.
166 	/// @param[out] pre_selection The section of unselected text before any selected text on the line.
167 	/// @param[out] selection The section of selected text on the line.
168 	/// @param[out] post_selection The section of unselected text after any selected text on the line. If there is no selection on the line, then this will be empty.
169 	/// @param[in] line The text making up the line.
170 	/// @param[in] line_begin The absolute index at the beginning of the line.
171 	void GetLineSelection(Core::WString& pre_selection, Core::WString& selection, Core::WString& post_selection, const Core::WString& line, int line_begin);
172 
173 	struct Line
174 	{
175 		// The contents of the line (including the trailing endline, if that terminated the line).
176 		Core::WString content;
177 		// The length of the editable characters on the line (excluding any trailing endline).
178 		int content_length;
179 
180 		// The number of extra characters at the end of the content that are not present in the actual value; in the
181 		// case of a soft return, this may be negative.
182 		int extra_characters;
183 	};
184 
185 	ElementFormControl* parent;
186 
187 	Core::ElementText* text_element;
188 	Core::ElementText* selected_text_element;
189 	Rocket::Core::Vector2f internal_dimensions;
190 	Rocket::Core::Vector2f scroll_offset;
191 
192 	typedef std::vector< Line > LineList;
193 	LineList lines;
194 
195 	int max_length;
196 
197 	int edit_index;
198 
199 	int absolute_cursor_index;
200 	int cursor_line_index;
201 	int cursor_character_index;
202 
203 	// Selection. The start and end indices of the selection are in absolute coordinates.
204 	Core::Element* selection_element;
205 	int selection_anchor_index;
206 	int selection_begin_index;
207 	int selection_length;
208 
209 	// The colour of the background of selected text.
210 	Rocket::Core::Colourb selection_colour;
211 	// The selection background.
212 	Core::Geometry selection_geometry;
213 
214 	// Cursor visibility and timings.
215 	float cursor_timer;
216 	bool cursor_visible;
217 	bool keyboard_showed;
218 	/// Activate or deactivate keyboard (for touchscreen devices)
219 	/// @param[in] active True if need activate keyboard, false if need deactivate.
220 	void SetKeyboardActive(bool active);
221 
222 	float last_update_time;
223 
224 	// The cursor geometry.
225 	float ideal_cursor_position;
226 	Rocket::Core::Vector2f cursor_position;
227 	Rocket::Core::Vector2f cursor_size;
228 	Core::Geometry cursor_geometry;
229 };
230 
231 }
232 }
233 
234 #endif
235