Skip to content

Commit 0421b29

Browse files
authored
Merge pull request #557 from gabriel-roth/aliases
Add user-defined aliases for modules
2 parents af43cea + 6975676 commit 0421b29

File tree

8 files changed

+146
-10
lines changed

8 files changed

+146
-10
lines changed

firmware/src/gui/elements/element_name.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ get_full_element_name(unsigned module_id, unsigned element_idx, ElementType type
1616
FullElementName fullname{"?", "?"};
1717

1818
if (module_id < patch.module_slugs.size()) {
19-
fullname.module_name = ModuleFactory::getModuleDisplayName(patch.module_slugs[module_id]);
19+
auto alias = patch.get_module_alias(static_cast<uint16_t>(module_id));
20+
fullname.module_name = alias.empty() ? ModuleFactory::getModuleDisplayName(patch.module_slugs[module_id]) : alias;
2021

2122
auto &info = ModuleFactory::getModuleInfo(patch.module_slugs[module_id]);
2223

firmware/src/gui/pages/keyboard_entry.hh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@ struct KeyboardEntry {
2222
kb_popup.init(parent_obj, parent_group);
2323
}
2424

25-
void show_keyboard(lv_obj_t *textarea_field, FunctionSized<16, void(std::string_view)> save_callback) {
25+
void show_keyboard(lv_obj_t *textarea_field,
26+
FunctionSized<16, void(std::string_view)> save_callback,
27+
bool hide_field_on_dismiss = false) {
2628
text_field = textarea_field;
29+
hide_on_dismiss = hide_field_on_dismiss;
2730

2831
save_cb = save_callback;
2932

@@ -78,6 +81,8 @@ struct KeyboardEntry {
7881
if (text_field) {
7982
lv_obj_clear_state(text_field, LV_STATE_USER_1);
8083
lv_group_focus_obj(text_field);
84+
if (hide_on_dismiss)
85+
lv_hide(text_field);
8186
}
8287
lv_group_remove_obj(ui_Keyboard);
8388
lv_hide(ui_Keyboard);
@@ -123,6 +128,7 @@ private:
123128
lv_obj_t *text_field = nullptr;
124129

125130
bool kb_visible = false;
131+
bool hide_on_dismiss = false;
126132
ConfirmPopup kb_popup;
127133

128134
FunctionSized<16, void(std::string_view)> save_cb;

firmware/src/gui/pages/module_view/action_menu.hh

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
#pragma once
2+
#include "CoreModules/moduleFactory.hh"
23
#include "fat_file_io.hh"
34
#include "gui/gui_state.hh"
45
#include "gui/helpers/lv_helpers.hh"
56
#include "gui/notify/queue.hh"
7+
#include "gui/pages/keyboard_entry.hh"
68
#include "gui/pages/module_view/automap.hh"
79
#include "gui/pages/page_list.hh"
810
#include "gui/pages/roller_popup.hh"
@@ -44,11 +46,27 @@ public:
4446
, reset_params_{patch_mod_queue}
4547
, group(lv_group_create())
4648
, moduleViewActionPresetBut{create_lv_list_button(ui_ModuleViewActionMenu, "Presets")}
47-
, moduleViewActionBypassBut{create_lv_list_button(ui_ModuleViewActionMenu, "Bypass: Off")} {
49+
, moduleViewActionBypassBut{create_lv_list_button(ui_ModuleViewActionMenu, "Bypass: Off")}
50+
, moduleViewActionRenameBut{create_lv_list_button(ui_ModuleViewActionMenu, "Rename...")}
51+
, moduleViewActionResetNameBut{create_lv_list_button(ui_ModuleViewActionMenu, "Reset name")} {
4852
lv_obj_set_parent(ui_ModuleViewActionMenu, lv_layer_top());
4953
lv_show(ui_ModuleViewActionMenu);
5054
lv_show(moduleViewActionPresetBut);
5155
lv_show(moduleViewActionBypassBut);
56+
lv_show(moduleViewActionRenameBut);
57+
lv_hide(moduleViewActionResetNameBut);
58+
59+
rename_textarea = lv_textarea_create(lv_layer_top());
60+
lv_hide(rename_textarea);
61+
lv_textarea_set_max_length(rename_textarea, AliasNameString::capacity);
62+
lv_textarea_set_one_line(rename_textarea, true);
63+
lv_obj_set_width(rename_textarea, 300); // screen width (320) minus 10px margin each side
64+
lv_obj_set_style_bg_opa(rename_textarea, LV_OPA_COVER, 0);
65+
lv_obj_set_style_border_color(rename_textarea, lv_color_white(), LV_PART_CURSOR | LV_STATE_DEFAULT);
66+
lv_obj_set_style_border_opa(rename_textarea, LV_OPA_COVER, LV_PART_CURSOR | LV_STATE_DEFAULT);
67+
lv_obj_set_style_border_width(rename_textarea, 1, LV_PART_CURSOR | LV_STATE_DEFAULT);
68+
lv_obj_set_style_border_side(rename_textarea, LV_BORDER_SIDE_LEFT, LV_PART_CURSOR | LV_STATE_DEFAULT);
69+
lv_obj_add_event_cb(rename_textarea, textarea_changed_cb, LV_EVENT_VALUE_CHANGED, this);
5270
lv_obj_set_x(ui_ModuleViewActionMenu, 160);
5371
lv_obj_set_height(ui_ModuleViewActionMenu, 240);
5472

@@ -64,6 +82,8 @@ public:
6482
lv_obj_add_event_cb(ui_ModuleViewActionResetBut, reset_but_cb, LV_EVENT_CLICKED, this);
6583
lv_obj_add_event_cb(ui_ModuleViewActionMidiBut, midi_but_cb, LV_EVENT_CLICKED, this);
6684
lv_obj_add_event_cb(moduleViewActionBypassBut, bypass_but_cb, LV_EVENT_CLICKED, this);
85+
lv_obj_add_event_cb(moduleViewActionRenameBut, rename_but_cb, LV_EVENT_CLICKED, this);
86+
lv_obj_add_event_cb(moduleViewActionResetNameBut, reset_name_but_cb, LV_EVENT_CLICKED, this);
6787

6888
lv_group_add_obj(group, ui_ModuleViewActionAutopatchBut);
6989
lv_group_add_obj(group, ui_ModuleViewActionAutoKnobSet);
@@ -72,6 +92,8 @@ public:
7292
lv_group_add_obj(group, ui_ModuleViewActionMidiBut);
7393
lv_group_add_obj(group, moduleViewActionPresetBut);
7494
lv_group_add_obj(group, moduleViewActionBypassBut);
95+
lv_group_add_obj(group, moduleViewActionRenameBut);
96+
lv_group_add_obj(group, moduleViewActionResetNameBut);
7597
lv_group_add_obj(group, ui_ModuleViewActionDeleteBut);
7698
lv_group_set_wrap(group, false);
7799
}
@@ -80,6 +102,8 @@ public:
80102
this->module_idx = module_idx;
81103
base_group = parent_group;
82104
confirm_popup.init(lv_layer_top(), group);
105+
reset_name_popup.init(lv_layer_top(), base_group);
106+
keyboard_entry.prepare_focus(lv_layer_top(), base_group);
83107

84108
const auto module_slug = std::string{patches.get_view_patch()->module_slugs[module_idx]};
85109
const auto module_name = module_slug.substr(module_slug.find_first_of(':') + 1);
@@ -129,8 +153,12 @@ public:
129153
preset_popup.hide();
130154
} else if (confirm_popup.is_visible()) {
131155
confirm_popup.hide();
156+
} else if (reset_name_popup.is_visible()) {
157+
reset_name_popup.hide();
132158
} else if (auto_map.is_visible()) {
133159
auto_map.hide();
160+
} else if (keyboard_entry.is_visible()) {
161+
keyboard_entry.back();
134162
} else if (visible) {
135163
hide();
136164
}
@@ -139,6 +167,7 @@ public:
139167
void hide() {
140168
preset_popup.hide();
141169
confirm_popup.hide();
170+
reset_name_popup.hide();
142171
hide_menu();
143172
}
144173

@@ -154,6 +183,7 @@ public:
154183

155184
void show() {
156185
update_bypass_text();
186+
update_reset_name_visibility();
157187
lv_group_focus_obj(ui_ModuleViewActionAutopatchBut);
158188

159189
if (!visible) {
@@ -170,6 +200,11 @@ public:
170200
return visible;
171201
}
172202

203+
bool keyboard_visible() {
204+
// also covers reset_name_popup which intercepts back button -- consider renaming to modal_visible()
205+
return keyboard_entry.is_visible() || reset_name_popup.is_visible();
206+
}
207+
173208
void reactivate_group() {
174209
lv_group_activate(group);
175210
}
@@ -333,6 +368,11 @@ private:
333368
lv_label_set_text(label, bypassed ? "Bypass: On" : "Bypass: Off");
334369
}
335370

371+
void update_reset_name_visibility() {
372+
auto alias = patches.get_view_patch()->get_module_alias(static_cast<uint16_t>(module_idx));
373+
lv_show(moduleViewActionResetNameBut, !alias.empty());
374+
}
375+
336376
static void bypass_but_cb(lv_event_t *event) {
337377
if (!event || !event->user_data)
338378
return;
@@ -351,6 +391,83 @@ private:
351391
lv_label_set_text(label, new_state ? "Bypass: On" : "Bypass: Off");
352392
}
353393

394+
static void reset_name_but_cb(lv_event_t *event) {
395+
if (!event || !event->user_data)
396+
return;
397+
auto page = static_cast<ModuleViewActionMenu *>(event->user_data);
398+
std::string msg;
399+
{
400+
auto *pd = page->patches.get_view_patch();
401+
auto default_name = ModuleFactory::getModuleDisplayName(pd->module_slugs[page->module_idx]);
402+
msg = "Reset module name to '" + std::string{default_name} + "'?";
403+
}
404+
405+
page->hide_menu();
406+
page->reset_name_popup.show(
407+
[page](unsigned choice) {
408+
if (choice == 1) {
409+
auto *pd = page->patches.get_view_patch();
410+
pd->set_module_alias(static_cast<uint16_t>(page->module_idx), "");
411+
page->patches.mark_view_patch_modified();
412+
auto display = ModuleFactory::getModuleDisplayName(pd->module_slugs[page->module_idx]);
413+
lv_label_set_text(ui_ElementRollerModuleName, display.data());
414+
}
415+
},
416+
msg.c_str(),
417+
"Reset");
418+
}
419+
420+
static void textarea_changed_cb(lv_event_t *event) {
421+
if (!event || !event->user_data)
422+
return;
423+
auto page = static_cast<ModuleViewActionMenu *>(event->user_data);
424+
std::string_view text = lv_textarea_get_text(page->rename_textarea);
425+
auto *pd = page->patches.get_view_patch();
426+
std::string_view display = text.empty()
427+
? (page->pending_alias.empty()
428+
? ModuleFactory::getModuleDisplayName(pd->module_slugs[page->module_idx])
429+
: std::string_view{page->pending_alias})
430+
: text;
431+
lv_label_set_text(ui_ElementRollerModuleName, display.data());
432+
}
433+
434+
static void rename_but_cb(lv_event_t *event) {
435+
if (!event || !event->user_data)
436+
return;
437+
auto page = static_cast<ModuleViewActionMenu *>(event->user_data);
438+
439+
auto *pd = page->patches.get_view_patch();
440+
auto alias = pd->get_module_alias(static_cast<uint16_t>(page->module_idx));
441+
442+
// Show current alias (or module name) as greyed-out placeholder; don't pre-fill
443+
std::string_view placeholder = alias.empty()
444+
? ModuleFactory::getModuleDisplayName(pd->module_slugs[page->module_idx])
445+
: alias;
446+
lv_textarea_set_placeholder_text(page->rename_textarea, placeholder.data());
447+
lv_textarea_set_text(page->rename_textarea, "");
448+
lv_label_set_text(ui_ElementRollerModuleName, placeholder.data());
449+
450+
page->hide_menu();
451+
page->pending_alias = alias;
452+
page->keyboard_entry.show_keyboard(
453+
page->rename_textarea,
454+
[page](std::string_view text) {
455+
auto *pd = page->patches.get_view_patch();
456+
// Empty text means user didn't type anything — preserve existing alias
457+
std::string_view actual = text.empty() ? std::string_view{page->pending_alias} : text;
458+
pd->set_module_alias(static_cast<uint16_t>(page->module_idx), actual);
459+
page->patches.mark_view_patch_modified();
460+
461+
std::string_view display = actual.empty()
462+
? ModuleFactory::getModuleDisplayName(pd->module_slugs[page->module_idx])
463+
: actual;
464+
lv_label_set_text(ui_ElementRollerModuleName, display.data());
465+
},
466+
/*hide_field_on_dismiss=*/true);
467+
lv_show(page->rename_textarea);
468+
lv_obj_align_to(page->rename_textarea, ui_Keyboard, LV_ALIGN_OUT_TOP_MID, 0, -4);
469+
}
470+
354471
FatFileIO &ramdisk;
355472
OpenPatchManager &patches;
356473
PageList &page_list;
@@ -360,6 +477,7 @@ private:
360477
NotificationQueue &notify_queue;
361478

362479
ConfirmPopup confirm_popup;
480+
ConfirmPopup reset_name_popup;
363481

364482
ModuleViewAutoMapDialog auto_map;
365483
RandomizeParams randomizer;
@@ -372,6 +490,11 @@ private:
372490

373491
lv_obj_t *moduleViewActionPresetBut;
374492
lv_obj_t *moduleViewActionBypassBut;
493+
lv_obj_t *moduleViewActionRenameBut;
494+
lv_obj_t *moduleViewActionResetNameBut;
495+
lv_obj_t *rename_textarea = nullptr;
496+
std::string pending_alias{};
497+
KeyboardEntry keyboard_entry;
375498
std::string preset_path{};
376499
uint16_t cur_preset_idx{};
377500
std::string presets{};

firmware/src/gui/pages/module_view/automap.hh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ private:
178178
void name_knobset_by_modulename(uint16_t knobset_id) {
179179
if (knobset_id < patch->knob_sets.size()) {
180180
if (module_idx < patch->module_slugs.size()) {
181-
auto module_display_name = ModuleFactory::getModuleDisplayName(patch->module_slugs[module_idx]);
181+
auto alias = patch->get_module_alias(static_cast<uint16_t>(module_idx));
182+
auto module_display_name = alias.empty() ? ModuleFactory::getModuleDisplayName(patch->module_slugs[module_idx]) : alias;
182183
patch->knob_sets[knobset_id].name = module_display_name;
183184
}
184185
}

firmware/src/gui/pages/module_view/mapping_pane.hh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ struct ModuleViewMappingPane {
100100
args.detail_mode = true;
101101

102102
auto slug = patch->module_slugs[this_module_id];
103-
auto display_name = ModuleFactory::getModuleDisplayName(slug);
103+
auto alias = patch->get_module_alias(static_cast<uint16_t>(this_module_id));
104+
auto display_name = alias.empty() ? ModuleFactory::getModuleDisplayName(slug) : alias;
104105

105106
// Knob name label
106107
lv_label_set_text(ui_Module_Name, display_name.data());

firmware/src/gui/pages/module_view/module_view.hh

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,9 @@ struct ModuleViewPage : PageBase {
116116
return;
117117
}
118118

119-
auto module_display_name = ModuleFactory::getModuleDisplayName(slug);
120-
lv_label_set_text(ui_ElementRollerModuleName, module_display_name.data());
119+
auto alias = patch->get_module_alias(static_cast<uint16_t>(this_module_id));
120+
auto display = alias.empty() ? ModuleFactory::getModuleDisplayName(slug) : alias;
121+
lv_label_set_text(ui_ElementRollerModuleName, display.data());
121122

122123
has_context_menu = module_context_menu.create_options_menu(this_module_id);
123124

@@ -166,7 +167,7 @@ struct ModuleViewPage : PageBase {
166167
// Back button
167168
if (gui_state.back_button.is_just_released()) {
168169

169-
if (action_menu.is_visible()) {
170+
if (action_menu.is_visible() || action_menu.keyboard_visible()) {
170171
action_menu.back();
171172

172173
} else if (settings_menu.is_visible()) {

firmware/src/gui/pages/patch_view.hh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,10 @@ private:
708708
page->highlighted_module_obj = this_module_obj;
709709

710710
const auto this_slug = page->patch->module_slugs[module_id];
711-
if (auto display_name = ModuleFactory::getModuleDisplayName(this_slug); display_name.length()) {
711+
auto alias = page->patch->get_module_alias(static_cast<uint16_t>(module_id));
712+
if (!alias.empty()) {
713+
lv_label_set_text(ui_ModuleName, alias.data());
714+
} else if (auto display_name = ModuleFactory::getModuleDisplayName(this_slug); display_name.length()) {
712715
lv_label_set_text(ui_ModuleName, display_name.data());
713716
} else {
714717
lv_label_set_text(ui_ModuleName, "");

0 commit comments

Comments
 (0)