Files
tarrot/main/ui_main.c
2026-06-23 06:03:19 -07:00

216 lines
7.2 KiB
C

#include "ui_main.h"
#include <stdio.h>
#include "esp_log.h"
#include "lvgl.h"
#include "card_assets.h"
#include "settings.h"
#include "tarot_logic.h"
#include "ui_settings.h"
static const char *TAG = "ui_main";
static lv_style_t s_style_screen;
static lv_style_t s_style_title;
static lv_style_t s_style_button;
static lv_style_t s_style_card;
static lv_style_t s_style_muted;
static bool s_styles_ready;
static tarot_reading_t s_current_reading;
static void show_reading_cb(lv_event_t *event);
static void show_home_cb(lv_event_t *event);
static void show_settings_cb(lv_event_t *event);
static lv_obj_t *create_button(lv_obj_t *parent, const char *text, lv_event_cb_t cb)
{
lv_obj_t *button = lv_btn_create(parent);
lv_obj_add_style(button, &s_style_button, 0);
lv_obj_set_size(button, 210, 54);
lv_obj_add_event_cb(button, cb, LV_EVENT_CLICKED, NULL);
lv_obj_t *label = lv_label_create(button);
lv_label_set_text(label, text);
lv_obj_center(label);
return button;
}
void ui_apply_current_theme(void)
{
tarot_settings_t settings = settings_get();
lv_color_t bg = lv_color_hex(0x111018);
lv_color_t fg = lv_color_hex(0xf5efe6);
lv_color_t card = lv_color_hex(0x201827);
lv_color_t accent = lv_color_hex(0x8d5cf6);
if (settings.theme == TAROT_THEME_LIGHT) {
bg = lv_color_hex(0xf7f0e6);
fg = lv_color_hex(0x221b18);
card = lv_color_hex(0xffffff);
accent = lv_color_hex(0x805b2f);
} else if (settings.theme == TAROT_THEME_MYSTIC) {
bg = lv_color_hex(0x080b19);
fg = lv_color_hex(0xf1e8ff);
card = lv_color_hex(0x151b36);
accent = lv_color_hex(0xc39bff);
}
if (!s_styles_ready) {
lv_style_init(&s_style_screen);
lv_style_init(&s_style_title);
lv_style_init(&s_style_button);
lv_style_init(&s_style_card);
lv_style_init(&s_style_muted);
s_styles_ready = true;
}
lv_style_reset(&s_style_screen);
lv_style_set_bg_color(&s_style_screen, bg);
lv_style_set_text_color(&s_style_screen, fg);
lv_style_set_pad_all(&s_style_screen, 18);
lv_style_reset(&s_style_title);
lv_style_set_text_color(&s_style_title, fg);
lv_style_set_text_font(&s_style_title, LV_FONT_DEFAULT);
lv_style_reset(&s_style_button);
lv_style_set_bg_color(&s_style_button, accent);
lv_style_set_text_color(&s_style_button, lv_color_white());
lv_style_set_radius(&s_style_button, 8);
lv_style_reset(&s_style_card);
lv_style_set_bg_color(&s_style_card, card);
lv_style_set_text_color(&s_style_card, fg);
lv_style_set_radius(&s_style_card, 8);
lv_style_set_pad_all(&s_style_card, 10);
lv_style_set_border_width(&s_style_card, 1);
lv_style_set_border_color(&s_style_card, accent);
lv_style_reset(&s_style_muted);
lv_style_set_text_color(&s_style_muted, lv_color_hex(0xaaa2b8));
}
void ui_main_init(void)
{
ui_apply_current_theme();
}
void ui_show_home(void)
{
ui_apply_current_theme();
lv_obj_t *screen = lv_obj_create(NULL);
lv_obj_add_style(screen, &s_style_screen, 0);
lv_obj_set_flex_flow(screen, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(screen, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_t *title = lv_label_create(screen);
lv_obj_add_style(title, &s_style_title, 0);
lv_label_set_text(title, "ESP32-P4 Tarot");
lv_obj_set_style_text_font(title, LV_FONT_DEFAULT, 0);
lv_obj_t *subtitle = lv_label_create(screen);
lv_obj_add_style(subtitle, &s_style_muted, 0);
lv_label_set_text(subtitle, "On-device card art ready");
create_button(screen, "Draw Cards", show_reading_cb);
create_button(screen, "Settings", show_settings_cb);
lv_scr_load(screen);
}
static void add_card_tile(lv_obj_t *grid, const tarot_drawn_card_t *drawn, size_t index)
{
const tarot_card_t *card = drawn->card;
lv_obj_t *tile = lv_obj_create(grid);
lv_obj_add_style(tile, &s_style_card, 0);
lv_obj_set_size(tile, 230, 340);
lv_obj_set_flex_flow(tile, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(tile, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_t *position = lv_label_create(tile);
lv_label_set_text_fmt(position, "%u. %s", (unsigned)(index + 1), drawn->position_meaning);
lv_label_set_long_mode(position, LV_LABEL_LONG_WRAP);
lv_obj_set_width(position, 205);
card_assets_create_card_art(tile, card, drawn->reversed);
lv_obj_t *name = lv_label_create(tile);
lv_label_set_text(name, card->name);
lv_label_set_long_mode(name, LV_LABEL_LONG_WRAP);
lv_obj_set_width(name, 205);
lv_obj_t *orientation = lv_label_create(tile);
lv_obj_add_style(orientation, &s_style_muted, 0);
lv_label_set_text(orientation, drawn->reversed ? "Reversed" : "Upright");
lv_obj_t *meaning = lv_label_create(tile);
lv_label_set_text(meaning, drawn->reversed ? card->reversed_meaning : card->upright_meaning);
lv_label_set_long_mode(meaning, LV_LABEL_LONG_WRAP);
lv_obj_set_width(meaning, 205);
}
void ui_show_reading(void)
{
tarot_settings_t settings = settings_get();
tarot_logic_draw_reading(&s_current_reading, settings.selected_spread, settings.reversed_cards_enabled);
ESP_LOGI(TAG, "Drew %u unique tarot cards", (unsigned)s_current_reading.count);
lv_obj_t *screen = lv_obj_create(NULL);
lv_obj_add_style(screen, &s_style_screen, 0);
lv_obj_set_flex_flow(screen, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(screen, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_t *header = lv_obj_create(screen);
lv_obj_set_width(header, LV_PCT(100));
lv_obj_set_height(header, LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(header, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(header, 0, 0);
lv_obj_set_flex_flow(header, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(header, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_t *title = lv_label_create(header);
lv_label_set_text_fmt(title, "%s Reading", tarot_spread_name(s_current_reading.spread));
lv_obj_t *actions = lv_obj_create(header);
lv_obj_set_style_bg_opa(actions, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(actions, 0, 0);
lv_obj_set_size(actions, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_flex_flow(actions, LV_FLEX_FLOW_ROW);
create_button(actions, "New Reading", show_reading_cb);
create_button(actions, "Back Home", show_home_cb);
lv_obj_t *grid = lv_obj_create(screen);
lv_obj_set_width(grid, LV_PCT(100));
lv_obj_set_flex_grow(grid, 1);
lv_obj_set_style_bg_opa(grid, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(grid, 0, 0);
lv_obj_set_flex_flow(grid, LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(grid, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
for (size_t i = 0; i < s_current_reading.count; i++) {
add_card_tile(grid, &s_current_reading.cards[i], i);
}
lv_scr_load(screen);
}
static void show_reading_cb(lv_event_t *event)
{
(void)event;
ui_show_reading();
}
static void show_home_cb(lv_event_t *event)
{
(void)event;
ui_show_home();
}
static void show_settings_cb(lv_event_t *event)
{
(void)event;
ui_show_settings();
}