- 왼쪽 · 일반 맞춤 글은 오른쪽으로 · 오른쪽 맞춤은 왼쪽으로 · 가운데는 양쪽으로 — 옆 칸이 빌 때만 - 비지 않은 칸 · 병합 칸 · 틀 고정 경계에서 멈춤 · 가운데 맞춤이 한쪽만 막히면 그쪽을 잘라 냄 - 줄 바꿈 켠 칸 · 숫자(####) · 오류는 안 넘침 · 덮은 칸 사이 눈금선 감춤 · 고치는 중에는 활성 칸 넘침 감춤 - 폭 계산은 새 파일 spreadsheet_spill.ts(격자 파일이 이미 700 줄 넘어 따로) · 정확한 글 폭은 글 요소 scrollWidth 를 판마다 한 번에 읽음 - ORCA(M02 면적산출 편집 창) 수치 확인 — 왼 · 오른 · 가운데 넘침 글 잘림 0 · 막힘 · 병합 · 틀 고정 멈춤 · 스크롤 · 확대 뒤 칸에 붙어 있음 · 비지 않은 칸과 겹침 0 · 실제 문서 새 그림 겹침 0 · 크기 시험 통과 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BYN9gMie8e6pXzSxJNb6Xt
62 lines
2.3 KiB
TypeScript
62 lines
2.3 KiB
TypeScript
/* =============================================================================
|
|
* spreadsheet_spill.ts
|
|
* 긴 글 넘침(엑셀) — 칸보다 긴 글을 옆 빈 칸 위로 보임. 왼쪽 · 일반 맞춤은 오른쪽으로 · 오른쪽 맞춤은
|
|
* 왼쪽으로 · 가운데는 양쪽으로. 비지 않은 칸 · 병합 칸 · 판 끝(틀 고정 경계 · 그린 범위 밖)에서 멈춤.
|
|
* 격자(`spreadsheet_grid.ts`)가 판 하나를 그릴 때 줄마다 칸 자리(`slots`)를 모아 부름 — 계산만 여기.
|
|
* ========================================================================== */
|
|
|
|
/** 같은 판 · 같은 줄 · 병합 아닌 칸 하나(병합 칸 · 안 그린 칸은 넣지 않음 → 거기서 멈춤) */
|
|
export interface SpillSlot {
|
|
w: number;
|
|
empty: boolean;
|
|
}
|
|
|
|
/** 넘침 — 왼 · 오른쪽으로 더 쓸 폭(px) · 덮은 칸 열 범위 · 가운데 맞춤이 한쪽만 막혀 잘라 낼 폭 */
|
|
export interface Spill {
|
|
left: number;
|
|
right: number;
|
|
from: number;
|
|
to: number;
|
|
/** 가운데 맞춤 — 글 상자는 양쪽 반씩 늘리고 막힌 쪽은 이만큼 잘라 냄(글은 칸 가운데 그대로) */
|
|
clipLeft: number;
|
|
clipRight: number;
|
|
}
|
|
|
|
export type SpillAlign = "left" | "right" | "center";
|
|
|
|
/** 칸 c(폭 own)의 글 폭 need 가 넘치면 정렬 쪽 빈 칸으로 늘린 결과 · 안 넘치거나 못 늘리면 null */
|
|
export function spillOf(
|
|
slots: Map<number, SpillSlot>,
|
|
c: number,
|
|
own: number,
|
|
need: number,
|
|
align: SpillAlign,
|
|
): Spill | null {
|
|
if (need <= own) return null;
|
|
let from = c;
|
|
let to = c;
|
|
const grow = (dir: -1 | 1, want: number): number => {
|
|
let got = 0;
|
|
for (let k = c + dir; got < want; k += dir) {
|
|
const s = slots.get(k);
|
|
if (!s || !s.empty) break;
|
|
got += s.w;
|
|
if (dir < 0) from = k;
|
|
else to = k;
|
|
}
|
|
return got;
|
|
};
|
|
if (align === "center") {
|
|
const half = (need - own) / 2;
|
|
const l = Math.min(grow(-1, half), half);
|
|
const r = Math.min(grow(1, half), half);
|
|
if (!l && !r) return null;
|
|
return { left: half, right: half, from, to, clipLeft: half - l, clipRight: half - r };
|
|
}
|
|
const got = grow(align === "right" ? -1 : 1, need - own);
|
|
if (!got) return null;
|
|
return align === "right"
|
|
? { left: got, right: 0, from, to, clipLeft: 0, clipRight: 0 }
|
|
: { left: 0, right: got, from, to, clipLeft: 0, clipRight: 0 };
|
|
}
|