diff --git a/src/Perspex.Controls/LayoutTransformControl.cs b/src/Perspex.Controls/LayoutTransformControl.cs
index 7c7be3c6f8..74b2c44a45 100644
--- a/src/Perspex.Controls/LayoutTransformControl.cs
+++ b/src/Perspex.Controls/LayoutTransformControl.cs
@@ -9,7 +9,7 @@ using Perspex.Controls.Primitives;
using Perspex.Media;
using Perspex.VisualTree;
using System;
-//using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reactive.Linq;
@@ -32,99 +32,61 @@ namespace Perspex.Controls
set { SetValue(LayoutTransformProperty, value); }
}
- ///
- /// Acceptable difference between two doubles.
- ///
- private const double AcceptableDelta = 0.0001;
-
- ///
- /// Number of decimals to round the Matrix to.
- ///
- private const int DecimalsAfterRound = 4;
-
- ///
- /// RenderTransform/MatrixTransform applied to TransformRoot.
- ///
- private MatrixTransform _matrixTransform;
-
- ///
- /// Transformation matrix corresponding to _matrixTransform.
- ///
- private Matrix _transformation;
+ public Control TransformRoot => _transformRoot ??
+ (_transformRoot = this.GetVisualChildren().OfType().FirstOrDefault());
///
- /// Actual DesiredSize of Child element (the value it returned from its MeasureOverride method).
+ /// Provides the behavior for the "Arrange" pass of layout.
///
- private Size _childActualSize = Size.Empty;
-
- private Control _transformRoot;
-
- public Control TransformRoot => _transformRoot ??
- (_transformRoot = this.GetVisualChildren().OfType().FirstOrDefault());
-
- private IDisposable _transformChangedEvent = null;
-
- private void OnLayoutTransformChanged(PerspexPropertyChangedEventArgs e)
+ /// The final area within the parent that this element should use to arrange itself and its children.
+ /// The actual size used.
+ protected override Size ArrangeOverride(Size finalSize)
{
- var newTransform = e.NewValue as Transform;
-
- if (_transformChangedEvent != null)
+ if (TransformRoot == null || LayoutTransform == null)
{
- _transformChangedEvent.Dispose();
- _transformChangedEvent = null;
+ return base.ArrangeOverride(finalSize);
}
- if (newTransform != null)
+ // Determine the largest available size after the transformation
+ Size finalSizeTransformed = ComputeLargestTransformedSize(finalSize);
+ if (IsSizeSmaller(finalSizeTransformed, TransformRoot.DesiredSize))
{
- _transformChangedEvent = Observable.FromEventPattern(
- v => newTransform.Changed += v, v => newTransform.Changed -= v)
- .Subscribe(onNext: v => ApplyLayoutTransform());
+ // Some elements do not like being given less space than they asked for (ex: TextBlock)
+ // Bump the working size up to do the right thing by them
+ finalSizeTransformed = TransformRoot.DesiredSize;
}
- ApplyLayoutTransform();
- }
-
- ///
- /// Builds the visual tree for the LayoutTransformerControl when a new
- /// template is applied.
- ///
- protected override void OnTemplateApplied(TemplateAppliedEventArgs e)
- {
- base.OnTemplateApplied(e);
+ // Transform the working size to find its width/height
+ Rect transformedRect = new Rect(0, 0, finalSizeTransformed.Width, finalSizeTransformed.Height).TransformToAABB(_transformation);
+ // Create the Arrange rect to center the transformed content
+ Rect finalRect = new Rect(
+ -transformedRect.X + ((finalSize.Width - transformedRect.Width) / 2),
+ -transformedRect.Y + ((finalSize.Height - transformedRect.Height) / 2),
+ finalSizeTransformed.Width,
+ finalSizeTransformed.Height);
- _matrixTransform = new MatrixTransform();
+ // Perform an Arrange on TransformRoot (containing Child)
+ Size arrangedsize;
+ TransformRoot.Arrange(finalRect);
+ arrangedsize = TransformRoot.Bounds.Size;
- if (null != TransformRoot)
+ // This is the first opportunity under Silverlight to find out the Child's true DesiredSize
+ if (IsSizeSmaller(finalSizeTransformed, arrangedsize) && (Size.Empty == _childActualSize))
{
- TransformRoot.RenderTransform = _matrixTransform;
- TransformRoot.TransformOrigin = new RelativePoint(0, 0, RelativeUnit.Absolute);
+ //// Unfortunately, all the work so far is invalid because the wrong DesiredSize was used
+ //// Make a note of the actual DesiredSize
+ //_childActualSize = arrangedsize;
+ //// Force a new measure/arrange pass
+ //InvalidateMeasure();
}
-
- ApplyLayoutTransform();
- }
-
- ///
- /// Applies the layout transform on the LayoutTransformerControl content.
- ///
- ///
- /// Only used in advanced scenarios (like animating the LayoutTransform).
- /// Should be used to notify the LayoutTransformer control that some aspect
- /// of its Transform property has changed.
- ///
- private void ApplyLayoutTransform()
- {
- if (LayoutTransform == null) return;
-
- // Get the transform matrix and apply it
- _transformation = RoundMatrix(LayoutTransform.Value, DecimalsAfterRound);
-
- if (null != _matrixTransform)
+ else
{
- _matrixTransform.Matrix = _transformation;
+ // Clear the "need to measure/arrange again" flag
+ _childActualSize = Size.Empty;
}
- // New transform means re-layout is necessary
- InvalidateMeasure();
+ // Return result to perform the transformation
+ return finalSize;
}
///
@@ -165,57 +127,100 @@ namespace Perspex.Controls
}
///
- /// Provides the behavior for the "Arrange" pass of layout.
+ /// Builds the visual tree for the LayoutTransformerControl when a new
+ /// template is applied.
///
- /// The final area within the parent that this element should use to arrange itself and its children.
- /// The actual size used.
- protected override Size ArrangeOverride(Size finalSize)
+ protected override void OnTemplateApplied(TemplateAppliedEventArgs e)
{
- if (TransformRoot == null || LayoutTransform == null)
- {
- return base.ArrangeOverride(finalSize);
- }
+ base.OnTemplateApplied(e);
- // Determine the largest available size after the transformation
- Size finalSizeTransformed = ComputeLargestTransformedSize(finalSize);
- if (IsSizeSmaller(finalSizeTransformed, TransformRoot.DesiredSize))
+ _matrixTransform = new MatrixTransform();
+
+ if (null != TransformRoot)
{
- // Some elements do not like being given less space than they asked for (ex: TextBlock)
- // Bump the working size up to do the right thing by them
- finalSizeTransformed = TransformRoot.DesiredSize;
+ TransformRoot.RenderTransform = _matrixTransform;
+ TransformRoot.TransformOrigin = new RelativePoint(0, 0, RelativeUnit.Absolute);
}
- // Transform the working size to find its width/height
- Rect transformedRect = new Rect(0, 0, finalSizeTransformed.Width, finalSizeTransformed.Height).TransformToAABB(_transformation);
- // Create the Arrange rect to center the transformed content
- Rect finalRect = new Rect(
- -transformedRect.X + ((finalSize.Width - transformedRect.Width) / 2),
- -transformedRect.Y + ((finalSize.Height - transformedRect.Height) / 2),
- finalSizeTransformed.Width,
- finalSizeTransformed.Height);
+ ApplyLayoutTransform();
+ }
- // Perform an Arrange on TransformRoot (containing Child)
- Size arrangedsize;
- TransformRoot.Arrange(finalRect);
- arrangedsize = TransformRoot.Bounds.Size;
+ ///
+ /// Acceptable difference between two doubles.
+ ///
+ private const double AcceptableDelta = 0.0001;
- // This is the first opportunity under Silverlight to find out the Child's true DesiredSize
- if (IsSizeSmaller(finalSizeTransformed, arrangedsize) && (Size.Empty == _childActualSize))
- {
- //// Unfortunately, all the work so far is invalid because the wrong DesiredSize was used
- //// Make a note of the actual DesiredSize
- //_childActualSize = arrangedsize;
- //// Force a new measure/arrange pass
- //InvalidateMeasure();
- }
- else
+ ///
+ /// Number of decimals to round the Matrix to.
+ ///
+ private const int DecimalsAfterRound = 4;
+
+ ///
+ /// Actual DesiredSize of Child element (the value it returned from its MeasureOverride method).
+ ///
+ private Size _childActualSize = Size.Empty;
+
+ ///
+ /// RenderTransform/MatrixTransform applied to TransformRoot.
+ ///
+ private MatrixTransform _matrixTransform;
+
+ ///
+ /// Transformation matrix corresponding to _matrixTransform.
+ ///
+ private Matrix _transformation;
+ private IDisposable _transformChangedEvent = null;
+ private Control _transformRoot;
+ ///
+ /// Returns true if Size a is smaller than Size b in either dimension.
+ ///
+ /// Second Size.
+ /// First Size.
+ /// True if Size a is smaller than Size b in either dimension.
+ private static bool IsSizeSmaller(Size a, Size b)
+ {
+ return (a.Width + AcceptableDelta < b.Width) || (a.Height + AcceptableDelta < b.Height);
+ }
+
+ ///
+ /// Rounds the non-offset elements of a Matrix to avoid issues due to floating point imprecision.
+ ///
+ /// Matrix to round.
+ /// Number of decimal places to round to.
+ /// Rounded Matrix.
+ private static Matrix RoundMatrix(Matrix matrix, int decimals)
+ {
+ return new Matrix(
+ Math.Round(matrix.M11, decimals),
+ Math.Round(matrix.M12, decimals),
+ Math.Round(matrix.M21, decimals),
+ Math.Round(matrix.M22, decimals),
+ matrix.M31,
+ matrix.M32);
+ }
+
+ ///
+ /// Applies the layout transform on the LayoutTransformerControl content.
+ ///
+ ///
+ /// Only used in advanced scenarios (like animating the LayoutTransform).
+ /// Should be used to notify the LayoutTransformer control that some aspect
+ /// of its Transform property has changed.
+ ///
+ private void ApplyLayoutTransform()
+ {
+ if (LayoutTransform == null) return;
+
+ // Get the transform matrix and apply it
+ _transformation = RoundMatrix(LayoutTransform.Value, DecimalsAfterRound);
+
+ if (null != _matrixTransform)
{
- // Clear the "need to measure/arrange again" flag
- _childActualSize = Size.Empty;
+ _matrixTransform.Matrix = _transformation;
}
- // Return result to perform the transformation
- return finalSize;
+ // New transform means re-layout is necessary
+ InvalidateMeasure();
}
///
@@ -361,32 +366,24 @@ namespace Perspex.Controls
return computedSize;
}
- ///
- /// Returns true if Size a is smaller than Size b in either dimension.
- ///
- /// Second Size.
- /// First Size.
- /// True if Size a is smaller than Size b in either dimension.
- private static bool IsSizeSmaller(Size a, Size b)
+ private void OnLayoutTransformChanged(PerspexPropertyChangedEventArgs e)
{
- return (a.Width + AcceptableDelta < b.Width) || (a.Height + AcceptableDelta < b.Height);
- }
+ var newTransform = e.NewValue as Transform;
- ///
- /// Rounds the non-offset elements of a Matrix to avoid issues due to floating point imprecision.
- ///
- /// Matrix to round.
- /// Number of decimal places to round to.
- /// Rounded Matrix.
- private static Matrix RoundMatrix(Matrix matrix, int decimals)
- {
- return new Matrix(
- Math.Round(matrix.M11, decimals),
- Math.Round(matrix.M12, decimals),
- Math.Round(matrix.M21, decimals),
- Math.Round(matrix.M22, decimals),
- matrix.M31,
- matrix.M32);
+ if (_transformChangedEvent != null)
+ {
+ _transformChangedEvent.Dispose();
+ _transformChangedEvent = null;
+ }
+
+ if (newTransform != null)
+ {
+ _transformChangedEvent = Observable.FromEventPattern(
+ v => newTransform.Changed += v, v => newTransform.Changed -= v)
+ .Subscribe(onNext: v => ApplyLayoutTransform());
+ }
+
+ ApplyLayoutTransform();
}
}
}
\ No newline at end of file
diff --git a/tests/Perspex.Controls.UnitTests/LayoutTransformControlTests.cs b/tests/Perspex.Controls.UnitTests/LayoutTransformControlTests.cs
index 946fb9e8b9..10c4caa381 100644
--- a/tests/Perspex.Controls.UnitTests/LayoutTransformControlTests.cs
+++ b/tests/Perspex.Controls.UnitTests/LayoutTransformControlTests.cs
@@ -223,20 +223,17 @@ namespace Perspex.Controls.UnitTests
{
LayoutTransform = transform,
Template = new FuncControlTemplate(
- p =>
- {
- var c = new ContentPresenter() { Content = p.Content };
- //we need to force create visual child
- //so the measure after is correct
- c.UpdateChild();
- return c;
- })
+ p => new ContentPresenter() { Content = p.Content })
};
lt.Content = new Rectangle() { Width = width, Height = height };
lt.ApplyTemplate();
+ //we need to force create visual child
+ //so the measure after is correct
+ (lt.Presenter as ContentPresenter).UpdateChild();
+
Assert.NotNull(lt.Presenter?.Child);
lt.Measure(Size.Infinity);