diff --git a/B05_Profile/B05_Profile_UI_Profile_Tools.ts b/B05_Profile/B05_Profile_UI_Profile_Tools.ts index f14a0b087..b82790a57 100644 --- a/B05_Profile/B05_Profile_UI_Profile_Tools.ts +++ b/B05_Profile/B05_Profile_UI_Profile_Tools.ts @@ -16,6 +16,7 @@ import type { StraightRun } from "./logic/B05_Profile_UI_Profile_Straighten"; import { sameRun } from "./logic/B05_Profile_UI_Profile_Straighten"; +import { HISTORY_ICON } from "./B05_Profile_UI_RouteEdit_Chrome"; import type { FreeChartGeom } from "../A00_Common/design/design_profile_free_view"; export type ProfileToolMode = "none" | "straighten" | "shift" | "free"; @@ -174,6 +175,11 @@ export function createProfileTools(callbacks: ProfileToolsCallbacks): ProfileToo undo.disabled = !callbacks.canUndo(); const redo = toolButton("↷", "다시하기 (Ctrl+Shift+Z)", callbacks.onRedo); redo.disabled = !callbacks.canRedo(); + // 평면 편집과 같은 그림(요구 241-9) — 글은 aria-label 로. + undo.innerHTML = HISTORY_ICON.undo; + undo.setAttribute("aria-label", "되돌리기"); + redo.innerHTML = HISTORY_ICON.redo; + redo.setAttribute("aria-label", "다시하기"); const straighten = toolButton( "직선화", diff --git a/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts b/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts index 13021c9e8..982dde338 100644 --- a/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts +++ b/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts @@ -31,6 +31,17 @@ export const HALF_TURN_ICON = { `, }; +/** 되돌리기 · 다시하기 아이콘 — **곧은 꼬리 + 갈고리**(↩ ↪ · 요구 241-9). 둥근 화살표(`↶`·`↷`)는 + * 회전 단추와 헷갈렸다. 종단 도구줄도 같은 그림. */ +export const HISTORY_ICON = { + undo: ``, + redo: ``, +}; + export interface RouteEditChrome { overlay: HTMLElement; canvas: HTMLCanvasElement; @@ -65,9 +76,9 @@ export function createRouteEditChrome( data-act="hint-toggle" aria-expanded="false" title="조작 도움말 펼치기 · 접기">? + title="되돌리기 (Ctrl+Z)" aria-label="되돌리기" disabled>${HISTORY_ICON.undo} + title="다시하기 (Ctrl+Y)" aria-label="다시하기" disabled>${HISTORY_ICON.redo} @@ -79,7 +90,7 @@ export function createRouteEditChrome( aria-pressed="false" disabled title="1m 간격 등고선을 얇고 옅게 겹칩니다 (확대하면 보임)">1m 등고선 + title="도로 끝 · 비탈 끝(깎기 붉음 · 쌓기 청록)을 평면에 겹칩니다">절/성토선 diff --git a/B05_Profile/B05_Profile_UI_RouteEdit_Footprint.ts b/B05_Profile/B05_Profile_UI_RouteEdit_Footprint.ts index 82faeb7d3..5f10c6989 100644 --- a/B05_Profile/B05_Profile_UI_RouteEdit_Footprint.ts +++ b/B05_Profile/B05_Profile_UI_RouteEdit_Footprint.ts @@ -17,14 +17,13 @@ import { } from "./logic/B05_Profile_Footprint_Strokes"; import "./B05_Profile_UI_Style_RouteEdit_Footprint.css"; -/** 갈래 → 색 토큰 · 대체 색. */ -const STROKE_STYLE: Record = { - road: ["--b05-footprint-road", "#475569"], - cut: ["--b05-footprint-cut", "#dc2626"], - fill: ["--b05-footprint-fill", "#2563eb"], - slope: ["--b05-footprint-road", "#475569"], +/** 갈래 → 색 토큰 · 대체 색 · 굵기(px · 비탈 끝이 더 굵음 · 요구 241-10). */ +const STROKE_STYLE: Record = { + road: ["--b05-footprint-road", "#475569", 1.8], + cut: ["--b05-footprint-cut", "#e11d48", 2.6], + fill: ["--b05-footprint-fill", "#0d9488", 2.6], + slope: ["--b05-footprint-road", "#475569", 2.6], }; -const STROKE_WIDTH = 1.4; let shown = true; let redraw: (() => void) | null = null; @@ -77,9 +76,9 @@ export function drawFootprint( if (!strokes.length) return; context.save(); context.setLineDash([]); - context.lineWidth = STROKE_WIDTH; for (const { kind, points } of strokes) { - const [token, fallback] = STROKE_STYLE[kind]; + const [token, fallback, width] = STROKE_STYLE[kind]; + context.lineWidth = width; context.strokeStyle = style.getPropertyValue(token).trim() || fallback; context.beginPath(); points.forEach((vertex, index) => { diff --git a/B05_Profile/B05_Profile_UI_Style_RouteEdit_Footprint.css b/B05_Profile/B05_Profile_UI_Style_RouteEdit_Footprint.css index f2e5fa3c0..18781a952 100644 --- a/B05_Profile/B05_Profile_UI_Style_RouteEdit_Footprint.css +++ b/B05_Profile/B05_Profile_UI_Style_RouteEdit_Footprint.css @@ -1,20 +1,20 @@ -/* 노선 편집 평면 발자국(PLAN 346-2) — 도로 끝 · 비탈 끝 깎기(붉음) · 쌓기(파랑) */ +/* 노선 편집 평면 발자국(PLAN 346-2) — 도로 끝 · 비탈 끝 깎기(붉음) · 쌓기(청록) */ :root { --b05-footprint-road: #475569; - --b05-footprint-cut: #dc2626; - --b05-footprint-fill: #2563eb; + --b05-footprint-cut: #e11d48; + --b05-footprint-fill: #0d9488; } :root[data-theme="dark"] { --b05-footprint-road: #cbd5e1; - --b05-footprint-cut: #f87171; - --b05-footprint-fill: #60a5fa; + --b05-footprint-cut: #ff6b6b; + --b05-footprint-fill: #2dd4bf; } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --b05-footprint-road: #cbd5e1; - --b05-footprint-cut: #f87171; - --b05-footprint-fill: #60a5fa; + --b05-footprint-cut: #ff6b6b; + --b05-footprint-fill: #2dd4bf; } } diff --git a/resources/tester/helper_282_1_profile_toolbar.cjs b/resources/tester/helper_282_1_profile_toolbar.cjs index 1fe0671b6..932c18225 100644 --- a/resources/tester/helper_282_1_profile_toolbar.cjs +++ b/resources/tester/helper_282_1_profile_toolbar.cjs @@ -103,7 +103,7 @@ const popup = { // ---- 진짜 도구 묶음 ---- const { createProfileTools } = load(read("B05_Profile", "B05_Profile_UI_Profile_Tools.ts"), { - require: () => ({ sameRun: () => false }), + require: () => ({ sameRun: () => false, HISTORY_ICON: { undo: "", redo: "" } }), document, }); const tools = createProfileTools({ diff --git a/resources/tester/test_346_2_footprint_draw.py b/resources/tester/test_346_2_footprint_draw.py index 26642f4bf..c5c105ba4 100644 --- a/resources/tester/test_346_2_footprint_draw.py +++ b/resources/tester/test_346_2_footprint_draw.py @@ -111,3 +111,8 @@ def test_편집기가_발자국을_그리고_단추로_켬끔() -> None: for token in ("--b05-footprint-road", "--b05-footprint-cut", "--b05-footprint-fill"): assert token in footprint assert css.count(f"{token}:") == 3 # 밝음 · 어두움 · 시스템 어두움 + # 381-1 — 절토 · 성토 테마 색 · 굵게(도로 끝 1.8 · 비탈 끝 2.6) + for color in ("#e11d48", "#ff6b6b", "#0d9488", "#2dd4bf"): + assert color in css + assert '"#e11d48", 2.6]' in footprint and '"#0d9488", 2.6]' in footprint + assert 'road: ["--b05-footprint-road", "#475569", 1.8]' in footprint diff --git a/resources/tester/test_b05_routeedit_chrome_modal.py b/resources/tester/test_b05_routeedit_chrome_modal.py index 0214f08ef..8cfe246f3 100644 --- a/resources/tester/test_b05_routeedit_chrome_modal.py +++ b/resources/tester/test_b05_routeedit_chrome_modal.py @@ -38,8 +38,13 @@ def test_겉틀은_본문_칸(): assert ">저장 전으로" not in chrome and "노선 반영" not in chrome assert ">취소" not in chrome and ">확인" not in chrome # 352-2 — 되돌리기 · 다시하기 = 글 없이 기호 + aria-label · title(단축키) - assert 'aria-label="되돌리기" disabled>↶' in chrome - assert 'aria-label="다시하기" disabled>↷' in chrome + # 381-1 — 곧은 꼬리 + 갈고리 SVG(회전 반 바퀴 그림과 헷갈리지 않게) + assert 'aria-label="되돌리기" disabled>${HISTORY_ICON.undo}' in chrome + assert 'aria-label="다시하기" disabled>${HISTORY_ICON.redo}' in chrome + assert ">↶" not in chrome and ">↷" not in chrome + tools = _read("B05_Profile_UI_Profile_Tools.ts") + assert "undo.innerHTML = HISTORY_ICON.undo;" in tools + assert "redo.innerHTML = HISTORY_ICON.redo;" in tools assert 'title="되돌리기 (Ctrl+Z)"' in chrome and 'title="다시하기 (Ctrl+Y)"' in chrome # 시험 · 배선이 집는 자리는 남김 assert "b05-routeedit__measure-close" in chrome