216 lines
7.2 KiB
C
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();
|
|
}
|