From b7dfa8322319977908c9f210d3561b6f1a373ec3 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 26 Oct 2020 20:43:59 +0100 Subject: [PATCH] LibGUI+LibGfx: Improve focus rect appearance Draw a dotted focus rect to make it stand out more. Also make it much larger on regular text-only GUI::Buttons. --- Libraries/LibGUI/AbstractButton.cpp | 2 -- Libraries/LibGUI/Button.cpp | 9 +++++++++ Libraries/LibGUI/CheckBox.cpp | 3 +++ Libraries/LibGUI/RadioButton.cpp | 3 +++ Libraries/LibGfx/Painter.cpp | 31 +++++++++++++++++++++++++++++ Libraries/LibGfx/Painter.h | 1 + 6 files changed, 47 insertions(+), 2 deletions(-) diff --git a/Libraries/LibGUI/AbstractButton.cpp b/Libraries/LibGUI/AbstractButton.cpp index 36dc287941..8b883a25e3 100644 --- a/Libraries/LibGUI/AbstractButton.cpp +++ b/Libraries/LibGUI/AbstractButton.cpp @@ -176,8 +176,6 @@ void AbstractButton::paint_text(Painter& painter, const Gfx::IntRect& rect, cons if (text().is_empty()) return; painter.draw_text(clipped_rect, text(), font, text_alignment, palette().color(foreground_role()), Gfx::TextElision::Right); - if (is_focused()) - painter.draw_rect(clipped_rect.inflated(6, 4), palette().focus_outline()); } void AbstractButton::change_event(Event& event) diff --git a/Libraries/LibGUI/Button.cpp b/Libraries/LibGUI/Button.cpp index 1ff8f18194..f8a4aba224 100644 --- a/Libraries/LibGUI/Button.cpp +++ b/Libraries/LibGUI/Button.cpp @@ -92,6 +92,15 @@ void Button::paint_event(PaintEvent& event) text_rect.set_width(content_rect.width()); text_rect.align_within(content_rect, text_alignment()); paint_text(painter, text_rect, font, text_alignment()); + + if (is_focused()) { + Gfx::IntRect focus_rect; + if (m_icon) + focus_rect = text_rect.inflated(6, 6); + else + focus_rect = rect().shrunken(8, 8); + painter.draw_focus_rect(focus_rect, palette().focus_outline()); + } } void Button::click(unsigned modifiers) diff --git a/Libraries/LibGUI/CheckBox.cpp b/Libraries/LibGUI/CheckBox.cpp index 3ff28097ec..caa37ea95a 100644 --- a/Libraries/LibGUI/CheckBox.cpp +++ b/Libraries/LibGUI/CheckBox.cpp @@ -70,6 +70,9 @@ void CheckBox::paint_event(PaintEvent& event) Gfx::StylePainter::paint_check_box(painter, box_rect, palette(), is_enabled(), is_checked(), is_being_pressed()); paint_text(painter, text_rect, font(), Gfx::TextAlignment::TopLeft); + + if (is_focused()) + painter.draw_focus_rect(text_rect.inflated(6, 6), palette().focus_outline()); } void CheckBox::click(unsigned) diff --git a/Libraries/LibGUI/RadioButton.cpp b/Libraries/LibGUI/RadioButton.cpp index d7fcc5f695..63fe1d4362 100644 --- a/Libraries/LibGUI/RadioButton.cpp +++ b/Libraries/LibGUI/RadioButton.cpp @@ -66,6 +66,9 @@ void RadioButton::paint_event(PaintEvent& event) Gfx::IntRect text_rect { circle_rect.right() + 4, 0, font().width(text()), font().glyph_height() }; text_rect.center_vertically_within(rect()); paint_text(painter, text_rect, font(), Gfx::TextAlignment::TopLeft); + + if (is_focused()) + painter.draw_focus_rect(text_rect.inflated(6, 6), palette().focus_outline()); } template diff --git a/Libraries/LibGfx/Painter.cpp b/Libraries/LibGfx/Painter.cpp index 2d73d9d559..38655da1ec 100644 --- a/Libraries/LibGfx/Painter.cpp +++ b/Libraries/LibGfx/Painter.cpp @@ -279,6 +279,37 @@ void Painter::draw_ellipse_intersecting(const IntRect& rect, Color color, int th } } +template +static void for_each_pixel_around_rect_clockwise(const RectType& rect, Callback callback) +{ + if (rect.is_empty()) + return; + for (auto x = rect.left(); x <= rect.right(); ++x) { + callback(x, rect.top()); + } + for (auto y = rect.top() + 1; y <= rect.bottom(); ++y) { + callback(rect.right(), y); + } + for (auto x = rect.right() - 1; x >= rect.left(); --x) { + callback(x, rect.bottom()); + } + for (auto y = rect.bottom() - 1; y > rect.top(); --y) { + callback(rect.left(), y); + } +} + +void Painter::draw_focus_rect(const IntRect& rect, Color color) +{ + if (rect.is_empty()) + return; + bool state = false; + for_each_pixel_around_rect_clockwise(rect, [&](auto x, auto y) { + if (state) + set_pixel(x, y, color); + state = !state; + }); +} + void Painter::draw_rect(const IntRect& a_rect, Color color, bool rough) { IntRect rect = a_rect.translated(translation()); diff --git a/Libraries/LibGfx/Painter.h b/Libraries/LibGfx/Painter.h index 4983f0ef8b..d2b71cb74a 100644 --- a/Libraries/LibGfx/Painter.h +++ b/Libraries/LibGfx/Painter.h @@ -58,6 +58,7 @@ public: void fill_rect_with_gradient(const IntRect&, Color gradient_start, Color gradient_end); void fill_ellipse(const IntRect&, Color); void draw_rect(const IntRect&, Color, bool rough = false); + void draw_focus_rect(const IntRect&, Color); void draw_bitmap(const IntPoint&, const CharacterBitmap&, Color = Color()); void draw_bitmap(const IntPoint&, const GlyphBitmap&, Color = Color()); void draw_scaled_bitmap(const IntRect& dst_rect, const Gfx::Bitmap&, const IntRect& src_rect, float opacity = 1.0f);