Files
STM32F4-Base/Drivers/BSP/UI/ui_w_setlist.h
T
wandering1 f711130b4c feat(UI组件): 新增数值编辑器/定值表/动作确认页三组件(道B task-5)
域5 新增 3 对文件(双端注册 uvprojx + CMakeLists),只做渲染与输入抽象、
不接真实数据源(数据绑定 = 批 2 道E ui_data/prot_set 经回调注入):
- ui_w_editor:定点整数(10^decimals)逐位编辑——上下步进(0..9 环绕无进位)、
  左右移数字光标(首末环绕)、ENTER 提交经 min/max 范围校验,越界拒绝并
  显示"越界"提示留在编辑态;光标反显盒与 ui_page_net_cfg 字节光标同画法
  (含"只画单字符防折行"实测坑注释);共享格式化 ui_w_editor_fmt_scaled()
  单一规则源(值列显示与编辑光标恒同串)
- ui_w_setlist:定值四视图(参数/定值/控制字/软压板)共用列表渲染 +
  整定输入——行表(名称<=7字/id/类型/小数位/范围/二态串表) + 回调注入
  (get/set/commit/state/bad);查看视图(commit=NULL)与整定视图只差绑定:
  整定视图末行固定"保存"行,值随交接态 ENTER/WAIT/OK/ERR(net_cfg 先例),
  整表一次提交(一次封存一次校验和,页面补齐规划 §3.2);二态行 ENTER
  循环切换;保存失败越界行经 bad 回调反显(页面扩充详细方案 §3.2.7)
- ui_page_action:可复用操作确认链——一次确认 -> 二次确认 -> ok_cb
  只投递不阻塞 -> done_text 回报(或成功即关页),拒收显示 ERR 可重试;
  ESC/LEFT 关页取消(实测取消后菜单与基线逐字节一致);单例描述符由
  开页装载(内容页框架全局单页前提),不定义 ui_page_action_desc
  (registration-check 页面模块判据不误拦,批 2 跳板各自出口)

组件文案用字全部落在上一分支预置字集内(font-charset WARN 60->52 印证
确/取/消/越/二/次/返/回 已转源码在用),无需再动字库。

BSP 公开 API 约定合规(首提被 cppcheck/coding-standard/bsp-err 三钩拦下,
按门禁口径修净后复验全绿):
- 键分发返回值取 uint8_t 1/0 不用 bool(bsp-err/err-type:bool 只许
  is_/has_ 谓词);ui_w_editor_value 直返 int32_t(出参形状无错误通道)
- ui_page_action_open 返回 bsp_err_t:BSP_ERR_PARAM 参数无效 /
  BSP_ERR_STATE 已有页打开 / BSP_ERR_NO_SPACE 框架开页失败(可判分支)
- get/state/bad 回调 typedef 各补"返回值:"注释块(bsp-err/return-doc)
- cppcheck variableScope 变量收scope 7 处;CODE-RULE-18 Yoda 1 处
  (sel+1u==total -> sel==count);提交内已不含 --wdemo/--wact harness

验证:
- 模拟器零警告;组件行为经临时 sim-only harness(--wdemo/--wact) 截图
  目检 7 态:基线视图/bad 反显/进编辑步进/越界拒绝/二态切换/保存整表
  提交 OK/确认链三段/取消回菜单;harness(main.c 4 处 + CMake 1 行 +
  ui_w_demo.c)已完整还原删除,提交内不含(最终树 main.c 无改动,
  CMakeLists diff 仅 3 行注册)
- 回归:菜单 8 状态 + 内容页 11 页黄金参考逐字节 PASS(ref 无变化,
  无基线更新提交);池基线 5368/往返 5448 不变
- 门禁:coding-standard PASS / font-charset PASS / layer-deps PASS
  (新文件零 App include,基线 6 不变——减基线归 task-6)
- @build 0 Error 0 Warning;Code +324 B、RO/RW/ZI 0(组件尚无引用方,
  ARM 链接器未剥离仅因新 TU;批 2 页面接线后实例 RAM 每页约 +40~60 B)

gate: 全钩子正常执行通过,无 --no-verify
- pre-commit run --all-files 全绿(含 mem-budget/mem-numbers:本分支基于
  回填后台账 d9ab955,RAM 0 变化、RO 不变,仅 Code +324 B 不涉受管区)
- 手工自查:6 新文件 BOM=EF BB BF 齐全、全 LF、U+FFFD=0、字面量仅
  UTF-8 中文(UI 带 BOM 先例口径:保存/越界/二次确认/告警/跳闸等,
  全部已在字体子集);ASCII 串仅 ENTER/WAIT/OK/ERR 状态字
2026-10-25 04:34:43 +08:00

194 lines
9.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 模块名称:UI 定值表共享组件(ui_w_setlist)
* 模块功能:把"参数/定值/控制字/软压板"四类视图的列表渲染与整定输入抽象成
* 一份实现——行表 + 数据回调注入(取数/写工作副本/提交/状态回读/
* 越界行查询),同一份组件供多个页面实例复用:
* 查看视图(commit=NULL:无保存行、ENTER 无效)与整定视图
* (commit 非空:末行固定为"保存"行,ENTER 投递整表提交)只差绑定;
* 数值行走 ui_w_editor 逐位编辑(范围校验提交),二态文字行
* (控制字"告警/跳闸"、软压板"投入/退出")ENTER 直接切换;
* 保存失败后的越界行经 bad 回调反显高亮;
* 分页跟随内容页框架内置(8 行/页,UI_LIST_ROWS)
* 适用范围:Drivers/BSP/UI(标准列表页骨架几何:UI_LIST_TOP/ROW_PITCH/
* ROW_BAND_H/LIST_ROWS/RIGHT_X 令牌;页面描述符须 selectable=1、
* key_intercept=1、rows_per_page=UI_LIST_ROWS、text_dy=0)
* 说明:数据绑定全部经回调注入(批 2 ui_data/prot_set 交接时由页面薄跳板
* 提供实现),组件不 include 任何 App 头(分层门禁方向);
* 实例化使用——每个页面文件 static 一份实例,钩子包一层 &inst 转调
* (同 ui_w_records 模式)
* 作者:王建锋
* 创建日期:2026-10-25
* 修改记录:
* v1.0 2026-10-25 王建锋 创建(道B task-5;规格 = 页面扩充详细方案.md
* §3.2 四视图表/§3.2.6 查看与整定差别/§3.2.7 编辑
* 交互/§4.2 bind 要点;保存行 ENTER/WAIT/OK/ERR
* 沿用 ui_page_net_cfg 交接显示先例)
*/
#ifndef UI_W_SETLIST_H
#define UI_W_SETLIST_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
#include "ui_content_page.h" /* lvgl(lv_key_t/lv_layer_t)+ 框架类型 */
#include "ui_w_editor.h"
/* 保存交接显示态(值列 ENTER/WAIT/OK/ERR,与 net_cfg 保存行同字面) */
typedef enum {
UI_W_SETLIST_ST_IDLE = 0, /* 空闲:保存行显示 ENTER */
UI_W_SETLIST_ST_WAIT, /* 请求已投递、属主任务处理中:WAIT */
UI_W_SETLIST_ST_OK, /* 上轮提交成功:OK */
UI_W_SETLIST_ST_FAIL /* 上轮提交失败:ERR */
} ui_w_setlist_st_t;
/* 行种类 */
#define UI_W_SETLIST_KIND_NUM 0u /* 数值行:ui_w_editor 逐位编辑(min/max/decimals 有效) */
#define UI_W_SETLIST_KIND_ENUM 1u /* 二态文字行:ENTER 在 opts 串表内循环切换 */
/*
* 视图行描述(Flash const 表,一行一条)
* 值通道统一 int32_t 定点:
* 数值行 = 工程量 * 10^decimals(如 10.24 A -> 1024)
* 二态行 = opts 串表下标(0/1/...)
*/
typedef struct {
const char *name; /* 中文名 <= 7 字(字体子集已预置) */
uint8_t id; /* 应用侧枚举 ID:组件只透传给回调,不解释语义 */
uint8_t kind; /* UI_W_SETLIST_KIND_NUM / _ENUM */
uint8_t decimals; /* 数值行小数位 0..3(二态行忽略) */
int32_t min; /* 数值行下限(含;>=0;二态行忽略) */
int32_t max; /* 数值行上限(含;二态行忽略) */
const char *const *opts; /* 二态行:NUL 结尾 Flash 字符串串表(数值行 NULL) */
} ui_w_setlist_row_t;
/* 数据回调组(均 uiTask 上下文、页面绘制/按键链内调用;实现由批 2 页面跳板提供,
* 组件不 include 任何 App 头——数据绑定经此注入) */
/*
* 函数功能:读某行当前值(数值行 = 工程量 * 10^decimals;二态行 = 串表下标)
* 入口参数:id - 行表登记的枚举 ID uint8_t
* 返回值:当前值 int32_t
*/
typedef int32_t (*ui_w_setlist_get_fn)(uint8_t a_id);
/*
* 函数功能:写某行 RAM 工作副本(不写盘;落盘统一经 commit 整表提交)
* 入口参数:id - 行枚举 ID uint8_t
* val - 新值(口径同 get) int32_t
* 返回值:无
*/
typedef void (*ui_w_setlist_set_fn)(uint8_t a_id, int32_t a_val);
/*
* 函数功能:整表提交(一次封存一次校验和;实现只投递请求到属主任务,不阻塞)
* 入口参数:无
* 返回值:无(投递结果经 state 回调回读)
*/
typedef void (*ui_w_setlist_commit_fn)(void);
/*
* 函数功能:保存交接态回读(保存行值列显示源)
* 入口参数:无
* 返回值:当前交接态 ui_w_setlist_st_t
*/
typedef ui_w_setlist_st_t (*ui_w_setlist_state_fn)(void);
/*
* 函数功能:查询某数据行是否为"保存失败越界行"(需反显高亮)
* 入口参数:row - 数据行下标(不含保存行) uint16_t
* 返回值:true = 需反显;false = 正常(提问谓词,非错误通道) bool
*/
typedef bool (*ui_w_setlist_bad_fn)(uint16_t a_row);
/*
* 定值表实例
* 用法(页面跳板示例,批 2):
* static ui_w_setlist_t s_sl = { .rows = s_rows, .count = N, .get = get, ... };
* count_cb -> ui_w_setlist_count(&s_sl)
* refresh -> ui_w_setlist_refresh(&s_sl, row, name, value)
* key_cb -> ui_w_setlist_key(&s_sl, key)
* draw_cb -> ui_w_setlist_draw(&s_sl, layer, clip)
* init_cb -> ui_w_setlist_reset(&s_sl)
*/
typedef struct {
const ui_w_setlist_row_t *rows; /* Flash 行表 */
uint16_t count; /* 数据行数(不含保存行) */
ui_w_setlist_get_fn get; /* 必填 */
ui_w_setlist_set_fn set; /* 必填(整定提交前的 RAM 副本写入口) */
ui_w_setlist_commit_fn commit; /* NULL = 查看视图(无保存行、禁编辑) */
ui_w_setlist_state_fn state; /* NULL = 保存行恒显示 ENTER */
ui_w_setlist_bad_fn bad; /* NULL = 不做越界行反显 */
ui_w_editor_t ed; /* 数值编辑实例 */
uint16_t ed_row; /* 编辑中行下标(仅 editing 时有效) */
} ui_w_setlist_t;
/*
* 函数功能:开页复位(清编辑态;接页面 init_cb)
* 入口参数:inst - 定值表实例 ui_w_setlist_t *
* 返回值:无
* 限定条件:无
*/
void ui_w_setlist_reset(ui_w_setlist_t *a_inst);
/*
* 函数功能:总行数(接框架 count_cb:数据行 + 保存行[仅整定视图])
* 入口参数:inst - 定值表实例 const ui_w_setlist_t *
* 返回值:总行数 uint16_t
* 限定条件:rows 非空(空表防御返回 0)
*/
uint16_t ui_w_setlist_count(const ui_w_setlist_t *a_inst);
/*
* 函数功能:逐行取数(接框架 refresh:名 = 行表、值 = 回调读/编辑器实时串/保存态)
* 入口参数:inst - 定值表实例 ui_w_setlist_t *
* row - 全局行下标 uint16_t
* name - 名输出缓冲(UI_BUF_STRLEN) char *
* value - 值输出缓冲(同上) char *
* 返回值:无
* 限定条件:页面打开(框架绘制链内调用)
* 函数说明:编辑中行的值列显示编辑器当前串(实时随 ↑↓ 变,同 net_cfg);
* 保存行(最后一行、整定视图)值 = ENTER/WAIT/OK/ERR(state 回调)
*/
void ui_w_setlist_refresh(ui_w_setlist_t *a_inst, uint16_t a_row,
char *a_name, char *a_value);
/*
* 函数功能:按键处理(接框架 key_cb;配合描述符 key_intercept=1 转发 LEFT)
* 入口参数:inst - 定值表实例 ui_w_setlist_t *
* key - LVGL 键值 lv_key_t
* 返回值:1 = 已消费(框架跳过内置);0 = 交回框架(↑↓ 移选、← 关页等)
* (键分发标志非错误通道,取 uint8_t——BSP 公开 API 约定)
* 限定条件:页面打开(内部经 ui_content_page_selected_row / is_editable 判态)
* 函数说明:1. 数值编辑中:↑↓ 步进 / ←→ 移位 / ENTER 提交(越界拒绝)全由
* ui_w_editor 消费;提交成功即经 set 回调写工作副本
* 2. 正常态 ENTER(可编辑权限):数值行进编辑(光标个位);
* 二态行循环切换;保存行投递整表提交(一次封存一次校验和,
* 整表提交口径见 页面补齐规划.md §3.2)
* 3. 只读权限 ENTER 一律不消费;ESC 恒关页(框架,未提交编辑丢弃,
* 已经 ENTER 提交到工作副本的调整保留、不落盘——net_cfg 先例)
*/
uint8_t ui_w_setlist_key(ui_w_setlist_t *a_inst, lv_key_t a_key);
/*
* 函数功能:自绘(接框架 draw_cb:编辑光标反显 + 保存失败越界行反显)
* 入口参数:inst - 定值表实例 ui_w_setlist_t *
* layer - 绘制层 lv_layer_t *
* clip - 重绘区 const lv_area_t *
* 返回值:无
* 限定条件:页面打开;框架内置区块(行/带/页脚)已绘完
* 函数说明:行槽 y 按标准列表骨架 + 当前页窗口换算(与框架 cp_draw_rows 同式:
* first = sel / UI_LIST_ROWS * UI_LIST_ROWS)
*/
void ui_w_setlist_draw(ui_w_setlist_t *a_inst, lv_layer_t *a_layer,
const lv_area_t *a_clip);
#ifdef __cplusplus
}
#endif
#endif /* UI_W_SETLIST_H */