Loading...
Searching...
No Matches
RichTextBuffer.h
Go to the documentation of this file.
1//
2// RichTextBuffer.h
3//
4
5#ifndef MALENA_RICHTEXTBUFFER_H
6#define MALENA_RICHTEXTBUFFER_H
7
8#pragma once
9
14#include <optional>
15#include <string>
16#include <vector>
17
18namespace ml
19{
20 // ── TextAttribute ─────────────────────────────────────────────────────────
21
32 {
33 std::size_t start = 0;
34 std::size_t end = 0;
35
36 const sf::Font* font;
37 std::optional<unsigned int> charSize;
38 std::optional<sf::Color> color;
39 std::optional<bool> bold;
40 std::optional<bool> italic;
41 std::optional<bool> underline;
42
43 // Paragraph-level (uniform across a line): horizontal alignment.
44 // 0 = left, 1 = center, 2 = right. nullopt = inherit (left).
45 std::optional<int> align;
46
47 // Paragraph-level list style. 0 = none, 1 = bullet, 2 = numbered.
48 std::optional<int> listType;
49
50 // Paragraph-level indent depth (Tab/Shift+Tab). 0 = flush left.
51 std::optional<int> indentLevel;
52
53 TextAttribute() : font(nullptr) {}
54 };
55
56 // ── RichTextBuffer ────────────────────────────────────────────────────────
57
79 {
80 public:
81 // ── Construction ──────────────────────────────────────────────────────
82
83 RichTextBuffer() = default;
84
85 // ── Buffer access ─────────────────────────────────────────────────────
86
88 [[nodiscard]] const std::string& getText() const;
89
91 [[nodiscard]] std::size_t size() const;
92
94 [[nodiscard]] bool empty() const;
95
97 [[nodiscard]] const std::vector<TextAttribute>& getAttributes() const;
98
99 // ── Cursor ────────────────────────────────────────────────────────────
100
102 [[nodiscard]] std::size_t getCursor() const;
103
110 void setCursor(std::size_t pos);
111
118 void moveCursor(int delta, bool extendSelection = false);
119
126 void moveCursorByWord(int direction, bool extendSelection = false);
127
132 void moveCursorToLineStart(bool extendSelection = false);
133
138 void moveCursorToLineEnd(bool extendSelection = false);
139
140 // ── Selection ─────────────────────────────────────────────────────────
141
143 [[nodiscard]] bool hasSelection() const;
144
146 [[nodiscard]] std::size_t getSelectionStart() const;
147
149 [[nodiscard]] std::size_t getSelectionEnd() const;
150
157 void setSelection(std::size_t start, std::size_t end);
158
160 void selectAll();
161
164
166 [[nodiscard]] std::string getSelectedText() const;
167
168 // ── Editing ───────────────────────────────────────────────────────────
169
178 void insert(const std::string& text);
179
184 void insertChar(char32_t unicode);
185
190 void backspace();
191
197
201 void clear();
202
209 void setText(const std::string& text);
210
211 // ── Attributes ────────────────────────────────────────────────────────
212
224
237 void applyAttributeRange(std::size_t start, std::size_t end, TextAttribute attr);
238
244
257 std::size_t index,
258 const sf::Font* defaultFont,
259 unsigned int defaultSize,
260 sf::Color defaultColor) const;
261
263 [[nodiscard]] bool hasPendingAttribute() const { return _hasPending; }
264
266 [[nodiscard]] const TextAttribute& getPendingAttribute() const { return _pendingAttr; }
267
268 // ── Clipboard helpers ─────────────────────────────────────────────────
269
274 void copyToClipboard() const;
275
281
286
287 private:
288 std::string _text;
289 std::vector<TextAttribute> _attributes;
290
291 std::size_t _cursor = 0;
292 std::size_t _selStart = 0;
293 std::size_t _selEnd = 0;
294 bool _hasSelection = false;
295
296 // Pending attribute for next insert (applied when no selection active)
297 TextAttribute _pendingAttr;
298 bool _hasPending = false;
299
300 void deleteRange(std::size_t start, std::size_t end);
301 void shiftAttributesAfterInsert(std::size_t pos, std::size_t count);
302 void shiftAttributesAfterDelete(std::size_t start, std::size_t count);
303 void splitAttributeAt(std::size_t pos);
304 void mergeAdjacentAttributes();
305 void normalizeAttributes();
306
307 std::size_t findWordBoundary(std::size_t pos, int direction) const;
308 std::size_t findLineStart(std::size_t pos) const;
309 std::size_t findLineEnd(std::size_t pos) const;
310 };
311
312} // namespace ml
313
314#endif // MALENA_RICHTEXTBUFFER_H
void moveCursorToLineStart(bool extendSelection=false)
Move the cursor to the start of the current line.
void setCursor(std::size_t pos)
Set the cursor position clamped to [0, size()]. Clears the selection.
const TextAttribute & getPendingAttribute() const
The pending (next-insert) style; only meaningful when hasPendingAttribute().
void applyAttributeRange(std::size_t start, std::size_t end, TextAttribute attr)
Apply an attribute to an explicit character range.
void backspace()
Delete the character immediately before the cursor (backspace). If a selection is active,...
const std::vector< TextAttribute > & getAttributes() const
Return all attribute ranges.
void setText(const std::string &text)
Replace the entire buffer content. Cursor moves to end. Clears all attributes.
std::size_t size() const
Return the number of characters in the buffer.
void moveCursor(int delta, bool extendSelection=false)
Move the cursor by delta characters, clamped to buffer bounds.
void moveCursorToLineEnd(bool extendSelection=false)
Move the cursor to the end of the current line.
std::size_t getCursor() const
Return the current cursor position (char index).
void setSelection(std::size_t start, std::size_t end)
Set an explicit selection range. Cursor moves to end.
void insert(const std::string &text)
Insert text at the cursor position.
void pasteFromClipboard()
Insert the system clipboard contents at the cursor.
void insertChar(char32_t unicode)
Insert a single unicode character at the cursor position.
void clearSelection()
Clear the selection without moving the cursor.
bool empty() const
Return true if the buffer contains no characters.
void selectAll()
Select all text.
void deleteForward()
Delete the character immediately after the cursor (delete key). If a selection is active,...
std::size_t getSelectionStart() const
Return the selection start (always <= selectionEnd).
void copyToClipboard() const
Copy the current selection to the system clipboard. Has no effect if nothing is selected.
bool hasSelection() const
Return true if a selection is active.
bool hasPendingAttribute() const
Whether a pending (next-insert) style is active.
std::string getSelectedText() const
Return the currently selected text. Empty if no selection.
void applyAttribute(TextAttribute attr)
Apply an attribute to the current selection.
void moveCursorByWord(int direction, bool extendSelection=false)
Move the cursor to the start of the previous or next word.
TextAttribute getAttributeAt(std::size_t index, const sf::Font *defaultFont, unsigned int defaultSize, sf::Color defaultColor) const
Return the effective TextAttribute at a given character index.
const std::string & getText() const
Return the full text content as a UTF-8 string.
std::size_t getSelectionEnd() const
Return the selection end (always >= selectionStart).
void cutToClipboard()
Cut the current selection to the system clipboard. Has no effect if nothing is selected.
void clear()
Delete all text in the buffer.
RichTextBuffer()=default
void clearAttributes()
Remove all attribute ranges (and any pending style), leaving the text and cursor untouched....
#define MALENA_API
Definition Component.h:22
A styled attribute range applied to a span of characters.
std::optional< bool > bold
nullopt = inherit
std::optional< int > listType
std::size_t end
Last character index (exclusive).
std::optional< sf::Color > color
nullopt = inherit default color
std::size_t start
First character index (inclusive).
std::optional< int > indentLevel
std::optional< unsigned int > charSize
nullopt = inherit default size
std::optional< int > align
const sf::Font * font
nullptr = inherit default font
std::optional< bool > italic
nullopt = inherit
std::optional< bool > underline
nullopt = inherit