组件基础状态契约
DirectSurface UI 的业务组件应把基础状态暴露为可由页面状态直接驱动的公开能力。业务权限、流程状态、表单模式和上下文切换可以在业务层计算,但组件本身需要提供一致的 UI 表达和交互清理。
状态分层
| 状态 | 所属层级 | 语义 | 典型来源 |
|---|---|---|---|
visible |
所有 RenderObject |
是否参与布局、绘制、hit test 和焦点。 | 权限、页面模式、条件字段。 |
disabled |
可交互控件 | 控件不可操作,不进入焦点顺序,清理 hover、pressed、popup、拖拽等临时状态。 | 权限不足、业务条件不满足、流程锁定。 |
readonly |
输入或选择控件 | 值可展示,通常可复制或查看,但不能修改。 | 审核模式、归档记录、只读详情页。 |
visible 是基础渲染状态,所有 render object 都继承。disabled 和 readonly 是组件公开 API,只有具备对应交互语义的组件才提供。
visible
object.visible = false 表示折叠隐藏:
- 不参与父布局。
- 不绘制。
- 不参与 hit test。
- 不进入焦点顺序。
- 对已有焦点的控件,组件基础类会在隐藏时释放焦点。
业务权限只需要控制组件是否出现时,优先使用 visible。如果需要保留布局占位但临时不绘制,使用 RenderVisibility 的 hidden 模式。
disabled
disabled 表示控件当前不可操作。可交互组件提供整体禁用能力时,应满足:
- 禁用后不响应 pointer、keyboard、shortcut 或 popup 激活。
- 禁用后从
FocusManager的焦点顺序中移除。 - 若禁用前持有焦点,立即释放焦点。
- 清理 hover、pressed、keyboard active、拖拽、弹窗、菜单、临时捕获等内部状态。
- 视觉上使用主题的 disabled 状态色。
局部项也可以有自己的 disabled,例如菜单项、面包屑项、工具栏项或单选选项。整体 disabled 优先级更高:整体禁用后所有子项都按不可交互处理。
readonly
readonly 用于值类控件,表达“可看但不可改”。它和 disabled 的区别是:
| 行为 | readonly |
disabled |
|---|---|---|
| 展示当前值 | 是 | 是 |
| 编辑值 | 否 | 否 |
| 焦点 | 由组件语义决定 | 否 |
| 文本选择或复制 | 输入类控件通常允许 | 通常不允许 |
| 视觉 | 保持可读状态 | 使用 disabled 弱化状态 |
例如 RenderTextBox 和 RenderTextArea 在只读时仍适合展示可复制内容;下拉选择器、日期选择器、颜色选择器在只读时不应打开 popup。
业务接入建议
业务层负责计算权限和状态,组件层负责执行 UI 状态:
saveButton.disabled = !canSave
advancedPanel.visible = canViewAdvanced
patientName.readonly = isArchived
对于命令型入口,优先使用命令系统统一计算 visible/enabled,再把结果映射到按钮、菜单和工具栏。对于纯表单或页面局部状态,可以直接设置组件的 visible、disabled 或 readonly。
状态变化后,如果修改会影响布局,例如 visible、文本长度、字段结构或分组内容,需要让父布局重新 layout。单纯 disabled/readonly 通常只需要组件自身重绘,组件 setter 会处理。