mirror of
https://github.com/RGBCube/serenity
synced 2025-07-10 12:17:35 +00:00
GTextEditor: Add a "span" mechanism for having custom-style text ranges
It's now possible to give GTextEditor a vector of Span objects. Spans currently tell the editor which color to use for each character in the span. This can be used to implement syntax highlighting :^)
This commit is contained in:
parent
307cbf83c3
commit
0d53d74d5f
2 changed files with 43 additions and 2 deletions
|
@ -364,7 +364,27 @@ void GTextEditor::paint_event(GPaintEvent& event)
|
||||||
#ifdef DEBUG_GTEXTEDITOR
|
#ifdef DEBUG_GTEXTEDITOR
|
||||||
painter.draw_rect(visual_line_rect, Color::Cyan);
|
painter.draw_rect(visual_line_rect, Color::Cyan);
|
||||||
#endif
|
#endif
|
||||||
painter.draw_text(visual_line_rect, visual_line_text, m_text_alignment, Color::Black);
|
if (m_spans.is_empty()) {
|
||||||
|
// Fast-path for plain text
|
||||||
|
painter.draw_text(visual_line_rect, visual_line_text, m_text_alignment, Color::Black);
|
||||||
|
} else {
|
||||||
|
int advance = font().glyph_width(' ') + font().glyph_spacing();
|
||||||
|
Rect character_rect = { visual_line_rect.location(), { font().glyph_width(' '), line_height() } };
|
||||||
|
for (int i = 0; i < visual_line_text.length(); ++i) {
|
||||||
|
Color color;
|
||||||
|
int physical_line = line_index;
|
||||||
|
int physical_column = start_of_visual_line + i;
|
||||||
|
// FIXME: This is *horribly* inefficient.
|
||||||
|
for (auto& span : m_spans) {
|
||||||
|
if (!span.contains(GTextPosition(physical_line, physical_column)))
|
||||||
|
continue;
|
||||||
|
color = span.color;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
painter.draw_text(character_rect, visual_line_text.substring_view(i, 1), m_text_alignment, color);
|
||||||
|
character_rect.move_by(advance, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
bool physical_line_has_selection = has_selection && line_index >= selection.start().line() && line_index <= selection.end().line();
|
bool physical_line_has_selection = has_selection && line_index >= selection.start().line() && line_index <= selection.end().line();
|
||||||
if (physical_line_has_selection) {
|
if (physical_line_has_selection) {
|
||||||
|
|
||||||
|
|
|
@ -167,6 +167,26 @@ public:
|
||||||
void set_cursor(int line, int column);
|
void set_cursor(int line, int column);
|
||||||
void set_cursor(const GTextPosition&);
|
void set_cursor(const GTextPosition&);
|
||||||
|
|
||||||
|
struct Span {
|
||||||
|
bool contains(const GTextPosition& position) const
|
||||||
|
{
|
||||||
|
if (!(position.line() > start.line() || (position.line() == start.line() && position.column() >= start.column())))
|
||||||
|
return false;
|
||||||
|
if (!(position.line() < end.line() || (position.line() == end.line() && position.column() <= end.column())))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
GTextPosition start;
|
||||||
|
GTextPosition end;
|
||||||
|
Color color;
|
||||||
|
};
|
||||||
|
|
||||||
|
void set_spans(const Vector<Span>& spans)
|
||||||
|
{
|
||||||
|
m_spans = spans;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GTextEditor(Type, GWidget* parent);
|
GTextEditor(Type, GWidget* parent);
|
||||||
|
|
||||||
|
@ -187,7 +207,6 @@ protected:
|
||||||
virtual void resize_event(GResizeEvent&) override;
|
virtual void resize_event(GResizeEvent&) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void create_actions();
|
void create_actions();
|
||||||
void paint_ruler(Painter&);
|
void paint_ruler(Painter&);
|
||||||
void update_content_size();
|
void update_content_size();
|
||||||
|
@ -274,6 +293,8 @@ private:
|
||||||
RefPtr<GAction> m_delete_action;
|
RefPtr<GAction> m_delete_action;
|
||||||
CElapsedTimer m_triple_click_timer;
|
CElapsedTimer m_triple_click_timer;
|
||||||
NonnullRefPtrVector<GAction> m_custom_context_menu_actions;
|
NonnullRefPtrVector<GAction> m_custom_context_menu_actions;
|
||||||
|
|
||||||
|
Vector<Span> m_spans;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const LogStream& operator<<(const LogStream& stream, const GTextPosition& value)
|
inline const LogStream& operator<<(const LogStream& stream, const GTextPosition& value)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue