Loading...
Searching...
No Matches
RichTextRenderer.h
Go to the documentation of this file.
1//
2// RichTextRenderer.h
3//
4
5#ifndef MALENA_RICHTEXTRENDERER_H
6#define MALENA_RICHTEXTRENDERER_H
7
8#pragma once
9
15#include <vector>
16
17namespace ml
18{
19 // ── RenderedSegment ───────────────────────────────────────────────────────
20
31 {
33 std::size_t bufStart = 0;
34 std::size_t bufEnd = 0;
36
38 std::size_t start,
39 std::size_t end,
40 sf::Vector2f pos)
41 : sfText(std::move(text)),
42 bufStart(start),
43 bufEnd(end),
44 position(pos)
45 {}
46 };
47
48 // ── RenderedLine ──────────────────────────────────────────────────────────
49
54 {
55 std::vector<RenderedSegment> segments;
56 float y = 0.f;
57 float height = 0.f;
58 float rowHeight = 0.f;
59 std::size_t charStart = 0;
60 std::size_t charEnd = 0;
61
62 // List rendering (computed by computeListMarkers).
63 int listType = 0;
64 float indent = 0.f;
65 std::string marker;
67 };
68
69 // ── RichTextRenderer ─────────────────────────────────────────────────────
70
86 {
87 public:
89 const sf::Font& defaultFont,
90 unsigned int defaultSize,
91 sf::Color defaultColor);
92
93 // ── Layout control ────────────────────────────────────────────────────
94
101 void setOrigin(const sf::Vector2f& origin);
102
104 void setMaxWidth(float width);
105
107 [[nodiscard]] sf::Color getDefaultColor() const { return _defaultColor; }
108
114 void rebuild();
115
121 void reflow();
122
123 // ── Drawing ───────────────────────────────────────────────────────────
124
125 void draw(sf::RenderTarget& target, const sf::RenderStates& states) const;
126
128 const sf::RenderStates& states,
129 std::size_t selStart,
130 std::size_t selEnd,
131 const sf::Color& color) const;
132
134 const sf::RenderStates& states,
135 std::size_t charIndex,
136 const sf::Color& color,
137 float width = 2.f) const;
138
139 // ── Coordinate mapping ────────────────────────────────────────────────
140
141 [[nodiscard]] sf::Vector2f charIndexToPosition(std::size_t index) const;
142 [[nodiscard]] std::size_t positionToCharIndex(const sf::Vector2f& pos) const;
143 [[nodiscard]] std::size_t lineIndexForChar(std::size_t charIndex) const;
144 [[nodiscard]] std::size_t charIndexAbove(std::size_t cursorIndex) const;
145 [[nodiscard]] std::size_t charIndexBelow(std::size_t cursorIndex) const;
146
147 // ── Layout info ───────────────────────────────────────────────────────
148
149 [[nodiscard]] float getTotalHeight() const;
150 [[nodiscard]] const std::vector<RenderedLine>& getLines() const;
151
152 private:
153 const RichTextBuffer& _buffer;
154 const sf::Font* _defaultFont;
155 unsigned int _defaultSize;
156 sf::Color _defaultColor;
157
158 sf::Vector2f _origin;
159 float _maxWidth = 0.f;
160 std::vector<RenderedLine> _lines;
161
162 void buildSegments();
163 void computeListMarkers(); // assign listType/indent/marker per line + numbering
164 void layoutLines();
165 // Height basis for an empty line: the size text typed there would take
166 // (the preceding character's size), so a blank line after small text isn't
167 // stuck at the default height. Falls back to the default.
168 [[nodiscard]] unsigned int emptyLineSize(std::size_t charStart) const;
169 void alignLineRows(RenderedLine& line, float maxSize); // shift rows per paragraph align
170 sf::Text makeText(const std::string& str, const TextAttribute& attr) const;
171 };
172
173} // namespace ml
174
175#endif // MALENA_RICHTEXTRENDERER_H
Pure data layer for rich text editing.
float getTotalHeight() const
sf::Vector2f charIndexToPosition(std::size_t index) const
void drawCursor(sf::RenderTarget &target, const sf::RenderStates &states, std::size_t charIndex, const sf::Color &color, float width=2.f) const
std::size_t charIndexAbove(std::size_t cursorIndex) const
std::size_t charIndexBelow(std::size_t cursorIndex) const
void draw(sf::RenderTarget &target, const sf::RenderStates &states) const
sf::Color getDefaultColor() const
The default (unstyled) text color.
const std::vector< RenderedLine > & getLines() const
void setMaxWidth(float width)
Set max line width for wrapping. 0 = no wrap.
std::size_t lineIndexForChar(std::size_t charIndex) const
void reflow()
Reposition existing sf::Text objects to the current origin.
std::size_t positionToCharIndex(const sf::Vector2f &pos) const
void rebuild()
Rebuild sf::Text objects from the current buffer content.
void setOrigin(const sf::Vector2f &origin)
Set the top-left origin and reposition segments.
RichTextRenderer(const RichTextBuffer &buffer, const sf::Font &defaultFont, unsigned int defaultSize, sf::Color defaultColor)
void drawSelection(sf::RenderTarget &target, const sf::RenderStates &states, std::size_t selStart, std::size_t selEnd, const sf::Color &color) const
#define MALENA_API
Definition Component.h:22
Vector2< float > Vector2f
One visual line of text made up of RenderedSegment objects.
std::string marker
"•" or "N." (empty = none)
std::size_t charStart
float height
Total height including word-wrap rows.
std::vector< RenderedSegment > segments
sf::Vector2f markerPos
where to draw the marker
int listType
0 none, 1 bullet, 2 numbered
float rowHeight
Single visual row height (for cursor/selection).
float indent
left hanging indent for list text
sf::Text sfText
SFML text object, positioned and styled.
sf::Vector2f position
Top-left position.
std::size_t bufEnd
Last char index in the buffer (exclusive).
std::size_t bufStart
First char index in the buffer (inclusive).
RenderedSegment(sf::Text &&text, std::size_t start, std::size_t end, sf::Vector2f pos)
A styled attribute range applied to a span of characters.