diff options
-rw-r--r-- | Base/res/themes/Basalt.ini | 2 | ||||
-rw-r--r-- | Base/res/themes/Coffee.ini | 2 | ||||
-rw-r--r-- | Base/res/themes/Dark.ini | 2 | ||||
-rw-r--r-- | Base/res/themes/Default.ini | 2 | ||||
-rw-r--r-- | Base/res/themes/Desert.ini | 2 | ||||
-rw-r--r-- | Base/res/themes/Faux Pas.ini | 2 | ||||
-rw-r--r-- | Base/res/themes/Light.ini | 2 | ||||
-rw-r--r-- | Base/res/themes/Nord.ini | 2 | ||||
-rw-r--r-- | Base/res/themes/Plum.ini | 2 | ||||
-rw-r--r-- | Base/res/themes/Redmond 2000.ini | 2 | ||||
-rw-r--r-- | Base/res/themes/Redmond.ini | 2 | ||||
-rw-r--r-- | Base/res/themes/Silver.ini | 2 | ||||
-rw-r--r-- | Base/res/themes/Sunshine.ini | 2 | ||||
-rw-r--r-- | Userland/DevTools/HackStudio/Editor.cpp | 22 | ||||
-rw-r--r-- | Userland/DevTools/HackStudio/Editor.h | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibGUI/TextEditor.cpp | 66 | ||||
-rw-r--r-- | Userland/Libraries/LibGUI/TextEditor.h | 8 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/Palette.h | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/SystemTheme.h | 2 |
19 files changed, 103 insertions, 25 deletions
diff --git a/Base/res/themes/Basalt.ini b/Base/res/themes/Basalt.ini index 5c2be3d4e8..794c36d861 100644 --- a/Base/res/themes/Basalt.ini +++ b/Base/res/themes/Basalt.ini @@ -47,6 +47,8 @@ Link=#88c ActiveLink=#c88 VisitedLink=#c8c PlaceholderText=#171717 +Gutter=#0f0f0f +GutterBorder=#2f2f2f Ruler=#0f0f0f RulerBorder=#2f2f2f RulerActiveText=white diff --git a/Base/res/themes/Coffee.ini b/Base/res/themes/Coffee.ini index 19f3c37a4c..ccbaaff429 100644 --- a/Base/res/themes/Coffee.ini +++ b/Base/res/themes/Coffee.ini @@ -43,6 +43,8 @@ RubberBandBorder=#594fbf Link=#0000ff ActiveLink=#ee0000 VisitedLink=#551a8b +Gutter=#aeb2c3 +GutterBorder=#5d6069 Ruler=#aeb2c3 RulerBorder=#5d6069 RulerActiveText=#5d6069 diff --git a/Base/res/themes/Dark.ini b/Base/res/themes/Dark.ini index 18233c1448..44b8c54bfd 100644 --- a/Base/res/themes/Dark.ini +++ b/Base/res/themes/Dark.ini @@ -39,6 +39,8 @@ Link=#88c ActiveLink=#c88 VisitedLink=#c8c PlaceholderText=#2e2f30 +Gutter=#505050 +GutterBorder=#666666 Ruler=#505050 RulerBorder=#666666 RulerActiveText=white diff --git a/Base/res/themes/Default.ini b/Base/res/themes/Default.ini index 096ec148d8..c628317c77 100644 --- a/Base/res/themes/Default.ini +++ b/Base/res/themes/Default.ini @@ -47,6 +47,8 @@ RubberBandBorder=#6e2209 Link=blue ActiveLink=red VisitedLink=magenta +Gutter=#d4d0c8 +GutterBorder=#404040 Ruler=#d4d0c8 RulerBorder=#404040 RulerActiveText=#404040 diff --git a/Base/res/themes/Desert.ini b/Base/res/themes/Desert.ini index 5e4c3b8507..42233375d9 100644 --- a/Base/res/themes/Desert.ini +++ b/Base/res/themes/Desert.ini @@ -47,6 +47,8 @@ RubberBandBorder=#6e2209 Link=blue ActiveLink=red VisitedLink=magenta +Gutter=#d5ccbb +GutterBorder=#404040 Ruler=#d5ccbb RulerBorder=#404040 RulerActiveText=#404040 diff --git a/Base/res/themes/Faux Pas.ini b/Base/res/themes/Faux Pas.ini index 463f301e5b..b5c19639ce 100644 --- a/Base/res/themes/Faux Pas.ini +++ b/Base/res/themes/Faux Pas.ini @@ -39,6 +39,8 @@ RubberBandBorder=black Link=#0000b0 ActiveLink=#2020d0 VisitedLink=#2000b0 +Gutter=#808080 +GutterBorder=black Ruler=#808080 RulerBorder=black RulerActiveText=#404040 diff --git a/Base/res/themes/Light.ini b/Base/res/themes/Light.ini index c3a294c4e3..8a55d0bcb4 100644 --- a/Base/res/themes/Light.ini +++ b/Base/res/themes/Light.ini @@ -47,6 +47,8 @@ RubberBandBorder=#598dc6 Link=blue ActiveLink=red VisitedLink=magenta +Gutter=#d4d0c8 +GutterBorder=#404040 Ruler=#d4d0c8 RulerBorder=#404040 RulerActiveText=#404040 diff --git a/Base/res/themes/Nord.ini b/Base/res/themes/Nord.ini index d28b7eb246..693a85e86f 100644 --- a/Base/res/themes/Nord.ini +++ b/Base/res/themes/Nord.ini @@ -39,6 +39,8 @@ RubberBandBorder=#4c566a Link=#7e9dbc ActiveLink=#95adc5 VisitedLink=#3b4e68 +Gutter=#434c5e +GutterBorder=#3b4252 Ruler=#434c5e RulerBorder=#3b4252 RulerActiveText=#95adc5 diff --git a/Base/res/themes/Plum.ini b/Base/res/themes/Plum.ini index 7726f244a8..4c11a21435 100644 --- a/Base/res/themes/Plum.ini +++ b/Base/res/themes/Plum.ini @@ -47,6 +47,8 @@ RubberBandBorder=#50096e Link=blue ActiveLink=red VisitedLink=magenta +Gutter=#d4d0c8 +GutterBorder=#404040 Ruler=#d4d0c8 RulerBorder=#404040 RulerActiveText=#404040 diff --git a/Base/res/themes/Redmond 2000.ini b/Base/res/themes/Redmond 2000.ini index fa94580974..e12ae2f2de 100644 --- a/Base/res/themes/Redmond 2000.ini +++ b/Base/res/themes/Redmond 2000.ini @@ -43,6 +43,8 @@ RubberBandBorder=#09226e Link=blue ActiveLink=red VisitedLink=magenta +Gutter=#d4d0c8 +GutterBorder=#404040 Ruler=#d4d0c8 RulerBorder=#404040 RulerActiveText=#404040 diff --git a/Base/res/themes/Redmond.ini b/Base/res/themes/Redmond.ini index 7fc008ed1b..7125974d61 100644 --- a/Base/res/themes/Redmond.ini +++ b/Base/res/themes/Redmond.ini @@ -43,6 +43,8 @@ RubberBandBorder=black Link=blue ActiveLink=red VisitedLink=magenta +Gutter=#d4d0c8 +GutterBorder=#404040 Ruler=#d4d0c8 RulerBorder=#404040 RulerActiveText=#404040 diff --git a/Base/res/themes/Silver.ini b/Base/res/themes/Silver.ini index 6c1a4f1804..d9bf711e17 100644 --- a/Base/res/themes/Silver.ini +++ b/Base/res/themes/Silver.ini @@ -39,6 +39,8 @@ RubberBandBorder=#6e2209 Link=blue ActiveLink=red VisitedLink=magenta +Gutter=#d4d0c8 +GutterBorder=#404040 Ruler=#d4d0c8 RulerBorder=#404040 RulerActiveText=#404040 diff --git a/Base/res/themes/Sunshine.ini b/Base/res/themes/Sunshine.ini index 08c03795ec..1107247823 100644 --- a/Base/res/themes/Sunshine.ini +++ b/Base/res/themes/Sunshine.ini @@ -43,6 +43,8 @@ RubberBandBorder=#007f7f Link=#88c ActiveLink=#c88 VisitedLink=#c8c +Gutter=#aeb2c3 +GutterBorder=#5d6069 Ruler=#aeb2c3 RulerBorder=#5d6069 RulerActiveText=#5d6069 diff --git a/Userland/DevTools/HackStudio/Editor.cpp b/Userland/DevTools/HackStudio/Editor.cpp index cd3a3a61b0..0ae83188e7 100644 --- a/Userland/DevTools/HackStudio/Editor.cpp +++ b/Userland/DevTools/HackStudio/Editor.cpp @@ -66,6 +66,8 @@ Editor::Editor() }); add_custom_context_menu_action(*m_evaluate_expression_action); add_custom_context_menu_action(*m_move_execution_to_line_action); + + set_gutter_visible(true); } Editor::~Editor() @@ -95,15 +97,9 @@ void Editor::focusout_event(GUI::FocusEvent& event) GUI::TextEditor::focusout_event(event); } -Gfx::IntRect Editor::breakpoint_icon_rect(size_t line_number) const +Gfx::IntRect Editor::gutter_icon_rect(size_t line_number) const { - auto ruler_line_rect = ruler_content_rect(line_number); - - auto scroll_value = vertical_scrollbar().value(); - ruler_line_rect = ruler_line_rect.translated({ 0, -scroll_value }); - auto center = ruler_line_rect.center().translated({ ruler_line_rect.width() - 10, -line_spacing() - 3 }); - constexpr int size = 32; - return { center.x() - size / 2, center.y() - size / 2, size, size }; + return gutter_content_rect(line_number).translated(ruler_width() + gutter_width() + frame_thickness(), -vertical_scrollbar().value()); } void Editor::paint_event(GUI::PaintEvent& event) @@ -122,7 +118,7 @@ void Editor::paint_event(GUI::PaintEvent& event) painter.draw_rect(rect, palette().selection()); } - if (ruler_visible()) { + if (gutter_visible()) { 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(); for (size_t line : breakpoint_lines()) { @@ -130,11 +126,11 @@ void Editor::paint_event(GUI::PaintEvent& event) continue; } const auto& icon = breakpoint_icon_bitmap(); - painter.blit(breakpoint_icon_rect(line).center(), icon, icon.rect()); + painter.blit(gutter_icon_rect(line).top_left(), icon, icon.rect()); } if (execution_position().has_value()) { const auto& icon = current_position_icon_bitmap(); - painter.blit(breakpoint_icon_rect(execution_position().value()).center(), icon, icon.rect()); + painter.blit(gutter_icon_rect(execution_position().value()).top_left(), icon, icon.rect()); } } } @@ -379,7 +375,7 @@ void Editor::set_execution_position(size_t line_number) { code_document().set_execution_position(line_number); scroll_position_into_view({ line_number, 0 }); - update(breakpoint_icon_rect(line_number)); + update(gutter_icon_rect(line_number)); } void Editor::clear_execution_position() @@ -389,7 +385,7 @@ void Editor::clear_execution_position() } size_t previous_position = execution_position().value(); code_document().clear_execution_position(); - update(breakpoint_icon_rect(previous_position)); + update(gutter_icon_rect(previous_position)); } const Gfx::Bitmap& Editor::breakpoint_icon_bitmap() diff --git a/Userland/DevTools/HackStudio/Editor.h b/Userland/DevTools/HackStudio/Editor.h index 036287f97b..be66ca7839 100644 --- a/Userland/DevTools/HackStudio/Editor.h +++ b/Userland/DevTools/HackStudio/Editor.h @@ -68,7 +68,7 @@ private: void on_navigatable_link_click(const GUI::TextDocumentSpan&); void on_identifier_click(const GUI::TextDocumentSpan&); - Gfx::IntRect breakpoint_icon_rect(size_t line_number) const; + Gfx::IntRect gutter_icon_rect(size_t line_number) const; static const Gfx::Bitmap& breakpoint_icon_bitmap(); static const Gfx::Bitmap& current_position_icon_bitmap(); 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 }; diff --git a/Userland/Libraries/LibGfx/Palette.h b/Userland/Libraries/LibGfx/Palette.h index fe4cb726fb..f60b698c76 100644 --- a/Userland/Libraries/LibGfx/Palette.h +++ b/Userland/Libraries/LibGfx/Palette.h @@ -92,6 +92,8 @@ public: Color hover_highlight() const { return color(ColorRole::HoverHighlight); } Color rubber_band_fill() const { return color(ColorRole::RubberBandFill); } Color rubber_band_border() const { return color(ColorRole::RubberBandBorder); } + Color gutter() const { return color(ColorRole::Gutter); } + Color gutter_border() const { return color(ColorRole::Gutter); } Color ruler() const { return color(ColorRole::Ruler); } Color ruler_border() const { return color(ColorRole::RulerBorder); } Color ruler_active_text() const { return color(ColorRole::RulerActiveText); } diff --git a/Userland/Libraries/LibGfx/SystemTheme.h b/Userland/Libraries/LibGfx/SystemTheme.h index 8c1eca5132..f155bd9a1b 100644 --- a/Userland/Libraries/LibGfx/SystemTheme.h +++ b/Userland/Libraries/LibGfx/SystemTheme.h @@ -27,6 +27,8 @@ namespace Gfx { C(ButtonText) \ C(DesktopBackground) \ C(FocusOutline) \ + C(Gutter) \ + C(GutterBorder) \ C(HighlightWindowBorder1) \ C(HighlightWindowBorder2) \ C(HighlightWindowTitle) \ |