Login
1 branch 0 tags
Ben (Desktop/Arch) Games screen 51bdbfc 1 month ago 16 Commits
moon / firmware / src / screens / demo_screen.c
#include "demo_screen.h"
#include <stdlib.h>

// Wrapper for lv_bar_set_value to work with animations
static void bar_anim_cb(void *obj, int32_t value) {
    lv_bar_set_value(obj, value, LV_ANIM_OFF);
}

static void btn_event_cb(lv_event_t *e) {
    lv_event_code_t code = lv_event_get_code(e);
    if (code == LV_EVENT_CLICKED) {
        demo_screen_state_t *state = lv_event_get_user_data(e);
        state->click_count++;
        lv_label_set_text_fmt(state->status_label, "Clicks: %d", state->click_count);

        // Animate progress bar on click
        int32_t new_val = (state->click_count * 10) % 110;
        lv_anim_t a;
        lv_anim_init(&a);
        lv_anim_set_var(&a, state->progress_bar);
        lv_anim_set_values(&a, lv_bar_get_value(state->progress_bar), new_val);
        lv_anim_set_duration(&a, 300);
        lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)bar_anim_cb);
        lv_anim_start(&a);
    }
}

static void back_btn_event_cb(lv_event_t *e) {
    lv_event_code_t code = lv_event_get_code(e);
    if (code == LV_EVENT_CLICKED) {
        navigate_to(SCREEN_GAMES);
    }
}

static void cancel_event_cb(lv_event_t *e) {
    (void)e;
    navigate_to(SCREEN_GAMES);
}

ui_state_t setup_demo_screen(void) {
    demo_screen_state_t *state = calloc(1, sizeof(demo_screen_state_t));

    // Create title label at top
    state->title_label = lv_label_create(lv_screen_active());
    lv_label_set_text(state->title_label, "音楽");
    lv_obj_align(state->title_label, LV_ALIGN_TOP_MID, 0, 6);

    // Create a small spinner in top-left corner
    state->spinner = lv_spinner_create(lv_screen_active());
    lv_obj_set_size(state->spinner, 16, 16);
    lv_obj_align(state->spinner, LV_ALIGN_TOP_LEFT, 6, 6);
    lv_spinner_set_anim_params(state->spinner, 1400, 200);

    // Create status label (with CJK test)
    state->status_label = lv_label_create(lv_screen_active());
    lv_label_set_text(state->status_label, "Onigiri is Ready");
    lv_obj_align(state->status_label, LV_ALIGN_CENTER, 0, -15);

    // Create animated progress bar
    state->progress_bar = lv_bar_create(lv_screen_active());
    lv_obj_set_size(state->progress_bar, 144, 8);
    lv_obj_align(state->progress_bar, LV_ALIGN_CENTER, 0, 10);
    lv_bar_set_value(state->progress_bar, 30, LV_ANIM_OFF);

    // Create test button (left side)
    state->test_btn = lv_button_create(lv_screen_active());
    lv_obj_align(state->test_btn, LV_ALIGN_BOTTOM_LEFT, 8, -8);
    lv_obj_add_event_cb(state->test_btn, btn_event_cb, LV_EVENT_CLICKED, state);
    lv_obj_set_size(state->test_btn, 68, 26);

    lv_obj_t *btn_label = lv_label_create(state->test_btn);
    lv_label_set_text(btn_label, "Test");
    lv_obj_center(btn_label);

    // Create back button (right side) with secondary color
    state->back_btn = lv_button_create(lv_screen_active());
    lv_obj_align(state->back_btn, LV_ALIGN_BOTTOM_RIGHT, -8, -8);
    lv_obj_add_event_cb(state->back_btn, back_btn_event_cb, LV_EVENT_CLICKED, NULL);
    lv_obj_set_size(state->back_btn, 68, 26);
    lv_obj_set_style_bg_color(state->back_btn, lv_color_hex(0x0288D1), 0);

    lv_obj_t *back_label = lv_label_create(state->back_btn);
    lv_label_set_text(back_label, "Back");
    lv_obj_center(back_label);

    // Add buttons to default group for keyboard navigation
    lv_group_add_obj(lv_group_get_default(), state->test_btn);
    lv_group_add_obj(lv_group_get_default(), state->back_btn);

    // Handle ESC/back key on both buttons to return to home
    lv_obj_add_event_cb(state->test_btn, cancel_event_cb, LV_EVENT_CANCEL, NULL);
    lv_obj_add_event_cb(state->back_btn, cancel_event_cb, LV_EVENT_CANCEL, NULL);

    // Focus first button to enable navigation
    lv_group_focus_obj(state->test_btn);

    return (ui_state_t){.type = SCREEN_DEMO, .demo = state};
}

void free_demo_screen(demo_screen_state_t *state) {
    if (!state) return;

    // Remove from group before deleting
    lv_group_remove_obj(state->test_btn);
    lv_group_remove_obj(state->back_btn);

    // Delete all widgets (children are deleted automatically)
    lv_obj_delete(state->title_label);
    lv_obj_delete(state->spinner);
    lv_obj_delete(state->status_label);
    lv_obj_delete(state->progress_bar);
    lv_obj_delete(state->test_btn);
    lv_obj_delete(state->back_btn);

    free(state);
}

void update_demo_screen(demo_screen_state_t *state) {
    (void)state;  // LVGL handles updates via timer
}