diff --git a/Perspex.UnitTests/StyleTests.cs b/Perspex.UnitTests/StyleTests.cs index 0c51bb4552..7662869578 100644 --- a/Perspex.UnitTests/StyleTests.cs +++ b/Perspex.UnitTests/StyleTests.cs @@ -119,7 +119,7 @@ namespace Perspex.UnitTests set { this.SetValue(FooProperty, value); } } - protected override Size MeasureContent(Size availableSize) + protected override Size MeasureOverride(Size availableSize) { throw new NotImplementedException(); } diff --git a/Perspex/Controls/Border.cs b/Perspex/Controls/Border.cs index a496d4c16c..b2c563df3b 100644 --- a/Perspex/Controls/Border.cs +++ b/Perspex/Controls/Border.cs @@ -42,16 +42,20 @@ namespace Perspex.Controls } } - protected override Size ArrangeContent(Size finalSize) + protected override Size ArrangeOverride(Size finalSize) { - return LayoutHelper.ArrangeDecorator( - this, - this.Content, - finalSize, - this.Padding + new Thickness(this.BorderThickness)); + Control content = this.Content; + + if (content != null) + { + Thickness padding = this.Padding + new Thickness(this.BorderThickness); + content.Arrange(new Rect(finalSize).Deflate(padding)); + } + + return finalSize; } - protected override Size MeasureContent(Size availableSize) + protected override Size MeasureOverride(Size availableSize) { return LayoutHelper.MeasureDecorator( this, diff --git a/Perspex/Controls/ContentControl.cs b/Perspex/Controls/ContentControl.cs index 4bc3d9b6aa..5cb7e47087 100644 --- a/Perspex/Controls/ContentControl.cs +++ b/Perspex/Controls/ContentControl.cs @@ -48,7 +48,7 @@ namespace Perspex.Controls } } - protected override Size ArrangeContent(Size finalSize) + protected override Size ArrangeOverride(Size finalSize) { Control child = ((IVisual)this).VisualChildren.SingleOrDefault() as Control; @@ -63,7 +63,7 @@ namespace Perspex.Controls } } - protected override Size MeasureContent(Size availableSize) + protected override Size MeasureOverride(Size availableSize) { if (this.Visibility != Visibility.Collapsed) { diff --git a/Perspex/Controls/ContentPresenter.cs b/Perspex/Controls/ContentPresenter.cs index 373c024633..4825ae175b 100644 --- a/Perspex/Controls/ContentPresenter.cs +++ b/Perspex/Controls/ContentPresenter.cs @@ -86,7 +86,7 @@ namespace Perspex.Controls } } - protected override Size ArrangeContent(Size finalSize) + protected override Size ArrangeOverride(Size finalSize) { Control child = ((IVisual)this).VisualChildren.SingleOrDefault() as Control; @@ -143,7 +143,7 @@ namespace Perspex.Controls return finalSize; } - protected override Size MeasureContent(Size availableSize) + protected override Size MeasureOverride(Size availableSize) { if (this.Visibility != Visibility.Collapsed) { diff --git a/Perspex/Controls/Control.cs b/Perspex/Controls/Control.cs index abcb75ef17..bbdfddfc5a 100644 --- a/Perspex/Controls/Control.cs +++ b/Perspex/Controls/Control.cs @@ -332,17 +332,13 @@ namespace Perspex.Controls public void Arrange(Rect rect) { - Thickness margin = this.Margin; - - ((IVisual)this).Bounds = new Rect( - new Point(rect.Position.X + margin.Left, rect.Position.Y + margin.Top), - this.ArrangeContent(rect.Size.Deflate(margin).Constrain(rect.Size))); + this.ArrangeCore(rect); } public void Measure(Size availableSize) { availableSize = availableSize.Deflate(this.Margin); - this.DesiredSize = this.MeasureContent(availableSize).Constrain(availableSize); + this.DesiredSize = this.MeasureCore(availableSize).Constrain(availableSize); } public void InvalidateArrange() @@ -365,12 +361,63 @@ namespace Perspex.Controls } } - protected virtual Size ArrangeContent(Size finalSize) + protected virtual void ArrangeCore(Rect finalRect) + { + double originX = finalRect.X + this.Margin.Left; + double originY = finalRect.Y + this.Margin.Top; + double sizeX = Math.Max(0, finalRect.Width - this.Margin.Left - this.Margin.Right); + double sizeY = Math.Max(0, finalRect.Height - this.Margin.Top - this.Margin.Bottom); + + if (this.HorizontalAlignment != HorizontalAlignment.Stretch) + { + sizeX = Math.Min(sizeX, this.DesiredSize.Value.Width); + } + + if (this.VerticalAlignment != VerticalAlignment.Stretch) + { + sizeY = Math.Min(sizeY, this.DesiredSize.Value.Height); + } + + Size taken = this.ArrangeOverride(new Size(sizeX, sizeY)); + + sizeX = Math.Min(taken.Width, sizeX); + sizeY = Math.Min(taken.Height, sizeY); + + switch (this.HorizontalAlignment) + { + case HorizontalAlignment.Center: + originX += (finalRect.Width - sizeX) / 2; + break; + case HorizontalAlignment.Right: + originX += finalRect.Width - sizeX; + break; + } + + switch (this.VerticalAlignment) + { + case VerticalAlignment.Center: + originY += (finalRect.Height - sizeY) / 2; + break; + case VerticalAlignment.Bottom: + originY += finalRect.Height - sizeY; + break; + } + + ((IVisual)this).Bounds = new Rect(originX, originY, sizeX, sizeY); + } + + protected virtual Size ArrangeOverride(Size finalSize) { return finalSize; } - protected virtual Size MeasureContent(Size availableSize) + protected virtual Size MeasureCore(Size availableSize) + { + availableSize = availableSize.Deflate(this.Margin); + return this.MeasureOverride(availableSize); + } + + protected virtual Size MeasureOverride(Size availableSize) { return new Size(); } diff --git a/Perspex/Controls/Decorator.cs b/Perspex/Controls/Decorator.cs index 9e9d77cf71..cd2e648f8e 100644 --- a/Perspex/Controls/Decorator.cs +++ b/Perspex/Controls/Decorator.cs @@ -64,12 +64,19 @@ namespace Perspex.Controls } } - protected override Size ArrangeContent(Size finalSize) + protected override Size ArrangeOverride(Size finalSize) { - return LayoutHelper.ArrangeDecorator(this, this.Content, finalSize, this.Padding); + Control content = this.Content; + + if (content != null) + { + content.Arrange(new Rect(finalSize).Deflate(this.Padding)); + } + + return finalSize; } - protected override Size MeasureContent(Size availableSize) + protected override Size MeasureOverride(Size availableSize) { return LayoutHelper.MeasureDecorator(this, this.Content, availableSize, this.Padding); } diff --git a/Perspex/Controls/Grid.cs b/Perspex/Controls/Grid.cs index 57d5c8bfb5..4cc626b139 100644 --- a/Perspex/Controls/Grid.cs +++ b/Perspex/Controls/Grid.cs @@ -88,7 +88,7 @@ namespace Perspex.Controls element.SetValue(RowSpanProperty, value); } - protected override Size MeasureContent(Size constraint) + protected override Size MeasureOverride(Size constraint) { Size totalSize = constraint; int colCount = this.ColumnDefinitions.Count; @@ -379,7 +379,7 @@ namespace Perspex.Controls return new Size(gridSizeX, gridSizeY); } - protected override Size ArrangeContent(Size finalSize) + protected override Size ArrangeOverride(Size finalSize) { int colCount = this.ColumnDefinitions.Count; int rowCount = this.RowDefinitions.Count; diff --git a/Perspex/Controls/StackPanel.cs b/Perspex/Controls/StackPanel.cs index 9a7ab81318..7c84004764 100644 --- a/Perspex/Controls/StackPanel.cs +++ b/Perspex/Controls/StackPanel.cs @@ -38,7 +38,7 @@ namespace Perspex.Controls set { this.SetValue(OrientationProperty, value); } } - protected override Size MeasureContent(Size availableSize) + protected override Size MeasureOverride(Size availableSize) { if (this.Visibility != Visibility.Collapsed) { @@ -97,7 +97,7 @@ namespace Perspex.Controls return new Size(); } - protected override Size ArrangeContent(Size finalSize) + protected override Size ArrangeOverride(Size finalSize) { double arrangedWidth = finalSize.Width; double arrangedHeight = finalSize.Height; diff --git a/Perspex/Controls/TextBlock.cs b/Perspex/Controls/TextBlock.cs index 180ae42285..7d0e7bdd99 100644 --- a/Perspex/Controls/TextBlock.cs +++ b/Perspex/Controls/TextBlock.cs @@ -67,7 +67,7 @@ namespace Perspex.Controls } } - protected override Size MeasureContent(Size availableSize) + protected override Size MeasureOverride(Size availableSize) { if (this.Visibility != Visibility.Collapsed) { diff --git a/Perspex/Layout/LayoutHelper.cs b/Perspex/Layout/LayoutHelper.cs index 94b15eceee..8665897b31 100644 --- a/Perspex/Layout/LayoutHelper.cs +++ b/Perspex/Layout/LayoutHelper.cs @@ -47,91 +47,5 @@ namespace Perspex.Layout return new Size(width, height); } - - public static Size ArrangeDecorator( - Control decorator, - Control content, - Size finalSize, - Thickness padding) - { - if (content != null) - { - Rect childRect = AlignChild( - new Rect(finalSize).Deflate(padding), - content.DesiredSize.Value, - content.HorizontalAlignment, - content.VerticalAlignment); - - content.Arrange(childRect); - } - - return finalSize; - } - - public static Rect AlignChild( - Rect parentRect, - Size desiredSize, - HorizontalAlignment horizontalAlignment, - VerticalAlignment verticalAlignment) - { - double x; - double y; - double width; - double height; - - switch (horizontalAlignment) - { - case HorizontalAlignment.Stretch: - width = parentRect.Width; - x = parentRect.X; - break; - - case HorizontalAlignment.Left: - width = desiredSize.Width; - x = parentRect.X; - break; - - case HorizontalAlignment.Center: - width = desiredSize.Width; - x = (parentRect.Width - width) / 2; - break; - - case HorizontalAlignment.Right: - width = desiredSize.Width; - x = parentRect.Right - width; - break; - - default: - throw new InvalidOperationException("Invalid HorizontalAlignment."); - } - - switch (verticalAlignment) - { - case VerticalAlignment.Stretch: - height = parentRect.Height; - y = parentRect.Y; - break; - - case VerticalAlignment.Top: - height = desiredSize.Height; - y = parentRect.Y; - break; - - case VerticalAlignment.Center: - height = desiredSize.Height; - y = (parentRect.Height - height) / 2; - break; - - case VerticalAlignment.Bottom: - height = desiredSize.Height; - y = parentRect.Bottom - height; - break; - - default: - throw new InvalidOperationException("Invalid VerticalAlignment."); - } - - return new Rect(x, y, width, height); - } } } diff --git a/Perspex/Shapes/Rectangle.cs b/Perspex/Shapes/Rectangle.cs index d62809f0fb..c386c14922 100644 --- a/Perspex/Shapes/Rectangle.cs +++ b/Perspex/Shapes/Rectangle.cs @@ -19,15 +19,15 @@ namespace Perspex.Shapes get { return new RectangleGeometry(new Rect(size)); } } - protected override Size MeasureContent(Size availableSize) + protected override Size MeasureOverride(Size availableSize) { return new Size(this.Width, this.Height); } - protected override Size ArrangeContent(Size finalSize) + protected override Size ArrangeOverride(Size finalSize) { this.size = finalSize; - return base.ArrangeContent(finalSize); + return base.ArrangeOverride(finalSize); } } } diff --git a/Perspex/Shapes/Shape.cs b/Perspex/Shapes/Shape.cs index 068b5e8520..b5d0c8b140 100644 --- a/Perspex/Shapes/Shape.cs +++ b/Perspex/Shapes/Shape.cs @@ -58,7 +58,7 @@ namespace Perspex.Shapes set { this.SetValue(StrokeThicknessProperty, value); } } - protected override Size MeasureContent(Size availableSize) + protected override Size MeasureOverride(Size availableSize) { Rect shapeBounds = this.RenderedGeometry.Bounds; double width = this.Width; diff --git a/TestFiles/Direct2D1/Controls/Border/Border_Centers_Content_Horizontally.expected.png b/TestFiles/Direct2D1/Controls/Border/Border_Centers_Content_Horizontally.expected.png index c893b695e5..18ecd01c7a 100644 Binary files a/TestFiles/Direct2D1/Controls/Border/Border_Centers_Content_Horizontally.expected.png and b/TestFiles/Direct2D1/Controls/Border/Border_Centers_Content_Horizontally.expected.png differ diff --git a/TestFiles/Direct2D1/Controls/Border/Border_Centers_Content_Vertically.expected.png b/TestFiles/Direct2D1/Controls/Border/Border_Centers_Content_Vertically.expected.png index 725128b2c9..40d0de862e 100644 Binary files a/TestFiles/Direct2D1/Controls/Border/Border_Centers_Content_Vertically.expected.png and b/TestFiles/Direct2D1/Controls/Border/Border_Centers_Content_Vertically.expected.png differ