网格菜单重构、大文件异步加载与内存/解析优化、修复应用图标

网格右键菜单:
- 菜单顺序改为: 网格 N / Y 轴最大值 / Y 轴最小值 / 选区 Y 轴自适应 / --分隔线-- /
  Y 轴自适应 / 时间轴自适应 / 全部自适应
  (恢复自适应移到分隔线以下、时间轴自适应上方)
- Y 轴最大值/最小值改为菜单内联输入框:点击就地编辑、回车提交,菜单不关闭,
  处理方式与拾色器的 RGB 内联编辑一致;提交后按真实夹取结果回写菜单显示值,
  并同步刷新自适应项的文案/对勾/可用状态
- 新增"选区 Y 轴自适应":只按当前显示时间段内的数据做幅值自适应
  (时间单调时二分定位区间,非单调时全扫并按区间过滤)

大文件加载:
- 加载改为工作线程执行(解析 + 按列重组),主线程抽送消息并播放过渡动画
  (旋转弧线 + 进度条 + 文件名 + 百分比 + 按 Esc 取消),界面不再整块卡死
- 加载完成后主线程只做一次 O(1) 的移动入队,不会产生可见卡顿
- 新增 DataModel::BuildDataFile / DataSet::AddPreparedFile:不依赖 DataSet,
  因此可以安全地在线程上运行

内存与解析效率:
- CsvTable 由"行优先二维数组"改为"列优先":百万行文件原先会产生上百万次独立堆分配
  (每行还有 vector 控制块与容量对齐开销),现在每列一整块连续内存
- 解析改为流式分块读取(4MB),不再把整个文件读入内存,也没有体积上限
  (原先超过 512MB 直接拒绝);实测 51MB 文件峰值内存约 126MB(数据本身 113MB)
- BuildDataFile 直接把整列移动进 SignalData(零拷贝),不再逐元素复制
- TryParseDouble 增加十进制快速路径:ucrt strtod 实测约 335ns/次,手写路径约 13ns
  (快 25 倍);非十进制写法(十六进制浮点、inf/nan、带尾部杂字符)原样交回 strtod,
  输入接受语义完全不变(实测与 strtod 的差异不超过 1 ULP)
  → 640MB 测试文件加载时间由约 40s 降到 2s 以内

交互流畅性:
- 拖拽(平移/框选/拖动信号)期间关闭波形抗锯齿并压缩顶点预算(2 像素一列包络),
  松开后立即恢复全质量绘制;实测 BIG_DATA 10 信号全显示的帧耗时由
  105~168ms 降到 75~90ms(其中折线绘制 55ms→23ms)
- 折线包络抽稀改为"列边界单调推进"的二分,避免每列在全区间二分造成缓存缺失
- 未对波形构建引入多线程:构建已由几何键缓存消除,且拖拽降级后仅约 1~2ms/帧,
  并行化收益不足以抵消线程与同步的复杂度(加载路径的多线程收益明确,故只在该处引入)

图标:
- 窗口类与 WM_SETICON 原先使用系统默认图标 IDI_APPLICATION,导致标题栏、
  任务栏与 Alt+Tab 缩略图都显示成通用应用图标;改为按 SM_CXICON/SM_CXSMICON
  从应用的 IDI_APP_ICON 资源加载(多尺寸 ICO 会挑选最接近的一帧)

其他:
- PopupMenu 新增 EDIT 项类型(菜单内联输入框)与 UpdateItemValue/UpdateItemLabel
This commit is contained in:
DeepSeek V4.1 Flash committed 2026-09-30 18:46:56 +08:00
1 parent d6a81839bb
commit 45b44eae57
11 files changed
+1637 -222

No files matched your search

+31 -7
View File
@@ -47,11 +47,12 @@ namespace jdi
*/
enum PlotMenuCommand : int
{
PLOT_CMD_LANE_AUTO = 1, /**< 该网格恢复 Y 轴自适应。 */
PLOT_CMD_LANE_Y_MAX = 2, /**< 输入该网格 Y 轴最大值。 */
PLOT_CMD_LANE_Y_MIN = 3, /**< 输入该网格 Y 轴最小值。 */
PLOT_CMD_FIT_ALL = 4, /**< 全部网格与时间轴自适应。 */
PLOT_CMD_LANE_FIT_TIME = 5 /**< 时间轴自适应到本网格信号范围。 */
PLOT_CMD_LANE_AUTO = 1, /**< 该网格恢复 Y 轴自适应。 */
PLOT_CMD_LANE_Y_MAX = 2, /**< 输入该网格 Y 轴最大值。 */
PLOT_CMD_LANE_Y_MIN = 3, /**< 输入该网格 Y 轴最小值。 */
PLOT_CMD_FIT_ALL = 4, /**< 全部网格与时间轴自适应。 */
PLOT_CMD_LANE_FIT_TIME = 5, /**< 时间轴自适应到本网格信号范围。 */
PLOT_CMD_LANE_AUTO_VIEW = 6 /**< 按当前显示时间段内的数据做 Y 轴自适应。 */
};
/**
@@ -158,6 +159,17 @@ namespace jdi
*/
bool FitTimeToLane(int laneIndex);
/**
* @brief 依据当前显示时间段内的数据对该网格做 Y 轴自适应(“选区 Y 轴自适应”)。
*
* 与普通自适应(用整段数据的极值)不同:这里只看时间轴当前可见区间内的采样点,
* 因此放大到某段局部波形后可以快速把该段的幅值铺满整个网格。
*
* @param [IN] laneIndex 网格下标。
* @return 调整成功返回 true(区间内无有效数据时返回 false)。
*/
bool AutoRangeLaneToView(int laneIndex);
/**
* @brief 把时间吸附到距今最近的数据采样点。
*
@@ -302,6 +314,15 @@ namespace jdi
*/
bool BeginLaneValueEdit(int laneIndex, bool editMax, const gd::RectF& anchorRect);
/**
* @brief 直接把文本解析为网格 Y 轴上限/下限并应用(供菜单内联输入框提交使用)。
* @param [IN] laneIndex 网格下标。
* @param [IN] editMax true 写上限,false 写下限。
* @param [IN] text 输入文本。
* @return 解析并应用成功返回 true。
*/
bool ApplyLaneValueText(int laneIndex, bool editMax, const std::wstring& text);
/**
* @brief 查询某网格当前的 Y 轴显示范围。
* @param [IN] laneIndex 网格下标。
@@ -602,10 +623,11 @@ namespace jdi
* @brief 构建单条信号在当前视图下的折线点序列。
* @param [IN] resolved 已解析的信号视图。
* @param [IN] lane 所属网格绘制信息。
* @param [IN] coarse 交互降级模式:限制每列扫描的采样点数,降低拖拽帧耗时。
* @param [OUT] points 输出点序列。
* @param [OUT] breaks 输出每段折线的起始下标(用于处理缺失值断线)。
*/
void BuildPolyline(const ResolvedSignal& resolved, const LaneVisual& lane,
void BuildPolyline(const ResolvedSignal& resolved, const LaneVisual& lane, bool coarse,
std::vector<gd::PointF>& points, std::vector<std::size_t>& breaks) const;
/**
@@ -776,6 +798,7 @@ namespace jdi
float laneHeight = 0.0f; /**< 网格高度。 */
double laneYMin = 0.0; /**< 网格幅值下界。 */
double laneYMax = 0.0; /**< 网格幅值上界。 */
bool coarse = false; /**< 是否为交互降级顶点(拖拽期间)。 */
std::vector<gd::PointF> points; /**< 折线顶点。 */
std::vector<std::size_t> breaks; /**< 每段折线在 points 中的起始下标。 */
};
@@ -785,10 +808,11 @@ namespace jdi
* @param [IN] ref 信号引用(缓存键的一部分)。
* @param [IN] resolved 已解析的信号。
* @param [IN] lane 网格绘制信息。
* @param [IN] coarse 是否使用交互降级顶点(全质量与降级结果分别缓存)。
* @return 缓存条目指针,无法构建时返回 nullptr。
*/
const PolylineCacheEntry* AcquirePolyline(const SignalRef& ref, const ResolvedSignal& resolved,
const LaneVisual& lane) const;
const LaneVisual& lane, bool coarse) const;
mutable std::deque<PolylineCacheEntry> m_polylineCache; /**< 折线顶点缓存(按几何键复用)。 */