fix(ui): 选区截取面板空白真正根因、拖拽指示线层序、新建分组修复、避让动画更顺
一、选区截取面板「条目区与按钮之间的空白」(连续三轮未修好的那个) 根因不是内容区几何,而是**底部固定区高度算了两行**:footerHeight 用 `buttonHeight * 2 + 6 + pad` 预留,而布局把「截取为新信号 / 原始信号截取」 两个按钮并排画在同一行 ⇒ 内容区下边界与按钮上边界之间空出一整行。 改为按一行算(两处:高度算式分支 + 布局几何分支同步修改)。 数值核对(scale=1.25、1 条可见信号):GAP 53.8px → 8.8px(= 一个 pad 的预期留白)。 二、拖拽插入指示线不再盖住被拖条目 PaintSignalDragGhost 的绘制顺序改为「插入指示线 → 阴影 → 幽灵行 → 描边」, 指示线始终位于跟随鼠标的那部分之下。 三、「移动到…」二级菜单 * 条目文案改为「组号 | 组名」(不再是括号形式)。 * 修复「新建分组」点了没反应:DataSet::AddGroup 拒收「无信号且无时间轴」的空分组, 旧实现「先建空组再搬信号」必然在建组那一步失败。新增 DataSet::MoveSignalToNewGroup 把建组 + 搬运时间轴 + 搬运信号做成原子操作(失败回滚)。 * TabConfig::RemapAfterSignalMove 在目标分组是新建时自行扩展 m_visible (调用方不再先 SyncToDataSet —— 那次同步会按旧下标清理引用)。 * Application::MoveSignalCore 增加 newGroupName 参数并返回 bool,避免失败仍报"已移动"。 四、信号拖拽避让动画更流畅 * 插值系数按真实帧间隔计算:1 - exp(-dt/22ms),dt 夹在 1~60ms,帧间隔抖动时不再忽快忽慢。 * 鼠标移动事件里也推进一次插值,快速拖动时让位效果跟得上指针。 验证:删 .o 全量重编译零 error / 零 warning,产物 875,008 B(< 1MB 预警阈值)。 本轮未占用鼠标/键盘/屏幕,未运行任何 GUI 探针;面板空白改为纯数值算式核对。 规则已同步到 Documents/agent_mem.md(含"改面板几何必须数值验证"的教训条目)。
This commit is contained in:
1 parent
97b361dedd
commit
328a3b3b59
10 files changed
+259
-75
No files matched your search
@@ -747,6 +747,25 @@ namespace jdi
|
||||
bool MoveSignal(int fromGroup, int fromSignal, int toGroup, int toSignalIndex,
|
||||
int& newSignalIndex);
|
||||
|
||||
/**
|
||||
* @brief 新建一个分组,并把一条信号(连同它的时间轴)搬进去。
|
||||
*
|
||||
* ⚠️ **不能写成「先 `AddGroup` 再 `MoveSignal`」**:`AddGroup` 拒绝“既没有信号、
|
||||
* 也没有时间轴”的空分组(它用于加载器/派生信号,需要完整内容)⇒ 先建空组必然
|
||||
* 失败返回,表现出来就是“点了「新建分组」毫无反应”(用户 2026-11-03 报告,
|
||||
* 其推测——空分组被当作不需要而拒收——完全正确)。
|
||||
* 本函数把“建组 + 搬运”做成一次原子操作:先推入空组,再搬信号进来,失败则回滚。
|
||||
*
|
||||
* @param [IN] fromGroup 源分组下标。
|
||||
* @param [IN] fromSignal 源分组内的信号下标。
|
||||
* @param [IN] groupName 新分组名称(调用方负责去重)。
|
||||
* @param [OUT] newGroupIndex 新分组下标(恒为原分组数的位置)。
|
||||
* @param [OUT] newSignalIndex 该信号在新分组内的下标(恒为 0)。
|
||||
* @return 成功返回 true。
|
||||
*/
|
||||
bool MoveSignalToNewGroup(int fromGroup, int fromSignal, const std::wstring& groupName,
|
||||
int& newGroupIndex, int& newSignalIndex);
|
||||
|
||||
/**
|
||||
* @brief 移除指定下标的分组,并立即释放其占用的全部采样内存。
|
||||
* @param [IN] groupIndex 分组下标。
|
||||
|
||||
@@ -742,6 +742,46 @@ namespace jdi
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DataSet::MoveSignalToNewGroup(int fromGroup, int fromSignal, const std::wstring& groupName,
|
||||
int& newGroupIndex, int& newSignalIndex)
|
||||
{
|
||||
newGroupIndex = -1;
|
||||
newSignalIndex = -1;
|
||||
if (fromGroup < 0 || fromGroup >= static_cast<int>(m_groups.size()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (fromSignal < 0 ||
|
||||
fromSignal >= static_cast<int>(m_groups[static_cast<std::size_t>(fromGroup)].signals.size()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// ⚠️ 不能走 `AddGroup`:它拒绝“既没有信号、也没有时间轴”的空分组
|
||||
// (那正是「新建分组」点了没反应的根本原因,用户 2026-11-03 的推测是对的)。
|
||||
// 这里先把空组推进去,再把信号(连同它的时间轴)搬进来。
|
||||
SignalGroup created;
|
||||
created.name = groupName;
|
||||
m_groups.push_back(std::move(created));
|
||||
const int target = static_cast<int>(m_groups.size()) - 1;
|
||||
|
||||
int moved = -1;
|
||||
if (!MoveSignal(fromGroup, fromSignal, target, 0, moved))
|
||||
{
|
||||
// 回滚:移动没有发生 ⇒ 去掉刚建的空组(前面已校验过,理论不会走到)。
|
||||
if (static_cast<int>(m_groups.size()) == target + 1 &&
|
||||
m_groups[static_cast<std::size_t>(target)].signals.empty())
|
||||
{
|
||||
m_groups.pop_back();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
newGroupIndex = target;
|
||||
newSignalIndex = moved;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DataSet::MoveSignalToGroup(int fromGroup, int fromSignal, int toGroup, int& newSignalIndex)
|
||||
{
|
||||
if (fromGroup == toGroup)
|
||||
|
||||
@@ -92,7 +92,15 @@ namespace jdi
|
||||
}
|
||||
|
||||
// 1) 可见性表:目标分组在目标位置插入一列(沿用源分组里的可见性),源分组删除一列。
|
||||
// ⚠️⚠️ 目标分组可能是**刚新建**的(「移动到… → 新建分组」):此时 `m_visible`
|
||||
// 还没有它那一行。必须在这里**自行扩展**(否则插入被跳过 ⇒ 信号到新组后
|
||||
// 变为未勾选、曲线直接消失)。不能依赖调用方先 `SyncToDataSet`:那次同步会
|
||||
// 按**旧下标**清理引用,而数据层马上就要整体位移。
|
||||
const std::size_t toSlot = static_cast<std::size_t>(to.groupIndex);
|
||||
if (toSlot >= m_visible.size())
|
||||
{
|
||||
m_visible.resize(toSlot + 1);
|
||||
}
|
||||
if (toSlot < m_visible.size() &&
|
||||
static_cast<std::size_t>(to.signalIndex) <= m_visible[toSlot].size())
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user