From 13edf3ecd9434d3da851ffbf73156f667ac20f6d Mon Sep 17 00:00:00 2001 From: Msystech Date: Thu, 20 Aug 2026 17:56:36 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A0=9C=EB=AA=A9=EC=A4=84=20=ED=99=98?= =?UTF-8?q?=EC=9E=90=20=EC=95=84=EC=9D=B4=EC=BD=98=EC=9D=B4=20=ED=98=BC?= =?UTF-8?q?=EC=9E=90=20=EA=B9=8C=EB=A7=B8=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 지적을 받고서야 실제로 봤다. 앞 커밋에서 "제목줄의 환자 아이콘 버튼은 손대지 않았다 — 옆 아이콘들과 같은 스타일·크기다" 라고 썼는데, 마크업만 읽고 화면을 안 봤다. 스타일과 크기는 같았지만 색이 달랐다. ## 무슨 일이었나 이웃 아이콘(복사·삭제·테마·저장)은 XAML 컨버터를 타고, 그 기본 브러시 키가 B.Muted 다. 환자 아이콘만 코드에서 만드는데 안 고른 상태에 null 을 넘겼고, LucideIcons.Paint 는 키도 색도 없으면 Brushes.Black 으로 칠했다 — 어두운 제목줄에서 안 보이는 아이콘이라는 뜻이다. 컴파일러가 CS8604 로 그 자리(MainView.xaml.cs:139)를 이 세션 내내 경고하고 있었다. 빌드 로그에서 매번 지나쳤다. ## 두 군데를 고친다 ① 호출부 — 안 고른 상태의 키를 "B.Muted" 로. 이웃과 같은 토큰이라 테마 전환도 따라간다. ② 기본값 자체 — 색도 키도 없으면 이제 B.Muted 리소스 참조로 떨어진다. 검정은 다크 테마에서 아이콘을 숨기는 기본값이라 함정으로 남겨 둘 이유가 없다. null 을 넘기던 호출부는 ①이 유일했으므로 다른 곳의 색은 바뀌지 않는다. ## 확인 방법도 고쳤다 이번에는 제목줄을 잘라 3배로 키워 다크·라이트 양쪽을 눈으로 대조했다. 전에는 대화상자 사진만 보고 제목줄은 마크업으로 판단했다 — 그래서 놓쳤다. 회귀 방지로 edit-smoke 에 "아이콘 기본색이 하드코딩 검정이 아니다" 를 넣는다. ## 판정 - 단위 시험 388 · edit-smoke 377건 전건 통과 (아이콘 색 1건 추가) - CS8604 경고 소멸 - --dialog-shots 69장 · --modal-check · --maxrect · --scale-budget 전건 통과 - --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 불변 Co-Authored-By: Claude Fable 5 --- src/SheetMe.Designer/Controls/LucideIcons.cs | 16 ++++++++- src/SheetMe.Designer/Diagnostics/EditSmoke.cs | 33 +++++++++++++++++++ src/SheetMe.Designer/Views/MainView.xaml.cs | 6 +++- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/SheetMe.Designer/Controls/LucideIcons.cs b/src/SheetMe.Designer/Controls/LucideIcons.cs index 0e6cb9f..46f30d0 100644 --- a/src/SheetMe.Designer/Controls/LucideIcons.cs +++ b/src/SheetMe.Designer/Controls/LucideIcons.cs @@ -168,6 +168,15 @@ public static class LucideIcons return new Viewbox { Width = size, Height = size, Child = canvas, Stretch = Stretch.Uniform, SnapsToDevicePixels = true }; } + /// + /// 아이콘 색 칠하기 — 키가 있으면 리소스 참조(테마 추종), 없으면 넘겨받은 브러시. + /// + /// 둘 다 없으면 검정이 아니라 B.Muted 다. 전에는 Brushes.Black 으로 떨어졌는데, + /// 그건 다크 테마에서 아이콘을 보이지 않게 만드는 기본값이다. + /// 실제로 제목줄의 환자 아이콘이 그 경로로 혼자만 까맣게 묻혀 있었고, + /// 컴파일러가 CS8604 로 그 자리를 계속 가리키고 있었는데도 오래 남아 있었다. + /// 기본값을 테마 토큰으로 두면 어느 호출부도 같은 함정에 빠질 수 없다. + /// private static void Paint(Path path, DependencyProperty property, Brush? color, string? brushKey) { if (brushKey is not null) @@ -175,7 +184,12 @@ public static class LucideIcons path.SetResourceReference(property, brushKey); return; } - path.SetValue(property, color ?? Brushes.Black); + if (color is not null) + { + path.SetValue(property, color); + return; + } + path.SetResourceReference(property, "B.Muted"); } private static (GeometryGroup Stroke, GeometryGroup Fill) Parse(string markup) diff --git a/src/SheetMe.Designer/Diagnostics/EditSmoke.cs b/src/SheetMe.Designer/Diagnostics/EditSmoke.cs index 1f04387..2800a6f 100644 --- a/src/SheetMe.Designer/Diagnostics/EditSmoke.cs +++ b/src/SheetMe.Designer/Diagnostics/EditSmoke.cs @@ -36,6 +36,23 @@ public static class EditSmoke /// 종이에 실제로 그려진 글자를 모은다 — 값이 찍혔는지는 시각 트리에서 확인해야 한다. /// VM 속성만 보면 템플릿이 그 값을 쓰는지 알 수 없다(배선과 결과는 다른 문제다). /// + /// 시각 트리에서 Path 를 전부 모은다 — 아이콘 색 검사에 쓴다 + private static IEnumerable FindPaths(System.Windows.DependencyObject node) + { + if (node is System.Windows.Shapes.Path path) + { + yield return path; + } + // 아이콘은 Viewbox → Canvas → Path 라 논리 자식을 훑어야 한다(시각 트리는 아직 안 만들어졌다) + foreach (var child in System.Windows.LogicalTreeHelper.GetChildren(node).OfType()) + { + foreach (var found in FindPaths(child)) + { + yield return found; + } + } + } + private static string CollectText(System.Windows.DependencyObject node) { var text = node is System.Windows.Controls.TextBlock block ? block.Text + "\n" : string.Empty; @@ -1095,6 +1112,22 @@ public static class EditSmoke $"ValueText='{choiceRow.ValueText}' IsMixed={choiceRow.IsMixed}"); } + // 15-a00) 아이콘 기본색이 검정으로 떨어지지 않는다. + // + // 색도 리소스 키도 안 준 아이콘이 Brushes.Black 으로 칠해지고 있었다. + // 다크 테마에서 그건 안 보이는 아이콘이라는 뜻이다 — 제목줄의 환자 아이콘이 + // 정확히 그 상태로, 옆 아이콘들이 B.Muted 로 밝게 그려지는 사이에서 혼자 까맸다. + // 컴파일러가 CS8604 로 그 자리를 가리키고 있었는데도 오래 남아 있었다. + { + var iconVisual = Controls.LucideIcons.Icon("user", 16, (System.Windows.Media.Brush?)null); + var painted = FindPaths(iconVisual).ToList(); + Check("아이콘: 기본색이 하드코딩 검정이 아니다", + painted.Count > 0 && painted.All(p => + !ReferenceEquals(p.Stroke, System.Windows.Media.Brushes.Black) + && !ReferenceEquals(p.Fill, System.Windows.Media.Brushes.Black)), + $"경로 {painted.Count}개"); + } + // 15-a0) 선택 확장 — 정렬·간격 명령이 전제하는 '올바른 선택'을 만드는 수단. // // 마퀴는 교차 판정이라 행 띠를 스치는 것이 전부 딸려 온다(실측 787건: diff --git a/src/SheetMe.Designer/Views/MainView.xaml.cs b/src/SheetMe.Designer/Views/MainView.xaml.cs index 57fb1b9..4616360 100644 --- a/src/SheetMe.Designer/Views/MainView.xaml.cs +++ b/src/SheetMe.Designer/Views/MainView.xaml.cs @@ -136,7 +136,11 @@ public partial class MainView : Window return; } var on = PatientSession.HasPatient; - PatientIconButton.Content = Controls.LucideIcons.Icon("user", 16, on ? "B.Accent" : null); + // 안 고른 상태의 색은 B.Muted 다 — 옆 아이콘들(복사·삭제·테마·저장)이 XAML 컨버터의 + // 기본값으로 쓰는 바로 그 키다. 전에는 null 을 넘겼고, 그러면 아이콘이 테마 토큰이 아니라 + // 하드코딩 검정으로 칠해져 어두운 제목줄에서 혼자만 까맣게 묻혔다. + // (컴파일러가 CS8604 로 계속 경고하고 있었는데 그 경고가 가리키던 것이 이것이다.) + PatientIconButton.Content = Controls.LucideIcons.Icon("user", 16, on ? "B.Accent" : "B.Muted"); PatientIconButton.ToolTip = on ? $"환자: {PatientSession.Label}\n누르면 바꾸기·해제" : "환자 선택 — 태그와 MDataTable 에 실제 값이 들어갑니다(앱 전체 적용)";