Files
Aislo/M02_MasterTemplete/M02_MasterTemplete_DrawingCard.ts
T
eomsangdonandClaude Opus 5.5 ad511175bf fix(m02): 셀 밀기 · 당기기에 이름 따라감 · 카드 도면 저장도 표 없는 연결표 줄 뺌(114-2)
- 칸 삽입 · 삭제 창(밀기 · 당기기) — 띠 안에 통째로 든 이름정의 범위를 같이 옮김 · 되돌리기 한 걸음
- 연결표 맞춤 몸을 fitLinks 로 떼어 도면 상세 · 카드 도면 저장이 같이 씀
- 시험 — 밀기 여섯 갈래 · 카드 저장 줄 빼기

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MgChuAcyBqUkhHMTXomQC7
2026-10-08 18:28:48 +09:00

160 lines
6.9 KiB
TypeScript

/* =============================================================================
* M02_MasterTemplete_DrawingCard.ts
* 항목 카드 「도면 정보」 미리보기 — 고칠 수 있으면 메뉴(제목줄 · 리본 · 패널 · 상태줄) 없이
* **단축키로 그리기 · 고치기**(전체 편집기 [도면 수정]과 같은 웹캐드 · 같은 단축키) · 카드 [저장]
* (전체 편집기와 같은 저장 길 = 그 항목 구조물 도면 파일 `도면` · `더한장` 칸을 갈아 끼움 · PLAN 31-4).
* 여러 장은 공용 탭 줄(고르기만 · 105-3) — 저장은 지금 탭이 아니라 문서 전체(`getDoc`).
* [저장] · ? · 점(●) · 알림 글은 공용 카드 틀(`M02_MasterTemplete_CardShell` · 31-7) — 여기는 CAD 와 저장 길만.
* 고칠 수 없으면(읽기 층 · 저장 길 없는 자료 자리) 예전처럼 보기만.
* CAD 앱은 안 고침 — 메뉴는 같은 출처 iframe 에 스타일을 얹어 숨김.
* ========================================================================== */
import type { StructureDoc } from "./M02_MasterTemplete_Api_Fetch";
import { fitLinks } from "./M02_MasterTemplete_AreaToDrawing";
import type { SaveControl } from "./M02_MasterTemplete_CardShell";
import {
mountStructureSheets,
type DrawingTemplateOptions,
type StructureSheetsHandle,
} from "./M02_MasterTemplete_Drawing";
import type { ItemSource } from "./M02_MasterTemplete_ItemSource";
export const DRAWING_HELP = "단축키 — 글자를 치고 Enter";
/** 단축키 도움말 — 전체 편집기 명령 별칭(openwebcad `commands.*.ts`)과 같은 것만 */
export const DRAWING_KEYS: [string, string][] = [
["L · PL", "선 · 폴리선"],
["C · A · REC", "원 · 호 · 사각형"],
["T · DT", "글(여러 줄 · 한 줄)"],
["DLI", "치수"],
["M · CO · RO", "옮기기 · 복사 · 회전"],
["SC · MI · O", "축척 · 대칭 · 간격 띄우기"],
["TR · EX · F", "자르기 · 연장 · 모깎기"],
["E · Delete", "지우기"],
["누름 · 끌기 · Ctrl+A", "고르기 · 전부"],
["Esc", "고름 풀기 · 명령 멈춤"],
["Ctrl+Z · Ctrl+Y", "되돌리기 · 다시 하기"],
["Ctrl+S", "저장(카드 [저장]과 같음)"],
["휠 · 가운데 끌기", "확대·축소 · 화면 옮기기"],
];
/** 보기만 = 제목줄 · 리본만 숨김(예전 그대로) · 고치기 = 패널 · 상태줄까지(명령 안내 줄은 남김) */
const HIDE_VIEW = ".cad-titlebar, .cad-ribbon { display: none !important; }";
const HIDE_EDIT =
".cad-titlebar, .cad-ribbon, .cad-inspector, .cad-statusbar, .cad-quick-access" +
" { display: none !important; }";
/** 같은 출처 iframe 안쪽에 스타일 한 벌 — 다시 뜨면(load) 또 얹음 */
function hideChrome(frame: HTMLIFrameElement, css: string): void {
const apply = (): void => {
const inner = frame.contentDocument;
if (!inner?.head || inner.getElementById("m02-struct-hide")) return;
const style = inner.createElement("style");
style.id = "m02-struct-hide";
style.textContent = css;
inner.head.append(style);
};
frame.addEventListener("load", apply);
apply();
}
/** 고칠 수 있나 — 층 권한 + 자료 자리에 저장 길(`write`) */
export const drawingEditable = (editable: boolean, source: ItemSource): boolean =>
editable && !!source.write;
type Where = Pick<ItemSource, "layer" | "projectId">;
/** 구조물 도면 미리보기 한 벌 — 카드 · 면적산출 도면 패널이 같이 씀 · `hooks` 있으면 고치기 */
function mountStructure(
host: HTMLElement,
doc: StructureDoc,
source: Where,
column: string,
hooks?: Pick<DrawingTemplateOptions, "onChanged" | "onSave">,
): StructureSheetsHandle {
const edit = !!hooks;
const sheets = doc as unknown as Parameters<typeof mountStructureSheets>[1];
// 여러 장(82-2) = 공용 탭 줄 고르기만(105-3) · 도각 `{{도면번호}}` = 장 도번
const handle = mountStructureSheets(host, sheets, {
readOnly: !edit,
name: `preview:${column}`, // 자동백업 칸은 전체 편집 화면과 갈라 둠
layer: source.layer,
projectId: source.projectId,
panelsCollapsed: true,
preview: !edit, // 보기만 = 왼쪽 끌기 화면 옮기기 · 고치기 = 누름 고르기 · 단축키
originMarker: true, // 좌표 0,0 기준점 십자
noArea: true, // 작도 영역 칸 없음
frame: true, // 도각 = 보여주기만 · 외곽 좌하단 (0,0)(56장)
noImport: true, // 파일 불러오기는 도면 상세에서만(47-2)
pickTabs: true,
...hooks,
});
const frame = host.querySelector("iframe");
if (frame) hideChrome(frame, edit ? HIDE_EDIT : HIDE_VIEW);
return handle;
}
/** 보기만 도면 — 카드 미리보기의 보기 갈래와 같은 길(확대 · 이동만 · 면적산출 오른쪽 도면 패널 47-6) */
export function mountDrawingView(
host: HTMLElement,
doc: StructureDoc,
source: Where,
column: string,
): { destroy: () => void } {
const handle = mountStructure(host, doc, source, column);
return { destroy: () => handle.destroy() };
}
export interface DrawingCardOptions {
/** 구조물 도면 문서 통째(`도번` · `도면` …) — 저장은 `도면` · `더한장` 칸만 갈아 끼움 */
doc: StructureDoc;
/** 읽은 판 — 저장 때 보냄(다르면 409) */
version: string | null;
source: ItemSource;
column: string;
/** 고칠 권한(층) — 자료 자리에 저장 길(`write`)도 있어야 고치기 */
editable: boolean;
/** 카드 [저장] · 점(●) — 공용 틀(31-7) */
saver: SaveControl;
}
export interface DrawingCardHandle {
/** 저장 길 한 번(카드 [저장] · 위 [저장]이 틀의 `run` 으로 부름) — 못 하면 던짐 */
write: () => Promise<void>;
destroy: () => void;
}
export function mountDrawingCard(host: HTMLElement, opt: DrawingCardOptions): DrawingCardHandle {
const write = opt.source.write;
const edit = drawingEditable(opt.editable, opt.source);
let doc = opt.doc;
let version = opt.version ?? "";
/** 전체 편집기 [저장]과 같은 길 — 읽은 문서에 `도면` · `더한장`(모든 장)을 갈아 끼워 그 항목 파일에
* (실패는 던짐) · CAD Ctrl+S 가 넘기는 지금 탭 장은 안 씀 — 2장 보다 저장해도 1장 그대로(105-3) ·
* 도면에서 지운 표의 연결표 줄은 뺌(114-2 · 도면 상세 저장과 같은 몸) */
async function doSave(): Promise<void> {
if (!write) return;
const next = fitLinks({
...doc,
...((await handle.getDoc()) as Pick<StructureDoc, "도면" | "더한장">),
});
version = (await write("structure", opt.column, version, next)).판;
doc = next;
}
const handle = mountStructure(
host,
doc,
opt.source,
opt.column,
edit
? {
onChanged: (dirty: boolean) => opt.saver.mark(dirty),
onSave: () => void opt.saver.run(() => doSave()),
}
: undefined,
);
return { write: () => doSave(), destroy: () => handle.destroy() };
}