add label scrolling in Bluetooth menu

This commit is contained in:
Brent Perteet
2025-11-19 17:42:22 -06:00
parent a272a15bcf
commit 31e0e3a148
2 changed files with 38 additions and 12 deletions

View File

@@ -23,7 +23,9 @@
"Bash(./build_web_macos.sh:*)", "Bash(./build_web_macos.sh:*)",
"Bash(./dist/ESP32_Flasher.app/Contents/MacOS/ESP32_Flasher:*)", "Bash(./dist/ESP32_Flasher.app/Contents/MacOS/ESP32_Flasher:*)",
"Bash(where:*)", "Bash(where:*)",
"Bash(idf.py size-components:*)" "Bash(idf.py size-components:*)",
"Bash(find:*)",
"Bash(git log:*)"
], ],
"deny": [] "deny": []
} }

View File

@@ -75,6 +75,7 @@ static void bt_device_click_cb(lv_event_t * e);
static void show_calibration_menu(void); static void show_calibration_menu(void);
static lv_obj_t* create_calibration_page(void); static lv_obj_t* create_calibration_page(void);
static void calibration_click_cb(lv_event_t * e); static void calibration_click_cb(lv_event_t * e);
static void update_label_scroll(lv_obj_t * btn, bool focused);
// Menu stack management functions // Menu stack management functions
static void menu_stack_push(lv_obj_t *page); static void menu_stack_push(lv_obj_t *page);
@@ -195,6 +196,7 @@ static lv_obj_t* create_main_page(void) {
lv_obj_t* tmpObj; lv_obj_t* tmpObj;
tmpObj = addMenuItem(main_page, "Bluetooth"); tmpObj = addMenuItem(main_page, "Bluetooth");
lv_obj_add_state(tmpObj, LV_STATE_FOCUSED); // First item focused lv_obj_add_state(tmpObj, LV_STATE_FOCUSED); // First item focused
update_label_scroll(tmpObj, true); // Start scrolling on initially focused item
addMenuItem(main_page, "Calibration"); addMenuItem(main_page, "Calibration");
addMenuItem(main_page, "Volume"); addMenuItem(main_page, "Volume");
@@ -555,10 +557,16 @@ static void menuInc(int inc)
} }
if (next) { if (next) {
// Update scroll on old focused item (stop scrolling)
update_label_scroll(_menuContext.obj, false);
lv_obj_add_state(next, LV_STATE_FOCUSED); lv_obj_add_state(next, LV_STATE_FOCUSED);
lv_obj_clear_state(_menuContext.obj, LV_STATE_FOCUSED); lv_obj_clear_state(_menuContext.obj, LV_STATE_FOCUSED);
lv_obj_scroll_to_view(next, LV_ANIM_ON); lv_obj_scroll_to_view(next, LV_ANIM_ON);
// Update scroll on new focused item (start scrolling)
update_label_scroll(next, true);
_menuContext.obj = next; _menuContext.obj = next;
_menuContext.selected = search_index; _menuContext.selected = search_index;
} }
@@ -586,22 +594,35 @@ static void activate_selected(void)
UNLOCK(); UNLOCK();
} }
// Helper function to update label scroll mode based on focus
static void update_label_scroll(lv_obj_t * btn, bool focused)
{
if (!btn) return;
lv_obj_t * lbl = lv_obj_get_child(btn, 0); // Get the label child
if (!lbl) return;
const char* txt = lv_label_get_text(lbl);
if (focused) {
ESP_LOGI(TAG, "Label focused - starting scroll: %s", txt);
lv_label_set_long_mode(lbl, LV_LABEL_LONG_SCROLL_CIRCULAR);
} else {
ESP_LOGI(TAG, "Label defocused - stopping scroll: %s", txt);
lv_label_set_long_mode(lbl, LV_LABEL_LONG_CLIP);
}
}
// Event handler to control label scrolling based on focus state // Event handler to control label scrolling based on focus state
static void label_scroll_focus_cb(lv_event_t * e) static void label_scroll_focus_cb(lv_event_t * e)
{ {
lv_event_code_t code = lv_event_get_code(e); lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * btn = lv_event_get_target(e); lv_obj_t * btn = lv_event_get_target(e);
lv_obj_t * lbl = lv_obj_get_child(btn, 0); // Get the label child
if (!lbl) return;
if (code == LV_EVENT_FOCUSED) { if (code == LV_EVENT_FOCUSED) {
// Start scrolling when focused update_label_scroll(btn, true);
lv_label_set_long_mode(lbl, LV_LABEL_LONG_SCROLL_CIRCULAR);
} }
else if (code == LV_EVENT_DEFOCUSED) { else if (code == LV_EVENT_DEFOCUSED) {
// Stop scrolling and reset position when defocused update_label_scroll(btn, false);
lv_label_set_long_mode(lbl, LV_LABEL_LONG_CLIP);
} }
} }
@@ -648,12 +669,12 @@ static lv_obj_t * addMenuItem(lv_obj_t *page, const char *text)
lv_obj_set_width(lbl, LV_PCT(95)); // Set width to allow scrolling lv_obj_set_width(lbl, LV_PCT(95)); // Set width to allow scrolling
lv_obj_set_style_radius(lbl, 0, LV_PART_MAIN | LV_STATE_ANY); lv_obj_set_style_radius(lbl, 0, LV_PART_MAIN | LV_STATE_ANY);
lv_obj_set_style_border_width(lbl, 0, LV_PART_MAIN | LV_STATE_ANY); lv_obj_set_style_border_width(lbl, 0, LV_PART_MAIN | LV_STATE_ANY);
lv_obj_set_style_anim_time(lbl, 3000, LV_PART_MAIN); // Set scrolling duration (3 seconds per cycle) lv_obj_set_style_anim_time(lbl, 4000, LV_PART_MAIN); // Set scrolling duration (4 seconds per cycle)
lv_obj_align(lbl, LV_ALIGN_LEFT_MID, 0, 0); // Center vertically, align left horizontally lv_obj_align(lbl, LV_ALIGN_LEFT_MID, 0, 0); // Center vertically, align left horizontally
// Add focus event handler to control scrolling // Add focus event handler to control scrolling (use LV_EVENT_ALL to catch all events)
lv_obj_add_event_cb(btn, label_scroll_focus_cb, LV_EVENT_FOCUSED, NULL); lv_obj_add_event_cb(btn, label_scroll_focus_cb, LV_EVENT_ALL, NULL);
lv_obj_add_event_cb(btn, label_scroll_focus_cb, LV_EVENT_DEFOCUSED, NULL); ESP_LOGI(TAG, "Registered scroll callbacks for menu item: %s", text);
// click callback // click callback
lv_obj_add_event_cb(btn, btn_click_cb, LV_EVENT_CLICKED, NULL); lv_obj_add_event_cb(btn, btn_click_cb, LV_EVENT_CLICKED, NULL);
@@ -881,6 +902,8 @@ static void populate_bt_device_list(bool is_scanning) {
if (focus_target) { if (focus_target) {
lv_obj_add_state(focus_target, LV_STATE_FOCUSED); lv_obj_add_state(focus_target, LV_STATE_FOCUSED);
// Start scrolling on initially focused item
update_label_scroll(focus_target, true);
} }
// Update menu context to track the newly focused item // Update menu context to track the newly focused item
@@ -1485,6 +1508,7 @@ static lv_obj_t* create_calibration_page(void) {
lv_obj_t* cancel_btn = addMenuItem(_calibration_page, "Cancel"); lv_obj_t* cancel_btn = addMenuItem(_calibration_page, "Cancel");
lv_obj_add_event_cb(cancel_btn, calibration_click_cb, LV_EVENT_CLICKED, NULL); lv_obj_add_event_cb(cancel_btn, calibration_click_cb, LV_EVENT_CLICKED, NULL);
lv_obj_add_state(cancel_btn, LV_STATE_FOCUSED); // First item focused lv_obj_add_state(cancel_btn, LV_STATE_FOCUSED); // First item focused
update_label_scroll(cancel_btn, true); // Start scrolling on initially focused item
lv_obj_t* calibrate_btn = addMenuItem(_calibration_page, "Calibrate"); lv_obj_t* calibrate_btn = addMenuItem(_calibration_page, "Calibrate");
lv_obj_add_event_cb(calibrate_btn, calibration_click_cb, LV_EVENT_CLICKED, NULL); lv_obj_add_event_cb(calibrate_btn, calibration_click_cb, LV_EVENT_CLICKED, NULL);