/* ============================================================================= * B05_Profile_UI_RouteEdit_Draft.ts * 노선 편집기 ↔ 계산 묶음 다리(PLAN 346-1) — 노선을 한 번 고칠 때마다(놓기 · 더함 · 지움 · 곡선 · * 되돌리기 · 다시하기 · [반영 전으로] · 추천 [적용]) 노선 초안을 넘김. 끄는 동안은 넘기지 않음 * (사진첩에 쌓이는 때 = 손을 놓은 때). * * 편집기는 사진첩(`_History`)을 `watch` 로 감싸기만 함 — 고친 줄 하나. 저장 안 한 초안은 * 다리가 캐시 칸(`route-draft`)에 두고, 편집기가 자료를 읽은 뒤 `restore` 로 한 번 되살림 * (새로고침 · 보기 전환에도 남음). 계산 · 가게는 `A00_Common/design/design_pipeline_page.ts` 몫. * ========================================================================== */ import type { RouteDraft } from "../A00_Common/design/design_pipeline_types"; import type { RouteEditHistory, RouteEditSnapshot } from "./B05_Profile_UI_RouteEdit_History"; /** 편집기가 넘기는 노선 — 판 번호 · 지형은 다리가 붙임. */ export type RouteDraftEdit = Omit; export interface RouteDraftBridge { /** 노선이 바뀜 — 열 때(저장분)와 같으면 null. */ edited(draft: RouteDraftEdit | null): void; /** 저장 안 한 초안(캐시 칸) — 없으면 null. */ saved(): RouteDraft | null; } /** 사진 → 노선 초안(고정 · 고른 점은 노선이 아님). */ export function draftOfSnapshot(snapshot: RouteEditSnapshot, stationSnap: boolean): RouteDraftEdit { return { nodes: snapshot.planned.map(([x, y]): [number, number] => [x, y]), curveOn: [...snapshot.curveOn], curveRadius: [...snapshot.curveRadius], curveLock: [...snapshot.curveLock], curveArc: [...snapshot.curveArc], stationSnap, }; } /** 노선 초안 → 사진 — 고정은 편집기가 좌표로 다시 짚음(`restoreSnapshot` 새 걸음). */ export function snapshotOfDraft(draft: RouteDraft): RouteEditSnapshot { return { planned: draft.nodes.map(([x, y]): [number, number] => [x, y]), curveOn: [...draft.curveOn], curveRadius: [...draft.curveRadius], curveLock: [...draft.curveLock], curveArc: [...draft.curveArc], apexLock: draft.nodes.map(() => false), picked: -1, }; } /** 사진첩을 감싸 노선이 바뀔 때마다 다리에 알림 — 쌓기 · 되돌리기 · 다시하기 · 열 때로. */ export function watch( history: RouteEditHistory, bridge: RouteDraftBridge | undefined, stationSnap: () => boolean, ): RouteEditHistory { if (!bridge) return history; const tell = (snapshot: RouteEditSnapshot | null): RouteEditSnapshot | null => { if (snapshot) bridge.edited(history.isDirty() ? draftOfSnapshot(snapshot, stationSnap()) : null); return snapshot; }; return { ...history, commit: (snapshot) => { history.commit(snapshot); tell(snapshot); }, undo: () => tell(history.undo()), redo: () => tell(history.redo()), reset: () => tell(history.reset()), }; } /** 저장 안 한 초안을 편집기에 한 번 되살림 — 사진첩에 새 걸음으로(되돌리면 저장분). */ export function restore( bridge: RouteDraftBridge | undefined, apply: (snapshot: RouteEditSnapshot, message: string, record: boolean) => void, ): void { const kept = bridge?.saved(); if (kept?.nodes.length) apply(snapshotOfDraft(kept), "저장 안 한 노선 초안을 되살렸습니다.", true); }