diff --git a/docs/api/XCEngine/UI/Widgets/UIDragDropInteraction/UIDragDropInteraction.md b/docs/api/XCEngine/UI/Widgets/UIDragDropInteraction/UIDragDropInteraction.md new file mode 100644 index 00000000..25248451 --- /dev/null +++ b/docs/api/XCEngine/UI/Widgets/UIDragDropInteraction/UIDragDropInteraction.md @@ -0,0 +1,51 @@ +# UIDragDropInteraction + +**命名空间**: `XCEngine::UI::Widgets` + +**类型**: `header-only state model + free functions` + +**头文件**: `XCEngine/UI/Widgets/UIDragDropInteraction.h` + +**描述**: XCUI 拖放交互 helper,定义拖放 payload、source/target 描述、会话状态与一组纯头文件状态迁移函数。 + +## 概览 + +当前公开声明可以分成四层: + +- `UIDragDropOperation` + - `Copy / Move / Link` 三种操作位,以及 `|`、`&`、`|=` 辅助运算。 +- `UIDragDropPayload` / `UIDragDropSourceDescriptor` / `UIDragDropTargetDescriptor` + - 描述拖拽源、目标和 payload 类型约束。 +- `UIDragDropState` / `UIDragDropResult` + - 保存拖放会话当前状态,以及每一步更新后回传给调用方的快照结果。 +- 一组状态迁移函数 + - `BeginUIDragDrop(...)` + - `UpdateUIDragDropPointer(...)` + - `UpdateUIDragDropTarget(...)` + - `EndUIDragDrop(...)` + - `CancelUIDragDrop(...)` + +## 当前实现行为 + +- `BeginUIDragDrop(...)` 要求 `ownerId != 0` 且 `allowedOperations != None`,否则直接失败。 +- 拖放开始后先进入 `armed` 状态;只有指针移动距离达到 `activationDistance`,`UpdateUIDragDropPointer(...)` 才会把它提升为 `active`。 +- `DoesUIDragDropPayloadTypeMatch(...)` 在 `acceptedPayloadTypes` 为空时会把目标视为“接受任意类型”。 +- `ResolveUIDragDropOperation(...)` 只会在 source 允许集和 target 接受集的交集中选择操作,并优先满足 target 的 preferred operation。 +- `UpdateUIDragDropTarget(...)` 在拖拽未激活、target 为空或类型/操作不匹配时,会清空当前 target 解析结果。 +- `EndUIDragDrop(...)` 只有在 `active == true` 且 target 已解析完成时才返回 `completed = true`;否则统一记为 `cancelled = true`。 +- 这些 helper 不依赖具体 widget 类型,本质上只是在维护一份 UI 拖放状态机。 + +## 测试与调用链 + +- `tests/UI/Core/unit/test_ui_drag_drop_interaction.cpp` 当前覆盖: + - payload type 匹配与操作解析 + - activation distance 门槛 + - target 接受/拒绝后的状态快照一致性 + - 完成与取消路径的结果回填 +- `tests/UI/Core/integration/shared/src/DragDropValidationScene.h` 当前直接包含这组 helper,作为交互验证场景的一部分。 + +## 相关文档 + +- [Widgets](../Widgets.md) +- [UISelectionModel](../UISelectionModel/UISelectionModel.md) +- [UIScreenDocumentHost](../../Runtime/UIScreenDocumentHost/UIScreenDocumentHost.md) diff --git a/docs/api/XCEngine/UI/Widgets/UIScrollModel/UIScrollModel.md b/docs/api/XCEngine/UI/Widgets/UIScrollModel/UIScrollModel.md new file mode 100644 index 00000000..bec08c45 --- /dev/null +++ b/docs/api/XCEngine/UI/Widgets/UIScrollModel/UIScrollModel.md @@ -0,0 +1,50 @@ +# UIScrollModel + +**命名空间**: `XCEngine::UI::Widgets` + +**类型**: `free functions + result struct` + +**头文件**: `XCEngine/UI/Widgets/UIScrollModel.h` + +**源文件**: `engine/src/UI/Widgets/UIScrollModel.cpp` + +**描述**: XCUI 纵向/横向滚动的纯函数模型,负责 overflow 计算、offset 裁剪、滚轮步进和“保证某个项可见”的偏移修正。 + +## 概览 + +当前公开声明包括: + +- `UIScrollWheelResult` + - 返回滚轮处理前后 offset、overflow 和是否真的发生变化。 +- `ComputeUIScrollOverflow(...)` + - 计算 `contentExtent - viewportExtent` 的有效溢出。 +- `ClampUIScrollOffset(...)` + - 把 offset 约束到 `[0, overflow]`。 +- `ApplyUIScrollWheel(...)` + - 把鼠标滚轮 delta 映射到新的滚动偏移。 +- `EnsureUIScrollOffsetVisible(...)` + - 让指定 item 区间滚进当前 viewport。 + +## 当前实现行为 + +- `ComputeUIScrollOverflow(...)` 使用 `max(0, contentExtent - viewportExtent)`,没有负溢出概念。 +- `ClampUIScrollOffset(...)` 总是把结果限制在 `0` 到 `overflow` 之间。 +- `ApplyUIScrollWheel(...)` 以 `120` 为一个标准滚轮单位,默认 `wheelStep = 48.0f`。 +- 当 `overflow <= 0`、`fabs(wheelDelta) <= epsilon` 或 `wheelStep <= 0` 时,滚轮处理会直接返回 no-op。 +- `ApplyUIScrollWheel(...)` 会先裁剪传入 offset,再计算变化,因此返回结果始终基于有效滚动区间。 +- `EnsureUIScrollOffsetVisible(...)` 会把 item 的 `[itemStart, itemStart + itemExtent]` 区间推回 viewport 内,但最终仍会再次 clamp。 + +## 测试与调用链 + +- `tests/UI/Core/unit/test_ui_scroll_model.cpp` 当前覆盖: + - overflow 与 clamp 的边界 + - 默认滚轮步长 `48` + - 被裁剪的 no-op 返回 + - `EnsureUIScrollOffsetVisible(...)` 的可见性修正 +- `engine/src/UI/Runtime/UIScreenDocumentHost.cpp` 当前直接包含这组 helper,用于 runtime 文档宿主的滚动计算。 + +## 相关文档 + +- [Widgets](../Widgets.md) +- [UIKeyboardNavigationModel](../UIKeyboardNavigationModel/UIKeyboardNavigationModel.md) +- [UIScreenDocumentHost](../../Runtime/UIScreenDocumentHost/UIScreenDocumentHost.md) diff --git a/docs/api/XCEngine/UI/Widgets/Widgets.md b/docs/api/XCEngine/UI/Widgets/Widgets.md index 725d258b..d48bdd91 100644 --- a/docs/api/XCEngine/UI/Widgets/Widgets.md +++ b/docs/api/XCEngine/UI/Widgets/Widgets.md @@ -6,7 +6,7 @@ **头文件目录**: `engine/include/XCEngine/UI/Widgets/` -**描述**: XCUI widget 状态与交互辅助层,覆盖选择、展开、键盘导航、popup overlay、property edit、splitter interaction 和 tab-strip model。 +**描述**: XCUI widget 状态与交互辅助层,覆盖选择、展开、键盘导航、popup overlay、property edit、drag-drop、scroll、splitter interaction 和 tab-strip model。 ## 当前范围 @@ -20,8 +20,12 @@ - popup 链管理、dismiss 规则和 placement 求解。 - [UIPropertyEditModel](UIPropertyEditModel/UIPropertyEditModel.md) - inspector 风格的 staged property edit 会话状态。 +- [UIDragDropInteraction](UIDragDropInteraction/UIDragDropInteraction.md) + - 通用拖放 payload、target 解析与完成/取消状态机。 - [UISelectionModel](UISelectionModel/UISelectionModel.md) - 单选 id 状态模型。 +- [UIScrollModel](UIScrollModel/UIScrollModel.md) + - overflow、滚轮步进和可见性修正的纯函数滚动模型。 - [UISplitterInteraction](UISplitterInteraction/UISplitterInteraction.md) - splitter handle hit-test 与拖拽状态 helper。 - [UITabStripModel](UITabStripModel/UITabStripModel.md)