Files
SheetMe/src/SheetMe.Designer/Themes/Tokens.Light.xaml
T
MsystechandClaude Opus 5 ba838ae54a 피그마식 스냅 — 여러 선이 동시에, 관련된 것만 잇고, 같은 간격이면 그렇다고 말한다
정렬 스냅 자체는 있었다. 다만 축마다 선 하나만, 그것도 화면 끝에서 끝까지 긋는 무한 점선이라
무엇에 맞춘 것인지가 안 보였다. 판단을 SheetMe.Core 로 옮기고 후보의 출처를 끝까지 들고 간다.

왜 옮겼나. 스냅은 눈으로만 확인되는 종류의 코드다 — 후보 하나, 열거 순서 하나가 바뀌면
붙는 자리가 조용히 달라지고 드래그해 보기 전엔 아무도 모른다. Core/Layout 의 SnapSolver 는
순수 기하이고 단위 테스트 27건이 승자 규칙·가이드 개수·선분 범위·간격 계산을 못 박는다.
SnapEngine 에는 "어떤 사각형이 후보인가"와 좌표 변환만 남았다.

달라진 것들:

· 동시에 맞는 정렬은 전부 보인다. 폭이 같은 형제 옆에 대면 좌·중·우 세 줄이 함께 뜬다.
  보정량은 승자 하나만 쓰되, 그 보정을 적용했을 때 실제로 맞는 후보만 선으로 낸다 —
  |거리|만 같고 부호가 반대인 후보까지 그리면 '붙었다고 그려 놓고 안 붙은' 선이 된다.

· 선이 선분이 됐다. 형제 가이드는 관련된 것들의 합집합 범위까지만, 용지 가이드는 그 용지 전체.
  같은 좌표의 형제 여럿은 한 선으로 합치고 범위만 넓힌다.
  덤으로 대비 문제도 풀렸다 — 예전 분홍(#FF4FA3)은 종이 밖 회색 배경 위에서 2.1:1 로 죽었다.

· 허용 오차가 화면 기준이 됐다. 월드 고정이면 줌 50%에서 두 배로 끈적이고 200%에서 절반으로
  미끄러진다 — 손끝 감각은 화면 거리로 정해진다. 핸들 히트 반경도 같은 병이라 함께 고쳤다
  (줌 300%에서 그림은 8px 인데 판정이 18px 였다). 선 두께도 화면 1px 로 고정한다.

· 승자가 결정적이 됐다. 예전에는 컨트롤 열거 순서가 동률을 갈랐다.
  이제 |거리| → 종류(형제 모서리 > 형제 중심 > 용지 경계 > 용지 중앙) → 좌표 → 모서리 순이다.

· 간격 균등. 형제들이 이미 같은 간격으로 늘어서 있으면 그 리듬에 끼거나 이어 붙는 자리에 붙고,
  같은 값이 된 빈틈 전부에 막대와 수치 칩을 놓는다. 양옆만 재면 "30"이 한 번 뜰 뿐이라
  무엇과 같아졌는지 안 보인다. 같은 축에서 정렬과 동시에 사정권이면 정렬이 이긴다 —
  거리로 겨루게 하면 한 픽셀 차이로 표시가 선↔막대로 튀어 종잡을 수 없다.

· 후보 범위. 컨테이너 자식도 이제 후보다(히트테스트는 재귀하는데 스냅만 최상위를 보던 규칙 불일치).
  대신 끌려가는 컨테이너의 자식은 빼야 한다 — 선택 목록엔 없지만 함께 움직이므로
  빼지 않으면 컨테이너가 제 자식에게 붙어 그 자리에서 굳는다.

· 리사이즈. 후보를 이동 드래그에서만 모으고 있어서, 앱을 켜자마자 핸들을 잡으면 스냅이 없고
  이동을 한 번 한 뒤에는 그때의 낡은 좌표에 붙었다. 리사이즈 시작에도 모으고 놓을 때 버린다.
  모서리 스냅이 '첫 매치'였던 것도 이동과 같은 최근접 규칙으로 통일했다. 가이드도 함께 보인다.

· 정합된 축은 반올림하지 않는다. 형제 폭이 홀수면 중심이 반정수라, 반올림하면 중앙에 맞췄는데
  0.5px 어긋난 채로 놓인다. 무한선일 땐 안 보였지만 선분이 되면 모서리에서 뜬 게 눈에 띈다.
  저장은 LegacyFormat.FormatPair 가 어차피 정수로 쓰므로 포맷은 영향 없다.

성능 가드: 한 줄에 겹치는 형제가 64개 넘으면 간격 계산을 건너뛰고(정렬은 정상),
형제가 2000개 넘으면 간격을 끈다. 후보 정렬은 드래그 시작에 1회, 프레임 경로는 무할당.
가이드 내용이 이전과 같으면 컬렉션을 건드리지 않는다.

신규 진단 --snap-shots — 종이와 오버레이를 겹쳐 드래그 도중을 찍는다.
기존 --render-smoke/--db-render 는 종이만 찍어 오버레이가 안 나왔다. 선이 어디서 어디까지
그어지는지, 몇 개가 동시에 보이는지는 그림으로만 확인된다. 게이트는 함께 남기는 _report.txt 의
수치로 걸고 PNG 는 눈 검증 보조다(픽셀 비교는 테마·글꼴에 흔들려 게이트로 못 쓴다).

게이트: 테스트 257/257(신규 27), --edit-smoke 223건 0실패(스냅 검사 14건 신규),
--query-popup 17/17, --maxrect 10/10, --db-smoke 3000 diff 0·예외 0,
--db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 동일, --snap-shots 7종 0실패.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 09:23:42 +09:00

131 lines
9.3 KiB
XML

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- ============================================================
디자이너 라이트 토큰 — Tokens.Dark.xaml 과 동일 키, 라이트값
· Framer 라이트 에디터 기준: 중립 회색(쿨/블루톤 제거) + 강조는 Framer 블루 #0099FF
· 회색은 무채색(R=G=B)로 통일, 블루 틴트는 선택/활성(Accent2/Sel)에만
============================================================ -->
<!-- 색상 토큰 -->
<SolidColorBrush x:Key="B.Ink" Color="#222222" />
<!--
보조 텍스트·아이콘. 다크와 같은 #969696 을 쓰면 라이트에서 명암비가 2.5~2.96:1 로 떨어져
본문 기준(4.5:1)은 물론 아이콘 기준(3:1)도 못 넘긴다(다크는 같은 값이 4.85~6.53:1).
회색 하나를 양 테마가 공유할 수 없다 — 배경이 정반대이기 때문이다.
#6B6B6B 는 이 토큰이 얹히는 모든 배경에서 4.5:1 이상: Panel 5.33 / AppBg 4.89 /
CanvasBg 4.51 / Chip 4.63. 전 사용처 59곳이 전부 Foreground 라 채움 룩에는 영향이 없다.
-->
<SolidColorBrush x:Key="B.Muted" Color="#6B6B6B" />
<SolidColorBrush x:Key="B.Line" Color="#EAEAEA" />
<!-- 체크박스 상자·포커스 링 등 '컨트롤 경계'로도 쓰인다 — 흰 배경에서 1.43:1 이면 컨트롤이
거기 있다는 사실 자체가 안 보인다. -->
<SolidColorBrush x:Key="B.Line2" Color="#C6C6C6" />
<SolidColorBrush x:Key="B.Accent" Color="#0099FF" /><!-- 브랜드색 유지 — 아이콘·테두리·강조선(3:1) 용도 -->
<!--
강조'글자' 전용. #0099FF 는 흰 배경에서 3.0:1 이라 본문 4.5:1 을 못 넘긴다
(쿼리 편집기 변수 그룹 헤더, 마스크 미리보기 등). 라이트에서만 짙게 간다.
-->
<SolidColorBrush x:Key="B.AccentText" Color="#0F6FBF" />
<!-- 강조 채움(Primary 버튼) — 흰 글자를 얹으므로 5.19:1. 양 테마 동일값. -->
<SolidColorBrush x:Key="B.AccentFill" Color="#0F6FBF" />
<!--
레이어 목록 전용 4종 — 다크 대응본과 <b>방향이 반대</b>다.
다크는 짙은 파랑 채움 + 흰 글자, 라이트는 연한 파랑 채움 + 진한 글자로 간다.
흰 배경에 짙은 파랑 슬라브를 얹으면 선택 몇 줄이 패널 전체를 짓눌러 목록이 안 읽힌다.
#A8D3F7: 흰 패널 대비 1.58:1 로 밴드가 분명히 보이고, 그 위 B.Ink 는 10.1:1.
-->
<SolidColorBrush x:Key="B.LayerSel" Color="#A8D3F7" />
<!--
그룹 전원 선택 시 멤버 행 배경 — 선택 밴드보다 한 단계 옅게(선택 대비 1.30:1)
해서 '폴더가 주인, 멤버는 딸림'이 색 세기로 읽히게 한다.
[200] 원본 #E4F2FF 는 흰 패널 위 1.14:1 이고 같은 hex 가 B.Accent2 에서 이미 기각됐다.
-->
<SolidColorBrush x:Key="B.LayerSubtree" Color="#DCEBFB" />
<!-- 선택 밴드 위 글자 — 라이트는 연한 채움이라 흰 글자를 쓸 수 없다 -->
<SolidColorBrush x:Key="B.OnLayerSel" Color="#222222" />
<!-- 선택 밴드 위 보조 텍스트(컨트롤 이름 둘째 줄·멤버 수) — #A8D3F7 위 5.12:1 -->
<SolidColorBrush x:Key="B.OnSelMuted" Color="#35536C" />
<SolidColorBrush x:Key="B.Accent2" Color="#CFE7FF" /><!-- 활성 틴트 — 흰 바 위 1.14:1 로는 켜짐이 안 읽혀 진하게 -->
<SolidColorBrush x:Key="B.Sel" Color="#C2E2FF" /><!-- 선택 채움 — 흰 배경 1.19:1 은 선택 여부가 안 보인다 -->
<SolidColorBrush x:Key="B.Hover" Color="#EAEAEA" />
<SolidColorBrush x:Key="B.AppBg" Color="#F5F5F5" />
<SolidColorBrush x:Key="B.Panel" Color="#FFFFFF" />
<SolidColorBrush x:Key="B.PanelHeader" Color="#FAFAFA" />
<SolidColorBrush x:Key="B.Surface" Color="#FFFFFF" />
<SolidColorBrush x:Key="B.Titlebar" Color="#F7F7F7" /><!-- 순백 아님(패널과 미묘한 분리) -->
<SolidColorBrush x:Key="B.Input" Color="#FFFFFF" /><!-- 입력칩=흰색(라이트). 옅은 테두리 B.InputBorder 동반 -->
<!--
흰 입력칩 가장자리. 라이트는 B.Input = B.Panel = B.Surface = #FFFFFF 라 채움 대비가
정확히 1.000:1 — 이 테두리 하나가 입력란의 유일한 경계다. #E3E3E3(1.28:1)로는 보이지 않는다.
#C4C4C4 는 1.74:1 — WCAG 의 컨트롤 경계 3:1 을 채우려면 #949494 까지 가야 하지만
그건 [200] 의 가벼운 룩을 크게 벗어난다. 가시성을 확보하는 선에서 멈췄다.
-->
<SolidColorBrush x:Key="B.InputBorder" Color="#C4C4C4" />
<!--
캔버스(용지 뒷배경). #ECECEC 는 흰 용지와 명암비 1.18:1 이라 종이 경계가 사실상 안 보였다
(다크는 14.35:1). #D8D8D8 로 낮춰 1.43:1 — PageView 의 오프셋 그림자·테두리와 합쳐져야
용지가 떠 보인다. 용지 자체(PageView 의 종이·테두리·그림자)는 손대지 않는다 —
레거시 1:1 렌더 영역이고 P062 픽셀 대조가 회귀 게이트다.
-->
<SolidColorBrush x:Key="B.CanvasBg" Color="#D8D8D8" />
<SolidColorBrush x:Key="B.Chip" Color="#EFEFEF" />
<!-- 결과 문구용. #2E9E6B 는 B.Chip(#EFEFEF) 위 2.94:1 로 본문 기준 미달이었다 → 4.6:1 -->
<SolidColorBrush x:Key="B.Success" Color="#217A52" />
<!--
알림 대화상자 성격색 — 다크값을 그대로 쓸 수 없다.
경고 #E0A33A 는 흰 면 위 2.22:1 로 아이콘 기준(3:1)도 못 넘고, 오류 #E04A2B 는 4.05:1 로
아이콘은 되지만 본문 기준(4.5:1)에 못 미쳐 나중에 글자로 쓰면 무너진다.
#B45309 경고 5.02:1 / #C4321A 오류 5.50:1 (둘 다 B.Surface 기준).
-->
<SolidColorBrush x:Key="B.Warning" Color="#B45309" />
<SolidColorBrush x:Key="B.Danger" Color="#C4321A" />
<SolidColorBrush x:Key="B.Ok" Color="#1A7F37" />
<!-- 캔버스 오버레이 — 종이는 양 테마 모두 흰색이라(PageView 의 PaperBrush) 값이 같다.
테마별로 가르면 흰 종이 위 대비가 무너진다. -->
<SolidColorBrush x:Key="B.CanvasGuide" Color="#F24822" /><!-- 정렬 가이드 -->
<SolidColorBrush x:Key="B.CanvasSpacing" Color="#F24822" /><!-- 간격 균등 막대 -->
<!-- SQL 구문 색 — 흰 배경 대비 4.5:1 이상.
치환 변수는 이 편집기에서 가장 중요한 조각이라 가장 진하게 둔다. -->
<SolidColorBrush x:Key="B.SqlKeyword" Color="#0B5FA5" />
<SolidColorBrush x:Key="B.SqlFunction" Color="#7A3E9D" />
<SolidColorBrush x:Key="B.SqlNumber" Color="#B25000" />
<SolidColorBrush x:Key="B.SqlText" Color="#1A7F37" />
<SolidColorBrush x:Key="B.SqlComment" Color="#6B7280" />
<SolidColorBrush x:Key="B.SqlVariable" Color="#9A3412" />
<!-- 편집기 현재 줄 띠 — B.Hover 는 버튼 호버용이라 편집 면 위에서 안 보인다(다크에선 더 어둡기까지 하다) -->
<SolidColorBrush x:Key="B.SqlCurrentLine" Color="#F0F4F8" />
<!-- 카드 그림자 — B.FloatShadow 는 팔레트·플라이아웃용이라 카드엔 세다 -->
<DropShadowEffect x:Key="B.CardShadow" BlurRadius="10" ShadowDepth="1" Direction="270" Opacity="0.07" Color="Black" RenderingBias="Quality" />
<!-- 강조 채움 버튼의 호버·누름 — 다크 대응본 주석 참조(양 테마 동일값) -->
<SolidColorBrush x:Key="B.AccentFillHover" Color="#0C5B9C" />
<SolidColorBrush x:Key="B.AccentFillPressed" Color="#0A4C83" />
<SolidColorBrush x:Key="B.Dark" Color="#1A1A1A" />
<!-- 트리거/템플릿 추출 토큰 -->
<SolidColorBrush x:Key="B.BtnHover" Color="#F3F3F3" />
<SolidColorBrush x:Key="B.BtnPressed" Color="#EAEAEA" />
<SolidColorBrush x:Key="B.TabHover" Color="#F0F0F0" />
<SolidColorBrush x:Key="B.TabSel" Color="#E8E8E8" />
<SolidColorBrush x:Key="B.OnAccent" Color="#FFFFFF" />
<SolidColorBrush x:Key="B.ScrollThumb" Color="#CDCDCD" />
<SolidColorBrush x:Key="B.ScrollThumbHover" Color="#B6B6B6" />
<SolidColorBrush x:Key="B.ScrollThumbDrag" Color="#A2A2A2" />
<SolidColorBrush x:Key="B.CaptionFg" Color="#444444" />
<SolidColorBrush x:Key="B.CaptionFgHover" Color="#1A1A1A" />
<SolidColorBrush x:Key="B.CaptionHover" Color="#E8E8E8" />
<SolidColorBrush x:Key="B.CloseHover" Color="#E04A2B" />
<!-- 흰 슬라이더 썸은 라이트 배경에서 1.15:1 이라 이 링이 썸의 유일한 윤곽이다 — 옅으면 썸이 사라진다 -->
<SolidColorBrush x:Key="B.SliderRing" Color="#9A9A9A" />
<!-- 플로팅 요소(팔레트 바·플라이아웃) 그림자 — 라이트는 흰 배경에 검은 그림자가 튀지 않게 더 넓고 옅게 -->
<DropShadowEffect x:Key="B.FloatShadow" BlurRadius="26" ShadowDepth="5" Direction="270" Opacity="0.14" Color="Black" RenderingBias="Quality" />
<!-- ScrollViewer 코너 사각형 — 다크 대응본 주석 참조(프레임워크 템플릿 소속이라 키를 덮어쓴다) -->
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="#FFFFFF" />
</ResourceDictionary>