Skip to content

Commit 15349a3

Browse files
committed
LibGUI: Add ability to assign a menu to a GUI::Button
When a button has a menu, it opens the menu on mousedown and the menu gains input focus immediately. While the menu is open, the button is painted in a pressed state.
1 parent 9b740f2 commit 15349a3

File tree

2 files changed

+36
-5
lines changed

2 files changed

+36
-5
lines changed

Userland/Libraries/LibGUI/Button.cpp

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
2+
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -28,6 +28,7 @@
2828
#include <LibGUI/Action.h>
2929
#include <LibGUI/ActionGroup.h>
3030
#include <LibGUI/Button.h>
31+
#include <LibGUI/Menu.h>
3132
#include <LibGUI/Painter.h>
3233
#include <LibGfx/Font.h>
3334
#include <LibGfx/FontDatabase.h>
@@ -62,7 +63,9 @@ void Button::paint_event(PaintEvent& event)
6263
Painter painter(*this);
6364
painter.add_clip_rect(event.rect());
6465

65-
Gfx::StylePainter::paint_button(painter, rect(), palette(), m_button_style, is_being_pressed(), is_hovered(), is_checked(), is_enabled(), is_focused());
66+
bool paint_pressed = is_being_pressed() || (m_menu && m_menu->is_visible());
67+
68+
Gfx::StylePainter::paint_button(painter, rect(), palette(), m_button_style, paint_pressed, is_hovered(), is_checked(), is_enabled(), is_focused());
6669

6770
if (text().is_empty() && !m_icon)
6871
return;
@@ -72,9 +75,9 @@ void Button::paint_event(PaintEvent& event)
7275
if (m_icon && !text().is_empty())
7376
icon_location.set_x(content_rect.x());
7477

75-
if (is_being_pressed() || is_checked())
78+
if (paint_pressed || is_checked()) {
7679
painter.translate(1, 1);
77-
else if (m_icon && is_enabled() && is_hovered() && button_style() == Gfx::ButtonStyle::CoolBar) {
80+
} else if (m_icon && is_enabled() && is_hovered() && button_style() == Gfx::ButtonStyle::CoolBar) {
7881
auto shadow_color = palette().button().darkened(0.7f);
7982
painter.blit_filtered(icon_location.translated(1, 1), *m_icon, m_icon->rect(), [&shadow_color](auto) {
8083
return shadow_color;
@@ -167,4 +170,28 @@ bool Button::is_uncheckable() const
167170
return m_action->group()->is_unchecking_allowed();
168171
}
169172

173+
void Button::set_menu(RefPtr<GUI::Menu> menu)
174+
{
175+
if (m_menu == menu)
176+
return;
177+
if (m_menu)
178+
m_menu->on_visibility_change = nullptr;
179+
m_menu = menu;
180+
if (m_menu) {
181+
m_menu->on_visibility_change = [&](bool) {
182+
update();
183+
};
184+
}
185+
}
186+
187+
void Button::mousedown_event(MouseEvent& event)
188+
{
189+
if (m_menu) {
190+
m_menu->popup(screen_relative_rect().top_left());
191+
update();
192+
return;
193+
}
194+
AbstractButton::mousedown_event(event);
195+
}
196+
170197
}

Userland/Libraries/LibGUI/Button.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
2+
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -63,12 +63,16 @@ class Button : public AbstractButton {
6363
int icon_spacing() const { return m_icon_spacing; }
6464
void set_icon_spacing(int spacing) { m_icon_spacing = spacing; }
6565

66+
void set_menu(RefPtr<GUI::Menu>);
67+
6668
protected:
6769
explicit Button(String text = {});
70+
virtual void mousedown_event(MouseEvent&) override;
6871
virtual void paint_event(PaintEvent&) override;
6972

7073
private:
7174
RefPtr<Gfx::Bitmap> m_icon;
75+
RefPtr<GUI::Menu> m_menu;
7276
Gfx::ButtonStyle m_button_style { Gfx::ButtonStyle::Normal };
7377
Gfx::TextAlignment m_text_alignment { Gfx::TextAlignment::Center };
7478
WeakPtr<Action> m_action;

0 commit comments

Comments
 (0)