Files
Aislo/B07_DesignDetail/openwebcad/src/components/RibbonWidgets.tsx
T
eomsangdonandClaude Opus 5.5 5d28a22832 fix(557-1): B07 · CAD 작은 흠 셋 — 토적도 설정 창 제목 말줄임 · 주석 리본 문자 스타일 칸 겹침 · 넘침 메뉴 왼쪽 판 뒤 가림
- ⚙ 설정 모달 폭 360 → 400 — 「토적도(유토곡선) 설정」 제목 148px 이 124px 칸에 잘리던 것 다 보임(B07 설정 모달만 · 공용 모달 머리 꼴 그대로)
- 주석 › 문자 스타일 칸 다섯 = 다섯 줄(102px)이 리본 높이 66 넘어 묶음 이름과 겹침 → 세 줄(글꼴 / 크기 · 색상 / 굵게 · 기울임) · 묶음 폭 · 다른 묶음 자리 그대로
- 리본(position: fixed)이 쌓임 맥락이라 넘침 메뉴 z 20 이 왼쪽 판(z 3) 밑 → 메뉴 연 동안 리본 z 10
- 지킴 시험 test_557_1_b07_cad_fixes

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

205 lines
6.0 KiB
TypeScript

/** 리본 안에 들어가는 위젯 패널 — 특성(색·굵기·선종류), 도면층, 문자 스타일 */
import type { FC } from 'react';
import { runCommandInput } from '../commands/run-command';
import type { Entity } from '../entities/Entity';
import { EntityName } from '../entities/Entity';
import type { TextEntity } from '../entities/TextEntity';
import {
LINE_TYPES,
LINE_WIDTHS,
paintNowCommitLater,
restyle,
selectionLineStyle,
styleTargets,
} from '../helpers/selection-style';
import {
getActiveLayerId,
getActiveTextStyle,
getLayers,
getSelectedEntities,
setActiveLayerId,
setActiveLineColor,
setActiveLineDash,
setActiveLineWidth,
setActiveTextStyle,
} from '../state';
const FONT_FAMILIES = ['Noto Sans KR', 'Malgun Gothic', 'Pretendard', 'Arial', 'monospace'];
/** 고른 선 있으면 그것만 바꿈(488 — 그리기 기본값 그대로) · 없으면 그리기 기본값만 */
const selectedLines = () => styleTargets(getSelectedEntities());
export const PropertiesWidget: FC = () => {
const view = selectionLineStyle();
return (
<div className="cad-ribbon-props">
<label className="cad-prop" title="객체 색상 (COLOR)">
<span>색상</span>
<input
type="color"
value={view.color || '#000000'}
data-mixed={view.color ? undefined : 'true'}
onChange={(event) => {
const color = event.target.value;
const lines = selectedLines();
if (!lines.length) return setActiveLineColor(color);
paintNowCommitLater(lines, (entity) => {
entity.lineColor = color;
});
}}
/>
</label>
<label className="cad-prop" title="선 두께 (LWEIGHT)">
<span>선 두께</span>
<select
value={view.width}
onChange={(event) => {
const width = Number(event.target.value);
const lines = selectedLines();
if (!lines.length) return setActiveLineWidth(width);
restyle(lines, (entity) => {
entity.lineWidth = width;
});
}}
>
<option value="" hidden />
{LINE_WIDTHS.map((width) => (
<option key={width} value={width}>
{width}px
</option>
))}
</select>
</label>
<label className="cad-prop" title="선종류 (LINETYPE)">
<span>선종류</span>
<select
value={view.lineType}
onChange={(event) => {
const dash = LINE_TYPES.find((type) => type.value === event.target.value)?.dash;
const lines = selectedLines();
if (!lines.length) return setActiveLineDash(dash ? [...dash] : undefined);
restyle(lines, (entity) => {
entity.lineDash = dash ? [...dash] : undefined;
});
}}
>
<option value="" hidden />
{LINE_TYPES.map((type) => (
<option key={type.value} value={type.value}>
{type.label}
</option>
))}
</select>
</label>
</div>
);
};
export const LayersWidget: FC = () => {
const layers = getLayers();
const activeLayerId = getActiveLayerId();
return (
<div className="cad-ribbon-props">
<label className="cad-prop cad-prop--wide" title="현재 레이어">
<span>현재 레이어</span>
<select value={activeLayerId} onChange={(event) => setActiveLayerId(event.target.value)}>
{/* 잠금 레이어(배경)는 고를 수 없으니 보여 주지 않는다. 현재 층이 잠금이면
(전부 잠금인 도면) 표시가 비지 않게 그 항목만 남긴다. */}
{layers
.filter((layer) => !layer.isLocked || layer.id === activeLayerId)
.map((layer) => (
<option key={layer.id} value={layer.id}>
{layer.name}
</option>
))}
</select>
</label>
<button
type="button"
className="cad-tool"
data-size="small"
title="레이어 특성 관리자 (LAYER)"
onClick={() => runCommandInput('LAYER')}
>
<span className="cad-tool__glyph">▤</span>
<span className="cad-tool__label">레이어</span>
</button>
</div>
);
};
export const TextStyleWidget: FC = () => {
const textStyle = getActiveTextStyle();
const handle = (patch: Partial<typeof textStyle>, live = false) => {
setActiveTextStyle(patch);
const texts = getSelectedEntities().filter((entity) => entity.getType() === EntityName.Text);
const mutate = (entity: Entity) => (entity as TextEntity).setTextOptions(patch);
// 색만 드래그 중 연발한다 — 나머지 항목은 한 번 고르면 끝이라 바로 싣는다.
if (live) paintNowCommitLater(texts, mutate);
else restyle(texts, mutate);
};
return (
<div className="cad-ribbon-props">
<label className="cad-prop cad-prop--wide" title="문자 글꼴 (STYLE)">
<span>글꼴</span>
<select
value={textStyle.fontFamily}
onChange={(event) => handle({ fontFamily: event.target.value })}
>
{FONT_FAMILIES.map((family) => (
<option key={family} value={family}>
{family}
</option>
))}
</select>
</label>
{/* 칸 다섯 = 세 줄(리본 높이 66 안 · 557-1) — 글꼴 / 크기 · 색상 / 굵게 · 기울임 */}
<div className="cad-prop-row">
<label className="cad-prop" title="문자 높이">
<span>크기</span>
<input
type="number"
min={4}
max={120}
value={textStyle.fontSize}
onChange={(event) => {
const size = Number(event.target.value);
if (Number.isFinite(size) && size > 0) handle({ fontSize: size });
}}
/>
</label>
<label className="cad-prop" title="문자 색상">
<span>색상</span>
<input
type="color"
value={textStyle.textColor}
onChange={(event) => handle({ textColor: event.target.value }, true)}
/>
</label>
</div>
<div className="cad-prop-row">
<label className="cad-prop" title="굵게">
<span>굵게</span>
<input
type="checkbox"
checked={textStyle.bold}
onChange={(event) => handle({ bold: event.target.checked })}
/>
</label>
<label className="cad-prop" title="기울임">
<span>기울임</span>
<input
type="checkbox"
checked={textStyle.italic}
onChange={(event) => handle({ italic: event.target.checked })}
/>
</label>
</div>
</div>
);
};