- 글 중심 = 줄 세로 가운데(옛 칸 아래 변 2px 밑) - 칸 폭 = max(150, 가장 긴 줄 글 폭 + 여백 8) · measureTextScreen(measureText 감쌈) - 안내 · 좌표 · 명령 후보(최대 6줄)도 바탕 한 장 안 · 입력 줄 아래 가는 줄 - 그리기 시험: 글 중심 · 12px 글 전체가 칸 안 · 폭 · 최소 폭 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015KYZ2HWWdUwZWYnn3tQz7X
87 lines
3.2 KiB
TypeScript
87 lines
3.2 KiB
TypeScript
/**
|
|
* 커서 따라다니는 입력창 — 캔버스에 직접 그림(`input-controller.ts` draw 가 부름).
|
|
* 칸 · 글은 테마 토큰 색을 그대로 칠함(자동색 뒤집기 건너뜀) — 명령줄 후보 상자(`App.css`
|
|
* `.cad-command-suggestions`)와 같은 색.
|
|
*/
|
|
import { Point } from '@flatten-js/core';
|
|
import {
|
|
CANVAS_INPUT_FIELD_BACKGROUND_COLOR,
|
|
CANVAS_INPUT_FIELD_BORDER_COLOR,
|
|
CANVAS_INPUT_FIELD_FONT_SIZE,
|
|
CANVAS_INPUT_FIELD_HEIGHT,
|
|
CANVAS_INPUT_FIELD_INSTRUCTION_TEXT_COLOR,
|
|
CANVAS_INPUT_FIELD_MOUSE_OFFSET,
|
|
CANVAS_INPUT_FIELD_TEXT_COLOR,
|
|
CANVAS_INPUT_FIELD_WIDTH,
|
|
} from '../App.consts.ts';
|
|
import type { ScreenCanvasDrawController } from '../drawControllers/screenCanvas.drawController.ts';
|
|
import { themeColor } from '../theme.ts';
|
|
|
|
/** 입력창 색 — 밝음 = 흰 칸 + 테두리 · 어두움 = 짙은 보라 칸 · 글 = CAD 글 색 */
|
|
export function inputFieldColors(read: (name: string, fallback: string) => string = themeColor) {
|
|
return {
|
|
background: read('--cad-chrome-raised', CANVAS_INPUT_FIELD_BACKGROUND_COLOR),
|
|
border: read('--cad-line', CANVAS_INPUT_FIELD_BORDER_COLOR),
|
|
text: read('--cad-text', CANVAS_INPUT_FIELD_TEXT_COLOR),
|
|
dimText: read('--cad-text-dim', CANVAS_INPUT_FIELD_INSTRUCTION_TEXT_COLOR),
|
|
};
|
|
}
|
|
|
|
/** 글 좌우 여백(px) */
|
|
const INPUT_FIELD_PADDING = 4;
|
|
|
|
/**
|
|
* 입력 글 칸 + 그 아래 안내 · 좌표 · 명령 후보 줄 — 바탕 한 장(명령줄 후보 상자 꼴).
|
|
* 줄마다 높이 CANVAS_INPUT_FIELD_HEIGHT · 글 중심 = 줄 세로 가운데 · 폭 = max(최소 폭, 가장 긴 줄 + 여백).
|
|
*/
|
|
export function drawInputField(
|
|
drawController: ScreenCanvasDrawController,
|
|
input: string,
|
|
lines: string[]
|
|
): void {
|
|
const mouse = drawController.getScreenMouseLocation();
|
|
const colors = inputFieldColors();
|
|
const rowHeight = CANVAS_INPUT_FIELD_HEIGHT;
|
|
const fontSize = CANVAS_INPUT_FIELD_FONT_SIZE;
|
|
const left = mouse.x + CANVAS_INPUT_FIELD_MOUSE_OFFSET;
|
|
// 화면 좌표는 위가 + — 칸 위 변이 커서 아래 OFFSET · fillRectScreen 의 y 는 아래 변
|
|
const top = mouse.y - CANVAS_INPUT_FIELD_MOUSE_OFFSET;
|
|
const height = rowHeight * (1 + lines.length);
|
|
const textWidth = Math.max(
|
|
0,
|
|
...[input, ...lines].map((text) => drawController.measureTextScreen(text, fontSize))
|
|
);
|
|
const width = Math.max(CANVAS_INPUT_FIELD_WIDTH, Math.ceil(textWidth) + INPUT_FIELD_PADDING * 2);
|
|
drawController.fillRectScreen(
|
|
left - 1,
|
|
top - height - 1,
|
|
width + 2,
|
|
height + 2,
|
|
colors.border,
|
|
true
|
|
);
|
|
drawController.fillRectScreen(left, top - height, width, height, colors.background, true);
|
|
if (lines.length) {
|
|
// 입력 줄과 목록 사이 가는 줄
|
|
drawController.fillRectScreen(left, top - rowHeight, width, 1, colors.border, true);
|
|
}
|
|
const textOptions = { textAlign: 'left' as const, fontSize, rawColor: true };
|
|
const rowCenter = (row: number) => top - rowHeight * row - rowHeight / 2;
|
|
if (input) {
|
|
drawController.drawTextScreen(input, new Point(left + INPUT_FIELD_PADDING, rowCenter(0)), {
|
|
...textOptions,
|
|
textColor: colors.text,
|
|
});
|
|
}
|
|
lines.forEach((line, index) => {
|
|
drawController.drawTextScreen(
|
|
line,
|
|
new Point(left + INPUT_FIELD_PADDING, rowCenter(index + 1)),
|
|
{
|
|
...textOptions,
|
|
textColor: colors.dimText,
|
|
}
|
|
);
|
|
});
|
|
}
|