feat(clip): 新增「选区截取」实验性功能 + 筛选态组复选框只作用于筛选结果 + 重采样统计不被省略
一、重采样面板统计信息不再被省略为 `…`
- 根因:EdgePanelWidth 里数值列按"典型样例"(1h 1min 2s(1.23456 GHz))估宽,
真实文本(16ms 182.614us(61.795 Hz))更长 => 绘制矩形不够宽 => 尾部被裁。
- 新增 FormatIntervalWithFrequency() 作为「间隔(频率)」文本的唯一实现,
宽度计算与绘制共用它;EdgePanelWidth 改为逐信号实测真实文本宽度取最大值。
二、筛选状态下组复选框只作用于「筛选出来的信号」
- TabConfig 新增 SetGroupVisibleSubset / GroupAllVisibleSubset / GroupHasVisibleSubset,
只读写掩码内元素,未通过筛选的信号可见性保持不变。
- SignalPanel::BuildFilterMask 提供逐信号掩码(未筛选时返回 false,走整组语义)。
- 组复选框的点击、绘制、行位图缓存键三处统一改用子集判定
(只改绘制不改缓存键会导致勾选后复选框不刷新)。
三、新增实验性功能「选区截取」(EdgePanelKind::CLIP = 6,PLOT_CMD_LANE_CLIP = 14)
- 菜单位置:实验性功能二级菜单,「重采样」之下、「自由标记」上方,带勾选。
- 面板:逐信号一行(信号色叠底条目栏 + 右侧复选框,不可展开),内容可滚动;
底部两个不滚动的按钮「截取为新信号」与「原始信号截取」;
未启用双光标时两个按钮为空矩形并给出提示。
- 截取为新信号:区间内原始数据(不烘焙)+ 继承源信号整套调整,
名称为 <源信号名> (AAAA - BBBB)(显示时刻、保留三位小数、带 s),插入源信号下方,
使用 AppendGroupAxis 新建的独立时间轴。
- 原始信号截取:DataSet::ClipSignalRange 就地裁剪时间轴与采样,
用新建+swap+shrink_to_fit 真正归还内存,并重算统计与轴的 minTime/maxTime/monotonic。
调用前先 PauseDerivedAsync() 避免后台派生读到已释放采样。
- 时间轴偏移参与区间比较:双光标是显示时刻(time+offsetTime),
BuildClippedSignal 比较时加偏移,ClipSignalInPlace 换算回采样时刻(low-offsetTime)。
- 同步点已全部补齐:LaneCarry(三处)/SplitLane/PruneLaneSignalItems/RemapAfterSignalInsert/
purgeRefs/PanelSlotKey/CollectDebugBoxes/SceneContentHash/kEdgePanelKinds/kOrder/
EdgePanelLayoutFor/EDGE_PANEL_MOVE/m_pendingPanelClose/MEAN_SCROLL/滚轮/悬停/
SetLanePanelCollapsed/LanePanelCollapsed/QueryCursor。
make release 零 warning,产物 860,160 B。
This commit is contained in:
1 parent
5d305cb10f
commit
62220477c0
18 files changed
+1263
-67
No files matched your search
@@ -669,6 +669,26 @@ namespace jdi
|
||||
bool InsertDerivedSignal(int groupIndex, int afterSignalIndex, SignalData&& signal,
|
||||
int& newSignalIndex);
|
||||
|
||||
/**
|
||||
* @brief **破坏性**截取一条信号:只保留 `[low, high]` 内的采样,其余立即释放。
|
||||
*
|
||||
* 用于「实验性功能 → 选区截取 → 原始信号截取」(用户 2026-11-03 明确要求):
|
||||
* * 同时裁剪该信号所属的**时间轴**(`axes[signal.axisIndex].time`)与采样值数组;
|
||||
* * 两者按下标一一对应,因此截取后仍保持对齐;
|
||||
* * 用「新建 + 交换 + `shrink_to_fit`」释放多余容量(`erase` 不会归还内存);
|
||||
* * 重算统计(min/max/finiteCount 与粗粒度包络层),并重建该轴的
|
||||
* `minTime/maxTime/finiteCount/monotonic`。
|
||||
*
|
||||
* ⚠️ 该操作**不可撤销**;区间内有效采样不足两个时返回 false 且不改动任何数据。
|
||||
*
|
||||
* @param [IN] groupIndex 分组下标。
|
||||
* @param [IN] signalIndex 信号下标。
|
||||
* @param [IN] low 保留区间左端(时间,秒)。
|
||||
* @param [IN] high 保留区间右端(时间,秒)。
|
||||
* @return 截取成功返回 true。
|
||||
*/
|
||||
bool ClipSignalRange(int groupIndex, int signalIndex, double low, double high);
|
||||
|
||||
/**
|
||||
* @brief 移除指定下标的分组,并立即释放其占用的全部采样内存。
|
||||
* @param [IN] groupIndex 分组下标。
|
||||
@@ -1248,6 +1268,51 @@ namespace jdi
|
||||
/** @brief 「重采样」面板内容的滚动偏移(客户区像素,0 = 顶部)。 */
|
||||
float resampleScroll = 0.0f;
|
||||
|
||||
/**
|
||||
* @brief 「选区截取」中某个信号是否为**处理目标**(面板条目栏右侧复选框)。
|
||||
*
|
||||
* 与其它实验性功能不同,这里不需要参数:截取区间固定来自**双光标**(`CursorTime` /
|
||||
* `CursorTimeAlt`),因此每个信号只记一个布尔标记。条目按 `Lane::signals` 顺序排列,
|
||||
* **不可展开/收起**(用户 2026-11-03 明确要求)。
|
||||
*/
|
||||
struct ClipItem
|
||||
{
|
||||
SignalRef ref; /**< 目标信号。 */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 「实验性功能 → 选区截取」开关。
|
||||
*
|
||||
* 开启后本网格出现浮动面板:逐信号一行(信号色叠底 + 右侧复选框),
|
||||
* 底部两个固定按钮「截取为新信号」与「原始信号截取」。
|
||||
* ⚠️ 该功能**必须配合双光标**使用,未开启双光标时面板给出提示、按钮不可用。
|
||||
*/
|
||||
bool clip = false;
|
||||
|
||||
/** @brief 参与选区截取的信号(只包含被勾选的信号)。 */
|
||||
std::vector<ClipItem> clipItems;
|
||||
|
||||
/** 取某个信号的选区截取标记(未勾选时返回空指针)。 */
|
||||
const ClipItem* FindClipItem(const SignalRef& ref) const;
|
||||
|
||||
/** 取得或创建某信号的选区截取标记(用于勾选)。 */
|
||||
ClipItem& EnsureClipItem(const SignalRef& ref);
|
||||
|
||||
/** 取消某信号的选区截取勾选。 */
|
||||
void RemoveClipItem(const SignalRef& ref);
|
||||
|
||||
/** 取某信号的选区截取勾选状态。 */
|
||||
bool ClipEnabled(const SignalRef& ref) const
|
||||
{
|
||||
return FindClipItem(ref) != nullptr;
|
||||
}
|
||||
|
||||
/** 选区截取浮动面板的 UI 状态(展开/折起 + 位置)。 */
|
||||
LanePanelState clipPanel;
|
||||
|
||||
/** @brief 「选区截取」面板内容的滚动偏移(客户区像素,0 = 顶部)。 */
|
||||
float clipScroll = 0.0f;
|
||||
|
||||
/**
|
||||
* @brief 「自由标记」面板里被**收起**的信号分组(点击分组栏切换)。
|
||||
*
|
||||
@@ -1508,6 +1573,35 @@ namespace jdi
|
||||
*/
|
||||
void SetGroupVisible(int groupIndex, bool visible);
|
||||
|
||||
/**
|
||||
* @brief 设置某分组内**子集**信号的可见性,并同步网格划分。
|
||||
*
|
||||
* 用于「筛选状态」下的组复选框(用户 2026-11-03 明确要求):
|
||||
* 筛选时组名前的复选框只对应**组内被筛选出来的那些信号**,
|
||||
* 因此全选/部分选择/未选都只作用于 `signalMask` 为 true 的元素,
|
||||
* 不会把未通过筛选的信号一起勾上或一起取消。
|
||||
*
|
||||
* @param [IN] groupIndex 分组下标。
|
||||
* @param [IN] signalMask 逐信号的目标状态(长度不足的部分视为"不参与",保持不变)。
|
||||
*/
|
||||
void SetGroupVisibleSubset(int groupIndex, const std::vector<bool>& signalMask);
|
||||
|
||||
/**
|
||||
* @brief 判断某分组的**子集**是否全部可见(用于筛选状态下的复选框显示)。
|
||||
* @param [IN] groupIndex 分组下标。
|
||||
* @param [IN] signalMask 参与判定的信号(长度不足的部分不参与)。
|
||||
* @return 参与判定的信号**全部**可见且至少有一条返回 true。
|
||||
*/
|
||||
bool GroupAllVisibleSubset(int groupIndex, const std::vector<bool>& signalMask) const;
|
||||
|
||||
/**
|
||||
* @brief 判断某分组的**子集**是否存在可见信号(用于筛选状态下的部分选择态)。
|
||||
* @param [IN] groupIndex 分组下标。
|
||||
* @param [IN] signalMask 参与判定的信号(长度不足的部分不参与)。
|
||||
* @return 参与判定的信号中至少有一条可见返回 true。
|
||||
*/
|
||||
bool GroupHasVisibleSubset(int groupIndex, const std::vector<bool>& signalMask) const;
|
||||
|
||||
/**
|
||||
* @brief 设置全部信号可见性,并同步网格划分。
|
||||
* @param [IN] visible 目标可见状态。
|
||||
|
||||
@@ -88,6 +88,7 @@ namespace jdi
|
||||
prune(lane.weakPeakItems);
|
||||
prune(lane.freeMarkerItems);
|
||||
prune(lane.resampleItems);
|
||||
prune(lane.clipItems);
|
||||
lane.freeMarkerCollapsedGroups.erase(
|
||||
std::remove_if(lane.freeMarkerCollapsedGroups.begin(), lane.freeMarkerCollapsedGroups.end(),
|
||||
[&inLane](const SignalRef& ref) { return !inLane(ref); }),
|
||||
@@ -146,6 +147,11 @@ namespace jdi
|
||||
std::vector<Lane::ResampleItem> resampleItems;
|
||||
LanePanelState resamplePanel;
|
||||
float resampleScroll = 0.0f;
|
||||
/** @brief 「选区截取」开关与逐信号目标标记(详见 `Lane::clip`)。 */
|
||||
bool clip = false;
|
||||
std::vector<Lane::ClipItem> clipItems;
|
||||
LanePanelState clipPanel;
|
||||
float clipScroll = 0.0f;
|
||||
/** @brief 「均值滤波」面板内容的滚动偏移(详见 `Lane::meanFilterScroll`)。 */
|
||||
float meanFilterScroll = 0.0f;
|
||||
/** @brief 「中心轴边沿计数」面板内容的滚动偏移(详见 `Lane::edgeCenterScroll`)。 */
|
||||
@@ -209,6 +215,10 @@ namespace jdi
|
||||
carry.resampleItems = lane.resampleItems;
|
||||
carry.resamplePanel = lane.resamplePanel;
|
||||
carry.resampleScroll = lane.resampleScroll;
|
||||
carry.clip = lane.clip;
|
||||
carry.clipItems = lane.clipItems;
|
||||
carry.clipPanel = lane.clipPanel;
|
||||
carry.clipScroll = lane.clipScroll;
|
||||
for (std::size_t signalIndex = 0; signalIndex < lane.signals.size(); ++signalIndex)
|
||||
{
|
||||
LaneCarry entry = carry;
|
||||
@@ -288,6 +298,13 @@ namespace jdi
|
||||
lane.resamplePanel.x = carry.resamplePanel.x;
|
||||
lane.resamplePanel.y = carry.resamplePanel.y;
|
||||
lane.resampleScroll = carry.resampleScroll;
|
||||
lane.clip = carry.clip;
|
||||
lane.clipItems = carry.clipItems;
|
||||
lane.clipPanel.open = carry.clipPanel.open;
|
||||
lane.clipPanel.collapsed = carry.clipPanel.collapsed;
|
||||
lane.clipPanel.x = carry.clipPanel.x;
|
||||
lane.clipPanel.y = carry.clipPanel.y;
|
||||
lane.clipScroll = carry.clipScroll;
|
||||
};
|
||||
|
||||
// 收集全部可见信号引用。
|
||||
|
||||
Reference in new issue
Block a user