메인 화면을 게이트에 넣고, 최소 크기를 단일 출처로, 창 크기를 기억한다

재설계 1단계 계속.

<b>메인 셸이 게이트에 아예 없었다.</b> 사용자가 하루 종일 보는 화면만 자동 검증 밖이었다.
넣고 나서 글자 31개만 검사되는 것을 보고 빈 껍데기를 찍고 있다는 것을 알았다 —
컨트롤을 놓고 하나를 골라 인스펙터·레이어를 채우니 81~95개가 된다.
세 크기·탭으로 찍는다: 기본 1440x920, 현장 최대화 1920x1032, 도구 상자 탭.
Loaded 커맨드(서식 목록 DB 조회)는 진단 모드에서 돌지 않게 막았다 —
게이트 결과가 접속 상태에 따라 달라지면 안 된다.

<b>게이트가 게이트의 오류를 잡았다.</b> 메인 화면을 넣자 세로잘림 30건이 떴는데 전부 오탐이었다.
DesiredSize 는 Margin 을 포함하고 RenderSize 는 포함하지 않아서, 세로 Margin 이 있는
TextBlock 이 예외 없이 걸린 것이다(도구 상자 그룹 머리가 "필요 27 > 실제 14" 였고 그 13 이 Margin).
Margin 을 빼고 비교하도록 고쳤다. 이 검사기에서 측정이 나를 정정한 세 번째다.

<b>--maxrect 가 최소 크기를 베껴 두고 있었다.</b> ProbeMinWidth=940 / ProbeMinHeight=640 /
ProbeBorder=6 은 MainView.xaml 의 복사본이라, 최소 크기를 바꾸면 이 검사가
<b>옛 값을 계속 검사하며 계속 통과한다</b>. 실제 MainView 를 만들어 XAML 이 정한 값을 읽는다.

<b>창 크기·위치·상태·두 패널 폭을 기억한다.</b> UserPrefs 가 Dictionary&lt;string,bool&gt; 이라
숫자를 못 담던 것이 원인이었다. JsonElement 로 바꿔 이미 깔린 prefs.json 이 살아남게 했다 —
string 이나 double 로 바꾸면 역직렬화가 터져 기존 취향이 통째로 초기화된다.

복원값은 반드시 클램프한다. 이 앱은 WindowStyle=None 이라 제목 표시줄을 직접 그리므로,
저장된 위치가 지금 화면에 없으면(회사에서 두 번째 모니터, 집에서 노트북) 메뉴·저장·닫기가
전부 손에 닿지 않고 마우스로 되돌릴 방법이 없다.
기본 크기로는 이 문제가 안 나지만, 저장을 시작하는 순간 복원되는 것은 사용자가 만든 값이다.
닫기를 물렀을 때는 저장하지 않는다 — 조작하지 않은 값이 남는다.

게이트: 테스트 277/277, --dialog-shots 대조군 4/4 · 글자 2,465개 검사 · 넘침 0건,
--maxrect 0실패(MainView 실측 940x640 테두리 6), --cleartype 11/11,
--edit-smoke 0실패, --modal-check 0실패, 빌드 경고 0,
--db-smoke 1271건 diff 0, --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 동일.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Msystech
2026-08-14 16:50:24 +09:00
co-authored by Claude Opus 5
parent 862657cf2f
commit 4150ebe1d7
9 changed files with 270 additions and 17 deletions
@@ -120,6 +120,13 @@ public static class DialogShots
var designer = SampleDesigner();
return new List<(string, Func<Window>)>
{
// 메인 셸 — 이 게이트에 <b>아예 없었다</b>. 사용자가 하루 종일 보는 화면만 자동 검증 밖이었다.
// 두 크기로 찍는다: 기본 창(1440×920)과 현장 단말 최대화 크기(1920×1032).
// 현장이 1920×1080 이상뿐이라는 답을 받았으므로 그 사각형이 실제 기준이다.
("00-main-default", () => NewMainShell(1440, 920)),
("00b-main-1920", () => NewMainShell(1920, 1032)),
// 도구 상자 탭은 타일 라벨이 좁은 2열에 들어가므로 잘림이 가장 잘 나는 자리다
("00c-main-toolbox", () => NewMainShell(1440, 920, leftTab: 2)),
("01-sheet-open", () => new Views.SheetOpenDialogView(_ => SampleSheets())),
("02-sheet-history", () => new Views.SheetHistoryDialogView("S999", "표본 서식", SampleVersions())),
("03-query-editor", () => NewQueryEditor(designer,
@@ -203,6 +210,58 @@ public static class DialogShots
/// MainViewModel 을 통째로 만들면 DB 조회가 딸려 오므로, 패널이 읽는 <c>CurrentDesigner</c> 하나만
/// 들고 있는 최소 DataContext 를 세워 준다.
/// </summary>
/// <summary>
/// 메인 셸을 주어진 크기로 만든다.
///
/// Loaded 커맨드(서식 목록 DB 조회)는 <see cref="StartupArguments.DiagnosticMode"/> 때문에 돌지 않으므로
/// 접속 없이도 같은 결과가 나온다. 문서 한 장을 넣어 캔버스·레이어·인스펙터가 빈 상태가 아니게 한다 —
/// 빈 껍데기를 찍으면 잘림을 볼 수 없다.
/// </summary>
private static Window NewMainShell(double width, double height, int leftTab = 1)
{
var window = new Views.MainView
{
Width = width,
Height = height,
Left = -10000,
Top = -10000,
WindowStartupLocation = WindowStartupLocation.Manual,
};
if (window.DataContext is not MainViewModel shell)
{
return window;
}
shell.NewFileCommand?.Execute(null);
shell.SelectedLeftTabIndex = leftTab;
// 컨트롤을 놓고 하나를 고른다 — 이걸 안 하면 인스펙터가 비어 있고 레이어에 행이 없어서
// 검사할 글자가 31개밖에 안 나온다(빈 껍데기를 찍으면 잘림을 볼 수 없다).
// 이름이 긴 컨트롤을 섞는다 — 좁은 칸에서 잘리는 것은 짧은 이름이 아니라 긴 이름이다.
if (shell.CurrentDesigner is { } designer)
{
foreach (var type in new[] { "Label", "TextBox", "CheckBox", "MDataTable", "MPictureBox" })
{
designer.AddPaletteItemAtCenter(type);
}
foreach (var control in designer.Pages[0].Controls)
{
if (control.Type == "Label")
{
control.Model.Id = "아주긴이름을가진라벨컨트롤_LAB_00123";
control.Model.Props.SetText("Text",
"잘림을 보려면 충분히 긴 문구가 필요하다 — 간호·간병통합서비스 병동");
control.NotifyAllChanged();
break;
}
}
if (designer.Pages[0].Controls.FirstOrDefault() is { } first)
{
designer.Selection.SetSingle(first);
}
}
return window;
}
private static Window HostLayerPanel(DesignerViewModel designer, LayerShotMode mode)
{
designer.Selection.Clear();