diff --git a/source/Components/AvalonDock/Controls/LayoutAutoHideWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutAutoHideWindowControl.cs index e5c876a2..081ce97d 100644 --- a/source/Components/AvalonDock/Controls/LayoutAutoHideWindowControl.cs +++ b/source/Components/AvalonDock/Controls/LayoutAutoHideWindowControl.cs @@ -9,6 +9,7 @@ This program is provided to you under the terms of the Microsoft Public using AvalonDock.Layout; using System; +using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Runtime.InteropServices; @@ -44,6 +45,8 @@ public class LayoutAutoHideWindowControl : HwndHost, ILayoutControl private Border _resizerGhost = null; private Window _resizerWindowHost = null; private Vector _initialStartPoint; + private List _sizeChangedListeningControls; + private SizeChangedEventHandler _sizeChangedHandler; #endregion fields @@ -59,6 +62,7 @@ static LayoutAutoHideWindowControl() internal LayoutAutoHideWindowControl() { + _sizeChangedHandler = ViewboxZoomChanged; } #endregion Constructors @@ -116,6 +120,8 @@ internal void Show(LayoutAnchorControl anchor) _manager = _model.Root.Manager; CreateInternalGrid(); _model.PropertyChanged += _model_PropertyChanged; + SetLayoutTransform(); + StartListeningToViewboxZoomChange(); Visibility = Visibility.Visible; InvalidateMeasure(); UpdateWindowPos(); @@ -124,6 +130,8 @@ internal void Show(LayoutAnchorControl anchor) internal void Hide() { + StopListeningToViewboxZoomChange(); + if (_model == null) return; _model.PropertyChanged -= _model_PropertyChanged; RemoveInternalGrid(); @@ -214,6 +222,61 @@ private void _model_PropertyChanged(object sender, System.ComponentModel.Propert if (!_model.IsAutoHidden) _manager.HideAutoHideWindow(_anchor); } + private Transform ChildLayoutTransform + { + get + { + var viewboxes = _manager.GetParents().OfType().ToList(); + + if (viewboxes.Any()) + { + if (_manager.TransformToAncestor(viewboxes[viewboxes.Count - 1]) is Transform transform) + { + if (!transform.Value.IsIdentity) + { + var origin = transform.Transform(new Point()); + + var newTransformGroup = new TransformGroup(); + newTransformGroup.Children.Add(transform); + newTransformGroup.Children.Add(new TranslateTransform(-origin.X, -origin.Y)); + return newTransformGroup; + } + } + } + + return Transform.Identity; + } + } + + private void SetLayoutTransform() + { + // We refresh this each time either: + // 1) The window is created. + // 2) An ancestor Viewbox changes its zoom (the Viewbox or its child changes size) + // We would also want to refresh when the visual tree changes such that an ancestor Viewbox is added, removed, or changed. However, this is completely unnecessary + // because the LayoutAutoHideWindowControl closes if a visual ancestor is changed: DockingManager.Unloaded handler calls _autoHideWindowManager?.HideAutoWindow() + if (ChildLayoutTransform is Transform transform && _internalHostPresenter.LayoutTransform.Value != transform.Value) + { + LayoutTransform = (Transform)transform.Inverse; + _internalHostPresenter.LayoutTransform = transform; + } + } + private void StartListeningToViewboxZoomChange() + { + StopListeningToViewboxZoomChange(); + _sizeChangedListeningControls = _manager.GetParents().OfType().SelectMany(x => new[] { x, x.Child }).OfType().Distinct().ToList(); + _sizeChangedListeningControls.ForEach(x => x.SizeChanged += _sizeChangedHandler); + } + private void StopListeningToViewboxZoomChange() + { + _sizeChangedListeningControls?.ForEach(x => x.SizeChanged -= _sizeChangedHandler); + _sizeChangedListeningControls?.Clear(); + } + private void ViewboxZoomChanged(object sender, SizeChangedEventArgs e) + { + SetLayoutTransform(); + } + private void CreateInternalGrid() { _internalGrid = new Grid { FlowDirection = FlowDirection.LeftToRight }; @@ -351,11 +414,13 @@ private void OnResizerDragCompleted(object sender, System.Windows.Controls.Primi var trToWnd = TransformToAncestor(rootVisual); //var transformedDelta = trToWnd.Transform(new Point(e.HorizontalChange, e.VerticalChange)) - trToWnd.Transform(new Point()); + var deltaPoint = ChildLayoutTransform.Inverse.Transform(new Point(Canvas.GetLeft(_resizerGhost) - _initialStartPoint.X, Canvas.GetTop(_resizerGhost) - _initialStartPoint.Y)); + double delta; if (_side == AnchorSide.Right || _side == AnchorSide.Left) - delta = Canvas.GetLeft(_resizerGhost) - _initialStartPoint.X; + delta = deltaPoint.X; else - delta = Canvas.GetTop(_resizerGhost) - _initialStartPoint.Y; + delta = deltaPoint.Y; switch (_side) { @@ -400,6 +465,10 @@ private void OnResizerDragDelta(object sender, System.Windows.Controls.Primitive var trToWnd = TransformToAncestor(rootVisual); var transformedDelta = trToWnd.Transform(new Point(e.HorizontalChange, e.VerticalChange)) - trToWnd.Transform(new Point()); + if (ChildLayoutTransform is Transform transform && !transform.Value.IsIdentity) + { + transformedDelta = transform.Transform(new Point() + transformedDelta) - new Point(); + } if (_side == AnchorSide.Right || _side == AnchorSide.Left) {