diff --git a/Components/Application/Src/Application.cpp b/Components/Application/Src/Application.cpp index 703df33..37493da 100644 --- a/Components/Application/Src/Application.cpp +++ b/Components/Application/Src/Application.cpp @@ -547,8 +547,8 @@ namespace jdi m_dataSet.ValidateSelection(); m_panel.InvalidateRows(); - // 文件/信号结构变化会让信号引用与文件地址改变,折线顶点缓存必须作废。 - m_plot.InvalidatePolylineCache(); + // 文件/信号结构变化会让信号引用与文件地址改变,派生缓存必须整体作废。 + m_plot.InvalidateDerivedCaches(); // 强制下一次同步重新计算视图状态。 m_cachedVisibleCount = -1; @@ -892,7 +892,7 @@ namespace jdi int fileIndex = -1; // 此处只做一次指针/缓冲移动,不拷贝任何采样数据,因此不会造成可见卡顿。 - if (!m_dataSet.AddPreparedFile(std::move(file), fileIndex)) + if (!m_dataSet.AddDataFile(std::move(file), fileIndex)) { SetStatusMessage(L"解析失败:数据为空。", true); InvalidateRect(m_hwnd, nullptr, FALSE); @@ -1033,7 +1033,7 @@ namespace jdi // 超长文件名用省略号截断,避免撑破卡片。 const std::wstring nameText = - UiEllipsize(g, m_loadingText, m_fonts.uiSmall, textWidth); + UiEllipsize(m_loadingText, m_fonts.uiSmall, textWidth); UiText(g, nameText, m_fonts.uiSmall, gd::RectF(textLeft, card.Y + 42.0f * m_scale, textWidth, 20.0f * m_scale), m_theme.textMuted, TextAlign::LEFT); @@ -1125,21 +1125,21 @@ namespace jdi case ToolbarAction::MERGE_LANES: if (!m_dataSet.Empty()) { - ActiveTab().SetMode(m_dataSet, LaneMode::MERGED); + ActiveTab().SetMode(LaneMode::MERGED); SetStatusMessage(L"已将当前标签页的全部可见信号合并到同一网格。", false); } break; case ToolbarAction::SPLIT_LANES: if (!m_dataSet.Empty()) { - ActiveTab().SetMode(m_dataSet, LaneMode::PER_SIGNAL); + ActiveTab().SetMode(LaneMode::PER_SIGNAL); SetStatusMessage(L"当前标签页已切换为「每信号一格」。", false); } break; case ToolbarAction::CLEAR_ALL: if (!m_dataSet.Empty()) { - ActiveTab().SetAllVisible(m_dataSet, false); + ActiveTab().SetAllVisible(false); m_panel.InvalidateRows(); SetStatusMessage(L"已清空当前标签页的全部网格。", false); } @@ -1436,7 +1436,7 @@ namespace jdi SignalRef derivedRef; derivedRef.fileIndex = fileIndex; derivedRef.signalIndex = newIndex; - ActiveTab().SetVisible(m_dataSet, derivedRef, true); + ActiveTab().SetVisible(derivedRef, true); SignalRef sourceRef; sourceRef.fileIndex = fileIndex; @@ -1812,7 +1812,7 @@ namespace jdi m_activeTarget = Target::NONE; m_draggingSplitter = false; m_panel.OnLButtonUp(0, 0); - m_plot.OnLButtonUp(0, 0); + m_plot.OnLButtonUp(0); } switch (message) @@ -1937,7 +1937,7 @@ namespace jdi // 拾色器接管输入后,取消底层组件可能仍在进行的拖拽。 m_panel.OnLButtonUp(0, 0); - m_plot.OnLButtonUp(0, 0); + m_plot.OnLButtonUp(0); m_activeTarget = Target::NONE; m_draggingSplitter = false; @@ -2295,7 +2295,7 @@ namespace jdi m_panel.OnLButtonUp(x, y); break; case Target::PLOT: - m_plot.OnLButtonUp(x, y); + m_plot.OnLButtonUp(y); break; case Target::NONE: default: @@ -2469,7 +2469,7 @@ namespace jdi } else if (m_plot.HitTest(point.x, point.y)) { - changed = m_plot.OnMouseWheel(point.x, point.y, delta, shift); + changed = m_plot.OnMouseWheel(delta, shift); } if (changed) { diff --git a/Components/PlotView/Inc/PlotView.hpp b/Components/PlotView/Inc/PlotView.hpp index 7d3e914..f09d23a 100644 --- a/Components/PlotView/Inc/PlotView.hpp +++ b/Components/PlotView/Inc/PlotView.hpp @@ -160,7 +160,7 @@ namespace jdi * @param [IN] y 客户区纵坐标。 * @return 需要重绘返回 true。 */ - bool OnLButtonUp(int x, int y); + bool OnLButtonUp(int y); /** * @brief 处理鼠标中键按下:与左键在常规模式下一致,进入自由平移(水平平移时间轴 + @@ -186,7 +186,7 @@ namespace jdi * @param [IN] shift 是否按下 Shift(水平平移时间轴)。 * @return 需要重绘返回 true。 */ - bool OnMouseWheel(int x, int y, int delta, bool shift); + bool OnMouseWheel(int delta, bool shift); /** * @brief 处理鼠标双击(命中时间光标时进入精确时间输入)。 @@ -301,12 +301,6 @@ namespace jdi */ void ScrollLanesByFraction(double fraction); - /** - * @brief 获取网格当前内容总高度。 - * @return 内容高度(像素)。 - */ - float LaneContentHeight() const { return m_laneContentHeight; } - /** * @brief 提示浮层是否仍在显示(含淡出阶段)。 * @@ -341,12 +335,14 @@ namespace jdi bool ExitZoomModes(); /** - * @brief 清空折线顶点缓存。 + * @brief 使全部派生结果失效:折线顶点、边沿统计、中心平均值曲线与静态场景缓存。 * * 数据层结构变化(加载/移除文件、信号增删)后信号引用与文件地址都可能改变, - * 必须清空缓存,避免旧几何键与新的信号意外重合而取到过期顶点。 + * 必须整体失效,避免旧几何键与新的信号意外重合而取到过期结果。 */ - void InvalidatePolylineCache(); /** + void InvalidateDerivedCaches(); + + /** * @brief 三态循环切换时间光标:无 → 单光标 → 双光标 → 无。 * @return 状态发生变化返回 true。 */ @@ -508,14 +504,6 @@ namespace jdi */ bool TakePendingMeanFilterBuild(int& laneIndex, int& radius); - /** - * @brief 进入某网格 Y 轴上限/下限的内联输入状态。 - * @param [IN] laneIndex 网格下标。 - * @param [IN] editMax 为 true 编辑上限,为 false 编辑下限。 - * @return 进入成功返回 true。 - */ - bool BeginLaneValueEdit(int laneIndex, bool editMax, const gd::RectF& anchorRect); - /** * @brief 直接把文本解析为网格 Y 轴上限/下限并应用(供菜单内联输入框提交使用)。 * @param [IN] laneIndex 网格下标。 @@ -590,18 +578,6 @@ namespace jdi */ bool OnEditMouseUp(); - /** - * @brief 获取当前视图左边界时间。 - * @return 视图左边界时间。 - */ - double ViewMinTime() const; - - /** - * @brief 获取当前视图右边界时间。 - * @return 视图右边界时间。 - */ - double ViewMaxTime() const; - /** * @brief 重新生成网格几何(可见性或网格划分变化后调用)。 */ @@ -756,14 +732,6 @@ namespace jdi */ bool ApplyValueSelection(int laneIndex, float y0, float y1); - /** - * @brief 以指定倍率缩放某网格的幅值轴(保持锚点幅值不动)。 - * @param [IN] laneIndex 目标网格下标。 - * @param [IN] factor 缩放倍率,大于 1 表示放大。 - * @param [IN] anchorValue 锚点幅值。 - */ - void ScaleLaneRange(int laneIndex, double factor, double anchorValue); - /** * @brief 平移某网格的幅值轴(偏移波形显示位置)。 * @param [IN] laneIndex 目标网格下标。 @@ -827,7 +795,7 @@ namespace jdi * @param [IN] which 光标序号(1 或 2)。 * @return 颜色。 */ - std::uint32_t CursorColor(int which) const; + std::uint32_t CursorColor() const; /** * @brief 设置并显示一条临时提示(在绘图区底部以浮层方式绘制,短暂停留后淡出)。 @@ -979,13 +947,6 @@ namespace jdi */ EdgePanelLayout EdgePanelLayoutFor(int laneIndex, EdgePanelKind kind) const; - /** - * @brief 获取「边沿计数(中心轴)」浮动面板的矩形。 - * @param [IN] laneIndex 网格下标。 - * @return 面板矩形(未展开时为空矩形)。 - */ - gd::RectF EdgeCenterPanelRect(int laneIndex) const; - /** * @brief 获取中心平均值曲线(每个数据点 = 自身与左右各 N 点的平均值),结果带缓存。 * @param [IN] signal 目标信号。 @@ -1103,20 +1064,6 @@ namespace jdi void PlaceCursorLabel(gd::RectF& rect, float preferredTop, float textHeight, float clipTop, float clipBottom); - /** - * @brief 获取边沿统计面板的矩形(未展开时返回空矩形)。 - * @param [IN] laneIndex 网格下标。 - * @return 面板矩形。 - */ - gd::RectF EdgePanelRect(int laneIndex) const; - - /** - * @brief 获取边沿统计面板上关闭按钮的矩形。 - * @param [IN] laneIndex 网格下标。 - * @return 关闭按钮矩形。 - */ - gd::RectF EdgePanelCloseRect(int laneIndex) const; - /** * @brief 统计某信号穿越横向光标幅值的上/下边沿数量,结果带缓存。 * @param [IN] file 信号所属文件。 @@ -1466,12 +1413,11 @@ namespace jdi /** * @brief 绘制某条信号的悬停/拖拽光晕。 * @param [IN,OUT] g 绘图上下文。 - * @param [IN] ref 信号引用。 * @param [IN] resolved 已解析的信号。 * @param [IN] points 折线顶点。 * @param [IN] breaks 每段折线的起始下标。 */ - void PaintSignalHalo(gd::Graphics& g, const SignalRef& ref, const ResolvedSignal& resolved, + void PaintSignalHalo(gd::Graphics& g, const ResolvedSignal& resolved, const std::vector& points, const std::vector& breaks); /** diff --git a/Components/PlotView/Src/PlotView.cpp b/Components/PlotView/Src/PlotView.cpp index e0d5e32..515f417 100644 --- a/Components/PlotView/Src/PlotView.cpp +++ b/Components/PlotView/Src/PlotView.cpp @@ -363,7 +363,7 @@ namespace jdi m_hoverLane = -1; m_dragMode = PlotDragMode::NONE; // 重新绑定数据源后旧的几何键不再有意义,必须清空折线缓存。 - InvalidatePolylineCache(); + InvalidateDerivedCaches(); InvalidateSceneCache(); RefreshLanes(); } @@ -389,16 +389,6 @@ namespace jdi return Tab().CursorMode(); } - double PlotView::ViewMinTime() const - { - return Tab().ViewMin(); - } - - double PlotView::ViewMaxTime() const - { - return Tab().ViewMax(); - } - bool PlotView::HasDrawableContent() const { return (m_dataSet != nullptr) && !m_dataSet->Empty() && (m_tab != nullptr) && m_tab->AnyVisible(); @@ -899,10 +889,9 @@ namespace jdi } } - std::uint32_t PlotView::CursorColor(int which) const + std::uint32_t PlotView::CursorColor() const { - // 两条光标统一使用同一样式与颜色(与光标 1 一致),不再按序号区分配色。 - (void)which; + // 两条光标统一使用同一样式与颜色,不按序号区分配色。 if (m_theme == nullptr) { return 0xFF000000u; @@ -952,7 +941,7 @@ namespace jdi return true; } - void PlotView::InvalidatePolylineCache() + void PlotView::InvalidateDerivedCaches() { m_polylineCache.clear(); // 数据层结构变化后边沿统计与中心平均值曲线的派生结果都会失效。 @@ -2080,37 +2069,6 @@ namespace jdi } } - void PlotView::ScaleLaneRange(int laneIndex, double factor, double anchorValue) - { - if (m_tab == nullptr || laneIndex < 0 || laneIndex >= static_cast(m_lanes.size())) - { - return; - } - if (!(factor > 0.0) || !std::isfinite(anchorValue)) - { - return; - } - - const LaneVisual& visual = m_lanes[static_cast(laneIndex)]; - const double span = visual.yMax - visual.yMin; - if (!(span > 0.0)) - { - return; - } - - const double magnitude = std::max(std::fabs(visual.yMax), std::fabs(visual.yMin)); - const double minSpan = std::max(magnitude * 1.0e-9, 1.0e-12); - const double newSpan = ClampDouble(span / factor, minSpan, magnitude * 100.0 + 1.0); - const double ratio = (visual.yMax - anchorValue) / span; - - Lane& lane = m_tab->Lanes()[static_cast(laneIndex)]; - lane.autoRange = false; - lane.fitYToSelection = false; - lane.yMin = anchorValue - ratio * newSpan; - lane.yMax = lane.yMin + newSpan; - BuildLaneVisuals(); - } - void PlotView::ShiftLaneRange(int laneIndex, double deltaValue) { if (m_tab == nullptr || laneIndex < 0 || laneIndex >= static_cast(m_lanes.size()) || @@ -2135,27 +2093,6 @@ namespace jdi BuildLaneVisuals(); } - bool PlotView::BeginLaneValueEdit(int laneIndex, bool editMax, const gd::RectF& anchorRect) - { - if (m_tab == nullptr || laneIndex < 0 || laneIndex >= static_cast(m_tab->Lanes().size())) - { - return false; - } - if (m_lanes.empty()) - { - BuildLaneVisuals(); - } - if (laneIndex >= static_cast(m_lanes.size())) - { - return false; - } - - const LaneVisual& visual = m_lanes[static_cast(laneIndex)]; - const double current = editMax ? visual.yMax : visual.yMin; - return BeginEdit(editMax ? PlotEditTarget::LANE_Y_MAX : PlotEditTarget::LANE_Y_MIN, laneIndex, - FormatValue(current), anchorRect); - } - bool PlotView::ApplyLaneValueText(int laneIndex, bool editMax, const std::wstring& text) { if (m_tab == nullptr || laneIndex < 0 || laneIndex >= static_cast(m_tab->Lanes().size())) @@ -3468,8 +3405,9 @@ namespace jdi return changed; } - bool PlotView::OnLButtonUp(int x, int y) - { bool changed = (m_dragMode != PlotDragMode::NONE); + bool PlotView::OnLButtonUp(int y) + { + bool changed = (m_dragMode != PlotDragMode::NONE); switch (m_dragMode) { @@ -3528,11 +3466,10 @@ namespace jdi m_edgePanelDragKind = EdgePanelKind::COUNT; // 松开左键:粘滞提示结束计时,开始"停留后淡出"。 ReleaseHint(); - (void)x; return changed; } - bool PlotView::OnMouseWheel(int x, int y, int delta, bool shift) + bool PlotView::OnMouseWheel(int delta, bool shift) { if (!HasDrawableContent() || delta == 0) { @@ -3559,8 +3496,6 @@ namespace jdi Tab().LaneScroll() -= static_cast(notches * 48.0 * m_scale); BuildLaneVisuals(); - (void)x; - (void)y; return true; } @@ -4125,7 +4060,7 @@ namespace jdi g.DrawRectangle(&borderPen, m_plotRect.X, m_plotRect.Y, m_plotRect.Width, m_plotRect.Height); } - void PlotView::PaintSignalHalo(gd::Graphics& g, const SignalRef& ref, const ResolvedSignal& resolved, + void PlotView::PaintSignalHalo(gd::Graphics& g, const ResolvedSignal& resolved, const std::vector& points, const std::vector& breaks) { @@ -4133,8 +4068,6 @@ namespace jdi if (!drawLine || breaks.empty()) { // 散点模式没有光晕(原实现同样只对折线绘制光晕)。 - (void)g; - (void)ref; return; } @@ -4194,7 +4127,7 @@ namespace jdi const PolylineCacheEntry* cached = AcquirePolyline(m_hoverSignal, resolved, lane); if (cached != nullptr) { - PaintSignalHalo(g, m_hoverSignal, resolved, cached->points, cached->breaks); + PaintSignalHalo(g, resolved, cached->points, cached->breaks); } } } @@ -4534,7 +4467,7 @@ namespace jdi return; } - const float textWidth = UiTextWidth(g, text, m_fonts->monoSmall) + 12.0f * m_scale; + const float textWidth = UiMeasureTextWidth(m_fonts->monoSmall, text) + 12.0f * m_scale; const float textHeight = 18.0f * m_scale; float labelX = m_rubberRect.X + m_rubberRect.Width * 0.5f - textWidth * 0.5f; labelX = std::max(m_plotRect.X, std::min(labelX, m_plotRect.X + m_plotRect.Width - textWidth)); @@ -4568,7 +4501,7 @@ namespace jdi // 提示条贴在绘图区底部居中;时间光标的时间读数也在底部, // 因此光标启用时把提示条上移一行,避免两者互相遮挡。 const float reserved = (m_tab != nullptr && Tab().CursorEnabled()) ? 26.0f * m_scale : 0.0f; - const float width = UiTextWidth(g, m_hintText, m_fonts->ui) + 30.0f * m_scale; + const float width = UiMeasureTextWidth(m_fonts->ui, m_hintText) + 30.0f * m_scale; const float height = 30.0f * m_scale; float left = m_plotRect.X + (m_plotRect.Width - width) * 0.5f; left = std::max(m_plotRect.X + 2.0f * m_scale, @@ -4731,7 +4664,7 @@ namespace jdi const bool highlighted = (ref == haloRef); if (highlighted) { - PaintSignalHalo(g, ref, resolved, points, breaks); + PaintSignalHalo(g, resolved, points, breaks); } if (drawLine && !breaks.empty()) @@ -4892,7 +4825,7 @@ namespace jdi } UiFillRoundRect(g, pill, 3.0f * m_scale, WithAlpha(m_theme->cardBg, 0xF0)); - const std::wstring text = UiEllipsize(g, raw, m_fonts->monoSmall, pill.Width - 6.0f * m_scale); + const std::wstring text = UiEllipsize(raw, m_fonts->monoSmall, pill.Width - 6.0f * m_scale); UiText(g, text, m_fonts->monoSmall, gd::RectF(pill.X + 4.0f * m_scale, pill.Y, pill.Width - 8.0f * m_scale, pill.Height), (tick == 0.0) ? m_theme->text : m_theme->textMuted, TextAlign::LEFT); @@ -4972,7 +4905,7 @@ namespace jdi label += L" · " + resolved.file->Title(); } const float itemWidth = kLegendSwatchSize * m_scale + 5.0f * m_scale + - std::min(UiTextWidth(g, label, m_fonts->uiSmall), + std::min(UiMeasureTextWidth(m_fonts->uiSmall, label), kLegendMaxTextWidth * m_scale) + kLegendItemGap * m_scale; if (cursorX + legendWidth + itemWidth > maxX) @@ -5027,10 +4960,10 @@ namespace jdi } // 文本宽度按上限夹取,超出部分用省略号(与测量阶段保持一致)。 const float maxTextWidth = kLegendMaxTextWidth * m_scale; - const float fullTextWidth = UiTextWidth(g, label, m_fonts->uiSmall); + const float fullTextWidth = UiMeasureTextWidth(m_fonts->uiSmall, label); const float textWidth = std::min(fullTextWidth, maxTextWidth); const std::wstring drawLabel = - (fullTextWidth > maxTextWidth) ? UiEllipsize(g, label, m_fonts->uiSmall, maxTextWidth) : label; + (fullTextWidth > maxTextWidth) ? UiEllipsize(label, m_fonts->uiSmall, maxTextWidth) : label; const float itemWidth = kLegendSwatchSize * m_scale + 5.0f * m_scale + textWidth + kLegendItemGap * m_scale; if (drawnWidth + itemWidth > legendWidth + 0.5f) @@ -5114,7 +5047,7 @@ namespace jdi { for (std::size_t fileIndex = 0; fileIndex < m_dataSet->FileCount(); ++fileIndex) { - if (!m_tab->FileHasVisible(*m_dataSet, static_cast(fileIndex))) + if (!m_tab->FileHasVisible(static_cast(fileIndex))) { continue; } @@ -5138,7 +5071,7 @@ namespace jdi m_plotRect.Width * 0.4f); const gd::RectF nameRect(m_plotRect.X + 2.0f * m_scale, axisY + 3.0f * m_scale, nameWidth, std::max(0.0f, m_timeAxisRect.Height - 5.0f * m_scale)); - UiText(g, UiEllipsize(g, axisName, m_fonts->monoSmall, nameWidth), m_fonts->monoSmall, nameRect, + UiText(g, UiEllipsize(axisName, m_fonts->monoSmall, nameWidth), m_fonts->monoSmall, nameRect, m_theme->textMuted, TextAlign::LEFT); const float labelWidth = 96.0f * m_scale; @@ -5295,7 +5228,7 @@ namespace jdi } const bool hot = (m_hoverCursor == which); - const std::uint32_t color = CursorColor(which); + const std::uint32_t color = CursorColor(); const float lineTop = m_plotRect.Y; const float lineBottom = m_timeAxisRect.Y + m_timeAxisRect.Height; UiDrawLine(g, x, lineTop, x, lineBottom, color, (hot ? 2.0f : 1.4f) * m_scale); @@ -5346,7 +5279,7 @@ namespace jdi const bool interpolate = (resolved.style->mode != DrawMode::SCATTER); double value = 0.0; - if (!SampleFileAt(*resolved.file, *resolved.data, time, interpolate, value)) + if (!SampleSignalAt(*resolved.file, *resolved.data, time, interpolate, value)) { continue; } @@ -5368,7 +5301,7 @@ namespace jdi if (showDelta) { double otherValue = 0.0; - if (SampleFileAt(*resolved.file, *resolved.data, otherTime, interpolate, otherValue)) + if (SampleSignalAt(*resolved.file, *resolved.data, otherTime, interpolate, otherValue)) { const double delta = value - otherValue; // 增量 = 右侧光标取值 − 左侧光标取值,包在圆括号里并按差值显式给出正负号。 @@ -5379,7 +5312,7 @@ namespace jdi } } - const float textWidth = UiTextWidth(g, text, m_fonts->monoSmall) + 10.0f * m_scale; + const float textWidth = UiMeasureTextWidth(m_fonts->monoSmall, text) + 10.0f * m_scale; const float textHeight = 17.0f * m_scale; float labelLeft = pinX + radius + 4.0f * m_scale; if (labelLeft + textWidth > m_plotRect.X + m_plotRect.Width - 2.0f * m_scale) @@ -5454,7 +5387,7 @@ namespace jdi centerText += L")"; const float centerTextWidth = - UiTextWidth(g, centerText, m_fonts->monoSmall) + 10.0f * m_scale; + UiMeasureTextWidth(m_fonts->monoSmall, centerText) + 10.0f * m_scale; float centerLeft = pinX + radius + 4.0f * m_scale; if (centerLeft + centerTextWidth > m_plotRect.X + m_plotRect.Width - 2.0f * m_scale) @@ -5507,7 +5440,7 @@ namespace jdi continue; } const bool highlighted = (m_cursorHover && m_hoverCursor == which); - const std::uint32_t color = CursorColor(which); + const std::uint32_t color = CursorColor(); UiFillRoundRect(g, labelRect, 3.0f * m_scale, highlighted ? color : WithAlpha(color, 0xE0)); const bool dark = IsDarkColor(color); @@ -5526,7 +5459,7 @@ namespace jdi if (spanRect.Width > 0.0f && spanRect.Height > 0.0f) { // 样式与光标时间读数完全一致(同底色/同描边/同文字配色)。 - const std::uint32_t color = CursorColor(1); + const std::uint32_t color = CursorColor(); UiFillRoundRect(g, spanRect, 3.0f * m_scale, m_spanHover ? color : WithAlpha(color, 0xE0)); const bool dark = IsDarkColor(color); @@ -5628,21 +5561,6 @@ namespace jdi return layout; } - gd::RectF PlotView::EdgePanelRect(int laneIndex) const - { - return EdgePanelLayoutFor(laneIndex, EdgePanelKind::COUNT).panel; - } - - gd::RectF PlotView::EdgePanelCloseRect(int laneIndex) const - { - return EdgePanelLayoutFor(laneIndex, EdgePanelKind::COUNT).close; - } - - gd::RectF PlotView::EdgeCenterPanelRect(int laneIndex) const - { - return EdgePanelLayoutFor(laneIndex, EdgePanelKind::CENTER).panel; - } - bool PlotView::IsOnEdgeCursorLine(int x, int y, int& laneIndex) const { laneIndex = -1; @@ -5934,7 +5852,7 @@ namespace jdi std::vector& tabLanes = m_tab->Lanes(); const std::size_t count = std::min(lanes.size(), tabLanes.size()); - const std::uint32_t color = CursorColor(1); + const std::uint32_t color = CursorColor(); const bool dark = IsDarkColor(color); // ---- 横向光标(线与两端把手 + 左侧幅值读数)---- @@ -6334,7 +6252,7 @@ namespace jdi ? std::wstring(L"松开左键放回本网格") : (L"移动到网格 " + std::to_wstring(target + 1) + L":松开左键确认"); - const float textWidth = UiTextWidth(g, hint, m_fonts->uiSmall) + 16.0f * m_scale; + const float textWidth = UiMeasureTextWidth(m_fonts->uiSmall, hint) + 16.0f * m_scale; const float height = 20.0f * m_scale; float left = targetRect.X + (targetRect.Width - textWidth) * 0.5f; left = std::max(m_plotRect.X, std::min(left, m_plotRect.X + m_plotRect.Width - textWidth)); @@ -6373,7 +6291,7 @@ namespace jdi const std::wstring text = resolved.data->Title() + L" · 按住拖拽可移入其它网格"; // 提示跟随鼠标:在可拖拽区域内持续移动时,提示条也要跟着走。 - const float textWidth = UiTextWidth(g, text, m_fonts->uiSmall) + 16.0f * m_scale; + const float textWidth = UiMeasureTextWidth(m_fonts->uiSmall, text) + 16.0f * m_scale; const float height = 20.0f * m_scale; float left = static_cast(m_mouseX) + 12.0f * m_scale; if (left + textWidth > m_plotRect.X + m_plotRect.Width) diff --git a/Components/SignalPanel/Inc/SignalPanel.hpp b/Components/SignalPanel/Inc/SignalPanel.hpp index 3934387..3113928 100644 --- a/Components/SignalPanel/Inc/SignalPanel.hpp +++ b/Components/SignalPanel/Inc/SignalPanel.hpp @@ -78,12 +78,6 @@ namespace jdi */ void InvalidateRows() { m_rowsDirty = true; } - /** - * @brief 判断列表内容是否需要纵向滚动。 - * @return 内容超出可视区域返回 true。 - */ - bool NeedsScrollBar() const { return m_contentHeight > m_listRect.Height + 0.5f; } - /** * @brief 设置 DPI 缩放比例。 * @param [IN] scale 缩放比例(1.0 对应 96 DPI)。 @@ -187,18 +181,6 @@ namespace jdi */ bool EndFilterEdit(); - /** - * @brief 筛选框是否处于编辑状态。 - * @return 编辑中返回 true。 - */ - bool IsFilterEditing() const { return m_filterEditing; } - - /** - * @brief 获取当前筛选文本。 - * @return 筛选文本(未输入时为空串)。 - */ - const std::wstring& FilterText() const { return m_filterText; } - /** * @brief 向当前输入框送入一个字符。 * @param [IN] character 输入字符('\r' 提交、'\b' 退格、0x03 复制)。 @@ -385,12 +367,6 @@ namespace jdi */ void RefreshScrollBar(); - /** - * @brief 计算列表内容总高度。 - * @return 内容高度(像素)。 - */ - float ContentHeight() const; - /** * @brief 限制滚动偏移量到合法范围。 */ diff --git a/Components/SignalPanel/Src/SignalPanel.cpp b/Components/SignalPanel/Src/SignalPanel.cpp index e966878..f5b7e6a 100644 --- a/Components/SignalPanel/Src/SignalPanel.cpp +++ b/Components/SignalPanel/Src/SignalPanel.cpp @@ -419,11 +419,6 @@ namespace jdi ClampScroll(); } - float SignalPanel::ContentHeight() const - { - return m_contentHeight; - } - void SignalPanel::ClampScroll() { const float maxOffset = std::max(0.0f, m_contentHeight - m_listRect.Height); @@ -732,7 +727,7 @@ namespace jdi std::max(20.0f, m_headerRect.Width - kPadding * 2.0f * m_scale - m_toggleAllRect.Width - 8.0f * m_scale), m_headerRect.Height); - UiText(g, UiEllipsize(g, title, m_fonts->uiBold, titleRect.Width), m_fonts->uiBold, titleRect, + UiText(g, UiEllipsize(title, m_fonts->uiBold, titleRect.Width), m_fonts->uiBold, titleRect, m_theme->textStrong, TextAlign::LEFT); const bool allVisible = AreAllSignalsVisible(); @@ -775,7 +770,7 @@ namespace jdi } else { - UiText(g, UiEllipsize(g, m_filterText, m_fonts->uiSmall, textWidth), m_fonts->uiSmall, + UiText(g, UiEllipsize(m_filterText, m_fonts->uiSmall, textWidth), m_fonts->uiSmall, textRect, m_theme->text, TextAlign::LEFT); } @@ -894,8 +889,8 @@ namespace jdi // 分组复选框(三态:全选 / 部分 / 未选)。 const gd::RectF checkRect(baseX + kDisclosureWidth * m_scale, centerY - kCheckSize * m_scale * 0.5f, kCheckSize * m_scale, kCheckSize * m_scale); - const bool allVisible = m_tab->FileAllVisible(*m_dataSet, item.fileIndex); - const bool anyVisible = m_tab->FileHasVisible(*m_dataSet, item.fileIndex); + const bool allVisible = m_tab->FileAllVisible(item.fileIndex); + const bool anyVisible = m_tab->FileHasVisible(item.fileIndex); UiDrawCheckBox(g, checkRect, allVisible ? 1 : (anyVisible ? 2 : 0), 3.0f * m_scale); const gd::RectF closeRect = FileCloseRect(row); @@ -928,7 +923,7 @@ namespace jdi } else { - UiText(g, UiEllipsize(g, file->Title(), m_fonts->uiBold, nameWidth), m_fonts->uiBold, + UiText(g, UiEllipsize(file->Title(), m_fonts->uiBold, nameWidth), m_fonts->uiBold, gd::RectF(nameAreaLeft, rect.Y, nameWidth, rect.Height), m_theme->textStrong, TextAlign::LEFT); } @@ -1013,7 +1008,7 @@ namespace jdi { const float nameWidth = std::max(16.0f, nameRightLimit - nameLeft); const std::uint32_t nameColor = visible ? m_theme->text : m_theme->textMuted; - UiText(g, UiEllipsize(g, signal->Title(), m_fonts->ui, nameWidth), m_fonts->ui, + UiText(g, UiEllipsize(signal->Title(), m_fonts->ui, nameWidth), m_fonts->ui, gd::RectF(nameLeft, rect.Y, nameWidth, rect.Height), nameColor, TextAlign::LEFT); } @@ -1201,7 +1196,8 @@ namespace jdi const std::wstring fullText = numberText + L" px"; // 空间不足时省略单位,保证数值本身完整可读。 const std::wstring shown = - (UiTextWidth(g, fullText, m_fonts->monoSmall) > m_widthValueRect.Width - 6.0f * m_scale) + (UiMeasureTextWidth(m_fonts->monoSmall, fullText) > + m_widthValueRect.Width - 6.0f * m_scale) ? numberText : fullText; UiText(g, shown, m_fonts->monoSmall, m_widthValueRect, m_theme->textStrong, TextAlign::RIGHT); @@ -1996,7 +1992,7 @@ namespace jdi // 全部显示/隐藏。 if (UiPointInRect(m_toggleAllRect, fx, fy)) { - m_tab->SetAllVisible(*m_dataSet, !AreAllSignalsVisible()); + m_tab->SetAllVisible(!AreAllSignalsVisible()); m_rowsDirty = true; return true; } @@ -2066,8 +2062,8 @@ namespace jdi { if (part == RowPart::CHECK) { - const bool allVisible = m_tab->FileAllVisible(*m_dataSet, item.fileIndex); - m_tab->SetFileVisible(*m_dataSet, item.fileIndex, !allVisible); + const bool allVisible = m_tab->FileAllVisible(item.fileIndex); + m_tab->SetFileVisible(item.fileIndex, !allVisible); m_rowsDirty = true; return true; } @@ -2091,7 +2087,7 @@ namespace jdi if (part == RowPart::CHECK) { // 勾选/取消勾选会立即触发网格重新划分(取消后空网格随之消失)。 - m_tab->ToggleVisible(*m_dataSet, ref); + m_tab->ToggleVisible(ref); m_rowsDirty = true; } else if (part == RowPart::LANE_BADGE) @@ -2462,7 +2458,7 @@ namespace jdi case CMD_SIGNAL_TOGGLE: if (m_menuTargetSignal.IsValid()) { - m_tab->ToggleVisible(*m_dataSet, m_menuTargetSignal); + m_tab->ToggleVisible(m_menuTargetSignal); m_rowsDirty = true; needRelayout = true; } @@ -2470,25 +2466,25 @@ namespace jdi case CMD_SIGNAL_SOLO: if (m_menuTargetSignal.IsValid()) { - m_tab->SoloSignal(*m_dataSet, m_menuTargetSignal); + m_tab->SoloSignal(m_menuTargetSignal); m_rowsDirty = true; needRelayout = true; } break; case CMD_SIGNAL_SHOW_ALL: - m_tab->SetAllVisible(*m_dataSet, true); + m_tab->SetAllVisible(true); m_rowsDirty = true; needRelayout = true; break; case CMD_SIGNAL_HIDE_ALL: - m_tab->SetAllVisible(*m_dataSet, false); + m_tab->SetAllVisible(false); m_rowsDirty = true; needRelayout = true; break; case CMD_FILE_SHOW_ALL: if (m_menuTargetFile >= 0) { - m_tab->SetFileVisible(*m_dataSet, m_menuTargetFile, true); + m_tab->SetFileVisible(m_menuTargetFile, true); m_rowsDirty = true; needRelayout = true; } @@ -2496,7 +2492,7 @@ namespace jdi case CMD_FILE_HIDE_ALL: if (m_menuTargetFile >= 0) { - m_tab->SetFileVisible(*m_dataSet, m_menuTargetFile, false); + m_tab->SetFileVisible(m_menuTargetFile, false); m_rowsDirty = true; needRelayout = true; } diff --git a/Components/TabBar/Inc/TabBar.hpp b/Components/TabBar/Inc/TabBar.hpp index c4e4f32..74ab1f5 100644 --- a/Components/TabBar/Inc/TabBar.hpp +++ b/Components/TabBar/Inc/TabBar.hpp @@ -197,12 +197,6 @@ namespace jdi */ int DropIndexAt(int x) const; - /** - * @brief 判断是否正在拖动标签页。 - * @return 正在拖动返回 true。 - */ - bool IsDragging() const { return m_dragIndex >= 0; } - /** * @brief 处理鼠标离开标签栏。 * @return 视觉状态发生变化返回 true。 diff --git a/Components/TabBar/Src/TabBar.cpp b/Components/TabBar/Src/TabBar.cpp index ee7dbda..f45ca2f 100644 --- a/Components/TabBar/Src/TabBar.cpp +++ b/Components/TabBar/Src/TabBar.cpp @@ -180,7 +180,7 @@ namespace jdi } else { - const std::wstring label = UiEllipsize(g, tab.name, m_fonts->ui, std::max(8.0f, textWidth)); + const std::wstring label = UiEllipsize(tab.name, m_fonts->ui, std::max(8.0f, textWidth)); UiText(g, label, active ? m_fonts->uiBold : m_fonts->ui, gd::RectF(textLeft, tab.rect.Y, std::max(8.0f, textWidth), tab.rect.Height), active ? m_theme->textStrong : m_theme->text, TextAlign::LEFT); diff --git a/Utilities/Inc/CsvTable.hpp b/Utilities/Inc/CsvTable.hpp index ae17028..9412c24 100644 --- a/Utilities/Inc/CsvTable.hpp +++ b/Utilities/Inc/CsvTable.hpp @@ -23,9 +23,7 @@ namespace jdi std::vector> columns; /**< 列优先数值矩阵:columns[列][行],缺失处为 NaN。 */ std::size_t rowCount = 0; /**< 有效数据行数。 */ wchar_t delimiter = L','; /**< 实际使用的分隔符。 */ - std::size_t sourceRowCount = 0; /**< 文件中有效数据行数(不含空行与注释行)。 */ - std::size_t skippedRowCount = 0; /**< 因格式异常被置为缺失值的行数。 */ - unsigned long long fileBytes = 0; /**< 源文件字节数(用于按比例预留容量与进度显示)。 */ + unsigned long long fileBytes = 0; /**< 源文件字节数(用于按比例预留容量)。 */ /** * @brief 判断解析结果是否包含可用的表格数据。 diff --git a/Utilities/Inc/DataModel.hpp b/Utilities/Inc/DataModel.hpp index 3aad796..aa4df97 100644 --- a/Utilities/Inc/DataModel.hpp +++ b/Utilities/Inc/DataModel.hpp @@ -189,28 +189,13 @@ namespace jdi class DataSet { public: - /** - * @brief 清空全部已加载文件。 - */ - void Clear(); - - /** - * @brief 依据 CSV 解析结果追加一个数据文件。 - * @param [IN] table CSV 解析结果。 - * @param [IN] filePath 源文件路径。 - * @param [OUT] error 失败原因描述(成功时清空)。 - * @param [OUT] fileIndex 新文件下标,失败时为 -1。 - * @return 追加成功返回 true。 - */ - bool AddFromTable(const CsvTable& table, const std::wstring& filePath, std::wstring& error, int& fileIndex); - /** * @brief 追加一个已构建好的数据文件(仅做一次移动,不拷贝采样数据)。 * @param [IN,OUT] file 数据文件(内部缓冲会被移走)。 * @param [OUT] fileIndex 新文件下标。 * @return 追加成功返回 true。 */ - bool AddPreparedFile(DataFile&& file, int& fileIndex); + bool AddDataFile(DataFile&& file, int& fileIndex); /** * @brief 在指定文件的指定信号**下方**插入一条新信号(派生信号)。 @@ -431,15 +416,19 @@ namespace jdi }; /** - * @brief 计算某条信号在给定时刻的取值。 - * @param [IN] file 信号所属文件。 + * @brief 从内存中的信号采样点取某一时刻的取值。 + * + * 加载完成后全部采样值已在内存中,本函数只查询内存数据,与源文件无关。 + * + * @param [IN] file 信号所属的已加载数据分组(提供时间轴)。 * @param [IN] signal 目标信号。 * @param [IN] time 采样时刻。 * @param [IN] interpolate 是否在相邻采样点之间做线性插值。 * @param [OUT] value 输出采样值,缺失时为 NaN。 * @return 时间点落在数据范围内且取到有效值返回 true。 */ - bool SampleFileAt(const DataFile& file, const SignalData& signal, double time, bool interpolate, double& value); + bool SampleSignalAt(const DataFile& file, const SignalData& signal, double time, bool interpolate, + double& value); /** * @brief 计算 N 点滑动平均(窗口 = [i-N, i+N],边界按实际窗口长度)。 @@ -506,56 +495,49 @@ namespace jdi /** * @brief 设置指定信号的可见性,并同步网格划分。 - * @param [IN] dataSet 数据集合。 * @param [IN] ref 信号引用。 * @param [IN] visible 目标可见状态。 */ - void SetVisible(const DataSet& dataSet, const SignalRef& ref, bool visible); + void SetVisible(const SignalRef& ref, bool visible); /** * @brief 切换指定信号的可见性,并同步网格划分。 - * @param [IN] dataSet 数据集合。 * @param [IN] ref 信号引用。 */ - void ToggleVisible(const DataSet& dataSet, const SignalRef& ref); + void ToggleVisible(const SignalRef& ref); /** * @brief 设置某个文件全部信号的可见性,并同步网格划分。 - * @param [IN] dataSet 数据集合。 * @param [IN] fileIndex 文件下标。 * @param [IN] visible 目标可见状态。 */ - void SetFileVisible(const DataSet& dataSet, int fileIndex, bool visible); + void SetFileVisible(int fileIndex, bool visible); /** * @brief 设置全部信号可见性,并同步网格划分。 - * @param [IN] dataSet 数据集合。 * @param [IN] visible 目标可见状态。 */ - void SetAllVisible(const DataSet& dataSet, bool visible); + void SetAllVisible(bool visible); /** * @brief 仅显示指定信号,其余全部隐藏。 - * @param [IN] dataSet 数据集合。 * @param [IN] ref 需要保持可见的信号。 */ - void SoloSignal(const DataSet& dataSet, const SignalRef& ref); + void SoloSignal(const SignalRef& ref); /** * @brief 判断某文件是否存在可见信号。 - * @param [IN] dataSet 数据集合。 * @param [IN] fileIndex 文件下标。 * @return 存在可见信号返回 true。 */ - bool FileHasVisible(const DataSet& dataSet, int fileIndex) const; + bool FileHasVisible(int fileIndex) const; /** * @brief 判断某文件是否全部信号可见。 - * @param [IN] dataSet 数据集合。 * @param [IN] fileIndex 文件下标。 * @return 全部可见且至少有一条信号返回 true。 */ - bool FileAllVisible(const DataSet& dataSet, int fileIndex) const; + bool FileAllVisible(int fileIndex) const; /** * @brief 判断是否存在任何可见信号。 @@ -577,16 +559,14 @@ namespace jdi /** * @brief 设置网格划分策略并同步网格。 - * @param [IN] dataSet 数据集合。 * @param [IN] mode 目标策略。 */ - void SetMode(const DataSet& dataSet, LaneMode mode); + void SetMode(LaneMode mode); /** * @brief 依据当前可见性与策略重新生成网格划分。 - * @param [IN] dataSet 数据集合。 */ - void SyncLanes(const DataSet& dataSet); + void SyncLanes(); /** * @brief 获取网格集合(只读)。 diff --git a/Utilities/Inc/PaintUtil.hpp b/Utilities/Inc/PaintUtil.hpp index 17d60d7..8154ac5 100644 --- a/Utilities/Inc/PaintUtil.hpp +++ b/Utilities/Inc/PaintUtil.hpp @@ -137,15 +137,6 @@ namespace jdi void UiText(gd::Graphics& g, const std::wstring& text, HFONT font, const gd::RectF& rect, std::uint32_t argb, TextAlign align = TextAlign::LEFT); - /** - * @brief 测量单行文本的像素宽度。 - * @param [IN,OUT] g 绘图上下文。 - * @param [IN] text 文本内容。 - * @param [IN] font 字体句柄。 - * @return 文本像素宽度。 - */ - float UiTextWidth(gd::Graphics& g, const std::wstring& text, HFONT font); - /** * @brief 测量单行文本的像素宽度(无需 GDI+ 上下文,可在布局阶段调用)。 * @param [IN] font 字体句柄。 @@ -193,14 +184,13 @@ namespace jdi std::size_t UiEditOffsetAt(HFONT font, const std::wstring& text, float localX); /** - * @brief 在超出可用宽度时对文本做尾部省略截断。 - * @param [IN,OUT] g 绘图上下文。 + * @brief 在超出可用宽度时对文本做尾部省略截断(不绘制任何内容)。 * @param [IN] text 原始文本。 * @param [IN] font 字体句柄。 * @param [IN] maxWidth 允许的最大像素宽度。 * @return 截断后的文本。 */ - std::wstring UiEllipsize(gd::Graphics& g, const std::wstring& text, HFONT font, float maxWidth); + std::wstring UiEllipsize(const std::wstring& text, HFONT font, float maxWidth); /** * @brief 处理输入框内的鼠标按下:命中则把插入符定位到最近的字符边界并开始拖拽框选。 diff --git a/Utilities/Inc/PopupMenu.hpp b/Utilities/Inc/PopupMenu.hpp index 94a353a..edcf1d4 100644 --- a/Utilities/Inc/PopupMenu.hpp +++ b/Utilities/Inc/PopupMenu.hpp @@ -183,12 +183,6 @@ namespace jdi */ bool IsEditing() const { return m_editIndex >= 0; } - /** - * @brief 获取当前正在编辑的菜单项命令标识。 - * @return 命令标识,未编辑时返回 0。 - */ - int EditingItemId() const; - /** * @brief 判断坐标是否落在当前正在编辑的输入框内。 * @param [IN] x 客户区横坐标。 diff --git a/Utilities/Inc/TextEdit.hpp b/Utilities/Inc/TextEdit.hpp index d838673..3aa8a79 100644 --- a/Utilities/Inc/TextEdit.hpp +++ b/Utilities/Inc/TextEdit.hpp @@ -144,13 +144,6 @@ namespace jdi */ bool DeselectToEnd(); - /** - * @brief 把插入符定位到指定偏移(单击输入框内时使用),并清除选区。 - * @param [IN] offset 目标偏移(内部会夹到合法范围)。 - * @return 光标或选区发生变化返回 true。 - */ - bool PlaceCaret(std::size_t offset); - /** * @brief 开始鼠标拖拽框选:把锚点与插入符都放在给定偏移。 * @param [IN] offset 起始偏移。 diff --git a/Utilities/Inc/Theme.hpp b/Utilities/Inc/Theme.hpp index f12f592..0349427 100644 --- a/Utilities/Inc/Theme.hpp +++ b/Utilities/Inc/Theme.hpp @@ -121,12 +121,6 @@ namespace jdi */ const std::uint32_t* SignalPalette(int& count); - /** - * @brief 获取波形默认配色数量。 - * @return 配色数量。 - */ - int SignalColorCount(); - } // namespace jdi #endif // __THEME_HPP__ diff --git a/Utilities/Inc/Utf8Util.hpp b/Utilities/Inc/Utf8Util.hpp index d39fb25..e38508b 100644 --- a/Utilities/Inc/Utf8Util.hpp +++ b/Utilities/Inc/Utf8Util.hpp @@ -18,13 +18,6 @@ namespace jdi */ std::wstring Utf8ToWide(const char* text, int length = -1); - /** - * @brief 将宽字符串(UTF-16LE)转换为 UTF-8 编码的字节序列。 - * @param [IN] text 宽字符文本起始地址。 - * @return 转换后的 UTF-8 字符串,输入非法时返回空字符串。 - */ - std::string WideToUtf8(const wchar_t* text); - /** * @brief 去除字符串首尾的空白字符(含制表、换行与不间断空格)。 * @param [IN] text 待处理文本。 @@ -46,14 +39,6 @@ namespace jdi */ std::wstring ToLowerAscii(const std::wstring& text); - /** - * @brief 判断字符串是否以指定前缀开头。 - * @param [IN] text 被检索文本。 - * @param [IN] prefix 前缀文本。 - * @return 以该前缀开头返回 true,否则返回 false。 - */ - bool StartsWith(const std::wstring& text, const std::wstring& prefix); - /** * @brief 判断字符串是否包含指定子串(ASCII 大小写不敏感)。 * @param [IN] text 被检索文本。 diff --git a/Utilities/Src/CsvTable.cpp b/Utilities/Src/CsvTable.cpp index 4df8e31..b9ad67d 100644 --- a/Utilities/Src/CsvTable.cpp +++ b/Utilities/Src/CsvTable.cpp @@ -303,11 +303,6 @@ namespace jdi return true; } - if (state.fields.size() != table.headers.size()) - { - ++table.skippedRowCount; - } - bool rowHasValue = false; for (std::size_t column = 0; column < state.rowValues.size(); ++column) { @@ -332,7 +327,6 @@ namespace jdi table.columns[column].push_back(state.rowValues[column]); } ++table.rowCount; - ++table.sourceRowCount; return true; } } diff --git a/Utilities/Src/DataModel.cpp b/Utilities/Src/DataModel.cpp index f734981..9de2c77 100644 --- a/Utilities/Src/DataModel.cpp +++ b/Utilities/Src/DataModel.cpp @@ -464,7 +464,6 @@ namespace jdi } const std::size_t columnCount = table.headers.size(); - const std::size_t rowCount = table.rowCount; if (table.columns.size() < columnCount) { error = L"数据表列结构不完整。"; @@ -599,18 +598,12 @@ namespace jdi } file.minTime = tMin; file.maxTime = tMax; - (void)rowCount; return true; } // ============================ DataSet ============================ - void DataSet::Clear() - { - m_files.clear(); - } - - bool DataSet::AddPreparedFile(DataFile&& file, int& fileIndex) + bool DataSet::AddDataFile(DataFile&& file, int& fileIndex) { fileIndex = -1; if (file.signals.empty()) @@ -622,21 +615,6 @@ namespace jdi return true; } - bool DataSet::AddFromTable(const CsvTable& table, const std::wstring& filePath, std::wstring& error, - int& fileIndex) - { - fileIndex = -1; - - // 兼容入口:复制一份表格后走与后台加载完全一致的构建流程。 - CsvTable local = table; - DataFile file; - if (!BuildDataFile(std::move(local), filePath, SignalCount(), file, error)) - { - return false; - } - return AddPreparedFile(std::move(file), fileIndex); - } - bool DataSet::InsertDerivedSignal(int fileIndex, int afterSignalIndex, SignalData&& signal, int& newSignalIndex) { @@ -992,7 +970,8 @@ namespace jdi return best; } - bool SampleFileAt(const DataFile& file, const SignalData& signal, double time, bool interpolate, double& value) + bool SampleSignalAt(const DataFile& file, const SignalData& signal, double time, bool interpolate, + double& value) { value = kMissing; @@ -1093,7 +1072,7 @@ namespace jdi [](const Lane& lane) { return lane.signals.empty(); }), m_lanes.end()); - SyncLanes(dataSet); + SyncLanes(); } void TabConfig::RemapAfterFileRemoval(int fileIndex) @@ -1147,7 +1126,7 @@ namespace jdi return fileVisible[static_cast(ref.signalIndex)]; } - void TabConfig::SetVisible(const DataSet& dataSet, const SignalRef& ref, bool visible) + void TabConfig::SetVisible(const SignalRef& ref, bool visible) { if (ref.fileIndex < 0 || static_cast(ref.fileIndex) >= m_visible.size()) { @@ -1171,15 +1150,15 @@ namespace jdi m_laneMode = LaneMode::CUSTOM; } - SyncLanes(dataSet); + SyncLanes(); } - void TabConfig::ToggleVisible(const DataSet& dataSet, const SignalRef& ref) + void TabConfig::ToggleVisible(const SignalRef& ref) { - SetVisible(dataSet, ref, !IsVisible(ref)); + SetVisible(ref, !IsVisible(ref)); } - void TabConfig::SetFileVisible(const DataSet& dataSet, int fileIndex, bool visible) + void TabConfig::SetFileVisible(int fileIndex, bool visible) { if (fileIndex < 0 || static_cast(fileIndex) >= m_visible.size()) { @@ -1187,30 +1166,29 @@ namespace jdi } std::vector& fileVisible = m_visible[static_cast(fileIndex)]; std::fill(fileVisible.begin(), fileVisible.end(), visible); - SyncLanes(dataSet); + SyncLanes(); } - void TabConfig::SetAllVisible(const DataSet& dataSet, bool visible) + void TabConfig::SetAllVisible(bool visible) { for (std::vector& fileVisible : m_visible) { std::fill(fileVisible.begin(), fileVisible.end(), visible); } - SyncLanes(dataSet); + SyncLanes(); } - void TabConfig::SoloSignal(const DataSet& dataSet, const SignalRef& ref) + void TabConfig::SoloSignal(const SignalRef& ref) { for (std::vector& fileVisible : m_visible) { std::fill(fileVisible.begin(), fileVisible.end(), false); } - SetVisible(dataSet, ref, true); + SetVisible(ref, true); } - bool TabConfig::FileHasVisible(const DataSet& dataSet, int fileIndex) const + bool TabConfig::FileHasVisible(int fileIndex) const { - (void)dataSet; if (fileIndex < 0 || static_cast(fileIndex) >= m_visible.size()) { return false; @@ -1219,9 +1197,8 @@ namespace jdi return std::find(fileVisible.begin(), fileVisible.end(), true) != fileVisible.end(); } - bool TabConfig::FileAllVisible(const DataSet& dataSet, int fileIndex) const + bool TabConfig::FileAllVisible(int fileIndex) const { - (void)dataSet; if (fileIndex < 0 || static_cast(fileIndex) >= m_visible.size()) { return false; @@ -1256,15 +1233,14 @@ namespace jdi return count; } - void TabConfig::SetMode(const DataSet& dataSet, LaneMode mode) + void TabConfig::SetMode(LaneMode mode) { m_laneMode = mode; - SyncLanes(dataSet); + SyncLanes(); } - void TabConfig::SyncLanes(const DataSet& dataSet) + void TabConfig::SyncLanes() { - (void)dataSet; RebuildLanes(m_visible, m_lanes, m_laneMode); } diff --git a/Utilities/Src/PaintUtil.cpp b/Utilities/Src/PaintUtil.cpp index 36d6d90..559264c 100644 --- a/Utilities/Src/PaintUtil.cpp +++ b/Utilities/Src/PaintUtil.cpp @@ -249,16 +249,6 @@ namespace jdi g.ReleaseHDC(hdc); } - float UiTextWidth(gd::Graphics& g, const std::wstring& text, HFONT font) - { - // 直接复用 UiMeasureTextWidth:后者用 GetDC(nullptr) 取度量 HDC, - // 不会触发 **Graphics::GetHDC() 的 GDI+ 批次刷新**(实测每次约 5µs)。 - // UiEllipsize 会反复调用本函数(逐字符回退时每步一次), - // 若走 GetHDC 路线,一个长名称就要刷新十几次,是拖拽掉帧的隐性来源之一。 - (void)g; - return UiMeasureTextWidth(font, text); - } - float UiMeasureTextWidth(HFONT font, const std::wstring& text) { if (text.empty() || font == nullptr) @@ -281,19 +271,19 @@ namespace jdi return static_cast(size.cx); } - std::wstring UiEllipsize(gd::Graphics& g, const std::wstring& text, HFONT font, float maxWidth) + std::wstring UiEllipsize(const std::wstring& text, HFONT font, float maxWidth) { if (text.empty() || font == nullptr || maxWidth <= 0.0f) { return std::wstring(); } - if (UiTextWidth(g, text, font) <= maxWidth) + if (UiMeasureTextWidth(font, text) <= maxWidth) { return text; } const std::wstring ellipsis = L"…"; - const float ellipsisWidth = UiTextWidth(g, ellipsis, font); + const float ellipsisWidth = UiMeasureTextWidth(font, ellipsis); if (ellipsisWidth > maxWidth) { return std::wstring(); @@ -303,7 +293,7 @@ namespace jdi while (!result.empty()) { result.pop_back(); - if (UiTextWidth(g, result, font) + ellipsisWidth <= maxWidth) + if (UiMeasureTextWidth(font, result) + ellipsisWidth <= maxWidth) { return result + ellipsis; } diff --git a/Utilities/Src/PopupMenu.cpp b/Utilities/Src/PopupMenu.cpp index 8b91142..7991c95 100644 --- a/Utilities/Src/PopupMenu.cpp +++ b/Utilities/Src/PopupMenu.cpp @@ -318,15 +318,6 @@ namespace jdi rect.Y + (rect.Height - height) * 0.5f, width, height); } - int PopupMenu::EditingItemId() const - { - if (m_editIndex < 0 || m_editIndex >= static_cast(m_items.size())) - { - return 0; - } - return m_items[static_cast(m_editIndex)].id; - } - bool PopupMenu::IsOnEditField(int x, int y) const { if (m_editIndex < 0) @@ -1050,7 +1041,7 @@ namespace jdi const float labelLeft = rect.X + kItemPad * m_scale; const gd::RectF fieldRect = EditFieldRect(static_cast(index)); const float labelWidth = std::max(8.0f, fieldRect.X - labelLeft - kEditFieldGap * m_scale); - UiText(g, UiEllipsize(g, item.label, m_fonts->uiSmall, labelWidth), m_fonts->uiSmall, + UiText(g, UiEllipsize(item.label, m_fonts->uiSmall, labelWidth), m_fonts->uiSmall, gd::RectF(labelLeft, rect.Y, labelWidth, rect.Height), labelColor, TextAlign::LEFT); if (static_cast(index) == m_editIndex) @@ -1062,7 +1053,7 @@ namespace jdi UiFillRoundRect(g, fieldRect, 3.0f * m_scale, m_theme->pressed); UiDrawRoundRect(g, fieldRect, 3.0f * m_scale, m_theme->border, 1.0f); const std::wstring text = - UiEllipsize(g, item.value, m_fonts->uiSmall, fieldRect.Width - 12.0f * m_scale); + UiEllipsize(item.value, m_fonts->uiSmall, fieldRect.Width - 12.0f * m_scale); UiText(g, text, m_fonts->uiSmall, gd::RectF(fieldRect.X + 6.0f * m_scale, fieldRect.Y, std::max(8.0f, fieldRect.Width - 12.0f * m_scale), fieldRect.Height), @@ -1146,7 +1137,7 @@ namespace jdi const float textLeft = rect.X + kItemPad * m_scale; const float textWidth = rect.Width - 2.0f * kItemPad * m_scale - kMarkerColumn * m_scale - kMarkerGap * m_scale; - UiText(g, UiEllipsize(g, item.label, m_fonts->uiSmall, textWidth), m_fonts->uiSmall, + UiText(g, UiEllipsize(item.label, m_fonts->uiSmall, textWidth), m_fonts->uiSmall, gd::RectF(textLeft, rect.Y, std::max(8.0f, textWidth), rect.Height), textColor, TextAlign::LEFT); } @@ -1206,12 +1197,12 @@ namespace jdi const float labelLeft = rect.X + kItemPad * m_scale; const gd::RectF fieldRect = EditFieldRect(static_cast(index)); const float labelWidth = std::max(8.0f, fieldRect.X - labelLeft - kEditFieldGap * m_scale); - UiText(g, UiEllipsize(g, item.label, m_fonts->uiSmall, labelWidth), m_fonts->uiSmall, + UiText(g, UiEllipsize(item.label, m_fonts->uiSmall, labelWidth), m_fonts->uiSmall, gd::RectF(labelLeft, rect.Y, labelWidth, rect.Height), labelColor, TextAlign::LEFT); UiFillRoundRect(g, fieldRect, 3.0f * m_scale, m_theme->pressed); UiDrawRoundRect(g, fieldRect, 3.0f * m_scale, m_theme->border, 1.0f); const std::wstring text = - UiEllipsize(g, item.value, m_fonts->uiSmall, fieldRect.Width - 12.0f * m_scale); + UiEllipsize(item.value, m_fonts->uiSmall, fieldRect.Width - 12.0f * m_scale); UiText(g, text, m_fonts->uiSmall, gd::RectF(fieldRect.X + 6.0f * m_scale, fieldRect.Y, std::max(8.0f, fieldRect.Width - 12.0f * m_scale), fieldRect.Height), @@ -1258,7 +1249,7 @@ namespace jdi const float textLeft = rect.X + kItemPad * m_scale; const float textWidth = rect.Width - 2.0f * kItemPad * m_scale - kMarkerColumn * m_scale - kMarkerGap * m_scale; - UiText(g, UiEllipsize(g, item.label, m_fonts->uiSmall, textWidth), m_fonts->uiSmall, + UiText(g, UiEllipsize(item.label, m_fonts->uiSmall, textWidth), m_fonts->uiSmall, gd::RectF(textLeft, rect.Y, std::max(8.0f, textWidth), rect.Height), textColor, TextAlign::LEFT); } diff --git a/Utilities/Src/TextEdit.cpp b/Utilities/Src/TextEdit.cpp index 61d136f..2978e6a 100644 --- a/Utilities/Src/TextEdit.cpp +++ b/Utilities/Src/TextEdit.cpp @@ -322,21 +322,6 @@ namespace jdi return changed; } - bool TextEdit::PlaceCaret(std::size_t offset) - { - if (!m_active) - { - return false; - } - - const std::size_t target = ClampOffset(offset); - const bool changed = HasSelection() || (m_caret != target); - m_caret = target; - m_anchor = target; - m_fresh = false; - return changed; - } - void TextEdit::BeginDrag(std::size_t offset) { if (!m_active) diff --git a/Utilities/Src/Theme.cpp b/Utilities/Src/Theme.cpp index afc57d3..46ca97d 100644 --- a/Utilities/Src/Theme.cpp +++ b/Utilities/Src/Theme.cpp @@ -80,9 +80,4 @@ namespace jdi return kSignalPalette; } - int SignalColorCount() - { - return static_cast(sizeof(kSignalPalette) / sizeof(kSignalPalette[0])); - } - } // namespace jdi diff --git a/Utilities/Src/Utf8Util.cpp b/Utilities/Src/Utf8Util.cpp index 11338b2..ea1467c 100644 --- a/Utilities/Src/Utf8Util.cpp +++ b/Utilities/Src/Utf8Util.cpp @@ -50,30 +50,6 @@ namespace jdi return result; } - std::string WideToUtf8(const wchar_t* text) - { - if (text == nullptr) - { - return std::string(); - } - - int wideCount = static_cast(std::wcslen(text)); - if (wideCount <= 0) - { - return std::string(); - } - - int byteCount = WideCharToMultiByte(CP_UTF8, 0, text, wideCount, nullptr, 0, nullptr, nullptr); - if (byteCount <= 0) - { - return std::string(); - } - - std::string result(static_cast(byteCount), '\0'); - WideCharToMultiByte(CP_UTF8, 0, text, wideCount, &result[0], byteCount, nullptr, nullptr); - return result; - } - std::wstring Trim(const std::wstring& text) { size_t begin = 0; @@ -117,15 +93,6 @@ namespace jdi return result; } - bool StartsWith(const std::wstring& text, const std::wstring& prefix) - { - if (prefix.size() > text.size()) - { - return false; - } - return text.compare(0, prefix.size(), prefix) == 0; - } - bool ContainsInsensitive(const std::wstring& text, const std::wstring& needle) { if (needle.empty())