refactor(panels): 平行数组合并为 std::vector<PanelRow>(消除错位与字段重载)
对应 Code_Review_Report §15.6 第 1 项(方案 B:有结构,无列视图)。
结构
- EdgePanelLayout 的 16 个平行 std::vector 合并为 std::vector<PanelRow> rows,
PanelRow 带 17 个具名成员:ref / header / nameRect / nameClose / triangle / check /
stats / levelTrack / levelValue / levelReset / iterTrack / iterValue / iterReset /
infoMaxInterval / infoMinInterval / intervalField / frequencyField。
- 唯一新增入口:AppendRow(ref, header, nameRect, triangle, check)(返回新行引用)与
AppendMarkerGroupRow(ref, nameRect, nameClose)(「自由标记」分组行)。
参数行/重采样行一律 layout.rows.back().xxx = … 赋值。
- 原 int rows(可见信号数)与新容器同名 ⇒ 改名 signalCount,并注明它与 rows.size()
在 MARK 面板里不相等(只有有固定点的信号才有行)。
消掉的两类问题
1. 某分支漏 push 一列 ⇒ 该列之后所有行读到别人的矩形(静默错位)。现在一行一次成型。
2. rowRefs 字段重载(列表式 = 行信号 / MARK = 分组信号,其余 12 列必须为空)。
现在每行自带 ref,语义由“填哪些字段”表达;不变式简化为语义断言
(每行必须有名称区;MARK 行不得带 header/check/stats/滑块/重采样字段)。
顺带清理
- 合并后 rowIndex < layout.rowXxx.size() 全部变成恒真,批量删除 50+ 处
(含 15 元组长度数组、? x : gd::RectF() 三元判空、if(...){extendRow(...)} 包裹)。
- 调试框与缓存键改为逐行遍历(新增字段只需在 PanelRow 与这两处循环各加一行)。
等价性证明(rowgeom 键名刻意保持不变,故可逐键比对)
old keys = 919, new keys = 965
仅存在于旧 = 0;已有键值变化 = 20(全部是 ".count":0 -> N)
仅存在于新 = 46(全部是新增列的 [NNN],值 0.00,0.00,0.00,0.00)
⇒ 逐行逐字段的真实几何零位移;7 个面板像素哈希(含 resample=2BFC74B3D9B3239C)逐项不变。
验证
- make release:零 warning;784,896 → 782,336 B(−2,560);make debug / make -C Tools 同样零 warning
- UnitTests:checks=260 failed=0 cases=19
- OffscreenChecks -all:7 检查 / 133 断言(上轮 127)全 PASS
- panels -mode compare:7 面板像素哈希逐项不变
- rowgeom -mode compare:965+7 键 0 差异;-data MF4-Record.MF4 时 1268+7 键 0 差异
- 读点:旧 243 处 layout.rowXxx[…] → 现 95 处 layout.rows[…](84 命中判定 / 11 绘制)
过程记录:清理恒真判空时曾用整段替换把「均值滤波」双滑块段误换成「弱峰」双滑块,
编译器报 brace 不平衡,用备份回滚后重做 —— 整段替换必须先精确读出上下文。
文档:Plan §十一、Progress 第 39 轮、Report §16、agent_mem 第 39 轮、Tools/README §4.1/§4.4
This commit is contained in:
1 parent
f07ac74988
commit
1463f9d3f8
11 files changed
+672
-591
No files matched your search
@@ -814,18 +814,28 @@ namespace jdi
|
||||
boxes.Add(layout.clipBuildButton, 3);
|
||||
boxes.Add(layout.clipDestructiveButton, 3);
|
||||
|
||||
boxes.AddAll(layout.rowChecks, 4);
|
||||
boxes.AddAll(layout.rowStats, 4);
|
||||
boxes.AddAll(layout.rowLevelTracks, 4);
|
||||
boxes.AddAll(layout.rowLevelValues, 4);
|
||||
boxes.AddAll(layout.rowIterTracks, 4);
|
||||
boxes.AddAll(layout.rowIterValues, 4);
|
||||
boxes.AddAll(layout.rowLevelResets, 4);
|
||||
boxes.AddAll(layout.rowIterResets, 4);
|
||||
boxes.AddAll(layout.rowNameRects, 4);
|
||||
boxes.AddAll(layout.rowNameCloses, 4);
|
||||
boxes.AddAll(layout.rowTriangles, 4);
|
||||
boxes.AddAll(layout.rowHeaders, 4);
|
||||
// ⚠️ 行内元素**逐行**登记(不再有"整个数组一起 AddAll"):
|
||||
// 一行的字段是一个整体,逐字段登记才不会漏(旧的 12 次 AddAll 里
|
||||
// 少写一行就是整整一列元素不显示调试框,且没有任何检查会发现)。
|
||||
for (const EdgePanelLayout::PanelRow& row : layout.rows)
|
||||
{
|
||||
boxes.Add(row.header, 3);
|
||||
boxes.Add(row.nameRect, 4);
|
||||
boxes.Add(row.nameClose, 4);
|
||||
boxes.Add(row.triangle, 4);
|
||||
boxes.Add(row.check, 4);
|
||||
boxes.Add(row.stats, 4);
|
||||
boxes.Add(row.levelTrack, 4);
|
||||
boxes.Add(row.levelValue, 4);
|
||||
boxes.Add(row.levelReset, 4);
|
||||
boxes.Add(row.iterTrack, 4);
|
||||
boxes.Add(row.iterValue, 4);
|
||||
boxes.Add(row.iterReset, 4);
|
||||
boxes.Add(row.infoMaxInterval, 4);
|
||||
boxes.Add(row.infoMinInterval, 4);
|
||||
boxes.Add(row.intervalField, 4);
|
||||
boxes.Add(row.frequencyField, 4);
|
||||
}
|
||||
|
||||
for (const EdgePanelLayout::MarkerGroup& group : layout.markerGroups)
|
||||
{
|
||||
@@ -4081,14 +4091,28 @@ namespace jdi
|
||||
mixRect(layout.opacityValue);
|
||||
mix(layout.collapsed ? 1ull : 0ull);
|
||||
mix(layout.markerHasEnumColumn ? 1ull : 0ull);
|
||||
mix(static_cast<std::uint64_t>(layout.rows));
|
||||
for (const gd::RectF& rect : layout.rowChecks)
|
||||
mix(static_cast<std::uint64_t>(layout.signalCount));
|
||||
// 行的几何**逐行混入**(旧实现按列分组混 12~16 次,漏一列就少一层敏感度,
|
||||
// 而且“哪些列入键”分散在四个地方)。现在一个 `PanelRow` 是一个整体,
|
||||
// 新增字段只需在 `PanelRow` 与这一个循环里各加一行。
|
||||
for (const EdgePanelLayout::PanelRow& row : layout.rows)
|
||||
{
|
||||
mixRect(rect);
|
||||
}
|
||||
for (const gd::RectF& rect : layout.rowStats)
|
||||
{
|
||||
mixRect(rect);
|
||||
mixRect(row.header);
|
||||
mixRect(row.nameRect);
|
||||
mixRect(row.nameClose);
|
||||
mixRect(row.triangle);
|
||||
mixRect(row.check);
|
||||
mixRect(row.stats);
|
||||
mixRect(row.levelTrack);
|
||||
mixRect(row.levelValue);
|
||||
mixRect(row.levelReset);
|
||||
mixRect(row.iterTrack);
|
||||
mixRect(row.iterValue);
|
||||
mixRect(row.iterReset);
|
||||
mixRect(row.infoMaxInterval);
|
||||
mixRect(row.infoMinInterval);
|
||||
mixRect(row.intervalField);
|
||||
mixRect(row.frequencyField);
|
||||
}
|
||||
// 「自由标记」:固定点行/名称 ✕ 的矩形、五列边界、表头/吸顶状态与每个固定点的身份 + 时刻都要入键。
|
||||
for (const EdgePanelLayout::MarkerRow& row : layout.markerRows)
|
||||
@@ -4097,14 +4121,6 @@ namespace jdi
|
||||
mixRect(row.close);
|
||||
mix(static_cast<std::uint64_t>(row.itemIndex + 2));
|
||||
}
|
||||
for (const gd::RectF& rect : layout.rowNameCloses)
|
||||
{
|
||||
mixRect(rect);
|
||||
}
|
||||
for (const gd::RectF& rect : layout.rowNameRects)
|
||||
{
|
||||
mixRect(rect);
|
||||
}
|
||||
for (const EdgePanelLayout::MarkerColumn& column : layout.markerColumns)
|
||||
{
|
||||
mixFloat(column.left);
|
||||
@@ -4150,8 +4166,9 @@ namespace jdi
|
||||
mix(bits);
|
||||
}
|
||||
}
|
||||
for (const SignalRef& ref : layout.rowRefs)
|
||||
for (const EdgePanelLayout::PanelRow& row : layout.rows)
|
||||
{
|
||||
const SignalRef& ref = row.ref;
|
||||
mix(ref.IsValid() ? 1ull : 0ull);
|
||||
mix(static_cast<std::uint64_t>(ref.groupIndex));
|
||||
mix(static_cast<std::uint64_t>(ref.signalIndex));
|
||||
@@ -4220,54 +4237,6 @@ namespace jdi
|
||||
}
|
||||
|
||||
|
||||
// 弱峰调整的滑块行矩形(每信号两行)。
|
||||
for (const gd::RectF& rect : layout.rowLevelTracks)
|
||||
{
|
||||
mixRect(rect);
|
||||
}
|
||||
for (const gd::RectF& rect : layout.rowIterTracks)
|
||||
{
|
||||
mixRect(rect);
|
||||
}
|
||||
for (const gd::RectF& rect : layout.rowIterValues)
|
||||
{
|
||||
mixRect(rect);
|
||||
}
|
||||
// 弱峰调整每行滑块右侧的复位按钮(悬停高亮依赖它的精确矩形)。
|
||||
for (const gd::RectF& rect : layout.rowLevelResets)
|
||||
{
|
||||
mixRect(rect);
|
||||
}
|
||||
for (const gd::RectF& rect : layout.rowIterResets)
|
||||
{
|
||||
mixRect(rect);
|
||||
}
|
||||
// 「均值滤波」:信号色叠底标题栏 / 展开三角 / 内容区滚动偏移都要入键
|
||||
//(滚动改变的是面板内部像素,位置与尺寸不变)。
|
||||
for (const gd::RectF& rect : layout.rowHeaders)
|
||||
{
|
||||
mixRect(rect);
|
||||
}
|
||||
for (const gd::RectF& rect : layout.rowTriangles)
|
||||
{
|
||||
mixRect(rect);
|
||||
}
|
||||
for (const gd::RectF& rect : layout.rowInfoMaxInterval)
|
||||
{
|
||||
mixRect(rect);
|
||||
}
|
||||
for (const gd::RectF& rect : layout.rowInfoMinInterval)
|
||||
{
|
||||
mixRect(rect);
|
||||
}
|
||||
for (const gd::RectF& rect : layout.rowIntervalField)
|
||||
{
|
||||
mixRect(rect);
|
||||
}
|
||||
for (const gd::RectF& rect : layout.rowFrequencyField)
|
||||
{
|
||||
mixRect(rect);
|
||||
}
|
||||
mixFloat(layout.scrollOffset);
|
||||
|
||||
// 鼠标落在面板内时,✕ / 复选框 / 滑块 / 底部按钮的悬停态都依赖精确坐标。
|
||||
|
||||
Reference in new issue
Block a user