UI 代码:补全 remo_handle/cp_draw 注释,拆分 cp_draw_cb 绘制函数

This commit is contained in:
2026-09-13 17:04:12 +08:00
parent 4b68b479ba
commit 54e8356295
2 changed files with 150 additions and 62 deletions
+111 -55
View File
@@ -24,6 +24,8 @@
* 2026-09-10 王建锋 网口设置页(node 30):新增 CONTENT_PAGE_NET_CFG 入描述符表;
* 新 API ui_content_page_selected_row(页面钩子感知选中行)+
* 描述符 init_cb(开页后调一次,页面模块重置运行态)
* 2026-09-13 王建锋 cp_draw_cb 按区块拆为四个绘制子函数(cp_draw_deco/header/rows/footer),
* 主函数仅编排(行数取一次供行窗口/页脚共用),行为零变化
*/
/* 头文件包含区 */
@@ -181,32 +183,34 @@ static void cp_draw_centered_text(lv_layer_t *layer, const char *text, int32_t y
}
/*
* 函数功能:页面自绘(浅 V 装饰 + 标题/副标题 + 行数据 + 页脚页码 + 页面钩子)
* 入口参数:e - 事件指针 lv_event_t *
* 函数功能:绘制"浅 V"装饰(共享 ui_deco 模块,与菜单根框同几何)
* 入口参数:layer - 绘制层 lv_layer_t *
* d - 页面描述符 const content_page_def_t *
* 返回值:无
* 限定条件:事件为 LV_EVENT_DRAW_MAIN,页面已打开
* 函数说明: 1. 浅 V 装饰:共享 ui_deco 模块(与菜单根框同几何)
* 2. 行数:静态页取 row_count,动态页取 count_cb();
* 列表页窗口 = 选中行所在页(首可见行 = (sel/每页数)*每页数),
* 行槽位置固定、数据随页切换;信息页全量静态绘制
* 3. 行文本:静态页直绘 Flash 表(不拷内存);动态页经 refresh()
* 逐行取入栈缓冲(同帧同步光栅化,安全)
* 4. 选中行整行白带(x=2..156)+ 黑字,非选中白字
* 5. 各区块按 culling 区跳过不在重绘区的部分;末尾调 draw_cb(页自定义内容)
* 限定条件:页面已打开
* 函数说明:每页可关(hide_deco;密码页跟随实机:无装饰)
*/
static void cp_draw_cb(lv_event_t *e) {
const content_page_def_t *d = s_defs[s_open];
lv_layer_t *layer = lv_event_get_layer(e);
/* "浅 V"装饰:共享 ui_deco 模块(与菜单根框同几何);每页可关(密码页跟随实机:无装饰) */
static void cp_draw_deco(lv_layer_t *layer, const content_page_def_t *d) {
if (d->hide_deco == 0u) {
ui_deco_draw(layer, &layer->_clip_area);
}
}
/*
* 函数功能:绘制标题/副标题(居中;整宽带 + culling)
* 入口参数:layer - 绘制层 lv_layer_t *
* d - 页面描述符 const content_page_def_t *
* 返回值:无
* 限定条件:页面已打开
* 函数说明:标题放置 y 每页可配(title_y,0 = 框架默认 CP_TITLE_Y);
* 副标题仅信息页(subtitle 非空);重绘区不相交则跳过区块
*/
static void cp_draw_header(lv_layer_t *layer, const content_page_def_t *d) {
lv_area_t t;
/* 标题(居中;放置 y 每页可配,0 = 框架默认) */
{
int32_t ty = (d->title_y != 0) ? d->title_y : CP_TITLE_Y;
lv_area_t t;
t.x1 = 0;
t.x2 = CP_SCREEN_W - 1;
@@ -219,8 +223,6 @@ static void cp_draw_cb(lv_event_t *e) {
/* 副标题(仅信息页) */
if (d->subtitle != NULL) {
lv_area_t t;
t.x1 = 0;
t.x2 = CP_SCREEN_W - 1;
t.y1 = d->subtitle_y;
@@ -229,9 +231,22 @@ static void cp_draw_cb(lv_event_t *e) {
cp_draw_centered_text(layer, d->subtitle, d->subtitle_y);
}
}
}
/* 行数据:列表页窗口跟随选中行所在页,信息页全量 */
int32_t nrows = (int32_t)cp_row_total(d);
/*
* 函数功能:绘制行数据(列表页窗口跟随选中行所在页,信息页全量;逐行 culling)
* 入口参数:layer - 绘制层 lv_layer_t *
* d - 页面描述符 const content_page_def_t *
* nrows - 总行数 int32_t(调用方取一次,与页脚同帧共用)
* 返回值:无
* 限定条件:页面已打开
* 函数说明: 1. 列表页窗口顶行 = (sel/每页行数)*每页行数,末页不足整页截断
* 2. 行条带(整宽)不在重绘区则跳过(culling)
* 3. 选中行:整行白带(x=2..156,高 band_h)+ 黑字,非选中白字
* 4. 行文本:静态 = Flash 表(不拷内存);动态 = refresh() 逐行取
* 入栈缓冲(同帧同步光栅化,安全)
*/
static void cp_draw_rows(lv_layer_t *layer, const content_page_def_t *d, int32_t nrows) {
int32_t first = 0;
int32_t cnt = nrows;
@@ -316,43 +331,84 @@ static void cp_draw_cb(lv_event_t *e) {
lv_draw_label(layer, &ld, &strip);
}
}
}
/* 页脚"第 X 页,共 Y 页":列表页随选中行现算,信息页按参考图固定值;每页可关(密码页跟随实机) */
{
char buf[32];
uint8_t cur;
uint8_t pages;
lv_area_t t;
/*
* 函数功能:绘制页脚"第 X 页,共 Y 页"
* 入口参数:layer - 绘制层 lv_layer_t *
* d - 页面描述符 const content_page_def_t *
* nrows - 总行数 int32_t(调用方取一次,与行窗口同帧同值)
* 返回值:无
* 限定条件:页面已打开
* 函数说明:列表页随选中行现算,信息页按参考图固定值;每页可关
* (hide_footer;密码页跟随实机)
*/
static void cp_draw_footer(lv_layer_t *layer, const content_page_def_t *d, int32_t nrows) {
char buf[32]; /* 页行文本缓冲(栈):"第 %u 页,共 %u 页" 最长远不足 32B */
uint8_t cur; /* 当前页码(1 基) */
uint8_t pages; /* 总页数 */
lv_area_t t; /* 页脚条带区域(整宽,放置于 CP_PAGE_LINE_Y) */
if (d->selectable != 0u) {
cur = (uint8_t)(s_sel / d->rows_per_page + 1u);
pages = (uint8_t)((nrows + (int32_t)d->rows_per_page - 1) / d->rows_per_page);
}
else {
cur = d->fixed_cur_page;
pages = 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 (d->hide_footer == 0u && cp_areas_intersect(&t, &layer->_clip_area)) {
/* lv_snprintf 而非 snprintf:MSVC 对 printf 族做格式串扫描,中文字面量会误报 C4819 */
lv_snprintf(buf, sizeof(buf), "第 %u 页,共 %u 页", (unsigned)cur, (unsigned)pages);
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);
}
/* 页码计算,两种来源:
* - 列表页(selectable):随选中行现算——当前页 = 选中行/每页行数 + 1
* (选中行所在页);总页数 = ceil(nrows/每页行数),
* 写成经典向上取整 (n + p - 1) / p(nrows 恰为整页倍数时不多算一页);
* nrows 由调用方取一次、与行窗口共用,保证同帧页码与窗口一致
* - 信息/表单页(非 selectable):取参考图固定值(fixed_cur_page / fixed_total_pages) */
if (d->selectable != 0u) {
cur = (uint8_t)(s_sel / d->rows_per_page + 1u);
pages = (uint8_t)((nrows + (int32_t)d->rows_per_page - 1) / d->rows_per_page);
}
else {
cur = d->fixed_cur_page;
pages = d->fixed_total_pages;
}
/* 页脚条带:整宽,放置于 CP_PAGE_LINE_Y(143,字形顶距已计入放置 y,
* 墨迹与参考图对齐);高 15 = 字体行高 13 + 余量,整行文字一次覆盖 */
t.x1 = 0;
t.x2 = CP_SCREEN_W - 1;
t.y1 = CP_PAGE_LINE_Y;
t.y2 = CP_PAGE_LINE_Y + 15;
/* 双重门控:① 本页开启页脚(hide_footer;密码页跟随实机:无页码)
* ② 页脚条带与重绘区相交(culling)——两者皆成立才格式化并绘制 */
if (d->hide_footer == 0u && cp_areas_intersect(&t, &layer->_clip_area)) {
/* lv_snprintf 而非 snprintf:MSVC 对 printf 族做格式串扫描,中文字面量会误报 C4819 */
lv_snprintf(buf, sizeof(buf), "第 %u 页,共 %u 页", (unsigned)cur, (unsigned)pages);
lv_draw_label_dsc_t ld;
/* ofs 相对 coords 原点(t.x1=0,t.y1=CP_PAGE_LINE_Y):
* 水平 6 = 左对齐、左留白 6px(与实机一致);垂直 0(顶距已计入放置 y) */
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);
}
}
/*
* 函数功能:页面自绘(编排:浅 V 装饰 + 标题/副标题 + 行数据 + 页脚页码 + 页面钩子)
* 入口参数:e - 事件指针 lv_event_t *
* 返回值:无
* 限定条件:事件为 LV_EVENT_DRAW_MAIN,页面已打开
* 函数说明:行数取一次(cp_row_total)供行窗口与页脚页码共用(同帧同值);
* 各区块由子函数绘制(deco/header/rows/footer),均按 culling 区
* 跳过不在重绘区的部分;末尾调 draw_cb(页自定义内容,在内置区块之后)
*/
static void cp_draw_cb(lv_event_t *e) {
const content_page_def_t *d = s_defs[s_open];
lv_layer_t *layer = lv_event_get_layer(e);
int32_t nrows = (int32_t)cp_row_total(d); /* 行数取一次:供行窗口与页脚页码共用 */
cp_draw_deco(layer, d);
cp_draw_header(layer, d);
cp_draw_rows(layer, d, nrows);
cp_draw_footer(layer, d, nrows);
/* 页面钩子:自定义内容(表单/操作页;在内置区块之后绘制) */
if (d->draw_cb != NULL) {