diff --git a/src/hotkey_data_view_model.cpp b/src/hotkey_data_view_model.cpp index 9dc25f901e..5187cc0807 100644 --- a/src/hotkey_data_view_model.cpp +++ b/src/hotkey_data_view_model.cpp @@ -84,14 +84,7 @@ class HotkeyModelCombo final : public HotkeyModelItem { if (col == 0) variant = to_wx(combo.Str()); else if (col == 1) { - wxBitmapBundle icon; - try { - icon = cmd::get(combo.CmdName())->Icon(); - } - catch (agi::Exception const&) { - // Just use no icon; error is reported in the description column - } - variant << wxDataViewIconText(to_wx(combo.CmdName()), icon); + variant = to_wx(combo.CmdName()); } else if (col == 2) { try { @@ -112,9 +105,17 @@ class HotkeyModelCombo final : public HotkeyModelItem { return true; } else if (col == 1) { - wxDataViewIconText text; - text << variant; - cmd_name = from_wx(text.GetText()); + if (variant.GetType() == "wxDataViewIconText") { + wxDataViewIconText text; + text << variant; + cmd_name = from_wx(text.GetText()); + } + else if (variant.GetType() == "string") { + cmd_name = from_wx(variant.GetString()); + } + else { + return false; + } combo = Combo(combo.Context(), cmd_name, combo.Str()); return true; } @@ -147,7 +148,14 @@ class HotkeyModelCategory final : public HotkeyModelItem { void Delete(wxDataViewItem const& item) { for (auto it = children.begin(); it != children.end(); ++it) { if (&*it == item.GetID()) { - model->ItemDeleted(wxDataViewItem(this), wxDataViewItem((void*)&*it)); + wxDataViewItem deleted_item((void*)&*it); + for (auto visible_it = visible_items.begin(); visible_it != visible_items.end(); ++visible_it) { + if (visible_it->GetID() == deleted_item.GetID()) { + visible_items.erase(visible_it); + break; + } + } + model->ItemDeleted(wxDataViewItem(this), deleted_item); children.erase(it); return; } @@ -193,11 +201,8 @@ class HotkeyModelCategory final : public HotkeyModelItem { wxDataViewItem GetParent() const override { return wxDataViewItem(nullptr); } bool IsContainer() const override { return true; } bool SetValue(wxVariant const&, unsigned int) override { return false; } - void GetValue(wxVariant &variant, unsigned int col) const override { - if (col == 1) - variant << wxDataViewIconText(translated_name); - else - variant = translated_name; + void GetValue(wxVariant &variant, unsigned int) const override { + variant = translated_name; } unsigned int GetChildren(wxDataViewItemArray &out) const override { diff --git a/src/preferences.cpp b/src/preferences.cpp index e92e750f02..01e8221621 100644 --- a/src/preferences.cpp +++ b/src/preferences.cpp @@ -59,6 +59,40 @@ #include namespace { +wxArrayString get_registered_commands() { + wxArrayString commands = to_wx(cmd::get_registered_commands()); + commands.Sort(); + return commands; +} + +#ifdef __APPLE__ +void add_current_hotkey_commands(wxArrayString& commands, HotkeyDataViewModel *model, wxDataViewItem const& parent) { + wxDataViewItemArray children; + model->GetChildren(parent, children); + + for (auto const& child : children) { + wxVariant value; + model->GetValue(value, child, 1); + wxString command = value.GetString(); + if (commands.Index(command) == wxNOT_FOUND) + commands.Add(command); + + if (model->IsContainer(child)) + add_current_hotkey_commands(commands, model, child); + } +} + +wxArrayString get_hotkey_command_choices(HotkeyDataViewModel *model) { + wxArrayString commands = get_registered_commands(); + if (commands.Index("") == wxNOT_FOUND) + commands.Add(""); + + add_current_hotkey_commands(commands, model, wxDataViewItem(nullptr)); + commands.Sort(); + return commands; +} +#endif + /// General preferences page void General(wxTreebook *book, Preferences *parent) { auto p = new OptionPage(book, parent, _("General")); @@ -481,18 +515,34 @@ class CommandRenderer final : public wxDataViewCustomRenderer { wxDataViewIconText value; static const int icon_width = 20; + wxDataViewIconText MakeValue(wxString const& text) const { + wxBitmapBundle icon; + try { + icon = cmd::get(from_wx(text))->Icon(); + } + catch (agi::Exception const&) { + // Invalid command names are reported in the description column. + } + return wxDataViewIconText(text, icon); + } + public: CommandRenderer() - : wxDataViewCustomRenderer("wxDataViewIconText", wxDATAVIEW_CELL_EDITABLE) - , autocomplete(to_wx(cmd::get_registered_commands())) + : wxDataViewCustomRenderer("string", wxDATAVIEW_CELL_EDITABLE) + , autocomplete(get_registered_commands()) { } wxWindow *CreateEditorCtrl(wxWindow *parent, wxRect label_rect, wxVariant const& value) override { - wxDataViewIconText iconText; - iconText << value; - - wxString text = iconText.GetText(); + wxString text; + if (value.GetType() == "wxDataViewIconText") { + wxDataViewIconText iconText; + iconText << value; + text = iconText.GetText(); + } + else { + text = value.GetString(); + } // adjust the label rect to take the width of the icon into account label_rect.x += parent->FromDIP(icon_width); @@ -510,6 +560,10 @@ class CommandRenderer final : public wxDataViewCustomRenderer { value << var; return true; } + if (var.GetType() == "string") { + value = MakeValue(var.GetString()); + return true; + } return false; } @@ -537,8 +591,7 @@ class CommandRenderer final : public wxDataViewCustomRenderer { bool GetValueFromEditorCtrl(wxWindow* editor, wxVariant &var) override { wxTextCtrl *text = static_cast(editor); - wxDataViewIconText iconText(text->GetValue(), value.GetIcon()); - var << iconText; + var = text->GetValue(); return true; } @@ -630,7 +683,7 @@ Interface_Hotkeys::Interface_Hotkeys(wxTreebook *book, Preferences *parent) auto col = new wxDataViewColumn(_("Hotkey"), new wxDataViewTextRenderer("string", wxDATAVIEW_CELL_EDITABLE), 0, 150, wxALIGN_LEFT, wxCOL_SORTABLE | wxCOL_RESIZABLE); col->SetMinWidth(150); dvc->AppendColumn(col); - dvc->AppendColumn(new wxDataViewColumn(_("Command"), new wxDataViewIconTextRenderer("wxDataViewIconText", wxDATAVIEW_CELL_EDITABLE), 1, 250, wxALIGN_LEFT, wxCOL_SORTABLE | wxCOL_RESIZABLE)); + dvc->AppendColumn(new wxDataViewColumn(_("Command"), new wxDataViewChoiceRenderer(get_hotkey_command_choices(model.get()), wxDATAVIEW_CELL_EDITABLE), 1, 250, wxALIGN_LEFT, wxCOL_SORTABLE | wxCOL_RESIZABLE)); #endif dvc->AppendTextColumn(_("Description"), 2, wxDATAVIEW_CELL_INERT, 300, wxALIGN_LEFT, wxCOL_SORTABLE | wxCOL_RESIZABLE);