요약에서 환자를 두 번 적지 않고, 흐린 글씨를 표면 단위로 잡는다
## ① 요약이 환자를 두 번 적고 있었다 아래 버튼이 이미 "환자 해제 — 강한(0001381872) · 외래 2019-03-28 09:22 · 기준 …" 을 그대로 보여 주는데 요약도 같은 것을 다시 적었다. 두 줄로 늘어 결과 표를 밀어내고, 화면에 환자 이름이 필요 이상으로 여러 번 남았다. 환자가 있을 때는 침묵한다 — 버튼이 이미 말한다. 없을 때만 "변수 NULL — 구문만 검사" 를 남긴다(그 결과는 값이 아니라는 뜻이고, 그건 버튼 글자로는 알 수 없다). 빈 조각은 걸러 낸다 — 안 걸러 내면 "성공 · · 경고" 처럼 가운뎃점이 떠 있는다. ## ② 앞 수정이 부족했다 — 표면마다 경계가 따로 있다 카드 DockPanel 에만 힌트를 걸어 두고 고쳤다고 했는데 정작 SQL 글자는 계속 뭉개졌다. 본문은 SqlHighlightLayer 가 그리고 그 사이에 또 다른 중간 서피스가 있으며, 치환 변수 목록은 ListBox 템플릿 안에 ScrollViewer 를 품고 있다 — 카드에 건 힌트는 그 <b>바깥</b>이라 듣지 않는다(진단 표본 I 가 정확히 그 경우다). - SQL 편집 영역: 불투명 B.Surface 를 가진 안쪽 Border 에 힌트 - 검증 결과 창(TrialPane): 배경 + 힌트 - 치환 변수 목록: ItemsPanel 을 불투명하게 만들어 ScrollViewer <b>안쪽</b>에 힌트(표본 J). VirtualizingStackPanel 을 쓴다 — StackPanel 로 바꾸면 변수 120개가 전부 실체화된다. ## 게이트가 초록불인데 화면만 틀린 것을 또 만들지 않기 위해 앞 커밋에서 실제 창 표본을 넣었지만 <b>카드 제목만</b> 쟀다. 제목은 켜졌고(150) 본문은 꺼져 있었는데 게이트는 통과했다 — 같은 함정을 한 번 더 밟았다. 사람이 실제로 들여다보는 표면을 다 재도록 바꿨다: G 카드 제목 색번짐 150 H SQL 본문 색번짐 8,114 I 치환 변수 목록 색번짐 22,047 대조군(B Effect·C1 힌트를 Effect 요소에·I 힌트 바깥 ScrollViewer)은 모두 0 이므로 이 숫자들은 뜻이 있다. ## 게이트 - dotnet test 323/323 - --cleartype 실패 0 (실제 창 표본 1개 → 3개) - --query-popup 실패 0 · --edit-smoke 실패 0 · --dialog-shots FAIL 0 (변수 목록 그룹 표시 유지 확인 — ItemsPanel 교체가 그룹을 깨지 않았다) - --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 불변 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
52f1e30437
commit
bbbc7f5a08
@@ -51,14 +51,34 @@ internal static class ClearTypeCheck
|
|||||||
// 위 표본들은 <b>기법</b>이 듣는지를 잰다(합성 도형). 그것이 통과해도
|
// 위 표본들은 <b>기법</b>이 듣는지를 잰다(합성 도형). 그것이 통과해도
|
||||||
// 실제 창에 기법을 <b>안 걸었으면</b> 글자는 계속 뭉개진다 — 실제로 그랬다.
|
// 실제 창에 기법을 <b>안 걸었으면</b> 글자는 계속 뭉개진다 — 실제로 그랬다.
|
||||||
// 쿼리 편집 창은 카드에 그림자 Effect 가 있어 그 안 글자가 전부 중간 서피스를 탄다.
|
// 쿼리 편집 창은 카드에 그림자 Effect 가 있어 그 안 글자가 전부 중간 서피스를 탄다.
|
||||||
|
// 카드 제목만 재던 것으로는 부족했다 — 제목은 켜졌는데 <b>SQL 본문</b>은 계속 꺼져 있었다.
|
||||||
|
// 사람이 실제로 들여다보는 표면을 다 재야 한다: 본문·변수 목록·결과 요약.
|
||||||
var real = OpenQueryEditorForClearType();
|
var real = OpenQueryEditorForClearType();
|
||||||
if (real.Window is not null && real.Target is not null)
|
if (real is null)
|
||||||
{
|
{
|
||||||
samples.Add(("G(실제 창) 쿼리 편집 카드 안 글자", real.Target, true));
|
Lines.Add("SKIP G~J(실제 창) — 창을 띄우지 못해 판정 불가");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Lines.Add("SKIP G(실제 창) — 창을 띄우지 못해 판정 불가");
|
foreach (var (label, name) in new[]
|
||||||
|
{
|
||||||
|
("G(실제 창) 카드 제목", "SQL 편집기"),
|
||||||
|
("H(실제 창) SQL 본문", "Highlight"),
|
||||||
|
("I(실제 창) 치환 변수 목록", "VariableList"),
|
||||||
|
})
|
||||||
|
{
|
||||||
|
var target = name == "SQL 편집기"
|
||||||
|
? FindTextBlock(real, name)
|
||||||
|
: real.FindName(name) as FrameworkElement;
|
||||||
|
if (target is { ActualWidth: > 0 })
|
||||||
|
{
|
||||||
|
samples.Add((label, target, true));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Lines.Add($"SKIP {label} — 대상을 찾지 못해 판정 불가");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 창이 보이는 것과 합성기가 그려 낸 것은 다르다 — Loaded 직후 찍으면 빈 화면을 잰다.
|
// 창이 보이는 것과 합성기가 그려 낸 것은 다르다 — Loaded 직후 찍으면 빈 화면을 잰다.
|
||||||
@@ -106,11 +126,12 @@ internal static class ClearTypeCheck
|
|||||||
/// 창은 화면 안(0,0)에 띄운다. BitBlt 는 화면에 실제로 그려진 픽셀만 읽으므로
|
/// 창은 화면 안(0,0)에 띄운다. BitBlt 는 화면에 실제로 그려진 픽셀만 읽으므로
|
||||||
/// 화면 밖(-10000)에 두면 아무것도 못 잰다.
|
/// 화면 밖(-10000)에 두면 아무것도 못 잰다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static (Window? Window, FrameworkElement? Target) OpenQueryEditorForClearType()
|
private static Window? OpenQueryEditorForClearType()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var editor = new Views.QueryEditorWindow("MDataTable1", "select 1 from dual")
|
var editor = new Views.QueryEditorWindow("MDataTable1",
|
||||||
|
"select PatChtNum, PatNam from P_PatInf where ROWNUM <= 1")
|
||||||
{
|
{
|
||||||
Left = 0,
|
Left = 0,
|
||||||
Top = 0,
|
Top = 0,
|
||||||
@@ -118,14 +139,12 @@ internal static class ClearTypeCheck
|
|||||||
};
|
};
|
||||||
editor.Show();
|
editor.Show();
|
||||||
editor.UpdateLayout();
|
editor.UpdateLayout();
|
||||||
// 카드 제목은 13.5px SemiBold — 뭉개짐이 가장 먼저 보이는 자리다
|
return editor;
|
||||||
var target = FindTextBlock(editor, "SQL 편집기");
|
|
||||||
return (editor, target);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Lines.Add($"SKIP G(실제 창) — {ex.GetType().Name}: {ex.Message}");
|
Lines.Add($"SKIP G~I(실제 창) — {ex.GetType().Name}: {ex.Message}");
|
||||||
return (null, null);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -317,7 +317,9 @@
|
|||||||
</DockPanel>
|
</DockPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<DockPanel x:Name="TrialPane" Visibility="Collapsed" Margin="12,10,12,10">
|
<DockPanel x:Name="TrialPane" Visibility="Collapsed" Margin="12,10,12,10"
|
||||||
|
Background="{DynamicResource B.Surface}"
|
||||||
|
RenderOptions.ClearTypeHint="Enabled">
|
||||||
<DockPanel DockPanel.Dock="Top" Margin="0,0,0,8">
|
<DockPanel DockPanel.Dock="Top" Margin="0,0,0,8">
|
||||||
<Button DockPanel.Dock="Right" Content="닫기"
|
<Button DockPanel.Dock="Right" Content="닫기"
|
||||||
Style="{StaticResource LinkBtn}" Click="OnCloseTrial"/>
|
Style="{StaticResource LinkBtn}" Click="OnCloseTrial"/>
|
||||||
@@ -338,8 +340,13 @@
|
|||||||
본문 사이 구분선까지 함께 휘어 보인다. -->
|
본문 사이 구분선까지 함께 휘어 보인다. -->
|
||||||
<!-- 본문 면은 B.Surface 다. B.Input 을 쓰면 다크에서 홈통(B.Chip)과 같은 #262626 이라
|
<!-- 본문 면은 B.Surface 다. B.Input 을 쓰면 다크에서 홈통(B.Chip)과 같은 #262626 이라
|
||||||
홈통이 통째로 사라진다(양 토큰이 같은 값이다). -->
|
홈통이 통째로 사라진다(양 토큰이 같은 값이다). -->
|
||||||
|
<!-- ClearTypeHint 를 여기에 건다. 카드 DockPanel 에만 걸어 봤더니 SQL 글자는
|
||||||
|
계속 뭉개졌다 — 본문은 이 아래 SqlHighlightLayer 가 그리고, 그 사이에
|
||||||
|
또 다른 중간 서피스가 있다(진단 cleartype 표본 I·J — ScrollViewer 도 경계다).
|
||||||
|
이 Border 는 불투명 B.Surface 를 갖고 Effect 경계 안쪽이라 조건이 맞는다. -->
|
||||||
<Border BorderThickness="1" CornerRadius="0"
|
<Border BorderThickness="1" CornerRadius="0"
|
||||||
BorderBrush="{DynamicResource B.Line2}" Background="{DynamicResource B.Surface}">
|
BorderBrush="{DynamicResource B.Line2}" Background="{DynamicResource B.Surface}"
|
||||||
|
RenderOptions.ClearTypeHint="Enabled">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
@@ -455,6 +462,19 @@
|
|||||||
HorizontalContentAlignment="Stretch"
|
HorizontalContentAlignment="Stretch"
|
||||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||||
AutomationProperties.Name="치환 변수 목록">
|
AutomationProperties.Name="치환 변수 목록">
|
||||||
|
<!--
|
||||||
|
ListBox 는 템플릿 안에 ScrollViewer 를 품고 있고 그것이 중간 서피스다 —
|
||||||
|
카드에 건 힌트는 <b>바깥</b>이라 목록 글자에는 듣지 않는다(표본 I).
|
||||||
|
항목 패널을 불투명하게 만들어 힌트를 ScrollViewer <b>안쪽</b>에 둔다(표본 J).
|
||||||
|
StackPanel 이 아니라 VirtualizingStackPanel 이어야 한다 —
|
||||||
|
바꾸면 변수 120개가 전부 실체화된다.
|
||||||
|
-->
|
||||||
|
<ListBox.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<VirtualizingStackPanel Background="{DynamicResource B.Surface}"
|
||||||
|
RenderOptions.ClearTypeHint="Enabled"/>
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ListBox.ItemsPanel>
|
||||||
<ListBox.ItemTemplate>
|
<ListBox.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<DockPanel Margin="0,3" ToolTip="{Binding Token}">
|
<DockPanel Margin="0,3" ToolTip="{Binding Token}">
|
||||||
|
|||||||
@@ -560,11 +560,12 @@ public partial class QueryEditorWindow : Window
|
|||||||
}
|
}
|
||||||
|
|
||||||
TrialPane.Visibility = Visibility.Visible;
|
TrialPane.Visibility = Visibility.Visible;
|
||||||
// 무엇으로 돌렸는지 먼저 말한다 — 실제 값인지 자리표시인지에 따라 결과의 의미가 완전히 다르다.
|
// 무엇으로 돌렸는지는 말해야 하지만 <b>환자를 두 번 적지 않는다</b> —
|
||||||
// 이 한 줄이 없으면 0행을 보고 "이 환자에게 자료가 없다"로 잘못 읽는다.
|
// 아래 버튼이 이미 "환자 해제 — 강한(0001381872) · 외래 …" 를 그대로 보여 준다.
|
||||||
var basis = variables is not null
|
// 같은 정보를 두 군데 적으면 요약이 두 줄로 늘어 결과 표를 밀어내고,
|
||||||
? $"환자 {Services.PatientSession.Label} 의 실제 값으로 실행"
|
// 화면에 환자 이름이 필요 이상으로 여러 번 남는다.
|
||||||
: "환자를 고르지 않아 변수를 NULL 로 두고 구문만 검사";
|
// 환자가 있을 때 필요한 말은 이미 버튼이 하고 있으므로 여기서는 침묵한다.
|
||||||
|
var basis = variables is not null ? string.Empty : "변수 NULL — 구문만 검사";
|
||||||
var notes = new List<string>();
|
var notes = new List<string>();
|
||||||
// 환자를 안 골랐으면 <b>모든</b> 변수가 Unknown 이다 — 그것을 "아직 옮기지 않았다"고 적으면
|
// 환자를 안 골랐으면 <b>모든</b> 변수가 Unknown 이다 — 그것을 "아직 옮기지 않았다"고 적으면
|
||||||
// 거짓이 된다(ChtNum 은 옮겨져 있다). 그 사유는 위 basis 줄이 이미 말한다.
|
// 거짓이 된다(ChtNum 은 옮겨져 있다). 그 사유는 위 basis 줄이 이미 말한다.
|
||||||
@@ -597,7 +598,9 @@ public partial class QueryEditorWindow : Window
|
|||||||
? " — 구문은 정상입니다(변수가 NULL 이라 조건에 걸리는 행이 없습니다)."
|
? " — 구문은 정상입니다(변수가 NULL 이라 조건에 걸리는 행이 없습니다)."
|
||||||
: " — 구문은 정상이고, 이 환자에게 해당하는 행이 없습니다.")
|
: " — 구문은 정상이고, 이 환자에게 해당하는 행이 없습니다.")
|
||||||
: result.Summary;
|
: result.Summary;
|
||||||
TrialSummary.Text = string.Join(" · ", new[] { head, basis }.Concat(notes));
|
// 빈 조각은 버린다 — 안 버리면 "성공 · · 경고" 처럼 가운뎃점이 떠 있는다
|
||||||
|
TrialSummary.Text = string.Join(" · ",
|
||||||
|
new[] { head, basis }.Concat(notes).Where(s => s.Length > 0));
|
||||||
TrialGrid.ItemsSource = ToGridRows(result);
|
TrialGrid.ItemsSource = ToGridRows(result);
|
||||||
TrialGrid.Visibility = result.Rows.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
|
TrialGrid.Visibility = result.Rows.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
|
||||||
}
|
}
|
||||||
@@ -605,7 +608,7 @@ public partial class QueryEditorWindow : Window
|
|||||||
{
|
{
|
||||||
TrialSummary.Foreground = (System.Windows.Media.Brush)FindResource("B.Danger");
|
TrialSummary.Foreground = (System.Windows.Media.Brush)FindResource("B.Danger");
|
||||||
TrialSummary.Text = string.Join(" · ",
|
TrialSummary.Text = string.Join(" · ",
|
||||||
new[] { "실패 — " + result.Error, basis }.Concat(notes));
|
new[] { "실패 — " + result.Error, basis }.Concat(notes).Where(s => s.Length > 0));
|
||||||
TrialGrid.ItemsSource = null;
|
TrialGrid.ItemsSource = null;
|
||||||
TrialGrid.Visibility = Visibility.Collapsed;
|
TrialGrid.Visibility = Visibility.Collapsed;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user