fix: 修复网格滚动溢出并重构绘图区缩放与时间光标交互
网格滚动: - 修复纵向滚动时波形与文字溢出到工具栏/时间轴的问题:网格内容裁剪改为与绘图区求交, 并对网格内的图例、幅值标签与读数框增加显式可见性判定 (GDI 文本不遵循 GDI+ 裁剪区,仅裁剪矢量绘制不足以阻止溢出)。 - 网格之间改为完整矩形描边并加大间距,边界清晰;时间轴固定预留高度,不再被网格挤压。 - 时间轴刻度标签夹在绘图区横向范围内,避免与左侧时间列名重叠。 缩放交互: - 取消滚轮缩放:滚轮改为纵向滚动网格,Shift+滚轮水平平移。 - 新增「时间轴缩放」「Y 轴缩放」工具栏切换按钮:选中后在绘图区拖拽选区放大对应轴向, 拖动过程显示选区与跨度提示(时间用强调色、Y 轴用警示色);再次点击退出该模式。 - 「适应视图」回到初始状态:恢复自适应范围并退出缩放模式。 - 移除右键框选缩放,避免与模式化缩放重复。 时间光标: - 改为工具栏「光标」按钮切换;启用时置于当前视图中心,再次点击关闭(Esc 亦可关闭)。 - 光标由鼠标靠近后拖拽移动,不再跟随鼠标;纵向贯穿全部网格并延伸到时间轴底部, 顶部带三角把手提示可拖拽。 - 具体时间读数移至绘图区顶部,仅在鼠标覆盖光标时显示,不再遮挡时间轴刻度尺。 - 双击光标进入精确时间输入,交互与线宽输入一致:整段高亮、首次键入即整体覆盖、 回车提交、Esc 取消、点击框外提交。 - 光标形态按模式区分:默认与悬停线外为箭头(不再出现十字指针), 时间轴缩放/光标为水平双向箭头,Y 轴缩放为垂直双向箭头。
This commit is contained in:
1 parent
cba62c8218
commit
17eb03a1b3
6 files changed
+852
-359
No files matched your search
@@ -21,9 +21,10 @@ namespace jdi
|
||||
{
|
||||
NONE = 0, /**< 未触发任何动作。 */
|
||||
OPEN_FILE, /**< 打开 CSV 文件。 */
|
||||
FIT_ALL, /**< 视图自适应到可见信号范围。 */
|
||||
ZOOM_IN, /**< 放大时间轴。 */
|
||||
ZOOM_OUT, /**< 缩小时间轴。 */
|
||||
FIT_ALL, /**< 视图自适应到可见信号范围(同时退出缩放模式)。 */
|
||||
ZOOM_TIME, /**< 切换「在时间轴缩放」模式。 */
|
||||
ZOOM_VALUE, /**< 切换「在 Y 轴缩放」模式。 */
|
||||
CURSOR, /**< 切换时间光标。 */
|
||||
MERGE_LANES, /**< 合并为单一网格。 */
|
||||
SPLIT_LANES, /**< 按信号拆分为多网格。 */
|
||||
SELECT_ALL, /**< 勾选当前标签页全部信号。 */
|
||||
@@ -63,6 +64,13 @@ namespace jdi
|
||||
*/
|
||||
void SetStatusText(const std::wstring& text);
|
||||
|
||||
/**
|
||||
* @brief 设置可切换按钮的选中状态。
|
||||
* @param [IN] action 目标按钮动作。
|
||||
* @param [IN] checked 是否处于选中(生效)状态。
|
||||
*/
|
||||
void SetToggleState(ToolbarAction action, bool checked);
|
||||
|
||||
/**
|
||||
* @brief 计算工具栏在指定缩放下的期望高度。
|
||||
* @return 期望高度(像素)。
|
||||
@@ -132,8 +140,8 @@ namespace jdi
|
||||
gd::RectF rect; /**< 按钮矩形。 */
|
||||
float width = 0.0f; /**< 按钮宽度。 */
|
||||
bool primary = false; /**< 是否为主按钮(强调色填充)。 */
|
||||
bool needsDocument = true; /**< 是否依赖已加载数据。 */
|
||||
bool hover = false; /**< 悬停状态。 */
|
||||
bool needsDocument = true; /**< 是否依赖已加载数据。 */ bool toggle = false; /**< 是否为可切换按钮。 */
|
||||
bool checked = false; /**< 可切换按钮的选中状态。 */ bool hover = false; /**< 悬停状态。 */
|
||||
bool pressed = false; /**< 按下状态。 */
|
||||
};
|
||||
|
||||
|
||||
@@ -67,17 +67,19 @@ namespace jdi
|
||||
const wchar_t* label;
|
||||
bool primary;
|
||||
bool needsDocument;
|
||||
bool toggle;
|
||||
};
|
||||
|
||||
const Spec specs[] = {
|
||||
{ToolbarAction::OPEN_FILE, L"打开 CSV", true, false},
|
||||
{ToolbarAction::FIT_ALL, L"适应视图", false, true},
|
||||
{ToolbarAction::ZOOM_IN, L"放大", false, true},
|
||||
{ToolbarAction::ZOOM_OUT, L"缩小", false, true},
|
||||
{ToolbarAction::MERGE_LANES, L"合并网格", false, true},
|
||||
{ToolbarAction::SPLIT_LANES, L"每信号一格", false, true},
|
||||
{ToolbarAction::SELECT_ALL, L"全选信号", false, true},
|
||||
{ToolbarAction::CLEAR_ALL, L"清空勾选", false, true},
|
||||
{ToolbarAction::OPEN_FILE, L"打开 CSV", true, false, false},
|
||||
{ToolbarAction::FIT_ALL, L"适应视图", false, true, false},
|
||||
{ToolbarAction::ZOOM_TIME, L"时间轴缩放", false, true, true},
|
||||
{ToolbarAction::ZOOM_VALUE, L"Y 轴缩放", false, true, true},
|
||||
{ToolbarAction::CURSOR, L"光标", false, true, true},
|
||||
{ToolbarAction::MERGE_LANES, L"合并网格", false, true, false},
|
||||
{ToolbarAction::SPLIT_LANES, L"每信号一格", false, true, false},
|
||||
{ToolbarAction::SELECT_ALL, L"全选信号", false, true, false},
|
||||
{ToolbarAction::CLEAR_ALL, L"清空勾选", false, true, false},
|
||||
};
|
||||
|
||||
// 按钮宽度按实际文本像素宽 + 固定内边距计算,避免中文标签被裁切。
|
||||
@@ -93,11 +95,12 @@ namespace jdi
|
||||
button.label = spec.label;
|
||||
button.primary = spec.primary;
|
||||
button.needsDocument = spec.needsDocument;
|
||||
button.toggle = spec.toggle;
|
||||
button.width = horizontalPadding + UiMeasureTextWidth(m_fonts->ui, button.label);
|
||||
button.rect = gd::RectF(cursorX, top, button.width, height);
|
||||
cursorX += button.width + kButtonGap * m_scale;
|
||||
|
||||
if (spec.action == ToolbarAction::OPEN_FILE || spec.action == ToolbarAction::ZOOM_OUT ||
|
||||
if (spec.action == ToolbarAction::OPEN_FILE || spec.action == ToolbarAction::CURSOR ||
|
||||
spec.action == ToolbarAction::SPLIT_LANES)
|
||||
{
|
||||
cursorX += kGroupGap * m_scale;
|
||||
@@ -107,6 +110,18 @@ namespace jdi
|
||||
}
|
||||
}
|
||||
|
||||
void Toolbar::SetToggleState(ToolbarAction action, bool checked)
|
||||
{
|
||||
for (Button& button : m_buttons)
|
||||
{
|
||||
if (button.action == action && button.toggle)
|
||||
{
|
||||
button.checked = checked;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Toolbar::Paint(gd::Graphics& g)
|
||||
{
|
||||
if (m_theme == nullptr || m_fonts == nullptr)
|
||||
@@ -139,17 +154,33 @@ namespace jdi
|
||||
}
|
||||
else
|
||||
{
|
||||
background = m_theme->toolbarBg;
|
||||
// 可切换按钮在选中时用强调色浅底 + 强调描边,与普通按钮区分。
|
||||
background = (button.toggle && button.checked) ? m_theme->accentSoft : m_theme->toolbarBg;
|
||||
if (button.pressed)
|
||||
{
|
||||
background = m_theme->pressed;
|
||||
}
|
||||
else if (enabled && button.hover)
|
||||
{
|
||||
background = m_theme->hover;
|
||||
background = (button.toggle && button.checked) ? MixColor(m_theme->accentSoft, m_theme->accent,
|
||||
0.16)
|
||||
: m_theme->hover;
|
||||
}
|
||||
border = MixColor(m_theme->border, m_theme->toolbarBg, enabled ? 0.0 : 0.5);
|
||||
textColor = enabled ? m_theme->text : m_theme->textMuted;
|
||||
if (!enabled)
|
||||
{
|
||||
background = m_theme->toolbarBg;
|
||||
}
|
||||
|
||||
if (button.toggle && button.checked && enabled)
|
||||
{
|
||||
border = m_theme->accent;
|
||||
}
|
||||
else
|
||||
{
|
||||
border = MixColor(m_theme->border, m_theme->toolbarBg, enabled ? 0.0 : 0.5);
|
||||
}
|
||||
textColor = enabled ? ((button.toggle && button.checked) ? m_theme->textStrong : m_theme->text)
|
||||
: m_theme->textMuted;
|
||||
}
|
||||
|
||||
if (background != m_theme->toolbarBg)
|
||||
|
||||
Reference in new issue
Block a user