输入框鼠标编辑、图例省略、信号跨视图共享选择与网格菜单布局修复

- 输入框:支持鼠标左键点击定位插入符、拖拽框选区域,并且不再限制字符长度
- 输入框:长文本使用 ETO_CLIPPED 裁剪绘制,避免字符溢出到编辑区域之外
- 图例:信号名称超过 200px 时省略号截断,不再挤压标尺区域
- 选中状态从 TabConfig 迁移到 DataSet,切换视图后信号选中状态保持一致
- 网格右键菜单:Y 轴最大值/最小值直接显示当前值,点击后原位置弹出内联编辑框
- 标尺数值改为绘制在图例下层,不再因避让图例而隐藏
- 移除已无用的 LegendBandRect,新增共享的编辑框布局与命中检测工具
- .gitignore 忽略 TestData 测试数据目录
This commit is contained in:
DeepSeek V4.1 Flash committed 2026-09-30 17:10:23 +08:00
1 parent e3744f3eff
commit 12b3531485
19 files changed
+790 -186

No files matched your search

+57 -14
View File
@@ -344,7 +344,8 @@ namespace jdi
Relayout();
// 切换标签页后把该页已选中的信号滚动到可见位置。
m_panel.ScrollToSignal(m_tabs[static_cast<std::size_t>(m_activeTab)].Selected());
// 切换标签页后把共享的选中信号滚动到可见位置(选中状态跨页保持一致)。
m_panel.ScrollToSignal(m_dataSet.Selected());
SynchronizeView(true);
UpdateWindowTitle();
@@ -418,6 +419,9 @@ namespace jdi
{
tab.SyncToDataSet(m_dataSet);
}
// 选中状态由数据层共享维护,数据变动后需校验其是否仍指向存在的信号。
m_dataSet.ValidateSelection();
m_panel.InvalidateRows();
// 强制下一次同步重新计算视图状态。
@@ -440,11 +444,12 @@ namespace jdi
}
const std::wstring name = file->fileName;
// 先按旧下标修正各标签页配置,再从数据层移除,最后统一对齐。
// 先按旧下标修正各标签页配置与共享选中项,再从数据层移除,最后统一对齐。
for (TabConfig& tab : m_tabs)
{
tab.RemapAfterFileRemoval(fileIndex);
}
m_dataSet.RemapSelectionAfterFileRemoval(fileIndex);
m_dataSet.RemoveFile(fileIndex);
SyncTabsToDataSet();
@@ -921,6 +926,15 @@ namespace jdi
return m_toolbar.OnMouseMove(x, y);
case Target::TAB_BAR:
return m_tabBar.OnMouseMove(x, y);
case Target::EDIT_FIELD:
{
// 输入框拖拽框选:按当前正在编辑的组件分发。
bool changed = m_tabBar.OnEditMouseMove(x);
changed = m_panel.OnEditMouseMove(x) || changed;
changed = m_plot.OnEditMouseMove(x) || changed;
changed = m_colorPicker.OnEditMouseMove(x) || changed;
return changed;
}
case Target::NONE:
default:
return false;
@@ -1107,6 +1121,21 @@ namespace jdi
const bool isAuto = m_plot.LaneRangeIsAuto(laneIndex);
// 当前网格的 Y 轴上下限值直接在菜单项中显示,单击即可直接改写。
double laneYMin = 0.0;
double laneYMax = 1.0;
m_plot.LaneRange(laneIndex, laneYMin, laneYMax);
MenuItem maxItem;
maxItem.label = L"Y 轴最大值:" + FormatValue(laneYMax);
maxItem.id = PLOT_CMD_LANE_Y_MAX;
items.push_back(maxItem);
MenuItem minItem;
minItem.label = L"Y 轴最小值:" + FormatValue(laneYMin);
minItem.id = PLOT_CMD_LANE_Y_MIN;
items.push_back(minItem);
MenuItem autoItem;
autoItem.label = isAuto ? L"Y 轴自适应(当前)" : L"恢复 Y 轴自适应";
autoItem.id = PLOT_CMD_LANE_AUTO;
@@ -1114,16 +1143,6 @@ namespace jdi
autoItem.enabled = !isAuto;
items.push_back(autoItem);
MenuItem maxItem;
maxItem.label = L"设置 Y 轴最大值…";
maxItem.id = PLOT_CMD_LANE_Y_MAX;
items.push_back(maxItem);
MenuItem minItem;
minItem.label = L"设置 Y 轴最小值…";
minItem.id = PLOT_CMD_LANE_Y_MIN;
items.push_back(minItem);
MenuItem separator;
separator.kind = MenuItemKind::SEPARATOR;
items.push_back(separator);
@@ -1175,10 +1194,10 @@ namespace jdi
m_plot.ResetLaneRange(laneIndex);
break;
case PLOT_CMD_LANE_Y_MAX:
m_plot.BeginLaneValueEdit(laneIndex, true);
m_plot.BeginLaneValueEdit(laneIndex, true, result.itemRect);
break;
case PLOT_CMD_LANE_Y_MIN:
m_plot.BeginLaneValueEdit(laneIndex, false);
m_plot.BeginLaneValueEdit(laneIndex, false, result.itemRect);
break;
case PLOT_CMD_LANE_FIT_TIME:
m_plot.FitTimeToLane(laneIndex);
@@ -1475,6 +1494,16 @@ namespace jdi
const int x = GET_X_LPARAM(lParam);
const int y = GET_Y_LPARAM(lParam);
// 编辑态下点击输入框内部:定位插入符并开始拖拽框选,不再触发底层控件的选中/拖拽。
if (m_tabBar.OnEditMouseDown(x, y) || m_panel.OnEditMouseDown(x, y) ||
m_plot.OnEditMouseDown(x, y) || m_colorPicker.OnEditMouseDown(x, y))
{
SetCapture(hwnd);
m_activeTarget = Target::EDIT_FIELD;
InvalidateRect(hwnd, nullptr, FALSE);
return 0;
}
// 内联数值输入处于活动态时,点击绘图区之外视为提交(与线宽输入一致)。
if (m_plot.IsEditing() && !m_plot.HitTest(x, y))
{
@@ -1557,6 +1586,20 @@ namespace jdi
case Target::SPLITTER:
m_draggingSplitter = false;
break;
case Target::EDIT_FIELD:
{
// 结束输入框内的拖拽框选(选区保留)。
bool changed = m_tabBar.OnEditMouseUp();
changed = m_panel.OnEditMouseUp() || changed;
changed = m_plot.OnEditMouseUp() || changed;
changed = m_colorPicker.OnEditMouseUp() || changed;
m_activeTarget = Target::NONE;
if (changed)
{
InvalidateRect(hwnd, nullptr, FALSE);
}
return 0;
}
case Target::TAB_BAR:
{
TabBarResult result;