From 7e2724c22ca683c6ebc0b6d52fd6b7b412fd7735 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Mon, 5 May 2014 13:40:25 -0700 Subject: [PATCH] Add support for submenus in the automation menu Split the menu text on /, with each segment before the last used as the submenu name and the last as the actual menu text. Closes #852. --- src/menu.cpp | 63 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/src/menu.cpp b/src/menu.cpp index 7a35cb97a..c7f938aea 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -31,13 +31,14 @@ #include #include #include -#include #include +#include +#include #include +#include #include #include - #include #include #include @@ -164,15 +165,23 @@ public: { } + int AddCommand(cmd::Command *co, wxMenu *parent, std::string const& text = "") { + return AddCommand(co, parent, text.empty() ? co->StrMenu(context) : _(to_wx(text))); + } + + // because wxString doesn't have a move constructor + int AddCommand(cmd::Command *co, wxMenu *parent, wxString const& menu_text) { + return AddCommand(co, parent, wxString(menu_text)); + } + /// Append a command to a menu and register the needed handlers - int AddCommand(cmd::Command *co, wxMenu *parent, std::string const& text) { + int AddCommand(cmd::Command *co, wxMenu *parent, wxString&& menu_text) { int flags = co->Type(); wxItemKind kind = flags & cmd::COMMAND_RADIO ? wxITEM_RADIO : flags & cmd::COMMAND_TOGGLE ? wxITEM_CHECK : wxITEM_NORMAL; - wxString menu_text = text.empty() ? co->StrMenu(context) : _(to_wx(text)); menu_text += to_wx("\t" + hotkey::get_hotkey_str_first("Default", co->name())); wxMenuItem *item = new wxMenuItem(parent, MENU_ID_BASE + items.size(), menu_text, co->StrHelp(), kind); @@ -380,23 +389,47 @@ class AutomationMenu final : public wxMenu { CommandManager *cm; agi::signal::Connection global_slot; agi::signal::Connection local_slot; + std::vector all_items; void Regenerate() { + for (auto item : all_items) + cm->Remove(item); + wxMenuItemList &items = GetMenuItems(); - for (size_t i = items.size() - 1; i >= 2; --i) { - cm->Remove(items[i]); + // Remove everything but automation manager and the separator + for (size_t i = items.size() - 1; i >= 2; --i) Delete(items[i]); + + auto macros = wxGetApp().global_scripts->GetMacros(); + boost::push_back(macros, c->local_scripts->GetMacros()); + if (macros.empty()) { + Append(-1, _("No Automation macros loaded"))->Enable(false); + return; } - std::vector macros = wxGetApp().global_scripts->GetMacros(); - std::vector local_macros = c->local_scripts->GetMacros(); - copy(local_macros.begin(), local_macros.end(), back_inserter(macros)); + std::map submenus; - if (macros.empty()) - Append(-1, _("No Automation macros loaded"))->Enable(false); - else { - for (auto const& macro : macros) - cm->AddCommand(macro, this, ""); + for (auto macro : macros) { + const auto name = from_wx(macro->StrMenu(c)); + wxMenu *parent = this; + for (auto section : agi::Split(name, wxS('/'))) { + if (section.end() == name.end()) { + cm->AddCommand(macro, parent, wxString::FromUTF8Unchecked(&*section.begin(), section.size())); + all_items.push_back(parent->GetMenuItems().back()); + break; + } + + std::string prefix(name.begin(), section.end()); + auto it = submenus.find(prefix); + if (it != submenus.end()) + parent = it->second; + else { + auto menu = new wxMenu; + parent->AppendSubMenu(menu, wxString::FromUTF8Unchecked(&*section.begin(), section.size())); + submenus[prefix] = menu; + parent = menu; + } + } } } public: @@ -406,7 +439,7 @@ public: , global_slot(wxGetApp().global_scripts->AddScriptChangeListener(&AutomationMenu::Regenerate, this)) , local_slot(c->local_scripts->AddScriptChangeListener(&AutomationMenu::Regenerate, this)) { - cm->AddCommand(cmd::get("am/meta"), this, ""); + cm->AddCommand(cmd::get("am/meta"), this); AppendSeparator(); Regenerate(); }