BsGUIInputBox.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsPrerequisites.h"
  5. #include "BsGUIElement.h"
  6. #include "BsImageSprite.h"
  7. #include "BsTextSprite.h"
  8. #include "BsVirtualInput.h"
  9. namespace BansheeEngine
  10. {
  11. /** @addtogroup GUI
  12. * @{
  13. */
  14. /**
  15. * Input box is a GUI element that accepts Unicode textual input. It can be single or multi-line and handles various
  16. * types of text manipulation.
  17. */
  18. class BS_EXPORT GUIInputBox : public GUIElement
  19. {
  20. /** Possible visual states the input box can be in. */
  21. enum class State
  22. {
  23. Normal,
  24. Hover,
  25. Focused
  26. };
  27. public:
  28. /** Returns type name of the GUI element used for finding GUI element styles. */
  29. static const String& getGUITypeName();
  30. /**
  31. * Creates a new input box.
  32. *
  33. * @param[in] multiline If true the input box can be of arbitrary height and will accept multiple lines of
  34. * text.
  35. * @param[in] styleName Optional style to use for the element. Style will be retrieved from GUISkin of the
  36. * GUIWidget the element is used on. If not specified default style for this element
  37. * is used.
  38. */
  39. static GUIInputBox* create(bool multiline = false, const String& styleName = StringUtil::BLANK);
  40. /**
  41. * Creates a new input box.
  42. *
  43. * @param[in] multiline If true the input box can be of arbitrary height and will accept multiple lines of
  44. * text.
  45. * @param[in] options Options that allow you to control how is the element positioned and sized. This will
  46. * override any similar options set by style.
  47. * @param[in] styleName Optional style to use for the element. Style will be retrieved from GUISkin of the
  48. * GUIWidget the element is used on. If not specified default button style is used.
  49. */
  50. static GUIInputBox* create(bool multiline, const GUIOptions& options, const String& styleName = StringUtil::BLANK);
  51. /**
  52. * Creates a new single-line input box.
  53. *
  54. * @param[in] options Options that allow you to control how is the element positioned and sized. This will
  55. * override any similar options set by style.
  56. * @param[in] styleName Optional style to use for the element. Style will be retrieved from GUISkin of the
  57. * GUIWidget the element is used on. If not specified default button style is used.
  58. */
  59. static GUIInputBox* create(const GUIOptions& options, const String& styleName = StringUtil::BLANK);
  60. /** Returns the text currently entered in the input box. */
  61. const WString& getText() const { return mText; }
  62. /** Sets the text inside the input box. This will replace any current text. */
  63. void setText(const WString& text);
  64. /**
  65. * Sets an optional filter that can control what is allowed to be entered into the input box. Filter should return
  66. * true if the provided string is valid and false otherwise. Set the filter to null to deactivate filtering.
  67. */
  68. void setFilter(std::function<bool(const WString&)> filter) { mFilter = filter; }
  69. /** Triggered whenever input text has changed. */
  70. Event<void(const WString&)> onValueChanged;
  71. /** Triggered when the user hits the Enter key with the input box in focus. */
  72. Event<void()> onConfirm;
  73. public: // ***** INTERNAL ******
  74. /** @name Internal
  75. * @{
  76. */
  77. /** @copydoc GUIElement::_getElementType */
  78. ElementType _getElementType() const override { return ElementType::InputBox; }
  79. /** @copydoc GUIElement::_getOptimalSize */
  80. Vector2I _getOptimalSize() const override;
  81. /** @} */
  82. protected:
  83. GUIInputBox(const String& styleName, const GUIDimensions& dimensions, bool multiline);
  84. virtual ~GUIInputBox();
  85. /** @copydoc GUIElement::_getNumRenderElements() */
  86. UINT32 _getNumRenderElements() const override;
  87. /** @copydoc GUIElement::_getMaterial() */
  88. const SpriteMaterialInfo& _getMaterial(UINT32 renderElementIdx, SpriteMaterial** material) const override;
  89. /** @copydoc GUIElement::_getMeshSize() */
  90. void _getMeshInfo(UINT32 renderElementIdx, UINT32& numVertices, UINT32& numIndices, GUIMeshType& type) const override;
  91. /** @copydoc GUIElement::_fillBuffer() */
  92. void _fillBuffer(UINT8* vertices, UINT32* indices, UINT32 vertexOffset, UINT32 indexOffset,
  93. UINT32 maxNumVerts, UINT32 maxNumIndices, UINT32 renderElementIdx) const override;
  94. /** @copydoc GUIElement::updateRenderElementsInternal() */
  95. void updateRenderElementsInternal() override;
  96. /** @copydoc GUIElement::updateClippedBounds() */
  97. void updateClippedBounds() override;
  98. /** @copydoc GUIElement::_mouseEvent */
  99. bool _mouseEvent(const GUIMouseEvent& ev) override;
  100. /** @copydoc GUIElement::_textInputEvent */
  101. bool _textInputEvent(const GUITextInputEvent& ev) override;
  102. /** @copydoc GUIElement::_commandEvent */
  103. bool _commandEvent(const GUICommandEvent& ev) override;
  104. /** @copydoc GUIElement::_virtualButtonEvent */
  105. bool _virtualButtonEvent(const GUIVirtualButtonEvent& ev) override;
  106. /**
  107. * Returns how much to offset text due to scrolling.
  108. *
  109. * @note
  110. * This is used when text is larger than the input box itself. As the caret moves the text will scroll so that the
  111. * caret remains visible, and how much scroll is applied is determined by this value.
  112. */
  113. Vector2I _getTextInputOffset() const override;
  114. /** Returns rectangle in which the text can be displayed, in local coordinates (text will start at 0, 0). */
  115. Rect2I _getTextInputRect() const override;
  116. /** @copydoc GUIElement::_getRenderElementDepth */
  117. UINT32 _getRenderElementDepth(UINT32 renderElementIdx) const override;
  118. /** @copydoc GUIElement::_getRenderElementDepthRange */
  119. UINT32 _getRenderElementDepthRange() const override;
  120. /** @copydoc GUIElement::_hasCustomCursor */
  121. bool _hasCustomCursor(const Vector2I position, CursorType& type) const override;
  122. /** @copydoc GUIElement::_getContextMenu */
  123. SPtr<GUIContextMenu> _getContextMenu() const override;
  124. private:
  125. /**
  126. * Retrieves a sprite from a render element index, and a local render element index that represents render element
  127. * within the returned sprite.
  128. */
  129. Sprite* renderElemToSprite(UINT32 renderElemIdx, UINT32& localRenderElemIdx) const;
  130. /**
  131. * Returns offset at which is the element with the provided render element index. Offset is relative to parent
  132. * widget.
  133. */
  134. Vector2I renderElemToOffset(UINT32 renderElemIdx) const;
  135. /**
  136. * Returns a clip rectangle that can be used for clipping the render element with the provided index. Rectangle is
  137. * in local coordiantes relative to element origin.
  138. */
  139. Rect2I renderElemToClipRect(UINT32 renderElemIdx) const;
  140. /** Inserts a new string into the current text at the specified index. */
  141. void insertString(UINT32 charIdx, const WString& string);
  142. /** Inserts a new character into the current text at the specified index. */
  143. void insertChar(UINT32 charIdx, UINT32 charCode);
  144. /** Erases a single character at the specified index. */
  145. void eraseChar(UINT32 charIdx);
  146. /**
  147. * Deletes text that is currently selected.
  148. *
  149. * @param[in] internal If internal not filter will be applied after the text is deleted, and no event will be
  150. * triggered either.
  151. */
  152. void deleteSelectedText(bool internal = false);
  153. /** Returns currently selected text. */
  154. WString getSelectedText();
  155. /** Shows the input caret. You must position the caret manually after showing it. */
  156. void showCaret();
  157. /** Hides the input caret. */
  158. void hideCaret();
  159. /**
  160. * Shows selection with the specified anchor position. You must position selection start and end before selection
  161. * will actually render. Anchor position determines selection behavior as the user moves the selection with the
  162. * keyboard.
  163. */
  164. void showSelection(UINT32 anchorCaretPos);
  165. /** Removes any active selection. */
  166. void clearSelection();
  167. /** Adjusts the text offset (scroll) so that the caret is visible. */
  168. void scrollTextToCaret();
  169. /** Clamps the text offset (scroll) so that the text fits in the provided bounds nicely with minimal white space. */
  170. void clampScrollToBounds(Rect2I unclippedTextBounds);
  171. /** Returns offset at which to render the text. Relative to parent widget. */
  172. Vector2I getTextOffset() const;
  173. /** Returns rectangle used for clipping the text. Relative to element. */
  174. Rect2I getTextClipRect() const;
  175. /** Returns text sprite descriptor determining how is text sprite created. */
  176. TEXT_SPRITE_DESC getTextDesc() const;
  177. /** Returns currently active input box texture, depending on active state. */
  178. const HSpriteTexture& getActiveTexture() const;
  179. /** Returns currently active input box text color, depending on active state. */
  180. Color getActiveTextColor() const;
  181. /** Cuts currently selected text to clipboard. */
  182. void cutText();
  183. /** Copies currently selected text to clipboard. */
  184. void copyText();
  185. /** Inserts text from clipboard to current caret location. */
  186. void pasteText();
  187. private:
  188. static VirtualButton mCopyVB;
  189. static VirtualButton mPasteVB;
  190. static VirtualButton mCutVB;
  191. static VirtualButton mSelectAllVB;
  192. // Sprites
  193. ImageSprite* mImageSprite;
  194. TextSprite* mTextSprite;
  195. bool mIsMultiline;
  196. Vector2I mTextOffset;
  197. bool mHasFocus;
  198. bool mIsMouseOver;
  199. State mState;
  200. IMAGE_SPRITE_DESC mImageDesc;
  201. WString mText;
  202. std::function<bool(const WString&)> mFilter;
  203. bool mCaretShown;
  204. bool mSelectionShown;
  205. bool mDragInProgress;
  206. };
  207. /** @} */
  208. }