自由标记体验重做 + 全部实验性面板可折起

- 网格内固定点:取值胶囊按已放置矩形做纵向避让(不再互相遮挡);行尾 ✕ 改为与
  胶囊同高的正方形;移除固定点的纵向半透明竖线
- 新增「标记透明度」(0–100%),作用于本网格全部固定点的圆点/胶囊/描边/文字/✕;
  半透明时文字改走 GDI+(GDI DrawTextW 忽略 alpha),100% 时像素零变化;
  ≤2% 时不绘制且不登记 ✕ 命中矩形(看不见的按钮不可点)
- 面板按信号分组:信号色托底分组栏(展开三角 + 信号名 + N 标记点 + ✕,文字/三角/✕
  一律用自适应对比色),点击分组栏收起/展开;条目五列(值/枚举/增量/时刻/间隔),
  首项增列与 Δt 显示 N/A,整个面板没有枚举文本时枚举列整列缺省;行尾仍有 ✕
- 面板内容超高时右侧出现滚动条(分组栏与条目一起滚动),滚轮在内容区翻页;
  底部按钮与「标记透明度」滑块固定在底部、不参与滚动
- 底部按钮改为「光标选取模式」切换类按钮(外观与工具栏切换按钮一致,激活高亮),
  激活时其上方出现「标记透明度」滑动条(与信号样式区的透明度滑块同款)
- 所有实验性功能浮动面板支持展开/折起:标题栏 GX 徽标左侧新增「三角 + 横线」指示器,
  单击切换、双击标题栏切换;折起的面板只有标题栏
- 数据层:LanePanelState.collapsed、Lane.freeMarkerOpacity/freeMarkerScroll/
  freeMarkerCollapsedGroups,LaneCarry 与 SplitLane 一并继承
- 验证:新增离屏 .preflight/perf/mark2check 69/69(含两组 A/B);回归 datacheck 69/69、
  verify 49/49、panelanim 158/158、errcheck 19/19;make release/debug 零警告
This commit is contained in:
DeepSeek-V4.1-Flash committed 2026-10-21 02:59:05 +08:00
1 parent 067128f46c
commit 3400ac7c29
9 files changed
+1225 -202

No files matched your search

+107 -10
View File
@@ -57,7 +57,9 @@ namespace jdi
EDGE_PANEL_MOVE, /**< 拖动边沿计数浮动面板。 */
PEAK_LEVEL, /**< 拖动「弱峰调整」某信号的幅度滑块(-400% – +400%)。 */
PEAK_ITERATIONS, /**< 拖动「弱峰调整」某信号的迭代次数滑块(1 … 该信号自定义上限)。 */
LANE_REORDER /**< 拖动网格图例中的 GX 编号徽标:上下调整网格次序。 */
LANE_REORDER, /**< 拖动网格图例中的 GX 编号徽标:上下调整网格次序。 */
MARKER_OPACITY, /**< 拖动「自由标记」面板的「标记透明度」滑块。 */
MARKER_SCROLL /**< 拖动「自由标记」面板内容的滚动条滑块。 */
};
/**
@@ -969,6 +971,46 @@ namespace jdi
*/
bool ToggleLaneFreeMarkerCursor(int laneIndex);
/**
* @brief 设置某网格「自由标记」固定点的**显示不透明度**(0–1)。
*
* 只影响网格内固定数据点的显示内容(数据点 / 取值胶囊 / ✕),
* 面板自身的像素与交互不受影响。
*/
bool SetLaneFreeMarkerOpacity(int laneIndex, float opacity);
/**
* @brief 设置某网格「自由标记」面板内容的滚动偏移(客户区像素,0 = 顶部)。
* @return 偏移真的发生变化返回 true。
*/
bool SetLaneFreeMarkerScroll(int laneIndex, float scroll);
/**
* @brief 切换某网格「自由标记」面板里某个信号分组的收起状态。
* @return 切换后为「已收起」返回 true。
*/
bool ToggleLaneFreeMarkerGroup(int laneIndex, const SignalRef& ref);
/**
* @brief 切换某个实验性功能浮动面板的**折起**状态(只显示标题栏)。
* @param [IN] laneIndex 网格下标。
* @param [IN] kind 面板种类。
* @param [IN] collapsed 是否折起。
* @return 状态发生变化返回 true。
*/
bool SetLanePanelCollapsed(int laneIndex, EdgePanelKind kind, bool collapsed);
/**
* @brief 查询某个实验性功能浮动面板是否处于折起状态。
*/
bool LanePanelCollapsed(int laneIndex, EdgePanelKind kind) const;
/**
* @brief 切换某个实验性功能浮动面板的折起状态。
* @return 切换后的状态(true = 已折起)。
*/
bool ToggleLanePanelCollapsed(int laneIndex, EdgePanelKind kind);
/**
* @brief 直接把文本解析为网格 Y 轴上限/下限并应用(供菜单内联输入框提交使用)。
* @param [IN] laneIndex 网格下标。
@@ -1595,6 +1637,15 @@ namespace jdi
gd::RectF panel; /**< 面板整体矩形。 */
gd::RectF title; /**< 标题栏(**唯一可拖拽区域**)。 */
gd::RectF close; /**< ✕ 关闭按钮。 */
/**
* @brief 标题栏左侧的「展开 / 折起」三角指示器(三角 + 后方一条横线)。
*
* 单击它切换面板的折起状态;折起后面板只剩标题栏(内容区完全省略)。
* 它位于「GX」编号徽标的**左边**。
*/
gd::RectF disclosure;
/** 面板当前是否处于折起状态(只显示标题栏)。 */
bool collapsed = false;
/**
* @brief 标题栏左侧的「GX」编号徽标。
*
@@ -1654,6 +1705,35 @@ namespace jdi
};
/** 「自由标记」:每个固定点一行(按信号分组、组内按时间升序展开后的顺序)。 */
std::vector<MarkerRow> markerRows;
/**
* @brief 「自由标记」的一个**信号分组栏**(以信号色为托底底色)。
*
* 左侧 = 展开/收起三角 + 信号名;右侧 = 标记点个数(`N 标记点`)+ ✕
*(清除该信号全部固定点)。单击分组栏(✕ 除外)切换收起状态。
* 只有至少有一个固定点的信号才会有分组栏。
*/
struct MarkerGroup
{
SignalRef ref;
gd::RectF header; /**< 分组栏托底矩形。 */
gd::RectF triangle; /**< 展开/收起三角的命中矩形。 */
gd::RectF close; /**< 右侧✕的命中矩形。 */
bool collapsed = false;
};
/** 「自由标记」:信号分组栏(顺序与面板显示顺序一致)。 */
std::vector<MarkerGroup> markerGroups;
/**
* @brief 「自由标记」面板的**可滚动内容区**(分组栏 + 固定点条目)。
*
* 内容高度超过它时出现上下滚动条(不参与滚动的按钮与透明度滑块在它下方)。
*/
gd::RectF content;
/** 「自由标记」面板的**内容总高度**(含被滚动出去的条目),用于换算滚动比例。 */
float markerContentHeight = 0.0f;
gd::RectF scrollTrack; /**< 内容区右侧的滚动条轨道(不需要滚动时为空矩形)。 */
gd::RectF scrollThumb; /**< 滚动条滑块。 */
gd::RectF opacityTrack; /**< 「标记透明度」滑动条轨道(仅光标模式激活时非空)。 */
gd::RectF opacityValue; /**< 「标记透明度」数值文本矩形。 */
/**
* @brief 「自由标记」:每个信号名右侧的「清除该信号全部固定点」✕。
*
@@ -1667,25 +1747,29 @@ namespace jdi
*/
std::vector<gd::RectF> rowNameRects;
/**
* @brief 「自由标记」面板的四列文本区(① 取值 ② 增量 ③ 时刻 ④ 间隔)。
* @brief 「自由标记」面板的五列文本区
* (① 取值 ② 枚举文本 ③ 增量 ④ 时刻 ⑤ 间隔)。
*
* 每行都在这四列的**同一横坐标**上左对齐输出,因此同一信息在纵向上严格对齐
*(用户 2026-10-20 明确要求:"将每个信息元素纵向对齐")。
* 每行都在这五列的**同一横坐标**上左对齐输出,因此同一信息在纵向上严格对齐。
* 列宽固定(不按文本测量),绘制时用 `UiEllipsize` 截断,避免布局期查询采样。
* 当整个面板里没有任何枚举文本时,② 枚举列的宽度为 0(整列缺省)。
*/
struct MarkerColumn
{
float left = 0.0f;
float width = 0.0f;
};
std::array<MarkerColumn, 4> markerColumns{};
/** 四列的语义下标(`markerColumns` 的索引)。 */
std::array<MarkerColumn, 5> markerColumns{};
/** 面板里是否存在枚举文本(为 false 时 ② 列整列缺省)。 */
bool markerHasEnumColumn = false;
/** 五列的语义下标(`markerColumns` 的索引)。 */
enum MarkerColumnIndex
{
MARKER_COL_VALUE = 0,
MARKER_COL_DELTA = 1,
MARKER_COL_TIME = 2,
MARKER_COL_DT = 3
MARKER_COL_ENUM = 1,
MARKER_COL_DELTA = 2,
MARKER_COL_TIME = 3,
MARKER_COL_DT = 4
};
};
@@ -1776,9 +1860,11 @@ namespace jdi
* @param [IN] color 信号色。
* @param [IN] close ✕ 按钮矩形(宽度为 0 表示不画)。
* @param [IN] closeHot ✕ 是否处于悬停态。
* @param [IN] alphaScale 整体不透明度系数(1 = 不透明;固定点受「标记透明度」控制)。
*/
void PaintFreeMarkerCapsule(gd::Graphics& g, const gd::RectF& label, const std::wstring& text,
std::uint32_t color, const gd::RectF& close, bool closeHot);
std::uint32_t color, const gd::RectF& close, bool closeHot,
float alphaScale = 1.0f);
/**
* @brief 计算某个固定点相对**同信号**前一个固定点的增量与其时间间隔。
@@ -2576,6 +2662,17 @@ namespace jdi
/** 正在编辑的固定点(`m_editLane` 网格内的 `freeMarkerItems` 下标)。 */
std::size_t m_editMarkerIndex = static_cast<std::size_t>(-1);
/** 「标记透明度」滑块拖拽的目标网格(-1 = 未拖拽)。 */
int m_markerOpacityDragLane = -1;
/** 面板内容滚动条拖拽的目标网格(-1 = 未拖拽)。 */
int m_markerScrollDragLane = -1;
/** 按下滑块时鼠标相对滚动条滑块上沿的偏移(避免滑块跳动)。 */
float m_markerScrollGrabOffset = 0.0f;
/** 「自由标记」面板:分组栏三角的悬停态(用于给出可点击提示)。 */
int m_freeMarkerTriangleHoverLane = -1;
SignalRef m_freeMarkerTriangleHoverSignal;
int m_mouseX = 0; /**< 最近一次鼠标横坐标(用于悬停提示定位)。 */
int m_mouseY = 0; /**< 最近一次鼠标纵坐标(用于悬停提示定位)。 */
bool m_spanHover = false; /**< 鼠标是否悬停在双光标差值标签上。 */