페이지 속성 편집 — 레이어의 페이지 행을 고르면 속성 패널이 페이지를 연다

레거시에서 페이지는 MDesignerHost 라는 하나의 Object 이고 자기 속성을 갖는다.
SheetMe 도 그 루트 노드를 FormPage.Root 로 통째로 보존해 왔고(그래서 운영 1,271건 왕복
diff 가 0이다), 값도 일부는 이미 쓰고 있었다 — BackColor 는 용지 배경으로 렌더하고
Font 는 자식이 상속한다. 없던 것은 편집 화면뿐이었다.

그 결과 용지 크기조차 바꿀 수 없는 상태였다. ApplyPaperSize 는 구현돼 있었지만 호출처가
편집 스모크뿐이고 메뉴·XAML 어디에도 배선이 없었다 — 새 서식은 720×856 고정으로만 시작했다.

레이어 아웃라인의 페이지 헤더 행을 누르면 선택을 비우고 속성 패널이 페이지 모드로 바뀐다.
컨트롤을 하나라도 고르면 자동으로 빠져나온다.

  용지        너비·높이(한 줄), 배경색
  기본 글꼴    글꼴·크기 — 여기를 바꾸면 Font 를 명시하지 않은 컨트롤이 전부 따라온다
  전체 속성    나머지 원본 속성(레거시 PropertyGrid 등가)

저장 규약을 지켰다. writer 는 저장할 때 Size 를 Bounds 에서, Name 을 Id 에서 다시 만들어
덮으므로 그 두 키는 raw 편집 대상에서 뺐다 — 열어 두면 고쳐도 저장하면 되돌아간다.
크기는 raw Size 가 아니라 Bounds 를 고치고, 편집 결과가 저장 XML 의 Size 와 같은지
스모크로 못 박았다.

용지 크기가 바뀌면 페이지 스택 오프셋과 월드 크기를 다시 계산한다(여러 장이면 한 장의
높이 변화가 아래 페이지를 전부 밀어낸다). 기본 글꼴이 바뀌면 그 페이지 컨트롤의 상속
컨텍스트를 다시 흘린다.

편집 스모크에 페이지 속성 검사 11건 추가.
회귀: 테스트 124/124, 편집 스모크 실패 0, DB 왕복 1,271건 diff 0/예외 0,
종이 렌더 P062 바이트 동일.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Msystech
2026-08-13 10:23:49 +09:00
co-authored by Claude Opus 5
parent f5cce00019
commit 38093691ad
4 changed files with 285 additions and 6 deletions
@@ -479,6 +479,62 @@ public static class EditSmoke
badgeTarget.Model.Props.SetText("DataTableField", string.Empty);
}
// 20-2-1-2) 페이지 속성 — 레거시 MDesignerHost 루트가 갖는 속성을 편집한다
{
var pg = new DesignerViewModel(business.CreateNew());
pg.AddControlAt("Label", new Point(100, 100));
var pageRow = pg.LayerRows.OfType<LayerPageViewModel>().First();
pg.ActivatePage(pageRow.Page);
Check("페이지 속성: 페이지 모드 진입", pg.InspectedPage is not null && pg.Selection.Items.Count == 0);
Check("페이지 속성: 요약이 페이지를 가리킴", pg.Inspector.Summary.StartsWith("페이지 1"),
$"실제 {pg.Inspector.Summary}");
Check("페이지 속성: 행 생성", pg.Inspector.Rows.Count > 0, $"행 {pg.Inspector.Rows.Count}");
// 용지 크기 — raw Size 가 아니라 Bounds 를 고쳐야 저장 시 되돌아가지 않는다
var sizePair = pg.Inspector.Rows.OfType<ViewModels.Inspector.PairRowViewModel>().First();
((ViewModels.Inspector.NumberRowViewModel)sizePair.Left).ValueText = "794";
((ViewModels.Inspector.NumberRowViewModel)sizePair.Right).ValueText = "1123";
Check("페이지 속성: 용지 크기 편집(A4)",
pg.Pages[0].WidthDip == 794 && pg.Pages[0].HeightDip == 1123,
$"실제 {pg.Pages[0].WidthDip}×{pg.Pages[0].HeightDip}");
// 저장하면 writer 가 Bounds 로 Size 를 다시 쓴다 — 그 값이 편집 결과와 같아야 한다
var pageXml = serializer.Write(pg.Document);
Check("페이지 속성: 저장 XML 의 Size 가 편집값", pageXml.Contains("794, 1123"),
"Size 가 Bounds 와 어긋남");
// 배경색
var colorRow = pg.Inspector.Rows.OfType<ViewModels.Inspector.ColorRowViewModel>()
.FirstOrDefault(r => r.Label == "배경색");
Check("페이지 속성: 배경색 행 존재", colorRow is not null);
if (colorRow is not null)
{
colorRow.ValueText = "Silver";
Check("페이지 속성: 배경색 편집 → 루트 반영",
pg.Pages[0].Model.Root.Props.GetText("BackColor") == "Silver");
}
// 기본 글꼴 — 명시 Font 가 없는 컨트롤이 상속한다
var fontRow = pg.Inspector.Rows.OfType<ViewModels.Inspector.TextRowViewModel>()
.FirstOrDefault(r => r.Label == "글꼴");
Check("페이지 속성: 기본 글꼴 행 존재", fontRow is not null);
if (fontRow is not null)
{
fontRow.ValueText = "돋움";
Check("페이지 속성: 기본 글꼴이 루트에 기록",
(pg.Pages[0].Model.Root.Props.GetText("Font") ?? string.Empty).StartsWith("돋움"),
$"실제 {pg.Pages[0].Model.Root.Props.GetText("Font")}");
}
Check("페이지 속성: 편집이 되돌리기 스텝", pg.Undo.CanUndo);
// 컨트롤을 고르면 페이지 모드에서 빠진다
pg.Selection.SetSingle(pg.Pages[0].Controls[0]);
Check("페이지 속성: 컨트롤 선택 시 해제",
pg.InspectedPage is null && !pg.Inspector.Summary.StartsWith("페이지"));
}
// 20-2-2) 알림이 무인 실행을 멈추지 않는다 — 진단 모드에서는 창을 만들지 않고 즉시
// 기각 기본값을 돌려줘야 한다. 이 규약이 깨지면 여기서 영원히 대기한다.
Check("알림: 진단 모드에서 창 없이 반환", Services.UserSession.IsDiagnostic);