/// <summary> /// Provides the behavior for the "Arrange" pass of layout. /// </summary> /// <param name="finalSize">The final area within the parent that this element should use to arrange itself and its children.</param> /// <returns>The actual size used.</returns> /// <remarks> /// Using the WPF paramater name finalSize instead of Silverlight's finalSize for clarity /// </remarks> protected override Size ArrangeOverride(Size finalSize) { FrameworkElement child = Child; if ((null == _transformRoot) || (null == child)) { // No child, use whatever was given return(finalSize); } DiagnosticWriteLine("ArrangeOverride < " + finalSize); // Determine the largest available size after the transformation Size finalSizeTransformed = ComputeLargestTransformedSize(finalSize); if (IsSizeSmaller(finalSizeTransformed, _transformRoot.DesiredSize)) { // 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 DiagnosticWriteLine(" Replacing finalSizeTransformed with larger _transformRoot.DesiredSize"); finalSizeTransformed = _transformRoot.DesiredSize; } DiagnosticWriteLine(" finalSizeTransformed = " + finalSizeTransformed); // Transform the working size to find its width/height Rect transformedRect = RectTransform(new Rect(0, 0, finalSizeTransformed.Width, finalSizeTransformed.Height), _transformation); // Create the Arrange rect to center the transformed content Rect finalRect = new Rect( -transformedRect.Left + ((finalSize.Width - transformedRect.Width) / 2), -transformedRect.Top + ((finalSize.Height - transformedRect.Height) / 2), finalSizeTransformed.Width, finalSizeTransformed.Height); // Perform an Arrange on _transformRoot (containing Child) DiagnosticWriteLine(" _transformRoot.Arrange < " + finalRect); _transformRoot.Arrange(finalRect); DiagnosticWriteLine(" Child.RenderSize = " + child.RenderSize); // This is the first opportunity under Silverlight to find out the Child's true DesiredSize if (IsSizeSmaller(finalSizeTransformed, child.RenderSize) && (Size.Empty == _childActualSize)) { // Unfortunately, all the work so far is invalid because the wrong DesiredSize was used DiagnosticWriteLine(" finalSizeTransformed smaller than Child.RenderSize"); // Make a note of the actual DesiredSize _childActualSize = new Size(child.ActualWidth, child.ActualHeight); DiagnosticWriteLine(" _childActualSize = " + _childActualSize); // Force a new measure/arrange pass InvalidateMeasure(); } else { // Clear the "need to measure/arrange again" flag _childActualSize = Size.Empty; } DiagnosticWriteLine(" _transformRoot.RenderSize = " + _transformRoot.RenderSize); // Return result to perform the transformation DiagnosticWriteLine("ArrangeOverride > " + finalSize); return(finalSize); }