mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 19:22:45 +00:00 
			
		
		
		
	LibGUI+WindowServer: Make it possible to have checkable GActions.
They show up as checkable GButtons in GToolBar, and with (or without) check marks in menus. There are a bunch of places to make use of this. This patch only takes advantage of it in the FileManager for the view type actions.
This commit is contained in:
		
							parent
							
								
									9ff36afeaa
								
							
						
					
					
						commit
						8f81a3f9dd
					
				
					 15 changed files with 148 additions and 20 deletions
				
			
		|  | @ -98,13 +98,24 @@ int main(int argc, char** argv) | |||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     auto view_as_table_action = GAction::create("Table view", { Mod_Ctrl, KeyCode::Key_L }, GraphicsBitmap::load_from_file("/res/icons/16x16/table-view.png"), [&] (const GAction&) { | ||||
|         directory_view->set_view_mode(DirectoryView::ViewMode::List); | ||||
|     }); | ||||
|     RetainPtr<GAction> view_as_table_action; | ||||
|     RetainPtr<GAction> view_as_icons_action; | ||||
| 
 | ||||
|     auto view_as_icons_action = GAction::create("Icon view", { Mod_Ctrl, KeyCode::Key_I }, GraphicsBitmap::load_from_file("/res/icons/16x16/icon-view.png"), [&] (const GAction&) { | ||||
|         directory_view->set_view_mode(DirectoryView::ViewMode::Icon); | ||||
|     view_as_table_action = GAction::create("Table view", { Mod_Ctrl, KeyCode::Key_L }, GraphicsBitmap::load_from_file("/res/icons/16x16/table-view.png"), [&] (const GAction&) { | ||||
|         directory_view->set_view_mode(DirectoryView::ViewMode::List); | ||||
|         view_as_icons_action->set_checked(false); | ||||
|         view_as_table_action->set_checked(true); | ||||
|     }); | ||||
|     view_as_table_action->set_checkable(true); | ||||
|     view_as_table_action->set_checked(false); | ||||
| 
 | ||||
|     view_as_icons_action = GAction::create("Icon view", { Mod_Ctrl, KeyCode::Key_I }, GraphicsBitmap::load_from_file("/res/icons/16x16/icon-view.png"), [&] (const GAction&) { | ||||
|         directory_view->set_view_mode(DirectoryView::ViewMode::Icon); | ||||
|         view_as_table_action->set_checked(false); | ||||
|         view_as_icons_action->set_checked(true); | ||||
|     }); | ||||
|     view_as_icons_action->set_checkable(true); | ||||
|     view_as_icons_action->set_checked(true); | ||||
| 
 | ||||
|     auto copy_action = GAction::create("Copy", GraphicsBitmap::load_from_file("/res/icons/16x16/edit-copy.png"), [] (const GAction&) { | ||||
|         dbgprintf("'Copy' action activated!\n"); | ||||
|  | @ -138,8 +149,8 @@ int main(int argc, char** argv) | |||
|     menubar->add_menu(move(file_menu)); | ||||
| 
 | ||||
|     auto view_menu = make<GMenu>("View"); | ||||
|     view_menu->add_action(view_as_table_action.copy_ref()); | ||||
|     view_menu->add_action(view_as_icons_action.copy_ref()); | ||||
|     view_menu->add_action(*view_as_icons_action); | ||||
|     view_menu->add_action(*view_as_table_action); | ||||
|     menubar->add_menu(move(view_menu)); | ||||
| 
 | ||||
|     auto go_menu = make<GMenu>("Go"); | ||||
|  | @ -165,8 +176,8 @@ int main(int argc, char** argv) | |||
|     main_toolbar->add_action(delete_action.copy_ref()); | ||||
| 
 | ||||
|     main_toolbar->add_separator(); | ||||
|     main_toolbar->add_action(view_as_icons_action.copy_ref()); | ||||
|     main_toolbar->add_action(view_as_table_action.copy_ref()); | ||||
|     main_toolbar->add_action(*view_as_icons_action); | ||||
|     main_toolbar->add_action(*view_as_table_action); | ||||
| 
 | ||||
|     directory_view->on_path_change = [window, location_textbox, &file_system_model, tree_view] (const String& new_path) { | ||||
|         window->set_title(String::format("FileManager: %s", new_path.characters())); | ||||
|  |  | |||
|  | @ -106,3 +106,16 @@ void GAction::set_enabled(bool enabled) | |||
|         item.set_enabled(enabled); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| void GAction::set_checked(bool checked) | ||||
| { | ||||
|     if (m_checked == checked) | ||||
|         return; | ||||
|     m_checked = checked; | ||||
|     for_each_toolbar_button([checked] (GButton& button) { | ||||
|         button.set_checked(checked); | ||||
|     }); | ||||
|     for_each_menu_item([checked] (GMenuItem& item) { | ||||
|         item.set_checked(checked); | ||||
|     }); | ||||
| } | ||||
|  |  | |||
|  | @ -59,6 +59,12 @@ public: | |||
|     bool is_enabled() const { return m_enabled; } | ||||
|     void set_enabled(bool); | ||||
| 
 | ||||
|     bool is_checkable() const { return m_checkable; } | ||||
|     void set_checkable(bool checkable) { m_checkable = checkable; } | ||||
| 
 | ||||
|     bool is_checked() const { ASSERT(is_checkable()); return m_checked; } | ||||
|     void set_checked(bool); | ||||
| 
 | ||||
|     void register_button(Badge<GButton>, GButton&); | ||||
|     void unregister_button(Badge<GButton>, GButton&); | ||||
|     void register_menu_item(Badge<GMenuItem>, GMenuItem&); | ||||
|  | @ -79,6 +85,8 @@ private: | |||
|     RetainPtr<GraphicsBitmap> m_icon; | ||||
|     GShortcut m_shortcut; | ||||
|     bool m_enabled { true }; | ||||
|     bool m_checkable { false }; | ||||
|     bool m_checked { false }; | ||||
|     ShortcutScope m_scope { ShortcutScope::None }; | ||||
| 
 | ||||
|     HashTable<GButton*> m_buttons; | ||||
|  |  | |||
|  | @ -133,6 +133,9 @@ void GButton::set_action(GAction& action) | |||
|     m_action = action.make_weak_ptr(); | ||||
|     action.register_button({ }, *this); | ||||
|     set_enabled(action.is_enabled()); | ||||
|     set_checkable(action.is_checkable()); | ||||
|     if (action.is_checkable()) | ||||
|         set_checked(action.is_checked()); | ||||
| } | ||||
| 
 | ||||
| void GButton::set_icon(RetainPtr<GraphicsBitmap>&& icon) | ||||
|  |  | |||
|  | @ -90,6 +90,9 @@ int GMenu::realize_menu() | |||
|             request.menu.menu_id = m_menu_id; | ||||
|             request.menu.identifier = i; | ||||
|             request.menu.enabled = action.is_enabled(); | ||||
|             request.menu.checkable = action.is_checkable(); | ||||
|             if (action.is_checkable()) | ||||
|                 request.menu.checked = action.is_checked(); | ||||
|             ASSERT(action.text().length() < (ssize_t)sizeof(request.text)); | ||||
|             strcpy(request.text, action.text().characters()); | ||||
|             request.text_length = action.text().length(); | ||||
|  |  | |||
|  | @ -16,6 +16,9 @@ GMenuItem::GMenuItem(unsigned menu_id, Retained<GAction>&& action) | |||
| { | ||||
|     m_action->register_menu_item({ }, *this); | ||||
|     m_enabled = m_action->is_enabled(); | ||||
|     m_checkable = m_action->is_checkable(); | ||||
|     if (m_checkable) | ||||
|         m_checked = m_action->is_checked(); | ||||
| } | ||||
| 
 | ||||
| GMenuItem::~GMenuItem() | ||||
|  | @ -32,6 +35,15 @@ void GMenuItem::set_enabled(bool enabled) | |||
|     update_window_server(); | ||||
| } | ||||
| 
 | ||||
| void GMenuItem::set_checked(bool checked) | ||||
| { | ||||
|     ASSERT(is_checkable()); | ||||
|     if (m_checked == checked) | ||||
|         return; | ||||
|     m_checked = checked; | ||||
|     update_window_server(); | ||||
| } | ||||
| 
 | ||||
| void GMenuItem::update_window_server() | ||||
| { | ||||
|     auto& action = *m_action; | ||||
|  | @ -40,6 +52,9 @@ void GMenuItem::update_window_server() | |||
|     request.menu.menu_id = m_menu_id; | ||||
|     request.menu.identifier = m_identifier; | ||||
|     request.menu.enabled = action.is_enabled(); | ||||
|     request.menu.checkable = action.is_checkable(); | ||||
|     if (action.is_checkable()) | ||||
|         request.menu.checked = action.is_checked(); | ||||
|     ASSERT(action.text().length() < (ssize_t)sizeof(request.text)); | ||||
|     strcpy(request.text, action.text().characters()); | ||||
|     request.text_length = action.text().length(); | ||||
|  |  | |||
|  | @ -20,6 +20,12 @@ public: | |||
|     GAction* action() { return m_action.ptr(); } | ||||
|     unsigned identifier() const { return m_identifier; } | ||||
| 
 | ||||
|     bool is_checkable() const { return m_checkable; } | ||||
|     void set_checkable(bool checkable) { m_checkable = checkable; } | ||||
| 
 | ||||
|     bool is_checked() const { return m_checked; } | ||||
|     void set_checked(bool); | ||||
| 
 | ||||
|     bool is_enabled() const { return m_enabled; } | ||||
|     void set_enabled(bool); | ||||
| 
 | ||||
|  | @ -33,6 +39,8 @@ private: | |||
|     unsigned m_menu_id { 0 }; | ||||
|     unsigned m_identifier { 0 }; | ||||
|     bool m_enabled { true }; | ||||
|     bool m_checkable { false }; | ||||
|     bool m_checked { false }; | ||||
|     RetainPtr<GAction> m_action; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -246,6 +246,8 @@ struct WSAPI_ClientMessage { | |||
|             char shortcut_text[32]; | ||||
|             int shortcut_text_length; | ||||
|             bool enabled; | ||||
|             bool checkable; | ||||
|             bool checked; | ||||
|             WSAPI_Point position; | ||||
|             bool top_anchored; | ||||
|         } menu; | ||||
|  |  | |||
|  | @ -241,7 +241,7 @@ void WSClientConnection::handle_request(const WSAPIAddMenuItemRequest& request) | |||
|         return; | ||||
|     } | ||||
|     auto& menu = *(*it).value; | ||||
|     menu.add_item(make<WSMenuItem>(menu, identifier, request.text(), request.shortcut_text(), request.is_enabled())); | ||||
|     menu.add_item(make<WSMenuItem>(menu, identifier, request.text(), request.shortcut_text(), request.is_enabled(), request.is_checkable(), request.is_checked())); | ||||
|     WSAPI_ServerMessage response; | ||||
|     response.type = WSAPI_ServerMessage::Type::DidAddMenuItem; | ||||
|     response.menu.menu_id = menu_id; | ||||
|  | @ -292,6 +292,9 @@ void WSClientConnection::handle_request(const WSAPIUpdateMenuItemRequest& reques | |||
|     menu_item->set_text(request.text()); | ||||
|     menu_item->set_shortcut_text(request.shortcut_text()); | ||||
|     menu_item->set_enabled(request.is_enabled()); | ||||
|     menu_item->set_checkable(request.is_checkable()); | ||||
|     if (request.is_checkable()) | ||||
|         menu_item->set_checked(request.is_checked()); | ||||
|     WSAPI_ServerMessage response; | ||||
|     response.type = WSAPI_ServerMessage::Type::DidUpdateMenuItem; | ||||
|     response.menu.menu_id = menu_id; | ||||
|  |  | |||
|  | @ -276,13 +276,15 @@ private: | |||
| 
 | ||||
| class WSAPIAddMenuItemRequest : public WSAPIClientRequest { | ||||
| public: | ||||
|     WSAPIAddMenuItemRequest(int client_id, int menu_id, unsigned identifier, const String& text, const String& shortcut_text, bool enabled) | ||||
|     WSAPIAddMenuItemRequest(int client_id, int menu_id, unsigned identifier, const String& text, const String& shortcut_text, bool enabled, bool checkable, bool checked) | ||||
|         : WSAPIClientRequest(WSEvent::APIAddMenuItemRequest, client_id) | ||||
|         , m_menu_id(menu_id) | ||||
|         , m_identifier(identifier) | ||||
|         , m_text(text) | ||||
|         , m_shortcut_text(shortcut_text) | ||||
|         , m_enabled(enabled) | ||||
|         , m_checkable(checkable) | ||||
|         , m_checked(checked) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|  | @ -291,24 +293,30 @@ public: | |||
|     String text() const { return m_text; } | ||||
|     String shortcut_text() const { return m_shortcut_text; } | ||||
|     bool is_enabled() const { return m_enabled; } | ||||
|     bool is_checkable() const { return m_checkable; } | ||||
|     bool is_checked() const { return m_checked; } | ||||
| 
 | ||||
| private: | ||||
|     int m_menu_id { 0 }; | ||||
|     unsigned m_identifier { 0 }; | ||||
|     String m_text; | ||||
|     String m_shortcut_text; | ||||
|     bool m_enabled { true }; | ||||
|     bool m_enabled; | ||||
|     bool m_checkable; | ||||
|     bool m_checked; | ||||
| }; | ||||
| 
 | ||||
| class WSAPIUpdateMenuItemRequest : public WSAPIClientRequest { | ||||
| public: | ||||
|     WSAPIUpdateMenuItemRequest(int client_id, int menu_id, unsigned identifier, const String& text, const String& shortcut_text, bool enabled) | ||||
|     WSAPIUpdateMenuItemRequest(int client_id, int menu_id, unsigned identifier, const String& text, const String& shortcut_text, bool enabled, bool checkable, bool checked) | ||||
|         : WSAPIClientRequest(WSEvent::APIUpdateMenuItemRequest, client_id) | ||||
|         , m_menu_id(menu_id) | ||||
|         , m_identifier(identifier) | ||||
|         , m_text(text) | ||||
|         , m_shortcut_text(shortcut_text) | ||||
|         , m_enabled(enabled) | ||||
|         , m_checkable(checkable) | ||||
|         , m_checked(checked) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|  | @ -317,6 +325,8 @@ public: | |||
|     String text() const { return m_text; } | ||||
|     String shortcut_text() const { return m_shortcut_text; } | ||||
|     bool is_enabled() const { return m_enabled; } | ||||
|     bool is_checkable() const { return m_checkable; } | ||||
|     bool is_checked() const { return m_checked; } | ||||
| 
 | ||||
| private: | ||||
|     int m_menu_id { 0 }; | ||||
|  | @ -324,6 +334,8 @@ private: | |||
|     String m_text; | ||||
|     String m_shortcut_text; | ||||
|     bool m_enabled { true }; | ||||
|     bool m_checkable; | ||||
|     bool m_checked; | ||||
| }; | ||||
| 
 | ||||
| class WSAPIAddMenuSeparatorRequest : public WSAPIClientRequest { | ||||
|  |  | |||
|  | @ -170,12 +170,12 @@ bool WSEventLoop::on_receive_from_client(int client_id, const WSAPI_ClientMessag | |||
|     case WSAPI_ClientMessage::Type::AddMenuItem: | ||||
|         ASSERT(message.text_length < (ssize_t)sizeof(message.text)); | ||||
|         ASSERT(message.menu.shortcut_text_length < (ssize_t)sizeof(message.menu.shortcut_text)); | ||||
|         post_event(client, make<WSAPIAddMenuItemRequest>(client_id, message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length), String(message.menu.shortcut_text, message.menu.shortcut_text_length), message.menu.enabled)); | ||||
|         post_event(client, make<WSAPIAddMenuItemRequest>(client_id, message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length), String(message.menu.shortcut_text, message.menu.shortcut_text_length), message.menu.enabled, message.menu.checkable, message.menu.checked)); | ||||
|         break; | ||||
|     case WSAPI_ClientMessage::Type::UpdateMenuItem: | ||||
|         ASSERT(message.text_length < (ssize_t)sizeof(message.text)); | ||||
|         ASSERT(message.menu.shortcut_text_length < (ssize_t)sizeof(message.menu.shortcut_text)); | ||||
|         post_event(client, make<WSAPIUpdateMenuItemRequest>(client_id, message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length), String(message.menu.shortcut_text, message.menu.shortcut_text_length), message.menu.enabled)); | ||||
|         post_event(client, make<WSAPIUpdateMenuItemRequest>(client_id, message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length), String(message.menu.shortcut_text, message.menu.shortcut_text_length), message.menu.enabled, message.menu.checkable, message.menu.checked)); | ||||
|         break; | ||||
|     case WSAPI_ClientMessage::Type::AddMenuSeparator: | ||||
|         post_event(client, make<WSAPIAddMenuSeparatorRequest>(client_id, message.menu.menu_id)); | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| #include "WSWindowManager.h" | ||||
| #include <WindowServer/WSAPITypes.h> | ||||
| #include <WindowServer/WSClientConnection.h> | ||||
| #include <SharedGraphics/CharacterBitmap.h> | ||||
| #include <SharedGraphics/Painter.h> | ||||
| #include <SharedGraphics/StylePainter.h> | ||||
| #include <SharedGraphics/Font.h> | ||||
|  | @ -26,6 +27,23 @@ const Font& WSMenu::font() const | |||
|     return Font::default_font(); | ||||
| } | ||||
| 
 | ||||
| static const char* s_checked_bitmap_data = { | ||||
|     "         " | ||||
|     "      ## " | ||||
|     "     ##  " | ||||
|     "     ##  " | ||||
|     "    ##   " | ||||
|     " ## ##   " | ||||
|     "  ####   " | ||||
|     "   ##    " | ||||
|     "         " | ||||
| }; | ||||
| 
 | ||||
| static CharacterBitmap* s_checked_bitmap; | ||||
| static const int s_checked_bitmap_width = 9; | ||||
| static const int s_checked_bitmap_height = 9; | ||||
| static const int s_checked_bitmap_padding = 6; | ||||
| 
 | ||||
| int WSMenu::width() const | ||||
| { | ||||
|     int longest = 0; | ||||
|  | @ -34,6 +52,8 @@ int WSMenu::width() const | |||
|             int item_width = font().width(item->text()); | ||||
|             if (!item->shortcut_text().is_empty()) | ||||
|                 item_width += padding_between_text_and_shortcut() + font().width(item->shortcut_text()); | ||||
|             if (item->is_checkable()) | ||||
|                 item_width += s_checked_bitmap_width + s_checked_bitmap_padding; | ||||
| 
 | ||||
|             longest = max(longest, item_width); | ||||
|         } | ||||
|  | @ -92,6 +112,9 @@ void WSMenu::draw() | |||
|     StylePainter::paint_menu_frame(painter, rect); | ||||
|     int width = this->width(); | ||||
| 
 | ||||
|     if (!s_checked_bitmap) | ||||
|         s_checked_bitmap = &CharacterBitmap::create_from_ascii(s_checked_bitmap_data, s_checked_bitmap_width, s_checked_bitmap_height).leak_ref(); | ||||
| 
 | ||||
|     for (auto& item : m_items) { | ||||
|         if (item->type() == WSMenuItem::Text) { | ||||
|             Color text_color = Color::Black; | ||||
|  | @ -101,7 +124,16 @@ void WSMenu::draw() | |||
|             } | ||||
|             if (!item->is_enabled()) | ||||
|                 text_color = Color::MidGray; | ||||
|             painter.draw_text(item->rect().translated(left_padding(), 0), item->text(), TextAlignment::CenterLeft, text_color); | ||||
|             Rect text_rect = item->rect().translated(left_padding(), 0); | ||||
|             if (item->is_checkable()) { | ||||
|                 if (item->is_checked()) { | ||||
|                     Rect checkmark_rect { text_rect.location().x(), 0, s_checked_bitmap_width, s_checked_bitmap_height }; | ||||
|                     checkmark_rect.center_vertically_within(text_rect); | ||||
|                     painter.draw_bitmap(checkmark_rect.location(), *s_checked_bitmap, Color::Black); | ||||
|                 } | ||||
|                 text_rect.move_by(s_checked_bitmap_width + s_checked_bitmap_padding, 0); | ||||
|             } | ||||
|             painter.draw_text(text_rect, item->text(), TextAlignment::CenterLeft, text_color); | ||||
|             if (!item->shortcut_text().is_empty()) { | ||||
|                 painter.draw_text(item->rect().translated(-right_padding(), 0), item->shortcut_text(), TextAlignment::CenterRight, text_color); | ||||
|             } | ||||
|  |  | |||
|  | @ -1,10 +1,12 @@ | |||
| #include "WSMenuItem.h" | ||||
| #include "WSMenu.h" | ||||
| 
 | ||||
| WSMenuItem::WSMenuItem(WSMenu& menu, unsigned identifier, const String& text, const String& shortcut_text, bool enabled) | ||||
| WSMenuItem::WSMenuItem(WSMenu& menu, unsigned identifier, const String& text, const String& shortcut_text, bool enabled, bool checkable, bool checked) | ||||
|     : m_menu(menu) | ||||
|     , m_type(Text) | ||||
|     , m_enabled(enabled) | ||||
|     , m_checkable(checkable) | ||||
|     , m_checked(checked) | ||||
|     , m_identifier(identifier) | ||||
|     , m_text(text) | ||||
|     , m_shortcut_text(shortcut_text) | ||||
|  | @ -28,3 +30,11 @@ void WSMenuItem::set_enabled(bool enabled) | |||
|     m_enabled = enabled; | ||||
|     m_menu.redraw(); | ||||
| } | ||||
| 
 | ||||
| void WSMenuItem::set_checked(bool checked) | ||||
| { | ||||
|     if (m_checked == checked) | ||||
|         return; | ||||
|     m_checked = checked; | ||||
|     m_menu.redraw(); | ||||
| } | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ public: | |||
|         Separator, | ||||
|     }; | ||||
| 
 | ||||
|     WSMenuItem(WSMenu&, unsigned identifier, const String& text, const String& shortcut_text = { }, bool enabled = true); | ||||
|     WSMenuItem(WSMenu&, unsigned identifier, const String& text, const String& shortcut_text = { }, bool enabled = true, bool checkable = false, bool checked = false); | ||||
|     WSMenuItem(WSMenu&, Type); | ||||
|     ~WSMenuItem(); | ||||
| 
 | ||||
|  | @ -23,6 +23,12 @@ public: | |||
|     bool is_enabled() const { return m_enabled; } | ||||
|     void set_enabled(bool); | ||||
| 
 | ||||
|     bool is_checkable() const { return m_checkable; } | ||||
|     void set_checkable(bool checkable) { m_checkable = checkable; } | ||||
| 
 | ||||
|     bool is_checked() const { return m_checked; } | ||||
|     void set_checked(bool); | ||||
| 
 | ||||
|     String text() const { return m_text; } | ||||
|     void set_text(const String& text) { m_text = text; } | ||||
| 
 | ||||
|  | @ -38,6 +44,8 @@ private: | |||
|     WSMenu& m_menu; | ||||
|     Type m_type { None }; | ||||
|     bool m_enabled { true }; | ||||
|     bool m_checkable { false }; | ||||
|     bool m_checked { false }; | ||||
|     unsigned m_identifier { 0 }; | ||||
|     String m_text; | ||||
|     String m_shortcut_text; | ||||
|  |  | |||
|  | @ -58,7 +58,7 @@ void StylePainter::paint_button(Painter& painter, const Rect& rect, ButtonStyle | |||
|     if (button_style == ButtonStyle::Normal) | ||||
|         return paint_button_new(painter, rect, pressed, checked, hovered); | ||||
| 
 | ||||
|     Color button_color = Color::LightGray; | ||||
|     Color button_color = checked ? Color::from_rgb(0xd6d2ce) : Color::LightGray; | ||||
|     Color highlight_color = Color::White; | ||||
|     Color shadow_color = Color(96, 96, 96); | ||||
| 
 | ||||
|  | @ -71,7 +71,7 @@ void StylePainter::paint_button(Painter& painter, const Rect& rect, ButtonStyle | |||
|     PainterStateSaver saver(painter); | ||||
|     painter.translate(rect.location()); | ||||
| 
 | ||||
|     if (pressed) { | ||||
|     if (pressed || checked) { | ||||
|         // Base
 | ||||
|         painter.fill_rect({ 1, 1, rect.width() - 2, rect.height() - 2 }, button_color); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling