Skip to content

Commit

Permalink
Fixes #362 DockingManager with a Viewbox ancestor does not properly r…
Browse files Browse the repository at this point in the history
…ender auto-hidden LayoutAnchorables
  • Loading branch information
Tim Cooke committed Jun 9, 2022
1 parent 22b9bb9 commit 05021c9
Showing 1 changed file with 71 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -44,6 +45,8 @@ public class LayoutAutoHideWindowControl : HwndHost, ILayoutControl
private Border _resizerGhost = null;
private Window _resizerWindowHost = null;
private Vector _initialStartPoint;
private List<FrameworkElement> _sizeChangedListeningControls;
private SizeChangedEventHandler _sizeChangedHandler;

#endregion fields

Expand All @@ -59,6 +62,7 @@ static LayoutAutoHideWindowControl()

internal LayoutAutoHideWindowControl()
{
_sizeChangedHandler = ViewboxZoomChanged;
}

#endregion Constructors
Expand Down Expand Up @@ -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();
Expand All @@ -124,6 +130,8 @@ internal void Show(LayoutAnchorControl anchor)

internal void Hide()
{
StopListeningToViewboxZoomChange();

if (_model == null) return;
_model.PropertyChanged -= _model_PropertyChanged;
RemoveInternalGrid();
Expand Down Expand Up @@ -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<Viewbox>().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<Viewbox>().SelectMany(x => new[] { x, x.Child }).OfType<FrameworkElement>().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 };
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
{
Expand Down

0 comments on commit 05021c9

Please sign in to comment.