guiTextEditCtrl.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _GUITEXTEDITCTRL_H_
  23. #define _GUITEXTEDITCTRL_H_
  24. #ifndef _GUITYPES_H_
  25. #include "gui/guiTypes.h"
  26. #endif
  27. class GuiTextEditSelection
  28. {
  29. private:
  30. U32 mBlockAnchor;
  31. U32 mBlockStart;
  32. U32 mBlockEnd;
  33. U32 mCursorPos;
  34. bool mCursorAtEOL;
  35. bool mIsFirstResponder;
  36. RectI mGlobalUnadjustedCursorRect;
  37. bool mCursorRendered;
  38. U32 mTextLength;
  39. U32 mNumFramesElapsed;
  40. U32 mTimeLastCursorFlipped;
  41. bool mCursorOn;
  42. public:
  43. GuiTextEditSelection();
  44. GuiTextEditSelection(const GuiTextEditSelection& selector);
  45. inline U32 getSelStart() const { return mBlockStart; }
  46. inline U32 getSelEnd() const { return mBlockEnd; }
  47. inline U32 getCursorPos() const { return mCursorPos; }
  48. inline void setCursorPosition(const U32 newPos) { mBlockAnchor = mCursorPos = mClamp(newPos, 0, mTextLength); clearSelection(); }
  49. inline void setTextLength(const U32 length) { mTextLength = length; if (mCursorPos > length) mCursorPos = length; }
  50. inline const bool isCursorRendered() const { return mCursorRendered; }
  51. inline Point2I getCursorCenter() const { return mGlobalUnadjustedCursorRect.centre(); }
  52. inline RectI getCursorRect() const { return mGlobalUnadjustedCursorRect; }
  53. inline void setCursorRect(RectI rect) { mGlobalUnadjustedCursorRect = rect; mCursorRendered = true; }
  54. inline void setCursorAtEOL(const bool isEOL) { mCursorAtEOL = isEOL; }
  55. inline void setFirstResponder(const bool isFirstResponder) { mIsFirstResponder = isFirstResponder; mCursorRendered = mCursorRendered && isFirstResponder; }
  56. inline void clearSelection() { mBlockStart = mBlockEnd = 0; }
  57. void selectTo(const U32 target);
  58. inline bool hasSelection() { return mBlockEnd > mBlockStart; }
  59. void onPreRender(const U32 time);
  60. bool renderIbeam(const Point2I& startPoint, const Point2I& extent, const string line, const U32 start, const U32 end, GuiControlProfile* profile, GFont* font);
  61. inline string getSelection(const string& fullText) { return hasSelection() ? fullText.substr(mBlockStart, mBlockEnd - mBlockStart) : string(); }
  62. void eraseSelection(string& fullText);
  63. void stepCursorForward();
  64. void stepCursorBackward();
  65. void resetCursorBlink();
  66. void selectWholeWord(const string& text);
  67. };
  68. class GuiTextEditTextBlock
  69. {
  70. private:
  71. RectI mGlobalBounds;
  72. S32 mTextOffsetX;
  73. S32 mTextScrollX;
  74. U32 mLineStartIbeamValue;
  75. string mText;
  76. public:
  77. GuiTextEditTextBlock();
  78. inline const U32 getStartValue() const { return mLineStartIbeamValue; }
  79. inline RectI getGlobalBounds() const { return mGlobalBounds; }
  80. inline Point2I getGlobalTextStart() { return Point2I(mGlobalBounds.point.x + mTextOffsetX - mTextScrollX, mGlobalBounds.point.y); }
  81. void render(const RectI& bounds, string line, U32 ibeamStartValue, GuiControlProfile* profile, GuiControlState currentState, GuiTextEditSelection& selector, AlignmentType align, GFont* font, bool overrideFontColor = false);
  82. U32 renderTextSection(const Point2I& startPoint, const U32 subStrStart, const U32 subStrLen, GuiControlProfile* profile, const GuiControlState currentState, GFont* font, bool isSelectedText = false, bool overrideFontColor = false);
  83. void performScrollJumpX(const S32 targetX, const S32 areaStart, const S32 areaEnd);
  84. U32 calculateIbeamPositionInLine(const S32 targetX, GFont* font);
  85. inline bool calculateCursorAtEOL(const U32 cursorPos) { return cursorPos == mText.length(); }
  86. inline void resetScroll() { mTextScrollX = 0; }
  87. void processScrollVelocity(const S32 delta, const S32 extentX, GFont* font);
  88. void processTextAlignment(const string line, GFont* font, AlignmentType align);
  89. };
  90. class GuiTextEditCtrl : public GuiControl
  91. {
  92. private:
  93. typedef GuiControl Parent;
  94. typedef vector<GuiTextEditTextBlock> TextBlockList;
  95. static U32 smNumAwake;
  96. protected:
  97. S32 mMaxStrLen;
  98. string mTextBuffer;
  99. TextBlockList mTextBlockList;
  100. StringTableEntry mReturnCommand;
  101. StringTableEntry mEscapeCommand;
  102. public:
  103. //input mode
  104. enum InputMode
  105. {
  106. AllText = 0,
  107. Decimal,
  108. Number,
  109. Alpha,
  110. AlphaNumeric
  111. };
  112. protected:
  113. InputMode mInputMode;
  114. bool mReturnCausesTab;
  115. //Edit Cursor
  116. GuiCursor* mEditCursor;
  117. bool mInsertOn;
  118. bool mMouseOver;
  119. GuiTextEditSelection mSelector;
  120. S32 mTextOffsetY;
  121. F32 mScrollVelocity;
  122. const U32 SCROLL_EDGE_SIZE = 20;
  123. const F32 SCROLL_VELOCITY_PER_SEC = 200.0f;
  124. U32 mTimeLastScrollProcess;
  125. bool mSuspendVerticalScrollJump;
  126. //undo members
  127. string mUndoText;
  128. GuiTextEditSelection mUndoSelector;
  129. void saveUndoState();
  130. bool mPasswordText;
  131. StringTableEntry mPasswordMask;
  132. /// If set, any non-ESC key is handled here or not at all
  133. bool mSinkAllKeyEvents;
  134. const RectI getGlobalInnerRect();
  135. S32 calculateIbeamPosition(const Point2I &offset);
  136. S32 calculateIbeamPosition(const Point2I& globalMousePoint, const RectI& globalInnerRect);
  137. S32 calculateIbeamPositionInLine(string line, const S32 startX, const S32 targetX);
  138. S32 getLineAdjustedIbeamPosition(S32 heightAdjustment);
  139. virtual bool handleKeyDownWithShift(const GuiEvent& event);
  140. virtual bool handleKeyDownWithCtrl(const GuiEvent& event);
  141. virtual bool handleKeyDownWithAlt(const GuiEvent& event);
  142. virtual bool handleKeyDownWithNoModifier(const GuiEvent& event);
  143. virtual bool handleCharacterInput(const GuiEvent& event);
  144. virtual bool handleEnterKey();
  145. virtual bool handleArrowKey(GuiDirection direction);
  146. virtual bool handleShiftArrowKey(GuiDirection direction);
  147. virtual bool handleBackSpace();
  148. virtual bool handleDelete();
  149. void modifySelectBlock(const U32 target);
  150. S32 textBufferWidth(StringBuffer buffer);
  151. StringBuffer truncate(StringBuffer buffer, StringBuffer terminationString, S32 width);
  152. public:
  153. GuiTextEditCtrl();
  154. DECLARE_CONOBJECT(GuiTextEditCtrl);
  155. static void initPersistFields();
  156. bool onAdd();
  157. void inspectPostApply();
  158. bool onWake();
  159. void onSleep();
  160. virtual const char* getText();
  161. virtual void getCursor(GuiCursor*& cursor, bool& showCursor, const GuiEvent& lastGuiEvent);
  162. virtual void setText(const UTF8* txt);
  163. virtual void setText(const UTF16* txt);
  164. inline virtual void setText(const string txt) { setText(txt.c_str()); }
  165. void enforceMaxLength();
  166. virtual void setTextID(S32 id);
  167. virtual void setTextID(const char *id);
  168. inline U32 getIbeamPosition() { return mSelector.getCursorPos(); }
  169. inline void setIbeamPosition(const U32 newPos) { mSelector.setCursorPosition(newPos); }
  170. void selectAllText();
  171. bool validate();
  172. const char *getScriptValue();
  173. void setScriptValue(const char *value);
  174. bool onKeyDown(const GuiEvent &event);
  175. void onTouchDown(const GuiEvent &event);
  176. void onTouchDragged(const GuiEvent &event);
  177. void onTouchUp(const GuiEvent& event);
  178. void onTouchEnter(const GuiEvent& event);
  179. void onTouchLeave(const GuiEvent& event);
  180. void onMouseWheelUp(const GuiEvent& event);
  181. void onMouseWheelDown(const GuiEvent& event);
  182. void onCopy(bool andCut);
  183. void onPaste();
  184. void onUndo();
  185. virtual void setFirstResponder();
  186. virtual void onLoseFirstResponder();
  187. void parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent);
  188. bool hasText();
  189. void onStaticModified(const char* slotName);
  190. void onPreRender();
  191. void onRender(Point2I offset, const RectI &updateRect);
  192. virtual void renderLineList(const Point2I& offset, const Point2I& extent, const S32 startOffsetY, const vector<string> lineList, GuiControlProfile* profile, const TextRotationOptions rot = tRotateNone);
  193. GuiControlState getCurrentState();
  194. const ColorI& getCurrentFontColor();
  195. bool inputModeValidate(const U16 key, S32 cursorPos);
  196. void keyDenied();
  197. void execConsoleCallback();
  198. inline void setEscapeCommand(const char *newCmd) { mEscapeCommand = newCmd ? StringTable->insert(newCmd) : StringTable->EmptyString; }
  199. inline const char * getEscapeCommand() { return mEscapeCommand; }
  200. inline void setReturnCausesTab(bool setting) { mReturnCausesTab = setting; }
  201. inline bool getReturnCausesTab() { return mReturnCausesTab; }
  202. inline void setSinkAllKeyEvents(bool setting) { mSinkAllKeyEvents = setting; }
  203. inline bool getSinkAllKeyEvents() { return mSinkAllKeyEvents; }
  204. inline void setIsPassword(bool setting) { mPasswordText = setting; }
  205. inline bool getIsPassword() { return mPasswordText; }
  206. void setMaxLength(S32 max);
  207. inline S32 getMaxLength() { return mMaxStrLen; }
  208. static bool setMaxLengthProperty(void* obj, const char* data) { static_cast<GuiTextEditCtrl*>(obj)->setMaxLength(dAtoi(data)); return true; }
  209. void setInputMode(const InputMode mode);
  210. inline InputMode getInputMode() { return mInputMode; }
  211. static bool setInputMode(void* obj, const char* data)
  212. {
  213. // Fetch body type.
  214. const InputMode mode = getInputModeEnum(data);
  215. // Check for error.
  216. if (mode < AllText || mode > AlphaNumeric)
  217. return false;
  218. static_cast<GuiTextEditCtrl*>(obj)->setInputMode(mode);
  219. return true;
  220. }
  221. static const char* getInputMode(void* obj, const char* data) { return getInputModeDescription(static_cast<GuiTextEditCtrl*>(obj)->getInputMode()); }
  222. static bool writeInputMode(void* obj, StringTableEntry pFieldName) { return static_cast<GuiTextEditCtrl*>(obj)->getInputMode() != AllText; }
  223. static InputMode getInputModeEnum(const char* label);
  224. static const char* getInputModeDescription(const InputMode mode);
  225. string applyPasswordMasking();
  226. void adjustScrollVelocity(const Point2I& globalMousePoint, const RectI& globalInnerRect);
  227. void performScrollJumpY();
  228. void processScrollVelocity();
  229. enum Constants { MAX_STRING_LENGTH = 1024 };
  230. private:
  231. bool tabNext();
  232. bool tabPrev();
  233. };
  234. #endif //_GUI_TEXTEDIT_CTRL_H