diff options
author | Dmitrii Ubskii <ubskydm@gmail.com> | 2021-06-12 04:50:23 +0300 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-06-13 12:33:15 +0100 |
commit | 8501617fcb750bc8f540dc524faf47ce5b5961c9 (patch) | |
tree | 08cf3feac135e00e8ee302a2f1ba3db7af4816e2 /Userland/Libraries/LibGUI | |
parent | 920b4d730e04a37e7247ce9a456af39a16705188 (diff) | |
download | serenity-8501617fcb750bc8f540dc524faf47ce5b5961c9.zip |
LibGUI+HackStudio: Make gutter a first class element
Gutter -- a space left of the text, before the ruler -- is not a part of
the ruler, nor should it be treated as such. This commit implements
gutter handling in LibGUI::TextEditor as part of mild cleaning up of the
gutter handling (breakpoint icons) in HackStudio's Editor.
This commit also enables separate theming of the gutter.
Diffstat (limited to 'Userland/Libraries/LibGUI')
-rw-r--r-- | Userland/Libraries/LibGUI/TextEditor.cpp | 66 | ||||
-rw-r--r-- | Userland/Libraries/LibGUI/TextEditor.h | 8 |
2 files changed, 63 insertions, 11 deletions
diff --git a/Userland/Libraries/LibGUI/TextEditor.cpp b/Userland/Libraries/LibGUI/TextEditor.cpp index cd475d994c..5801d9185a 100644 --- a/Userland/Libraries/LibGUI/TextEditor.cpp +++ b/Userland/Libraries/LibGUI/TextEditor.cpp @@ -127,7 +127,7 @@ void TextEditor::update_content_size() content_width = max(frame_inner_rect().width(), content_width); set_content_size({ content_width, content_height }); - set_size_occupied_by_fixed_elements({ ruler_width(), 0 }); + set_size_occupied_by_fixed_elements({ ruler_width() + gutter_width(), 0 }); } TextPosition TextEditor::text_position_at_content_position(const Gfx::IntPoint& content_position) const @@ -195,7 +195,7 @@ TextPosition TextEditor::text_position_at(const Gfx::IntPoint& widget_position) { auto content_position = widget_position; content_position.translate_by(horizontal_scrollbar().value(), vertical_scrollbar().value()); - content_position.translate_by(-(m_horizontal_content_padding + ruler_width()), 0); + content_position.translate_by(-(m_horizontal_content_padding + ruler_width() + gutter_width()), 0); content_position.translate_by(-frame_thickness(), -frame_thickness()); return text_position_at_content_position(content_position); } @@ -339,10 +339,17 @@ int TextEditor::ruler_width() const if (!m_ruler_visible) return 0; int line_count_digits = static_cast<int>(log10(line_count())) + 1; - constexpr size_t padding = 20; + constexpr size_t padding = 5; return line_count() < 10 ? (line_count_digits + 1) * font().glyph_width('x') + padding : line_count_digits * font().glyph_width('x') + padding; } +int TextEditor::gutter_width() const +{ + if (!m_gutter_visible) + return 0; + return line_height(); // square gutter +} + Gfx::IntRect TextEditor::ruler_content_rect(size_t line_index) const { if (!m_ruler_visible) @@ -355,9 +362,26 @@ Gfx::IntRect TextEditor::ruler_content_rect(size_t line_index) const }; } +Gfx::IntRect TextEditor::gutter_content_rect(size_t line_index) const +{ + if (!m_gutter_visible) + return {}; + return { + 0 - ruler_width() - gutter_width() + horizontal_scrollbar().value(), + line_content_rect(line_index).y(), + gutter_width(), + line_content_rect(line_index).height() + }; +} + Gfx::IntRect TextEditor::ruler_rect_in_inner_coordinates() const { - return { 0, 0, ruler_width(), height() - height_occupied_by_horizontal_scrollbar() }; + return { gutter_width(), 0, ruler_width(), height() - height_occupied_by_horizontal_scrollbar() }; +} + +Gfx::IntRect TextEditor::gutter_rect_in_inner_coordinates() const +{ + return { 0, 0, gutter_width(), height() - height_occupied_by_horizontal_scrollbar() }; } Gfx::IntRect TextEditor::visible_text_rect_in_inner_coordinates() const @@ -398,16 +422,22 @@ void TextEditor::paint_event(PaintEvent& event) painter.translate(frame_thickness(), frame_thickness()); - auto ruler_rect = ruler_rect_in_inner_coordinates(); + if (m_gutter_visible) { + auto gutter_rect = gutter_rect_in_inner_coordinates(); + painter.fill_rect(gutter_rect, palette().gutter()); + if (!m_ruler_visible) + painter.draw_line(gutter_rect.top_right(), gutter_rect.bottom_right(), palette().gutter_border()); + } if (m_ruler_visible) { + auto ruler_rect = ruler_rect_in_inner_coordinates(); painter.fill_rect(ruler_rect, palette().ruler()); painter.draw_line(ruler_rect.top_right(), ruler_rect.bottom_right(), palette().ruler_border()); } painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value()); - if (m_ruler_visible) - painter.translate(ruler_width(), 0); + painter.translate(gutter_width(), 0); + painter.translate(ruler_width(), 0); size_t first_visible_line = text_position_at(event.rect().top_left()).line(); size_t last_visible_line = text_position_at(event.rect().bottom_right()).line(); @@ -428,14 +458,19 @@ void TextEditor::paint_event(PaintEvent& event) } } + auto text_left = 0; + if (m_ruler_visible) + text_left = ruler_rect_in_inner_coordinates().right() + 1; + else if (m_gutter_visible) + text_left = gutter_rect_in_inner_coordinates().right() + 1; + text_left += frame_thickness(); + Gfx::IntRect text_clip_rect { - (m_ruler_visible ? (ruler_rect_in_inner_coordinates().right() + frame_thickness() + 1) : frame_thickness()), + 0, frame_thickness(), - width() - width_occupied_by_vertical_scrollbar() - ruler_width(), + width() - width_occupied_by_vertical_scrollbar() - text_left, height() - height_occupied_by_horizontal_scrollbar() }; - if (m_ruler_visible) - text_clip_rect.translate_by(-ruler_width(), 0); text_clip_rect.translate_by(horizontal_scrollbar().value(), vertical_scrollbar().value()); painter.add_clip_rect(text_clip_rect); @@ -1860,6 +1895,15 @@ void TextEditor::set_ruler_visible(bool visible) update(); } +void TextEditor::set_gutter_visible(bool visible) +{ + if (m_gutter_visible == visible) + return; + m_gutter_visible = visible; + recompute_all_visual_lines(); + update(); +} + void TextEditor::undo() { clear_selection(); diff --git a/Userland/Libraries/LibGUI/TextEditor.h b/Userland/Libraries/LibGUI/TextEditor.h index 72f6a46b5a..591bff461f 100644 --- a/Userland/Libraries/LibGUI/TextEditor.h +++ b/Userland/Libraries/LibGUI/TextEditor.h @@ -90,6 +90,9 @@ public: bool is_ruler_visible() const { return m_ruler_visible; } void set_ruler_visible(bool); + bool is_gutter_visible() const { return m_gutter_visible; } + void set_gutter_visible(bool); + void set_icon(const Gfx::Bitmap*); const Gfx::Bitmap* icon() const { return m_icon; } @@ -209,11 +212,14 @@ protected: virtual void theme_change_event(ThemeChangeEvent&) override; virtual void cursor_did_change() { } Gfx::IntRect ruler_content_rect(size_t line) const; + Gfx::IntRect gutter_content_rect(size_t line) const; TextPosition text_position_at(const Gfx::IntPoint&) const; bool ruler_visible() const { return m_ruler_visible; } + bool gutter_visible() const { return m_gutter_visible; } Gfx::IntRect content_rect_for_position(const TextPosition&) const; int ruler_width() const; + int gutter_width() const; private: friend class TextDocumentLine; @@ -272,6 +278,7 @@ private: void delete_selection(); int content_x_for_position(const TextPosition&) const; Gfx::IntRect ruler_rect_in_inner_coordinates() const; + Gfx::IntRect gutter_rect_in_inner_coordinates() const; Gfx::IntRect visible_text_rect_in_inner_coordinates() const; void recompute_all_visual_lines(); void ensure_cursor_is_valid(); @@ -302,6 +309,7 @@ private: bool m_cursor_state { true }; bool m_in_drag_select { false }; bool m_ruler_visible { false }; + bool m_gutter_visible { false }; bool m_has_pending_change_notification { false }; bool m_automatic_indentation_enabled { false }; WrappingMode m_wrapping_mode { WrappingMode::NoWrap }; |