按钮与面板: - 「系数」按钮改名为「系数/偏移」;点击展开的二级面板在原「系数调整」输入框下方新增「偏移调整」: 与「系数调整」同一套绘制(标题 + 标题栏右侧的还原图标),下面两行分别是「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 零警告。
160 lines
5.6 KiB
C++
160 lines
5.6 KiB
C++
#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__
|