summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-09-01 19:10:55 +0200
committerAndreas Kling <kling@serenityos.org>2020-09-01 23:55:35 +0200
commitaa70d8c217d9b6bfc9634835d59d0cb9eea0a192 (patch)
treeb01b401ebd4008f146cbcf5ea335f851824eaf38
parent08f1ea3e45db6d00814d7fced935d0e53afc9d99 (diff)
downloadserenity-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.cpp17
-rw-r--r--Libraries/LibGUI/TextDocument.h2
-rw-r--r--Libraries/LibGUI/TextEditor.cpp29
-rw-r--r--Libraries/LibGUI/TextEditor.h4
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 };