Files
Aislo/B07_DesignDetail/openwebcad/src/integration/aislo-table-bridge.ts
T

81 lines
3.6 KiB
TypeScript

/**
* 부모 화면 ↔ CAD 표 메시지(M02 41장 · 면적산출 범위 → 도면 표). 짝 = `ui_template/cad_host/cad_host.ts`.
* place-table{entity, link} 표 JSON(TableEntity 꼴) → `style.연결 = link` 로 표 놓기 도구(PLACETABLE) 시작
* update-table{link, cells} `style.연결 === link` 인 표의 칸만 갈아 끼움(자리 · 크기 그대로 · 되돌리기 한 걸음)
* → 부모에 table-updated{link, count}
* 놓기 · 갈기 모두 `setEntities(…, true)` 를 거쳐 drawing-changed 가 간다. 확정 · 보기 전용이면 안 함.
*/
import { toast } from 'react-toastify';
import { runCommandInput } from '../commands/run-command.ts';
import type { JsonEntity } from '../entities/Entity.ts';
import { TableEntity } from '../entities/TableEntity.ts';
import type { TableCells } from '../helpers/table-geometry.ts';
import { getEntities, isDrawingReadOnly, isViewOnly, setEntities } from '../state.ts';
import { setPendingTable } from '../tools/annotate/place-table-tool.ts';
export const AISLO_PLACE_TABLE_MESSAGE = 'aislo:b08:place-table';
export const AISLO_UPDATE_TABLE_MESSAGE = 'aislo:b08:update-table';
export const AISLO_TABLE_UPDATED_MESSAGE = 'aislo:b08:table-updated';
/** 두 메시지를 한 꼴로 받음 — place = entity · link · update = link · cells */
interface TableMessage {
type?: string;
entity?: JsonEntity;
link?: string;
cells?: TableCells;
}
/** 이 표가 그 연결의 것인가 */
export const isLinkedTable = (entity: unknown, link: string): entity is TableEntity =>
entity instanceof TableEntity && entity.getStyle().연결 === link;
/** 연결 표마다 칸을 갈아 끼움 — 바꾼 표 수(0 이면 도면을 건드리지 않음) */
export function updateLinkedTables(link: string, cells: TableCells): number {
const tables = getEntities().filter((entity) => isLinkedTable(entity, link));
for (const table of tables) table.replaceCells(cells);
if (tables.length) setEntities([...getEntities()], true);
return tables.length;
}
/** 표 JSON 을 놓기 도구에 맡기고 도구를 켬 */
export async function startPlaceTable(entity: JsonEntity, link: string): Promise<void> {
const table = await TableEntity.fromJson(entity as Parameters<typeof TableEntity.fromJson>[0]);
const linked = new TableEntity(
table.layerId,
table.getOrigin(),
table.getColumnWidths(),
table.getRowHeights(),
table.getCells(),
{ ...table.getStyle(), 연결: link }
);
linked.lineColor = table.lineColor; // 보낸 선 색 · 굵기 그대로
linked.lineWidth = table.lineWidth;
setPendingTable(linked);
runCommandInput('PLACETABLE');
}
const blocked = (): boolean => {
if (!isDrawingReadOnly() && !isViewOnly()) return false;
toast.info('보기 전용 도면 — 표를 넣거나 고치려면 [수정]을 먼저 누르세요.');
return true;
};
/** 표 메시지면 처리하고 true — 아니면 false(다른 메시지 갈래로) */
export async function handleTableMessage(
data: unknown,
notify: (type: string, payload: Record<string, unknown>) => void
): Promise<boolean> {
const message = data as TableMessage | null;
if (!message || typeof message !== 'object') return false;
if (message.type === AISLO_PLACE_TABLE_MESSAGE && message.entity && message.link) {
if (!blocked()) await startPlaceTable(message.entity, message.link);
return true;
}
if (message.type === AISLO_UPDATE_TABLE_MESSAGE && message.link && message.cells) {
const count = blocked() ? 0 : updateLinkedTables(message.link, message.cells);
notify(AISLO_TABLE_UPDATED_MESSAGE, { link: message.link, count });
return true;
}
return false;
}