Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UoSr2sqvYtBf1dtQdus88s
81 lines
3.6 KiB
TypeScript
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;
|
|
}
|