Repository navigation
Expand file tree
/
Copy pathTextareaComponent.h
More file actions
142 lines (114 loc) · 4.15 KB
/
Copy pathTextareaComponent.h
File metadata and controls
142 lines (114 loc) · 4.15 KB
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
#pragma once
#include <stdint.h>
#include <functional>
#include <string>
#include <vector>
#include <deki/Component.h>
#include <deki/reflection/ObjectRef.h>
#include <deki/reflection/Property.h>
#include "FocusSystem.h"
namespace Deki
{
class Object;
}
namespace DekiInput
{
class InputCollider;
}
namespace Deki2D
{
/// A box to type text into: a name, a password, a chat line. A tap gives it
/// the focus; then a keyboard types into it, a real one (the T-Deck's, a
/// desktop's) or a KeyboardComponent on screen. Backspace deletes, and
/// Enter submits a one-line box or starts a new line in a taller one.
///
/// Its parts are children the editor makes: Box, Text, Placeholder, Cursor
/// and Focus.
DEKI_CATEGORY("2D")
DEKI_DESCRIPTION("A box to type text into, from a keyboard or one on screen.")
class TextareaComponent : public Deki::Component, public IFocusable
{
public:
DEKI_EXPORT
DEKI_TOOLTIP("The hit area that takes the tap that starts typing. The editor adds one on the same object and "
"sizes it to the box.")
Deki::ObjectRef<DekiInput::InputCollider> inputCollider;
DEKI_EXPORT
DEKI_TOOLTIP("The text typed so far.")
std::string text;
DEKI_EXPORT
DEKI_TOOLTIP("Shown dimmed while the box is empty.")
std::string placeholder = "Type here";
DEKI_EXPORT
DEKI_TOOLTIP("The most characters it takes. 0 for no limit.")
DEKI_RANGE(0, 1024)
int32_t maxLength = 32;
DEKI_EXPORT
DEKI_TOOLTIP("One line: Enter submits. Off, Enter starts a new line and long lines wrap.")
bool oneLine = true;
DEKI_EXPORT
DEKI_TOOLTIP("Shows a star for each character instead of the text.")
bool password = false;
DEKI_EXPORT
DEKI_TOOLTIP("A disabled box ignores taps and typing.")
bool isEnabled = true;
DEKI_EXPORT
DEKI_TOOLTIP("Width of the box in meters.")
DEKI_UNIT(Distance)
float width = 10.0f;
DEKI_EXPORT
DEKI_TOOLTIP("Height of the box in meters.")
DEKI_UNIT(Distance)
float height = 1.75f;
// Runtime-only listeners
std::vector<std::function<void(const std::string&)>> onTextChanged;
std::vector<std::function<void(const std::string&)>> onSubmit;
TextareaComponent() = default;
~TextareaComponent() override;
/// Replaces the text, cut to Max Length.
void SetText(const std::string& newText);
/// Types `value` at the end, as far as Max Length allows. Returns false
/// when nothing fitted.
bool InsertText(const char* value);
/// Deletes the last character, a whole UTF-8 sequence.
void Backspace();
/// Enter: submits a one-line box, starts a new line in a taller one.
void Enter();
void AddOnTextChangedCallback(const std::function<void(const std::string&)>& callback);
void AddOnSubmitCallback(const std::function<void(const std::string&)>& callback);
/// Places and sizes the parts, making any the editor is missing.
void SyncParts();
void Start() override;
bool NeedsRuntimeUpdate() const override { return true; }
void RuntimeUpdate(float deltaTime) override;
void OnPropertyChanged(const char* propertyName) override;
// IFocusable
Deki::Object* GetFocusObject() const override { return GetOwner(); }
bool CanFocus() const override { return isEnabled; }
void GetFocusSize(float& w, float& h) const override
{
w = width;
h = height;
}
void OnFocusChanged(bool focused) override;
bool OnFocusKey(uint32_t key, uint32_t character) override;
bool HasFocus() const { return m_Focused; }
private:
Deki::Object* m_Box = nullptr;
Deki::Object* m_Text = nullptr;
Deki::Object* m_Placeholder = nullptr;
Deki::Object* m_Cursor = nullptr;
Deki::Object* m_Focus = nullptr;
size_t m_KnownChildren = static_cast<size_t>(-1);
uint64_t m_LastLayout = 0;
bool m_Focused = false;
bool m_Pressed = false;
float m_Blink = 0.0f;
std::string m_Shown; // what the Text part shows: the text, or stars
void EnsureParts();
void LayoutParts();
void Changed();
// Where the cursor goes, from the box's centre, in meters.
void CursorPosition(float& x, float& y) const;
};
} // namespace Deki2D