Line data Source code
1 : /* Copyright (C) 2022 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #ifndef INCLUDED_CINPUT
19 : #define INCLUDED_CINPUT
20 :
21 : #include "gui/CGUISprite.h"
22 : #include "gui/ObjectBases/IGUIObject.h"
23 : #include "gui/ObjectBases/IGUIScrollBarOwner.h"
24 : #include "gui/SettingTypes/CGUIString.h"
25 : #include "lib/external_libraries/libsdl.h"
26 :
27 : #include <list>
28 : #include <vector>
29 :
30 : /**
31 : * Text field where you can input and edit the text.
32 : *
33 : * It doesn't use IGUITextOwner, because we don't need
34 : * any other features than word-wrapping, and we need to be
35 : * able to rapidly change the string.
36 : */
37 : class CInput : public IGUIObject, public IGUIScrollBarOwner
38 : {
39 0 : GUI_OBJECT(CInput)
40 :
41 : protected: // forwards
42 : struct SRow;
43 :
44 : public:
45 : CInput(CGUI& pGUI);
46 : virtual ~CInput();
47 :
48 : /**
49 : * @see IGUIObject#ResetStates()
50 : */
51 : virtual void ResetStates();
52 :
53 : // Check where the mouse is hovering, and get the appropriate text position.
54 : // return is the text-position index.
55 : int GetMouseHoveringTextPosition() const;
56 :
57 : // Same as above, but only on one row in X, and a given value, not the mouse's.
58 : // wanted is filled with x if the row didn't extend as far as the mouse pos.
59 : int GetXTextPosition(const std::list<SRow>::const_iterator& c, const float& x, float& wanted) const;
60 :
61 : protected:
62 :
63 : void SetupGeneratedPlaceholderText();
64 :
65 : /**
66 : * @see IGUIObject#HandleMessage()
67 : */
68 : virtual void HandleMessage(SGUIMessage& Message);
69 :
70 : /**
71 : * Handle events manually to catch keyboard inputting.
72 : */
73 : virtual InReaction ManuallyHandleKeys(const SDL_Event_* ev);
74 :
75 : /**
76 : * Handle events manually to catch keys which change the text.
77 : */
78 : virtual void ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode);
79 :
80 : /**
81 : * Handle events manually to catch keys which don't change the text.
82 : */
83 : virtual void ManuallyImmutableHandleKeyDownEvent(const SDL_Keycode keyCode);
84 :
85 : /**
86 : * Handle hotkey events (called by ManuallyHandleKeys)
87 : */
88 : virtual InReaction ManuallyHandleHotkeyEvent(const SDL_Event_* ev);
89 :
90 : /**
91 : * @see IGUIObject#UpdateCachedSize()
92 : */
93 : virtual void UpdateCachedSize();
94 :
95 : /**
96 : * Draws the Text
97 : */
98 : virtual void Draw(CCanvas2D& canvas);
99 :
100 : void DrawContent(CCanvas2D& canvas);
101 :
102 : /**
103 : * Calculate m_CharacterPosition
104 : * the main task for this function is to perfom word-wrapping
105 : * You input from which character it has been changed, because
106 : * if we add a character to the very last end, we don't want
107 : * process everything all over again! Also notice you can
108 : * specify a 'to' also, it will only be used though if a '\n'
109 : * appears, because then the word-wrapping won't change after
110 : * that.
111 : */
112 : void UpdateText(int from = 0, int to_before = -1, int to_after = -1);
113 :
114 : /**
115 : * Draws the text generated for placeholder.
116 : *
117 : * @param canvas Canvas to draw on.
118 : * @param clipping Clipping rectangle, don't even add a parameter
119 : * to get no clipping.
120 : */
121 : virtual void DrawPlaceholderText(CCanvas2D& canvas, const CRect& clipping = CRect());
122 :
123 : /**
124 : * Delete the current selection. Also places the pointer at the
125 : * crack between the two segments kept.
126 : */
127 : void DeleteCurSelection();
128 :
129 : /**
130 : * Is text selected? It can be denote two ways, m_iBufferPos_Tail
131 : * being -1 or the same as m_iBufferPos. This makes for clearer
132 : * code.
133 : */
134 : bool SelectingText() const;
135 :
136 : /// Get area of where text can be drawn.
137 : float GetTextAreaWidth();
138 :
139 : /// Called every time the auto-scrolling should be checked.
140 : void UpdateAutoScroll();
141 :
142 : /// Clear composed IME input when supported (SDL2 only).
143 : void ClearComposedText();
144 :
145 : /// Updates the buffer (cursor) position exposed to JS.
146 : void UpdateBufferPositionSetting();
147 : protected:
148 : /// Cursor position
149 : int m_iBufferPos;
150 : /// Cursor position we started to select from. (-1 if not selecting)
151 : /// (NB: Can be larger than m_iBufferPos if selecting from back to front.)
152 : int m_iBufferPos_Tail;
153 :
154 : /// If we're composing text with an IME
155 : bool m_ComposingText;
156 : /// The length and position of the current IME composition
157 : int m_iComposedLength, m_iComposedPos;
158 : /// The position to insert committed text
159 : int m_iInsertPos;
160 :
161 : // the outer vector is lines, and the inner is X positions
162 : // in a row. So that we can determine where characters are
163 : // placed. It's important because we need to know where the
164 : // pointer should be placed when the input control is pressed.
165 0 : struct SRow
166 : {
167 : // Where the Row starts
168 : int m_ListStart;
169 :
170 : // List of X values for each character.
171 : std::vector<float> m_ListOfX;
172 : };
173 :
174 : /**
175 : * List of rows to ease changing its size, so iterators stay valid.
176 : * For one-liners only one row is used.
177 : */
178 : std::list<SRow> m_CharacterPositions;
179 :
180 : // *** Things for a multi-lined input control *** //
181 :
182 : /**
183 : * When you change row with up/down, and the row you jump to does
184 : * not have anything at that X position, then it will keep the
185 : * m_WantedX position in mind when switching to the next row.
186 : * It will keep on being used until it reach a row which meets the
187 : * requirements.
188 : * 0.0f means not in use.
189 : */
190 : float m_WantedX;
191 :
192 : /**
193 : * If we are in the process of selecting a larger selection of text
194 : * using the mouse click (hold) and drag, this is true.
195 : */
196 : bool m_SelectingText;
197 :
198 : /**
199 : * Whether the cached text is currently valid (if not then SetupText will be called by Draw)
200 : */
201 : bool m_GeneratedPlaceholderTextValid;
202 :
203 : CGUIText m_GeneratedPlaceholderText;
204 :
205 : // *** Things for one-line input control *** //
206 : float m_HorizontalScroll;
207 :
208 : /// Used to store the previous time for flashing the cursor.
209 : double m_PrevTime;
210 :
211 : /// Cursor blink rate in seconds, if greater than 0.0.
212 : double m_CursorBlinkRate;
213 :
214 : /// If the cursor should be drawn or not.
215 : bool m_CursorVisState;
216 :
217 : static const CStr EventNameTextEdit;
218 : static const CStr EventNamePress;
219 : static const CStr EventNameTab;
220 :
221 : CGUISimpleSetting<i32> m_BufferPosition;
222 : CGUISimpleSetting<float> m_BufferZone;
223 : CGUISimpleSetting<CStrW> m_Caption;
224 : CGUISimpleSetting<CGUIString> m_PlaceholderText;
225 : CGUISimpleSetting<CStrW> m_Font;
226 : CGUISimpleSetting<CStrW> m_MaskChar;
227 : CGUISimpleSetting<bool> m_Mask;
228 : CGUISimpleSetting<i32> m_MaxLength;
229 : CGUISimpleSetting<bool> m_MultiLine;
230 : CGUISimpleSetting<bool> m_Readonly;
231 : CGUISimpleSetting<bool> m_ScrollBar;
232 : CGUISimpleSetting<CStr> m_ScrollBarStyle;
233 : CGUISimpleSetting<CGUISpriteInstance> m_Sprite;
234 : CGUISimpleSetting<CGUISpriteInstance> m_SpriteOverlay;
235 : CGUISimpleSetting<CGUISpriteInstance> m_SpriteSelectArea;
236 : CGUISimpleSetting<CGUIColor> m_TextColor;
237 : CGUISimpleSetting<CGUIColor> m_TextColorSelected;
238 : CGUISimpleSetting<CGUIColor> m_PlaceholderColor;
239 : };
240 :
241 : #endif // INCLUDED_CINPUT
|