增加两页UI

This commit is contained in:
2026-09-09 13:18:06 +08:00
parent 9ead5679a1
commit 24c2f57555
24 changed files with 1436 additions and 122 deletions
+497
View File
@@ -0,0 +1,497 @@
/*
* 模块名称:UI Content Page (内容页面显示层)
* 模块功能:菜单叶子节点的内容页(装置信息/交流量/直流量)——独立 LVGL 屏幕,
* 全屏容器 DRAW_MAIN 自绘全部内容(浅 V 装饰 + 居中标题 + 行数据 +
* 页脚页码),无子对象;进入时切屏并获焦、ESC 返回菜单屏并还原焦点
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
* 作者:王建锋
* 创建日期:2026-09-09
* 修改记录:
* 2026-09-09 王建锋 创建:装置信息/交流量/直流量三页(参考图 10/20/21 实测几何)
*/
/* 头文件包含区 */
#include <string.h>
#include "ui_content_page.h"
#include "ui_menu_view.h"
#include "lvgl.h"
#define DBG_TAG "[UI_CONTENT_PAGE]"
#include "dbg_log.h"
/* 私有宏定义区 */
/*
* 布局常量(设备像素;参考图 10/20/21 实测,3x 放大图缩回 160x160 测量):
* 标题 y=2(CJK 字形顶距 +1 → 墨迹自 y=3 起,与参考图一致)、页脚 y=143;
* 信息页行:首行 y=40、行距 15、标签列 x=6 / 值列 x=86(无选中带);
* 列表页行:槽顶 = 24+14i、选中白带 x=2..156 高 13、名 x=7 / 值 x=101;
* 字形顶距(CJK +1 / ASCII +2)已计入放置 y,墨迹与参考图对齐
*/
#define CP_SCREEN_W 160 /* 屏幕宽(px,与 ui_port.h / 模拟器一致) */
#define CP_SCREEN_H 160 /* 屏幕高(px) */
#define CP_TITLE_Y 2 /* 标题放置 y(居中;墨迹自 y=3 起) */
#define CP_PAGE_LINE_Y 143 /* 页脚"第 X 页,共 Y 页"放置 y(x=6 左对齐) */
#define CP_DECO_LEG_W 3 /* "浅 V"两腿线宽(与菜单根框一致:1bpp 斜线须加粗) */
#define CP_DECO_HORIZ_W 2 /* "浅 V"水平线宽 */
/* 私有类型定义区 */
/* 行数据:左列名 + 右列值(Flash 字面量,不 strdup) */
typedef struct {
const char *name;
const char *value;
} cp_row_t;
/*
* 页面定义(Flash 常量表):标题/行几何/数据表/页脚参数;
* selectable=1 为可移选分页的数据列表页,0 为静态信息页
*/
typedef struct {
const char *title; /* 标题(浅 V 区居中) */
uint8_t selectable; /* 1 = 数据列表页(↑↓移选/分页);0 = 信息页(静态行) */
int32_t top_y; /* 首行槽顶 y */
int32_t pitch; /* 行距(相邻行槽顶间距) */
int32_t band_h; /* 选中白带高(0 = 无选中带) */
int32_t text_dy; /* 文本放置相对行槽顶的垂直偏移 */
int32_t left_x; /* 左列 x(信息页=标签、列表页=名) */
int32_t right_x; /* 右列 x(值) */
uint8_t rows_per_page; /* 每页可见行数(0 = 不分页) */
uint16_t total_rows; /* 数据总行数 */
const cp_row_t *rows; /* 数据表(Flash) */
const char *subtitle; /* 副标题(居中;NULL = 无,仅信息页有) */
int32_t subtitle_y; /* 副标题放置 y(-1 = 无) */
uint8_t fixed_cur_page; /* 页脚"第 X 页"固定显示值(信息页按参考图原样) */
uint8_t fixed_total_pages; /* 页脚"共 Y 页"固定显示值 */
} cp_def_t;
/* 静态变量定义区 */
/* "浅 V"装饰点集与线宽:几何与菜单根框一致(ui_menu_view.c s_deco_*),culling 区同范围 */
static const lv_point_precise_t s_deco_leg_l[2] = { {7, 7}, {16, 17} }; /* 左腿 */
static const lv_point_precise_t s_deco_hoz[2] = { {16, 17}, {145, 17} }; /* 水平线:接两腿底端 */
static const lv_point_precise_t s_deco_leg_r[2] = { {158, 7}, {145, 17} }; /* 右腿 */
static const lv_point_precise_t *const s_deco_segs[3] = {s_deco_leg_l, s_deco_leg_r, s_deco_hoz};
static const int32_t s_deco_seg_w[3] = {CP_DECO_LEG_W, CP_DECO_LEG_W, CP_DECO_HORIZ_W};
static const lv_area_t s_deco_band = {0, 0, CP_SCREEN_W - 1, 19}; /* 浅 V culling 区 */
/* 装置信息行(参考图 10;标签含全角冒号,值列固定 x=86) */
static const cp_row_t s_info_rows[] = {
{"终端类型:", "F30"},
{"终端型号:", "F30"},
{"软件版本:", "SV0.010"},
{"硬件版本:", "HW0.010"},
{"软件校验:", "4454"},
{"程序日期:", "2024.08.27"},
};
/* 交流量行(参考图 20 = 第 1 页原样;第 2/3 页为占位数据,可替换) */
static const cp_row_t s_ac_rows[] = {
{"Ia1", "0.000"}, /* 第 1 页(参考图 20) */
{"Ib1", "0.137"},
{"Ic1", "0.274"},
{"Ia2", "0.411"},
{"Ib2", "0.548"},
{"Ic2", "0.685"},
{"Ua1", "0.82"},
{"Ub1", "0.96"},
{"Uc1", "1.03"}, /* 第 2 页(占位数据) */
{"Uab", "1.17"},
{"Ubc", "1.24"},
{"Uca", "1.31"},
{"Hz", "50.00"},
{"P", "1.42"},
{"Q", "0.87"},
{"S", "1.63"},
{"PF", "0.95"}, /* 第 3 页(占位数据) */
{"Iavg","0.35"},
{"Uavg","0.87"},
{"Fmax","50.02"},
{"Imax","1.24"},
{"Pmax","2.10"},
{"Qmax","1.05"},
{"Smax","2.45"},
};
/* 直流量行(参考图 21) */
static const cp_row_t s_dc_rows[] = {
{"ZL01", "3.01"},
{"ZL02", "3.15"},
{"Pa1", "3.288"},
};
/* 页面定义表(顺序与 content_page_id_t 一致) */
static const cp_def_t s_defs[CONTENT_PAGE_COUNT] = {
/* 装置信息:静态键值行 + 副标题;页脚按参考图原样"第 10 页,共 1 页" */
{"装置信息", 0u, 40, 15, 0, 0, 6, 86, 0u, (uint16_t)6, s_info_rows,
"馈线自动化终端", 25, 10u, 1u},
/* 交流量:24 项 / 8 项每页(3 页);text_dy=0:ASCII 字形顶距 +2,墨迹落槽顶+2(与参考图一致) */
{"交流量", 1u, 24, 14, 13, 0, 7, 101, 8u, (uint16_t)24, s_ac_rows,
NULL, -1, 0u, 0u},
/* 直流量:3 项单页 */
{"直流量", 1u, 24, 14, 13, 0, 7, 101, 8u, (uint16_t)3, s_dc_rows,
NULL, -1, 0u, 0u},
};
static content_page_id_t s_open = CONTENT_PAGE_COUNT; /* 当前打开的页(COUNT = 未打开) */
static uint16_t s_sel; /* 列表页选中行(全局下标,跨页连续) */
static lv_obj_t *s_scr; /* 页面屏幕(进入时建、返回时毁) */
static lv_obj_t *s_cont; /* 页面全屏容器(焦点/键入口 + 自绘载体) */
/* flat:透明、无边框/圆角/内边距——剥离 mono 主题给普通 lv_obj 附加的 card 样式(同 ui_menu_view.c) */
/* 用常量样式(LV_STYLE_CONST_INIT):属性存静态数组,零 LV_MEM 池分配;
* 动态样式首次 set_prop 会从池分配 values_and_props 且永不释放(x64 实测 88B/个) */
static const lv_style_const_prop_t cp_flat_props[] = {
{ .prop = LV_STYLE_BG_OPA, .value = { .num = LV_OPA_TRANSP } },
{ .prop = LV_STYLE_BORDER_WIDTH, .value = { .num = 0 } },
{ .prop = LV_STYLE_RADIUS, .value = { .num = 0 } },
{ .prop = LV_STYLE_PAD_LEFT, .value = { .num = 0 } },
{ .prop = LV_STYLE_PAD_RIGHT, .value = { .num = 0 } },
{ .prop = LV_STYLE_PAD_TOP, .value = { .num = 0 } },
{ .prop = LV_STYLE_PAD_BOTTOM, .value = { .num = 0 } },
{ .prop = LV_STYLE_PAD_ROW, .value = { .num = 0 } },
{ .prop = LV_STYLE_PAD_COLUMN, .value = { .num = 0 } },
LV_STYLE_CONST_PROPS_END
};
LV_STYLE_CONST_INIT(cp_style_flat, cp_flat_props);
/* 函数定义区 */
/*
* 函数功能:判断两区域是否相交(等价 lv_area_intersect 非空判断;避免依赖 LVGL 私有头)
* 入口参数:a - 区域 1 const lv_area_t *
* b - 区域 2 const lv_area_t *
* 返回值:true - 相交;false - 不相交
* 限定条件:无
* 函数说明:四边取 min/max 成交集,任一边为空即不相交(与 ui_menu_view.c 同实现)
*/
static bool cp_areas_intersect(const lv_area_t *a, const lv_area_t *b) {
int32_t x1 = (a->x1 > b->x1) ? a->x1 : b->x1;
int32_t y1 = (a->y1 > b->y1) ? a->y1 : b->y1;
int32_t x2 = (a->x2 < b->x2) ? a->x2 : b->x2;
int32_t y2 = (a->y2 < b->y2) ? a->y2 : b->y2;
return (x1 <= x2 && y1 <= y2);
}
/*
* 函数功能:绘制居中单行文本(标题/副标题)
* 入口参数:layer - 绘制层 lv_layer_t *
* text - 文本(Flash) const char *
* y - 放置 y int32_t
* 返回值:无
* 限定条件:text 非空;重绘区已含该行区域(调用方 culling)
* 函数说明:x = (屏宽 - 文本实际步进)/2 居中;白色、静态字符串不拷内存
*/
static void cp_draw_centered_text(lv_layer_t *layer, const char *text, int32_t y) {
lv_area_t area;
lv_draw_label_dsc_t ld;
area.x1 = 0;
area.x2 = CP_SCREEN_W - 1;
area.y1 = y;
area.y2 = y + 15; /* 覆盖字体行高(13)+ 余量 */
lv_draw_label_dsc_init(&ld);
ld.base.layer = layer;
ld.text = text;
ld.text_static = 1; /* Flash 字符串:不拷内存 */
ld.color = lv_color_white();
/* 本 LVGL 版 lv_text_get_width 的 length=0 表示"不测量",必须传 strlen */
ld.ofs_x = (CP_SCREEN_W - lv_text_get_width(text, (uint32_t)strlen(text), LV_FONT_DEFAULT, 0)) / 2;
ld.ofs_y = 0;
lv_draw_label(layer, &ld, &area);
}
/*
* 函数功能:页面自绘(浅 V 装饰 + 标题/副标题 + 行数据 + 页脚页码)
* 入口参数:e - 事件指针 lv_event_t *
* 返回值:无
* 限定条件:事件为 LV_EVENT_DRAW_MAIN,页面已打开
* 函数说明: 1. 浅 V 装饰几何与菜单根框一致(3 段线逐段画)
* 2. 列表页窗口 = 选中行所在页(首可见行 = (sel/每页数)*每页数),
* 行槽位置固定、数据随页切换;信息页全量静态绘制
* 3. 选中行整行白带(x=2..156)+ 黑字,非选中白字
* 4. 各区块按 culling 区跳过不在重绘区的部分
*/
static void cp_draw_cb(lv_event_t *e) {
const cp_def_t *d = &s_defs[s_open];
lv_layer_t *layer = lv_event_get_layer(e);
/* "浅 V"装饰:3 段线(与菜单根框同几何) */
if (cp_areas_intersect(&s_deco_band, &layer->_clip_area)) {
for (uint8_t i = 0; i < 3; i++) {
lv_draw_line_dsc_t ld;
lv_draw_line_dsc_init(&ld);
ld.base.layer = layer;
ld.color = lv_color_white();
ld.width = s_deco_seg_w[i];
ld.p1 = s_deco_segs[i][0];
ld.p2 = s_deco_segs[i][1];
lv_draw_line(layer, &ld);
}
}
/* 标题(居中) */
{
lv_area_t t;
t.x1 = 0;
t.x2 = CP_SCREEN_W - 1;
t.y1 = CP_TITLE_Y;
t.y2 = CP_TITLE_Y + 15;
if (cp_areas_intersect(&t, &layer->_clip_area)) {
cp_draw_centered_text(layer, d->title, CP_TITLE_Y);
}
}
/* 副标题(仅信息页) */
if (d->subtitle != NULL) {
lv_area_t t;
t.x1 = 0;
t.x2 = CP_SCREEN_W - 1;
t.y1 = d->subtitle_y;
t.y2 = d->subtitle_y + 15;
if (cp_areas_intersect(&t, &layer->_clip_area)) {
cp_draw_centered_text(layer, d->subtitle, d->subtitle_y);
}
}
/* 行数据:列表页窗口跟随选中行所在页,信息页全量 */
int32_t first = 0;
int32_t cnt = (int32_t)d->total_rows;
if (d->selectable && d->rows_per_page > 0u) {
first = (int32_t)(s_sel / d->rows_per_page) * d->rows_per_page; /* 窗口顶行 */
cnt = (int32_t)d->total_rows - first;
if (cnt > (int32_t)d->rows_per_page) {
cnt = (int32_t)d->rows_per_page; /* 末页不足整页时截断 */
}
}
for (int32_t i = 0; i < cnt; i++) {
int32_t row_idx = first + i; /* 数据下标(跨页连续) */
int32_t slot_y = d->top_y + i * d->pitch; /* 行槽顶(窗口内位置固定) */
bool is_sel = (d->selectable != 0u) && (row_idx == (int32_t)s_sel);
lv_color_t color = is_sel ? lv_color_black() : lv_color_white();
lv_area_t strip;
/* 行条带(整宽)不在重绘区:跳过(culling) */
strip.x1 = 0;
strip.x2 = CP_SCREEN_W - 1;
strip.y1 = slot_y;
strip.y2 = slot_y + d->pitch - 1;
if (!cp_areas_intersect(&strip, &layer->_clip_area)) {
continue;
}
/* 选中行:整行白带(x=2..156,高 band_h) */
if (is_sel && d->band_h > 0) {
lv_draw_rect_dsc_t fd;
lv_area_t band;
band.x1 = 2;
band.x2 = CP_SCREEN_W - 3; /* x=156(与参考图实测一致) */
band.y1 = slot_y;
band.y2 = slot_y + d->band_h - 1;
lv_draw_rect_dsc_init(&fd);
fd.base.layer = layer;
fd.bg_color = lv_color_white();
fd.bg_opa = LV_OPA_COVER;
lv_draw_rect(layer, &fd, &band);
}
/* 左列(标签/名)与右列(值):固定列 x,垂直偏移 text_dy */
{
lv_draw_label_dsc_t ld;
/* ofs_x/ofs_y 相对 coords 原点(strip.y1=slot_y),勿再叠加 slot_y */
lv_draw_label_dsc_init(&ld);
ld.base.layer = layer;
ld.text = d->rows[row_idx].name;
ld.text_static = 1; /* Flash 字符串:不拷内存 */
ld.color = color; /* 选中黑 / 非选中白 */
ld.ofs_x = d->left_x;
ld.ofs_y = d->text_dy;
lv_draw_label(layer, &ld, &strip);
lv_draw_label_dsc_init(&ld);
ld.base.layer = layer;
ld.text = d->rows[row_idx].value;
ld.text_static = 1;
ld.color = color;
ld.ofs_x = d->right_x;
ld.ofs_y = d->text_dy;
lv_draw_label(layer, &ld, &strip);
}
}
/* 页脚"第 X 页,共 Y 页":列表页随选中行现算,信息页按参考图固定值 */
{
char buf[32];
uint8_t cur;
uint8_t total;
lv_area_t t;
if (d->selectable) {
cur = (uint8_t)(s_sel / d->rows_per_page + 1u);
total = (uint8_t)((d->total_rows + d->rows_per_page - 1u) / d->rows_per_page);
}
else {
cur = d->fixed_cur_page;
total = d->fixed_total_pages;
}
t.x1 = 0;
t.x2 = CP_SCREEN_W - 1;
t.y1 = CP_PAGE_LINE_Y;
t.y2 = CP_PAGE_LINE_Y + 15;
if (cp_areas_intersect(&t, &layer->_clip_area)) {
/* lv_snprintf 而非 snprintf:MSVC 对 printf 族做格式串扫描,中文字面量会误报 C4819 */
lv_snprintf(buf, sizeof(buf), "第 %u 页,共 %u 页", (unsigned)cur, (unsigned)total);
lv_draw_label_dsc_t ld;
/* ofs 相对 coords 原点(t.y1=CP_PAGE_LINE_Y),垂直偏移取 0 */
lv_draw_label_dsc_init(&ld);
ld.base.layer = layer;
ld.text = buf; /* 栈缓冲:本页码每次现算 */
ld.color = lv_color_white();
ld.ofs_x = 6;
ld.ofs_y = 0;
lv_draw_label(layer, &ld, &t);
}
}
}
/*
* 函数功能:页面按键事件入口(↑↓移选 / ESC·←返回)
* 入口参数:e - 事件指针 lv_event_t *
* 返回值:无
* 限定条件:容器已加入默认输入组并获焦
* 函数说明:1. ↑/↓:列表页移选(首尾环绕,跨页连续),窗口随页切换后重绘;信息页不响应
* 2. ESC/←:关闭页面返回菜单(导航状态未压层,原样还原)
*/
static void cp_key_cb(lv_event_t *e) {
const cp_def_t *d = &s_defs[s_open];
lv_key_t key = (lv_key_t)lv_event_get_key(e);
switch (key) {
case LV_KEY_UP:
if (d->selectable && d->total_rows > 0u) {
/* 上移、首尾环绕:先加 total 再减 1 保证无符号下不为负 */
s_sel = (uint16_t)((s_sel + d->total_rows - 1u) % d->total_rows);
lv_obj_invalidate(s_cont); /* 重绘(选中带/窗口/页码可能变化) */
}
break;
case LV_KEY_DOWN:
if (d->selectable && d->total_rows > 0u) {
s_sel = (uint16_t)((s_sel + 1u) % d->total_rows); /* 下移、越尾绕回首行 */
lv_obj_invalidate(s_cont);
}
break;
case LV_KEY_ESC:
case LV_KEY_LEFT:
ui_content_page_close(); /* 返回菜单屏(焦点/导航状态还原) */
break;
default:
break; /* 其余键值忽略 */
}
}
/*
* 函数功能:打开指定内容页(建屏 + 切屏 + 焦点置页面容器)
* 入口参数:id - 内容页 ID content_page_id_t
* 返回值:true - 成功;false - 失败(ID 无效/已有页面打开/对象创建失败)
* 限定条件:ui_menu_init() 已完成(默认输入组与菜单屏存在)
* 函数说明:1. lv_obj_create(NULL) 新建独立屏幕 + 全屏容器(自绘载体,无子对象)
* 2. 容器入默认输入组并获焦后再切屏——按键立即由本模块接管
* 3. 导航状态不压层:菜单 s_depth/s_sel 原样保留,ESC 返回即还原
*/
bool ui_content_page_open(content_page_id_t id) {
if (id >= CONTENT_PAGE_COUNT || s_open != CONTENT_PAGE_COUNT) {
return false; /* ID 无效或已有页面打开(防御) */
}
s_scr = lv_obj_create(NULL); /* parent=NULL → 新建屏幕 */
if (s_scr == NULL) {
return false; /* LVGL 池耗尽 */
}
s_cont = lv_obj_create(s_scr);
if (s_cont == NULL) {
lv_obj_delete(s_scr); /* 回滚:屏已建、容器失败 */
s_scr = NULL;
return false;
}
lv_obj_add_flag(s_cont, LV_OBJ_FLAG_IGNORE_LAYOUT); /* 绝对定位,不参与父级布局 */
lv_obj_set_size(s_cont, CP_SCREEN_W, CP_SCREEN_H); /* 全屏覆盖 */
lv_obj_add_style(s_cont, &cp_style_flat, 0); /* 透明、无边框:剥离主题 card */
lv_obj_add_flag(s_cont, LV_OBJ_FLAG_CLICK_FOCUSABLE); /* 可获焦:键事件入口 */
lv_obj_add_event_cb(s_cont, cp_key_cb, LV_EVENT_KEY, NULL);
lv_obj_add_event_cb(s_cont, cp_draw_cb, LV_EVENT_DRAW_MAIN, NULL);
s_open = id;
s_sel = 0u; /* 每次进入从首行开始(页面按需建毁,不跨次保留) */
/* 焦点/键入口:入默认输入组并获焦(先于切屏,保证按键立即由本模块接管) */
lv_group_t *g = lv_group_get_default();
if (g != NULL) {
lv_group_add_obj(g, s_cont);
lv_group_focus_obj(s_cont);
}
lv_screen_load(s_scr); /* 切到内容页(菜单屏对象保留、不销毁) */
DBG_INFO("page open: id=%u rows=%u", (unsigned)id, (unsigned)s_defs[id].total_rows);
return true;
}
/*
* 函数功能:关闭当前内容页(焦点回菜单容器 + 切回菜单屏 + 销毁页面)
* 入口参数:无
* 返回值:无
* 限定条件:ui_content_page_is_open() 为 true
* 函数说明:1. 先移焦到菜单容器再删屏——防输入组焦点悬空(删除自动移出组)
* 2. 切回菜单屏后销毁页面屏幕,LVGL 池内存随即回落
*/
void ui_content_page_close(void) {
if (s_open == CONTENT_PAGE_COUNT || s_cont == NULL) {
return; /* 未打开(防御) */
}
lv_obj_t *menu_cont = ui_menu_view_container();
if (menu_cont != NULL) {
lv_group_focus_obj(menu_cont); /* 焦点先回菜单容器 */
lv_screen_load(lv_obj_get_screen(menu_cont)); /* 切回菜单屏(对象未动,原样还原) */
}
DBG_INFO("page close: id=%u", (unsigned)s_open);
lv_obj_delete(s_cont); /* 先删容器 */
lv_obj_delete(s_scr); /* 再删屏 */
s_scr = NULL;
s_cont = NULL;
s_open = CONTENT_PAGE_COUNT;
s_sel = 0u;
}
/*
* 函数功能:查询是否有内容页打开
* 入口参数:无
* 返回值:true - 有页面打开;false - 无
* 限定条件:无
* 函数说明:供逻辑层/调试判断当前处于菜单屏还是内容页
*/
bool ui_content_page_is_open(void) {
return (s_open != CONTENT_PAGE_COUNT);
}
+59
View File
@@ -0,0 +1,59 @@
/*
* 模块名称:UI Content Page (内容页面显示层)
* 模块功能:菜单叶子节点的内容页(装置信息/交流量/直流量)——独立 LVGL 屏幕,
* 全屏容器自绘全部内容(浅 V 装饰 + 居中标题 + 行数据 + 页脚页码),
* 无子对象;进入时切屏并获焦、ESC 返回菜单屏并还原焦点;
* 不持有导航状态——由逻辑层 ui_menu.c 在 ENTER 叶子节点时驱动
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
* 作者:王建锋
* 创建日期:2026-09-09
* 修改记录:
* 2026-09-09 王建锋 创建:装置信息/交流量/直流量三页(参考图 10/20/21)
*/
#ifndef UI_CONTENT_PAGE_H
#define UI_CONTENT_PAGE_H
#include <stdint.h>
#include <stdbool.h>
/*
* 内容页 ID:与菜单叶子节点一一对应(映射见 ui_menu.c menu_content_page_for);
* CONTENT_PAGE_COUNT 兼作"无内容页/未打开"哨兵值
*/
typedef enum {
CONTENT_PAGE_DEVICE_INFO = 0u, /* 装置信息(node 1):静态键值行 + 副标题,单页 */
CONTENT_PAGE_AC, /* 交流量(node 3):数据列表,24 项 / 8 项每页 */
CONTENT_PAGE_DC, /* 直流量(node 4):数据列表,3 项单页 */
CONTENT_PAGE_COUNT /* 哨兵:无效 ID / 未打开 */
} content_page_id_t;
/*
* 函数功能:打开指定内容页(建屏 + 切屏 + 焦点置页面容器)
* 入口参数:id - 内容页 ID content_page_id_t
* 返回值:true - 成功;false - 失败(ID 无效/已有页面打开/对象创建失败)
* 限定条件:ui_menu_init() 已完成(默认输入组与菜单屏存在)
* 函数说明:1. 新建独立屏幕,全屏容器自绘全部内容(无子对象,池开销极小)
* 2. 容器入默认输入组并获焦——按键由本模块处理(↑↓移选/ESC返回)
* 3. 导航状态不压层:菜单 s_depth/s_sel 原样保留,ESC 返回即还原
*/
bool ui_content_page_open(content_page_id_t id);
/*
* 函数功能:关闭当前内容页(焦点回菜单容器 + 切回菜单屏 + 销毁页面)
* 入口参数:无
* 返回值:无
* 限定条件:ui_content_page_is_open() 为 true
* 函数说明:先移焦再删屏,防输入组焦点悬空;LVGL 池内存随即回落
*/
void ui_content_page_close(void);
/*
* 函数功能:查询是否有内容页打开
* 入口参数:无
* 返回值:true - 有页面打开;false - 无
* 限定条件:无
* 函数说明:供逻辑层/调试判断当前处于菜单屏还是内容页
*/
bool ui_content_page_is_open(void);
#endif /* UI_CONTENT_PAGE_H */
+178 -66
View File
@@ -1,7 +1,7 @@
/*******************************************************************************
* Size: 12 px
* Bpp: 1
* Opts: --font C:\Users\ADMINI~1\AppData\Local\Temp\simsun_regular.ttf --size 12 --bpp 1 -r 0x20-0x7E --symbols ▶三主事交作保信值制前动区压参双口启告型复字定实式强归当录息手抖护报据控操故数整无时板查检模死波流测清点界直看类系维网置自行装警讯记设询软运通遥量钟防除面: --no-compress --format lvgl --lv-font-name ui_font_cn_12 -o D:\Code\DTU Code\STM32F4-Base\Drivers\BSP\UI\ui_font_cn_12.c
* Opts: --font C:\Users\ADMINI~1\AppData\Local\Temp\simsun_regular.ttf --size 12 --bpp 1 -r 0x20-0x7E --symbols ▶三主事交作保信值制前动区压参双口启告型复字定实式强归当录息手抖护报据控操故数整无时板查检模死波流测清点界直看类系维网置自行装警讯记设询软运通遥量钟防除面:馈线化终端号件版硬校验程序日期第页共, --no-compress --format lvgl --lv-font-name ui_font_cn_12 -o D:\Code\DTU Code\STM32F4-Base\Drivers\BSP\UI\ui_font_cn_12.c
******************************************************************************/
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
@@ -327,6 +327,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x14, 0x50, 0x50, 0x4, 0x1, 0x40, 0xc6, 0x60,
0x30,
/* U+4EF6 "件" */
0x21, 0x5, 0x21, 0x24, 0x27, 0xfd, 0x10, 0x82,
0x10, 0x42, 0xff, 0x41, 0x8, 0x21, 0x4, 0x20,
0x80,
/* U+4F5C "作" */
0x14, 0x2, 0x80, 0x9f, 0x95, 0x6, 0x21, 0x47,
0x88, 0x81, 0x10, 0x23, 0xe4, 0x40, 0x88, 0x11,
@@ -347,6 +352,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x92, 0x12, 0x7e, 0x48, 0x49, 0xf9, 0x21, 0x2f,
0xf0,
/* U+5171 "共" */
0x11, 0x2, 0x20, 0x44, 0x3f, 0xe1, 0x10, 0x22,
0x4, 0x47, 0xff, 0x0, 0x2, 0x20, 0x82, 0x20,
0x20,
/* U+5236 "制" */
0x10, 0x2a, 0x5, 0xf4, 0xc8, 0x9f, 0xf2, 0x22,
0x5f, 0x4a, 0xa9, 0x55, 0x2a, 0x85, 0x70, 0x88,
@@ -362,6 +372,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x50, 0x4a, 0x89, 0x89, 0x3f, 0x44, 0x8, 0x82,
0x60,
/* U+5316 "化" */
0x12, 0x2, 0x40, 0x88, 0x91, 0x26, 0x29, 0x46,
0x8, 0x81, 0x30, 0x2a, 0x4, 0x44, 0x88, 0x90,
0xf0,
/* U+533A "区" */
0xff, 0xe0, 0xa, 0xa, 0x44, 0x8a, 0x21, 0x8,
0xa2, 0x44, 0xa0, 0xa0, 0xf, 0xfc,
@@ -383,6 +398,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xff, 0xc0, 0x60, 0x30, 0x18, 0xc, 0x6, 0x3,
0x1, 0xff, 0xc0, 0x40,
/* U+53F7 "号" */
0x3f, 0x84, 0x10, 0x82, 0x1f, 0xc0, 0x1, 0xff,
0xc4, 0x1, 0x0, 0x3f, 0xc0, 0x8, 0x1, 0x0,
0xc0,
/* U+542F "启" */
0x4, 0x0, 0x40, 0xff, 0x90, 0x12, 0x2, 0x7f,
0xc8, 0x1, 0xff, 0x30, 0x2a, 0x5, 0x7f, 0xc8,
@@ -418,6 +438,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x4, 0x87, 0xff, 0x4, 0x1, 0x30, 0xc1, 0x60,
0x10,
/* U+5E8F "序" */
0x2, 0xf, 0xfd, 0x0, 0x2f, 0xe4, 0x8, 0x9a,
0x10, 0x83, 0xff, 0x42, 0x28, 0x49, 0x8, 0x43,
0x0,
/* U+5F0F "式" */
0x1, 0x40, 0x24, 0x4, 0x7f, 0xf0, 0x10, 0x2,
0x1f, 0x40, 0x88, 0x10, 0x82, 0x14, 0x79, 0xf0,
@@ -501,11 +526,20 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x7f, 0xc0, 0x80, 0x10, 0x2, 0xf, 0xfe, 0x14,
0x2, 0x80, 0x90, 0x22, 0x28, 0x46, 0x7, 0x80,
/* U+65E5 "日" */
0xff, 0xc0, 0x60, 0x30, 0x1f, 0xfc, 0x6, 0x3,
0x1, 0x80, 0xff, 0xe0, 0x20,
/* U+65F6 "时" */
0x0, 0x5e, 0xa, 0x41, 0x4b, 0xf9, 0x5, 0xe0,
0xa4, 0x94, 0x8a, 0x91, 0x5e, 0xa, 0x41, 0x0,
0xe0,
/* U+671F "期" */
0x48, 0x9, 0x3f, 0xf4, 0xa4, 0x97, 0x9e, 0x92,
0x5e, 0x4a, 0x4f, 0xfd, 0x20, 0x25, 0x24, 0xc3,
0x30,
/* U+677F "板" */
0x20, 0x64, 0xf0, 0x90, 0x7a, 0x2, 0x7e, 0xea,
0x5b, 0x4d, 0x2a, 0x25, 0x44, 0x90, 0xa5, 0x19,
@@ -516,6 +550,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x8, 0x21, 0xfc, 0x20, 0x87, 0xf0, 0x0, 0x7f,
0xf0,
/* U+6821 "校" */
0x22, 0x4, 0x20, 0xbf, 0xf8, 0x2, 0x28, 0xe8,
0x9a, 0xad, 0x14, 0x22, 0x84, 0x20, 0x8a, 0x16,
0x30,
/* U+68C0 "检" */
0x21, 0x4, 0x20, 0x8a, 0x7a, 0x22, 0x82, 0xcf,
0x9c, 0x5, 0x12, 0x29, 0x44, 0xa8, 0x92, 0x17,
@@ -555,6 +594,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x90, 0x12, 0x2, 0x7f, 0xc0, 0x1, 0x49, 0x44,
0x90,
/* U+7248 "版" */
0x10, 0x6a, 0xf1, 0x50, 0x2a, 0x7, 0xfe, 0x8a,
0x51, 0x4b, 0xaa, 0x55, 0x4a, 0x91, 0x65, 0x49,
0x10,
/* U+754C "界" */
0x7f, 0xc8, 0x89, 0xff, 0x22, 0x27, 0xfc, 0x8,
0x6, 0xc7, 0x7, 0x11, 0x2, 0x20, 0x84, 0x20,
@@ -569,6 +613,25 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xc8, 0x13, 0xfe, 0xa0, 0x47, 0xf8, 0x81, 0x1f,
0xe0,
/* U+786C "硬" */
0xf7, 0xe4, 0x20, 0x9f, 0x22, 0xa7, 0x7d, 0xaa,
0x95, 0xf2, 0xc8, 0x55, 0xe, 0x61, 0x53, 0x80,
/* U+7A0B "程" */
0x17, 0xdc, 0x88, 0x91, 0x13, 0xef, 0x0, 0x4f,
0x9c, 0x43, 0x48, 0xa7, 0xc4, 0x20, 0x84, 0x17,
0xf0,
/* U+7AEF "端" */
0x81, 0x9, 0x24, 0x24, 0xf7, 0xf0, 0x1, 0x5f,
0xe8, 0x45, 0x7f, 0x4a, 0xa5, 0x57, 0x2a, 0x84,
0x30,
/* U+7B2C "第" */
0x42, 0xf, 0x7e, 0x52, 0x0, 0x7, 0xfc, 0x8,
0x9f, 0xf2, 0x20, 0x7f, 0xe2, 0x84, 0x90, 0xe2,
0x60,
/* U+7C7B "类" */
0x4, 0x4, 0x90, 0x54, 0x7f, 0xf1, 0x50, 0x49,
0x10, 0x10, 0x20, 0xff, 0xe1, 0x40, 0xc6, 0x60,
@@ -579,6 +642,16 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x6, 0x13, 0xff, 0x4, 0x24, 0x91, 0x11, 0x46,
0x10,
/* U+7EBF "线" */
0x21, 0x44, 0x25, 0x7, 0xcb, 0x8e, 0x10, 0x43,
0xd1, 0xc7, 0x8a, 0x1, 0x86, 0x27, 0xa, 0x86,
0x30,
/* U+7EC8 "终" */
0x22, 0x4, 0x79, 0x11, 0x4d, 0x4e, 0x10, 0x45,
0x13, 0x1f, 0x18, 0x0, 0x86, 0xc3, 0x6, 0x0,
0x20,
/* U+7EF4 "维" */
0x22, 0x84, 0x49, 0x1f, 0xca, 0x4e, 0xc8, 0x4f,
0xd1, 0x27, 0xa4, 0x7, 0xe6, 0x93, 0x12, 0x3,
@@ -677,6 +750,24 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xff, 0xe0, 0x80, 0x20, 0x3f, 0xf4, 0x92, 0x9e,
0x52, 0x4a, 0x79, 0x49, 0x2f, 0xfd, 0x0, 0x80,
/* U+9875 "页" */
0xff, 0xe0, 0x80, 0x20, 0x3f, 0xe4, 0x4, 0x80,
0x91, 0x12, 0x22, 0x44, 0x41, 0x60, 0xc3, 0x60,
0x10,
/* U+9988 "馈" */
0x41, 0x9, 0xfd, 0xa4, 0xd7, 0xf0, 0x10, 0xbf,
0xd0, 0x2, 0x7f, 0x49, 0x29, 0x25, 0x8b, 0x26,
0x10,
/* U+9A8C "验" */
0x1, 0x1c, 0x20, 0x8a, 0x52, 0x2a, 0x83, 0x4f,
0xbc, 0x0, 0x92, 0x39, 0x5a, 0xa8, 0x52, 0x37,
0xf0,
/* U+FF0C "," */
0xf6,
/* U+FF1A ":" */
0xf0, 0xf0,
@@ -797,14 +888,14 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
{.bitmap_index = 621, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 638, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 655, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 672, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 686, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 702, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 719, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 735, .adv_w = 192, .box_w = 9, .box_h = 10, .ofs_x = 1, .ofs_y = -1},
{.bitmap_index = 747, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 764, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 781, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 672, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 689, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 706, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 723, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 737, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 753, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 770, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 786, .adv_w = 192, .box_w = 9, .box_h = 10, .ofs_x = 1, .ofs_y = -1},
{.bitmap_index = 798, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 815, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 832, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
@@ -812,12 +903,12 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
{.bitmap_index = 866, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 883, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 900, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 917, .adv_w = 192, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 931, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 948, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 965, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 982, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 999, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 917, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 934, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 951, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 968, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 985, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1002, .adv_w = 192, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 1016, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1033, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1050, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
@@ -825,45 +916,64 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
{.bitmap_index = 1084, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1101, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1118, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1135, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1151, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1168, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1185, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1202, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1219, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1236, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1252, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1269, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1286, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1303, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1320, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1337, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1354, .adv_w = 192, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 1369, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1386, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1403, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1420, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1437, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1454, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1471, .adv_w = 192, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 1485, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1502, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1519, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1536, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1553, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1570, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1587, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1604, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1621, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1638, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1655, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1672, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1689, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1706, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1723, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1740, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1756, .adv_w = 192, .box_w = 2, .box_h = 6, .ofs_x = 2, .ofs_y = 0},
{.bitmap_index = 1758, .adv_w = 165, .box_w = 8, .box_h = 10, .ofs_x = 1, .ofs_y = -1} /* U+25B6 */
{.bitmap_index = 1135, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1152, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1169, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1186, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1203, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1220, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1236, .adv_w = 192, .box_w = 9, .box_h = 11, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 1249, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1266, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1283, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1300, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1317, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1334, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1351, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1368, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1384, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1401, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1418, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1435, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1452, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1469, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1486, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1503, .adv_w = 192, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 1518, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1535, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1551, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1568, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1585, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1602, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1619, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1636, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1653, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1670, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1687, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1704, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1721, .adv_w = 192, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 1735, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1752, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1769, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1786, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1803, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1820, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1837, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1854, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1871, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1888, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1905, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1922, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1939, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1956, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1973, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1990, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2006, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2023, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2040, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2057, .adv_w = 192, .box_w = 2, .box_h = 4, .ofs_x = 2, .ofs_y = 0},
{.bitmap_index = 2058, .adv_w = 192, .box_w = 2, .box_h = 6, .ofs_x = 2, .ofs_y = 0},
{.bitmap_index = 2060, .adv_w = 165, .box_w = 8, .box_h = 10, .ofs_x = 1, .ofs_y = -1} /* U+25B6 */
};
/*---------------------
@@ -871,16 +981,18 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
*--------------------*/
static const uint16_t unicode_list_1[] = {
0x0, 0x32, 0x82, 0x9b, 0x153, 0x1d4, 0x1d8, 0x233,
0x42d, 0x444, 0x49f, 0x531, 0x582, 0x5b9, 0x5c3, 0x5da,
0x626, 0x641, 0x982, 0xb04, 0xd4e, 0xd91, 0xd95, 0x1106,
0x1131, 0x1149, 0x114a, 0x114c, 0x1266, 0x1442, 0x148d, 0x149b,
0x149c, 0x1565, 0x159e, 0x16c4, 0x173c, 0x1767, 0x176b, 0x17d7,
0x17ed, 0x1976, 0x19dc, 0x1ab7, 0x1c18, 0x1d72, 0x1ed9, 0x1f38,
0x1f42, 0x1ffc, 0x22b0, 0x2743, 0x28eb, 0x2902, 0x2e72, 0x2ef2,
0x30eb, 0x3148, 0x3165, 0x33e1, 0x3a43, 0x3abc, 0x3d5d, 0x3da6,
0x3da7, 0x3db5, 0x3dd9, 0x4166, 0x41c7, 0x4211, 0x425c, 0x43c6,
0x4696, 0x4829, 0x485b, 0x4959, 0xb111
0x0, 0x32, 0x82, 0x9b, 0xed, 0x153, 0x1d4, 0x1d8,
0x233, 0x368, 0x42d, 0x444, 0x49f, 0x50d, 0x531, 0x582,
0x5b9, 0x5c3, 0x5da, 0x5ee, 0x626, 0x641, 0x982, 0xb04,
0xd4e, 0xd91, 0xd95, 0x1086, 0x1106, 0x1131, 0x1149, 0x114a,
0x114c, 0x1266, 0x1442, 0x148d, 0x149b, 0x149c, 0x1565, 0x159e,
0x16c4, 0x173c, 0x1767, 0x176b, 0x17d7, 0x17dc, 0x17ed, 0x1916,
0x1976, 0x19dc, 0x1a18, 0x1ab7, 0x1c18, 0x1d72, 0x1ed9, 0x1f38,
0x1f42, 0x1ffc, 0x22b0, 0x243f, 0x2743, 0x28eb, 0x2902, 0x2a63,
0x2c02, 0x2ce6, 0x2d23, 0x2e72, 0x2ef2, 0x30b6, 0x30bf, 0x30eb,
0x3148, 0x3165, 0x33e1, 0x3a43, 0x3abc, 0x3d5d, 0x3da6, 0x3da7,
0x3db5, 0x3dd9, 0x4166, 0x41c7, 0x4211, 0x425c, 0x43c6, 0x4696,
0x4829, 0x485b, 0x4959, 0x4a6c, 0x4b7f, 0x4c83, 0xb103, 0xb111
};
/*Collect the unicode lists and glyph_id offsets*/
@@ -892,10 +1004,10 @@ static const lv_font_fmt_txt_cmap_t cmaps[] =
},
{
.range_start = 19977, .range_length = 45330, .glyph_id_start = 96,
.unicode_list = unicode_list_1, .glyph_id_ofs_list = NULL, .list_length = 77, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
.unicode_list = unicode_list_1, .glyph_id_ofs_list = NULL, .list_length = 96, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
},
{
.range_start = 9654, .range_length = 1, .glyph_id_start = 173,
.range_start = 9654, .range_length = 1, .glyph_id_start = 192,
.unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY
}
};
+32 -4
View File
@@ -21,6 +21,8 @@
#include "ui_menu_view.h"
#include "ui_content_page.h"
#include "ui_menu_tab.h"
#include "lvgl.h"
@@ -88,6 +90,23 @@ static void menu_back(void) {
ui_menu_view_focus();
}
/*
* 函数功能:查叶子节点对应的内容页(无内容页返回哨兵值)
* 入口参数:node - 菜单节点下标 uint8_t
* 返回值:内容页 ID content_page_id_t;无内容页 = CONTENT_PAGE_COUNT
* 限定条件:无
* 函数说明:仅部分叶子有内容页(参考图 10/20/21);下标对应 ui_menu_tab.c
* node 1=装置信息、3=交流量、4=直流量(表序变更时须同步本映射)
*/
static content_page_id_t menu_content_page_for(uint8_t node) {
switch (node) {
case 1u: return CONTENT_PAGE_DEVICE_INFO; /* 装置信息(L1 叶子) */
case 3u: return CONTENT_PAGE_AC; /* 交流量(实时数据子项) */
case 4u: return CONTENT_PAGE_DC; /* 直流量(实时数据子项) */
default: return (content_page_id_t)CONTENT_PAGE_COUNT; /* 无内容页 */
}
}
/*
* 函数功能:按键语义分发(移/进/退)
* 入口参数:depth - 焦点所在层深度 uint8_t
@@ -95,7 +114,7 @@ static void menu_back(void) {
* 返回值:无
* 限定条件:ui_menu_init() 已完成
* 函数说明: 1. UP/DOWN:移选(首尾环绕);选中越出可见区由显示层跟随滚动
* 2. ENTER/RIGHT:进子框(叶子 → 空白终点框)
* 2. ENTER/RIGHT:叶子有内容页 → 切内容屏(不压层);否则进子框(叶子 → 空白终点框)
* 3. ESC/LEFT:关最右框(根框不响应)
* 4. 空框(终点页 0 条目)只响应返回
*/
@@ -119,12 +138,21 @@ static void menu_key_handle(uint8_t depth, lv_key_t key) {
}
break;
case LV_KEY_ENTER:
case LV_KEY_RIGHT:
case LV_KEY_RIGHT: {
/* 进子框:空框无条目可进;最深层(depth=MAX-1)无子层可再开 */
if (cnt > 0u && depth < MENU_PAGE_MAX - 1u) {
menu_open(kids[s_sel[depth]]); /* 压层:建新框 + 焦点移到新框 */
if (cnt > 0u) {
content_page_id_t pid = menu_content_page_for(kids[s_sel[depth]]);
if (pid < CONTENT_PAGE_COUNT) {
/* 叶子有内容页:切内容屏(不压层,导航状态原样保留;ESC 返回即还原) */
ui_content_page_open(pid);
}
else if (depth < MENU_PAGE_MAX - 1u) {
menu_open(kids[s_sel[depth]]); /* 压层:建新框 + 焦点移到新框(叶子 → 空白终点框) */
}
}
break;
}
case LV_KEY_ESC:
case LV_KEY_LEFT:
if (depth > 0u) { /* 根框(d=0)不响应返回 */
+17 -10
View File
@@ -78,7 +78,22 @@ static uint8_t s_row_node[MENU_PAGE_MAX][MENU_ITEM_MAX]; /* 行数据:节
static menu_frame_t s_frame[MENU_PAGE_MAX]; /* 每层框几何缓存:位置/尺寸/选中行(现算不落状态,供子框对齐;见上方类型注释) */
/* 样式(静态,一次性初始化,常驻) */
static lv_style_t s_style_flat; /* 通用:透明、无边框/圆角/内边距(剥离主题 card) */
/* flat:通用——透明、无边框/圆角/内边距(剥离主题 card)。用常量样式(LV_STYLE_CONST_INIT):
* 属性存静态数组、零 LV_MEM 池分配;动态样式首次 set_prop 会从池分配 values_and_props 且永不释放 */
static const lv_style_const_prop_t s_flat_props[] = {
{ .prop = LV_STYLE_BG_OPA, .value = { .num = LV_OPA_TRANSP } },
{ .prop = LV_STYLE_BORDER_WIDTH, .value = { .num = 0 } },
{ .prop = LV_STYLE_RADIUS, .value = { .num = 0 } },
{ .prop = LV_STYLE_PAD_LEFT, .value = { .num = 0 } },
{ .prop = LV_STYLE_PAD_RIGHT, .value = { .num = 0 } },
{ .prop = LV_STYLE_PAD_TOP, .value = { .num = 0 } },
{ .prop = LV_STYLE_PAD_BOTTOM, .value = { .num = 0 } },
{ .prop = LV_STYLE_PAD_ROW, .value = { .num = 0 } },
{ .prop = LV_STYLE_PAD_COLUMN, .value = { .num = 0 } },
LV_STYLE_CONST_PROPS_END
};
LV_STYLE_CONST_INIT(s_style_flat, s_flat_props);
static lv_style_t s_style_frame; /* 框体:透明底 + 1px 白边框 */
static lv_style_t s_style_scrollbar; /* 滚动条:白色、4px 宽 */
@@ -89,7 +104,7 @@ static lv_style_t s_style_scrollbar; /* 滚动条:白色、4px 宽 */
* 入口参数:无
* 返回值:无
* 限定条件:无
* 函数说明: 1. flat 剥离主题给对象附加的卡片样式(边框/圆角/内边距)
* 函数说明: 1. flat 剥离主题给对象附加的卡片样式(边框/圆角/内边距;常量样式,见上方定义)
* 2. frame 为所有级联框(含根框)的 1px 白边框
* 3. 选中行反色不用样式:自绘回调按 sel 直接画白带(行不是对象)
*/
@@ -102,14 +117,6 @@ static void view_styles_init(void) {
}
inited = true;
/* flat:透明、无边框/圆角/内边距(剥离主题附加的卡片样式) */
lv_style_init(&s_style_flat);
lv_style_set_bg_opa(&s_style_flat, LV_OPA_TRANSP);
lv_style_set_border_width(&s_style_flat, 0);
lv_style_set_radius(&s_style_flat, 0);
lv_style_set_pad_all(&s_style_flat, 0);
lv_style_set_pad_gap(&s_style_flat, 0);
/* frame:透明底 + 1px 白边框(所有级联框含根框) */
lv_style_init(&s_style_frame);
lv_style_set_bg_opa(&s_style_frame, LV_OPA_TRANSP);