# ui / 界面扩展总览

> 文档：`vjcad/doc/ui/index.md`
> 示例：`vjcad/example/ui/01ribbon.js` ~ `16menucustom.js`

UI 模块覆盖三类需求：

1. **现成 UI 组件** —— 用 Toast / 对话框 / 选择器与用户交互，不写 HTML
2. **可插拔扩展点** —— 把自己的按钮、面板、菜单插入到 vjcad 主界面
3. **整体外观与模式** —— 改主题、改状态栏、切换查看 / 编辑模式

## 1. 子文档结构

| 主题 | 文档 | 何时看 |
|---|---|---|
| 对话框 / 消息 / 模态 / 面板基类 | [dialogs](dialogs.md) | 写自定义对话框 |
| 右键菜单 | [contextmenu](contextmenu.md) | 改右键行为 |
| 侧边栏面板 | [sidebar-panel](sidebar-panel.md) | 注册自己的侧边栏 |
| 预览视图（PreviewView） | [preview-view](preview-view.md) | 在对话框里嵌入小预览 |
| 浮动工具栏 | [floating-toolbar](floating-toolbar.md) | 自由拖动的小工具栏 |
| 图标注册 | [icons](icons.md) | 自定义命令的 SVG 图标 |
| 选择器（颜色 / 线型 / 图案 / 块 / 图层） | [pickers](pickers.md) | 调出系统专用 picker |
| 基础控件（输入框 / 按钮 / 线型预览 / message） | [controls](controls.md) | 在自定义面板里复用 vjcad 控件 |
| 主题与状态栏 | [theme-statusbar](theme-statusbar.md) | 切深 / 浅色，控制底栏功能按钮 |
| Viewer 查看模式 | [viewer-mode](viewer-mode.md) | 嵌入只读 / 移动端 / 极简 UI |
| 地图叠加 | [map-overlay](map-overlay.md) | 把 CAD 叠到 vjmap 地图 |

> 菜单与 Ribbon 由插件 / MainView 配置统一驱动，已在 `plugin/menu-ribbon.md` 详述，不再重复。

## 2. 入口 API 速查

```js
// 消息提示（Toast）
message.info('完成');  message.success('保存成功');
message.warn('注意');  message.error('失败原因');

// 命令行打字（HTML 片段）
writeMessage('<br/>已创建实体');

// 对话框（输入 / 选择 / 确认 / 提示）
await showInputDialog({ title, label, defaultValue, validator });
await showSelectDialog({ title, options, defaultValue });
await showConfirm('确定删除？', '删除确认');
await showInfo('已完成');
await showWarningConfirm('不可撤销，确定？');
await showError('保存失败');

// 选择器
await new ColorPanelDialog().startColorDialog(opt);
await new LineTypeDialog().startLineTypeDialog(opt);
await new PatternPickerDialog().startPatternDialog(opt);
await new BlockNameDialog().showBlockNameDialog(name);       // 不是 startXxxDialog
await new LayerNameDialog().showLayerNameDialog(name);       // 不是 startXxxDialog

// 自己写组件
class MyDialog extends ModalDialogBase { /* renderContent */ }
class MyPanel extends ModelessPanelBase { /* renderContent */ }
class MySidebar extends BasePanelComponent { /* render */ }
const tb = createFloatingToolbar('id', { items: [...] });

// 主题 / 状态栏
Engine.THEME_MODE = 0;          // 画布主题 0=深色，1=浅色（自动 setBgc，不改 UI 外壳配色）
Engine.setThemeColors({ accent: '#2563eb' });   // UI 外壳配色（--theme-color-* 变量）
Engine.setBgc(0);               // 画布底灰度 0~255；0=默认深色 #212830，255=白
Engine.ORTHOMODE  = 1;          // 正交
Engine.GRIDMODE   = 1;          // 栅格
Engine.OSMODE     = 1023;       // 对象捕捉位掩码：1~512 全开；|= 16384 为关闭（0xFFFF 含此位=关）

// 整体模式
new MainView({ viewMode: 'viewer', showUcsIcon: false, showAxis: false });
```

## 3. 心智模型

```mermaid
flowchart TB
    subgraph 内置
        T[Toast / Message]
        D[Dialogs / Pickers]
        CM[ContextMenu]
    end
    subgraph 可扩展
        SR[SidebarPanel<br/>BasePanelComponent]
        FT[FloatingToolbar]
        PV[PreviewView]
        MD[ModalDialogBase / ModelessPanelBase]
    end
    subgraph 整体
        TH[Theme / StatusBar]
        VM[viewMode]
        MO[CadMapOverlay]
    end

    User[(开发者)] --> 内置
    User --> 可扩展
    User --> 整体
```

## 4. 共同的红旗

- 大多数对话框 / 弹层走 **Lit + Shadow DOM**，外部 CSS 选择器不能穿透；整体配色用 `setThemeColors` 改 `--theme-color-*` 变量，单个自定义组件在自己的 `static styles` 里改（见 [dialogs](dialogs.md)）
- `await showXxx` / `await dialog.show()` 只能拿用户结果；想在对话框里继续与 CAD 交互（拾取点 / 选择实体），必须 **`baseDialog.suspend()`/`resume()`**，且对话框 **必须在命令上下文里弹出**
- `viewMode: "viewer"` 默认会把多个 UI 组件一并隐藏；若只想关菜单别忘了同时设置 `enableContextMenu / showGrips`
- `Engine.THEME_MODE` 是**画布**主题：setter 自动 `setBgc(0|255)`，但**不改** UI 外壳颜色；UI 配色走 MainView `themeColors` 配置或 `setThemeColors(partial)`
- 浮动工具栏 / 侧边栏 / 模态对话框基于 Web Components，**自定义元素 tagName 必须包含 `-`**

## 参考（官方文档 MCP）

- 文档：`vjcad/doc/ui/index.md`
- 示例：`vjcad/example/ui/01ribbon.js` ~ `16menucustom.js`
