From 6ee4435575a8e7439ab72d8ddecbd25907223a35 Mon Sep 17 00:00:00 2001 From: Msystech Date: Fri, 14 Aug 2026 11:33:57 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A2=8C=EC=B8=A1=20=ED=8C=A8=EB=84=90=20?= =?UTF-8?q?=E2=80=94=20=ED=8E=98=EC=9D=B4=EC=A7=80=EC=99=80=20=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=96=B4=EB=A5=BC=20=EB=91=90=20=EA=B5=AC=ED=9A=8D?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EA=B0=80=EB=A5=B8=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 레이어 탭 하나에 페이지 마디와 컨트롤이 한 시퀀스로 섞여 있었다. 페이지를 추가·복제·삭제하는 조작이 컨트롤을 눈으로 찾는 일과 같은 목록에서 경쟁했다. 위는 페이지, 아래는 레이어로 나눈다. 페이지 행을 누르면 그 페이지를 활성화한다 — 캔버스가 거기로 스크롤하고 인스펙터가 용지 속성을 연다. 경로는 이미 있던 ActivatePage 그대로다. 강조는 ListBox 의 IsSelected 가 아니라 IsCurrent 가 그린다 (레이어 행이 Highlight 3상태로 그리는 것과 같은 규율 — 두 강조가 겹치면 어느 쪽이 진짜인지 모른다). 트리는 그 페이지로 좁히지 않는다. 세 가지가 거기 걸려 있다: 레이어 검색이 문서 전체를 훑는 성질, 그룹 강조가 페이지를 넘나드는 멤버까지 집계해야 폴더가 파래지는 것, 그리고 캔버스가 전 페이지를 세로로 이어 그리므로 트리만 한 장으로 좁으면 두 뷰의 1:1 대응이 깨진다는 것. 좁히고 싶으면 페이지 접기가 이미 있고 그건 명시적이다. 트리의 페이지 마디는 장수로 갈린다. · 한 장이면 아예 없앤다 — 모든 컨트롤이 그 페이지 소속이라 정보가 0 이고, 최상위가 들여쓰기 없이 바로 보인다. 실사용 문서 대부분이 여기다. · 두 장 이상이면 남기되 경계 구분자로 줄인다(높이 20, 회색, 개수·복제·삭제 없음). 통째로 빼면 안 되는 이유가 있다 — 페이지 행이 항상 무강조라서 연속 선택 블록이 페이지 경계에서 저절로 끊기는데, 빼면 앞 페이지 마지막 컨트롤과 뒷 페이지 첫 컨트롤이 하나의 파란 띠로 붙는다. 들여쓰기 상수를 계산값으로 바꿨다. 페이지 마디가 없으면 들여쓸 이유도 없다 — 페이지 직속 12→0, 그룹 멤버 32→20. 트리 맨 아래 '페이지 추가' 행은 없앴다. 페이지 구획 머리의 + 가 그 자리다. 목록 안에 조작 행이 섞여 있으면 스크롤 끝까지 가야 눌 수 있다. 페이지 목록은 5행까지 보이고 그 뒤로는 목록 안에서만 스크롤한다 — 7장짜리 문서에서도 레이어 트리가 밀려나지 않는다. 트리는 남은 영역을 그대로 차지해 가상화를 유지한다. 이름 변경과 순서 변경은 넣지 않았다. FormPage 에 이름 필드가 없고 유일한 식별자인 Root.Id 는 E_SctMst 사전 매핑에 물려 있어 개명이 위험하다. 페이지 이동 API 도 없다(Pages 조작은 통째 재생성뿐). 표시 전용 이름을 새로 만들면 레거시 XML 에 담을 곳이 없어 왕복 diff 0 불변식과 충돌한다. 새 스타일 3종(SectionHead / SectionHeadText / PageRowItem). 구획 머리의 아래 1px 선은 필수다 — 라이트에서 B.PanelHeader(#FAFAFA)와 B.Panel(#FFFFFF)이 1.02:1 이라 배경만으로는 경계가 안 보인다. 게이트: 테스트 267/267, --edit-smoke 236건 0실패(레이어 단언 5건 갱신), --query-popup 17/17, --maxrect 10/10, --db-smoke 3000 diff 0·예외 0, --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 동일, --dialog-shots 57파일. Co-Authored-By: Claude Opus 5 --- src/SheetMe.Designer/Diagnostics/EditSmoke.cs | 18 +-- .../Themes/DesignerTheme.xaml | 49 +++++++++ .../ViewModels/DesignerViewModel.cs | 24 +++- .../Views/LayerPanelView.xaml | 103 +++++++++++++----- .../Views/LayerPanelView.xaml.cs | 25 ++++- 5 files changed, 177 insertions(+), 42 deletions(-) diff --git a/src/SheetMe.Designer/Diagnostics/EditSmoke.cs b/src/SheetMe.Designer/Diagnostics/EditSmoke.cs index 05840ed..a6ab162 100644 --- a/src/SheetMe.Designer/Diagnostics/EditSmoke.cs +++ b/src/SheetMe.Designer/Diagnostics/EditSmoke.cs @@ -285,10 +285,14 @@ public static class EditSmoke $"실제 {groupRow?.Members.Count} / {groupRow?.Name}"); // 아웃라인은 페이지 헤더로 시작하고 '페이지 추가' 행으로 끝난다 - Check("레이어: 첫 행은 페이지 헤더", lay.LayerRows.FirstOrDefault() is LayerPageViewModel); - Check("레이어: 마지막 행은 페이지 추가", lay.LayerRows.LastOrDefault() is LayerAddPageViewModel); + // 페이지는 별도 구획으로 나갔다 — 한 장짜리 문서의 트리에는 페이지 마디가 없다 + Check("레이어: 페이지 구획이 페이지를 담는다", + lay.PageRows.Count == lay.Pages.Count && lay.PageRows.Count == 1); + Check("레이어: 한 장이면 트리에 페이지 마디가 없다", + !lay.ShowPageNodes && !lay.LayerRows.OfType().Any()); + Check("레이어: 첫 행이 곧 컨트롤·그룹이다", lay.LayerRows.FirstOrDefault() is not LayerPageViewModel); Check("레이어: 페이지 헤더는 선택 대상 아님", - lay.LayerRows.OfType().Where(r => r is LayerPageViewModel or LayerAddPageViewModel) + lay.LayerRows.OfType().Where(r => r is LayerPageViewModel) .All(r => !r.IsSelectableRow)); // 폴더 바로 뒤에 멤버가 들여쓰기된 채 이어져야 한다(평탄화 시퀀스) @@ -296,11 +300,11 @@ public static class EditSmoke Check("레이어: 폴더 뒤에 멤버가 들여쓰여 이어짐", folderIndex >= 0 && lay.LayerRows.Skip(folderIndex + 1).Take(2) - .OfType().Count(c => c.LayerIndent == 32) == 2); - Check("레이어: 페이지 직속 컨트롤 들여쓰기 12", + .OfType().Count(c => c.LayerIndent == 20) == 2); + Check("레이어: 한 장이면 최상위 들여쓰기가 0", lay.LayerRows.OfType() .Where(c => c.Model.GroupId is null && c.Parent is null) - .All(c => c.LayerIndent == 12)); + .All(c => c.LayerIndent == 0)); // 목록 맨 위 = z-order 최상위 (모델 리스트 index 0) var topControl = lay.LayerRows.OfType().First(); @@ -493,7 +497,7 @@ public static class EditSmoke { var pg = new DesignerViewModel(business.CreateNew()); pg.AddControlAt("Label", new Point(100, 100)); - var pageRow = pg.LayerRows.OfType().First(); + var pageRow = pg.PageRows[0]; pg.ActivatePage(pageRow.Page); Check("페이지 속성: 페이지 모드 진입", pg.InspectedPage is not null && pg.Selection.Items.Count == 0); diff --git a/src/SheetMe.Designer/Themes/DesignerTheme.xaml b/src/SheetMe.Designer/Themes/DesignerTheme.xaml index 675085c..e7dc05a 100644 --- a/src/SheetMe.Designer/Themes/DesignerTheme.xaml +++ b/src/SheetMe.Designer/Themes/DesignerTheme.xaml @@ -993,6 +993,55 @@ + + + + + + + + - -