- 将UI相关的代码从display_module.c中提取到新的display_ui.c文件 - 创建display_ui.h头文件定义UI模型和接口函数 - 在CMakeLists.txt中添加UI目录包含路径和源文件引用 - 修改display_module.c中的UI相关数据结构和函数调用 - 将UI创建和刷新逻辑替换为对新UI模块的调用 - 优化了时间日期文本的更新机制,提高性能 - 移除了原有的内部UI实现代码,保持模块职责清晰
307 lines
9.2 KiB
C
307 lines
9.2 KiB
C
#include <string.h>
|
|
|
|
#include <lvgl.h>
|
|
#include <zephyr/sys/printk.h>
|
|
|
|
#include "battery_status_event.h"
|
|
#include "display_ui.h"
|
|
#include "keyboard_led_event.h"
|
|
|
|
#define DISPLAY_SYMBOL_PLUG "\xEF\x87\xA6"
|
|
|
|
LV_FONT_DECLARE(ui_font_keyboard_small_18);
|
|
LV_FONT_DECLARE(ui_font_keyboard_time_48);
|
|
|
|
enum display_status_id
|
|
{
|
|
DISPLAY_STATUS_USB = 0,
|
|
DISPLAY_STATUS_BLE,
|
|
DISPLAY_STATUS_NUMLOCK,
|
|
DISPLAY_STATUS_CAPSLOCK,
|
|
DISPLAY_STATUS_COUNT,
|
|
};
|
|
|
|
struct display_ui_ctx
|
|
{
|
|
lv_obj_t *status_badges[DISPLAY_STATUS_COUNT];
|
|
lv_obj_t *status_labels[DISPLAY_STATUS_COUNT];
|
|
lv_obj_t *battery_icon;
|
|
lv_obj_t *battery_label;
|
|
lv_obj_t *battery_state_label;
|
|
lv_obj_t *date_label;
|
|
lv_obj_t *time_label;
|
|
};
|
|
|
|
static struct display_ui_ctx g_display_ui;
|
|
|
|
static const char *const g_status_texts[DISPLAY_STATUS_COUNT] = {
|
|
LV_SYMBOL_USB,
|
|
LV_SYMBOL_BLUETOOTH,
|
|
"1",
|
|
"A",
|
|
};
|
|
|
|
static lv_color_t display_ui_get_battery_color(uint8_t battery_level)
|
|
{
|
|
if (battery_level > 70U) {
|
|
return lv_color_hex(0x8BD450);
|
|
}
|
|
|
|
if (battery_level >= 20U) {
|
|
return lv_color_hex(0xF4D35E);
|
|
}
|
|
|
|
return lv_color_hex(0xE63946);
|
|
}
|
|
|
|
static const char *display_ui_get_battery_symbol(uint8_t battery_level)
|
|
{
|
|
if (battery_level > 85U) {
|
|
return LV_SYMBOL_BATTERY_FULL;
|
|
}
|
|
|
|
if (battery_level > 60U) {
|
|
return LV_SYMBOL_BATTERY_3;
|
|
}
|
|
|
|
if (battery_level > 35U) {
|
|
return LV_SYMBOL_BATTERY_2;
|
|
}
|
|
|
|
if (battery_level >= 20U) {
|
|
return LV_SYMBOL_BATTERY_1;
|
|
}
|
|
|
|
return LV_SYMBOL_BATTERY_EMPTY;
|
|
}
|
|
|
|
static bool display_ui_status_is_active(enum display_status_id id,
|
|
const struct display_ui_model *model)
|
|
{
|
|
switch (id) {
|
|
case DISPLAY_STATUS_USB:
|
|
return model->mode == MODE_TYPE_USB;
|
|
|
|
case DISPLAY_STATUS_BLE:
|
|
return model->mode == MODE_TYPE_BLE;
|
|
|
|
case DISPLAY_STATUS_NUMLOCK:
|
|
return (model->led_mask & KEYBOARD_LED_MASK_NUM_LOCK) != 0U;
|
|
|
|
case DISPLAY_STATUS_CAPSLOCK:
|
|
return (model->led_mask & KEYBOARD_LED_MASK_CAPS_LOCK) != 0U;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static void display_ui_create_status_chip(lv_obj_t *parent, enum display_status_id id)
|
|
{
|
|
lv_obj_t *badge = lv_obj_create(parent);
|
|
lv_obj_t *label;
|
|
|
|
lv_obj_remove_style_all(badge);
|
|
lv_obj_set_size(badge, 50, 32);
|
|
lv_obj_set_style_radius(badge, 10, 0);
|
|
lv_obj_set_style_bg_opa(badge, LV_OPA_COVER, 0);
|
|
lv_obj_set_style_pad_all(badge, 0, 0);
|
|
|
|
label = lv_label_create(badge);
|
|
lv_label_set_text(label, g_status_texts[id]);
|
|
lv_obj_set_width(label, LV_PCT(100));
|
|
lv_obj_set_style_text_font(label, &ui_font_keyboard_small_18, 0);
|
|
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0);
|
|
lv_obj_center(label);
|
|
|
|
g_display_ui.status_badges[id] = badge;
|
|
g_display_ui.status_labels[id] = label;
|
|
}
|
|
|
|
void display_ui_refresh_status_bar(const struct display_ui_model *model)
|
|
{
|
|
for (uint32_t i = 0; i < DISPLAY_STATUS_COUNT; i++) {
|
|
lv_obj_t *badge = g_display_ui.status_badges[i];
|
|
lv_obj_t *label = g_display_ui.status_labels[i];
|
|
bool active = display_ui_status_is_active((enum display_status_id)i, model);
|
|
|
|
if (!badge || !label) {
|
|
continue;
|
|
}
|
|
|
|
lv_obj_set_style_border_width(badge, 4, 0);
|
|
lv_obj_set_style_border_color(badge,
|
|
active ? model->theme_color :
|
|
model->inactive_border_color,
|
|
0);
|
|
lv_obj_set_style_bg_color(badge,
|
|
active ? lv_color_hex(0x1D2735) :
|
|
lv_color_hex(0x161A20),
|
|
0);
|
|
lv_obj_set_style_text_color(label,
|
|
active ? lv_color_white() :
|
|
lv_color_hex(0x7C8798),
|
|
0);
|
|
}
|
|
}
|
|
|
|
void display_ui_refresh_battery(const struct display_ui_model *model)
|
|
{
|
|
char battery_text[8];
|
|
lv_color_t battery_color;
|
|
const char *state_symbol = "";
|
|
lv_color_t state_color = lv_color_white();
|
|
|
|
if (!g_display_ui.battery_icon ||
|
|
!g_display_ui.battery_label ||
|
|
!g_display_ui.battery_state_label) {
|
|
return;
|
|
}
|
|
|
|
battery_color = display_ui_get_battery_color(model->battery_level);
|
|
snprintk(battery_text, sizeof(battery_text), "%u%%", model->battery_level);
|
|
|
|
if ((model->battery_flags & BATTERY_STATUS_FLAG_FULL) != 0U) {
|
|
state_symbol = DISPLAY_SYMBOL_PLUG;
|
|
state_color = lv_color_hex(0x4C9EF5);
|
|
} else if ((model->battery_flags & BATTERY_STATUS_FLAG_CHARGING) != 0U) {
|
|
state_symbol = LV_SYMBOL_CHARGE;
|
|
state_color = lv_color_hex(0xF4D35E);
|
|
}
|
|
|
|
lv_label_set_text(g_display_ui.battery_icon,
|
|
display_ui_get_battery_symbol(model->battery_level));
|
|
lv_obj_set_style_text_color(g_display_ui.battery_icon, battery_color, 0);
|
|
lv_label_set_text(g_display_ui.battery_label, battery_text);
|
|
lv_label_set_text(g_display_ui.battery_state_label, state_symbol);
|
|
lv_obj_set_style_text_color(g_display_ui.battery_state_label, state_color, 0);
|
|
}
|
|
|
|
void display_ui_refresh_datetime(const char *date_text, const char *time_text)
|
|
{
|
|
if (!g_display_ui.date_label || !g_display_ui.time_label) {
|
|
return;
|
|
}
|
|
|
|
lv_label_set_text(g_display_ui.date_label, date_text);
|
|
lv_label_set_text(g_display_ui.time_label, time_text);
|
|
}
|
|
|
|
void display_ui_refresh_all(const struct display_ui_model *model,
|
|
const char *date_text,
|
|
const char *time_text)
|
|
{
|
|
display_ui_refresh_status_bar(model);
|
|
display_ui_refresh_battery(model);
|
|
display_ui_refresh_datetime(date_text, time_text);
|
|
}
|
|
|
|
void display_ui_init(const struct display_ui_model *model,
|
|
const char *date_text,
|
|
const char *time_text)
|
|
{
|
|
lv_obj_t *screen = lv_screen_active();
|
|
lv_obj_t *content;
|
|
lv_obj_t *top_row;
|
|
lv_obj_t *battery_wrap;
|
|
lv_obj_t *middle_row;
|
|
lv_obj_t *bottom_row;
|
|
|
|
memset(&g_display_ui, 0, sizeof(g_display_ui));
|
|
|
|
lv_obj_clean(screen);
|
|
lv_obj_set_style_bg_color(screen, lv_color_hex(0x0F1115), 0);
|
|
lv_obj_set_style_bg_grad_color(screen, lv_color_hex(0x1A1F29), 0);
|
|
lv_obj_set_style_bg_grad_dir(screen, LV_GRAD_DIR_VER, 0);
|
|
lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, 0);
|
|
lv_obj_set_style_text_color(screen, lv_color_white(), 0);
|
|
lv_obj_set_style_pad_all(screen, 0, 0);
|
|
lv_obj_set_scrollbar_mode(screen, LV_SCROLLBAR_MODE_OFF);
|
|
|
|
content = lv_obj_create(screen);
|
|
lv_obj_remove_style_all(content);
|
|
lv_obj_set_size(content, LV_PCT(100), LV_PCT(100));
|
|
lv_obj_set_style_bg_color(content, lv_color_hex(0x0F1115), 0);
|
|
lv_obj_set_style_bg_opa(content, LV_OPA_TRANSP, 0);
|
|
lv_obj_set_style_pad_left(content, 14, 0);
|
|
lv_obj_set_style_pad_right(content, 14, 0);
|
|
lv_obj_set_style_pad_top(content, 8, 0);
|
|
lv_obj_set_style_pad_bottom(content, 8, 0);
|
|
lv_obj_set_layout(content, LV_LAYOUT_FLEX);
|
|
lv_obj_set_flex_flow(content, LV_FLEX_FLOW_COLUMN);
|
|
lv_obj_set_flex_align(content,
|
|
LV_FLEX_ALIGN_START,
|
|
LV_FLEX_ALIGN_CENTER,
|
|
LV_FLEX_ALIGN_CENTER);
|
|
|
|
top_row = lv_obj_create(content);
|
|
lv_obj_remove_style_all(top_row);
|
|
lv_obj_set_width(top_row, LV_PCT(100));
|
|
lv_obj_set_flex_grow(top_row, 1);
|
|
lv_obj_set_style_bg_color(top_row, lv_color_hex(0x0F1115), 0);
|
|
lv_obj_set_style_bg_opa(top_row, LV_OPA_TRANSP, 0);
|
|
lv_obj_set_layout(top_row, LV_LAYOUT_FLEX);
|
|
lv_obj_set_flex_flow(top_row, LV_FLEX_FLOW_ROW);
|
|
lv_obj_set_flex_align(top_row,
|
|
LV_FLEX_ALIGN_SPACE_BETWEEN,
|
|
LV_FLEX_ALIGN_CENTER,
|
|
LV_FLEX_ALIGN_CENTER);
|
|
|
|
g_display_ui.date_label = lv_label_create(top_row);
|
|
lv_obj_set_style_text_font(g_display_ui.date_label, &ui_font_keyboard_small_18, 0);
|
|
lv_obj_set_style_text_color(g_display_ui.date_label, lv_color_hex(0xD8DEE9), 0);
|
|
|
|
battery_wrap = lv_obj_create(top_row);
|
|
lv_obj_remove_style_all(battery_wrap);
|
|
lv_obj_set_width(battery_wrap, LV_SIZE_CONTENT);
|
|
lv_obj_set_layout(battery_wrap, LV_LAYOUT_FLEX);
|
|
lv_obj_set_flex_flow(battery_wrap, LV_FLEX_FLOW_ROW);
|
|
lv_obj_set_flex_align(battery_wrap,
|
|
LV_FLEX_ALIGN_CENTER,
|
|
LV_FLEX_ALIGN_CENTER,
|
|
LV_FLEX_ALIGN_CENTER);
|
|
lv_obj_set_style_pad_column(battery_wrap, 4, 0);
|
|
|
|
g_display_ui.battery_icon = lv_label_create(battery_wrap);
|
|
lv_obj_set_style_text_font(g_display_ui.battery_icon, &ui_font_keyboard_small_18, 0);
|
|
|
|
g_display_ui.battery_label = lv_label_create(battery_wrap);
|
|
lv_obj_set_style_text_font(g_display_ui.battery_label, &ui_font_keyboard_small_18, 0);
|
|
lv_obj_set_style_text_color(g_display_ui.battery_label, lv_color_hex(0xD8DEE9), 0);
|
|
|
|
g_display_ui.battery_state_label = lv_label_create(battery_wrap);
|
|
lv_obj_set_style_text_font(g_display_ui.battery_state_label, &ui_font_keyboard_small_18, 0);
|
|
|
|
middle_row = lv_obj_create(content);
|
|
lv_obj_remove_style_all(middle_row);
|
|
lv_obj_set_width(middle_row, LV_PCT(100));
|
|
lv_obj_set_flex_grow(middle_row, 2);
|
|
lv_obj_set_style_bg_color(middle_row, lv_color_hex(0x0F1115), 0);
|
|
lv_obj_set_style_bg_opa(middle_row, LV_OPA_TRANSP, 0);
|
|
|
|
g_display_ui.time_label = lv_label_create(middle_row);
|
|
lv_obj_set_style_text_font(g_display_ui.time_label, &ui_font_keyboard_time_48, 0);
|
|
lv_obj_set_style_text_color(g_display_ui.time_label, lv_color_white(), 0);
|
|
lv_obj_center(g_display_ui.time_label);
|
|
|
|
bottom_row = lv_obj_create(content);
|
|
lv_obj_remove_style_all(bottom_row);
|
|
lv_obj_set_width(bottom_row, LV_PCT(100));
|
|
lv_obj_set_flex_grow(bottom_row, 1);
|
|
lv_obj_set_style_bg_color(bottom_row, lv_color_hex(0x0F1115), 0);
|
|
lv_obj_set_style_bg_opa(bottom_row, LV_OPA_TRANSP, 0);
|
|
lv_obj_set_layout(bottom_row, LV_LAYOUT_FLEX);
|
|
lv_obj_set_flex_flow(bottom_row, LV_FLEX_FLOW_ROW);
|
|
lv_obj_set_flex_align(bottom_row,
|
|
LV_FLEX_ALIGN_CENTER,
|
|
LV_FLEX_ALIGN_CENTER,
|
|
LV_FLEX_ALIGN_CENTER);
|
|
lv_obj_set_style_pad_column(bottom_row, 6, 0);
|
|
|
|
for (uint32_t i = 0; i < DISPLAY_STATUS_COUNT; i++) {
|
|
display_ui_create_status_chip(bottom_row, (enum display_status_id)i);
|
|
}
|
|
|
|
display_ui_refresh_all(model, date_text, time_text);
|
|
}
|