Files
Just-DataInspector/Utilities/Inc/PaintUtil.hpp
T
DeepSeek V4.1 Flash 350538c634 命名审查与垃圾代码清理(纯重命名 / 死代码删除,无行为变更)
前提:加载完成后全部采样都已驻留内存,程序此后与源文件再无联系。
据此修正了一批会让人误以为"仍在读写文件"的命名:

- SampleFileAt → SampleSignalAt(取的是内存信号在给定时刻的采样值)。
- DataSet::AddPreparedFile → AddDataFile。
- PlotView::InvalidatePolylineCache → InvalidateDerivedCaches
  (它同时清空折线、边沿统计、中心平均值曲线、静态场景缓存与悬停引用)。
- PlotView::CursorColor(int which) → CursorColor()(两条光标同色,参数从未使用)。
- UiEllipsize(g,…) → UiEllipsize(…):纯测量不绘制,删掉被忽略的绘图上下文参数;
  同时删除与 UiMeasureTextWidth 完全重复的 UiTextWidth,调用点统一到 UiMeasureTextWidth。

清理残留参数((void)xxx;):
- TabConfig 的可见性/网格族(SetVisible / ToggleVisible / SetFileVisible / SetAllVisible /
  SoloSignal / SetMode / SyncLanes / FileHasVisible / FileAllVisible)去掉从未使用的
  const DataSet& 参数(仅 SyncToDataSet 真正需要数据层,保留)。
- PlotView::OnLButtonUp(int y)、OnMouseWheel(int delta, bool shift);PainterSignalHalo 去掉未用的 ref。
- BuildDataFile 中未使用的局部 rowCount。

删除无人调用的死函数:
  DataSet::Clear / AddFromTable;SignalColorCount;WideToUtf8 / StartsWith;
  PlotView::ViewMinTime / ViewMaxTime / EdgePanelRect / EdgePanelCloseRect /
  EdgeCenterPanelRect / ScaleLaneRange / BeginLaneValueEdit / LaneContentHeight;
  SignalPanel::NeedsScrollBar / IsFilterEditing / FilterText / ContentHeight;
  PopupMenu::EditingItemId;TabBar::IsDragging;TextEdit::PlaceCaret。

删除只写不读的死字段:CsvTable::sourceRowCount(与 rowCount 等义)与 skippedRowCount。

以 VERY_BIG_DATA.CSV 回归验证:加载与勾选、筛选框(含"无匹配的筛选信号")、
样式区线宽文案省略、选区放大(横向与纵向)、双光标读数与 Δt、右键菜单(Y 轴数值与
实验性功能子菜单)、合并/拆分网格、标签与信号重命名省略号,行为均与改动前一致;
make clean && make all 无任何警告。
2026-10-09 21:52:46 +08:00

313 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#ifndef __PAINT_UTIL_HPP__
#define __PAINT_UTIL_HPP__
#include <windows.h>
#include <objidl.h>
#include <gdiplus.h>
#include <cstdint>
#include <string>
#include "TextEdit.hpp"
#include "Theme.hpp"
namespace jdi
{
/**
* @brief 文本水平对齐方式(垂直方向始终居中)。
*/
enum class TextAlign : int
{
LEFT = 0, /**< 左对齐。 */
CENTER = 1, /**< 水平居中。 */
RIGHT = 2 /**< 右对齐。 */
};
/**
* @brief 图标朝向。
*/
enum class IconDirection : int
{
LEFT = 0, /**< 指向左侧。 */
RIGHT = 1, /**< 指向右侧。 */
UP = 2, /**< 指向上方。 */
DOWN = 3 /**< 指向下方。 */
};
/**
* @brief 按 DPI 创建并缓存整套界面字体(GDI 字体句柄)。
*/
struct UiFonts
{
HFONT ui = nullptr; /**< 常规界面字体。 */
HFONT uiBold = nullptr; /**< 加粗界面字体。 */
HFONT uiSmall = nullptr; /**< 小号界面字体。 */
HFONT uiSmallBold = nullptr;/**< 小号加粗界面字体。 */
HFONT title = nullptr; /**< 标题字体。 */
HFONT mono = nullptr; /**< 等宽数值字体。 */
HFONT monoSmall = nullptr; /**< 小号等宽字体。 */
UINT dpi = 96; /**< 创建时所使用的 DPI。 */
/**
* @brief 依据 DPI 创建全部字体。
* @param [IN] dpi 目标 DPI(96 对应 100% 缩放)。
* @return 创建成功返回 true。
*/
bool Create(UINT dpi);
/**
* @brief 释放全部字体句柄。
*/
void Destroy();
~UiFonts() { Destroy(); }
};
/**
* @brief 将 0xAARRGGBB 颜色值转换为 GDI COLORREF。
* @param [IN] argb 颜色值。
* @return GDI 颜色值。
*/
inline COLORREF ToColorRef(std::uint32_t argb)
{
return RGB((argb >> 16) & 0xFFu, (argb >> 8) & 0xFFu, argb & 0xFFu);
}
/**
* @brief 判断点是否落在矩形内部。
* @param [IN] rect 目标矩形。
* @param [IN] x 横坐标。
* @param [IN] y 纵坐标。
* @return 落在内部返回 true。
*/
inline bool UiPointInRect(const gd::RectF& rect, float x, float y)
{
return x >= rect.X && x <= (rect.X + rect.Width) && y >= rect.Y && y <= (rect.Y + rect.Height);
}
/**
* @brief 填充矩形区域。
* @param [IN,OUT] g 绘图上下文。
* @param [IN] rect 目标矩形。
* @param [IN] argb 填充颜色。
*/
void UiFillRect(gd::Graphics& g, const gd::RectF& rect, std::uint32_t argb);
/**
* @brief 填充圆角矩形区域。
* @param [IN,OUT] g 绘图上下文。
* @param [IN] rect 目标矩形。
* @param [IN] radius 圆角半径。
* @param [IN] argb 填充颜色。
*/
void UiFillRoundRect(gd::Graphics& g, const gd::RectF& rect, float radius, std::uint32_t argb);
/**
* @brief 描边圆角矩形。
* @param [IN,OUT] g 绘图上下文。
* @param [IN] rect 目标矩形。
* @param [IN] radius 圆角半径。
* @param [IN] argb 线条颜色。
* @param [IN] width 线条宽度。
*/
void UiDrawRoundRect(gd::Graphics& g, const gd::RectF& rect, float radius, std::uint32_t argb, float width);
/**
* @brief 绘制一条直线。
* @param [IN,OUT] g 绘图上下文。
* @param [IN] x1 起点横坐标。
* @param [IN] y1 起点纵坐标。
* @param [IN] x2 终点横坐标。
* @param [IN] y2 终点纵坐标。
* @param [IN] argb 线条颜色。
* @param [IN] width 线条宽度。
*/
void UiDrawLine(gd::Graphics& g, float x1, float y1, float x2, float y2, std::uint32_t argb, float width);
/**
* @brief 在指定矩形内绘制单行文本(垂直居中,超长自动省略)。
* @param [IN,OUT] g 绘图上下文。
* @param [IN] text 文本内容。
* @param [IN] font 字体句柄。
* @param [IN] rect 文本布局矩形。
* @param [IN] argb 文本颜色。
* @param [IN] align 水平对齐方式。
*/
void UiText(gd::Graphics& g, const std::wstring& text, HFONT font, const gd::RectF& rect, std::uint32_t argb,
TextAlign align = TextAlign::LEFT);
/**
* @brief 测量单行文本的像素宽度(无需 GDI+ 上下文,可在布局阶段调用)。
* @param [IN] font 字体句柄。
* @param [IN] text 文本内容。
* @return 文本像素宽度。
*/
float UiMeasureTextWidth(HFONT font, const std::wstring& text);
/**
* @brief 在指定裁剪矩形内以显式起点绘制一段文本(使用 GDI ExtTextOut 裁剪)。
*
* `UiText` 走 `DrawTextW`,**不遵循 GDI+ 裁剪区**;输入框在长内容、水平滚动的情况下
* 会把字符画到框体之外。本函数用 `ETO_CLIPPING` 让 GDI 自己裁剪,彻底避免越界绘制。
*
* @param [IN,OUT] g 绘图上下文。
* @param [IN] text 文本内容。
* @param [IN] font 字体句柄。
* @param [IN] x 文本起始横坐标。
* @param [IN] rect 垂直居中参考矩形。
* @param [IN] argb 文本颜色。
* @param [IN] clipRect 裁剪矩形(超出部分不绘制)。
*/
void UiTextAtClipped(gd::Graphics& g, const std::wstring& text, HFONT font, float x, const gd::RectF& rect,
std::uint32_t argb, const gd::RectF& clipRect);
/**
* @brief 计算输入框文本的绘制起点(已考虑超出框宽时的水平滚动)。
* @param [IN] rect 输入框矩形。
* @param [IN] edit 编辑模型。
* @param [IN] font 字体句柄。
* @param [IN] scale 缩放比例。
* @param [OUT] innerWidth 框内可用宽度输出。
* @return 文本绘制起点横坐标。
*/
float UiEditTextLeft(const gd::RectF& rect, const TextEdit& edit, HFONT font, float scale,
float& innerWidth);
/**
* @brief 把输入框内的横坐标换算为字符偏移(就近取整,用于鼠标定位插入符)。
* @param [IN] font 字体句柄。
* @param [IN] text 当前文本。
* @param [IN] localX 相对文本起点的横坐标(可超出 [0, 文本宽度])。
* @return 字符偏移。
*/
std::size_t UiEditOffsetAt(HFONT font, const std::wstring& text, float localX);
/**
* @brief 在超出可用宽度时对文本做尾部省略截断(不绘制任何内容)。
* @param [IN] text 原始文本。
* @param [IN] font 字体句柄。
* @param [IN] maxWidth 允许的最大像素宽度。
* @return 截断后的文本。
*/
std::wstring UiEllipsize(const std::wstring& text, HFONT font, float maxWidth);
/**
* @brief 处理输入框内的鼠标按下:命中则把插入符定位到最近的字符边界并开始拖拽框选。
* @param [IN] font 字体句柄。
* @param [IN] rect 输入框矩形。
* @param [IN,OUT] edit 编辑模型。
* @param [IN] scale 缩放比例。
* @param [IN] x 客户区横坐标。
* @param [IN] y 客户区纵坐标。
* @return 命中输入框并开始拖拽返回 true。
*/
bool UiEditFieldMouseDown(HFONT font, const gd::RectF& rect, TextEdit& edit, float scale, int x, int y);
/**
* @brief 处理输入框内的鼠标拖拽移动(扩展选区)。
* @param [IN] font 字体句柄。
* @param [IN] rect 输入框矩形。
* @param [IN,OUT] edit 编辑模型。
* @param [IN] scale 缩放比例。
* @param [IN] x 客户区横坐标。
* @return 选区发生变化返回 true。
*/
bool UiEditFieldMouseMove(HFONT font, const gd::RectF& rect, TextEdit& edit, float scale, int x);
/**
* @brief 在矩形中心绘制一个加号图标。
* @param [IN,OUT] g 绘图上下文。
* @param [IN] rect 图标布局矩形。
* @param [IN] argb 线条颜色。
* @param [IN] strokeWidth 线条宽度。
*/
void UiDrawPlusIcon(gd::Graphics& g, const gd::RectF& rect, std::uint32_t argb, float strokeWidth);
/**
* @brief 在矩形中心绘制一个叉号(关闭)图标。
* @param [IN,OUT] g 绘图上下文。
* @param [IN] rect 图标布局矩形。
* @param [IN] argb 线条颜色。
* @param [IN] strokeWidth 线条宽度。
*/
void UiDrawCrossIcon(gd::Graphics& g, const gd::RectF& rect, std::uint32_t argb, float strokeWidth);
/**
* @brief 在矩形中心绘制一个实心三角形指示器。
* @param [IN,OUT] g 绘图上下文。
* @param [IN] rect 图标布局矩形。
* @param [IN] argb 填充颜色。
* @param [IN] direction 三角形朝向。
*/
void UiDrawTriangleIcon(gd::Graphics& g, const gd::RectF& rect, std::uint32_t argb, IconDirection direction);
/**
* @brief 将滑块轨道上的横坐标换算为取值比例。
* @param [IN] trackRect 轨道矩形。
* @param [IN] x 横坐标。
* @return 取值比例,范围 0-1。
*/
double UiSliderRatioFromX(const gd::RectF& trackRect, float x);
/**
* @brief 绘制水平滑块(轨道 + 已填充部分 + 圆钮)。
* @param [IN,OUT] g 绘图上下文。
* @param [IN] track 轨道矩形。
* @param [IN] ratio 当前值比例(0-1)。
* @param [IN] fillColor 已填充部分颜色。
* @param [IN] active 是否处于悬停或拖拽状态(影响圆钮半径)。
* @param [IN] scale DPI 缩放比例。
*/
void UiDrawSlider(gd::Graphics& g, const gd::RectF& track, double ratio, std::uint32_t fillColor,
bool active, float scale);
/**
* @brief 绘制单行内联输入框(含选区高亮、插入符与水平滚动)。
*
* 初始状态为“整体选中”时以强调色底衬显示全部内容,首字符键入即整体替换,
* 交互观感与常见登录界面的账号/密码输入框一致;文本超出框宽时自动横向滚动,
* 保证插入符始终可见。
*
* @param [IN,OUT] g 绘图上下文。
* @param [IN] rect 输入框矩形。
* @param [IN] edit 输入框编辑模型。
* @param [IN] font 文本字体。
* @param [IN] scale DPI 缩放比例。
*/
void UiDrawEditField(gd::Graphics& g, const gd::RectF& rect, const TextEdit& edit, HFONT font,
float scale);
/**
* @brief 绘制一个带边框的复选框。
* @param [IN,OUT] g 绘图上下文。
* @param [IN] rect 复选框矩形。
* @param [IN] state 选中状态:0 未选,1 全选,2 部分选。
* @param [IN] radius 圆角半径。
*/
void UiDrawCheckBox(gd::Graphics& g, const gd::RectF& rect, int state, float radius);
/**
* @brief 绘制颜色样块:叠加不透明度填充,透明度过低时补充描边以保证可辨识。
* @param [IN,OUT] g 绘图上下文。
* @param [IN] rect 样块矩形。
* @param [IN] color 基础颜色(0xAARRGGBB,其 Alpha 通道会被不透明度覆盖)。
* @param [IN] opacity 不透明度(0-1)。
* @param [IN] radius 圆角半径。
* @param [IN] scale DPI 缩放比例,用于推导描边粗细。
* @return 实际填充颜色的 0xAARRGGBB 值(供需要同步其他元素的调用方使用)。
*/
std::uint32_t UiDrawSwatch(gd::Graphics& g, const gd::RectF& rect, std::uint32_t color, float opacity,
float radius, float scale);
/**
* @brief 判断给定不透明度是否低到需要为样块补充描边。
* @param [IN] opacity 不透明度(0-1)。
* @return 需要描边返回 true。
*/
bool UiSwatchNeedsOutline(float opacity);
} // namespace jdi
#endif // __PAINT_UTIL_HPP__