앞선 감사가 불완전했다. 같은 부류로 도각·원지반을 건드리던 곳이 더 있었다. - select-tool.helpers pickEntityAt: 클릭 선택 후보에 잠금 객체가 섞여 도각을 물면 아무 일도 안 일어나는 죽은 클릭이 됐다. - eraser-tool: 자르기의 교차점 계산이 도각 선을 절단 경계로 썼다. - property-tools OVERKILL: 선택이 없으면 전체가 대상이라 도각까지 지웠다. - text-tools 찾기/바꾸기: 도각 표제란 글자를 바꿔 버렸다. - selection-tools 유형/유사 선택: 잠금 객체까지 세어 토스트 개수가 틀렸다. 전부 getPickableEntities()로 바꾼다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
114 lines
3.7 KiB
TypeScript
114 lines
3.7 KiB
TypeScript
/** 문자 명령 — 여러 줄 문자·단일 행 문자·편집·찾기 (조사표 5절 문자 패널) */
|
|
import { Point } from '@flatten-js/core';
|
|
import { toast } from 'react-toastify';
|
|
import { getAnnotationScale } from '../../commands/dim-settings';
|
|
import { EntityName } from '../../entities/Entity';
|
|
import type { Entity } from '../../entities/Entity';
|
|
import type { TextEntity } from '../../entities/TextEntity';
|
|
import {
|
|
addEntities,
|
|
getActiveTextStyle,
|
|
getEntities,
|
|
getPickableEntities,
|
|
setEntities,
|
|
} from '../../state';
|
|
import { Tool } from '../../tools';
|
|
import { textEntity } from '../factories/entity-factory';
|
|
import { createSequenceTool } from '../factories/sequence-tool';
|
|
|
|
/** AutoCAD 여러 줄 문자의 줄바꿈 표기(\P)와 \n을 모두 받는다 */
|
|
const splitLines = (text: string): string[] =>
|
|
text
|
|
.replace(/\\P/gi, '\n')
|
|
.split('\n')
|
|
.map((line) => line.trim())
|
|
.filter((line) => line.length > 0);
|
|
|
|
function buildTextLines(lines: string[], basePoint: Point): Entity[] {
|
|
const lineHeight = getActiveTextStyle().fontSize * getAnnotationScale() * 1.35;
|
|
const groupId = lines.length > 1 ? crypto.randomUUID() : undefined;
|
|
return lines.map((line, index) => {
|
|
const entity = textEntity(line, new Point(basePoint.x, basePoint.y - lineHeight * index), {
|
|
textAlign: 'left',
|
|
fontSize: getActiveTextStyle().fontSize * getAnnotationScale(),
|
|
});
|
|
entity.groupId = groupId;
|
|
return entity;
|
|
});
|
|
}
|
|
|
|
export const textToolStateMachine = createSequenceTool({
|
|
tool: Tool.TEXT,
|
|
steps: [
|
|
{ kind: 'point', instructions: '문자의 시작점을 지정하십시오.' },
|
|
{ kind: 'text', instructions: '문자를 입력하십시오.' },
|
|
],
|
|
commit: (input) => {
|
|
const lines = splitLines(input.text(1));
|
|
if (!lines.length) return;
|
|
addEntities(buildTextLines(lines.slice(0, 1), input.point(0)), true);
|
|
},
|
|
});
|
|
|
|
export const mtextToolStateMachine = createSequenceTool({
|
|
tool: Tool.MTEXT,
|
|
steps: [
|
|
{ kind: 'point', instructions: '여러 줄 문자의 첫 코너를 지정하십시오.' },
|
|
{ kind: 'text', instructions: '문자를 입력하십시오 (줄바꿈은 \\P).' },
|
|
],
|
|
commit: (input) => {
|
|
const lines = splitLines(input.text(1));
|
|
if (!lines.length) return;
|
|
addEntities(buildTextLines(lines, input.point(0)), true);
|
|
},
|
|
});
|
|
|
|
export const textEditToolStateMachine = createSequenceTool({
|
|
tool: Tool.TEXTEDIT,
|
|
helpers: false,
|
|
steps: [
|
|
{ kind: 'entity', instructions: '편집할 문자를 선택하십시오.' },
|
|
{ kind: 'text', instructions: '새 문자를 입력하십시오.' },
|
|
],
|
|
commit: (input) => {
|
|
const entity = input.entity(0);
|
|
if (entity.getType() !== EntityName.Text) {
|
|
toast.warn('문자 객체를 선택하십시오.');
|
|
return;
|
|
}
|
|
(entity as TextEntity).setLabel(input.text(1));
|
|
setEntities([...getEntities()], true);
|
|
},
|
|
});
|
|
|
|
export const findToolStateMachine = createSequenceTool({
|
|
tool: Tool.FIND,
|
|
helpers: false,
|
|
steps: [
|
|
{ kind: 'text', instructions: '찾을 문자열을 입력하십시오.' },
|
|
{
|
|
kind: 'text',
|
|
instructions: '바꿀 문자열을 입력하십시오 (그대로 두려면 ENTER).',
|
|
defaultValue: '',
|
|
},
|
|
],
|
|
commit: (input) => {
|
|
const needle = input.text(0);
|
|
const replacement = input.text(1);
|
|
let found = 0;
|
|
let replaced = 0;
|
|
for (const entity of getPickableEntities()) {
|
|
if (entity.getType() !== EntityName.Text) continue;
|
|
const text = entity as TextEntity;
|
|
if (!text.getLabel().includes(needle)) continue;
|
|
found += 1;
|
|
if (replacement) {
|
|
text.setLabel(text.getLabel().split(needle).join(replacement));
|
|
replaced += 1;
|
|
}
|
|
}
|
|
if (replaced) setEntities([...getEntities()], true);
|
|
toast.info(replaced ? `${replaced}개 문자를 바꿨습니다.` : `${found}개 문자를 찾았습니다.`);
|
|
},
|
|
});
|