浏览代码

LibGUI: Simplify submenu construction

The API for adding a submenu to a menu is now:

auto& submenu = menu.add_submenu("Name");
submenu.add_action(my_action);
Andreas Kling 5 年之前
父节点
当前提交
f0cde70c18

+ 7 - 9
Applications/HexEditor/HexEditorWidget.cpp

@@ -146,14 +146,6 @@ HexEditorWidget::HexEditorWidget()
         GUI::Application::the().quit(0);
     }));
 
-    auto bytes_per_row_menu = GUI::Menu::construct("Bytes Per Row");
-    for (int i = 8; i <= 32; i += 8) {
-        bytes_per_row_menu->add_action(GUI::Action::create(String::number(i), [this, i](auto&) {
-            m_editor->set_bytes_per_row(i);
-            m_editor->update();
-        }));
-    }
-
     m_goto_decimal_offset_action = GUI::Action::create("Go To Offset (Decimal)...", { Mod_Ctrl | Mod_Shift, Key_G }, Gfx::Bitmap::load_from_file("/res/icons/16x16/go-forward.png"), [this](const GUI::Action&) {
         auto input_box = GUI::InputBox::construct("Enter Decimal offset:", "Go To", window());
         if (input_box->exec() == GUI::InputBox::ExecOK && !input_box->text_value().is_empty()) {
@@ -197,7 +189,13 @@ HexEditorWidget::HexEditorWidget()
     }));
 
     auto& view_menu = menubar->add_menu("View");
-    view_menu.add_submenu(move(bytes_per_row_menu));
+    auto& bytes_per_row_menu = view_menu.add_submenu("Bytes per row");
+    for (int i = 8; i <= 32; i += 8) {
+        bytes_per_row_menu.add_action(GUI::Action::create(String::number(i), [this, i](auto&) {
+            m_editor->set_bytes_per_row(i);
+            m_editor->update();
+        }));
+    }
 
     auto& help_menu = menubar->add_menu("Help");
     help_menu.add_action(GUI::Action::create("About", [&](auto&) {

+ 9 - 10
Applications/IRCClient/IRCAppWindow.cpp

@@ -283,16 +283,15 @@ void IRCAppWindow::setup_menus()
     channel_menu.add_action(*m_invite_user_action);
     channel_menu.add_action(*m_banlist_action);
 
-    RefPtr<GUI::Menu> channel_control_menu = GUI::Menu::construct("Control");
-    channel_menu.add_submenu(*channel_control_menu);
-    channel_control_menu->add_action(*m_voice_user_action);
-    channel_control_menu->add_action(*m_devoice_user_action);
-    channel_control_menu->add_action(*m_hop_user_action);
-    channel_control_menu->add_action(*m_dehop_user_action);
-    channel_control_menu->add_action(*m_op_user_action);
-    channel_control_menu->add_action(*m_deop_user_action);
-    channel_control_menu->add_separator();
-    channel_control_menu->add_action(*m_kick_user_action);
+    auto& channel_control_menu = channel_menu.add_submenu("Control");
+    channel_control_menu.add_action(*m_voice_user_action);
+    channel_control_menu.add_action(*m_devoice_user_action);
+    channel_control_menu.add_action(*m_hop_user_action);
+    channel_control_menu.add_action(*m_dehop_user_action);
+    channel_control_menu.add_action(*m_op_user_action);
+    channel_control_menu.add_action(*m_deop_user_action);
+    channel_control_menu.add_separator();
+    channel_control_menu.add_action(*m_kick_user_action);
 
     channel_menu.add_separator();
     channel_menu.add_action(*m_cycle_channel_action);

+ 15 - 17
Applications/IRCClient/IRCWindow.cpp

@@ -90,10 +90,9 @@ IRCWindow::IRCWindow(IRCClient& client, void* owner, Type type, const String& na
                 m_client.handle_whois_action(m_client.nick_without_prefix(nick.characters()));
             }));
 
-            RefPtr<GUI::Menu> m_context_control_menu = GUI::Menu::construct("Control");
-            m_context_menu->add_submenu(*m_context_control_menu);
+            auto& context_control_menu = m_context_menu->add_submenu("Control");
 
-            m_context_control_menu->add_action(GUI::Action::create("Voice", [&](const GUI::Action&) {
+            context_control_menu.add_action(GUI::Action::create("Voice", [&](const GUI::Action&) {
                 auto nick = channel().member_model()->nick_at(member_view.selection().first());
                 if (nick.is_empty())
                     return;
@@ -101,44 +100,44 @@ IRCWindow::IRCWindow(IRCClient& client, void* owner, Type type, const String& na
                 m_client.handle_voice_user_action(m_name.characters(), m_client.nick_without_prefix(nick.characters()));
             }));
 
-            m_context_control_menu->add_action(GUI::Action::create("DeVoice", [&](const GUI::Action&) {
+            context_control_menu.add_action(GUI::Action::create("DeVoice", [&](const GUI::Action&) {
                 auto nick = channel().member_model()->nick_at(member_view.selection().first());
                 if (nick.is_empty())
                     return;
                 m_client.handle_devoice_user_action(m_name.characters(), m_client.nick_without_prefix(nick.characters()));
             }));
 
-            m_context_control_menu->add_action(GUI::Action::create("Hop", [&](const GUI::Action&) {
+            context_control_menu.add_action(GUI::Action::create("Hop", [&](const GUI::Action&) {
                 auto nick = channel().member_model()->nick_at(member_view.selection().first());
                 if (nick.is_empty())
                     return;
                 m_client.handle_hop_user_action(m_name.characters(), m_client.nick_without_prefix(nick.characters()));
             }));
 
-            m_context_control_menu->add_action(GUI::Action::create("DeHop", [&](const GUI::Action&) {
+            context_control_menu.add_action(GUI::Action::create("DeHop", [&](const GUI::Action&) {
                 auto nick = channel().member_model()->nick_at(member_view.selection().first());
                 if (nick.is_empty())
                     return;
                 m_client.handle_dehop_user_action(m_name.characters(), m_client.nick_without_prefix(nick.characters()));
             }));
 
-            m_context_control_menu->add_action(GUI::Action::create("Op", [&](const GUI::Action&) {
+            context_control_menu.add_action(GUI::Action::create("Op", [&](const GUI::Action&) {
                 auto nick = channel().member_model()->nick_at(member_view.selection().first());
                 if (nick.is_empty())
                     return;
                 m_client.handle_op_user_action(m_name.characters(), m_client.nick_without_prefix(nick.characters()));
             }));
 
-            m_context_control_menu->add_action(GUI::Action::create("DeOp", [&](const GUI::Action&) {
+            context_control_menu.add_action(GUI::Action::create("DeOp", [&](const GUI::Action&) {
                 auto nick = channel().member_model()->nick_at(member_view.selection().first());
                 if (nick.is_empty())
                     return;
                 m_client.handle_deop_user_action(m_name.characters(), m_client.nick_without_prefix(nick.characters()));
             }));
 
-            m_context_control_menu->add_separator();
+            context_control_menu.add_separator();
 
-            m_context_control_menu->add_action(GUI::Action::create("Kick", [&](const GUI::Action&) {
+            context_control_menu.add_action(GUI::Action::create("Kick", [&](const GUI::Action&) {
                 auto nick = channel().member_model()->nick_at(member_view.selection().first());
                 if (nick.is_empty())
                     return;
@@ -149,38 +148,37 @@ IRCWindow::IRCWindow(IRCClient& client, void* owner, Type type, const String& na
                     m_client.handle_kick_user_action(m_name.characters(), m_client.nick_without_prefix(nick.characters()), input_box->text_value());
             }));
 
-            RefPtr<GUI::Menu> m_context_ctcp_menu = GUI::Menu::construct("CTCP");
-            m_context_menu->add_submenu(*m_context_ctcp_menu);
+            auto& context_ctcp_menu = m_context_menu->add_submenu("CTCP");
 
-            m_context_ctcp_menu->add_action(GUI::Action::create("User info", [&](const GUI::Action&) {
+            context_ctcp_menu.add_action(GUI::Action::create("User info", [&](const GUI::Action&) {
                 auto nick = channel().member_model()->nick_at(member_view.selection().first());
                 if (nick.is_empty())
                     return;
                 m_client.handle_ctcp_user_action(m_client.nick_without_prefix(nick.characters()), "USERINFO");
             }));
 
-            m_context_ctcp_menu->add_action(GUI::Action::create("Finger", [&](const GUI::Action&) {
+            context_ctcp_menu.add_action(GUI::Action::create("Finger", [&](const GUI::Action&) {
                 auto nick = channel().member_model()->nick_at(member_view.selection().first());
                 if (nick.is_empty())
                     return;
                 m_client.handle_ctcp_user_action(m_client.nick_without_prefix(nick.characters()), "FINGER");
             }));
 
-            m_context_ctcp_menu->add_action(GUI::Action::create("Time", [&](const GUI::Action&) {
+            context_ctcp_menu.add_action(GUI::Action::create("Time", [&](const GUI::Action&) {
                 auto nick = channel().member_model()->nick_at(member_view.selection().first());
                 if (nick.is_empty())
                     return;
                 m_client.handle_ctcp_user_action(m_client.nick_without_prefix(nick.characters()), "TIME");
             }));
 
-            m_context_ctcp_menu->add_action(GUI::Action::create("Version", [&](const GUI::Action&) {
+            context_ctcp_menu.add_action(GUI::Action::create("Version", [&](const GUI::Action&) {
                 auto nick = channel().member_model()->nick_at(member_view.selection().first());
                 if (nick.is_empty())
                     return;
                 m_client.handle_ctcp_user_action(m_client.nick_without_prefix(nick.characters()), "VERSION");
             }));
 
-            m_context_ctcp_menu->add_action(GUI::Action::create("Client info", [&](const GUI::Action&) {
+            context_ctcp_menu.add_action(GUI::Action::create("Client info", [&](const GUI::Action&) {
                 auto nick = channel().member_model()->nick_at(member_view.selection().first());
                 if (nick.is_empty())
                     return;

+ 3 - 5
Applications/SystemMenu/main.cpp

@@ -137,9 +137,8 @@ NonnullRefPtr<GUI::Menu> build_system_menu()
 
         if (g_app_category_menus.contains(category))
             continue;
-        auto category_menu = GUI::Menu::construct(category);
-        system_menu->add_submenu(category_menu);
-        g_app_category_menus.set(category, move(category_menu));
+        auto& category_menu = system_menu->add_submenu(category);
+        g_app_category_menus.set(category, category_menu);
     }
 
     // Then we create and insert all the app menu items into the right place.
@@ -171,9 +170,8 @@ NonnullRefPtr<GUI::Menu> build_system_menu()
 
     g_themes_group.set_exclusive(true);
     g_themes_group.set_unchecking_allowed(false);
-    g_themes_menu = GUI::Menu::construct("Themes");
 
-    system_menu->add_submenu(*g_themes_menu);
+    g_themes_menu = &system_menu->add_submenu("Themes");
 
     {
         Core::DirIterator dt("/res/themes", Core::DirIterator::SkipDots);

+ 14 - 17
Applications/TextEditor/TextEditorWidget.cpp

@@ -384,7 +384,19 @@ TextEditorWidget::TextEditorWidget()
     edit_menu.add_action(*m_replace_previous_action);
     edit_menu.add_action(*m_replace_all_action);
 
-    auto& font_menu = menubar->add_menu("Font");
+    m_markdown_preview_action = GUI::Action::create_checkable(
+        "Markdown preview", [this](auto& action) {
+            set_markdown_preview_enabled(action.is_checked());
+        },
+        this);
+
+    auto& view_menu = menubar->add_menu("View");
+    view_menu.add_action(*m_line_wrapping_setting_action);
+    view_menu.add_separator();
+    view_menu.add_action(*m_markdown_preview_action);
+    view_menu.add_separator();
+
+    auto& font_menu = view_menu.add_submenu("Font");
     GUI::FontDatabase::the().for_each_fixed_width_font([&](const StringView& font_name) {
         font_menu.add_action(GUI::Action::create(font_name, [this](const GUI::Action& action) {
             m_editor->set_font(GUI::FontDatabase::the().get_by_name(action.text()));
@@ -392,10 +404,9 @@ TextEditorWidget::TextEditorWidget()
         }));
     });
 
-    syntax_actions = GUI::ActionGroup {};
     syntax_actions.set_exclusive(true);
 
-    auto& syntax_menu = menubar->add_menu("Syntax");
+    auto& syntax_menu = view_menu.add_submenu("Syntax");
     m_plain_text_highlight = GUI::Action::create_checkable("Plain text", [&](auto&) {
         m_editor->set_syntax_highlighter(nullptr);
         m_editor->update();
@@ -418,20 +429,6 @@ TextEditorWidget::TextEditorWidget()
     syntax_actions.add_action(*m_js_highlight);
     syntax_menu.add_action(*m_js_highlight);
 
-    m_markdown_preview_action = GUI::Action::create_checkable(
-        "Markdown preview", [this](auto& action) {
-            set_markdown_preview_enabled(action.is_checked());
-        },
-        this);
-
-    auto& view_menu = menubar->add_menu("View");
-    view_menu.add_action(*m_line_wrapping_setting_action);
-    view_menu.add_separator();
-    view_menu.add_action(*m_markdown_preview_action);
-    view_menu.add_separator();
-    view_menu.add_submenu(move(font_menu));
-    view_menu.add_submenu(move(syntax_menu));
-
     auto& help_menu = menubar->add_menu("Help");
     help_menu.add_action(GUI::Action::create("About", [&](auto&) {
         GUI::AboutDialog::show("Text Editor", Gfx::Bitmap::load_from_file("/res/icons/32x32/app-texteditor.png"), window());

+ 4 - 2
Libraries/LibGUI/Menu.cpp

@@ -71,9 +71,11 @@ void Menu::add_action(NonnullRefPtr<Action> action)
 #endif
 }
 
-void Menu::add_submenu(NonnullRefPtr<Menu> submenu)
+Menu& Menu::add_submenu(const String& name)
 {
-    m_items.append(make<MenuItem>(m_menu_id, move(submenu)));
+    auto submenu = Menu::construct(name);
+    m_items.append(make<MenuItem>(m_menu_id, submenu));
+    return submenu;
 }
 
 void Menu::add_separator()

+ 1 - 1
Libraries/LibGUI/Menu.h

@@ -54,7 +54,7 @@ public:
 
     void add_action(NonnullRefPtr<Action>);
     void add_separator();
-    void add_submenu(NonnullRefPtr<Menu>);
+    Menu& add_submenu(const String& name);
 
     void popup(const Gfx::Point& screen_position);
     void dismiss();

+ 2 - 2
Libraries/LibGUI/MenuItem.cpp

@@ -37,7 +37,7 @@ MenuItem::MenuItem(unsigned menu_id, Type type)
 {
 }
 
-MenuItem::MenuItem(unsigned menu_id, NonnullRefPtr<Action>&& action)
+MenuItem::MenuItem(unsigned menu_id, NonnullRefPtr<Action> action)
     : m_type(Type::Action)
     , m_menu_id(menu_id)
     , m_action(move(action))
@@ -49,7 +49,7 @@ MenuItem::MenuItem(unsigned menu_id, NonnullRefPtr<Action>&& action)
         m_checked = m_action->is_checked();
 }
 
-MenuItem::MenuItem(unsigned menu_id, NonnullRefPtr<Menu>&& submenu)
+MenuItem::MenuItem(unsigned menu_id, NonnullRefPtr<Menu> submenu)
     : m_type(Type::Submenu)
     , m_menu_id(menu_id)
     , m_submenu(move(submenu))

+ 2 - 2
Libraries/LibGUI/MenuItem.h

@@ -42,8 +42,8 @@ public:
     };
 
     MenuItem(unsigned menu_id, Type);
-    MenuItem(unsigned menu_id, NonnullRefPtr<Action>&&);
-    MenuItem(unsigned menu_id, NonnullRefPtr<Menu>&&);
+    MenuItem(unsigned menu_id, NonnullRefPtr<Action>);
+    MenuItem(unsigned menu_id, NonnullRefPtr<Menu>);
     ~MenuItem();
 
     Type type() const { return m_type; }