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