diff --git a/Userland/Libraries/LibGUI/Menu.cpp b/Userland/Libraries/LibGUI/Menu.cpp index 8ba2f57fe4..f981dd343a 100644 --- a/Userland/Libraries/LibGUI/Menu.cpp +++ b/Userland/Libraries/LibGUI/Menu.cpp @@ -73,6 +73,37 @@ void Menu::remove_all_actions() m_items.clear(); } +void Menu::update_parent_menu_item() +{ + if (auto parent = m_parent_menu.strong_ref()) { + auto const& parent_items = parent->items(); + if (m_index_in_parent_menu >= 0 && static_cast(m_index_in_parent_menu) < parent_items.size()) { + auto& item = *parent_items[m_index_in_parent_menu]; + if (item.submenu() == this) + item.update_from_menu(Badge {}); + return; + } + // Parent has since been cleared/repopulated: + parent = nullptr; + m_index_in_parent_menu = -1; + } +} + +void Menu::set_name(DeprecatedString name) +{ + m_name = move(name); + if (m_menu_id != -1) { + ConnectionToWindowServer::the().async_set_menu_name(m_menu_id, m_name); + update_parent_menu_item(); + } +} + +void Menu::set_parent(Menu& menu, int submenu_index) +{ + m_parent_menu = menu; + m_index_in_parent_menu = submenu_index; +} + ErrorOr> Menu::try_add_submenu(DeprecatedString name) { // NOTE: We grow the vector first, to get allocation failure handled immediately. @@ -81,6 +112,8 @@ ErrorOr> Menu::try_add_submenu(DeprecatedString name) auto submenu = TRY(Menu::try_create(name)); auto item = TRY(adopt_nonnull_own_or_enomem(new (nothrow) MenuItem(m_menu_id, submenu))); + submenu->set_parent(*this, m_items.size()); + if (m_menu_id != -1) realize_menu_item(*item, m_items.size()); diff --git a/Userland/Libraries/LibGUI/Menu.h b/Userland/Libraries/LibGUI/Menu.h index 25d5610925..2fa84d25fb 100644 --- a/Userland/Libraries/LibGUI/Menu.h +++ b/Userland/Libraries/LibGUI/Menu.h @@ -33,6 +33,8 @@ public: int menu_id() const { return m_menu_id; } DeprecatedString const& name() const { return m_name; } + void set_name(DeprecatedString); + Gfx::Bitmap const* icon() const { return m_icon.ptr(); } void set_icon(Gfx::Bitmap const*); @@ -73,12 +75,17 @@ private: void realize_menu_item(MenuItem&, int item_id); + void set_parent(Menu& menu, int submenu_index); + void update_parent_menu_item(); + int m_menu_id { -1 }; DeprecatedString m_name; RefPtr m_icon; Vector> m_items; WeakPtr m_current_default_action; bool m_visible { false }; + WeakPtr m_parent_menu; + int m_index_in_parent_menu { -1 }; Function m_recent_files_callback; }; diff --git a/Userland/Libraries/LibGUI/MenuItem.cpp b/Userland/Libraries/LibGUI/MenuItem.cpp index 79d20db10a..7cdc6bae74 100644 --- a/Userland/Libraries/LibGUI/MenuItem.cpp +++ b/Userland/Libraries/LibGUI/MenuItem.cpp @@ -80,10 +80,23 @@ void MenuItem::update_window_server() { if (m_menu_id < 0) return; - auto& action = *m_action; - auto shortcut_text = action.shortcut().is_valid() ? action.shortcut().to_deprecated_string() : DeprecatedString(); - auto icon = action.icon() ? action.icon()->to_shareable_bitmap() : Gfx::ShareableBitmap(); - ConnectionToWindowServer::the().async_update_menu_item(m_menu_id, m_identifier, -1, action.text(), action.is_enabled(), action.is_visible(), action.is_checkable(), action.is_checkable() ? action.is_checked() : false, m_default, shortcut_text, icon); + switch (m_type) { + case MenuItem::Type::Action: { + auto& action = *m_action; + auto shortcut_text = action.shortcut().is_valid() ? action.shortcut().to_deprecated_string() : DeprecatedString(); + auto icon = action.icon() ? action.icon()->to_shareable_bitmap() : Gfx::ShareableBitmap(); + ConnectionToWindowServer::the().async_update_menu_item(m_menu_id, m_identifier, -1, action.text(), action.is_enabled(), action.is_visible(), action.is_checkable(), action.is_checkable() ? action.is_checked() : false, m_default, shortcut_text, icon); + break; + } + case MenuItem::Type::Submenu: { + auto& submenu = *m_submenu; + auto icon = submenu.icon() ? submenu.icon()->to_shareable_bitmap() : Gfx::ShareableBitmap(); + ConnectionToWindowServer::the().async_update_menu_item(m_menu_id, m_identifier, submenu.menu_id(), submenu.name(), m_enabled, m_visible, false, false, m_default, "", icon); + break; + } + default: + VERIFY_NOT_REACHED(); + } } void MenuItem::set_menu_id(Badge, unsigned int menu_id) diff --git a/Userland/Libraries/LibGUI/MenuItem.h b/Userland/Libraries/LibGUI/MenuItem.h index 574f8a3b2f..09e64b5336 100644 --- a/Userland/Libraries/LibGUI/MenuItem.h +++ b/Userland/Libraries/LibGUI/MenuItem.h @@ -56,6 +56,7 @@ public: void set_identifier(Badge, unsigned identifier); void update_from_action(Badge) { update_window_server(); } + void update_from_menu(Badge) { update_window_server(); } private: void update_window_server();