refactor(plotview): 面板状态/滚动量收敛为唯一派发点,消除 20+ 处手写分支
问题:`Lane` 里 7 种实验性功能各自持有一份 `LanePanelState` 与滚动偏移(共 14 个字段)。 旧实现在每个需要“按种类取用”的地方各写一遍多层嵌套三元式或 switch: - EdgePanelLayoutFor 的 enabled / open / collapsed / storedX / storedY 共 5 条 7 层嵌套三元式(历史上多次因多/少一个右括号编译失败); - 标题栏拖拽、✕ 关闭、滚轮翻页、滚动条拖动、错开序数统计各自再写一遍。 新增一种面板要改 20+ 处,漏一处就是「面板拖不动 / 关不掉 / 滚轮滚不到底」 (MARK、RESAMPLE、CLIP 三种面板都真实踩过)。 改法(PlotViewInternal.hpp 新增唯一派发点): - LanePanelEnabled(lane, kind) - LanePanelStateOf(lane, kind) 可写/只读 - LanePanelScrollOf(lane, kind) 可写/只读 这些 switch **穷举全部 7 种且不写 default**,因此 -Wswitch(属 -Wall)会在新增 EdgePanelKind 而漏登记时直接报警 —— 已用最小程序验证 -Wswitch 确实会报。 调用点改造: - EdgePanelLayoutFor:5 条嵌套三元式 -> 3 行访问器调用;局部 kOrder[] -> kEdgePanelKinds。 - 标题栏拖拽:整个 7 分支 switch -> 一次访问器写入。 - 滚轮翻页:current 的三元式链 -> LanePanelScrollOf;switch 补全 MEAN/MARK 并去掉 default。 - 滚动条拖动:switch 补全 MEAN/MARK 并去掉 default。 - ✕ 关闭:去掉 `case COUNT: default:` 的兜底,改为穷举。 - SetLanePanelCollapsed / LanePanelCollapsed:两个 switch -> 一次访问器。 - 滚轮“是否可滚面板”的 kind 列举改为 `hoveredKind != MARK`。 验证:release / debug 全量编译零 warning;产物大小不变(793,088 B,逻辑等价)。
This commit is contained in:
1 parent
94fc1c45da
commit
7a3fefb9c2
5 files changed
+173
-181
No files matched your search
@@ -1736,42 +1736,12 @@ namespace jdi
|
||||
top = std::max(m_plotRect.Y + 2.0f * m_scale,
|
||||
std::min(top, m_plotRect.Y + m_plotRect.Height - panel.Height - 2.0f * m_scale));
|
||||
Lane& lane = m_tab->Lanes()[static_cast<std::size_t>(m_edgePanelDragLane)];
|
||||
switch (m_edgePanelDragKind)
|
||||
{
|
||||
case EdgePanelKind::CENTER:
|
||||
lane.edgeCenterPanel.x = left;
|
||||
lane.edgeCenterPanel.y = top;
|
||||
break;
|
||||
case EdgePanelKind::MEAN:
|
||||
lane.meanFilterPanel.x = left;
|
||||
lane.meanFilterPanel.y = top;
|
||||
break;
|
||||
case EdgePanelKind::PEAK:
|
||||
lane.weakPeakPanel.x = left;
|
||||
lane.weakPeakPanel.y = top;
|
||||
break;
|
||||
case EdgePanelKind::MARK:
|
||||
// ⚠️ 漏掉这一支会让「自由标记」面板**拖不动**(位置写进了 edgePanel,
|
||||
// 下一帧又从 freeMarkerPanel 读到旧值 ⇒ 面板纹丝不动)。
|
||||
lane.freeMarkerPanel.x = left;
|
||||
lane.freeMarkerPanel.y = top;
|
||||
break;
|
||||
case EdgePanelKind::RESAMPLE:
|
||||
// ⚠️ 同类缺陷:漏掉这一支会让「重采样」面板**拖不动**(用户 2026-11-03 报告)。
|
||||
// 位置必须写进它自己的 `resamplePanel`,布局也只从那里读。
|
||||
lane.resamplePanel.x = left;
|
||||
lane.resamplePanel.y = top;
|
||||
break;
|
||||
case EdgePanelKind::CLIP:
|
||||
lane.clipPanel.x = left;
|
||||
lane.clipPanel.y = top;
|
||||
break;
|
||||
case EdgePanelKind::COUNT:
|
||||
default:
|
||||
lane.edgePanel.x = left;
|
||||
lane.edgePanel.y = top;
|
||||
break;
|
||||
}
|
||||
// ⚠️ 面板位置必须写进**它自己的** `LanePanelState`(见 `LanePanelStateOf` 的说明):
|
||||
// 漏写会让面板“纹丝不动”(位置写进别的面板、布局又从自己那里读)。
|
||||
// 历史上 `MARK` 与 `RESAMPLE` 都踩过这个坑,因此这里只保留唯一派发点。
|
||||
LanePanelState& dragState = LanePanelStateOf(lane, m_edgePanelDragKind);
|
||||
dragState.x = left;
|
||||
dragState.y = top;
|
||||
m_dragMoved = true;
|
||||
return true;
|
||||
}
|
||||
@@ -1850,6 +1820,9 @@ namespace jdi
|
||||
const float ratio = (thumbTop - layout.scrollTrack.Y) / travel;
|
||||
const float target = ratio * maxScroll;
|
||||
bool scrolled = false;
|
||||
// ⚠️ 穷举所有面板种类且**不写 `default:`**:将来新增面板而忘登记时,
|
||||
// `-Wswitch`(属 `-Wall`)会直接报错,而不是静默落到其它面板上。
|
||||
// (「自由标记」在上面的独立分支处理,不会到达这里。)
|
||||
switch (m_meanDragKind)
|
||||
{
|
||||
case EdgePanelKind::COUNT:
|
||||
@@ -1858,18 +1831,20 @@ namespace jdi
|
||||
case EdgePanelKind::CENTER:
|
||||
scrolled = SetLaneEdgeCenterScroll(m_markerScrollDragLane, target);
|
||||
break;
|
||||
case EdgePanelKind::MEAN:
|
||||
scrolled = SetLaneMeanFilterScroll(m_markerScrollDragLane, target);
|
||||
break;
|
||||
case EdgePanelKind::PEAK:
|
||||
scrolled = SetLaneWeakPeakScroll(m_markerScrollDragLane, target);
|
||||
break;
|
||||
case EdgePanelKind::MARK:
|
||||
break;
|
||||
case EdgePanelKind::RESAMPLE:
|
||||
scrolled = SetLaneResampleScroll(m_markerScrollDragLane, target);
|
||||
break;
|
||||
case EdgePanelKind::CLIP:
|
||||
scrolled = SetLaneClipScroll(m_markerScrollDragLane, target);
|
||||
break;
|
||||
default:
|
||||
scrolled = SetLaneMeanFilterScroll(m_markerScrollDragLane, target);
|
||||
break;
|
||||
}
|
||||
if (scrolled)
|
||||
{
|
||||
@@ -3419,8 +3394,12 @@ namespace jdi
|
||||
if (layout.close.Width > 0.0f &&
|
||||
UiPointInRect(layout.close, static_cast<float>(x), static_cast<float>(y)))
|
||||
{
|
||||
// ⚠️ 穷举所有面板种类且**不写 `default:`**(理由同上:漏登记时编译器报警)。
|
||||
switch (kind)
|
||||
{
|
||||
case EdgePanelKind::COUNT:
|
||||
SetLaneEdgeCount(lane, false);
|
||||
break;
|
||||
case EdgePanelKind::CENTER:
|
||||
SetLaneEdgeCenterCount(lane, false);
|
||||
break;
|
||||
@@ -3434,17 +3413,11 @@ namespace jdi
|
||||
SetLaneFreeMarker(lane, false);
|
||||
break;
|
||||
case EdgePanelKind::RESAMPLE:
|
||||
// ⚠️ 漏掉这一支时 ✕ 点了没反应(落进 `default` 关掉的是「边沿计数」),
|
||||
// 用户只能改走右键菜单取消功能(用户 2026-11-03 报告)。
|
||||
SetLaneResample(lane, false);
|
||||
break;
|
||||
case EdgePanelKind::CLIP:
|
||||
SetLaneClip(lane, false);
|
||||
break;
|
||||
case EdgePanelKind::COUNT:
|
||||
default:
|
||||
SetLaneEdgeCount(lane, false);
|
||||
break;
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
@@ -3569,11 +3542,11 @@ namespace jdi
|
||||
panelLane, panelKind))
|
||||
{
|
||||
const EdgePanelKind hoveredKind = static_cast<EdgePanelKind>(panelKind);
|
||||
// 「均值滤波 / 中心轴边沿计数 / 弱峰调整 / 边沿计数」面板:内容区超高时用滚轮翻页
|
||||
//(上百个信号合并时必备)。
|
||||
if (hoveredKind == EdgePanelKind::MEAN || hoveredKind == EdgePanelKind::CENTER ||
|
||||
hoveredKind == EdgePanelKind::PEAK || hoveredKind == EdgePanelKind::COUNT ||
|
||||
hoveredKind == EdgePanelKind::RESAMPLE || hoveredKind == EdgePanelKind::CLIP)
|
||||
// 「均值滤波 / 中心轴边沿计数 / 弱峰调整 / 边沿计数 / 重采样 / 选区截取」面板:
|
||||
// 内容区超高时用滚轮翻页(上百个信号合并时必备)。
|
||||
// ⚠️ 除「自由标记」外的所有面板都走这一条(它有自己的独立分支,见下)——
|
||||
// 写成“逐个列举 kind”会让新增面板默默失去滚轮(历史踩过)。
|
||||
if (hoveredKind != EdgePanelKind::MARK)
|
||||
{
|
||||
const EdgePanelLayout layout = EdgePanelLayoutFor(panelLane, hoveredKind);
|
||||
if (layout.content.Width > 0.0f &&
|
||||
@@ -3586,17 +3559,11 @@ namespace jdi
|
||||
{
|
||||
const Lane& wheelLane =
|
||||
Tab().Lanes()[static_cast<std::size_t>(panelLane)];
|
||||
const float current = (hoveredKind == EdgePanelKind::CENTER)
|
||||
? wheelLane.edgeCenterScroll
|
||||
: (hoveredKind == EdgePanelKind::PEAK)
|
||||
? wheelLane.weakPeakScroll
|
||||
: (hoveredKind == EdgePanelKind::COUNT)
|
||||
? wheelLane.edgeCountScroll
|
||||
: (hoveredKind == EdgePanelKind::RESAMPLE)
|
||||
? wheelLane.resampleScroll
|
||||
: (hoveredKind == EdgePanelKind::CLIP)
|
||||
? wheelLane.clipScroll
|
||||
: wheelLane.meanFilterScroll;
|
||||
// ⚠️ 读取当前滚动量必须按**同一种分派规则**(`LanePanelScrollOf`):
|
||||
// 旧实现这里是一条三元式链,漏掉新面板时会退化成
|
||||
// `meanFilterScroll`(恒 0)⇒ 每次滚轮都从 0 开始算、
|
||||
// 永远滚不到底(用户 2026-11-03 报告「选区截取」的正是这一处)。
|
||||
const float current = LanePanelScrollOf(wheelLane, hoveredKind);
|
||||
const float next = current - static_cast<float>(notches * 40.0 * m_scale);
|
||||
const float target = std::max(0.0f, std::min(next, maxScroll));
|
||||
switch (hoveredKind)
|
||||
@@ -3616,9 +3583,12 @@ namespace jdi
|
||||
case EdgePanelKind::CLIP:
|
||||
SetLaneClipScroll(panelLane, target);
|
||||
break;
|
||||
default:
|
||||
case EdgePanelKind::MEAN:
|
||||
SetLaneMeanFilterScroll(panelLane, target);
|
||||
break;
|
||||
case EdgePanelKind::MARK:
|
||||
// 「自由标记」由下面的独立分支处理(它的内容高度来自布局)。
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user