From c22d84fb61b47c924b5249d70da74521488c6199 Mon Sep 17 00:00:00 2001 From: Msystech Date: Wed, 12 Aug 2026 18:03:19 +0900 Subject: [PATCH] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=96=B4=20=ED=8C=A8?= =?UTF-8?q?=EB=84=90=203=EA=B1=B4=20=EC=88=98=EC=A0=95=20=E2=80=94=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=EC=97=90=EC=84=9C=20Ctrl+G,=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A1=A4=EB=B0=94=20=EC=9E=98=EB=A6=BC,=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=EC=B9=A9=20=EC=9D=B4=EC=A4=91=20=ED=85=8C=EB=91=90?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1) 목록에서 단축키가 안 먹었다 CanvasKeyboardBehavior 는 캔버스에 붙어 있어 포커스가 레이어 목록에 있으면 이벤트가 거기까지 가지 않는다. 여러 행을 골라 놓고 Ctrl+G 를 눌러도 아무 일이 없던 이유다. 목록에 KeyDown 을 달아 그룹·삭제·복사·되돌리기를 처리한다. 방향키·Home/End·문자 입력은 넘기지 않는다(목록 자체의 이동과 형식 검색이 우선). 이름 편집 중에는 통과시킨다. 2) 세로 스크롤바가 오른쪽이 잘려 보였다 — 앱 전체 공통 결함 Thumb 스타일의 MinWidth/MinHeight 24 가 폭 9 짜리 막대 안에서 썸을 24 폭으로 강제해 오른쪽이 통째로 잘렸다(둥근 모서리가 사라지고 수직으로 싹둑 잘린 막대). 가로 막대는 아래쪽이 같은 식으로 잘렸다. 최소 '길이'는 MinThumbTrack.MinThumbLength=44 가 이미 보장하므로 최소 '두께'는 지운다. 화살표 글리프도 7 단위 + 스트로크 1.4 = 8.4 라 폭 9 에서 캡이 경계에 닿아 오른팔이 잘렸다 — 막대 폭을 11 로 올려 양옆 여유를 준다. 3) 검색칩 안에 상자가 하나 더 그려졌다 전역 TextBox 템플릿은 BorderThickness=1 이 하드코딩돼 있어 인스턴스에서 0 을 줘도 무시된다. 칩 전용 ChipTextBox 스타일(테두리 없는 템플릿)을 만들고, 포커스 표시는 칩 쪽 IsKeyboardFocusWithin 으로 옮겼다. 회귀: 테스트 124/124, 편집 스모크 실패 0, DB 왕복 1,271건 diff 0/예외 0, 종이 렌더 P062 바이트 동일. Co-Authored-By: Claude Opus 5 --- .../Themes/DesignerTheme.xaml | 42 ++++++++++++++++--- .../Views/LayerPanelView.xaml | 18 ++++++-- .../Views/LayerPanelView.xaml.cs | 41 ++++++++++++++++++ 3 files changed, 91 insertions(+), 10 deletions(-) diff --git a/src/SheetMe.Designer/Themes/DesignerTheme.xaml b/src/SheetMe.Designer/Themes/DesignerTheme.xaml index c1e8f88..a359b32 100644 --- a/src/SheetMe.Designer/Themes/DesignerTheme.xaml +++ b/src/SheetMe.Designer/Themes/DesignerTheme.xaml @@ -143,6 +143,27 @@ + + + + - @@ -104,6 +113,7 @@ SelectionMode="Extended" Padding="0,6,0,0" MouseDoubleClick="OnLayerDoubleClick" PreviewMouseLeftButtonDown="OnLayerRowPressed" + KeyDown="OnLayerListKeyDown" ScrollViewer.HorizontalScrollBarVisibility="Disabled"> diff --git a/src/SheetMe.Designer/Views/LayerPanelView.xaml.cs b/src/SheetMe.Designer/Views/LayerPanelView.xaml.cs index 43f37ef..bc07b2b 100644 --- a/src/SheetMe.Designer/Views/LayerPanelView.xaml.cs +++ b/src/SheetMe.Designer/Views/LayerPanelView.xaml.cs @@ -75,6 +75,47 @@ public partial class LayerPanelView : System.Windows.Controls.UserControl } } + /// + /// 레이어 목록 단축키 — 그룹/삭제/복사/되돌리기. + /// + /// 이 키들은 원래 가 처리하는데, 그 behavior 는 + /// 캔버스에 붙어 있어서 포커스가 목록에 있으면 이벤트가 거기까지 가지 않는다. + /// 목록에서 여러 행을 골라 놓고 Ctrl+G 를 눌렀을 때 아무 일도 안 일어나던 이유가 이것이다. + /// + /// 방향키·Home/End·문자 타이핑은 넘기지 않는다 — 목록 자체의 이동·형식 검색이 우선이다. + /// 그룹 이름을 편집 중일 때도 통과시킨다(입력 보호). + /// + private void OnLayerListKeyDown(object sender, System.Windows.Input.KeyEventArgs e) + { + if (Designer is not { } designer + || System.Windows.Input.Keyboard.FocusedElement + is System.Windows.Controls.Primitives.TextBoxBase or System.Windows.Controls.ComboBox) + { + return; + } + + var ctrl = System.Windows.Input.Keyboard.Modifiers.HasFlag(System.Windows.Input.ModifierKeys.Control); + var shift = System.Windows.Input.Keyboard.Modifiers.HasFlag(System.Windows.Input.ModifierKeys.Shift); + var handled = true; + + switch (e.Key) + { + case System.Windows.Input.Key.G when ctrl && shift: designer.UngroupSelection(); break; + case System.Windows.Input.Key.G when ctrl: designer.GroupSelection(); break; + case System.Windows.Input.Key.C when ctrl: designer.CopySelection(); break; + case System.Windows.Input.Key.X when ctrl: designer.CutSelection(); break; + case System.Windows.Input.Key.V when ctrl: designer.Paste(); break; + case System.Windows.Input.Key.D when ctrl: designer.CopySelection(); designer.Paste(); break; + case System.Windows.Input.Key.Z when ctrl: designer.Undo.Undo(); break; + case System.Windows.Input.Key.Y when ctrl: designer.Undo.Redo(); break; + case System.Windows.Input.Key.Delete: designer.DeleteSelection(); break; + case System.Windows.Input.Key.Escape: designer.Selection.Clear(); break; + default: handled = false; break; + } + + e.Handled = handled; + } + /// 페이지 헤더의 복제 버튼 private void OnPageDuplicateClick(object sender, RoutedEventArgs e) {