Files
Just-DataInspector/Utilities/Inc/Utf8Util.hpp
T
DeepSeek V4.1 Flash fc77b0262f 「调整」行:系数/偏移 按钮 + 偏移调整(Y 轴/时间轴)二级面板;结算顺序加入偏移;派生信号继承调整变换
按钮与面板:
- 「系数」按钮改名为「系数/偏移」;点击展开的二级面板在原「系数调整」输入框下方新增「偏移调整」:
  与「系数调整」同一套绘制(标题 + 标题栏右侧的还原图标),下面两行分别是「Y轴」「时间轴」,
  每行左侧说明文字、右侧内联输入框(整行数值框)。
- 「Y轴」默认 0.00,非编辑态**始终带正负号**(+0.00 / -12.50),小数不足两位时补两位、更高精度保留更多位。
- 「时间轴」默认 0.00,非编辑态显示与双光标差值同一套复合单位文本(`Δt:500ms`、`Δt:1h 1min 2s`);
  进入编辑态时显示以**秒**为单位的数值,并在输入框最右侧提示单位 `s`。
- 「偏移调整」的还原图标把两个偏移恢复为默认值 0;「系数调整」的还原图标仍只重置系数。
- 面板/输入框的编辑初值与显示文本分离(`MenuItem::editValue` / `editSuffix`),
  非编辑态(`Δt:…`)与编辑态(`3662`)不一致时也能正确回显。

语义与结算顺序:
- 结算顺序变为 **系数 → 绝对值 → 镜像 → 偏移**(前三步不变)。
- Y 偏移:给绘制值加常数(波形上下移动);时间偏移:采样绘制在 `t + offsetTime` 处
  (例如 t=1s、偏移 -0.5s → 画在 0.5s)。
- ⚠️ Y 偏移以**未镜像空间**为准:垂直镜像开关变化时同步取反偏移量,
  使绘制等价于「先加上偏移再镜像」(开关来回切换可逆)。
- 绘制链路全部跟随偏移:`BuildPolyline`(逐点描边 / 像素列包络 / 跨列边界插值 / 粗粒度分组层,
  保序的 Y 偏移直接加在分组极值上)、派生预览曲线、光标取值读数(含 Δt)、
  可见区间 Y 轴自适应、整段自适应的区间映射;折线缓存键、场景指纹、样式快照与图层指纹都纳入两个偏移。

派生信号(实验性功能「构建为新信号」):
- 修复「预览是调整后的波形、构建出来却按原始状态绘制」:新信号**继承源信号的调整变换**
  (系数/绝对值/两个镜像/两个偏移)——网格预览绘制的是 `变换(滤波结果)`,
  而构建出的信号只存了滤波结果,因此必须把变换一并继承;
  时间轴偏移**只能**靠继承(派生信号与源信号共用同一文件时间轴,无法把时间平移烘进数据)。

离屏验证(不干扰用户):
- ⚠️ harness 现在在每次注入鼠标消息后**立即释放本窗口的鼠标捕获**
  (宿主 WM_LBUTTONDOWN 会 SetCapture,隐藏窗口同样会把用户的真实鼠标输入吸走);
  后续消息本来就是直接投递,无需捕获。
- 新增 [AP]:按钮标签不裁切、面板 5 行顺序与「偏移调整」位于系数输入框下方、
  Y轴/时间轴行的标签与输入框同行且默认值/单位提示正确、时间轴编辑态显示秒值并在最右侧提示 `s`、
  Y 偏移提交/显示正负号/波形整体平移量、时间偏移提交/Δt 复合单位(含 3662 → Δt:1h 1min 2s)/
  编辑态为秒、**按"偏移若干个采样点"构造的精确几何验证**(采样被画到移位后的像素位置、且不再画在原处)、
  读数跟随、两个还原图标、垂直镜像对 Y 偏移取反(可逆)、
  以及派生信号继承变换;[AL] 补充「系数→绝对值→镜像→偏移」的顺序与区间映射(含 Y 偏移)。
- 合计 645/645 通过;make clean && make all 零警告。
2026-10-13 17:56:00 +08:00

160 lines
5.6 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 __UTF8_UTIL_HPP__
#define __UTF8_UTIL_HPP__
#include <windows.h>
#include <cstddef>
#include <string>
#include <vector>
namespace jdi
{
/**
* @brief 将 UTF-8 编码的字节序列转换为宽字符串(UTF-16LE)。
* @param [IN] text UTF-8 文本起始地址。
* @param [IN] length 文本字节数,传入负值表示按 '\0' 结尾自动计算长度。
* @return 转换后的宽字符串,输入非法时返回空字符串。
*/
std::wstring Utf8ToWide(const char* text, int length = -1);
/**
* @brief 去除字符串首尾的空白字符(含制表、换行与不间断空格)。
* @param [IN] text 待处理文本。
* @return 去除首尾空白后的新字符串。
*/
std::wstring Trim(const std::wstring& text);
/**
* @brief 去除字符串首尾的成对引号(单引号或双引号)。
* @param [IN] text 待处理文本。
* @return 去除引号后的新字符串。
*/
std::wstring StripQuotes(const std::wstring& text);
/**
* @brief 仅针对 ASCII 字母执行小写转换(其余字符原样保留)。
* @param [IN] text 待处理文本。
* @return 转换后的新字符串。
*/
std::wstring ToLowerAscii(const std::wstring& text);
/**
* @brief 判断字符串是否包含指定子串(ASCII 大小写不敏感)。
* @param [IN] text 被检索文本。
* @param [IN] needle 子串文本。
* @return 包含返回 true,否则返回 false。
*/
bool ContainsInsensitive(const std::wstring& text, const std::wstring& needle);
/**
* @brief 从字符区间中解析一个双精度浮点数(允许尾部存在非数字残留字符)。
* @param [IN] begin 区间起始指针。
* @param [IN] end 区间结束指针(不包含)。
* @param [OUT] value 解析结果输出。
* @return 解析成功返回 true,区间为空或完全无法识别时返回 false。
*/
bool TryParseDouble(const char* begin, const char* end, double& value);
/**
* @brief 以固定小数位格式化数值。
* @param [IN] value 待格式化数值。
* @param [IN] decimals 小数位数。
* @return 格式化后的文本。
*/
std::wstring FormatNumber(double value, int decimals);
/**
* @brief 把字节数格式化为自适应单位的文本(GB / MB / KB),保留两位小数。
*
* 单位阀值:1 GB = 1024 MB、1 MB = 1024 KB;小于 1 KB 时也按 KB 显示。
* 只输出"数字 + 单位"(如 "1.69 GB"),便于拼接为"已读取 / 总量"。
*
* @param [IN] bytes 字节数。
* @return 形如 "812.34 MB" 的文本。
*/
std::wstring FormatByteSize(unsigned long long bytes);
/**
* @brief 以自适应有效位格式化数值(NaN/Inf 会被转换为可读文本)。
* @param [IN] value 待格式化数值。
* @return 格式化后的文本。
*/
std::wstring FormatValue(double value);
/**
* @brief 依据坐标轴刻度步长格式化刻度标签。
* @param [IN] value 刻度值。
* @param [IN] step 刻度步长,用于推断所需小数位。
* @return 刻度标签文本。
*/
std::wstring FormatTick(double value, double step);
/**
* @brief 将整数格式化为带千位分隔符的文本。
* @param [IN] value 待格式化整数。
* @return 格式化后的文本。
*/
std::wstring FormatCount(unsigned long long value);
/**
* @brief 把时间间隔格式化为「Δt 语义」的复合单位文本(不含 "Δt:" 前缀)。
*
* 规则(用户明确要求,与双光标差值的显示完全一致):
* - 顶级单位高于 s(即 h / min)时**一路整合到 s**,例如 3662s → "1h 1min 2s";
* - 顶级单位为 s 及以下时,若不是该单位的整数,则**向下一级递进**,
* 例如 5.06s → "5s 60ms";整秒数不加下级单位,例如 5s → "5s";
* - 顶级单位为 ps 时不再递进次级单位,例如 5.123ps → "5.123 ps"。
*
* @param [IN] seconds 时间间隔(秒)。
* @return 形如 "1h 1min 2s" / "5s 60ms" 的间隔文本。
*/
std::wstring FormatDurationCompound(double seconds);
/**
* @brief 把时间间隔格式化为「秒」数值文本(不含单位),用于内联编辑。
*
* 编辑时的量级**始终是秒**:即使显示为 "1h 1min 2s",进入编辑后也是 3602。
*
* @param [IN] seconds 时间间隔(秒)。
* @return 形如 "3602" 的文本。
*/
std::wstring FormatDurationSeconds(double seconds);
/**
* @brief 计算“美观”的坐标轴刻度步长(1/2/5 乘以 10 的整数次幂)。
* @param [IN] range 坐标轴数值跨度,必须为正数。
* @param [IN] targetTicks 期望的刻度数量。
* @return 刻度步长,输入非法时返回 1.0。
*/
double NiceStep(double range, int targetTicks);
/**
* @brief 依据范围与步长生成刻度值序列。
* @param [IN] minValue 范围下限。
* @param [IN] maxValue 范围上限。
* @param [IN] step 刻度步长。
* @param [OUT] ticks 输出刻度序列(按升序排列)。
*/
void BuildTicks(double minValue, double maxValue, double step, std::vector<double>& ticks);
/**
* @brief 将文本复制到系统剪贴板。
* @param [IN] owner 剪贴板所有者窗口句柄,允许为空。
* @param [IN] text 待复制文本。
* @return 复制成功返回 true。
*/
bool CopyTextToClipboard(HWND owner, const std::wstring& text);
/**
* @brief 从系统剪贴板读取文本。
* @param [IN] owner 剪贴板所有者窗口句柄,允许为空。
* @param [OUT] text 读出的文本,剪贴板无文本时清空。
* @return 读到非空文本返回 true。
*/
bool PasteTextFromClipboard(HWND owner, std::wstring& text);
} // namespace jdi
#endif // __UTF8_UTIL_HPP__