Files
Aislo/B07_DesignDetail/openwebcad/src/integration/aislo-table-bridge.ts
T
eomsangdonandClaude Sonnet 5.5 5638bd5101 feat(M02): 면적 값 고침이 저장 전 도면 패널 표에 바로 비침 · 이름 · 보내기 취소는 [저장] 때 서버가 기록(112-1·112-2)
- 112-1 면적 표 변환을 공용 파일(spreadsheet_area_table.ts)로 빼 서버 Node 와 브라우저가 한 벌로 씀 · 도면 패널이 칸 고침마다(값 바뀐 표만 · 펼친 동안만) CAD 연결 표 갈기를 보기 전용 갈음(preview)으로 보냄
- 112-2 보낸 범위 이름은 도면 [저장] 요청 안에서 서버가 면적 문서에 둠(놓기만 하고 저장 안 하면 안 생김) · [보내기 취소]는 화면에서만 빼고 면적 [저장] 때 서버가 연결표 줄 · 이름을 뺌 · /name · /unlink 길 삭제

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MgChuAcyBqUkhHMTXomQC7
2026-10-08 17:36:44 +09:00

88 lines
4.1 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, preview?} `style.연결 === link` 인 표의 칸만 갈아 끼움(자리 · 크기 그대로 · 되돌리기 한 걸음)
* → 부모에 table-updated{link, count} · preview 면 보기 전용이어도 갈음(M02 면적 도면 패널 · 112-1)
* place-cancelled{} (CAD → 부모) 표를 놓지 않고 Esc 로 끝남
* 놓기 · 갈기 모두 `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, setPlaceCancelHandler } 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';
export const AISLO_PLACE_CANCELLED_MESSAGE = 'aislo:b08:place-cancelled';
/** 두 메시지를 한 꼴로 받음 — place = entity · link · update = link · cells */
interface TableMessage {
type?: string;
entity?: JsonEntity;
link?: string;
cells?: TableCells;
/** update 전용 — 보기 전용 미리보기 패널이 저장 전 값을 비춤(도면 문서는 안 고침 · 보기 전용이어도 갈음) */
preview?: boolean;
}
/** 이 표가 그 연결의 것인가 */
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()) {
setPlaceCancelHandler(() => notify(AISLO_PLACE_CANCELLED_MESSAGE, {}));
await startPlaceTable(message.entity, message.link);
}
return true;
}
if (message.type === AISLO_UPDATE_TABLE_MESSAGE && message.link && message.cells) {
const count = message.preview || !blocked() ? updateLinkedTables(message.link, message.cells) : 0;
notify(AISLO_TABLE_UPDATED_MESSAGE, { link: message.link, count });
return true;
}
return false;
}