diff options
author | Andreas Kling <kling@serenityos.org> | 2020-09-01 19:10:55 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-09-01 23:55:35 +0200 |
commit | aa70d8c217d9b6bfc9634835d59d0cb9eea0a192 (patch) | |
tree | b01b401ebd4008f146cbcf5ea335f851824eaf38 | |
parent | 08f1ea3e45db6d00814d7fced935d0e53afc9d99 (diff) | |
download | serenity-aa70d8c217d9b6bfc9634835d59d0cb9eea0a192.zip |
LibGUI: Implement trailing whitespace visualization in TextEditor
This patch adds an optional mode where TextEditor highlights trailing
whitespace characters on each line with a nice reddish dither pattern.
We should probably make this themable and I'm sure it could be nicer
somehow, but this is just a first cut and I do kinda like it. :^)
-rw-r--r-- | Libraries/LibGUI/TextDocument.cpp | 17 | ||||
-rw-r--r-- | Libraries/LibGUI/TextDocument.h | 2 | ||||
-rw-r--r-- | Libraries/LibGUI/TextEditor.cpp | 29 | ||||
-rw-r--r-- | Libraries/LibGUI/TextEditor.h | 4 |
4 files changed, 52 insertions, 0 deletions
diff --git a/Libraries/LibGUI/TextDocument.cpp b/Libraries/LibGUI/TextDocument.cpp index 25dec99964..c16e757c41 100644 --- a/Libraries/LibGUI/TextDocument.cpp +++ b/Libraries/LibGUI/TextDocument.cpp @@ -94,6 +94,23 @@ size_t TextDocumentLine::first_non_whitespace_column() const return length(); } +Optional<size_t> TextDocumentLine::last_non_whitespace_column() const +{ + for (ssize_t i = length() - 1; i >= 0; --i) { + auto code_point = code_points()[i]; + if (!isspace(code_point)) + return i; + } + return {}; +} + +bool TextDocumentLine::ends_in_whitespace() const +{ + if (!length()) + return false; + return isspace(code_points()[length() - 1]); +} + String TextDocumentLine::to_utf8() const { StringBuilder builder; diff --git a/Libraries/LibGUI/TextDocument.h b/Libraries/LibGUI/TextDocument.h index 5a061da3b0..759e8edf9f 100644 --- a/Libraries/LibGUI/TextDocument.h +++ b/Libraries/LibGUI/TextDocument.h @@ -177,6 +177,8 @@ public: void remove_range(TextDocument&, size_t start, size_t length); size_t first_non_whitespace_column() const; + Optional<size_t> last_non_whitespace_column() const; + bool ends_in_whitespace() const; private: // NOTE: This vector is null terminated. diff --git a/Libraries/LibGUI/TextEditor.cpp b/Libraries/LibGUI/TextEditor.cpp index 0317120f13..5460b6b37b 100644 --- a/Libraries/LibGUI/TextEditor.cpp +++ b/Libraries/LibGUI/TextEditor.cpp @@ -495,6 +495,26 @@ void TextEditor::paint_event(PaintEvent& event) } } + if (m_visualize_trailing_whitespace && line.ends_in_whitespace()) { + size_t physical_column; + auto last_non_whitespace_column = line.last_non_whitespace_column(); + if (last_non_whitespace_column.has_value()) + physical_column = last_non_whitespace_column.value() + 1; + else + physical_column = 0; + size_t end_of_visual_line = (start_of_visual_line + visual_line_text.length()); + if (physical_column < end_of_visual_line) { + size_t visual_column = physical_column > start_of_visual_line ? (physical_column - start_of_visual_line) : 0; + Gfx::IntRect whitespace_rect { + content_x_for_position({ line_index, visual_column }), + visual_line_rect.y(), + font().width(visual_line_text.substring_view(visual_column, visual_line_text.length() - visual_column)), + visual_line_rect.height() + }; + painter.fill_rect_with_dither_pattern(whitespace_rect, Color(), Color(255, 192, 192)); + } + } + if (physical_line_has_selection) { size_t start_of_selection_within_visual_line = (size_t)max(0, (int)selection_start_column_within_line - (int)start_of_visual_line); size_t end_of_selection_within_visual_line = selection_end_column_within_line - start_of_visual_line; @@ -536,6 +556,7 @@ void TextEditor::paint_event(PaintEvent& event) } } } + ++visual_line_index; return IterationDecision::Continue; }); @@ -1718,4 +1739,12 @@ void TextEditor::set_icon(const Gfx::Bitmap* icon) update(); } +void TextEditor::set_visualize_trailing_whitespace(bool enabled) +{ + if (m_visualize_trailing_whitespace == enabled) + return; + m_visualize_trailing_whitespace = enabled; + update(); +} + } diff --git a/Libraries/LibGUI/TextEditor.h b/Libraries/LibGUI/TextEditor.h index fdb95b72e7..56dd2377c4 100644 --- a/Libraries/LibGUI/TextEditor.h +++ b/Libraries/LibGUI/TextEditor.h @@ -60,6 +60,9 @@ public: virtual void set_document(TextDocument&); + void set_visualize_trailing_whitespace(bool); + bool visualize_trailing_whitespace() const { return m_visualize_trailing_whitespace; } + bool has_visible_list() const { return m_has_visible_list; } void set_has_visible_list(bool); bool has_open_button() const { return m_has_open_button; } @@ -274,6 +277,7 @@ private: bool m_line_wrapping_enabled { false }; bool m_has_visible_list { false }; bool m_has_open_button { false }; + bool m_visualize_trailing_whitespace { true }; int m_line_spacing { 4 }; size_t m_soft_tab_width { 4 }; int m_horizontal_content_padding { 3 }; |