Explorar o código

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.
Andreas Kling %!s(int64=4) %!d(string=hai) anos
pai
achega
b7dfa83223

+ 0 - 2
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)

+ 9 - 0
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)

+ 3 - 0
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)

+ 3 - 0
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<typename Callback>

+ 31 - 0
Libraries/LibGfx/Painter.cpp

@@ -279,6 +279,37 @@ void Painter::draw_ellipse_intersecting(const IntRect& rect, Color color, int th
     }
 }
 
+template<typename RectType, typename Callback>
+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());

+ 1 - 0
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);