diff --git a/src/HC-1/HC-1-menu.cpp b/src/HC-1/HC-1-menu.cpp index ef08045..95afdb1 100644 --- a/src/HC-1/HC-1-menu.cpp +++ b/src/HC-1/HC-1-menu.cpp @@ -16,8 +16,7 @@ void Hc1ModuleWidget::addSortBy(Menu *menu, std::string name, PresetOrder order) menu->addChild(createCheckMenuItem(name, "", [=](){ return my_module->preset_order == order; }, [=](){ - my_module->preset_order = order; - std::sort(my_module->system_presets.begin(), my_module->system_presets.end(), getPresetSort(my_module->preset_order)); + my_module->setPresetOrder(order); if (PresetTab::System == tab) { populatePresetWidgets(); showCurrentPreset(false); @@ -26,6 +25,13 @@ void Hc1ModuleWidget::addSortBy(Menu *menu, std::string name, PresetOrder order) )); } +void Hc1ModuleWidget::addJumpCategory(Menu *menu, uint16_t category) +{ + auto title = format_string("%s (%s)", hcCategoryCode.categoryName(category).c_str(), CategoryCode(category).to_string().c_str()); + menu->addChild(createMenuItem(title, "", + [=](){ toCategory(category); })); +} + void Hc1ModuleWidget::addRecirculator(Menu *menu, EM_Recirculator kind) { menu->addChild(createCheckMenuItem(RecirculatorName(kind), "", @@ -122,6 +128,22 @@ void Hc1ModuleWidget::appendContextMenu(Menu *menu) menu->addChild(createMenuItem("Refresh User presets", "", [=](){ my_module->transmitRequestUserPresets(); })); })); + menu->addChild(createSubmenuItem("Go to category", "", [=](Menu* menu) { + addJumpCategory(menu, ST); + addJumpCategory(menu, WI); + addJumpCategory(menu, VO); + addJumpCategory(menu, KY); + addJumpCategory(menu, CL); + addJumpCategory(menu, OT); + addJumpCategory(menu, PE); + addJumpCategory(menu, PT); + addJumpCategory(menu, PR); + addJumpCategory(menu, DO); + addJumpCategory(menu, MD); + addJumpCategory(menu, CV); + addJumpCategory(menu, UT); + })); + menu->addChild(createSubmenuItem("Sort System presets", "", [=](Menu* menu) { addSortBy(menu, "Alphabetically", PresetOrder::Alpha); addSortBy(menu, "by Category", PresetOrder::Category); diff --git a/src/HC-1/HC-1-presets.cpp b/src/HC-1/HC-1-presets.cpp index 35620ae..40006c0 100644 --- a/src/HC-1/HC-1-presets.cpp +++ b/src/HC-1/HC-1-presets.cpp @@ -1,6 +1,16 @@ #include "HC-1.hpp" namespace pachde { + +void Hc1Module::setPresetOrder(PresetOrder order) +{ + if (order != preset_order) + { + preset_order = order; + std::sort(system_presets.begin(), system_presets.end(), getPresetSort(preset_order)); + } +} + std::string Hc1Module::userPresetsPath() { if (deviceName().empty()) return ""; diff --git a/src/HC-1/HC-1-ui.cpp b/src/HC-1/HC-1-ui.cpp index d87f24d..7998173 100644 --- a/src/HC-1/HC-1-ui.cpp +++ b/src/HC-1/HC-1-ui.cpp @@ -387,18 +387,36 @@ void Hc1ModuleWidget::onPresetChanged(const PresetChangedEvent& e) showCurrentPreset(true); } +void Hc1ModuleWidget::toCategory(uint16_t code) +{ + if (!my_module) return; + my_module->setPresetOrder(PresetOrder::Category); + setTab(PresetTab::System); + if (my_module->current_preset && code == my_module->current_preset->primaryCategory()) { + return; + } + auto mp = my_module->getPresets(tab); + auto index = std::distance(mp.cbegin(), std::find_if(mp.cbegin(), mp.cend(), [=](std::shared_ptr p){ return code == p->primaryCategory(); })); + auto size = static_cast(mp.size()); + if (index == size) { + return; // not found + } + my_module->setPreset(mp[index]); +} + void Hc1ModuleWidget::toRelativePreset(int delta) { if (!my_module) return; auto mp = my_module->getPresets(tab); auto index = std::distance(mp.cbegin(), std::find_if(mp.cbegin(), mp.cend(), [=](std::shared_ptr p){ return isCurrentPreset(p); })); - if (index == mp.size()) { + auto size = static_cast(mp.size()); + if (index == size) { return; // not found } index = (index + delta); if (index < 0) { - index = mp.size() - 1; - } else if (index >= mp.size()) { + index = size - 1; + } else if (index >= size) { index = 0; // wrap to start (clipped) } my_module->setPreset(mp[index]); diff --git a/src/HC-1/HC-1.hpp b/src/HC-1/HC-1.hpp index b2f4dd3..ef1bfc5 100644 --- a/src/HC-1/HC-1.hpp +++ b/src/HC-1/HC-1.hpp @@ -87,6 +87,7 @@ struct Hc1Module : IPresetHolder, ISendMidi, midi::Input, Module PresetFilter preset_filter; #endif PresetOrder preset_order = PresetOrder::Alpha; + void setPresetOrder(PresetOrder order); std::string favoritesPath(); void clearFavorites(); @@ -444,6 +445,7 @@ struct Hc1ModuleWidget : ModuleWidget, IPresetHolder, IHandleHcEvents void pageUp(); void pageDown(); void toRelativePreset(int delta); + void toCategory(uint16_t code); void clearPresetWidgets(); void populatePresetWidgets(); void updatePresetWidgets(); @@ -486,6 +488,7 @@ struct Hc1ModuleWidget : ModuleWidget, IPresetHolder, IHandleHcEvents // HC-1-menu.cpp void addSortBy(Menu *menu, std::string name, PresetOrder order); + void addJumpCategory(Menu *menu, uint16_t category); void addRecirculator(Menu *menu, EM_Recirculator kind); void appendContextMenu(Menu *menu) override; }; diff --git a/src/preset_meta.cpp b/src/preset_meta.cpp index bc05860..67cb731 100644 --- a/src/preset_meta.cpp +++ b/src/preset_meta.cpp @@ -127,9 +127,14 @@ HCCategoryCode::HCCategoryCode() std::sort(data.begin(), data.end(), [](const std::shared_ptr& a, const std::shared_ptr& b) { return a->code < b->code; }); } +std::string HCCategoryCode::categoryName(uint16_t key) const +{ + auto cat = find(key); + return cat ? cat->name : "Unknown"; +} + std::shared_ptr HCCategoryCode::find(uint16_t key) const { - //auto key = make_cat_code(code_text); auto item = std::lower_bound(data.cbegin(), data.cend(), key, [](const std::shared_ptr &p, uint16_t key){ return p->code < key; }); return data.cend() != item ? *item : nullptr; } diff --git a/src/preset_meta.hpp b/src/preset_meta.hpp index d05ec48..a96317e 100644 --- a/src/preset_meta.hpp +++ b/src/preset_meta.hpp @@ -154,6 +154,7 @@ class HCCategoryCode std::vector> make_category_list(const std::string& text) const; std::string make_category_json(const std::string& text) const; std::string make_category_mulitline_text(const std::string& text) const; + std::string categoryName(uint16_t key) const; }; void FillCategoryCodeList(const std::string& text, std::vector& vec); diff --git a/src/preset_widget.hpp b/src/preset_widget.hpp index 5d28cfd..4bdab22 100644 --- a/src/preset_widget.hpp +++ b/src/preset_widget.hpp @@ -47,8 +47,7 @@ struct PresetWidget : TipWidget symbol->setSymbol((0 == preset->bank_hi) ? 1 : 0); symbol->box.pos.x = preset->favorite ? 12.f : 4.f; text_label->text(preset->name); - auto code = *preset->get_category_list().cbegin(); - text_code->text(CategoryCode(code).to_string()); + text_code->text(preset->categoryName()); } else { tip_text = "(no preset)"; symbol->setSymbol(0); diff --git a/src/presets.cpp b/src/presets.cpp index 1595d02..4206361 100644 --- a/src/presets.cpp +++ b/src/presets.cpp @@ -51,6 +51,17 @@ std::string Preset::describe(bool multi_line /*= true*/) line_break, m.empty() ? "-" : m.c_str() ); } +uint16_t Preset::primaryCategory() +{ + ensure_category_list(); + if (categories.empty()) return OT; + return *categories.cbegin(); +} + +std::string Preset::categoryName() +{ + return CategoryCode(primaryCategory()).to_string(); +} void Preset::nada() { diff --git a/src/presets.hpp b/src/presets.hpp index ce420d2..7f13506 100644 --- a/src/presets.hpp +++ b/src/presets.hpp @@ -118,6 +118,8 @@ struct Preset std::string meta(); // cached std::string make_friendly_text(); // not cached + std::string categoryName(); + uint16_t primaryCategory(); void clear(); std::string describe_short(); std::string describe(bool multi_line = true);