diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Dock/DockControl.xaml b/src/modules/cmdpal/Microsoft.CmdPal.UI/Dock/DockControl.xaml index 1987bb0675..b8acc4a182 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Dock/DockControl.xaml +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Dock/DockControl.xaml @@ -182,7 +182,7 @@ @@ -334,12 +334,16 @@ + + + + @@ -373,7 +377,8 @@ - + + @@ -411,7 +416,8 @@ - + + diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Dock/DockItemControl.xaml b/src/modules/cmdpal/Microsoft.CmdPal.UI/Dock/DockItemControl.xaml index 2247fae6ef..4dcd630779 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Dock/DockItemControl.xaml +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Dock/DockItemControl.xaml @@ -58,62 +58,67 @@ - - - - + x:Name="PART_RootGrid" + Margin="{TemplateBinding InnerMargin}" + Padding="{TemplateBinding Padding}" + VerticalAlignment="Stretch" + Background="{TemplateBinding Background}" + BorderBrush="{TemplateBinding BorderBrush}" + BorderThickness="{TemplateBinding BorderThickness}" + CornerRadius="{TemplateBinding CornerRadius}"> + + + + + - - + + - - - + - - + Visibility="{TemplateBinding TextVisibility}"> + + + + diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Dock/DockItemControl.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Dock/DockItemControl.xaml.cs index 0c95230f74..527b2bd834 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Dock/DockItemControl.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Dock/DockItemControl.xaml.cs @@ -5,10 +5,12 @@ using Microsoft.CmdPal.UI.Controls; using Microsoft.CmdPal.UI.ViewModels; using Microsoft.CmdPal.UI.ViewModels.Dock; +using Microsoft.CmdPal.UI.ViewModels.Settings; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Input; using Microsoft.UI.Xaml.Markup; +using Microsoft.UI.Xaml.Media; namespace Microsoft.CmdPal.UI.Dock; @@ -56,6 +58,15 @@ public sealed partial class DockItemControl : Control set => SetValue(IconProperty, value); } + public static readonly DependencyProperty InnerMarginProperty = + DependencyProperty.Register(nameof(InnerMargin), typeof(Thickness), typeof(DockItemControl), new PropertyMetadata(new Thickness(0))); + + public Thickness InnerMargin + { + get => (Thickness)GetValue(InnerMarginProperty); + set => SetValue(InnerMarginProperty, value); + } + public static readonly DependencyProperty TextVisibilityProperty = DependencyProperty.Register(nameof(TextVisibility), typeof(Visibility), typeof(DockItemControl), new PropertyMetadata(null, OnTextPropertyChanged)); @@ -68,6 +79,8 @@ public sealed partial class DockItemControl : Control private const string IconPresenterName = "IconPresenter"; private FrameworkElement? _iconPresenter; + private DockControl? _parentDock; + private long _dockSideCallbackToken = -1; private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { @@ -174,9 +187,13 @@ public sealed partial class DockItemControl : Control PointerEntered -= Control_PointerEntered; PointerExited -= Control_PointerExited; + Loaded -= DockItemControl_Loaded; + Unloaded -= DockItemControl_Unloaded; PointerEntered += Control_PointerEntered; PointerExited += Control_PointerExited; + Loaded += DockItemControl_Loaded; + Unloaded += DockItemControl_Unloaded; IsEnabledChanged += OnIsEnabledChanged; @@ -187,6 +204,62 @@ public sealed partial class DockItemControl : Control UpdateAllVisibility(); } + private void DockItemControl_Loaded(object sender, RoutedEventArgs e) + { + // Walk the visual tree to find our parent DockControl and watch its DockSide. + // This lets us extend the hit-test area toward the screen edge. + DependencyObject? parent = VisualTreeHelper.GetParent(this); + while (parent is not null and not DockControl) + { + parent = VisualTreeHelper.GetParent(parent); + } + + if (parent is DockControl dock) + { + _parentDock = dock; + UpdateInnerMarginForDockSide(dock.DockSide); + _dockSideCallbackToken = dock.RegisterPropertyChangedCallback( + DockControl.DockSideProperty, + OnParentDockSideChanged); + } + } + + private void DockItemControl_Unloaded(object sender, RoutedEventArgs e) + { + if (_parentDock is not null && _dockSideCallbackToken >= 0) + { + _parentDock.UnregisterPropertyChangedCallback( + DockControl.DockSideProperty, + _dockSideCallbackToken); + _dockSideCallbackToken = -1; + _parentDock = null; + } + } + + private void OnParentDockSideChanged(DependencyObject sender, DependencyProperty dp) + { + if (sender is DockControl dock) + { + UpdateInnerMarginForDockSide(dock.DockSide); + } + } + + private void UpdateInnerMarginForDockSide(DockSide side) + { + // Push the visual (PART_RootGrid) inward on the screen-edge side so + // the transparent hit-test area extends all the way to the edge. + // The values here compensate for the margin/padding removed from the + // DockControl's ContentGrid on the screen-edge side. + InnerMargin = side switch + { + DockSide.Top => new Thickness(0, 4, 0, 0), + DockSide.Bottom => new Thickness(0, 0, 0, 4), + DockSide.Left => new Thickness(8, 0, 0, 0), + DockSide.Right => new Thickness(0, 0, 8, 0), + _ => new Thickness(0), + }; + } + private void Control_PointerEntered(object sender, PointerRoutedEventArgs e) { VisualStateManager.GoToState(this, "PointerOver", true);