1) 打开「选区 Y 轴自适应」时立即自适应一次
- 之前打开开关(单个网格的菜单项或全局项/工具栏按钮)不会真的改变量程,
只有当用户再次做时间轴选区放大时才生效,观感上就是"点了没反应"
- ToggleLaneAutoFitToSelection / SetAllLanesAutoFitToSelection(enable, applyNow=true)
在打开时按当前视图立刻执行一次 AutoRangeLaneToView
- 新增 ApplyAutoFitToSelectionNow / ApplyAllAutoFitToSelectionNow
2) 「按网格时间轴展开」同时对该网格做一次 Y 轴自适应
- FitTimeToLane 在把时间轴展开到本网格信号范围后调用 AutoRangeLaneToView,
避免出现"时间对了但幅值区间不合适"的波形
3) 修复时间光标在大幅放大后丢失、无法拖动的问题
- 根因:缩放/平移改变 ViewMin/ViewMax 后,光标时间可能落到新视野之外,
PaintCursor 直接 return → 光标消失,用户报告为"放大到 10ms 一格后拖动光标会直接丢失"
- 新增 ClampCursorToView(),在 ApplyTimeSelection / FitAll / FitTimeToLane /
平移(PAN) 后把两条光标夹回可见区间;CURSOR_MOVE 也把目标时间夹在 [ViewMin, ViewMax]
- IsOnCursorLine 改为输出命中的光标序号,为双光标拖动做准备
4) 工具栏「时间轴选区」+「Y 轴选区」合并为「选区放大」,并支持右键放弃选区
- 单一 toggle(ToolbarAction::ZOOM_SELECT / PlotZoomMode::SELECT);
按下后按首次明显位移方向决定轴向:横向=时间轴选区,纵向=该网格 Y 轴选区,
轴向固定不变,轴向未定时不画选区(避免闪烁)
- 框选过程中按右键 = 放弃当前选区并显示提示浮层;与 Esc 不同,**不退出**选区放大模式
- 为此 WM_RBUTTONUP 在左键仍按下时不 ReleaseCapture / 不清 m_activeTarget,
否则松左键收不到 OnLButtonUp,m_dragMode 会永远停在 RUBBER_SELECT
- 新增 PlotView 内的提示浮层(m_hintText + PaintHint):切换模式/放弃选区时显示一行说明,
在网格内再次移动鼠标自动清除,无需定时器
- Esc 语义保持原样:放弃拖拽 + 退出选区放大模式
5) 光标功能改为三态:常态 → 单光标 → 双光标 → 常态
- TabConfig 用 PlotCursorMode{NONE,SINGLE,DOUBLE} + CursorTime/CursorTimeAlt 两个时间;
CursorEnabled() 变成只读派生;ToggleCursor 删除,改为 CycleCursorMode()
- 单 → 双时第二条光标落在第一条附近(+12% 视图跨度,越界反向)并保证在可见范围内
- 两条光标颜色区分且同族:光标 1 = Solarized 橙 #CB4B16(theme.cursor),
光标 2 = 青 #2AA198(新增 theme.cursorAlt),光标 2 的顶部把手画成朝上的三角
- 时间读数从绘图区顶部移到**底部**,单/双光标都始终显示(不必悬停才可见)
6) 取消原有的光标数值读数框,改为直接在数据点位置标注取值
- 删除 PaintLaneReadout/PaintLaneReadouts(网格右上角的读数框)
- PaintCursor 在光标与每条可见信号曲线的交点处绘制信号色圆角胶囊(底色=信号色,
文字按 IsDarkColor 自动取深/浅色),一条信号一个标注,颜色与信号一一对应;
右侧空间不足时自动标到左侧
- 双光标时以时间较小者为左;**右侧光标**显示"当前值 , ±增量"(增量 = 右 − 左),
增量为负时用负号前缀,避免出现 "±-" 双符号
验证([1].CSV 11 信号 / VERY_BIG_DATA 1.77GB,窗口 1725x996,125% DPI):
- 三态循环:点 1 次出现单光标、2 次双光标、3 次回到无光标
- 双光标读数:左"426.316 / 427.749",右"538.583 , ±112.267 / 513.726 , ±85.9769"
- 时间读数在底部显示(橙 0.63 / 青 0.7812);第二条光标出现在第一条右侧同一视野内
- 超大文件:放大两次后开启光标仍然可见,拖动从 68.2343 变为 68.1911(原先直接消失)
- 「Y 轴自适应」在放大后的视图中点击立即把量程收到可见区间(300~520)
- 「选区 Y 轴自适应」菜单项点击后立即生效并被勾选,全局项同步勾选
- 「按网格时间轴展开」把时间轴展开回全范围并重新自适应 Y 轴
- 选区放大:横向拖拽只放大时间轴、纵向拖拽只放大 Y 轴;右键放弃后视图不变、提示出现、
模式仍保持选中;Esc 则同时放弃并退出模式
- 回归:空闲 CPU 0.00%;make clean; make all 无警告无错误
91 lines
3.0 KiB
C++
91 lines
3.0 KiB
C++
#include "Theme.hpp"
|
||
|
||
namespace jdi
|
||
{
|
||
|
||
namespace
|
||
{
|
||
// Solarised Light 基础色板。
|
||
const std::uint32_t kBase03 = 0x002B36u; // #002B36
|
||
const std::uint32_t kBase02 = 0x073642u; // #073642
|
||
const std::uint32_t kBase01 = 0x586E75u; // #586E75
|
||
const std::uint32_t kBase00 = 0x657B83u; // #657B83
|
||
const std::uint32_t kBase0 = 0x839496u; // #839496
|
||
const std::uint32_t kBase1 = 0x93A1A1u; // #93A1A1
|
||
const std::uint32_t kBase2 = 0xEEE8D5u; // #EEE8D5
|
||
const std::uint32_t kBase3 = 0xFDF6E3u; // #FDF6E3
|
||
|
||
// Solarised 强调色。
|
||
const std::uint32_t kYellow = 0xB58900u; // #B58900
|
||
const std::uint32_t kOrange = 0xCB4B16u; // #CB4B16
|
||
const std::uint32_t kRed = 0xDC322Fu; // #DC322F
|
||
const std::uint32_t kMagenta = 0xD33682u; // #D33682
|
||
const std::uint32_t kViolet = 0x6C71C4u; // #6C71C4
|
||
const std::uint32_t kBlue = 0x268BD2u; // #268BD2
|
||
const std::uint32_t kCyan = 0x2AA198u; // #2AA198
|
||
const std::uint32_t kGreen = 0x859900u; // #859900
|
||
|
||
/** @brief 波形默认配色,按视觉对比度排序。 */
|
||
const std::uint32_t kSignalPalette[] = {
|
||
MakeArgb(kBlue), MakeArgb(kGreen), MakeArgb(kRed), MakeArgb(kViolet),
|
||
MakeArgb(kYellow), MakeArgb(kCyan), MakeArgb(kMagenta), MakeArgb(kOrange),
|
||
MakeArgb(kBase01), MakeArgb(kBase0),
|
||
};
|
||
|
||
/** @brief 全局唯一主题实例。 */
|
||
const Theme kSolarizedLight = []
|
||
{
|
||
Theme theme;
|
||
theme.windowBg = MakeArgb(kBase3);
|
||
theme.toolbarBg = MakeArgb(kBase2);
|
||
theme.panelBg = MakeArgb(kBase2);
|
||
theme.cardBg = MakeArgb(kBase3);
|
||
theme.statusBg = MakeArgb(kBase2);
|
||
theme.plotBg = MakeArgb(kBase3);
|
||
theme.border = MakeArgb(0xD9D1BCu);
|
||
theme.borderStrong = MakeArgb(kBase1);
|
||
|
||
theme.text = MakeArgb(kBase00);
|
||
theme.textStrong = MakeArgb(kBase02);
|
||
theme.textMuted = MakeArgb(kBase1);
|
||
theme.textOnAccent = MakeArgb(kBase3);
|
||
|
||
theme.accent = MakeArgb(kBlue);
|
||
theme.accentSoft = MakeArgb(0xCFE4F3u);
|
||
theme.hover = MakeArgb(0xE4DCC6u);
|
||
theme.pressed = MakeArgb(0xD8CFB6u);
|
||
theme.selection = MakeArgb(0xDCEAF6u);
|
||
|
||
// 网格线需要在绘图区底色(kBase3)上清晰可辨,同时又要与网格边界
|
||
// (axisLine/borderStrong 的蓝灰)明显区分——因此采用偏暖的加深米色。
|
||
theme.gridWeak = MakeArgb(0xDDD3B8u);
|
||
theme.gridStrong = MakeArgb(0xC3B896u);
|
||
theme.axisLine = MakeArgb(kBase1);
|
||
theme.cursor = MakeArgb(kOrange);
|
||
// 第二光标用 Solarized 青色:与橙色同族饱和度、对比清晰又不刺眼。
|
||
theme.cursorAlt = MakeArgb(kCyan);
|
||
theme.readoutBg = MakeArgb(0xF6EFDCu);
|
||
theme.danger = MakeArgb(kRed);
|
||
theme.warning = MakeArgb(kYellow);
|
||
return theme;
|
||
}();
|
||
}
|
||
|
||
const Theme& SolarizedLight()
|
||
{
|
||
return kSolarizedLight;
|
||
}
|
||
|
||
const std::uint32_t* SignalPalette(int& count)
|
||
{
|
||
count = static_cast<int>(sizeof(kSignalPalette) / sizeof(kSignalPalette[0]));
|
||
return kSignalPalette;
|
||
}
|
||
|
||
int SignalColorCount()
|
||
{
|
||
return static_cast<int>(sizeof(kSignalPalette) / sizeof(kSignalPalette[0]));
|
||
}
|
||
|
||
} // namespace jdi
|