Files
Just-DataInspector/Components/Toolbar/Inc/Toolbar.hpp
T
DeepSeek V4.1 Flash 9c6c374cce feat: 支持多视图标签页、按文件分组的多文件信号管理与网格随勾选自动收敛
数据层与视图配置解耦:新增 DataSet(多文件只读数据层)与 TabConfig(每标签页独立配置),
以 SignalRef{fileIndex,signalIndex} 标识全局信号,替换原有单文件 SignalSet。

- 标签页:新增 TabBar 组件,支持新建/切换/关闭标签页;每页独立保存信号勾选、
  颜色/线宽/显示方式、网格划分、视图范围与时间光标,互不影响。
- 网格收敛:可见性变更统一经 TabConfig 的 Set*Visible 接口并同步重算网格,
  取消勾选后对应的空网格立即回收(修复此前留下空轨道的问题)。
- 多文件分组:左侧面板改为「文件分组 + 信号」树形列表,分组可折叠、可整组勾选,
  分组复选框支持全选/部分/未选三态;新加载文件的信号默认未勾选,由用户自行选择。
- 来源标识:信号行、样式编辑区标题、波形图例与光标读数在跨文件时标注来源文件名。
- 交互补充:面板滚动条支持点击跳转与拖拽,切换标签页自动滚动到已选信号。
- 工具栏精简为「打开 CSV/适应视图/放大/缩小/合并网格/每信号一格/全选信号/清空勾选」,
  按钮宽度改为按实际文本像素测量;打开对话框支持多选文件,拖放支持批量载入。
- 新增 TestData/[2].CSV 作为跨文件对比测试数据。
2026-09-29 15:48:04 +08:00

161 lines
4.5 KiB
C++

#ifndef __TOOLBAR_HPP__
#define __TOOLBAR_HPP__
#include <windows.h>
#include <objidl.h>
#include <gdiplus.h>
#include <string>
#include <vector>
#include "PaintUtil.hpp"
#include "Theme.hpp"
namespace jdi
{
/**
* @brief 工具栏按钮触发的动作。
*/
enum class ToolbarAction : int
{
NONE = 0, /**< 未触发任何动作。 */
OPEN_FILE, /**< 打开 CSV 文件。 */
FIT_ALL, /**< 视图自适应到可见信号范围。 */
ZOOM_IN, /**< 放大时间轴。 */
ZOOM_OUT, /**< 缩小时间轴。 */
MERGE_LANES, /**< 合并为单一网格。 */
SPLIT_LANES, /**< 按信号拆分为多网格。 */
SELECT_ALL, /**< 勾选当前标签页全部信号。 */
CLEAR_ALL /**< 取消当前标签页全部信号勾选。 */
};
/**
* @brief 顶部工具栏:文件操作与视图控制的入口。
*/
class Toolbar
{
public:
Toolbar();
/**
* @brief 绑定字体与主题资源。
* @param [IN] fonts 字体集合,需在工具栏生命周期内保持有效。
* @param [IN] theme 主题配色,需在工具栏生命周期内保持有效。
*/
void Setup(const UiFonts* fonts, const Theme* theme);
/**
* @brief 设置 DPI 缩放比例。
* @param [IN] scale 缩放比例(1.0 对应 96 DPI)。
*/
void SetScale(float scale);
/**
* @brief 设置是否已加载数据(未加载时大部分按钮被禁用)。
* @param [IN] hasDocument 是否已加载数据。
*/
void SetDocumentLoaded(bool hasDocument);
/**
* @brief 设置工具栏右侧的状态文本。
* @param [IN] text 状态文本。
*/
void SetStatusText(const std::wstring& text);
/**
* @brief 计算工具栏在指定缩放下的期望高度。
* @return 期望高度(像素)。
*/
float DesiredHeight() const;
/**
* @brief 按给定区域重新排布按钮。
* @param [IN] area 工具栏可用区域。
*/
void Layout(const gd::RectF& area);
/**
* @brief 绘制工具栏。
* @param [IN,OUT] g 绘图上下文。
*/
void Paint(gd::Graphics& g);
/**
* @brief 处理鼠标移动,更新悬停状态。
* @param [IN] x 客户区横坐标。
* @param [IN] y 客户区纵坐标。
* @return 悬停状态发生变化返回 true。
*/
bool OnMouseMove(int x, int y);
/**
* @brief 处理鼠标左键按下。
* @param [IN] x 客户区横坐标。
* @param [IN] y 客户区纵坐标。
* @param [OUT] action 命中的按钮动作。
* @return 命中按钮返回 true。
*/
bool OnLButtonDown(int x, int y, ToolbarAction& action);
/**
* @brief 处理鼠标左键抬起。
* @param [IN] x 客户区横坐标。
* @param [IN] y 客户区纵坐标。
* @param [OUT] action 抬起时命中的按钮动作(仅在按钮上抬起时有效)。
* @return 视觉状态发生变化返回 true。
*/
bool OnLButtonUp(int x, int y, ToolbarAction& action);
/**
* @brief 处理鼠标离开工具栏。
* @return 视觉状态发生变化返回 true。
*/
bool OnMouseLeave();
/**
* @brief 判断坐标是否落在工具栏区域内。
* @param [IN] x 客户区横坐标。
* @param [IN] y 客户区纵坐标。
* @return 落在区域内返回 true。
*/
bool HitTest(int x, int y) const;
private:
/**
* @brief 单个工具栏按钮的运行时状态。
*/
struct Button
{
ToolbarAction action = ToolbarAction::NONE; /**< 按钮动作。 */
std::wstring label; /**< 按钮文本。 */
gd::RectF rect; /**< 按钮矩形。 */
float width = 0.0f; /**< 按钮宽度。 */
bool primary = false; /**< 是否为主按钮(强调色填充)。 */
bool needsDocument = true; /**< 是否依赖已加载数据。 */
bool hover = false; /**< 悬停状态。 */
bool pressed = false; /**< 按下状态。 */
};
/**
* @brief 判断按钮当前是否可用。
* @param [IN] button 目标按钮。
* @return 可用返回 true。
*/
bool IsEnabled(const Button& button) const;
const UiFonts* m_fonts = nullptr; /**< 字体资源。 */
const Theme* m_theme = nullptr; /**< 主题资源。 */
float m_scale = 1.0f; /**< DPI 缩放比例。 */
bool m_documentLoaded = false; /**< 是否已加载数据。 */
std::wstring m_statusText; /**< 右侧状态文本。 */
std::vector<Button> m_buttons; /**< 按钮集合。 */
gd::RectF m_area; /**< 工具栏整体区域。 */
int m_hoverIndex = -1; /**< 当前悬停按钮下标。 */
int m_pressedIndex = -1; /**< 当前按下按钮下标。 */
};
} // namespace jdi
#endif // __TOOLBAR_HPP__