mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 08:57:34 +00:00
LibGUI: Expand underline support for Spans in TextEditor
To achieve this, some of the lambdas got shifted around and the new attributes are respected.
This commit is contained in:
parent
ece59948c3
commit
5348c67ba4
1 changed files with 19 additions and 17 deletions
|
@ -401,11 +401,17 @@ void TextEditor::paint_event(PaintEvent& event)
|
||||||
|
|
||||||
// NOTE: This lambda and TextEditor::text_width_for_font() are used to substitute all glyphs with m_substitution_code_point if necessary.
|
// NOTE: This lambda and TextEditor::text_width_for_font() are used to substitute all glyphs with m_substitution_code_point if necessary.
|
||||||
// Painter::draw_text() and Gfx::Font::width() should not be called directly, but using this lambda and TextEditor::text_width_for_font().
|
// Painter::draw_text() and Gfx::Font::width() should not be called directly, but using this lambda and TextEditor::text_width_for_font().
|
||||||
auto draw_text = [&](Gfx::IntRect const& rect, auto const& raw_text, Gfx::Font const& font, Gfx::TextAlignment alignment, Gfx::Color color, bool substitue = true) {
|
auto draw_text = [&](Gfx::IntRect const& rect, auto const& raw_text, Gfx::Font const& font, Gfx::TextAlignment alignment, Gfx::TextAttributes attributes, bool substitue = true) {
|
||||||
if (m_substitution_code_point && substitue) {
|
if (m_substitution_code_point && substitue) {
|
||||||
painter.draw_text(rect, substitution_code_point_view(raw_text.length()), font, alignment, color);
|
painter.draw_text(rect, substitution_code_point_view(raw_text.length()), font, alignment, attributes.color);
|
||||||
} else {
|
} else {
|
||||||
painter.draw_text(rect, raw_text, font, alignment, color);
|
painter.draw_text(rect, raw_text, font, alignment, attributes.color);
|
||||||
|
}
|
||||||
|
if (attributes.underline) {
|
||||||
|
if (attributes.underline_style == Gfx::TextAttributes::UnderlineStyle::Solid)
|
||||||
|
painter.draw_line(rect.bottom_left().translated(0, 1), rect.bottom_right().translated(0, 1), attributes.underline_color.value_or(attributes.color));
|
||||||
|
if (attributes.underline_style == Gfx::TextAttributes::UnderlineStyle::Wavy)
|
||||||
|
painter.draw_triangle_wave(rect.bottom_left().translated(0, 1), rect.bottom_right().translated(0, 1), attributes.underline_color.value_or(attributes.color), 2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -518,13 +524,13 @@ void TextEditor::paint_event(PaintEvent& event)
|
||||||
if (!placeholder().is_empty() && document().is_empty() && line_index == 0) {
|
if (!placeholder().is_empty() && document().is_empty() && line_index == 0) {
|
||||||
auto line_rect = visual_line_rect;
|
auto line_rect = visual_line_rect;
|
||||||
line_rect.set_width(text_width_for_font(placeholder(), font()));
|
line_rect.set_width(text_width_for_font(placeholder(), font()));
|
||||||
draw_text(line_rect, placeholder(), font(), m_text_alignment, palette().color(Gfx::ColorRole::PlaceholderText), false);
|
draw_text(line_rect, placeholder(), font(), m_text_alignment, { palette().color(Gfx::ColorRole::PlaceholderText) }, false);
|
||||||
} else if (!document().has_spans()) {
|
} else if (!document().has_spans()) {
|
||||||
// Fast-path for plain text
|
// Fast-path for plain text
|
||||||
auto color = palette().color(is_enabled() ? foreground_role() : Gfx::ColorRole::DisabledText);
|
auto color = palette().color(is_enabled() ? foreground_role() : Gfx::ColorRole::DisabledText);
|
||||||
if (is_displayonly() && is_focused())
|
if (is_displayonly() && is_focused())
|
||||||
color = palette().color(is_enabled() ? Gfx::ColorRole::SelectionText : Gfx::ColorRole::DisabledText);
|
color = palette().color(is_enabled() ? Gfx::ColorRole::SelectionText : Gfx::ColorRole::DisabledText);
|
||||||
draw_text(visual_line_rect, visual_line_text, font(), m_text_alignment, color);
|
draw_text(visual_line_rect, visual_line_text, font(), m_text_alignment, { color });
|
||||||
} else {
|
} else {
|
||||||
auto unspanned_color = palette().color(is_enabled() ? foreground_role() : Gfx::ColorRole::DisabledText);
|
auto unspanned_color = palette().color(is_enabled() ? foreground_role() : Gfx::ColorRole::DisabledText);
|
||||||
if (is_displayonly() && is_focused())
|
if (is_displayonly() && is_focused())
|
||||||
|
@ -534,20 +540,16 @@ void TextEditor::paint_event(PaintEvent& event)
|
||||||
size_t next_column = 0;
|
size_t next_column = 0;
|
||||||
Gfx::IntRect span_rect = { visual_line_rect.location(), { 0, line_height() } };
|
Gfx::IntRect span_rect = { visual_line_rect.location(), { 0, line_height() } };
|
||||||
|
|
||||||
auto draw_text_helper = [&](size_t start, size_t end, RefPtr<Gfx::Font>& font, Color& color, Optional<Color> background_color = {}, bool underline = false) {
|
auto draw_text_helper = [&](size_t start, size_t end, RefPtr<Gfx::Font>& font, Gfx::TextAttributes text_attributes) {
|
||||||
size_t length = end - start;
|
size_t length = end - start;
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
return;
|
return;
|
||||||
auto text = visual_line_text.substring_view(start, length);
|
auto text = visual_line_text.substring_view(start, length);
|
||||||
span_rect.set_width(font->width(text));
|
span_rect.set_width(font->width(text));
|
||||||
if (background_color.has_value()) {
|
if (text_attributes.background_color.has_value()) {
|
||||||
painter.fill_rect(span_rect, background_color.value());
|
painter.fill_rect(span_rect, text_attributes.background_color.value());
|
||||||
}
|
}
|
||||||
draw_text(span_rect, text, *font, m_text_alignment, color);
|
draw_text(span_rect, text, *font, m_text_alignment, text_attributes);
|
||||||
if (underline) {
|
|
||||||
painter.draw_line(span_rect.bottom_left().translated(0, 1), span_rect.bottom_right().translated(0, 1), color);
|
|
||||||
}
|
|
||||||
span_rect.translate_by(span_rect.width(), 0);
|
|
||||||
};
|
};
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (span_index >= document().spans().size()) {
|
if (span_index >= document().spans().size()) {
|
||||||
|
@ -602,14 +604,14 @@ void TextEditor::paint_event(PaintEvent& event)
|
||||||
|
|
||||||
if (span_start != next_column) {
|
if (span_start != next_column) {
|
||||||
// draw unspanned text between spans
|
// draw unspanned text between spans
|
||||||
draw_text_helper(next_column, span_start, unspanned_font, unspanned_color);
|
draw_text_helper(next_column, span_start, unspanned_font, { unspanned_color });
|
||||||
}
|
}
|
||||||
auto font = unspanned_font;
|
auto font = unspanned_font;
|
||||||
if (span.attributes.bold) {
|
if (span.attributes.bold) {
|
||||||
if (auto bold_font = Gfx::FontDatabase::the().get(font->family(), font->presentation_size(), 700))
|
if (auto bold_font = Gfx::FontDatabase::the().get(font->family(), font->presentation_size(), 700))
|
||||||
font = bold_font;
|
font = bold_font;
|
||||||
}
|
}
|
||||||
draw_text_helper(span_start, span_end, font, span.attributes.color, span.attributes.background_color, span.attributes.underline);
|
draw_text_helper(span_start, span_end, font, span.attributes);
|
||||||
next_column = span_end;
|
next_column = span_end;
|
||||||
if (!span_consumned) {
|
if (!span_consumned) {
|
||||||
// continue with same span on next line
|
// continue with same span on next line
|
||||||
|
@ -620,7 +622,7 @@ void TextEditor::paint_event(PaintEvent& event)
|
||||||
}
|
}
|
||||||
// draw unspanned text after last span
|
// draw unspanned text after last span
|
||||||
if (next_column < visual_line_text.length()) {
|
if (next_column < visual_line_text.length()) {
|
||||||
draw_text_helper(next_column, visual_line_text.length(), unspanned_font, unspanned_color);
|
draw_text_helper(next_column, visual_line_text.length(), unspanned_font, { unspanned_color });
|
||||||
}
|
}
|
||||||
// consume all spans that should end this line
|
// consume all spans that should end this line
|
||||||
// this is necessary since the spans can include the new line character
|
// this is necessary since the spans can include the new line character
|
||||||
|
@ -704,7 +706,7 @@ void TextEditor::paint_event(PaintEvent& event)
|
||||||
end_of_selection_within_visual_line - start_of_selection_within_visual_line
|
end_of_selection_within_visual_line - start_of_selection_within_visual_line
|
||||||
};
|
};
|
||||||
|
|
||||||
draw_text(selection_rect, visual_selected_text, font(), Gfx::TextAlignment::CenterLeft, text_color);
|
draw_text(selection_rect, visual_selected_text, font(), Gfx::TextAlignment::CenterLeft, { text_color });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue