refactor(panels): 面板静态特征收敛为唯一登记表 + 标记面板绘制分段(§17.6 第 1/2 项)

- 新增 pvdetail::PanelKindTraits + PanelTraitsOf(唯一 switch):标题 / 排版类别 /
  滚动字段 / 面板状态 / 功能开关同表登记;新增面板只改「枚举 + 一行」,
  -Wswitch 仍在唯一登记点生效。PanelTitle 改为「前缀 + rangeSuffix 标志」,
  不再依赖 switch(标题降级为数据,不再需要函数指针)。
- PaintPanelMarkerGroups(约 340 行)拆成 6 个具名函数,主函数只保留绘制顺序
  (普通分组栏 -> 条目 -> 表头 -> 吸顶栏 -> 滚动条 -> 透明度行);纯搬移、0 字节变化。
- 顺手修正该函数体遗留的多余缩进。

验证:release/debug/tools 零 warning;UnitTests 260/19;OffscreenChecks -all 7/133;
panels -mode compare 7 面板像素哈希逐项不变;rowgeom compare 965+7 / 1268+7 键 0 差异。
产物 781,824 -> 782,336 B(+512,全部来自登记表)。
This commit is contained in:
DeepSeek V4.1 Flash committed 2026-11-04 17:22:06 +08:00
1 parent a9f1563896
commit 0c26da07d2
8 files changed
+761 -453

No files matched your search

+62
View File
@@ -10814,3 +10814,65 @@ std::vector<PanelRowPlan> PlanListPanelRows(const Lane&, EdgePanelKind) const;
2. `PaintPanelMarkerGroups`(约 260 行)按"分组栏 / 表头 / 条目吸顶"再拆。
3. **体积按用户指示暂停投入**(等后续功能更新产生新冗余时再做)。
---
## 2026-11-04 第 41 轮(`Code_Review` 分支,收尾):面板登记表 + 标记面板绘制分段
> 本轮之后**代码审查进入收尾**(判定见 `Code_Review_Report.md` §18.3)。
> 代码:`Components/PlotView/{Inc,Src}`。判据 = `panels -mode compare` + `rowgeom -mode compare`。
### 1. ✅ **取代**第 35 / 40 轮的"新增面板只改三处"
**已作废**:旧规则「新增一种面板要在 `LanePanelScrollOf` / `PanelStyleOf` / `PanelTitle` 三处登记」。
**现行**:新增面板只改**两处** —— `EdgePanelKind` 加枚举值 + `pvdetail::PanelTraitsOf` 加一行。
```cpp
struct PanelKindTraits
{
PanelStyle style; // 排版类别 + 底部控件
const wchar_t* title = L""; // 标题**前缀**(数据,不是函数)
bool rangeSuffix = false; // 是否追加 EdgeRangeSuffix()
float Lane::*scroll = nullptr; // 内容滚动偏移
LanePanelState Lane::*panel = nullptr; // 面板 UI 状态
bool Lane::*enabled = nullptr; // 功能开关
};
inline constexpr PanelKindTraits PanelTraitsOf(EdgePanelKind kind); // **唯一** switch
```
五个消费者(`PanelStyleOf` / `PanelTitle` / `LanePanelScrollOf` / `LanePanelStateOf` /
`LanePanelEnabled`)全部退化成一行取值,**签名未变、调用点一处未动**。
`-Wswitch` 保护仍只在 `PanelTraitsOf` 这一处(不写 `default:`)。
⚠️ `PanelStyle` 必须用三个具名构造函数(`ListPanelStyle` / `CountTablePanelStyle` /
`MarkerPanelStyle`):表里写 6 个裸 bool,聚合顺序错一位就是"表格面板带按钮"这种隐形错误。
**"标题是函数"的解法**:把标题降级成数据(前缀 + `rangeSuffix` 标志),
`PanelTitle` 只做 `前缀 + (rangeSuffix ? EdgeRangeSuffix() : L"")`。
不要为此引入函数指针(等于把数据重新变成代码,新增面板又要写函数)。
### 2. ✅ `PaintPanelMarkerGroups` 拆成 6 个具名函数
`MeasureMarkerColumnWidths` / `PaintMarkerGroupBar` / `PaintMarkerColumnSeparators` /
`PaintMarkerRow` / `PaintMarkerTableHeader` / `PaintMarkerOpacityRow`;
`PaintPanelMarkerGroups` 现在**只负责绘制顺序**:
**普通分组栏 → 条目 → 表头 → 吸顶分组栏 → 滚动条 → 透明度行**
🔴 硬规则:**表头与吸顶分组栏必须画在条目之后**(否则向上滚动的条目会盖住它们)。
这条约束现在只出现在一个函数里,是唯一"看代码就能看全"的顺序约束;新增悬浮/吸顶元素
一律加在"条目之后"。
### 3. 本轮数字
* Release 781,824 → **782,336 B(+512)**,全部来自登记表(7 份 traits 记录进 `.rdata`);
**P40 拆分前后字节数完全相同** ⇒ 纯搬移。
* release / debug / tools 全零 warning;`UnitTests` 260/19;`OffscreenChecks -all` 7 检查 / 133 断言。
* `panels -mode compare` 7 面板像素哈希逐项不变;`rowgeom compare` 965+7 / 1268+7 键 0 差异。
* 行数:`PlotViewPanelPaint.cpp` 939 → 977;`PlotViewPanels.cpp` 1766 → 1758。
### 4. 审查收尾时确认的三条"别再试"
1. `EdgeScanFor` 状态查找哈希化:**+5,632 B** / 每轮省 ≈4.8 µs ⇒ 不做。
2. `EdgePanelLayoutFor` 表驱动化:1.9~2.5 µs/次(每帧 ≈30 µs)⇒ 不是热点。
3. gdtoa(≈33 KB):libstdc++ 的 `os_defines.h` 无条件
`#define __USE_MINGW_ANSI_STDIO 1` ⇒ 只要还用 `std::to_*string`(含浮点)就去不掉。