Sort Automation menu items by display name

This commit is contained in:
Niels Martin Hansen 2015-01-25 00:35:42 +01:00
parent 0f3bca016e
commit d0296618a6
1 changed files with 51 additions and 16 deletions

View File

@ -39,6 +39,7 @@
#include <algorithm> #include <algorithm>
#include <boost/algorithm/string/case_conv.hpp> #include <boost/algorithm/string/case_conv.hpp>
#include <boost/range/algorithm_ext/push_back.hpp> #include <boost/range/algorithm_ext/push_back.hpp>
#include <boost/locale/collator.hpp>
#include <vector> #include <vector>
#include <wx/frame.h> #include <wx/frame.h>
#include <wx/menu.h> #include <wx/menu.h>
@ -395,6 +396,47 @@ class AutomationMenu final : public wxMenu {
agi::signal::Connection local_slot; agi::signal::Connection local_slot;
std::vector<wxMenuItem *> all_items; std::vector<wxMenuItem *> all_items;
struct WorkItem {
std::string displayname;
cmd::Command *command;
std::vector<WorkItem> subitems;
WorkItem(std::string const &displayname, cmd::Command *command = nullptr)
: displayname(displayname), command(command) { }
WorkItem *FindOrMakeSubitem(std::string const &name) {
auto sub = std::find_if(subitems.begin(), subitems.end(), [&](WorkItem const &item) { return item.displayname == name; });
if (sub != subitems.end()) return &*sub;
subitems.emplace_back(name);
return &subitems.back();
}
void Sort() {
if (command) return;
for (auto &sub : subitems)
sub.Sort();
auto comp = boost::locale::comparator<std::string::value_type>();
std::sort(subitems.begin(), subitems.end(), [&](WorkItem const &a, WorkItem const &b){
return comp(a.displayname, b.displayname);
});
}
void GenerateMenu(wxMenu *parent, AutomationMenu *am) {
for (auto item : subitems) {
if (item.command) {
am->cm->AddCommand(item.command, parent, item.displayname);
am->all_items.push_back(parent->GetMenuItems().back());
}
else {
auto submenu = new wxMenu;
parent->AppendSubMenu(submenu, to_wx(item.displayname));
item.GenerateMenu(submenu, am);
}
}
}
};
void Regenerate() { void Regenerate() {
for (auto item : all_items) for (auto item : all_items)
cm->Remove(item); cm->Remove(item);
@ -411,30 +453,23 @@ class AutomationMenu final : public wxMenu {
return; return;
} }
std::map<std::string, wxMenu *> submenus; WorkItem top("");
for (auto macro : macros) { for (auto macro : macros) {
const auto name = from_wx(macro->StrMenu(c)); const auto name = from_wx(macro->StrMenu(c));
wxMenu *parent = this; WorkItem *parent = &top;
for (auto section : agi::Split(name, wxS('/'))) { for (auto section : agi::Split(name, wxS('/'))) {
if (section.end() == name.end()) { std::string sectionname(section.begin(), section.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()); if (section.end() == name.end()) {
auto it = submenus.find(prefix); parent->subitems.emplace_back(sectionname, macro);
if (it != submenus.end()) }
parent = it->second;
else { else {
auto menu = new wxMenu; parent = parent->FindOrMakeSubitem(sectionname);
parent->AppendSubMenu(menu, wxString::FromUTF8Unchecked(&*section.begin(), section.size()));
submenus[prefix] = menu;
parent = menu;
} }
} }
} }
top.Sort();
top.GenerateMenu(this, this);
} }
public: public:
AutomationMenu(agi::Context *c, CommandManager *cm) AutomationMenu(agi::Context *c, CommandManager *cm)