Use tree control instead of pair of listboxes in hotkeys&controls

This commit is contained in:
Ilari Liusvaara 2013-08-11 16:48:35 +03:00
parent 408002eec1
commit be852e63e1
6 changed files with 327 additions and 186 deletions

View file

@ -3,6 +3,7 @@
#include <string>
#include <sstream>
#include <list>
#include <stdexcept>
#include <vector>
#include <boost/lexical_cast.hpp>
@ -122,4 +123,32 @@ template<> inline std::string parse_value(const std::string& value) throw(std::b
return value;
}
template<typename T>
class string_list
{
public:
string_list();
string_list(const std::list<std::basic_string<T>>& list);
bool empty();
string_list strip_one() const;
size_t size() const;
const std::basic_string<T>& operator[](size_t idx) const;
bool operator<(const string_list<T>& x) const;
bool operator==(const string_list<T>& x) const;
bool prefix_of(const string_list<T>& x) const;
std::basic_string<T> debug_name() const;
private:
string_list(const std::basic_string<T>* array, size_t arrsize);
std::vector<std::basic_string<T>> v;
};
/**
* Split a string into substrings on some unicode codepoint.
*/
string_list<char> split_on_codepoint(const std::string& s, char32_t cp);
/**
* Split a string into substrings on some unicode codepoint.
*/
string_list<char32_t> split_on_codepoint(const std::u32string& s, char32_t cp);
#endif

View file

@ -89,33 +89,33 @@ namespace
controller_key* k;
if(binding.mode == 0) {
k = new controller_key(lsnes_mapper, (stringfmt() << "+controller " << name).str(),
(stringfmt() << "Controller‣" << binding.cclass << "-" << binding.number << ""
(stringfmt() << "Controller‣" << binding.cclass << "‣#" << binding.number << ""
<< binding.name).str());
promote_key(*k);
k = new controller_key(lsnes_mapper, (stringfmt() << "hold-controller " << name).str(),
(stringfmt() << "Controller‣" << binding.cclass << "-" << binding.number << ""
<< binding.name << " (hold)").str());
(stringfmt() << "Controller‣" << binding.cclass << "‣#" << binding.number << ""
<< binding.name << "‣hold").str());
promote_key(*k);
k = new controller_key(lsnes_mapper, (stringfmt() << "type-controller " << name).str(),
(stringfmt() << "Controller‣" << binding.cclass << "-" << binding.number << ""
<< binding.name << " (type)").str());
(stringfmt() << "Controller‣" << binding.cclass << "‣#" << binding.number << ""
<< binding.name << "‣type").str());
promote_key(*k);
k = new controller_key(lsnes_mapper, (stringfmt() << "+autofire-controller " << name).str(),
(stringfmt() << "Controller‣" << binding.cclass << "-" << binding.number << ""
<< binding.name << " (autofire)").str());
(stringfmt() << "Controller‣" << binding.cclass << "‣#" << binding.number << ""
<< binding.name << "‣autofire").str());
promote_key(*k);
k = new controller_key(lsnes_mapper, (stringfmt() << "autofire-controller " << name).str(),
(stringfmt() << "Controller‣" << binding.cclass << "-" << binding.number << ""
<< binding.name << " (autofire toggle)").str());
(stringfmt() << "Controller‣" << binding.cclass << "‣#" << binding.number << ""
<< binding.name << "‣autofire toggle").str());
promote_key(*k);
} else if(binding.mode == 1) {
k = new controller_key(lsnes_mapper, (stringfmt() << "designate-position " << name).str(),
(stringfmt() << "Controller‣" << binding.cclass << "-" << binding.number << ""
(stringfmt() << "Controller‣" << binding.cclass << "‣#" << binding.number << ""
<< binding.name).str());
promote_key(*k);
} else if(binding.mode == 2) {
k = new controller_key(lsnes_mapper, (stringfmt() << "controller-analog " << name).str(),
(stringfmt() << "Controller‣" << binding.cclass << "-" << binding.number << ""
(stringfmt() << "Controller‣" << binding.cclass << "‣#" << binding.number << ""
<< binding.name << " (axis)").str(), true);
promote_key(*k);
}

View file

@ -14,7 +14,7 @@ ports = {
},{
["symbol"] = "ptype1", ["iname"] = "ptype1", ["hname"] = "ptype1", ["controllers"] = {
{
["name"] = "test1", ["class"] = "test1", ["buttons"] = {
["name"] = "test1", ["class"] = "test", ["buttons"] = {
{axis, "xlstick", -32768, 32767, true},
{axis, "ylstick", -32768, 32767, true},
{taxis, "ltrigger", 0, 255, false},
@ -42,7 +42,7 @@ ports = {
},{
["symbol"] = "ptype2", ["iname"] = "ptype2", ["hname"] = "ptype2", ["controllers"] = {
{
["name"] = "test2", ["class"] = "test2", ["buttons"] = {
["name"] = "test2", ["class"] = "test", ["buttons"] = {
{axis, "xlstick", -32768, 32767, true},
{taxis, "ltrigger", 0, 255, false},
{axis, "ylstick", -32768, 32767, true},

View file

@ -134,3 +134,162 @@ bool regex_match(const std::string& regexp, const std::string& str) throw(std::b
{
return regex(regexp, str);
}
namespace
{
template<typename ch>
std::list<std::basic_string<ch>> _split_on_codepoint(const std::basic_string<ch>& s,
const std::basic_string<ch>& cp)
{
std::list<std::basic_string<ch>> ret;
size_t start = 0;
size_t end = 0;
size_t len = s.length();
while(end < len) {
end = s.find(cp, start);
std::basic_string<ch> x;
if(end < len) {
x.resize(end - start);
std::copy(s.begin() + start, s.begin() + end, x.begin());
start = end + cp.length();
} else {
x.resize(len - start);
std::copy(s.begin() + start, s.end(), x.begin());
}
ret.push_back(x);
}
return ret;
}
}
template<typename T>
string_list<T>::string_list()
{
}
template<typename T>
string_list<T>::string_list(const std::list<std::basic_string<T>>& list)
{
v.resize(list.size());
std::copy(list.begin(), list.end(), v.begin());
}
template<typename T>
bool string_list<T>::empty()
{
return (v.size() == 0);
}
template<typename T>
string_list<T> string_list<T>::strip_one() const
{
return string_list<T>(&v[0], (v.size() > 0) ? (v.size() - 1) : 0);
}
template<typename T>
size_t string_list<T>::size() const
{
return v.size();
}
template<typename T>
const std::basic_string<T>& string_list<T>::operator[](size_t idx) const
{
if(idx >= v.size())
throw std::runtime_error("Index out of range");
return v[idx];
}
template<typename T>
string_list<T>::string_list(const std::basic_string<T>* array, size_t arrsize)
{
v.resize(arrsize);
std::copy(array, array + arrsize, v.begin());
}
template<typename T>
bool string_list<T>::operator<(const string_list<T>& x) const
{
for(size_t i = 0; i < v.size() && i < x.v.size(); i++)
if(v[i] < x.v[i])
return true;
else if(v[i] > x.v[i])
return false;
return (v.size() < x.v.size());
}
template<typename T>
bool string_list<T>::operator==(const string_list<T>& x) const
{
if(v.size() != x.v.size())
return false;
for(size_t i = 0; i < v.size(); i++)
if(v[i] != x.v[i])
return false;
return true;
}
template<typename T>
bool string_list<T>::prefix_of(const string_list<T>& x) const
{
if(v.size() > x.v.size())
return false;
for(size_t i = 0; i < v.size(); i++)
if(v[i] != x.v[i])
return false;
return true;
}
namespace
{
template<typename T> std::basic_string<T> separator();
template<> std::basic_string<char> separator()
{
return to_u8string(U"\u2023");
}
template<> std::basic_string<char16_t> separator()
{
return u"\u2023";
}
template<> std::basic_string<char32_t> separator()
{
return U"\u2023";
}
template<> std::basic_string<wchar_t> separator()
{
return L"->";
}
}
template<typename T>
std::basic_string<T> string_list<T>::debug_name() const
{
std::basic_stringstream<T> x;
for(size_t i = 0; i < v.size(); i++)
if(i != 0)
x << separator<T>() << v[i];
else
x << v[i];
return x.str();
}
template class string_list<char>;
template class string_list<wchar_t>;
template class string_list<char16_t>;
template class string_list<char32_t>;
string_list<char> split_on_codepoint(const std::string& s, char32_t cp)
{
std::string _cp = to_u8string(std::u32string(1, cp));
return _split_on_codepoint<char>(s, _cp);
}
string_list<char32_t> split_on_codepoint(const std::u32string& s, char32_t cp)
{
std::u32string _cp(1, cp);
return _split_on_codepoint<char32_t>(s, _cp);
}

View file

@ -1,6 +1,7 @@
#include "platform/wxwidgets/settings-common.hpp"
#include "platform/wxwidgets/settings-keyentry.hpp"
#include "core/keymapper.hpp"
#include "library/string.hpp"
namespace
{
@ -13,17 +14,15 @@ namespace
void on_clearkey(wxCommandEvent& e);
void on_change(wxCommandEvent& e);
private:
wxListBox* category;
wxListBox* control;
wxTreeCtrl* controls;
std::map<string_list<char>, wxTreeItemId> items;
std::map<string_list<char>, std::string> names;
std::map<string_list<char>, controller_key*> realitems;
wxButton* set_button;
wxButton* clear_button;
std::map<int, std::string> categories;
std::map<std::pair<int, int>, std::string> itemlabels;
std::map<std::pair<int, int>, std::string> items;
std::map<std::string, controller_key*> realitems;
void change_category(int cat);
void refresh();
std::pair<std::string, std::string> splitkeyname(const std::string& kn);
string_list<char> get_selection();
wxTreeItemId get_item(const string_list<char>& i);
};
wxeditor_esettings_controllers::wxeditor_esettings_controllers(wxWindow* parent)
@ -33,76 +32,59 @@ namespace
SetSizer(top_s);
wxString empty[1];
top_s->Add(category = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 1, empty), 1,
wxGROW);
top_s->Add(control = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 1, empty), 1,
wxGROW);
category->Connect(wxEVT_COMMAND_LISTBOX_SELECTED,
top_s->Add(controls = new wxTreeCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxTR_HIDE_ROOT | wxTR_LINES_AT_ROOT), 1, wxGROW);
controls->Connect(wxEVT_COMMAND_TREE_SEL_CHANGED,
wxCommandEventHandler(wxeditor_esettings_controllers::on_change), NULL, this);
controls->SetMinSize(wxSize(400, 300));
wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
pbutton_s->AddStretchSpacer();
pbutton_s->Add(set_button = new wxButton(this, wxID_ANY, wxT("Add")), 0, wxGROW);
set_button->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wxeditor_esettings_controllers::on_setkey), NULL, this);
set_button->Enable(false);
pbutton_s->Add(clear_button = new wxButton(this, wxID_ANY, wxT("Drop")), 0, wxGROW);
clear_button->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wxeditor_esettings_controllers::on_clearkey), NULL, this);
clear_button->Enable(false);
top_s->Add(pbutton_s, 0, wxGROW);
items[string_list<char>()] = controls->AddRoot(wxT(""));
refresh();
top_s->SetSizeHints(this);
Fit();
}
std::pair<std::string, std::string> wxeditor_esettings_controllers::splitkeyname(const std::string& kn)
wxTreeItemId wxeditor_esettings_controllers::get_item(const string_list<char>& i)
{
std::string tmp = kn;
size_t split = 0;
for(size_t itr = 0; itr < tmp.length() - 2 && itr < tmp.length(); itr++) {
unsigned char ch1 = tmp[itr];
unsigned char ch2 = tmp[itr + 1];
unsigned char ch3 = tmp[itr + 2];
if(ch1 == 0xE2 && ch2 == 0x80 && ch3 == 0xA3)
split = itr;
}
if(split)
return std::make_pair(tmp.substr(0, split), tmp.substr(split + 3));
else
return std::make_pair("(Uncategorized)", tmp);
if(i.size() == 1)
return items[string_list<char>()];
if(items.count(i) && items[i].IsOk())
return items[i];
return items[i] = controls->AppendItem(get_item(i.strip_one()), towxstring(i[i.size() - 1]));
}
string_list<char> wxeditor_esettings_controllers::get_selection()
{
if(closing())
return string_list<char>();
string_list<char> sel;
wxTreeItemId id = controls->GetSelection();
for(auto i : items)
if(i.second == id)
sel = i.first;
return sel;
}
void wxeditor_esettings_controllers::on_change(wxCommandEvent& e)
{
if(closing())
return;
int c = category->GetSelection();
if(c == wxNOT_FOUND) {
category->SetSelection(0);
change_category(0);
} else
change_category(c);
}
void wxeditor_esettings_controllers::change_category(int cat)
{
if(closing())
return;
std::map<int, std::string> n;
for(auto i : itemlabels)
if(i.first.first == cat)
n[i.first.second] = i.second;
for(size_t i = 0; i < control->GetCount(); i++)
if(n.count(i))
control->SetString(i, towxstring(n[i]));
else
control->Delete(i--);
for(auto i : n)
if(i.first >= (int)control->GetCount())
control->Append(towxstring(n[i.first]));
if(control->GetSelection() == wxNOT_FOUND && !control->IsEmpty())
control->SetSelection(0);
string_list<char> sel = get_selection();
set_button->Enable(realitems.count(sel));
clear_button->Enable(realitems.count(sel));
}
wxeditor_esettings_controllers::~wxeditor_esettings_controllers()
@ -113,13 +95,14 @@ namespace
{
if(closing())
return;
std::string name = items[std::make_pair(category->GetSelection(), control->GetSelection())];
string_list<char> sel = get_selection();
std::string name = names.count(sel) ? names[sel] : "";
if(name == "") {
refresh();
return;
}
try {
controller_key* ik = realitems[name];
controller_key* ik = realitems[sel];
if(!ik) {
refresh();
return;
@ -130,7 +113,8 @@ namespace
p->ShowModal();
std::string key = p->getkey();
p->Destroy();
ik->append(key);
if(key != "")
ik->append(key);
} catch(...) {
}
refresh();
@ -140,13 +124,14 @@ namespace
{
if(closing())
return;
std::string name = items[std::make_pair(category->GetSelection(), control->GetSelection())];
string_list<char> sel = get_selection();
std::string name = names.count(sel) ? names[sel] : "";
if(name == "") {
refresh();
return;
}
try {
controller_key* ik = realitems[name];
controller_key* ik = realitems[sel];
if(!ik) {
refresh();
return;
@ -157,6 +142,10 @@ namespace
while((tmp = ik->get_string(idx++)) != "")
dropchoices.push_back(towxstring(tmp));
idx = 0;
if(dropchoices.size() == 0) {
refresh();
return;
}
if(dropchoices.size() > 1) {
wxSingleChoiceDialog* d2 = new wxSingleChoiceDialog(this,
towxstring("Select key to remove from set"), towxstring("Pick key to drop"),
@ -181,47 +170,41 @@ namespace
if(closing())
return;
std::map<controller_key*, std::string> data;
std::map<std::string, int> cat_set;
std::map<std::string, int> cat_assign;
realitems.clear();
auto x = lsnes_mapper.get_controller_keys();
realitems.clear();
for(auto y : x) {
realitems[y->get_name()] = y;
string_list<char> key = split_on_codepoint(y->get_name(), U'\u2023');
names[key] = y->get_name();
realitems[key] = y;
std::string tmp;
unsigned idx = 0;
while((tmp = y->get_string(idx++)) != "")
data[y] += ((data[y] != "") ? ", " : "") + tmp;
}
int cidx = 0;
for(auto i : realitems) {
std::pair<std::string, std::string> j = splitkeyname(i.first);
if(!cat_set.count(j.first)) {
categories[cidx] = j.first;
cat_assign[j.first] = 0;
cat_set[j.first] = cidx++;
//Delete no longer present stuff.
for(auto i = items.rbegin(); i != items.rend(); i++) {
auto j = realitems.lower_bound(i->first);
if(j == realitems.end() || !i->first.prefix_of(j->first)) {
//Delete this item.
if(i->second.IsOk())
controls->Delete(i->second);
items[i->first] = wxTreeItemId();
}
items[std::make_pair(cat_set[j.first], cat_assign[j.first])] = i.first;
std::string text = j.second;
}
for(auto i : realitems) {
string_list<char> key = i.first;
std::string text = key[key.size() - 1];
if(data[i.second] == "")
text = text + " (not set)";
else
text = text + " (" + clean_keystring(data[i.second]) + ")";
itemlabels[std::make_pair(cat_set[j.first], cat_assign[j.first])] = text;
cat_assign[j.first]++;
wxTreeItemId id = get_item(key);
controls->SetItemText(id, towxstring(text));
}
for(size_t i = 0; i < category->GetCount(); i++)
if(categories.count(i))
category->SetString(i, towxstring(categories[i]));
else
category->Delete(i--);
for(auto i : categories)
if(i.first >= (int)category->GetCount())
category->Append(towxstring(categories[i.first]));
if(category->GetSelection() == wxNOT_FOUND && !category->IsEmpty())
category->SetSelection(0);
change_category(category->GetSelection());
wxCommandEvent e;
on_change(e);
}
settings_tab_factory controllers("Controllers", [](wxWindow* parent) -> settings_tab* {

View file

@ -15,17 +15,15 @@ namespace
void on_change(wxCommandEvent& e);
void on_notify() { refresh(); }
private:
wxListBox* category;
wxListBox* control;
wxTreeCtrl* controls;
wxButton* pri_button;
wxButton* sec_button;
std::map<int, std::string> categories;
std::map<std::pair<int, int>, std::string> itemlabels;
std::map<std::pair<int, int>, std::string> items;
std::map<std::string, inverse_bind*> realitems;
void change_category(int cat);
std::map<string_list<char>, wxTreeItemId> items;
std::map<string_list<char>, std::string> names;
std::map<string_list<char>, inverse_bind*> realitems;
void refresh();
std::pair<std::string, std::string> splitkeyname(const std::string& kn);
string_list<char> get_selection();
wxTreeItemId get_item(const string_list<char>& i);
};
@ -34,13 +32,10 @@ namespace
{
wxSizer* top_s = new wxBoxSizer(wxVERTICAL);
SetSizer(top_s);
wxString empty[1];
top_s->Add(category = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 1, empty), 1,
wxGROW);
top_s->Add(control = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 1, empty), 1,
wxGROW);
category->Connect(wxEVT_COMMAND_LISTBOX_SELECTED,
top_s->Add(controls = new wxTreeCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxTR_HIDE_ROOT | wxTR_LINES_AT_ROOT), 1, wxGROW);
controls->Connect(wxEVT_COMMAND_TREE_SEL_CHANGED,
wxCommandEventHandler(wxeditor_esettings_hotkeys::on_change), NULL, this);
wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
@ -48,64 +43,46 @@ namespace
pbutton_s->Add(pri_button = new wxButton(this, wxID_ANY, wxT("Add")), 0, wxGROW);
pri_button->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wxeditor_esettings_hotkeys::on_add), NULL, this);
pri_button->Enable(false);
pbutton_s->Add(sec_button = new wxButton(this, wxID_ANY, wxT("Drop")), 0, wxGROW);
sec_button->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(wxeditor_esettings_hotkeys::on_drop), NULL, this);
sec_button->Enable(false);
top_s->Add(pbutton_s, 0, wxGROW);
items[string_list<char>()] = controls->AddRoot(wxT(""));
refresh();
top_s->SetSizeHints(this);
Fit();
}
std::pair<std::string, std::string> wxeditor_esettings_hotkeys::splitkeyname(const std::string& kn)
wxTreeItemId wxeditor_esettings_hotkeys::get_item(const string_list<char>& i)
{
std::string tmp = kn;
size_t split = 0;
for(size_t itr = 0; itr < tmp.length() - 2 && itr < tmp.length(); itr++) {
unsigned char ch1 = tmp[itr];
unsigned char ch2 = tmp[itr + 1];
unsigned char ch3 = tmp[itr + 2];
if(ch1 == 0xE2 && ch2 == 0x80 && ch3 == 0xA3)
split = itr;
}
if(split)
return std::make_pair(tmp.substr(0, split), tmp.substr(split + 3));
else
return std::make_pair("(Uncategorized)", tmp);
if(items.count(i) && items[i].IsOk())
return items[i];
return items[i] = controls->AppendItem(get_item(i.strip_one()), towxstring(i[i.size() - 1]));
}
string_list<char> wxeditor_esettings_hotkeys::get_selection()
{
if(closing())
return string_list<char>();
string_list<char> sel;
wxTreeItemId id = controls->GetSelection();
for(auto i : items)
if(i.second == id)
sel = i.first;
return sel;
}
void wxeditor_esettings_hotkeys::on_change(wxCommandEvent& e)
{
if(closing())
return;
int c = category->GetSelection();
if(c == wxNOT_FOUND) {
category->SetSelection(0);
change_category(0);
} else
change_category(c);
}
void wxeditor_esettings_hotkeys::change_category(int cat)
{
if(closing())
return;
std::map<int, std::string> n;
for(auto i : itemlabels)
if(i.first.first == cat)
n[i.first.second] = i.second;
for(size_t i = 0; i < control->GetCount(); i++)
if(n.count(i))
control->SetString(i, towxstring(n[i]));
else
control->Delete(i--);
for(auto i : n)
if(i.first >= (int)control->GetCount())
control->Append(towxstring(n[i.first]));
if(control->GetSelection() == wxNOT_FOUND)
control->SetSelection(0);
string_list<char> sel = get_selection();
pri_button->Enable(realitems.count(sel));
sec_button->Enable(realitems.count(sel));
}
wxeditor_esettings_hotkeys::~wxeditor_esettings_hotkeys()
@ -116,13 +93,14 @@ namespace
{
if(closing())
return;
std::string name = items[std::make_pair(category->GetSelection(), control->GetSelection())];
string_list<char> sel = get_selection();
std::string name = names.count(sel) ? names[sel] : "";
if(name == "") {
refresh();
return;
}
try {
inverse_bind* ik = realitems[name];
inverse_bind* ik = realitems[sel];
if(!ik) {
refresh();
return;
@ -134,7 +112,8 @@ namespace
}
std::string key = d->getkey();
d->Destroy();
ik->append(key);
if(key != "")
ik->append(key);
} catch(...) {
}
refresh();
@ -144,13 +123,14 @@ namespace
{
if(closing())
return;
std::string name = items[std::make_pair(category->GetSelection(), control->GetSelection())];
string_list<char> sel = get_selection();
std::string name = names.count(sel) ? names[sel] : "";
if(name == "") {
refresh();
return;
}
try {
inverse_bind* ik = realitems[name];
inverse_bind* ik = realitems[sel];
if(!ik) {
refresh();
return;
@ -184,29 +164,31 @@ namespace
if(closing())
return;
std::map<inverse_bind*, std::list<key_specifier>> data;
std::map<std::string, int> cat_set;
std::map<std::string, int> cat_assign;
realitems.clear();
itemlabels.clear();
auto x = lsnes_mapper.get_inverses();
for(auto y : x) {
realitems[y->getname()] = y;
string_list<char> key = split_on_codepoint(y->getname(), U'\u2023');
names[key] = y->getname();
realitems[key] = y;
key_specifier tmp;
unsigned idx = 0;
while((tmp = y->get(idx++)))
data[y].push_back(tmp);
}
int cidx = 0;
for(auto i : realitems) {
std::pair<std::string, std::string> j = splitkeyname(i.first);
if(!cat_set.count(j.first)) {
categories[cidx] = j.first;
cat_assign[j.first] = 0;
cat_set[j.first] = cidx++;
//Delete no longer present stuff.
for(auto i = items.rbegin(); i != items.rend(); i++) {
auto j = realitems.lower_bound(i->first);
if(j == realitems.end() || !i->first.prefix_of(j->first)) {
//Delete this item.
if(i->second.IsOk())
controls->Delete(i->second);
items[i->first] = wxTreeItemId();
}
items[std::make_pair(cat_set[j.first], cat_assign[j.first])] = i.first;
std::string text = j.second;
}
//Update the rest.
for(auto i : realitems) {
string_list<char> key = i.first;
std::string text = key[key.size() - 1];
auto& I = data[i.second];
if(I.empty())
text = text + " (not set)";
@ -221,21 +203,9 @@ namespace
}
text = text + ")";
}
itemlabels[std::make_pair(cat_set[j.first], cat_assign[j.first])] = text;
cat_assign[j.first]++;
wxTreeItemId id = get_item(key);
controls->SetItemText(id, towxstring(text));
}
for(size_t i = 0; i < category->GetCount(); i++)
if(categories.count(i))
category->SetString(i, towxstring(categories[i]));
else
category->Delete(i--);
for(auto i : categories)
if(i.first >= (int)category->GetCount())
category->Append(towxstring(categories[i.first]));
if(category->GetSelection() == wxNOT_FOUND)
category->SetSelection(0);
change_category(category->GetSelection());
}
settings_tab_factory hotkeys("Hotkeys", [](wxWindow* parent) -> settings_tab* {