Files
Aislo/B05_Profile/B05_Profile_UI_RouteEdit_Mouse.ts
T
eomsangdonandClaude Opus 5.5 62a8ee362e refactor(B05 평면 · 지도 공용): RouteEdit 마우스 배선 · 재기 한 벌 떼어냄 · 긋기 방식 칸 공용 자리로 (PLAN 626-3 · 요구 530 · 531)
- B05_Profile_UI_RouteEdit.ts 684 → 655 줄 — 두 번 클릭 삽입 · 오른쪽 클릭 삭제 · 지도 이동 · 휠 = 새 `_RouteEdit_Mouse.ts` · 재기 도구 + 단추 한 벌 = `_Measure.ts` `createRouteMeasure` (동작 그대로)
- 긋기 방식 칸(`createDrawKindFields` · 기본값 · 이름) = 새 `A00_Common/map/map_draw_kind.ts` · `.css` — D03 DrawPanel 은 다시 내보냄(D03 화면 · 동작 같음 · 칸 꼴 선택자만 공용 이름)
- D03 `paintPreview` · `planLabel` 받는 지도 꼴을 쓰는 칸만(Pick)으로 — B05 평면이 그대로 부름
- 시험 test_553_4 — 방식 칸 대조를 공용 파일로 옮김(낡은 자리 대조)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 21:51:58 +09:00

73 lines
3.2 KiB
TypeScript

/* =============================================================================
* B05_Profile_UI_RouteEdit_Mouse.ts
* 계획노선 편집(평면) 마우스 배선 — 선 두 번 클릭 = 노드 넣기 · 노드 오른쪽 클릭 = 지움 · 가운데(휠) 버튼 끌기 =
* 지도 이동 · 휠 = 확대 · Ctrl+휠 = 돌리기. `B05_Profile_UI_RouteEdit.ts` 에서 뗌(626-3 · 동작 그대로).
* 노드 끌기 · 집기는 `_Pointer` 몫 · 집기 셈 · 듣기는 `_Input` 몫.
* ========================================================================== */
import type { ViewState } from "../B04_PreProcess/B04_PreProcess_UI_MapRender";
import type { VWorldMeta } from "../B04_PreProcess/B04_PreProcess_Api_Fetch";
import { showToast } from "@ui/ui_template_elements";
import { bindNodeSplice, bindRouteEditNavigation } from "./B05_Profile_UI_RouteEdit_Input";
import type { RouteEditSnapshot } from "./B05_Profile_UI_RouteEdit_History";
import type { MapRotation } from "./B05_Profile_UI_RouteEdit_Rotate";
import * as edits from "./logic/B05_Profile_UI_RouteEdit_Edits";
type Vertex = [number, number];
export interface RouteEditMouseParams {
canvas: HTMLCanvasElement;
rotation: Pick<MapRotation, "unrotate" | "unrotateDelta" | "wheel">;
pointer: {
segmentAt: (px: number, py: number) => number;
nodeAt: (px: number, py: number) => number;
claimed: () => boolean;
};
toMetric: (px: number, py: number) => Vertex;
getView: () => ViewState;
setView: (next: ViewState) => void;
getMeta: () => VWorldMeta | null;
/** 지금 편집값(같은 배열 — 넣고 빼면 그대로 바뀜). */
snapshot: () => RouteEditSnapshot;
setPicked: (index: number) => void;
applyEdit: (message: string) => void;
draw: () => void;
}
export function bindRouteEditMouse(params: RouteEditMouseParams): void {
const { canvas, rotation, pointer } = params;
bindNodeSplice({
canvas,
unrotate: rotation.unrotate,
segmentAt: pointer.segmentAt,
nodeAt: pointer.nodeAt,
insert: (segment, px, py) => {
edits.spliceNode(params.snapshot(), segment + 1, params.toMetric(px, py)); // 편집값도 같은 자리에 끼운다.
params.setPicked(segment + 1);
params.applyEdit("새 노드를 넣었습니다(직선 추가).");
},
remove: (index) => {
const snapshot = params.snapshot();
if (snapshot.planned.length <= 2)
return showToast("노선은 노드가 2개 이상이어야 합니다.", "error");
if (snapshot.apexLock[index])
return showToast("고정한 점은 못 지웁니다 — 고정을 먼저 푸세요.", "error");
edits.spliceNode(snapshot, index);
params.setPicked(-1);
params.applyEdit("노드를 지웠습니다(직선 삭제).");
},
});
bindRouteEditNavigation({
canvas,
getView: params.getView,
setView: params.setView,
getMeta: params.getMeta,
// 돌린 지도에서는 손이 민 방향과 그림이 움직일 방향이 다르다 — 거꾸로 돌려 넘긴다.
unrotateDelta: rotation.unrotateDelta,
rotateWheel: rotation.wheel, // Ctrl+휠 = 5° 돌리기(390-3)
claimed: pointer.claimed, // 왼쪽 옮기기 = 노드 · 손잡이 · 마커 · 재기 아닌 누름만(588-4)
draw: params.draw,
});
}