좌측 패널 — 페이지와 레이어를 두 구획으로 가른다

레이어 탭 하나에 페이지 마디와 컨트롤이 한 시퀀스로 섞여 있었다. 페이지를 추가·복제·삭제하는
조작이 컨트롤을 눈으로 찾는 일과 같은 목록에서 경쟁했다. 위는 페이지, 아래는 레이어로 나눈다.

페이지 행을 누르면 그 페이지를 활성화한다 — 캔버스가 거기로 스크롤하고 인스펙터가 용지 속성을 연다.
경로는 이미 있던 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 <noreply@anthropic.com>
This commit is contained in:
Msystech
2026-08-14 11:33:57 +09:00
co-authored by Claude Opus 5
parent e82d520de6
commit 6ee4435575
5 changed files with 177 additions and 42 deletions
@@ -993,6 +993,55 @@
<Setter Property="CornerRadius" Value="8" />
<Setter Property="Padding" Value="12" />
</Style>
<!--
구획 머리 — 좌측 패널을 페이지/레이어로 가르는 띠.
아래 1px 선이 필수다: 라이트에서 B.PanelHeader(#FAFAFA)와 B.Panel(#FFFFFF)이 1.02:1 이라
배경색만으로는 구획 경계가 보이지 않는다.
-->
<Style x:Key="SectionHead" TargetType="Border">
<Setter Property="Background" Value="{DynamicResource B.PanelHeader}" />
<Setter Property="BorderBrush" Value="{DynamicResource B.Line}" />
<Setter Property="BorderThickness" Value="0,0,0,1" />
<Setter Property="Padding" Value="10,5,6,5" />
<Setter Property="MinHeight" Value="30" />
</Style>
<Style x:Key="SectionHeadText" TargetType="TextBlock">
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Foreground" Value="{DynamicResource B.Ink}" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
</Style>
<!--
페이지 행 — 강조는 IsSelected 가 아니라 IsCurrent 가 그린다.
암시 ListBoxItem 의 선택 배경을 꺼야 두 강조가 겹쳐 보이지 않는다(레이어 행과 같은 규율).
-->
<Style x:Key="PageRowItem" TargetType="ListBoxItem">
<Setter Property="Padding" Value="4,2" />
<Setter Property="Margin" Value="2,1" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="bd" Background="Transparent" CornerRadius="5"
Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="bd" Property="Background" Value="{DynamicResource B.Hover}" />
</Trigger>
<DataTrigger Binding="{Binding IsCurrent}" Value="True">
<Setter TargetName="bd" Property="Background" Value="{DynamicResource B.LayerSubtree}" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="PanelHeader" TargetType="Border">
<Setter Property="Background" Value="{DynamicResource B.Surface}" />
<Setter Property="BorderBrush" Value="{DynamicResource B.Line}" />