# 颜色 / 线型 / 图案 / 块 / 图层 选择器

> 文档：`vjcad/doc/ui/pickers.md`
> 示例：`vjcad/example/ui/04yesnodialog.js` — 对话框基础用法
vjcad 提供一组与 AutoCAD 习惯一致的"选择器"对话框，统一由 `start...Dialog(opts)` 启动并 `await` 结果。

## 1. 颜色：`ColorPanelDialog`

```js
const dialog = new ColorPanelDialog();
const result = await dialog.startColorDialog({
    color: 1,                           // 当前 ACI 颜色索引（1=红，7=白/黑，...）
    disabledByLayerAndByBlock: false
});

if (result !== undefined) {
    // 返回值是字符串：可能是 '1'、'ByLayer'、'ByBlock'、'Red'、'#FF8000' 等——Number() 会得到 NaN
    const colorIndex = colorNameToIndex(result);   // 顶层导出，ByLayer→256、ByBlock→0、#RRGGBB→RGB 真彩索引
    selected.forEach(e => e.color = colorIndex);
    Engine.regen();
}
```

特性：

- 三栏布局：256 ACI / RGB 选择 / `ByLayer` / `ByBlock`（可禁用后两个）
- `ColorDialogOptions` 字段：`{ color: number, disabledByLayerAndByBlock: boolean }`；返回 `string | undefined`（取消为 `undefined`），用 `colorNameToIndex(result)` 转颜色索引

## 2. 线型：`LineTypeDialog`

```js
const dlg = new LineTypeDialog();
const r = await dlg.startLineTypeDialog({
    selectedName: 'Continuous',
    disabledByLayerAndByBlock: false  // 是否禁用 ByLayer/ByBlock
});

if (r !== undefined) {
    selected.forEach(e => e.lineType = r);   // 返回线型名字符串
    Engine.regen();
}
```

返回 `string | undefined`（线型名；取消为 `undefined`）。

### 内置线型名（节选）

`Continuous` `ByLayer` `ByBlock` `Hidden` `Dashed` `Dotted` `Center` `Phantom` `Dashdot`

## 3. 线型编辑 / 查看

```js
const ltEditor = new LinetypeEditorDialog();
const r = await ltEditor.startDialog(linetypeContent);   // 返回编辑后的 .lin 内容或 undefined
// 编辑结果由调用方写回 Engine.linetypeManager

const ltViewer = new LinetypeViewerDialog();
await ltViewer.startDialog();   // 只读预览（内部 loadLinetypeContent）
```

## 4. 图案填充：`PatternPickerDialog`

```js
const dlg = new PatternPickerDialog();
const r = await dlg.startPatternDialog({
    selectedPattern: 'ANSI31'   // PatternDialogOptions 只有 selectedPattern 一个字段
});

if (r !== undefined) {
    // r 为选中的图案名字符串；HatchEnt 为无参构造，字段用 setter 逐个设置
    const hatch = new HatchEnt();
    hatch.loops = loops;              // Edges 边界环
    hatch.patternName = r;
    hatch.patternScale = 1.0;
    hatch.patternAngle = 0;
    Engine.addEntities(hatch);
}
```

返回 `string | undefined`（图案名；取消为 `undefined`）。

### 内置图案（节选）

`SOLID` `ANSI31` `ANSI32` `ANSI37` `BRICK` `EARTH` `GRASS` `HONEY` `LINE` `NET` `STARS`

## 5. 图案编辑 / 查看

```js
const patEditor = new PatternEditorDialog();
await patEditor.startDialog(patternContent);   // 返回编辑后内容或 undefined

const patViewer = new PatternViewerDialog();
await patViewer.startDialog();   // 只读预览（内部 loadPatternContent）
```

编辑器支持 `.pat` 文件加载 / 导出。

## 6. 块名：`BlockNameDialog`

```js
const dlg = new BlockNameDialog();
const r   = await dlg.showBlockNameDialog('');   // 参数是初始块名字符串

if (r !== undefined) {
    // r 为块名字符串；InsertEnt 构造是位置参数且第一个参数是 blockId
    // const blockId = Engine.currentDoc.blocks.itemByName(r).blockId;   // BlockDefinition 的字段是 blockId，没有 objectId
    // const insert = new InsertEnt(blockId, new Point2D(0,0), 1, 0);
    // Engine.addEntities(insert);
}
```

返回 `string | undefined`（用户输入的块名；取消为 `undefined`）。注意它返回的是 **名字** 不是 blockId，插块时先 `Engine.currentDoc.blocks.itemByName(r)` 取块定义。

## 7. 图层名：`LayerNameDialog`

```js
const dlg = new LayerNameDialog();
const r   = await dlg.showLayerNameDialog('0');   // 参数是初始图层名字符串

if (r !== undefined) {
    selected.forEach(e => e.layer = r);   // EntityBase.layer setter 收图层名
    Engine.regen();
}
```

返回 `string | undefined`（图层名；取消为 `undefined`）。

## 8. 在自定义命令里串联使用

```js
class ChangeColorCommand {
    async main() {
        const opt = new SelectionInputOptions();   // 无参构造
        const sel = await Engine.editor.getSelections(opt);
        if (sel.status !== InputStatusEnum.OK || !sel.value?.length) return;

        const dlg = new ColorPanelDialog();
        const r   = await dlg.startColorDialog({ color: sel.value[0].color });
        if (r === undefined) return;

        sel.value.forEach(e => e.color = colorNameToIndex(r));
        Engine.regen();
        message.info(`已修改 ${sel.value.length} 个实体颜色`);
    }
}
CommandRegistry.regist(new CommandDefinition('CHCOLOR', '改颜色', ChangeColorCommand, new CommandOptions()));
```

## 9. 主题与样式

所有 picker 都基于 `BaseDialogComponent`。真实标签名：`ColorPanelDialog` → `<color-dialog>`、`LineTypeDialog` → `<line-type-dialog>`、`PatternPickerDialog` → `<pattern-picker-dialog>`、`BlockNameDialog` → `<block-name-dialog>`、`LayerNameDialog` → `<layer-name-dialog>`。

不要指望页面全局 CSS 给这些标签设 `--dialog-*` 变量来改色：对话框内部的 `<base-dialog>` 在自己的 `:host` 上重新声明了 `--dialog-header-bg / --dialog-contents-color` 等默认值，宿主上设的同名变量只能被继承、压不过它（详见 [dialogs](dialogs.md) 第 8 节）。这几个 picker 的 `<base-dialog>` 没有做 `--theme-color-*` 映射，标题栏用的是固定默认色，`setThemeColors` 也改不动；需要统一风格的选择界面请自己基于 `ModalDialogBase` 写（它把 `--dialog-*` 映射到 `--theme-color-dialog-*`）。

## 红旗

- picker 返回 `undefined` 表示"用户取消"；返回类型多为 `string | undefined`，不是 `{confirmed,...}` 对象
- `LineTypeDialog` 列出的是 `Engine.linetypeManager.getAllLinetypes()` 的**全部**线型（内置 + 已加载），不限于当前文档用过的；对话框自带"加载 .lin"按钮，加载结果写进 `linetypeManager`
- `PatternPickerDialog` 的 `scale` 单位与图档单位一致，超出 100 倍后会渲染极慢
- `BlockNameDialog` 只是名称输入框（`showBlockNameDialog`），不做块创建；新建块走 `BLOCK` 命令或 `Engine.currentDoc.blocks.add(...)`（`WBLOCK` 未注册）
- `LayerNameDialog` 只返回图层名字符串；是否允许新建由调用方判断，创建图层用 `Engine.createLayer(name)`
- 同一时刻 **只能弹一个对话框**；想接二连三弹出请使用 `await` 串联

## 参考（官方文档 MCP）

- 文档：`vjcad/doc/ui/pickers.md`
- 示例：`vjcad/example/ui/04yesnodialog.js` — 对话框基础用法
