TachyonUI 0.1.0
High-performance UI for building tools.
Loading...
Searching...
No Matches
gui_text_system_skribidi.h
Go to the documentation of this file.
1#pragma once
2
6#include <gui_core/gui_hash.h>
7
8#include <span>
9#include <unordered_map>
10#include <unordered_set>
11#include <string>
12
13struct skb_layout_t;
14struct skb_text_position_t;
15struct skb_editor_t;
16
17namespace tachyon
18{
21
23 class SkribidiContext;
24 struct RegisteredText;
25 struct EditSelection;
26
29 {
30 public:
33
34 // -------------------- Initialization --------------------
35
36 bool Initialize(GraphicsContext* graphicsContext, StyleManager* styleManager,
37 TextAtlasManager* textAtlasManager,
38 GUIStateManager* guiStateManager, IClipboard* clipboard) override;
39 void Shutdown() override;
40 void Update() override;
41 void BeginFrame(int2 screenMousePos, MouseButtons mouseButtons, uint32_t timeMs) override;
42 void BeginAtlasRecord(ID scopeId) override;
43 void EndAtlasRecord() override;
44 bool ReplayAtlasTouches(ID scopeId) override;
45
46 // -------------------- Editor Input Handling --------------------
47
48 void OnKeyboard(ID windowId, KeyCode key, int repeat, KeyModifier modifiers, KeyAction action) override;
49 void OnMouseMove(ID windowId, int2 screenPos, MouseButtons button, KeyModifier modifiers) override;
50 void OnMouseButton(ID windowId, int2 screenPos, MouseButtons button, KeyModifier modifiers, MouseAction action) override;
51 void OnMouseScroll(ID windowId, int2 screenPos, float2 scrollOffset, KeyModifier modifiers) override;
52 void OnTextComposition(ID windowId, std::string_view text, int32_t cursor) override;
53
54 void SwitchTextEditor(ID from, ID to) override;
55 void SetUndoHistory(UndoHistory* history) override { m_undoHistory = history; }
58 bool DoesTextEditorAcceptTabs(ID elementId) const override;
59 bool IsTextEditor(ID elementId) const override;
60 void RequestSelectAll(ID elementId) override;
61 TextEditUpdate ConsumeTextEditUpdate(TextID textId, std::string& outText) override;
62 bool UpdateText(TextID textId, std::string_view text) override;
63
64 std::string Copy() override;
65 std::string Cut() override;
66 void Paste(std::string_view text) override;
67
68 bool IsHoveringSelectedText(ID textEditorId, ID windowId, tachyon::int2 screenSpace) const override;
69 bool TryGetTextDragCursor(ID windowId, tachyon::int2 screenSpace, MouseCursor& outCursor) const override;
70 bool TryGetTextDragHoverTarget(ID windowId, tachyon::int2 screenSpace, ID& outTargetId) const override;
71
72 // -------------------- Cache Management --------------------
73
74 void ClearCache() override;
76 size_t RegisteredTextCount() const;
78 uint64_t LayoutsMade() const;
79
80
81
82 // -------------------- Cursor Visibility --------------------
83
84 void EnsureCursorVisible(ID textEditorId) override;
85 std::optional<IntRect> GetCursorRect(ID textEditorId) override;
86 std::optional<IntRect> GetCaretScreenRect() const override;
87
88 // -------------------- Editor Registration --------------------
89
90
91 TextID RegisterEditableText(ID elementId, std::string& text, TextEditBehavior behavior, StyleRef styleIndex, ElementState state, bool& wasModified,
92 const ITextValidator* validator = nullptr) override;
93 std::string* ValueEditText(ID elementId, bool& started) override;
94 void SetTextColor(TextID textId, VisualColorStyleIndex color) override;
96
97
98 // -------------------- Font Registration --------------------
99
100 void SetFontDirectory(std::string_view directory) override;
101 void SetFallbackFontDirectory(std::string_view directory) override;
102 void SetLanguage(std::string_view languageTag) override;
104 FontID RegisterFontFamily(std::string_view familyName, std::span<const FontFaceSource> faces) override;
105
106 // -------------------- Text Registration --------------------
107
108 TextID RegisterText(ID elementId, IconID iconId, std::string_view text, StyleRef styleIndex, ElementState state) override;
109 TextID RegisterRichText(ID elementId, const std::span<ContentRun>& contentRuns,
110 StyleRef styleIndex, ElementState state) override;
111 TextID RegisterEditableRichText(ID elementId, const std::span<ContentRun>& contentRuns,
112 TextEditBehavior behavior, StyleRef styleIndex,
113 ElementState state, bool& wasModified) override;
114 TextID GetTextID(ID elementId) const override;
115 std::string_view GetText(TextID textId) const override;
116
117 // -------------------- Text Measurement --------------------
118
120 int32_t GetTextHeightWithoutIcon(TextID textId) const override;
121 TextMeasurement MeasureText(TextID textId, const TextWrapContext& wrapContext) const override;
122
123 // -------------------- Text Rendering --------------------
124
125 void RenderText(TextID textId, IntRect rect, IntRect innerRect, IntRect clipRect, float pixelScale = 1.f,
126 const float3x2& screenToLayout = float3x2::Identity()) override;
127
128 std::optional<MouseCursor> LinkCursorAt(ID elementId, int32_t localX, int32_t localY) const override;
129 intptr_t HitTestContent(TextID textId, int32_t localX, int32_t localY) const override;
130 void SetHoveredContent(TextID textId, intptr_t contentId) override;
131
132
133 // -------------------- Icon Registration --------------------
134
135 bool IsValidIcon(IconID iconId) const override;
136
137 IconID RegisterIconFromSVG(const char* name, const char* svg_data, size_t svg_size) override;
138
139 IconID RegisterIconFromSVGFile(const char* path) override;
140 IconID RegisterIconFromPixels(const char* name, uint2 size, std::span<const uint8_t> rgba) override;
141 void UnregisterIcon(IconID iconId) override;
142
143 // -------------------- Icon Measurement --------------------
144
146 IconMeasurement MeasureIcon(IconID iconId) const override;
147
148 // -------------------- Icon Rendering --------------------
149
150 void RenderIcon(IconID iconId, IntRect rect, IntRect clipRect, VisualColorStyleIndex tint,
151 std::span<const VisualShadow> shadows = {}) override;
152
153 static void ScreenToTextEditorLocalPoint(tachyon::int2 screenSpace, const IntRect& textEditorInnerRect, tachyon::float2& outLocal,
154 const float3x2& screenToLayout = float3x2::Identity());
155
156 private:
157 void UpdateGlyphs();
160 bool RebuildFontCollection(FontID fontId);
161 void EvictUnusedTexts();
162
163 bool TryGetCaretPositionInternal(ID windowId, tachyon::int2 screenPos, ID targetTextEditorId, skb_editor_t*& outTargetEditor, skb_text_position_t& outPosition);
164 void DropDraggedText(ID windowId, tachyon::int2 screenPos, ID targetTextEditorId);
165 void SelectFromDropPoint(skb_editor_t* editor, skb_text_position_t dropPoint);
166 void EndTextDragging();
167
168 void RenderText(RegisteredText* entry, IntRect rect, IntRect innerRectScreen, IntRect clipRect, float pixelScale);
170 void DrawIcon(IconID iconId, IntRect rect, IntRect clipRect, VisualColorStyleIndex tint);
171 void RenderEditor(RegisteredText* entry, IntRect rect, IntRect innerRectScreen, IntRect clipRect, float pixelScale);
172 bool UpdateText(RegisteredText* entry, std::string_view text);
173
174 bool ApplyTextEditUpdate(ID elementId, std::string& currentText, bool& wasModified);
175 void ClearComposition();
176 bool TryGetActiveTextEditorLocalPoint(ID windowId, tachyon::int2 screenSpace, tachyon::float2& outLocal) const;
179 bool IsActiveEditorPosOnLink(float localX, float localY) const;
180 bool TryGetTextEditorLocalPoint(ID textEditorId, ID windowId, tachyon::int2 screenSpace, tachyon::float2& outLocal) const;
181 ID FindTextEditorAtScreenPoint(ID windowId, tachyon::int2 screenSpace) const;
183 const ITextValidator* TextEditorValidator(ID elementId) const;
184 bool CanDropDraggedTextInto(ID targetTextEditorId) const;
185 void* UpdateLayoutWhenNecessary(RegisteredText* entry, float width) const;
186 void* UpdateEditorWhenNecessary(RegisteredText* entry, float width) const;
187 TextMeasurement UpdateBaseMeasurementWhenNecessary(RegisteredText* entry) const;
188 TextMeasurement UpdateWrapMeasurementWhenNecessary(RegisteredText* entry, const TextWrapContext& wrapContext) const;
189 TextMeasurement MeasureTextInternal(RegisteredText* entry, const skb_layout_t* layout) const;
190
191 void UpdateRegisteredTextStyleState(RegisteredText* entry, tachyon::StyleRef styleIndex, tachyon::ElementState state);
192
193 std::unordered_map<uint64_t, TextID> m_elementIdToTextIdMap;
194 std::unordered_map<uint64_t, TextID> m_textKeyToIdMap;
195 std::unordered_set<uint64_t> m_textEditorElements;
196 std::unordered_set<uint64_t> m_readOnlyEditorElements;
197
198 std::unordered_map<uint64_t, const ITextValidator*> m_textEditorValidators;
199
200 ID m_textDragSourceId = ID::Invalid();
201 UndoHistory* m_undoHistory = nullptr;
204 std::unordered_map<uint64_t, std::string> m_externalText;
205 void PushTextEdit(ID elementId, const std::string& before, const std::string& after);
208 void FocusChangedField(ID elementId, EditSelection selection);
211 void NoteSelectionBeforeEdit();
212 std::string m_textDragPayload;
213 ID m_skipNextSelectAllId = ID::Invalid();
214 bool m_textDragArmed = false;
215 int2 m_textDragStartScreenPos = int2 { 0, 0 };
216 ID m_valueEditElementId = ID::Invalid();
217 std::string m_valueEditText;
218
219 ID m_pendingCursorVisibleEditorId = ID::Invalid();
220
221 SkribidiContext* m_skribidiContext;
222 std::string m_fontDirectory { "fonts" };
223 std::string m_fallbackFontDirectory;
224 };
225
227} // namespace tachyon
Owns the per-frame state objects and runs their BeginFrame / EndFrame in order.
Definition gui_state_manager.h:65
A graphics backend: the device, the window contexts that render the GUI's windows,...
Definition gui_graphics_context.h:60
The clipboard text editors copy to and paste from; GUIApplication::SetClipboard sets one (default: SD...
Definition gui_clipboard.h:14
Text and icon registration, measurement, rendering and editing.
Definition gui_text_system.h:178
virtual FontID RegisterFontFamily(std::string_view familyName, std::span< const FontFaceSource > faces)=0
Registers a font family from its faces (regular, bold, italic, ...); each face's weight and style com...
What an editable field takes as text, asked while it is edited.
Definition gui_text_converter.h:19
void EndAtlasRecord() override
static void ScreenToTextEditorLocalPoint(tachyon::int2 screenSpace, const IntRect &textEditorInnerRect, tachyon::float2 &outLocal, const float3x2 &screenToLayout=float3x2::Identity())
void OnMouseButton(ID windowId, int2 screenPos, MouseButtons button, KeyModifier modifiers, MouseAction action) override
Mouse buttons for text editors: caret placement, selection, drag-drop.
intptr_t HitTestContent(TextID textId, int32_t localX, int32_t localY) const override
The contentId of the run at (localX, localY), element-local; 0 if none.
void SwitchTextEditor(ID from, ID to) override
The focused text field changed (GUIStateManager::TextEditorFocus): commit from (ID::Invalid if none) ...
IconMeasurement MeasureIcon(IconID iconId) const override
The natural size of iconId, in pixels.
TextMeasurement MeasureText(TextID textId, const TextWrapContext &wrapContext) const override
The measurement of textId wrapped to wrapContext.maxWidth, in pixels.
void BeginFrame(int2 screenMousePos, MouseButtons mouseButtons, uint32_t timeMs) override
Starts a frame, before the UI is built: clears the per-frame editor registrations that this frame's R...
bool UpdateText(TextID textId, std::string_view text) override
Replaces the text of textId; true when it changed.
std::string * ValueEditText(ID elementId, bool &started) override
The text the focused field elementId edits, kept while it has the focus (its value isn't formatted ag...
bool TryGetTextDragCursor(ID windowId, tachyon::int2 screenSpace, MouseCursor &outCursor) const override
The mouse cursor to show while text is dragged; true when it overrides the hover cursor.
bool IsHoveringSelectedText(ID textEditorId, ID windowId, tachyon::int2 screenSpace) const override
True when the screen point screenSpace is over selected text in textEditorId.
bool IsTextEditor(ID elementId) const override
True when elementId registered editable text this frame.
uint64_t LayoutsMade() const
Number of text layouts made so far, for diagnostics.
TextID RegisterEditableText(ID elementId, std::string &text, TextEditBehavior behavior, StyleRef styleIndex, ElementState state, bool &wasModified, const ITextValidator *validator=nullptr) override
Registers text as editable by elementId; wasModified is set when an edit changed it.
std::optional< IntRect > GetCaretScreenRect() const override
The active editor's caret in absolute screen coordinates (through any zoom/pan), to place the IME can...
void OnKeyboard(ID windowId, KeyCode key, int repeat, KeyModifier modifiers, KeyAction action) override
Keyboard input for the active text editor.
void OnMouseMove(ID windowId, int2 screenPos, MouseButtons button, KeyModifier modifiers) override
Mouse movement for text selection and drag-drop.
void ClearCache() override
Drops every registered text and the live editor; earlier TextIDs become invalid.
IconMeasurement GetIconMeasurement(IconID iconId) const override
The natural size of iconId, in pixels (same as MeasureIcon).
void SetHoveredContent(TextID textId, intptr_t contentId) override
Sets the hovered run of textId (by contentId), drawn in its hover style; 0 for none.
bool DoesTextEditorAcceptTabs(ID elementId) const override
True when the editor elementId inserts tabs (TextEditBehavior::AcceptTabs).
void BeginAtlasRecord(ID scopeId) override
Records the glyph and icon atlas entries a cached scope's primitives use, until EndAtlasRecord.
bool IsValidIcon(IconID iconId) const override
True when iconId is a registered icon.
std::string Cut() override
Removes the active editor's selected text and returns it.
IconID RegisterIconFromPixels(const char *name, uint2 size, std::span< const uint8_t > rgba) override
Registers an icon from size.x x size.y RGBA pixels (straight alpha, rows from the top) under a unique...
bool TryGetTextDragHoverTarget(ID windowId, tachyon::int2 screenSpace, ID &outTargetId) const override
While text is dragged, sets outTargetId to the drop target under the cursor (ID::Invalid if none) and...
IconID RegisterIconFromSVG(const char *name, const char *svg_data, size_t svg_size) override
Registers an icon from SVG data under a unique name.
bool Initialize(GraphicsContext *graphicsContext, StyleManager *styleManager, TextAtlasManager *textAtlasManager, GUIStateManager *guiStateManager, IClipboard *clipboard) override
TextID RegisterRichText(ID elementId, const std::span< ContentRun > &contentRuns, StyleRef styleIndex, ElementState state) override
Registers text made of runs: styled text, inline icons and links.
std::optional< MouseCursor > LinkCursorAt(ID elementId, int32_t localX, int32_t localY) const override
The cursor of the link at (localX, localY), element-local (its LinkStyle::cursor); none when there's ...
void OnMouseScroll(ID windowId, int2 screenPos, float2 scrollOffset, KeyModifier modifiers) override
Mouse wheel input for text editors.
void SetFallbackFontDirectory(std::string_view directory) override
Where the optional fallback fonts are: Noto, for other scripts, emoji and symbols.
int32_t GetTextHeightWithoutIcon(TextID textId) const override
How high textId's text is unwrapped, in pixels, without the icon it was registered with (which its me...
TextID RegisterEditableRichText(ID elementId, const std::span< ContentRun > &contentRuns, TextEditBehavior behavior, StyleRef styleIndex, ElementState state, bool &wasModified) override
Registers rich text that renders like RegisterRichText but can also be selected and copied (the runs'...
std::string Copy() override
The active editor's selected text.
TextEditUpdate ConsumeTextEditUpdate(TextID textId, std::string &outText) override
Takes the pending edit of textId: the edited text goes to outText, the result says whether it changed...
TextMeasurement GetTextMeasurement(TextID textId) const override
The unwrapped measurement of textId, in pixels; cached until its text or style changes.
void OnTextComposition(ID windowId, std::string_view text, int32_t cursor) override
IME composition (pre-edit) text, UTF-8, shown but not yet committed; empty when composing ends.
TextID GetTextID(ID elementId) const override
The TextID elementId registered this frame, or TextID::Invalid.
void SetFontDirectory(std::string_view directory) override
Where the built-in fonts are (default "fonts", relative to the working directory): Inter for text and...
size_t RegisteredTextCount() const
Number of registered texts held, for diagnostics.
void SetLanguage(std::string_view languageTag) override
The default language as a BCP 47 tag ("ja", "zh-Hant", "ko"), for text whose style has no language of...
IconID RegisterIconFromSVGFile(const char *path) override
Registers an icon from an SVG file, named by its path.
FontID RegisterFontFamily(std::string_view familyName, std::span< const FontFaceSource > faces) override
Registers a font family from its faces (regular, bold, italic, ...); each face's weight and style com...
std::optional< IntRect > GetCursorRect(ID textEditorId) override
Takes a pending EnsureCursorVisible request for textEditorId and returns the caret rect,...
void RenderText(TextID textId, IntRect rect, IntRect innerRect, IntRect clipRect, float pixelScale=1.f, const float3x2 &screenToLayout=float3x2::Identity()) override
Draws textId into rect (renderer space, window-local), clipped to clipRect.
bool ReplayAtlasTouches(ID scopeId) override
void SetCaretColor(VisualColorStyleIndex color) override
The text caret's color (the theme's –caret). Set again after the style manager is cleared.
void RequestSelectAll(ID elementId) override
Selects all text of the editor elementId the next time it renders.
void Paste(std::string_view text) override
Inserts text into the active editor at the caret, replacing the selection.
void SetTextColor(TextID textId, VisualColorStyleIndex color) override
Draw a registered text in color instead of its style's text color, until it is registered again (call...
void RenderIcon(IconID iconId, IntRect rect, IntRect clipRect, VisualColorStyleIndex tint, std::span< const VisualShadow > shadows={}) override
Draws iconId fitted into rect (aspect kept, centered), clipped to clipRect.
ID ActiveElementID() const
The field the editor holds: the text focus as of the last switch.
std::string_view GetText(TextID textId) const override
The text registered as textId.
void EnsureCursorVisible(ID textEditorId) override
Asks for the caret of textEditorId to be scrolled into view; editor input calls it when the caret mov...
void SetUndoHistory(UndoHistory *history) override
Where committed text edits go as undo steps (none: not recorded).
Definition gui_text_system_skribidi.h:55
void UnregisterIcon(IconID iconId) override
Lets go of an icon from RegisterIconFromPixels: its image slot is freed, the ID draws nothing from th...
TextID RegisterText(ID elementId, IconID iconId, std::string_view text, StyleRef styleIndex, ElementState state) override
Registers static text, with an optional icon, for elementId.
Bakes serializable Styles into deduplicated runtime layout/visual styles; a StyleRef holds indices in...
Definition gui_style_manager.h:39
Definition gui_text_atlas_manager.h:17
The app's undo history: steps that each undo and redo one change.
Definition gui_undo_history.h:18
KeyCode
Keys by what the keyboard layout makes them, not by position.
Definition gui_input_enums.h:106
KeyAction
A keyboard event: a key down or up, or a typed character (KeyChar).
Definition gui_input_enums.h:50
KeyModifier
Modifier keys held, combined with |.
Definition gui_input_enums.h:26
MouseButtons
Mouse buttons, combined with |.
Definition gui_input_enums.h:38
MouseAction
Whether a mouse button went down or up.
Definition gui_input_enums.h:58
MouseCursor
Mouse cursor shown over an element (CSS: cursor).
Definition gui_style.h:478
VisualColorStyleIndex
Index into StyleManager's color style pool; Invalid (0) draws nothing (transparent).
Definition gui_style.h:33
FontID
Handle for a font family registered with ITextSystem::RegisterFontFamily().
Definition gui_style_text.h:20
TextID
Handle for text registered with the text system (ITextSystem::RegisterText and friends).
Definition gui_style_text.h:13
IconID
Handle for an icon registered with ITextSystem::RegisterIconFromSVG / RegisterIconFromSVGFile.
Definition gui_style_text.h:15
ElementState
Interaction state bits of an element; they pick the Style::states variant it draws with.
Definition gui_style.h:42
TextEditBehavior
Definition gui_text_system.h:99
Definition gui_logging.h:24
A 64-bit element ID whose bit layout depends on its IDMode.
Definition gui_id.h:23
static constexpr ID Invalid()
The "no element" ID (all bits zero); also the default for optional ID parameters.
Definition gui_id.h:66
Definition gui_text_system.h:183
Definition gui_text_system.h:54
Definition gui_base_types.h:407
A registered style, as StyleManager::Register returns it: indices into the shared style pools,...
Definition gui_style_ref.h:25
Definition gui_text_system.h:66
Definition gui_text_system.h:84
Definition gui_base_types.h:121
2D affine transform matrix (2 rows x 3 columns): x' = r0.x*x + r0.y*y + r0.z y' = r1....
Definition gui_base_types.h:219
static constexpr float3x2 Identity()
Definition gui_base_types.h:228
Integer 2D vector.
Definition gui_base_types.h:19
Definition gui_base_types.h:75