From 31e0e3a14815815818bdc40eab392105b33ee451 Mon Sep 17 00:00:00 2001 From: Brent Perteet Date: Wed, 19 Nov 2025 17:42:22 -0600 Subject: [PATCH] add label scrolling in Bluetooth menu --- .claude/settings.local.json | 4 +++- main/gui.c | 46 ++++++++++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 5298e8f..48e1a51 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -23,7 +23,9 @@ "Bash(./build_web_macos.sh:*)", "Bash(./dist/ESP32_Flasher.app/Contents/MacOS/ESP32_Flasher:*)", "Bash(where:*)", - "Bash(idf.py size-components:*)" + "Bash(idf.py size-components:*)", + "Bash(find:*)", + "Bash(git log:*)" ], "deny": [] } diff --git a/main/gui.c b/main/gui.c index 2812ce0..ef6733f 100644 --- a/main/gui.c +++ b/main/gui.c @@ -75,6 +75,7 @@ static void bt_device_click_cb(lv_event_t * e); static void show_calibration_menu(void); static lv_obj_t* create_calibration_page(void); static void calibration_click_cb(lv_event_t * e); +static void update_label_scroll(lv_obj_t * btn, bool focused); // Menu stack management functions 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; tmpObj = addMenuItem(main_page, "Bluetooth"); 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, "Volume"); @@ -555,10 +557,16 @@ static void menuInc(int inc) } 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_clear_state(_menuContext.obj, LV_STATE_FOCUSED); 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.selected = search_index; } @@ -586,22 +594,35 @@ static void activate_selected(void) 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 static void label_scroll_focus_cb(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(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) { - // Start scrolling when focused - lv_label_set_long_mode(lbl, LV_LABEL_LONG_SCROLL_CIRCULAR); + update_label_scroll(btn, true); } else if (code == LV_EVENT_DEFOCUSED) { - // Stop scrolling and reset position when defocused - lv_label_set_long_mode(lbl, LV_LABEL_LONG_CLIP); + update_label_scroll(btn, false); } } @@ -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_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_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 - // Add focus event handler to control scrolling - 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_DEFOCUSED, NULL); + // 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_ALL, NULL); + ESP_LOGI(TAG, "Registered scroll callbacks for menu item: %s", text); // click callback 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) { 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 @@ -1485,6 +1508,7 @@ static lv_obj_t* create_calibration_page(void) { 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_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_add_event_cb(calibrate_btn, calibration_click_cb, LV_EVENT_CLICKED, NULL);