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);
This commit is contained in:
Andreas Kling 2020-04-29 11:48:11 +02:00
parent 13dcd9a037
commit f0cde70c18
Notes: sideshowbarker 2024-07-19 07:11:54 +09:00
9 changed files with 57 additions and 65 deletions

View file

@ -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&) {

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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());

View file

@ -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()

View file

@ -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();

View file

@ -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))

View file

@ -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; }