재설계 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<string,bool> 이라 숫자를 못 담던 것이 원인이었다. 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>
751 lines
59 KiB
XML
751 lines
59 KiB
XML
<Window x:Class="SheetMe.Designer.Views.MainView"
|
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
xmlns:shell="clr-namespace:System.Windows.Shell;assembly=PresentationFramework"
|
|
xmlns:vm="clr-namespace:SheetMe.Designer.ViewModels"
|
|
xmlns:v="clr-namespace:SheetMe.Designer.Views"
|
|
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
|
|
xmlns:bh="clr-namespace:SheetMe.Designer.Behaviors"
|
|
xmlns:ctl="clr-namespace:SheetMe.Designer.Controls"
|
|
mc:Ignorable="d"
|
|
d:DataContext="{d:DesignInstance vm:MainViewModel}"
|
|
Title="{Binding Title}"
|
|
Icon="pack://application:,,,/SheetMe.Designer;component/Assets/sheetme.ico"
|
|
Width="1440" Height="920" MinWidth="940" MinHeight="640"
|
|
WindowStyle="None" WindowStartupLocation="CenterScreen"
|
|
Background="{DynamicResource B.AppBg}" FontFamily="Malgun Gothic" FontSize="13"
|
|
Loaded="OnWindowLoaded" StateChanged="OnWindowStateChanged" Closing="OnWindowClosing"
|
|
Style="{StaticResource ThemedWindow}">
|
|
|
|
<!--
|
|
파일/앱 계열만 창 단위로 바인딩한다. 편집 계열(Ctrl+Z/C/V/X/D/A/G)은 CanvasKeyboardBehavior 가
|
|
처리하며, 여기 올리면 인스펙터·검색 상자 등 TextBox 의 표준 편집 키와 충돌한다.
|
|
-->
|
|
<Window.InputBindings>
|
|
<KeyBinding Key="N" Modifiers="Control" Command="{Binding NewFileCommand}"/>
|
|
<KeyBinding Key="O" Modifiers="Control" Command="{Binding OpenFileCommand}"/>
|
|
<KeyBinding Key="S" Modifiers="Control" Command="{Binding SaveFileCommand}"/>
|
|
<KeyBinding Key="S" Modifiers="Control+Shift" Command="{Binding SaveAsFileCommand}"/>
|
|
<KeyBinding Key="P" Modifiers="Control" Command="{Binding PrintCommand}"/>
|
|
<KeyBinding Key="W" Modifiers="Control" Command="{Binding CloseDocumentCommand}"/>
|
|
</Window.InputBindings>
|
|
|
|
<!-- GlassFrameThickness 0,0,0,1: DWM 창 그림자 활성화([200]SheetMe 크롬과 동일) -->
|
|
<shell:WindowChrome.WindowChrome>
|
|
<shell:WindowChrome CaptionHeight="40" ResizeBorderThickness="6" GlassFrameThickness="0,0,0,1"
|
|
CornerRadius="0" UseAeroCaptionButtons="False"/>
|
|
</shell:WindowChrome.WindowChrome>
|
|
|
|
<Window.DataContext>
|
|
<vm:MainViewModel/>
|
|
</Window.DataContext>
|
|
|
|
<Window.Resources>
|
|
<ctl:TypeToIconConverter x:Key="TypeToIcon"/>
|
|
<ctl:TypeToCategoryConverter x:Key="TypeToCategory"/>
|
|
<ctl:IconNameToVisualConverter x:Key="IconName"/>
|
|
<ctl:IconSpecConverter x:Key="IconSpec"/>
|
|
<ctl:InverseBoolConverter x:Key="InverseBool"/>
|
|
<BooleanToVisibilityConverter x:Key="BoolToVisibility"/>
|
|
|
|
<vm:SheetClassToGroupConverter x:Key="SheetClassToGroup"/>
|
|
|
|
<!--
|
|
서식 목록 — 분류(E_ShtMst.ShtClsCod) 그룹 뷰.
|
|
SortDescriptions 를 두지 않는 것이 의도다: 그룹 순서는 SQL 의 ORDER BY(분류코드 A~X, 미분류 뒤)가
|
|
정하고 CollectionView 는 등장 순서대로 그룹을 만든다. 여기서 다시 정렬하면 그 의도가 덮인다.
|
|
-->
|
|
<CollectionViewSource x:Key="SheetsGrouped" Source="{Binding SheetList}">
|
|
<CollectionViewSource.GroupDescriptions>
|
|
<PropertyGroupDescription PropertyName="ClassCode" Converter="{StaticResource SheetClassToGroup}"/>
|
|
</CollectionViewSource.GroupDescriptions>
|
|
</CollectionViewSource>
|
|
|
|
<!-- 팔레트(도구 상자/플라이아웃 공용) — 카테고리 그룹 뷰 -->
|
|
<CollectionViewSource x:Key="PaletteGrouped" Source="{Binding PaletteItems}">
|
|
<CollectionViewSource.GroupDescriptions>
|
|
<PropertyGroupDescription PropertyName="Type" Converter="{StaticResource TypeToCategory}"/>
|
|
</CollectionViewSource.GroupDescriptions>
|
|
</CollectionViewSource>
|
|
|
|
<!-- 도구 상자 타일 카드([200] 컴포넌트 카드 룩) — 선택 하이라이트 없음 -->
|
|
<Style x:Key="PaletteTile" TargetType="ListBoxItem">
|
|
<Setter Property="Cursor" Value="Hand"/>
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="ListBoxItem">
|
|
<Border x:Name="bd" Background="{DynamicResource B.Surface}" BorderBrush="{DynamicResource B.Line}"
|
|
BorderThickness="1" CornerRadius="5" Margin="3" SnapsToDevicePixels="True">
|
|
<ContentPresenter/>
|
|
</Border>
|
|
<ControlTemplate.Triggers>
|
|
<Trigger Property="IsMouseOver" Value="True">
|
|
<Setter TargetName="bd" Property="Background" Value="{DynamicResource B.Hover}"/>
|
|
<Setter TargetName="bd" Property="BorderBrush" Value="{DynamicResource B.Line2}"/>
|
|
</Trigger>
|
|
</ControlTemplate.Triggers>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
<!-- 팔레트 카테고리 그룹 헤더 -->
|
|
<Style x:Key="PaletteGroupHeader" TargetType="TextBlock">
|
|
<Setter Property="FontSize" Value="10.5"/>
|
|
<Setter Property="FontWeight" Value="Bold"/>
|
|
<Setter Property="Foreground" Value="{DynamicResource B.Muted}"/>
|
|
<Setter Property="Margin" Value="5,9,0,4"/>
|
|
</Style>
|
|
|
|
<!-- 플라이아웃/줌 팝업 행 버튼 — 왼정렬 hover 행 -->
|
|
<Style x:Key="FlyoutRow" TargetType="Button">
|
|
<Setter Property="Background" Value="Transparent"/>
|
|
<Setter Property="Foreground" Value="{DynamicResource B.Ink}"/>
|
|
<Setter Property="Cursor" Value="Hand"/>
|
|
<Setter Property="Padding" Value="12,7"/>
|
|
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="Button">
|
|
<Border x:Name="bd" Background="{TemplateBinding Background}" CornerRadius="6"
|
|
Padding="{TemplateBinding Padding}">
|
|
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
|
VerticalAlignment="Center"/>
|
|
</Border>
|
|
<ControlTemplate.Triggers>
|
|
<Trigger Property="IsMouseOver" Value="True">
|
|
<Setter TargetName="bd" Property="Background" Value="{DynamicResource B.Hover}"/>
|
|
</Trigger>
|
|
</ControlTemplate.Triggers>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
</Window.Resources>
|
|
|
|
<DockPanel>
|
|
<!-- ===== 커스텀 타이틀바: 로고 + 메뉴 | 중앙 제목 | 창 제어 ===== -->
|
|
<Border DockPanel.Dock="Top" Background="{DynamicResource B.Titlebar}" Height="40"
|
|
BorderBrush="{DynamicResource B.Line}" BorderThickness="0,0,0,1">
|
|
<Grid>
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="Auto"/>
|
|
<ColumnDefinition Width="*"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
</Grid.ColumnDefinitions>
|
|
|
|
<!-- 좌: 로고 메뉴 루트 + 편집 아이콘 스트립 ([200] 타이틀바 구성) -->
|
|
<StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center" Margin="8,0,0,0"
|
|
shell:WindowChrome.IsHitTestVisibleInChrome="True">
|
|
<!-- 5개 텍스트 메뉴를 로고 하나 아래로 접어 넣는다 — 타이틀바가 아이콘 스트립 자리를 확보한다 -->
|
|
<Menu VerticalAlignment="Center">
|
|
<MenuItem>
|
|
<MenuItem.Header>
|
|
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
|
<Image Source="pack://application:,,,/SheetMe.Designer;component/Assets/sheetme-logo.png"
|
|
Width="20" Height="20" VerticalAlignment="Center" RenderOptions.BitmapScalingMode="HighQuality"/>
|
|
<ContentControl Margin="3,1,0,0" VerticalAlignment="Center" IsTabStop="False"
|
|
Content="{Binding Source=chevron-down, Converter={StaticResource IconName}, ConverterParameter=11}"/>
|
|
</StackPanel>
|
|
</MenuItem.Header>
|
|
<MenuItem Header="파일(_F)">
|
|
<MenuItem Header="새 서식(_N)" Command="{Binding NewFileCommand}" InputGestureText="Ctrl+N"/>
|
|
<MenuItem Header="열기(_O)..." Command="{Binding OpenFileCommand}" InputGestureText="Ctrl+O"/>
|
|
<Separator/>
|
|
<MenuItem Header="저장(_S)" Command="{Binding SaveFileCommand}" InputGestureText="Ctrl+S"/>
|
|
<MenuItem Header="다른 이름으로 저장(_A)..." Command="{Binding SaveAsFileCommand}" InputGestureText="Ctrl+Shift+S"/>
|
|
<Separator/>
|
|
<MenuItem Header="DB에서 열기(_D)..." Command="{Binding OpenFromDbCommand}"/>
|
|
<MenuItem Header="DB에 저장(_B)..." Command="{Binding SaveToDbCommand}"/>
|
|
<Separator/>
|
|
<MenuItem Header="JSON 가져오기(_I)..." Command="{Binding ImportJsonCommand}"/>
|
|
<MenuItem Header="JSON 내보내기(_E)..." Command="{Binding ExportJsonCommand}"/>
|
|
<Separator/>
|
|
<MenuItem Header="미리보기(_V)..." Command="{Binding PreviewCommand}"/>
|
|
<MenuItem Header="인쇄(_P)..." Command="{Binding PrintCommand}" InputGestureText="Ctrl+P"/>
|
|
<Separator/>
|
|
<MenuItem Header="종료(_X)" Command="{Binding ExitCommand}"/>
|
|
</MenuItem>
|
|
<MenuItem Header="편집(_E)">
|
|
<MenuItem Header="실행 취소(_U)" Command="{Binding CurrentDesigner.UndoCommand}" InputGestureText="Ctrl+Z"/>
|
|
<MenuItem Header="다시 실행(_R)" Command="{Binding CurrentDesigner.RedoCommand}" InputGestureText="Ctrl+Y"/>
|
|
<Separator/>
|
|
<MenuItem Header="잘라내기(_T)" Command="{Binding CurrentDesigner.CutCommand}" InputGestureText="Ctrl+X"/>
|
|
<MenuItem Header="복사(_C)" Command="{Binding CurrentDesigner.CopyCommand}" InputGestureText="Ctrl+C"/>
|
|
<MenuItem Header="붙여넣기(_P)" Command="{Binding CurrentDesigner.PasteCommand}" InputGestureText="Ctrl+V"/>
|
|
<MenuItem Header="복제(_D)" Command="{Binding CurrentDesigner.DuplicateCommand}" InputGestureText="Ctrl+D"/>
|
|
<MenuItem Header="삭제(_L)" Command="{Binding CurrentDesigner.DeleteCommand}" InputGestureText="Del"/>
|
|
<Separator/>
|
|
<MenuItem Header="전체 선택(_A)" Command="{Binding CurrentDesigner.SelectAllCommand}" InputGestureText="Ctrl+A"/>
|
|
</MenuItem>
|
|
<MenuItem Header="배치(_A)">
|
|
<MenuItem Header="맨 앞으로(_F)" Command="{Binding CurrentDesigner.BringToFrontCommand}"/>
|
|
<MenuItem Header="맨 뒤로(_B)" Command="{Binding CurrentDesigner.SendToBackCommand}"/>
|
|
<Separator/>
|
|
<MenuItem Header="그룹(_G)" Command="{Binding CurrentDesigner.GroupCommand}" InputGestureText="Ctrl+G"/>
|
|
<MenuItem Header="그룹 해제(_U)" Command="{Binding CurrentDesigner.UngroupCommand}" InputGestureText="Ctrl+Shift+G"/>
|
|
<Separator/>
|
|
<!-- 기준: 선택 1개면 페이지(컨테이너 안이면 그 컨테이너), 2개 이상이면 선택 영역 -->
|
|
<MenuItem Header="왼쪽 맞춤" Command="{Binding CurrentDesigner.AlignCommand}" CommandParameter="Left"
|
|
ToolTip="선택 1개면 페이지(또는 부모 컨테이너) 기준, 2개 이상이면 선택 영역 기준"/>
|
|
<MenuItem Header="오른쪽 맞춤" Command="{Binding CurrentDesigner.AlignCommand}" CommandParameter="Right"
|
|
ToolTip="선택 1개면 페이지(또는 부모 컨테이너) 기준, 2개 이상이면 선택 영역 기준"/>
|
|
<MenuItem Header="위 맞춤" Command="{Binding CurrentDesigner.AlignCommand}" CommandParameter="Top"
|
|
ToolTip="여러 페이지에 걸친 선택에서는 동작하지 않습니다"/>
|
|
<MenuItem Header="아래 맞춤" Command="{Binding CurrentDesigner.AlignCommand}" CommandParameter="Bottom"
|
|
ToolTip="여러 페이지에 걸친 선택에서는 동작하지 않습니다"/>
|
|
<MenuItem Header="가로 가운데" Command="{Binding CurrentDesigner.AlignCommand}" CommandParameter="CenterH"
|
|
ToolTip="선택 1개면 페이지(또는 부모 컨테이너) 기준, 2개 이상이면 선택 영역 기준"/>
|
|
<MenuItem Header="세로 가운데" Command="{Binding CurrentDesigner.AlignCommand}" CommandParameter="CenterV"
|
|
ToolTip="여러 페이지에 걸친 선택에서는 동작하지 않습니다"/>
|
|
<Separator/>
|
|
<MenuItem Header="같은 크기로">
|
|
<MenuItem Header="너비/높이 모두(_B)" Command="{Binding CurrentDesigner.SizeToControlCommand}" CommandParameter="Both"/>
|
|
<MenuItem Header="너비(_W)" Command="{Binding CurrentDesigner.SizeToControlCommand}" CommandParameter="Width"/>
|
|
<MenuItem Header="높이(_H)" Command="{Binding CurrentDesigner.SizeToControlCommand}" CommandParameter="Height"/>
|
|
</MenuItem>
|
|
<MenuItem Header="가로 간격">
|
|
<MenuItem Header="균등(_E)" Command="{Binding CurrentDesigner.SpacingCommand}" CommandParameter="HorizEqual"/>
|
|
<MenuItem Header="넓게(_I)" Command="{Binding CurrentDesigner.SpacingCommand}" CommandParameter="HorizIncrease"/>
|
|
<MenuItem Header="좁게(_D)" Command="{Binding CurrentDesigner.SpacingCommand}" CommandParameter="HorizDecrease"/>
|
|
<MenuItem Header="붙이기(_C)" Command="{Binding CurrentDesigner.SpacingCommand}" CommandParameter="HorizConcat"/>
|
|
</MenuItem>
|
|
<MenuItem Header="세로 간격">
|
|
<MenuItem Header="균등(_E)" Command="{Binding CurrentDesigner.SpacingCommand}" CommandParameter="VertEqual"/>
|
|
<MenuItem Header="넓게(_I)" Command="{Binding CurrentDesigner.SpacingCommand}" CommandParameter="VertIncrease"/>
|
|
<MenuItem Header="좁게(_D)" Command="{Binding CurrentDesigner.SpacingCommand}" CommandParameter="VertDecrease"/>
|
|
<MenuItem Header="붙이기(_C)" Command="{Binding CurrentDesigner.SpacingCommand}" CommandParameter="VertConcat"/>
|
|
</MenuItem>
|
|
<Separator/>
|
|
<MenuItem Header="페이지 가로 가운데 — 묶음째(_H)"
|
|
ToolTip="상대 배치를 유지한 채 선택 전체를 페이지 가운데로 옮깁니다" Command="{Binding CurrentDesigner.CenterInPageCommand}" CommandParameter="H"/>
|
|
<MenuItem Header="페이지 세로 가운데 — 묶음째(_V)"
|
|
ToolTip="상대 배치를 유지한 채 선택 전체를 페이지 가운데로 옮깁니다" Command="{Binding CurrentDesigner.CenterInPageCommand}" CommandParameter="V"/>
|
|
<Separator/>
|
|
<MenuItem Header="{Binding CurrentDesigner.TabOrderMenuHeader, FallbackValue=탭순서 편집 시작}"
|
|
Command="{Binding CurrentDesigner.TabOrderCommand}"
|
|
IsChecked="{Binding CurrentDesigner.IsTabOrderMode, Mode=OneWay}"
|
|
ToolTip="입력 컨트롤을 원하는 입력 순서대로 클릭한 뒤 완료 — Esc 취소"/>
|
|
</MenuItem>
|
|
<MenuItem Header="보기(_V)">
|
|
<MenuItem Header="확대(_I)" Command="{Binding ZoomInCommand}" InputGestureText="Ctrl+휠↑"/>
|
|
<MenuItem Header="축소(_O)" Command="{Binding ZoomOutCommand}" InputGestureText="Ctrl+휠↓"/>
|
|
<MenuItem Header="100%(_R)" Command="{Binding ZoomResetCommand}"/>
|
|
<Separator/>
|
|
<MenuItem x:Name="ThemeMenuItem" Header="다크 테마(_D)" IsCheckable="True" Click="OnThemeToggleClick"/>
|
|
</MenuItem>
|
|
<MenuItem Header="도구(_T)">
|
|
<MenuItem Header="서식 수정이력(_H)..." Command="{Binding SheetHistoryCommand}"/>
|
|
<Separator/>
|
|
<MenuItem Header="상용구 관리(_W)..." Command="{Binding RecordWordCommand}"/>
|
|
<MenuItem Header="폰트 일괄 변경(_F)..." Command="{Binding FontManagerCommand}"/>
|
|
</MenuItem>
|
|
</MenuItem>
|
|
</Menu>
|
|
|
|
<Border Width="1" Height="18" Background="{DynamicResource B.Line2}" Margin="6,0" VerticalAlignment="Center"/>
|
|
|
|
<!-- 편집 아이콘 스트립 — 메뉴 하위에만 있던 명령을 한 번에 닿게 -->
|
|
<Button Style="{StaticResource Subtle}" Width="30" Height="28" Padding="0" ToolTip="실행 취소 (Ctrl+Z)"
|
|
Command="{Binding CurrentDesigner.UndoCommand}"
|
|
Content="{Binding Source=undo-2, Converter={StaticResource IconName}, ConverterParameter=16}"/>
|
|
<Button Style="{StaticResource Subtle}" Width="30" Height="28" Padding="0" ToolTip="다시 실행 (Ctrl+Y)"
|
|
Command="{Binding CurrentDesigner.RedoCommand}"
|
|
Content="{Binding Source=redo-2, Converter={StaticResource IconName}, ConverterParameter=16}"/>
|
|
<Border Width="1" Height="18" Background="{DynamicResource B.Line2}" Margin="6,0" VerticalAlignment="Center"/>
|
|
<Button Style="{StaticResource Subtle}" Width="30" Height="28" Padding="0" ToolTip="복사 (Ctrl+C)"
|
|
Command="{Binding CurrentDesigner.CopyCommand}"
|
|
Content="{Binding Source=copy, Converter={StaticResource IconName}, ConverterParameter=16}"/>
|
|
<Button Style="{StaticResource Subtle}" Width="30" Height="28" Padding="0" ToolTip="삭제 (Delete)"
|
|
Command="{Binding CurrentDesigner.DeleteCommand}"
|
|
Content="{Binding Source=trash-2, Converter={StaticResource IconName}, ConverterParameter=16}"/>
|
|
<Button Style="{StaticResource Subtle}" Width="30" Height="28" Padding="0" ToolTip="그룹 (Ctrl+G)"
|
|
Command="{Binding CurrentDesigner.GroupCommand}"
|
|
Content="{Binding Source=group, Converter={StaticResource IconName}, ConverterParameter=16}"/>
|
|
<Button Style="{StaticResource Subtle}" Width="30" Height="28" Padding="0" ToolTip="그룹 해제 (Ctrl+Shift+G)"
|
|
Command="{Binding CurrentDesigner.UngroupCommand}"
|
|
Content="{Binding Source=ungroup, Converter={StaticResource IconName}, ConverterParameter=16}"/>
|
|
</StackPanel>
|
|
|
|
<!-- 중앙: 비움 — 서식명은 문서 탭이 이미 보여준다(Window.Title 은 작업표시줄용으로 유지) -->
|
|
<Border Grid.Column="1"/>
|
|
|
|
<!-- 우: 액션 아이콘 -->
|
|
<StackPanel Grid.Column="2" Orientation="Horizontal" VerticalAlignment="Center" Margin="0,0,8,0"
|
|
shell:WindowChrome.IsHitTestVisibleInChrome="True">
|
|
<Button Style="{StaticResource Subtle}" Width="34" Height="28" Padding="0" ToolTip="다크/라이트 전환"
|
|
Click="OnThemeToggleClick"
|
|
Content="{Binding Source=sun, Converter={StaticResource IconName}, ConverterParameter=16}"/>
|
|
<Button Style="{StaticResource Subtle}" Width="34" Height="28" Padding="0" ToolTip="DB에 저장"
|
|
Command="{Binding SaveToDbCommand}"
|
|
Content="{Binding Source=save, Converter={StaticResource IconName}, ConverterParameter=16}"/>
|
|
<Button Style="{StaticResource Subtle}" Width="34" Height="28" Padding="0" ToolTip="미리보기"
|
|
Command="{Binding PreviewCommand}"
|
|
Content="{Binding Source=play, Converter={StaticResource IconName}, ConverterParameter=16|B.Accent}"/>
|
|
</StackPanel>
|
|
|
|
<!-- 우: 창 제어 -->
|
|
<StackPanel Grid.Column="3" Orientation="Horizontal" shell:WindowChrome.IsHitTestVisibleInChrome="True">
|
|
<Button Style="{StaticResource CaptionBtn}" Click="OnMinimizeClick" ToolTip="최소화">
|
|
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="10"/>
|
|
</Button>
|
|
<Button Style="{StaticResource CaptionBtn}" Click="OnMaxRestoreClick" ToolTip="최대화/복원">
|
|
<TextBlock x:Name="MaxGlyph" Text="" FontFamily="Segoe MDL2 Assets" FontSize="10"/>
|
|
</Button>
|
|
<Button Style="{StaticResource CloseBtn}" Click="OnCloseWinClick" ToolTip="닫기">
|
|
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="10"/>
|
|
</Button>
|
|
</StackPanel>
|
|
</Grid>
|
|
</Border>
|
|
|
|
<!-- ===== 하단 상태바 (줌은 플로팅 바로 이동) ===== -->
|
|
<Border DockPanel.Dock="Bottom" Background="{DynamicResource B.Titlebar}"
|
|
BorderBrush="{DynamicResource B.Line}" BorderThickness="0,1,0,0" Padding="14,5">
|
|
<TextBlock Text="{Binding StatusText}" Foreground="{DynamicResource B.Muted}" FontSize="11.5"
|
|
TextTrimming="CharacterEllipsis"/>
|
|
</Border>
|
|
|
|
<!-- ===== 본문 3열: 좌 탭 패널 | 문서 탭+캔버스+플로팅 바 | 속성 ([200] 레이아웃) ===== -->
|
|
<Grid>
|
|
<Grid.ColumnDefinitions>
|
|
<!-- [200] 기본 폭 — 좌 248(레이어 행에 타입 아이콘 + 토글 2개가 들어가 232 로는 이름이 잘린다),
|
|
우 300(인스펙터 X|Y 쌍이 한 줄에 들어가는 최소치) -->
|
|
<ColumnDefinition x:Name="LeftColumn" Width="248" MinWidth="180" MaxWidth="480"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
<ColumnDefinition Width="*"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
<!-- 최소 250 — 글꼴 스타일 행이 라벨 92 + 토글 4칸 128 = 220px 를 요구한다
|
|
(행 가용폭 = 폭 − 스크롤바 9 − 여백 20). 220 이면 마지막 토글이 잘린다. -->
|
|
<ColumnDefinition x:Name="RightColumn" Width="300" MinWidth="250" MaxWidth="560"/>
|
|
</Grid.ColumnDefinitions>
|
|
|
|
<!-- 좌: 알약 탭 — 서식 목록 / 레이어 / 도구 상자 -->
|
|
<Border Grid.Column="0" Background="{DynamicResource B.Panel}">
|
|
<TabControl x:Name="LeftTabs" SelectedIndex="{Binding SelectedLeftTabIndex, Mode=TwoWay}">
|
|
|
|
<!-- 서식 목록 -->
|
|
<TabItem>
|
|
<TabItem.Header><TextBlock Text="서식 목록" Style="{StaticResource TabHeaderText}"/></TabItem.Header>
|
|
<DockPanel>
|
|
<DockPanel DockPanel.Dock="Top" Margin="8,8,8,4">
|
|
<Button DockPanel.Dock="Right" Style="{StaticResource Subtle}" Width="30" Padding="0"
|
|
Margin="6,0,0,0" ToolTip="검색 (Enter)"
|
|
Command="{Binding SearchSheetsCommand}"
|
|
Content="{Binding Source=search, Converter={StaticResource IconName}, ConverterParameter=15}"/>
|
|
<!-- 분류 24종을 하나씩 여닫는 건 번거롭다 — 전체 여닫기 -->
|
|
<ToggleButton DockPanel.Dock="Right" Style="{StaticResource MiniToggle}" Width="26" Height="28"
|
|
Margin="4,0,0,0" ToolTip="분류 전체 펼치기 / 접기"
|
|
IsChecked="{Binding AreSheetGroupsExpanded, Mode=TwoWay}"
|
|
Content="{Binding SheetGroupToggleIcon, Converter={StaticResource IconName}, ConverterParameter=15}"/>
|
|
<!-- 자리표시자는 TextBox 위에 겹친 TextBlock — Text 가 비었을 때만 보인다 -->
|
|
<Grid>
|
|
<TextBox x:Name="SheetSearchBox"
|
|
Text="{Binding SheetSearchKeyword, UpdateSourceTrigger=PropertyChanged}">
|
|
<TextBox.InputBindings>
|
|
<KeyBinding Key="Enter" Command="{Binding SearchSheetsCommand}"/>
|
|
</TextBox.InputBindings>
|
|
</TextBox>
|
|
<TextBlock Text="서식명 또는 코드 검색" FontSize="12" Foreground="{DynamicResource B.Muted}"
|
|
Margin="9,0,0,0" VerticalAlignment="Center" IsHitTestVisible="False">
|
|
<TextBlock.Style>
|
|
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
|
|
<Setter Property="Visibility" Value="Collapsed"/>
|
|
<Style.Triggers>
|
|
<DataTrigger Binding="{Binding Text, ElementName=SheetSearchBox}" Value="">
|
|
<Setter Property="Visibility" Value="Visible"/>
|
|
</DataTrigger>
|
|
</Style.Triggers>
|
|
</Style>
|
|
</TextBlock.Style>
|
|
</TextBlock>
|
|
</Grid>
|
|
</DockPanel>
|
|
|
|
<!-- 목록 상태 한 줄 — 로딩/결과 없음/조회 실패/건수를 같은 자리에서 보여준다 -->
|
|
<TextBlock DockPanel.Dock="Bottom" Text="{Binding SheetListStatusText}" FontSize="11"
|
|
Foreground="{DynamicResource B.Muted}" Margin="9,4,9,8" TextWrapping="Wrap"/>
|
|
<Grid>
|
|
<!--
|
|
IsVirtualizingWhenGrouping 은 반드시 켜야 한다 — 그룹핑을 걸면 WPF 는 기본적으로
|
|
가상화를 끄고 1,600여 항목을 한꺼번에 실체화한다(탭 전환이 눈에 띄게 멈춘다).
|
|
-->
|
|
<ListBox x:Name="SheetListBox" ItemsSource="{Binding Source={StaticResource SheetsGrouped}}"
|
|
Margin="4,0,4,4"
|
|
VirtualizingPanel.IsVirtualizing="True"
|
|
VirtualizingPanel.IsVirtualizingWhenGrouping="True"
|
|
VirtualizingPanel.VirtualizationMode="Recycling"
|
|
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
|
MouseDoubleClick="OnSheetListDoubleClick"
|
|
ToolTip="분류 머리글을 눌러 펼치고, 서식을 더블클릭해 엽니다">
|
|
<ListBox.GroupStyle>
|
|
<GroupStyle>
|
|
<GroupStyle.ContainerStyle>
|
|
<Style TargetType="GroupItem">
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="GroupItem">
|
|
<StackPanel>
|
|
<!-- 그룹 키가 SheetGroupViewModel 인스턴스라 Name.IsExpanded 를 TwoWay 로 잡을 수 있다 -->
|
|
<ToggleButton IsChecked="{Binding Name.IsExpanded, Mode=TwoWay}" Cursor="Hand"
|
|
Focusable="False">
|
|
<ToggleButton.Template>
|
|
<ControlTemplate TargetType="ToggleButton">
|
|
<Border x:Name="bd" Background="Transparent" CornerRadius="5"
|
|
Padding="4,5" Margin="1,4,1,1">
|
|
<DockPanel>
|
|
<ContentControl DockPanel.Dock="Left" Margin="0,0,5,0" VerticalAlignment="Center"
|
|
IsTabStop="False" Focusable="False"
|
|
Content="{Binding Name.ChevronIcon, Converter={StaticResource IconName}, ConverterParameter=12}"/>
|
|
<!-- 검색 중이면 이 숫자는 '검색 통과분'이지 그 분류의 전체 건수가 아니다 -->
|
|
<TextBlock DockPanel.Dock="Right" Text="{Binding ItemCount}" FontSize="11"
|
|
Foreground="{DynamicResource B.Muted}" VerticalAlignment="Center"
|
|
Margin="6,0,3,0"
|
|
ToolTip="현재 목록에 표시된 건수(검색 중이면 검색 통과분)"/>
|
|
<TextBlock Text="{Binding Name.Label}" FontWeight="Bold" FontSize="11.5"
|
|
Foreground="{DynamicResource B.Muted}" VerticalAlignment="Center"
|
|
TextTrimming="CharacterEllipsis"/>
|
|
</DockPanel>
|
|
</Border>
|
|
<ControlTemplate.Triggers>
|
|
<Trigger Property="IsMouseOver" Value="True">
|
|
<Setter TargetName="bd" Property="Background" Value="{DynamicResource B.Hover}"/>
|
|
</Trigger>
|
|
</ControlTemplate.Triggers>
|
|
</ControlTemplate>
|
|
</ToggleButton.Template>
|
|
</ToggleButton>
|
|
<ItemsPresenter>
|
|
<ItemsPresenter.Style>
|
|
<Style TargetType="ItemsPresenter">
|
|
<Setter Property="Visibility" Value="Collapsed"/>
|
|
<Style.Triggers>
|
|
<DataTrigger Binding="{Binding Name.IsExpanded}" Value="True">
|
|
<Setter Property="Visibility" Value="Visible"/>
|
|
</DataTrigger>
|
|
</Style.Triggers>
|
|
</Style>
|
|
</ItemsPresenter.Style>
|
|
</ItemsPresenter>
|
|
</StackPanel>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
</GroupStyle.ContainerStyle>
|
|
</GroupStyle>
|
|
</ListBox.GroupStyle>
|
|
<ListBox.ItemTemplate>
|
|
<DataTemplate>
|
|
<!-- 좌측 여백은 분류 머리글 아래 항목임을 드러내는 들여쓰기 -->
|
|
<StackPanel Orientation="Horizontal" Margin="14,1,1,1">
|
|
<TextBlock Text="{Binding ShtCod}" FontSize="11" Foreground="{DynamicResource B.Muted}"
|
|
Width="52" VerticalAlignment="Center"/>
|
|
<!-- 서식생성기 사용이 꺼진 서식(ShtUsrDesYon='N') — 열기 시 거부된다 -->
|
|
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="10"
|
|
VerticalAlignment="Center" Margin="0,0,4,0"
|
|
Foreground="{DynamicResource B.Muted}"
|
|
ToolTip="기록지 정보에서 서식생성기 사용이 꺼져 있습니다">
|
|
<TextBlock.Style>
|
|
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
|
|
<Setter Property="Visibility" Value="Collapsed"/>
|
|
<Style.Triggers>
|
|
<DataTrigger Binding="{Binding DesignAllowed}" Value="False">
|
|
<Setter Property="Visibility" Value="Visible"/>
|
|
</DataTrigger>
|
|
</Style.Triggers>
|
|
</Style>
|
|
</TextBlock.Style>
|
|
</TextBlock>
|
|
<TextBlock Text="{Binding Name}" FontSize="12" TextTrimming="CharacterEllipsis">
|
|
<TextBlock.Style>
|
|
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
|
|
<Style.Triggers>
|
|
<DataTrigger Binding="{Binding HasDesign}" Value="False">
|
|
<Setter Property="Foreground" Value="{DynamicResource B.Muted}"/>
|
|
<Setter Property="Opacity" Value="0.6"/>
|
|
</DataTrigger>
|
|
<DataTrigger Binding="{Binding DesignAllowed}" Value="False">
|
|
<Setter Property="Foreground" Value="{DynamicResource B.Muted}"/>
|
|
<Setter Property="Opacity" Value="0.6"/>
|
|
</DataTrigger>
|
|
</Style.Triggers>
|
|
</Style>
|
|
</TextBlock.Style>
|
|
</TextBlock>
|
|
</StackPanel>
|
|
</DataTemplate>
|
|
</ListBox.ItemTemplate>
|
|
</ListBox>
|
|
</Grid>
|
|
</DockPanel>
|
|
</TabItem>
|
|
<!--
|
|
레이어 — [200]SheetMe 아웃라인.
|
|
페이지를 별도 섹션으로 두지 않고 트리의 최상위 노드로 삼는다. 부수 효과가 하나 있는데
|
|
의도한 것이다: 페이지 행은 항상 무강조라 연속 선택 블록이 페이지 경계에서 저절로 끊긴다.
|
|
-->
|
|
<TabItem>
|
|
<TabItem.Header><TextBlock Text="레이어" Style="{StaticResource TabHeaderText}"/></TabItem.Header>
|
|
<DockPanel>
|
|
<v:LayerPanelView/>
|
|
</DockPanel>
|
|
</TabItem>
|
|
<!-- 도구 상자 ([200] 타일 카드 룩 — 드래그/더블클릭 배치) -->
|
|
<TabItem>
|
|
<TabItem.Header><TextBlock Text="도구 상자" Style="{StaticResource TabHeaderText}"/></TabItem.Header>
|
|
<ListBox ItemsSource="{Binding Source={StaticResource PaletteGrouped}}"
|
|
ItemContainerStyle="{StaticResource PaletteTile}"
|
|
Margin="6,4,6,6"
|
|
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
|
ToolTip="더블클릭 또는 드래그로 캔버스에 배치">
|
|
<b:Interaction.Behaviors>
|
|
<bh:PaletteDragBehavior/>
|
|
</b:Interaction.Behaviors>
|
|
<!-- 그룹 세로 나열(GroupStyle.Panel 기본) + 그룹 내 타일 2열(ItemsPanel — 그룹 내부 항목이 상속) -->
|
|
<ListBox.ItemsPanel>
|
|
<ItemsPanelTemplate>
|
|
<UniformGrid Columns="2"/>
|
|
</ItemsPanelTemplate>
|
|
</ListBox.ItemsPanel>
|
|
<ListBox.GroupStyle>
|
|
<GroupStyle>
|
|
<GroupStyle.HeaderTemplate>
|
|
<DataTemplate>
|
|
<TextBlock Text="{Binding Name}" Style="{StaticResource PaletteGroupHeader}"/>
|
|
</DataTemplate>
|
|
</GroupStyle.HeaderTemplate>
|
|
</GroupStyle>
|
|
</ListBox.GroupStyle>
|
|
<ListBox.ItemTemplate>
|
|
<DataTemplate>
|
|
<StackPanel HorizontalAlignment="Center" Margin="2,9,2,8" Background="Transparent">
|
|
<ContentControl Content="{Binding Type, Converter={StaticResource TypeToIcon}}"
|
|
HorizontalAlignment="Center" Margin="0,0,0,5" IsTabStop="False" Focusable="False"/>
|
|
<TextBlock Text="{Binding DisplayName}" FontSize="11" TextAlignment="Center"
|
|
HorizontalAlignment="Center" TextWrapping="Wrap"/>
|
|
</StackPanel>
|
|
</DataTemplate>
|
|
</ListBox.ItemTemplate>
|
|
</ListBox>
|
|
</TabItem>
|
|
</TabControl>
|
|
</Border>
|
|
|
|
<GridSplitter Grid.Column="1" Style="{StaticResource ColSplitter}" ToolTip="좌측 패널 너비 조절"/>
|
|
|
|
<!-- 중앙: 문서 탭(크롬식) + 캔버스 + 플로팅 팔레트 바 -->
|
|
<Grid Grid.Column="2" Background="{DynamicResource B.CanvasBg}">
|
|
<TabControl Style="{StaticResource DocTabs}"
|
|
ItemsSource="{Binding OpenDesigners}"
|
|
SelectedItem="{Binding CurrentDesigner}"
|
|
ItemContainerStyle="{StaticResource DocTabItem}">
|
|
<TabControl.ItemTemplate>
|
|
<DataTemplate>
|
|
<StackPanel Orientation="Horizontal">
|
|
<!-- 활성 탭만 아이콘을 강조색으로 — 탭이 여러 개일 때 어디가 활성인지가 배경색 차이만으로는 약하다 -->
|
|
<ContentControl Margin="0,0,6,0" VerticalAlignment="Center" IsTabStop="False" Focusable="False">
|
|
<ContentControl.Style>
|
|
<Style TargetType="ContentControl">
|
|
<Setter Property="Content"
|
|
Value="{Binding Source=file-text, Converter={StaticResource IconName}, ConverterParameter=12}"/>
|
|
<Style.Triggers>
|
|
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TabItem}}" Value="True">
|
|
<Setter Property="Content"
|
|
Value="{Binding Source=file-text, Converter={StaticResource IconName}, ConverterParameter=12|B.Accent}"/>
|
|
</DataTrigger>
|
|
</Style.Triggers>
|
|
</Style>
|
|
</ContentControl.Style>
|
|
</ContentControl>
|
|
<TextBlock Text="{Binding DisplayName}" MaxWidth="170" Style="{StaticResource TabHeaderText}"
|
|
TextTrimming="CharacterEllipsis" VerticalAlignment="Center"/>
|
|
<Button Content="✕" FontSize="11" Margin="7,0,0,0"
|
|
Style="{StaticResource Subtle}" Padding="3,0" Cursor="Hand" ToolTip="문서 닫기"
|
|
Command="{Binding DataContext.CloseDocumentCommand,
|
|
RelativeSource={RelativeSource AncestorType=Window}}"
|
|
CommandParameter="{Binding}"/>
|
|
</StackPanel>
|
|
</DataTemplate>
|
|
</TabControl.ItemTemplate>
|
|
<TabControl.ContentTemplate>
|
|
<DataTemplate>
|
|
<v:DesignerCanvasView/>
|
|
</DataTemplate>
|
|
</TabControl.ContentTemplate>
|
|
</TabControl>
|
|
|
|
<!-- 플로팅 팔레트 바 (Figma 식 — 컨트롤 추가 플라이아웃 | 줌) -->
|
|
<Border Background="{DynamicResource B.Surface}" BorderBrush="{DynamicResource B.Line}" BorderThickness="1"
|
|
CornerRadius="12" Padding="7,5" HorizontalAlignment="Center" VerticalAlignment="Bottom"
|
|
Margin="0,0,0,20">
|
|
<!-- 그림자는 토큰으로 — 라이트에서 흰 배경에 검은 그림자가 그대로 얹히던 것을 테마별로 분리.
|
|
반드시 DynamicResource — 요소 구문 <StaticResource/> 로 넣으면 로드 시점 값으로 굳어
|
|
테마를 바꿔도 다크용 진한 그림자가 그대로 남는다. -->
|
|
<Border.Effect>
|
|
<DynamicResource ResourceKey="B.FloatShadow"/>
|
|
</Border.Effect>
|
|
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
|
<ToggleButton Style="{StaticResource BarToolToggle}" Width="38" Height="34" Padding="0" Focusable="False"
|
|
ToolTip="선택 도구 — 클릭으로 선택, 드래그로 이동"
|
|
IsChecked="{Binding IsHandTool, Converter={StaticResource InverseBool}, Mode=OneWay}"
|
|
Click="OnSelectToolClick"
|
|
Content="{Binding Source=mouse-pointer-click, Converter={StaticResource IconName}, ConverterParameter=18|B.Ink}"/>
|
|
<ToggleButton Style="{StaticResource BarToolToggle}" Width="38" Height="34" Padding="0" Focusable="False"
|
|
ToolTip="손 도구 — 드래그로 화면 이동 (Space 누르는 동안 임시)"
|
|
IsChecked="{Binding IsHandTool, Mode=OneWay}"
|
|
Click="OnHandToolClick"
|
|
Content="{Binding Source=hand, Converter={StaticResource IconName}, ConverterParameter=18|B.Ink}"/>
|
|
<Border Width="1" Height="22" Background="{DynamicResource B.Line}" Margin="5,0" VerticalAlignment="Center"/>
|
|
<Button x:Name="AddControlBtn" Style="{StaticResource Subtle}" Width="38" Height="34" Padding="0"
|
|
ToolTip="컨트롤 추가 — 활성 페이지 중앙에 배치" Click="OnAddControlFlyoutClick"
|
|
Content="{Binding Source=layout-grid, Converter={StaticResource IconName}, ConverterParameter=18}"/>
|
|
<Border Width="1" Height="22" Background="{DynamicResource B.Line}" Margin="5,0" VerticalAlignment="Center"/>
|
|
<!-- ±버튼은 두지 않는다([200] 와 동일) — Ctrl+휠이 주 조작이고, 배율 버튼이 플라이아웃을 겸한다 -->
|
|
<Button x:Name="ZoomBtn" Style="{StaticResource Subtle}" Height="34" Padding="8,0,6,0" ToolTip="줌"
|
|
Click="OnZoomFlyoutClick">
|
|
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
|
<TextBlock Text="{Binding CurrentDesigner.ZoomPercentText, FallbackValue=100%}"
|
|
FontSize="12" MinWidth="38" TextAlignment="Center" VerticalAlignment="Center"/>
|
|
<ContentControl Content="{Binding Source=chevron-down, Converter={StaticResource IconName}, ConverterParameter=11}"
|
|
Margin="3,1,0,0" VerticalAlignment="Center" IsTabStop="False" Focusable="False"/>
|
|
</StackPanel>
|
|
</Button>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- 컨트롤 추가 플라이아웃 (카테고리별 타일) -->
|
|
<Popup x:Name="AddControlPopup" PlacementTarget="{Binding ElementName=AddControlBtn}" Placement="Top"
|
|
StaysOpen="False" AllowsTransparency="True" PopupAnimation="Fade" VerticalOffset="-8">
|
|
<Border Margin="18" Background="{DynamicResource B.Panel}" BorderBrush="{DynamicResource B.Line}"
|
|
BorderThickness="1" CornerRadius="10" MinWidth="300">
|
|
<!-- 플라이아웃 그림자도 토큰으로 — 라이트에서 흰 배경에 진한 검정이 그대로 얹힌다 -->
|
|
<Border.Effect>
|
|
<DynamicResource ResourceKey="B.FloatShadow"/>
|
|
</Border.Effect>
|
|
<!-- 힌트는 ScrollViewer <b>안쪽</b>이어야 한다 — ScrollViewer 도 중간 서피스를 열어
|
|
바깥에 걸면 무효다(진단 cleartype 의 I/J 표본이 그 차이다). -->
|
|
<ScrollViewer MaxHeight="440" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
|
|
<ItemsControl ItemsSource="{Binding Source={StaticResource PaletteGrouped}}" Margin="10,9,10,10"
|
|
Background="{DynamicResource B.Panel}" RenderOptions.ClearTypeHint="Enabled">
|
|
<!-- 그룹 세로 나열 + 그룹 내 타일 4열([200] 플라이아웃 치수) -->
|
|
<ItemsControl.ItemsPanel>
|
|
<ItemsPanelTemplate>
|
|
<UniformGrid Columns="4"/>
|
|
</ItemsPanelTemplate>
|
|
</ItemsControl.ItemsPanel>
|
|
<ItemsControl.GroupStyle>
|
|
<GroupStyle>
|
|
<GroupStyle.HeaderTemplate>
|
|
<DataTemplate>
|
|
<TextBlock Text="{Binding Name}" FontSize="10.5" FontWeight="Bold"
|
|
Foreground="{DynamicResource B.Muted}" Margin="2,9,0,6"/>
|
|
</DataTemplate>
|
|
</GroupStyle.HeaderTemplate>
|
|
</GroupStyle>
|
|
</ItemsControl.GroupStyle>
|
|
<ItemsControl.ItemTemplate>
|
|
<DataTemplate>
|
|
<Button Width="66" Margin="3" Padding="4,9,4,8" Click="OnFlyoutTileClick"
|
|
Background="{DynamicResource B.Surface}" BorderBrush="{DynamicResource B.Line}"
|
|
ToolTip="{Binding DisplayName}">
|
|
<StackPanel HorizontalAlignment="Center">
|
|
<ContentControl Content="{Binding Type, Converter={StaticResource TypeToIcon}}"
|
|
HorizontalAlignment="Center" Margin="0,0,0,5" IsTabStop="False" Focusable="False"/>
|
|
<TextBlock Text="{Binding DisplayName}" FontSize="11" TextAlignment="Center"
|
|
HorizontalAlignment="Center"/>
|
|
</StackPanel>
|
|
</Button>
|
|
</DataTemplate>
|
|
</ItemsControl.ItemTemplate>
|
|
</ItemsControl>
|
|
</ScrollViewer>
|
|
</Border>
|
|
</Popup>
|
|
|
|
<!-- 줌 플라이아웃 -->
|
|
<Popup x:Name="ZoomPopup" PlacementTarget="{Binding ElementName=ZoomBtn}" Placement="Top"
|
|
StaysOpen="False" AllowsTransparency="True" PopupAnimation="Fade" VerticalOffset="-8">
|
|
<Border Margin="18" Background="{DynamicResource B.Panel}" BorderBrush="{DynamicResource B.Line}"
|
|
BorderThickness="1" CornerRadius="10" MinWidth="190">
|
|
<!-- 플라이아웃 그림자도 토큰으로 — 라이트에서 흰 배경에 진한 검정이 그대로 얹힌다 -->
|
|
<Border.Effect>
|
|
<DynamicResource ResourceKey="B.FloatShadow"/>
|
|
</Border.Effect>
|
|
<StackPanel Margin="5" Background="{DynamicResource B.Panel}"
|
|
RenderOptions.ClearTypeHint="Enabled">
|
|
<Button Style="{StaticResource FlyoutRow}" Command="{Binding ZoomInCommand}" Click="OnZoomRowClick">
|
|
<DockPanel LastChildFill="True">
|
|
<TextBlock DockPanel.Dock="Right" Text="Ctrl+휠↑" Foreground="{DynamicResource B.Muted}"
|
|
FontSize="11.5" Margin="24,0,0,0" VerticalAlignment="Center"/>
|
|
<TextBlock Text="확대" FontSize="12.5" VerticalAlignment="Center"/>
|
|
</DockPanel>
|
|
</Button>
|
|
<Button Style="{StaticResource FlyoutRow}" Command="{Binding ZoomOutCommand}" Click="OnZoomRowClick">
|
|
<DockPanel LastChildFill="True">
|
|
<TextBlock DockPanel.Dock="Right" Text="Ctrl+휠↓" Foreground="{DynamicResource B.Muted}"
|
|
FontSize="11.5" Margin="24,0,0,0" VerticalAlignment="Center"/>
|
|
<TextBlock Text="축소" FontSize="12.5" VerticalAlignment="Center"/>
|
|
</DockPanel>
|
|
</Button>
|
|
<Border Height="1" Background="{DynamicResource B.Line}" Margin="8,5"/>
|
|
<Button Style="{StaticResource FlyoutRow}" Command="{Binding ZoomResetCommand}" Click="OnZoomRowClick">
|
|
<TextBlock Text="100%" FontSize="12.5" VerticalAlignment="Center"/>
|
|
</Button>
|
|
<Button Style="{StaticResource FlyoutRow}" Command="{Binding ZoomFitCommand}" Click="OnZoomRowClick">
|
|
<TextBlock Text="화면 맞춤" FontSize="12.5" VerticalAlignment="Center"/>
|
|
</Button>
|
|
</StackPanel>
|
|
</Border>
|
|
</Popup>
|
|
|
|
<!-- 빈 상태 — 열린 문서가 없으면 회색 허공 대신 다음 행동을 제시한다.
|
|
플로팅 바보다 뒤에 두어 위에 덮인다(문서 없이 줌·컨트롤 추가는 의미가 없다). -->
|
|
<Border Background="{DynamicResource B.CanvasBg}">
|
|
<Border.Style>
|
|
<Style TargetType="Border">
|
|
<Setter Property="Visibility" Value="Collapsed"/>
|
|
<Style.Triggers>
|
|
<DataTrigger Binding="{Binding HasOpenDocuments}" Value="False">
|
|
<Setter Property="Visibility" Value="Visible"/>
|
|
</DataTrigger>
|
|
</Style.Triggers>
|
|
</Style>
|
|
</Border.Style>
|
|
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" MaxWidth="360">
|
|
<ContentControl HorizontalAlignment="Center" IsTabStop="False" Focusable="False" Opacity="0.5"
|
|
Content="{Binding Source=file-text, Converter={StaticResource IconName}, ConverterParameter=44}"/>
|
|
<TextBlock Text="열린 서식이 없습니다" FontSize="15" FontWeight="Bold" TextAlignment="Center"
|
|
HorizontalAlignment="Center" Margin="0,16,0,6"/>
|
|
<TextBlock Foreground="{DynamicResource B.Muted}" FontSize="12.5" TextAlignment="Center"
|
|
TextWrapping="Wrap" HorizontalAlignment="Center" Margin="0,0,0,20"
|
|
Text="새 서식을 만들거나, 왼쪽 서식 목록에서 기존 서식을 두 번 눌러 엽니다."/>
|
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
|
<Button Content="새 서식" Command="{Binding NewFileCommand}" Padding="16,7" Margin="0,0,8,0"/>
|
|
<Button Content="DB에서 열기" Command="{Binding OpenFromDbCommand}" Padding="16,7"
|
|
IsEnabled="{Binding CanUseDb}"/>
|
|
<Button Content="파일 열기" Command="{Binding OpenFileCommand}" Padding="16,7" Margin="8,0,0,0"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</Border>
|
|
</Grid>
|
|
|
|
<GridSplitter Grid.Column="3" Style="{StaticResource ColSplitter}" ToolTip="속성 패널 너비 조절"/>
|
|
|
|
<!-- 우: 속성 인스펙터 -->
|
|
<Border Grid.Column="4" Background="{DynamicResource B.Panel}">
|
|
<DockPanel>
|
|
<Border DockPanel.Dock="Top" Background="{DynamicResource B.PanelHeader}" Padding="11,8"
|
|
BorderBrush="{DynamicResource B.Line}" BorderThickness="0,0,0,1">
|
|
<TextBlock Text="속성" FontWeight="Bold" Foreground="{DynamicResource B.Muted}"/>
|
|
</Border>
|
|
<v:InspectorView DataContext="{Binding CurrentDesigner.Inspector}"/>
|
|
</DockPanel>
|
|
</Border>
|
|
</Grid>
|
|
</DockPanel>
|
|
</Window>
|