using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using Microsoft.Xaml.Behaviors; using SheetMe.Designer.ViewModels; namespace SheetMe.Designer.Behaviors; /// /// 캔버스 키보드 단축키 — 텍스트 입력 요소에 포커스가 있으면 통과(입력 보호). /// 화살표 넛지(Shift=그리드), Del, Ctrl+A/C/V/D/Z/Y, Esc. /// public sealed class CanvasKeyboardBehavior : Behavior { #region Methods protected override void OnAttached() { base.OnAttached(); AssociatedObject.PreviewKeyDown += OnPreviewKeyDown; } protected override void OnDetaching() { AssociatedObject.PreviewKeyDown -= OnPreviewKeyDown; base.OnDetaching(); } private void OnPreviewKeyDown(object sender, KeyEventArgs e) { if ((AssociatedObject as FrameworkElement)?.DataContext is not DesignerViewModel designer) { return; } // 텍스트 입력 보호 — 포커스가 편집 컨트롤이면 단축키 라우팅 안 함 if (Keyboard.FocusedElement is TextBoxBase or ComboBox or PasswordBox) { return; } var ctrl = Keyboard.Modifiers.HasFlag(ModifierKeys.Control); var shift = Keyboard.Modifiers.HasFlag(ModifierKeys.Shift); var step = shift ? designer.Snap.GridSize * 2 : 1; var handled = true; switch (e.Key) { case Key.Left: designer.NudgeSelection(-step, 0); break; case Key.Right: designer.NudgeSelection(step, 0); break; case Key.Up: designer.NudgeSelection(0, -step); break; case Key.Down: designer.NudgeSelection(0, step); break; case Key.Delete: designer.DeleteSelection(); break; case Key.Escape: designer.Interaction.Cancel(); break; case Key.A when ctrl: designer.SelectAllOnActivePage(); break; case Key.C when ctrl: designer.CopySelection(); break; case Key.X when ctrl: designer.CutSelection(); break; case Key.V when ctrl: designer.Paste(); break; case Key.D when ctrl: designer.CopySelection(); designer.Paste(); break; case Key.Z when ctrl: designer.Undo.Undo(); break; case Key.Y when ctrl: designer.Undo.Redo(); break; case Key.G when ctrl && shift: designer.UngroupSelection(); break; case Key.G when ctrl: designer.GroupSelection(); break; default: handled = false; break; } e.Handled = handled; } #endregion }