BsGUIInputBox.h 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. #pragma once
  2. #include "BsPrerequisites.h"
  3. #include "BsGUIElement.h"
  4. #include "BsImageSprite.h"
  5. #include "BsTextSprite.h"
  6. #include "BsVirtualInput.h"
  7. namespace BansheeEngine
  8. {
  9. /**
  10. * @brief Input box is a GUI element that accepts Unicode textual input. It can be
  11. * single or multi-line and handles various types of text manipulation.
  12. */
  13. class BS_EXPORT GUIInputBox : public GUIElement
  14. {
  15. /**
  16. * @brief Possible visual states the input box can be in.
  17. */
  18. enum class State
  19. {
  20. Normal,
  21. Hover,
  22. Focused
  23. };
  24. public:
  25. /**
  26. * Returns type name of the GUI element used for finding GUI element styles.
  27. */
  28. static const String& getGUITypeName();
  29. /**
  30. * Creates a new input box.
  31. *
  32. * @param multiline If true the input box can be of arbitrary height and will accept multiple lines of text.
  33. * @param styleName Optional style to use for the element. Style will be retrieved
  34. * from GUISkin of the GUIWidget the element is used on. If not specified
  35. * default style for this element is used.
  36. */
  37. static GUIInputBox* create(bool multiline = false, const String& styleName = StringUtil::BLANK);
  38. /**
  39. * Creates a new input box.
  40. *
  41. * @param multiline If true the input box can be of arbitrary height and will accept multiple lines of text.
  42. * @param options Options that allow you to control how is the element positioned and sized.
  43. * This will override any similar options set by style.
  44. * @param styleName Optional style to use for the element. Style will be retrieved
  45. * from GUISkin of the GUIWidget the element is used on. If not specified
  46. * default button style is used.
  47. */
  48. static GUIInputBox* create(bool multiline, const GUIOptions& options, const String& styleName = StringUtil::BLANK);
  49. /**
  50. * Creates a new single-line input box.
  51. *
  52. * @param options Options that allow you to control how is the element positioned and sized.
  53. * This will override any similar options set by style.
  54. * @param styleName Optional style to use for the element. Style will be retrieved
  55. * from GUISkin of the GUIWidget the element is used on. If not specified
  56. * default button style is used.
  57. */
  58. static GUIInputBox* create(const GUIOptions& options, const String& styleName = StringUtil::BLANK);
  59. /**
  60. * @brief Returns the text currently entered in the input box.
  61. */
  62. const WString& getText() const { return mText; }
  63. /**
  64. * @brief Sets the text inside the input box. This will replace any current text.
  65. */
  66. void setText(const WString& text);
  67. /**
  68. * @brief Sets an optional filter that can control what is allowed to be entered into the
  69. * input box. Filter should return true if the provided string is valid and false otherwise.
  70. * Set the filter to null to deactivate filtering.
  71. */
  72. void setFilter(std::function<bool(const WString&)> filter) { mFilter = filter; }
  73. /**
  74. * @copydoc GUIElement::setTint
  75. */
  76. virtual void setTint(const Color& color) override;
  77. /**
  78. * @copydoc GUIElement::getElementType
  79. */
  80. virtual ElementType _getElementType() const override { return ElementType::InputBox; }
  81. /**
  82. * @copydoc GUIElement::_getOptimalSize
  83. */
  84. virtual Vector2I _getOptimalSize() const override;
  85. /**
  86. * @brief Triggered whenever input text has changed.
  87. */
  88. Event<void(const WString&)> onValueChanged;
  89. /**
  90. * @brief Triggered whenever the input box receives focus.
  91. */
  92. Event<void()> onFocusGained;
  93. /**
  94. * @brief Triggered whenever the input box loses focus.
  95. */
  96. Event<void()> onFocusLost;
  97. protected:
  98. GUIInputBox(const String& styleName, const GUIDimensions& dimensions, bool multiline);
  99. virtual ~GUIInputBox();
  100. /**
  101. * @copydoc GUIElement::getNumRenderElements()
  102. */
  103. virtual UINT32 _getNumRenderElements() const override;
  104. /**
  105. * @copydoc GUIElement::getMaterial()
  106. */
  107. virtual const GUIMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
  108. /**
  109. * @copydoc GUIElement::getNumQuads()
  110. */
  111. virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
  112. /**
  113. * @copydoc GUIElement::fillBuffer()
  114. */
  115. virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad,
  116. UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;
  117. /**
  118. * @copydoc GUIElement::updateRenderElementsInternal()
  119. */
  120. virtual void updateRenderElementsInternal() override;
  121. /**
  122. * @copydoc GUIElement::updateBounds()
  123. */
  124. virtual void updateClippedBounds() override;
  125. /**
  126. * @copydoc GUIElement::mouseEvent
  127. */
  128. virtual bool _mouseEvent(const GUIMouseEvent& ev) override;
  129. /**
  130. * @copydoc GUIElement::textInputEvent
  131. */
  132. virtual bool _textInputEvent(const GUITextInputEvent& ev) override;
  133. /**
  134. * @copydoc GUIElement::commandEvent
  135. */
  136. virtual bool _commandEvent(const GUICommandEvent& ev) override;
  137. /**
  138. * @copydoc GUIElement::virtualButtonEvent
  139. */
  140. virtual bool _virtualButtonEvent(const GUIVirtualButtonEvent& ev) override;
  141. /**
  142. * @brief Returns how much to offset text due to scrolling.
  143. *
  144. * @note This is used when text is larger than the input box itself. As the
  145. * caret moves the text will scroll so that the caret remains visible, and
  146. * how much scroll is applied is determined by this value.
  147. */
  148. virtual Vector2I _getTextInputOffset() const override;
  149. /**
  150. * @brief Returns rectangle in which the text can be displayed, in local
  151. * coordinates (i.e. text will start at 0, 0).
  152. */
  153. virtual Rect2I _getTextInputRect() const override;
  154. /**
  155. * @copydoc GUIElement::_getRenderElementDepth
  156. */
  157. virtual UINT32 _getRenderElementDepth(UINT32 renderElementIdx) const override;
  158. /**
  159. * @copydoc GUIElement::_getRenderElementDepthRange
  160. */
  161. virtual UINT32 _getRenderElementDepthRange() const override;
  162. /**
  163. * @copydoc GUIElement::_hasCustomCursor
  164. */
  165. virtual bool _hasCustomCursor(const Vector2I position, CursorType& type) const override;
  166. /**
  167. * @copydoc GUIElement::getContextMenu
  168. */
  169. virtual GUIContextMenuPtr _getContextMenu() const override;
  170. private:
  171. /**
  172. * @brief Retrieves a sprite from a render element index, and a local render element index
  173. * that represents render element within the returned sprite.
  174. */
  175. Sprite* renderElemToSprite(UINT32 renderElemIdx, UINT32& localRenderElemIdx) const;
  176. /**
  177. * @brief Returns offset at which is the element with the provided render element index.
  178. * Offset is relative to parent widget.
  179. */
  180. Vector2I renderElemToOffset(UINT32 renderElemIdx) const;
  181. /**
  182. * @brief Returns a clip rectangle that can be used for clipping the render element
  183. * with the provided index. Rectangle is in local coordiantes relative to
  184. * element origin.
  185. */
  186. Rect2I renderElemToClipRect(UINT32 renderElemIdx) const;
  187. /**
  188. * @brief Inserts a new string into the current text at the specified index.
  189. */
  190. void insertString(UINT32 charIdx, const WString& string);
  191. /**
  192. * @brief Inserts a new character into the current text at the specified index.
  193. */
  194. void insertChar(UINT32 charIdx, UINT32 charCode);
  195. /**
  196. * @brief Erases a single character at the specified index.
  197. */
  198. void eraseChar(UINT32 charIdx);
  199. /**
  200. * @brief Deletes text that is currently selected.
  201. */
  202. void deleteSelectedText();
  203. /**
  204. * @brief Returns currently selected text.
  205. */
  206. WString getSelectedText();
  207. /**
  208. * @brief Shows the input caret. You must position the caret manually after showing it.
  209. */
  210. void showCaret();
  211. /**
  212. * @brief Hides the input caret.
  213. */
  214. void hideCaret();
  215. /**
  216. * @brief Shows selection with the specified anchor position. You must
  217. * position selection start and end before selection will actually render.
  218. * Anchor position determines selection behavior as the user moves the selection
  219. * with the keyboard.
  220. */
  221. void showSelection(UINT32 anchorCaretPos);
  222. /**
  223. * @brief Removes any active selection.
  224. */
  225. void clearSelection();
  226. /**
  227. * @brief Adjusts the text offset (scroll) so that the caret is visible.
  228. */
  229. void scrollTextToCaret();
  230. /**
  231. * @brief Clamps the text offset (scroll) so that the text fits in the
  232. * provided bounds nicely with minimal white space.
  233. */
  234. void clampScrollToBounds(Rect2I unclippedTextBounds);
  235. /**
  236. * @brief Returns offset at which to render the text. Relative to parent widget.
  237. */
  238. Vector2I getTextOffset() const;
  239. /**
  240. * @brief Returns rectangle used for clipping the text. Relative to element.
  241. */
  242. Rect2I getTextClipRect() const;
  243. /**
  244. * @brief Returns text sprite descriptor determining how is text sprite created.
  245. */
  246. TEXT_SPRITE_DESC getTextDesc() const;
  247. /**
  248. * @brief Returns currently active input box texture, depending on active state.
  249. */
  250. const HSpriteTexture& getActiveTexture() const;
  251. /**
  252. * @brief Returns currently active input box text color, depending on active state.
  253. */
  254. Color getActiveTextColor() const;
  255. /**
  256. * @brief Cuts currently selected text to clipboard.
  257. */
  258. void cutText();
  259. /**
  260. * @brief Copies currently selected text to clipboard.
  261. */
  262. void copyText();
  263. /**
  264. * @brief Inserts text from clipboard to current caret location.
  265. */
  266. void pasteText();
  267. private:
  268. static VirtualButton mCopyVB;
  269. static VirtualButton mPasteVB;
  270. static VirtualButton mCutVB;
  271. static VirtualButton mSelectAllVB;
  272. // Sprites
  273. ImageSprite* mImageSprite;
  274. TextSprite* mTextSprite;
  275. bool mIsMultiline;
  276. Vector2I mTextOffset;
  277. bool mHasFocus;
  278. bool mIsMouseOver;
  279. State mState;
  280. Color mColor;
  281. IMAGE_SPRITE_DESC mImageDesc;
  282. WString mText;
  283. std::function<bool(const WString&)> mFilter;
  284. bool mCaretShown;
  285. bool mSelectionShown;
  286. bool mDragInProgress;
  287. };
  288. }