DeepSeek V4.1 Flash
|
ab19a6e72e
|
feat(UI): 显示布局边界(Android 风格)+ 工具栏设置菜单(齿轮)+ 三处可见收益优化
## 1. 新功能:齿轮按钮 -> 应用设置菜单 -> 显示布局边界
- ToolbarAction::SETTINGS 位于「导入文件」左侧;工具栏布局改为
「左侧固定簇(kLeftClusterCount = 2:齿轮 + 导入文件)+ 右侧按钮组」。
- 齿轮是矢量化绘制(8 齿 + 外环 + 轴孔,全部按 half 的比例推导),
不用字体字符「⚙」——该字符在不同回退字体里大小与基线不一致,会忽大忽小、垂直不居中。
UiButtonWidget 新增 UiButtonIcon(NONE / GEAR)与 SetIcon。
- MenuScope::APP_SETTINGS(新增)+ 设置菜单:HEADER「调试」+ 勾选切换项「显示布局边界」
(keepOpen:点击后菜单保持打开,勾选态由 UpdateItemLabel 回写)。
锚点取 Toolbar::ButtonRect(SETTINGS) 的控件实测矩形,宿主不再自己推算按钮几何。
## 2. 布局边界:基类给协议,组件自己上报
- UiComponent 新增 virtual PaintDebugBounds(g, scale),默认只画 Area()。
- Toolbar / TabBar 覆盖:跳过与区域重合的根控件,遍历 m_root->Children()(层级 1);
TabBar 另上报每个 ✕(层级 2)。
- SignalPanel 覆盖:表头 / 筛选框 / 列表 / 样式区(1)+ 滚动条、样式行、当前可见列表行(2)。
- PlotView 覆盖:每个 LaneVisual::rect(1);不上报随数据变化的瞬态几何(曲线/胶囊/提示)。
- UiWidget 新增 PaintDebugBounds(g, scale, depth) 递归整棵控件树 —— 已上树的控件零成本获得边界。
- 宿主 PaintLayoutBounds 补客户区外框、分隔条、打开的菜单/拾色器。
视觉与实现约束(Android「Show layout bounds」风):
- 只描边、不填充(几十个嵌套矩形叠加填充会把内容糊住);
- 层级配色 青蓝(2px) / 品红 / 琥珀 / 绿(1px);
- 线宽按设备像素固定(不乘 scale),临时 PixelOffsetModeNone + 关抗锯齿 + 整像素对齐,
保证 1px 就是 1px;
- ⚠️ 只在 Render 最后一步叠加,绝不进入任何位图缓存(PlotView 4 层缓存 / SignalPanel 行位图缓存),
否则关掉开关后线条会残留;
- ⚠️ fullFrame 并入 m_showLayoutBounds:开启时必须整帧回送,否则「只回送绘图区」的快路径
会让装饰区边界停在旧帧上。
## 3. 可见收益优化(行为不变)
- Toolbar::Layout:控件树改为按需重建(m_treeDirty),只在规格/字体/主题/缩放/动态文本
变化时重建。拖动面板分隔条时 Relayout 每帧调用一次 -> 不再每帧 10 次堆分配 + 8 次测量缓存失效。
- Toolbar::SetActionLabel:只写 m_labelOverrides(唯一权威)+ 置树脏,消除「覆盖表与控件文本
双写」可能不同步的问题。
- UiWidget::DispatchRedraw(event):新增;收敛 Toolbar / TabBar 里重复的
Dispatch(); return UiRectHasArea(TakeDirty());(TakeDirty 会清零,漏一次就把下一次真实变化
误判成「无变化」)。
## 4. 验证
- make release / make debug:零 error 零 warning;TargetCheck.exe 897,024 B(< 900 KB)。
- 新增离屏探针 .preflight/lbcheck:21 / 21 PASS
(齿轮在导入文件左侧/同高/更窄;开启后青蓝 24,930 px、品红 19,734 px;关闭后逐像素还原;
菜单 scope、锚定贴合按钮、宽度未被撑大、条目初始未勾选、点击翻转开关、菜单保持打开)。
- Tools/rendercheck:8 个场景的「工具栏带以下区域」哈希与改造前**逐一相同**
(证明改动像素被完全限制在工具栏带内);整帧哈希因新增按钮整体变化,属预期。
FUNC 断言 7 / 7 PASS。
- Tools/uicheck:69 passed / 0 failed。
## 5. 文档
Documents/UI_Refactor_Plan.md / UI_Refactor_Progress.md / UI_Refactor_Report.md 追加第六阶段;
Documents/agent_mem.md 同步变更日志与「2026-10-28 第八轮」硬约束与验证坑。
|
2026-10-28 15:46:45 +08:00 |
|
DeepSeek V4.1 Flash
|
0ec8055e95
|
重构(UI): 统一组件协议 + 去手写链路 + 大文件按职责拆分 + 代码审查 + 剥离 Tools
## 1. 新增 UiComponent 顶层组件协议(不是负优化)
Components/Shared/Inc/UiComponent.hpp:纯接口、无状态,8 个方法
SetScale / Layout / Area / Paint / HitTest / OnMouseLeave / IsEditing / QueryCursor。
Toolbar / TabBar / SignalPanel / PlotView 本来就各自拥有完全同名同签名的成员,
因此改造 = 加 override + 补 Area()(PlotView 另加一个非 const 的 QueryCursor 转发,
因为它自己的查询会惰性建立行缓存),实现代码零改动、静态派发、体积无增长。
刻意不把 UiWidget 当作它的基类:UiWidget 是"树节点"(父给尺寸、父下探脏区、
命中沿树链派发),而 PlotView(4 层位图缓存)/ SignalPanel(行位图缓存)是
"地盘宿主"。强行上树会推翻"父脏则子全脏"的前提,历史上正是这类耦合导致过
"后台渲染覆盖平移结果""命中矩形错位"的事故。头文件里已写明这条理由。
Toolbar/TabBar 是两者的交集:对外实现 UiComponent,对内持有一棵 UiWidget 树。
## 2. 宿主侧:四条手写链 -> 组件表
Application 新增 ComponentEntry{ component, target, chrome } 与 m_components
(底->顶:plot -> panel -> toolbar -> tabBar),BuildComponentTable() 装配一次。
- ApplyDpi 6 行逐个 SetScale -> 1 个循环
- Relayout 手算三列 x 坐标 -> UiStackRects(内容区, HORIZONTAL, {panelW, splitW, AUTO})
- WM_MOUSELEAVE 逐个 OnMouseLeave -> 循环累积 chromeChanged / plotChanged
- WM_SETCURSOR if/else if 链 -> 从表尾向前找首个命中者,取其 QueryCursor
顺带兑现历史缺口:UiLayout::UiStackRects 自引入以来第一次有了生产调用点。
有意保留显式的三条链(WM_LBUTTONDOWN / WM_LBUTTONUP / WM_MOUSEMOVE):它们各自带
组件专属后置动作(提交重命名、构建派生信号、面板联动滚动、更新拖拽光标、
plotOnlyMove 决定局部失效还是整帧失效)。塞进表里只能靠 lambda 字段,
可读性反而下降 —— 属于用户明确禁止的"过度抽象",因此不做。
## 3. 大文件按职责拆分(纯整函数搬移,逐像素 0 差异)
SignalPanelInteraction.cpp 2329 -> 831 行,拆出:
SignalPanelEdit.cpp 616 内联编辑(筛选框、组名/信号名、数值、颜色与透明度)
SignalPanelScroll.cpp 205 动画与滚动(折起、联动滚动、滚动到目标信号)
SignalPanelMenu.cpp 527 弹出菜单(系数/偏移、镜像、右键菜单与命令回执)
Shared/PopupMenu.cpp 1901 -> 706 行,拆出:
PopupMenuLayout.cpp 753 尺寸测量、项矩形排版、滚动可见性
PopupMenuPaint.cpp 397 背景/阴影/项绘制
Inc/PopupMenuInternal.hpp 103 pmdetail 常量 + inline 辅助(跨 TU 安全)
拆分判据是"职责"而非行数;共享常量一律收敛到 *Internal.hpp。
## 4. 代码审查(修 5 处)
- SignalPanelInteraction.cpp 头注释仍写"4 片",实际 6 片 -> 改为完整清单
- PopupMenuLayout.cpp 机械搬移时把构造函数一起搬走 -> 重复定义,只保留在交互分片
- PopupMenu.cpp 的 #include "PopupMenuInternal.hpp" 落进 namespace jdi 内 -> 移到文件头
- PopupMenuPaint.cpp 缺 UiControls.hpp(UiDrawEditFieldContent 未声明)-> 补 include
- 全仓复查历史删除符号残留引用(m_paintPlot / ClampCursorsAfterPan /
PaintFreeMarkerTooltip / CaptureDecorCache / FitSinglePointSignal / CsvTable /
DataFile / .preflight / structcheck)-> 零命中
## 5. Tools/ 剥离
git rm -r --cached Tools + .gitignore 新增 Tools/(本地文件保留,可随时复跑)。
ui_refactor 分支为全本地分支,另做 filter-branch 清除历史中的该目录。
## 6. 验证
- make release / make debug:零 error 零 warning
- rendercheck:A-H 八个场景哈希与改造前逐一相同
(A 2166933039626F66 B C444ECFEB18FD73D C 7984446D8E7A4418 D BF855879CA12F289
E 1C663E4118616016 F 0535292D8E07AE18 G 7A58172C46577729 H 23F390DD76141113)
FUNC 7/7 PASS
- uicheck:69 passed, 0 failed
- TargetCheck.exe 891,392 B(< 900 KB 阈值)
## 7. 文档
Documents/UI_Refactor_Plan.md / UI_Refactor_Progress.md / UI_Refactor_Report.md
新增第五阶段章节;Documents/agent_mem.md 同步变更日志与「第七轮」硬约束。
|
2026-10-28 14:35:32 +08:00 |
|
DeepSeek V4.1 Flash
|
4479aa52a5
|
UI 重构:其余计划项全部结案(附不采用理由),计划不再有悬空阶段
评估阶段最后的产物:把"能做但收益不成立"的项显式结案,而不是留成待办。
- Documents/UI_Refactor_Plan.md:P3 行改为「Toolbar/TabBar 已迁移;PopupMenu/ColorPicker/
SignalPanel 行经评估不采用」;P4 行改为「经评估不采用」。
- Documents/UI_Refactor_Report.md 第 7 节重写为「其余计划项的处理结论(均已结论,无悬空项)」,
逐项给出基于代码事实的理由:
* PopupMenu / ColorPicker:模态浮层每帧整体重画、命中是 <=20 行矩形线性扫描,
且已有单一 BuildLayout 同时产出绘制与命中矩形(已是同源几何)⇒ 控件树额外收益近零,
风险集中在子菜单悬停/内联编辑/滚动/拖拽钳制。
* SignalPanel 行:性能来自行位图缓存(PaintRowCached + RowCacheKey)与抽拉式折叠动画,
控件化会把缓存键与控件生命周期耦合,且"行高永不变、只平移"与通用布局模型冲突。
* 5 个浮动面板(P4):面板像素层已缓存到 0.3ms(全画 24~35ms)⇒ 控件化无帧时间收益;
几何已是单一纯函数(5 种面板共享);控件化需重写吸顶/滚动/滚动条/滑块复位/行悬停压暗,
回归面极大。
* 56 处 InvalidateRect 并集:InvalidatePlotRect() 已是按消息的批处理点,逐处替换只增间接层。
验证:make release 零警告;Tools/uicheck 69/69;Tools/rendercheck 7 条功能断言 PASS,退出码 0。
|
2026-10-28 12:47:01 +08:00 |
|
DeepSeek V4.1 Flash
|
47bb500954
|
UI 重构:文档按 M1/M2 里程碑划分,M1 标记为已验收
- Documents/UI_Refactor_Report.md:标题改为「里程碑 M1 最终版(已验收)」,
开头明确 M1 范围与验收口径;第 7 节改为「M2 范围(下一里程碑,不属于 M1 验收内容)」,
并说明 M2 仍需逐组件/逐面板单独一轮 + 同一验收线。
- Documents/UI_Refactor_Progress.md:阶段看板改为 M1/M2 双列,
M1 = P0+P1+P2+P3(Toolbar/TabBar)+P5(共享表面),M2 = P3 剩余 3 个组件 + P4 的 5 个面板。
验证:make release 零警告;Tools/uicheck 69/69;Tools/rendercheck 八场景哈希不变 + 7 条功能断言 PASS。
|
2026-10-28 12:45:31 +08:00 |
|
DeepSeek V4.1 Flash
|
0bb38a887e
|
UI 重构:关闭「脏区并集」计划项并记录评估结论
- Documents/UI_Refactor_Report.md §7:把「56 处 InvalidateRect 收敛为脏区并集」改为
**评估后不采用(计划项已关闭)**,理由基于代码事实:ApplicationInternal.hpp 的
InvalidatePlotRect() 已是「按消息一次回送」的批处理点,现状不存在同一消息多次回送;
逐处替换只会多一层间接调用,并把「回送必须有无条件 else」这条历史教训藏得更深。
真正需要脏区并集的是控件树接入之后(节点失效 → 根聚合),属下一里程碑前置。
- 同节把 PopupMenu / ColorPicker 的迁移说明改为「TabBar 已完成,这两者待做」并沿用同一验收线。
- Documents/UI_Refactor_Plan.md:P5 行同步标注该结论。
验证:make release 零警告;Tools/uicheck 69/69;8 场景像素哈希不变;
7 条功能断言(3 工具栏 + 4 标签栏)全 PASS。
|
2026-10-28 12:43:14 +08:00 |
|
DeepSeek V4.1 Flash
|
f242fb076c
|
UI 重构:文档纳入 TabBar 迁移(P3 完成 2/5)
- Documents/UI_Refactor_Progress.md:阶段看板 P3 标记为「Toolbar + TabBar 已完成」;
新增第 6 条提交记录(TabBar 新旧实现对照 + 手势语义未变的说明 + 8 场景哈希 + 4 条交互断言)。
- Documents/UI_Refactor_Report.md:交付表 P3 改为 2/5;关键数字(已迁移组件、产物 886,784 B);
提交清单加入 cd3a3fa;新增 5.1 节描述 TabBar 迁移与双轨验证。
验证:make release / make debug 零警告;Tools/uicheck 69/69;8 场景像素哈希与迁移前一致。
|
2026-10-28 12:42:31 +08:00 |
|
DeepSeek V4.1 Flash
|
c3b79a6d2c
|
UI 重构 P3(2):TabBar 迁移到控件树(逐像素 0 差异 + 4 条交互断言)
TabBar 的标签 / 「+」/ 覆盖层拆成控件,手势语义原样保留(自行判双击、3px 拖拽阈值、
关闭 ✕ 的「移开取消」、拖拽排序的 drop 位置),公开 API 未变:
- 新增(TabBar.cpp 内实现的内部控件)
* UiTabItemWidget:单格标签的绘制(底色/描边/激活指示条/文本或重命名输入框/关闭 ✕),
关闭按钮热区由基类的悬停点自行判定。
* UiAddWidget:「+」按钮绘制与悬停配色。
* UiOverlayWidget:命中透明的覆盖层,最后绘制「拖拽插入指示条 + 底部分隔线」
(必须晚于标签与「+」,否则会被它们压住)。
* UiTabRootWidget:只铺标签栏底色。
- TabBar 移除 m_hoverIndex / m_hoverClose / m_hoverAdd 三个手工下标,
改为 dispatch MOUSE_MOVE 后由 root->TakeDirty() 判断是否需要重绘。
- 绘制顺序保持:底色 → 各标签 → 「+」→ 拖拽指示条 → 底部分隔线(与旧实现逐像素一致)。
- UiWidget 新增 HoverPoint(x,y):派生控件据此自行判断「悬停在自身内部哪个热区」。
验证:
- 像素:8 场景哈希与迁移前逐一相同(A 2166933…、H 23F390D…)。
- 交互断言(全部 PASS):
* tabbar-hover-marks-dirty (1,0) —— 进入标签只标记一次脏区;
* tabbar-add-creates-tab (1 -> 2) —— 「+」新建标签;
* tabbar-click-selects-tab (active=0) —— 点击标签切换激活页;
* tabbar-close-removes-tab (2 -> 1) —— 点击 ✕ 关闭标签。
- Tools/uicheck 69 passed / 0 failed。
- make release / make debug 零警告;Target.exe 886,784 B(< 900KB)。
|
2026-10-28 12:41:57 +08:00 |
|
DeepSeek V4.1 Flash
|
c4faa930e2
|
UI 重构:生成里程碑最终报告,并在计划文档中标注阶段状态
- Documents/UI_Refactor_Report.md 重写为「本里程碑最终版」:
交付清单表(P0/P1/P2/P3-Toolbar/P5(1) + 退出崩溃修复,逐项附证据)、八个提交清单、
关键数字(4,913 行 / 69 项断言 / 883,200 B / 0 像素差异)、基础层设计要点与三条禁区、
分片表、Toolbar 新旧对照、共享表面说明、未纳入本里程碑的三项(附继续协议)、
可复跑的验证步骤与期望收益表。
- Documents/UI_Refactor_Plan.md:阶段表标注已完成的 P0/P1/P2、部分完成的 P3/P5。
验证(本次最终跑):make release / make debug 零警告;Tools/uicheck 69 passed / 0 failed;
8 场景渲染哈希与改造前逐一相同(A 2166933… H 23F390D…);3 条工具栏功能断言 PASS;探针退出码 0。
|
2026-10-28 12:37:44 +08:00 |
|
DeepSeek V4.1 Flash
|
4f3c88f398
|
UI 重构:文档更新为 P0-P3 + P5(1)(共享表面与退出崩溃修复)
- Documents/UI_Refactor_Progress.md:阶段看板标记 P5 部分完成;新增第 5 条提交记录
(UiSurface / top-down DIB / Shutdown 顺序修复 / Render 保护 / 69 项断言 / 8 场景哈希);
修正重复标题;「下一步」重写为 TabBar→菜单→面板→脏区并集。
- Documents/UI_Refactor_Report.md:标题与交付表纳入 P5(1);关键数字更新(69 项断言、
产物 883,200 B、共享 DIB);新增第 7 节描述共享表面与退出期崩溃修复;后续章节重编号。
验证:make release / make debug 零警告;Tools/uicheck 69/69;8 场景渲染哈希与改造前一致。
|
2026-10-28 12:35:39 +08:00 |
|
DeepSeek V4.1 Flash
|
9a9802e589
|
UI 重构:报告更新为 P0-P3(含 Toolbar 迁移),并补记框架裁剪约定变更
- Documents/UI_Refactor_Report.md:标题改为 P0/P1/P2/P3-Toolbar;新增第 6 节
「P3:Toolbar 迁移到控件树」(新旧实现对照表、UiButtonWidget、kUiClipBleed 约定、
8 场景像素哈希 + 3 条功能断言);关键数字更新(产物 881,664 B、已迁移 1 个组件);
重排后续章节编号(7 未做项 / 8 下一步 / 9 结论)。
- Documents/UI_Refactor_Progress.md:阶段看板标记 P3 为「Toolbar 已完成,其余待做」,
补第 4 条提交记录与新的「下一步」。
验证:make release / make debug 零警告;Tools/uicheck 62/62;Target.exe 881,664 B。
|
2026-10-28 12:29:59 +08:00 |
|
DeepSeek V4.1 Flash
|
7e1852c2d2
|
UI 重构:补充进度台账、阶段报告与共享记忆同步
- Documents/UI_Refactor_Progress.md 补齐 P2 续(PlotViewPanels.cpp)的完成状态、七个分片行数、
逐像素 A/B 哈希与"回退到旧文件做 A/B 时必须先删陈旧 .o"的复现要求。
- 新增 Documents/UI_Refactor_Report.md:第一阶段(P0/P1/P2)交付物、关键数字、
基础层契约、验证方式、过程中修掉的 4 个自身缺陷、明确未做项与下一步排序。
- Documents/agent_mem.md:§11.2 追加第 235-240 条(基础层位置与边界、只沿命中链派发、
Paint 三条契约、布局缓存纪律、PlotView 七分片硬约束、uicheck 回归网),
并在 §10 变更日志追加本阶段一行。
验证:make release / make debug 零警告;Tools/uicheck 62 passed / 0 failed;
Target.exe 877,568 B(< 900KB)。
|
2026-10-28 12:22:09 +08:00 |
|