쿼리 편집에서 환자를 고를 수 있게 하고, 카드 안 글씨를 다시 선명하게 만든다
"아직도 안됨, 그리고 글씨도 흐리게보이고" — 둘 다 맞다. ## ① 안 되는 게 아니라 고를 수가 없었다 ORA-00936 은 사라졌고 검증 실행은 성공한다. 그런데 0행이다. 화면이 이유를 말하고 있었다 — "환자를 고르지 않아 변수를 NULL 로 두고 구문만 검사". 그런데 <b>환자 선택이 미리보기 창 안에만 있었다.</b> 쿼리를 고치는 사람은 값 확인을 할 방법이 없고, 늘 0행이면 그건 "안 된다"로 읽힌다. 사유를 정확히 말해도 고칠 수단이 없으면 안내가 아니다. 검증 실행 옆에 '환자 선택...' 을 뒀다. 고르면 치환 변수에 실제 값이 들어가 구문뿐 아니라 값까지 확인된다. 세션 하나를 공유하므로 미리보기와 같은 환자다. 이미 고른 상태에서는 버튼이 '환자 해제 — <이름>' 이 된다 — 버튼 하나에 고르기·바꾸기·해제를 다 넣으면 무엇이 일어날지 예측할 수 없다. ## ② 카드 그림자가 ClearType 을 끄고 있었다 이 세션에서 미뤄 둔 항목이다. Card 스타일이 Effect(그림자)를 걸고, Effect 는 하위 트리 전체를 중간 서피스로 보내 ClearType 을 끈다 — 13px 한글이 회색 안티에일리어싱으로 뭉개진다. 힌트는 Effect 가 걸린 Border 에 걸면 듣지 않는다(--cleartype 표본 C1 이 그것이다). 안쪽의 불투명 배경 요소에 걸어야 한다(C2). 카드 안 DockPanel 에 배경과 힌트를 줬다. ## 기법이 듣는 것과 걸어 둔 것은 다른 일이다 --cleartype 은 그동안 <b>합성 도형</b>만 쟀다. A~J 전부 통과했는데도 실제 창에는 기법을 안 걸어 둬서 글씨가 계속 뭉개졌다 — 게이트가 초록불인 채로 사용자가 보는 화면만 틀려 있었다. 그래서 실제 쿼리 편집 창을 띄워 카드 제목을 재는 표본 G 를 넣었다. 색번짐 150 / 글자픽셀 188 → 켜짐. 고치기 전 조건은 표본 B(Effect + 힌트 없음)와 같고 그건 0 이다. 창은 화면 안(0,0)에 띄운다 — BitBlt 은 실제로 그려진 픽셀만 읽으므로 화면 밖에 두면 아무것도 못 잰다. ## 게이트 - dotnet test 323/323 - --cleartype 실패 0 (A~J + G(실제 창) 신규) - --query-popup 실패 0 · --edit-smoke 실패 0 · --dialog-shots FAIL 0 - --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
8964c662f3
commit
52f1e30437
@@ -47,6 +47,20 @@ internal static class ClearTypeCheck
|
|||||||
var window = BuildProbe(out var samples, out var popups);
|
var window = BuildProbe(out var samples, out var popups);
|
||||||
window.Show();
|
window.Show();
|
||||||
|
|
||||||
|
// ── 실제 창을 하나 잰다 ──
|
||||||
|
// 위 표본들은 <b>기법</b>이 듣는지를 잰다(합성 도형). 그것이 통과해도
|
||||||
|
// 실제 창에 기법을 <b>안 걸었으면</b> 글자는 계속 뭉개진다 — 실제로 그랬다.
|
||||||
|
// 쿼리 편집 창은 카드에 그림자 Effect 가 있어 그 안 글자가 전부 중간 서피스를 탄다.
|
||||||
|
var real = OpenQueryEditorForClearType();
|
||||||
|
if (real.Window is not null && real.Target is not null)
|
||||||
|
{
|
||||||
|
samples.Add(("G(실제 창) 쿼리 편집 카드 안 글자", real.Target, true));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Lines.Add("SKIP G(실제 창) — 창을 띄우지 못해 판정 불가");
|
||||||
|
}
|
||||||
|
|
||||||
// 창이 보이는 것과 합성기가 그려 낸 것은 다르다 — Loaded 직후 찍으면 빈 화면을 잰다.
|
// 창이 보이는 것과 합성기가 그려 낸 것은 다르다 — Loaded 직후 찍으면 빈 화면을 잰다.
|
||||||
// (--modal-check 에서 BeginInvoke 가 Loaded 보다 먼저 돌아 0 을 세던 것과 같은 함정)
|
// (--modal-check 에서 BeginInvoke 가 Loaded 보다 먼저 돌아 0 을 세던 것과 같은 함정)
|
||||||
var timer = new System.Windows.Threading.DispatcherTimer
|
var timer = new System.Windows.Threading.DispatcherTimer
|
||||||
@@ -84,6 +98,57 @@ internal static class ClearTypeCheck
|
|||||||
return failures == 0 ? 0 : 1;
|
return failures == 0 ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 실제 쿼리 편집 창을 띄워 카드 제목 글자를 잴 대상으로 내준다.
|
||||||
|
///
|
||||||
|
/// 합성 표본이 아니라 <b>배포되는 창</b>을 재야 한다 — 기법이 듣는 것과
|
||||||
|
/// 그 기법을 이 창에 걸어 둔 것은 다른 일이고, 후자가 빠져 있었다.
|
||||||
|
/// 창은 화면 안(0,0)에 띄운다. BitBlt 는 화면에 실제로 그려진 픽셀만 읽으므로
|
||||||
|
/// 화면 밖(-10000)에 두면 아무것도 못 잰다.
|
||||||
|
/// </summary>
|
||||||
|
private static (Window? Window, FrameworkElement? Target) OpenQueryEditorForClearType()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var editor = new Views.QueryEditorWindow("MDataTable1", "select 1 from dual")
|
||||||
|
{
|
||||||
|
Left = 0,
|
||||||
|
Top = 0,
|
||||||
|
WindowStartupLocation = WindowStartupLocation.Manual,
|
||||||
|
};
|
||||||
|
editor.Show();
|
||||||
|
editor.UpdateLayout();
|
||||||
|
// 카드 제목은 13.5px SemiBold — 뭉개짐이 가장 먼저 보이는 자리다
|
||||||
|
var target = FindTextBlock(editor, "SQL 편집기");
|
||||||
|
return (editor, target);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Lines.Add($"SKIP G(실제 창) — {ex.GetType().Name}: {ex.Message}");
|
||||||
|
return (null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>이 글자를 담은 TextBlock 을 찾는다 — 없으면 null</summary>
|
||||||
|
private static FrameworkElement? FindTextBlock(DependencyObject root, string text)
|
||||||
|
{
|
||||||
|
if (root is System.Windows.Controls.TextBlock block
|
||||||
|
&& block.Text.Contains(text, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
var count = System.Windows.Media.VisualTreeHelper.GetChildrenCount(root);
|
||||||
|
for (var i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (FindTextBlock(System.Windows.Media.VisualTreeHelper.GetChild(root, i), text)
|
||||||
|
is { } found)
|
||||||
|
{
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>대조군이 먼저 서야 나머지 숫자가 뜻을 갖는다</summary>
|
/// <summary>대조군이 먼저 서야 나머지 숫자가 뜻을 갖는다</summary>
|
||||||
private static void Judge(List<(string Name, FrameworkElement Target, bool ExpectClearType)> samples)
|
private static void Judge(List<(string Name, FrameworkElement Target, bool ExpectClearType)> samples)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -241,6 +241,14 @@
|
|||||||
<TextBlock Text="검증 실행" VerticalAlignment="Center"/>
|
<TextBlock Text="검증 실행" VerticalAlignment="Center"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Button>
|
</Button>
|
||||||
|
<!--
|
||||||
|
환자 선택 — 검증 실행을 <b>실제 값</b>으로 돌리려면 여기서 고를 수 있어야 한다.
|
||||||
|
전에는 미리보기 창 안에만 있어서, 쿼리를 고치는 사람은 값 확인을 할 수 없었다
|
||||||
|
(변수가 NULL 로 들어가 늘 0행이었고, 그건 "안 된다"로 읽힌다).
|
||||||
|
고른 환자는 세션 하나를 공유하므로 미리보기와 같은 환자다.
|
||||||
|
-->
|
||||||
|
<Button x:Name="PatientButton" Padding="14,8" Margin="10,0,0,0" Click="OnPickPatient"
|
||||||
|
ToolTip="환자를 고르면 치환 변수에 실제 값이 들어가 값까지 확인됩니다"/>
|
||||||
<Button Content="확인" Padding="30,8" Margin="10,0,0,0"
|
<Button Content="확인" Padding="30,8" Margin="10,0,0,0"
|
||||||
Style="{StaticResource Primary}" Click="OnConfirm" IsDefault="True"/>
|
Style="{StaticResource Primary}" Click="OnConfirm" IsDefault="True"/>
|
||||||
<Button Content="취소" Padding="26,8" Margin="10,0,0,0" IsCancel="True"/>
|
<Button Content="취소" Padding="26,8" Margin="10,0,0,0" IsCancel="True"/>
|
||||||
@@ -259,7 +267,11 @@
|
|||||||
|
|
||||||
<!-- ══ SQL 편집기 카드 ══ -->
|
<!-- ══ SQL 편집기 카드 ══ -->
|
||||||
<Border Grid.Column="0" Style="{StaticResource Card}">
|
<Border Grid.Column="0" Style="{StaticResource Card}">
|
||||||
<DockPanel Margin="14,12,14,12">
|
<!-- 불투명 배경 + ClearTypeHint 를 <b>안쪽</b>에 둔다. Card 의 Effect(그림자)가
|
||||||
|
중간 서피스를 만들어 ClearType 을 끄고, 그러면 13px 한글이 회색
|
||||||
|
안티에일리어싱으로 뭉개진다. 힌트를 Effect 가 걸린 Border 에 걸면 듣지 않는다. -->
|
||||||
|
<DockPanel Margin="14,12,14,12" Background="{DynamicResource B.Surface}"
|
||||||
|
RenderOptions.ClearTypeHint="Enabled">
|
||||||
<TextBlock DockPanel.Dock="Top" Text="SQL 편집기" Style="{StaticResource CardTitle}"
|
<TextBlock DockPanel.Dock="Top" Text="SQL 편집기" Style="{StaticResource CardTitle}"
|
||||||
Margin="0,0,0,10"/>
|
Margin="0,0,0,10"/>
|
||||||
|
|
||||||
@@ -393,7 +405,11 @@
|
|||||||
|
|
||||||
<!-- ══ 치환 변수 카드 ══ -->
|
<!-- ══ 치환 변수 카드 ══ -->
|
||||||
<Border x:Name="VariablePane" Grid.Column="2" Style="{StaticResource Card}">
|
<Border x:Name="VariablePane" Grid.Column="2" Style="{StaticResource Card}">
|
||||||
<DockPanel Margin="14,12,14,12">
|
<!-- 불투명 배경 + ClearTypeHint 를 <b>안쪽</b>에 둔다. Card 의 Effect(그림자)가
|
||||||
|
중간 서피스를 만들어 ClearType 을 끄고, 그러면 13px 한글이 회색
|
||||||
|
안티에일리어싱으로 뭉개진다. 힌트를 Effect 가 걸린 Border 에 걸면 듣지 않는다. -->
|
||||||
|
<DockPanel Margin="14,12,14,12" Background="{DynamicResource B.Surface}"
|
||||||
|
RenderOptions.ClearTypeHint="Enabled">
|
||||||
<TextBlock DockPanel.Dock="Top" Text="치환 변수" Style="{StaticResource CardTitle}"
|
<TextBlock DockPanel.Dock="Top" Text="치환 변수" Style="{StaticResource CardTitle}"
|
||||||
Margin="0,0,0,10"/>
|
Margin="0,0,0,10"/>
|
||||||
|
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ public partial class QueryEditorWindow : Window
|
|||||||
TextCompositionManager.AddTextInputHandler(SqlBox, OnComposed);
|
TextCompositionManager.AddTextInputHandler(SqlBox, OnComposed);
|
||||||
RebuildBucketChips();
|
RebuildBucketChips();
|
||||||
ApplyVariableFilter(string.Empty);
|
ApplyVariableFilter(string.Empty);
|
||||||
|
RefreshPatientButton();
|
||||||
var connection = Services.ConfigService.Current.ConnectionString;
|
var connection = Services.ConfigService.Current.ConnectionString;
|
||||||
workbench = new SheetMe.Data.Stores.OracleQueryWorkbench(connection);
|
workbench = new SheetMe.Data.Stores.OracleQueryWorkbench(connection);
|
||||||
if (!workbench.CanUseDb)
|
if (!workbench.CanUseDb)
|
||||||
@@ -190,6 +191,41 @@ public partial class QueryEditorWindow : Window
|
|||||||
/// <summary>진단(--query-popup)에서 검증 실행을 부르는 통로 — 결과 표가 실제로 차는지 본다</summary>
|
/// <summary>진단(--query-popup)에서 검증 실행을 부르는 통로 — 결과 표가 실제로 차는지 본다</summary>
|
||||||
internal void RunTrialForSmoke() => OnTrial(this, new RoutedEventArgs());
|
internal void RunTrialForSmoke() => OnTrial(this, new RoutedEventArgs());
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 환자를 고른다 — 고르면 검증 실행이 <b>실제 값</b>으로 돈다.
|
||||||
|
///
|
||||||
|
/// 권한 문·감사 기록·문맥 읽기는 전부 <see cref="PatientPickerDialogView.Pick"/> 안에 있다.
|
||||||
|
/// 세션 하나를 공유하므로 미리보기와 같은 환자다 — 두 화면이 다른 환자를 보면 구분할 수 없다.
|
||||||
|
/// </summary>
|
||||||
|
private void OnPickPatient(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (Services.PatientSession.HasPatient)
|
||||||
|
{
|
||||||
|
// 이미 고른 환자가 있으면 이 버튼은 '해제'다. 바꾸려면 해제하고 다시 고른다 —
|
||||||
|
// 버튼 하나에 '고르기/바꾸기/해제'를 다 넣으면 무엇이 일어날지 예측할 수 없다.
|
||||||
|
Services.PatientSession.Set(null, string.Empty);
|
||||||
|
RefreshPatientButton();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (PatientPickerDialogView.Pick(this, out var label) is { } picked)
|
||||||
|
{
|
||||||
|
Services.PatientSession.Set(picked, label);
|
||||||
|
RefreshPatientButton();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>버튼이 지금 무엇을 하는지 글자로 말한다 — 상태를 색으로만 알리면 못 읽는다</summary>
|
||||||
|
private void RefreshPatientButton()
|
||||||
|
{
|
||||||
|
if (PatientButton is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PatientButton.Content = Services.PatientSession.HasPatient
|
||||||
|
? $"환자 해제 — {Services.PatientSession.Label}"
|
||||||
|
: "환자 선택...";
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>커서 위치를 보고 목록을 띄우거나 닫는다</summary>
|
/// <summary>커서 위치를 보고 목록을 띄우거나 닫는다</summary>
|
||||||
private void UpdateCompletion()
|
private void UpdateCompletion()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user