1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "BsPrerequisites.h"
6#include "2D/BsTextSprite.h"
7
8namespace bs
9{
10 /** @addtogroup GUI-Internal
11 * @{
12 */
13
14 /** Represents a single line of text used by the input tools. */
15 class BS_EXPORT GUIInputLineDesc
16 {
17 public:
18 /**
19 * Constructs a new input line description.
20 *
21 * @param[in] startChar Index of the first character on the line.
22 * @param[in] endChar Index of the last character on the line.
23 * @param[in] lineHeight Height of the line in pixels.
24 * @param[in] lineYStart Vertical offset from the top of the text to the start of this line (0 for first
25 * line usually).
26 * @param[in] includesNewline True if the lines end character is a newline character.
27 */
28 GUIInputLineDesc(UINT32 startChar, UINT32 endChar, UINT32 lineHeight, INT32 lineYStart, bool includesNewline);
29
30 /**
31 * Returns index of the last character on the line. If lines contains a newline character it will be returned unless
32 * you set @p includeNewLine to false, in which case the next end-most character is returned. (If newline is the
33 * only character on the line, its index will still be returned).
34 */
35 UINT32 getEndChar(bool includeNewline = true) const;
36
37 /** Returns index of the first character on the line. */
38 UINT32 getStartChar() const { return mStartChar; }
39
40 /** Returns line height in pixels. */
41 UINT32 getLineHeight() const { return mLineHeight; }
42
43 /** Returns vertical offset from the top of the text to the start of this line (0 for first line usually). */
44 INT32 getLineYStart() const { return mLineYStart; }
45
46 /**
47 * Checks is the specified character index a newline. Character index is a global character index, not relative to
48 * the start character index of this line. If the index is out of range of this line character indices, it will
49 * always return false.
50 */
51 bool isNewline(UINT32 charIdx) const;
52
53 /** Returns true if the last character on this line is a newline. */
54 bool hasNewlineChar() const { return mIncludesNewline; }
55
56 private:
57 UINT32 mStartChar;
58 UINT32 mEndChar;
59 UINT32 mLineHeight;
60 INT32 mLineYStart;
61 bool mIncludesNewline;
62 };
63
64 /** Base class for input helper tools, like caret and text selection. */
65 class BS_EXPORT GUIInputTool
66 {
67 public:
68 GUIInputTool() = default;
69 ~GUIInputTool() = default;
70
71 /**
72 * Updates the input tool with new text descriptor and parent GUI element. These values will be used for all
73 * further calculations.
74 */
75 void updateText(const GUIElement* element, const TEXT_SPRITE_DESC& textDesc);
76 protected:
77 /** Returns text offset relative to parent widget. */
78 Vector2I getTextOffset() const;
79
80 /** Returns number of lines in the current text string. */
81 UINT32 getNumLines() const { return (UINT32)mLineDescs.size(); }
82
83 /** Returns descriptor for a line with the specified index. */
84 const GUIInputLineDesc& getLineDesc(UINT32 lineIdx) const { return mLineDescs.at(lineIdx); }
85
86 /**
87 * Returns index of a line containing the specified character.
88 *
89 * @param[in] charIdx Index of the character to look for.
90 * @param[in] newlineCountsOnNextLine If true, newline characters will return the next line and not the line
91 * they're actually on.
92 */
93 UINT32 getLineForChar(UINT32 charIdx, bool newlineCountsOnNextLine = false) const;
94
95 /**
96 * Returns a rectangle containing position and size of the character with the provided index, relative to parent
97 * widget.
98 */
99 Rect2I getCharRect(UINT32 charIdx) const;
100
101 /**
102 * Returns a rectangle containing position and size of the character with the provided index, relative to parent
103 * element.
104 */
105 Rect2I getLocalCharRect(UINT32 charIdx) const;
106
107 /** Returns character index nearest to the specified position. Position should be relative to parent widget. */
108 INT32 getCharIdxAtPos(const Vector2I& pos) const;
109
110 /** Returns true if the currently set text desctiptor is valid (has any characters). */
111 bool isDescValid() const;
112
113 /**
114 * Gets a character index after the input index. Input index represents the empty areas between the characters.
115 * Newline counts as a character. (for example 0 is before the first character, 1 is after the first character but
116 * before the second, etc.)
117 *
118 * @note
119 * This can return an out of range character index, in case the input index is specified after the last character.
120 */
121 UINT32 getCharIdxAtInputIdx(UINT32 inputIdx) const;
122
123 /** Checks is the specified character index a newline. */
124 bool isNewlineChar(UINT32 charIdx) const;
125
126 /**
127 * Checks is the character after the specified input index a newline.
128 *
129 * @see getCharIdxAtInputIdx
130 */
131 bool isNewline(UINT32 inputIdx) const;
132
133 protected:
134 const GUIElement* mElement = nullptr;
135
136 Vector2* mQuads = nullptr;
137 UINT32 mNumQuads = 0;
138
139 TEXT_SPRITE_DESC mTextDesc;
140 UINT32 mNumChars = 0;
141
142 Vector<GUIInputLineDesc> mLineDescs;
143 };
144
145 /** @} */
146}