review(panels+size): 面板结构收敛收尾、审查清理、新增平行数组护栏
一、审查清理 * `PlotView::FreeMarkerValue` 的 `const Lane&` 形参从未使用(函数体里只有一句 `(void)lane;`)⇒ 删除形参与该语句,更新 2 个调用点。 * `EdgePanelLayoutFor` 里「选区截取是否就绪(双光标)」算了 3 遍 ⇒ 收敛为函数顶部 一次 `clipReady`。它同时决定面板高度 footer、条目行可见性、按钮几何, 三处各算一遍时只要有一处条件写错,就是"底部多一段空白"或"没双光标却能滚动"。 二、新增护栏(离屏检查) * `panels`:新增「平行数组长度一致」不变式 —— `EdgePanelLayout` 的 13 个按行平行 vector 必须与行数一致;4 个「重采样」专属数组允许为空、非空则必须对齐。 这是"某列读到别人矩形"这类错位缺陷的唯一低成本护栏(O(1))。 * `panelscroll`:同样加一份(大文件、566 行时才会暴露的问题)。 * `panels` 输出增加 rows 数,便于定位。 三、文档 * `Documents/Code_Review_Plan.md` 新增 §七(第 35 轮节点与硬约束)。 * `Documents/Code_Review_Progress.md` 新增第 35 轮(面板架构评估 + 三次重构记录)。 * `Documents/Code_Review_Report.md` 新增 §12(评估结论 + gdtoa 最终结论 + 护栏价值)。 * `Documents/agent_mem.md` 新增第 35 轮六条规则。 * `Tools/README.md`:补 `panelscroll`、`integer_replacement_matches_std`, 断言数更新为 260 / 108,最小集表补充面板相关条目。 验证: * `make release`(删 .o 全量)零 error / 零 warning,产物 **786,944 B**。 * `make -C Tools` 零 error / 零 warning。 * `UnitTests` → checks=260 failed=0 cases=19。 * `OffscreenChecks -all` → 6/6 检查 PASS,checks=108 failed=0。 * `panels -mode compare` → 7 个面板像素哈希与几何逐项不变。
This commit is contained in:
1 parent
34365b3c1c
commit
b58b427f62
8 files changed
+408
-15
No files matched your search
@@ -241,3 +241,109 @@ Makefile 按目录通配收集源文件,**无需登记新文件**。
|
||||
| `Tools/UnitTests/Build/UnitTests.exe` | `checks=219 failed=0 cases=18` |
|
||||
| `Tools/OffscreenChecks/Build/OffscreenChecks.exe -all` | 5 个检查全 PASS,`checks=71 failed=0` |
|
||||
| Release 产物 | **788,480 B**(与第 33 轮末一致;T4/T6 均回退) |
|
||||
|
||||
---
|
||||
|
||||
## 第 35 轮(2026-11-04):浮动面板架构评估 + 收敛 + 整数格式化
|
||||
|
||||
### 评估:浮动面板 / 二级菜单 / 右键菜单算不算"公共组件"?
|
||||
|
||||
先回答用户的问题(结论来自读码,不是印象):
|
||||
|
||||
| 对象 | 现状 | 是否已是"公共组件" |
|
||||
| --- | --- | --- |
|
||||
| **右键菜单 / 二级菜单** | `Components/Shared/PopupMenu`(+ `Layout` / `Paint` 两分片) | **是**。同一份实现服务绘图区网格菜单、信号菜单、分组菜单、标签页菜单、工具栏设置菜单;新增菜单只需描述条目数组 |
|
||||
| **拾色器** | `Components/Shared/ColorPickerPopup` | **是**。独立的浮层组件,自带编辑框/滑块/色域/命中 |
|
||||
| **实验室功能浮动面板** | 全部在 `PlotView` 内部(`EdgePanelLayoutFor` 算几何 + `PaintEdgeCursor` 画 + `OnLButtonDown/Move/Up` 命中),**共用一份"面板骨架"**(标题栏 = 折起三角 + GX 徽标 + 标题 + ✕、可滚动内容区 + 滚动条、底部按钮行) | **骨架是公共的,但"按种类分支"的代码被抄了多份** |
|
||||
|
||||
**为什么不把面板做成 `UiWidget` 树节点(像 PopupMenu 那样)?**
|
||||
三条硬约束决定了成本远大于收益:
|
||||
1. 面板的**像素**要进 `m_panelDc` 图层缓存(键 = `PanelGlobalKey ⊕ PanelSlotKey`),
|
||||
而 `UiWidget` 有自己的 dirty/capture 体系,两套缓存叠加会互相失效(历史教训:
|
||||
`SignalPanel` 行位图缓存与控件树就被刻意分开维护)。
|
||||
2. 面板几何**必须**由 `EdgePanelLayoutFor` 唯一给出(绘制 / 命中 / 光标 / 调试盒 / 缓存键
|
||||
五处共用),改成控件树就要把这套"几何同源"拆掉。
|
||||
3. 面板绘制要往 `m_panelDc` 里 `BitBlt` 抓像素、要 `AddOccluder` 挖洞、要按 `m_panelOrder`
|
||||
逐层设置文本层号 —— 这些都是 `PlotView` 的内部协议。
|
||||
|
||||
⇒ **正确的公共化方向是把"按种类分支"收敛成唯一派发点,而不是把面板搬进控件树。**
|
||||
|
||||
### P20 面板「特征层」(提交 `abcf3e6`)
|
||||
|
||||
审计出同一套"按种类分支"被抄了多份:
|
||||
|
||||
| 重复项 | 位置 | 份数 |
|
||||
| --- | --- | --- |
|
||||
| 分类布尔量(`listStyle` / `countTable` / `hasButton` …) | `EdgePanelWidth` / `EdgePanelLayoutFor` / `PaintEdgeCursor` | 3 |
|
||||
| 滚动条几何 + 滚动量夹取 | 布局里表格 / 列表 / 自由标记三分支 | 3 |
|
||||
| 滚动条绘制(6 行) | 绘制里同样三分支 | 3 |
|
||||
| `SetLane*Scroll` 实现 | `PlotViewFeatures.cpp` | 7 |
|
||||
| 按种类转发滚动写入 | 滚轮 / 拖滚动条 | 2 |
|
||||
| 标题文本 | `EdgePanelWidth` / `PaintEdgeCursor` | 2(**内容还不一致**) |
|
||||
|
||||
新增 `pvdetail::PanelStyle` + `PanelStyleOf(kind)`、`PanelScrollMetricsFor(...)`、
|
||||
`PlotView::PanelTitle(kind)`,并让上面全部调用点改成读它们。
|
||||
**顺带修掉一处潜伏错误**:`EdgePanelWidth` 的标题链漏了 MARK/CLIP(按"边沿计数"量宽)。
|
||||
|
||||
⚠️ 过程中踩到并修掉一个真实回归:把 `hasButton` 直接映射到 `PanelStyle::buildButton` 后,
|
||||
「选区截取」的底部按钮行高归零 ⇒ 面板高度 124 → 87 px。像素基线**当场报 MISMATCH**。
|
||||
修正方式:区分 `footerButtons()`(有按钮行)与 `buildButton`(是"构建为新信号")。
|
||||
|
||||
### P21 滚动收敛(提交 `abcf3e6`)
|
||||
|
||||
* 7 个 `SetLane*Scroll` → 一行转发到新的 `SetLanePanelScroll(laneIndex, kind, scroll)`。
|
||||
* 滚轮 / 拖滚动条两条 `switch`/`if` 链 → 直接调它(**读与写从此同一个入口**)。
|
||||
* `EdgePanelLayoutFor` 里 5 层滚动量三元式 → `LanePanelScrollOf(lane, kind)`
|
||||
(该派发点第 33 轮就存在,布局一直没用它)。
|
||||
|
||||
新增离屏检查 `panelscroll`:7 种面板逐一验证"滚到底 / 滚回顶 / 夹取 / 内容区不动 /
|
||||
不可滚动时无滚动条"。用 `MF4-Record.MF4`(566 信号并入同一网格)实测 **6/7 可滚**
|
||||
(自由标记无固定点,不可滚是正确行为)。
|
||||
|
||||
### P22 整数格式化替换(提交 `34365b3`)
|
||||
|
||||
* 新增 `Utf8Util::FormatInteger` / `FormatIntegerUnsigned` / `FormatIntegerNarrow`
|
||||
(手写十进制展开,不经 printf)。
|
||||
* 全仓替换 **76 处** `std::to_wstring` + **2 处** `std::to_string`(20 个文件);
|
||||
`MatLoader::TrimNumber` 的整数分支也改(它曾是最后一个引用 MinGW printf 的点)。
|
||||
* **实测:−1,024 B**(787,968 → 786,944)。
|
||||
* ⚠️ **gdtoa 那条 ≈33 KB 的链仍然去不掉**,原因已定位到具体文件行:
|
||||
libstdc++ 的 `x86_64-w64-mingw32/bits/os_defines.h` **无条件**
|
||||
`#undef __USE_MINGW_ANSI_STDIO` + `#define … 1`("libstdc++ depends on POSIX-definitions"),
|
||||
`g++ -E -dM` 实测最终值恒为 1 ⇒ 任何 C++ TU 的 `swprintf`/`strtod` 必然是 MinGW 版本。
|
||||
叠加 `-D__USE_MINGW_ANSI_STDIO=0` 实测 **0 字节**收益,已回退并在 Makefile 留下结论。
|
||||
要真省这 33 KB 只能自己重写「浮点 → 十进制(正确舍入)」与浮点解析的特殊分支 ⇒ **不做**。
|
||||
|
||||
### P23 其余审查清理
|
||||
|
||||
* `PlotView::FreeMarkerValue` 的 `const Lane&` 形参从未使用(函数体里只有一句 `(void)lane;`)
|
||||
⇒ 删除形参与该语句,更新 2 个调用点。
|
||||
* 「选区截取是否就绪(双光标)」在布局里算了 3 遍 ⇒ 收敛到函数顶部一次
|
||||
(它同时决定面板高度 footer、条目行、按钮几何,写错任一处就是"底部多一段空白"或"没双光标却能滚动")。
|
||||
|
||||
### 本轮验证
|
||||
|
||||
| 项 | 结果 |
|
||||
| --- | --- |
|
||||
| `make release`(删 `.o` 全量) | 零 error / 零 warning;产物 **786,944 B**(起点 787,968,−1,024) |
|
||||
| `make -C Tools` | 零 error / 零 warning |
|
||||
| `UnitTests` | `checks=260 failed=0 cases=19`(新增 `integer_replacement_matches_std`,41 条断言) |
|
||||
| `OffscreenChecks -all` | 6 个检查全 PASS,`checks=87 failed=0`(新增 `panelscroll`) |
|
||||
| `panels -mode compare` | 7 个面板**像素哈希 + 几何逐项不变**(三次重构全程守住) |
|
||||
| `panelscroll`(MF4,566 信号) | 6/7 面板可滚,夹取与滑块位置全部符合预期 |
|
||||
|
||||
### 下一步建议(面板方向)
|
||||
|
||||
1. **`EdgePanelLayout` 的平行数组**:`rowHeaders` / `rowNameRects` / `rowTriangles` /
|
||||
`rowChecks` / `rowPoints` / `rowIterations` / `rowStats` / `rowLevel*` / `rowIter*` /
|
||||
`rowInfo*` / `rowIntervalField` / `rowFrequencyField` 共 17 个按行平行的 `vector`,
|
||||
全仓引用 **314 处**。每加一种参数行都必须在每个分支里按**同一顺序** push 恰好 17 项,
|
||||
漏一项 = 某列读到别人的矩形(这正是"改布局就出错"的机制)。
|
||||
建议合并为 `struct PanelRow { … }` + `std::vector<PanelRow> rows`。
|
||||
**本轮未做**:314 处引用、风险高,需要先补"逐行几何基线"检查。
|
||||
2. **`PaintEdgeCursor` 拆分**:该函数约 1600 行,其中三段"内容绘制"(表格 / 列表 / 自由标记)
|
||||
各 90–450 行,可机械提取为 3 个成员函数(`PaintPanelCountTableRows` /
|
||||
`PaintPanelListRows` / `PaintPanelMarkerGroups`)。判据:`panels -mode compare` 全绿。
|
||||
**本轮未做**:与 P22 抢时间,且属纯可读性收益。
|
||||
3. **给平行数组补检查**:在 `panels` 里增加"每个 row 的 17 项长度一致"断言
|
||||
(成本极低,可作为第 1 项的前置护栏)—— 已记入待办。
|
||||
Reference in new issue
Block a user