Files
Aislo/B07_DesignDetail/openwebcad/src/helpers/debug-hook.ts
T
eomsangdonandClaude Opus 5.5 cdfd2c6663 feat(487 CAD 글 테두리 · 리본 켜짐): 스침 테두리 = 더블클릭 입력 칸 한 벌(text-frame) · 잡는 범위 = 테두리 안 · 리본 켜짐 하나만
- 새 helpers/text-frame.ts — 정렬 · 가운데 맞춤 · 실제 글꼴 폭(굵게 · 기울임) · 회전 · 여러 줄 묶음 · 도각 칸 = 테두리 한 셈
- TextEntity 스침 · 고름 테두리 = 그 네 귀(여러 줄은 묶음 하나) · distanceTo = 테두리 안 0 · getBoundingBox 그대로
- 입력 칸 자리 · 폭 · 높이 = 같은 셈(여유 = 안쪽 여백) · 더블클릭 범위 = 테두리 + 집기 반경
- measureTextScreen 글꼴 받음 · 디버그 창구 textFrame(화면 네 귀)
- 리본 스침 = 바탕만(hover 기기만) · 켜짐 = 테두리 + 밑줄 · 누른 뒤 blur(초점 테두리 남음 막음)
- 시험 text-frame.test.ts 새로 · text-inplace-edit.test.ts 칸 폭 · 여백 · test_cad_host_tabs 줄바꿈 무관

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 22:25:55 +09:00

82 lines
3.2 KiB
TypeScript

/**
* 화면 검증용 상태 조회 창구 — 브라우저 콘솔·자동화 스크립트가
* window.__aisloCad로 현재 객체·도면층·선택을 읽는다. 앱 동작에는 관여하지 않는다.
*/
import {
getDesignMeta,
getEntities,
getHighlightedEntityIds,
getLayers,
getSelectedEntityIds,
getScreenCanvasDrawController,
getSnapPoint,
isDrawingDirty,
isDrawingReadOnly,
isOriginMarker,
isViewOnly,
} from '../state';
import { Point } from '@flatten-js/core';
import { isEntityHidden } from './visibility';
import type { TextEntity } from '../entities/TextEntity';
import { textFrame, textFrameCorners, textLinesOf } from './text-frame';
export function registerCadDebugHook(): void {
(window as unknown as Record<string, unknown>).__aisloCad = {
entities: () =>
getEntities().map((entity) => {
const box = entity.getBoundingBox();
return {
id: entity.id,
type: entity.getType(),
layerId: entity.layerId,
groupId: entity.groupId ?? null,
opacity: entity.opacity ?? null,
hidden: isEntityHidden(entity),
color: entity.lineColor,
// 글자 객체의 내용 — 한글 입력(IME) 검증이 읽는다
label: (entity as { getLabel?: () => string }).getLabel?.() ?? null,
box: [
Math.round(box.xmin),
Math.round(box.ymin),
Math.round(box.xmax),
Math.round(box.ymax),
],
};
}),
layers: () => getLayers(),
selection: () => getSelectedEntityIds(),
// 마우스 위치의 객체 스냅점 — 잠금 도면층(도각)이 스냅에 끼는지 검증할 때 읽는다.
snap: () => getSnapPoint(),
// 마우스가 스친 객체 — 잠금층(도각·등고선)이 밝아지는지 수치로 본다.
highlighted: () => getHighlightedEntityIds(),
// 확정 도면의 편집 잠금과 미저장 표시 — 화면 검증이 상태를 직접 읽는다.
readOnly: () => isDrawingReadOnly(),
dirty: () => isDrawingDirty(),
meta: () => getDesignMeta(),
// 기준점 십자 · 미리보기(보기 전용) 켜짐 — 그림이 안 도는 탭에서도 수치로 본다.
originMarker: () => isOriginMarker(),
viewOnly: () => isViewOnly(),
// 세계 좌표 → 화면 좌표. 그림·글자가 "제 자리에 그려졌나"를 픽셀로 판정할 때 쓴다.
screen: (x: number, y: number) => {
const point = getScreenCanvasDrawController().worldToTarget(new Point(x, y));
return { x: point.x, y: point.y };
},
// 글 스침 테두리 네 귀(화면 좌표 · 왼위부터) — 더블클릭 입력 칸과 픽셀로 견줌(487).
textFrame: (id: string) => {
const entity = getEntities().find((item) => item.id === id) as TextEntity | undefined;
if (!entity?.getTextOptions) return null;
const controller = getScreenCanvasDrawController();
const lines = textLinesOf(entity, getEntities());
const scale = controller.getScreenScale();
const rows = lines.map((line) => line.previewLabel ?? line.getLabel());
const frame = textFrame(lines, rows, scale, (row, px, font) =>
controller.measureTextScreen(row, px, font)
);
return textFrameCorners(lines, frame, scale).map((corner) => {
const point = controller.worldToTarget(corner);
return { x: point.x, y: point.y };
});
},
};
}