瀏覽代碼

Fix arrange size with margins.

Fixes #432.
Steven Kirk 9 年之前
父節點
當前提交
75e13dc02b

+ 18 - 15
src/Perspex.Layout/Layoutable.cs

@@ -521,24 +521,27 @@ namespace Perspex.Layout
         {
             if (IsVisible)
             {
-                var originX = finalRect.X + Margin.Left;
-                var originY = finalRect.Y + Margin.Top;
-                var sizeMinusMargins = new Size(
-                    Math.Max(0, finalRect.Width - Margin.Left - Margin.Right),
-                    Math.Max(0, finalRect.Height - Margin.Top - Margin.Bottom));
+                var margin = Margin;
+                var originX = finalRect.X + margin.Left;
+                var originY = finalRect.Y + margin.Top;
+                var availableSizeMinusMargins = new Size(
+                    Math.Max(0, finalRect.Width - margin.Left - margin.Right),
+                    Math.Max(0, finalRect.Height - margin.Top - margin.Bottom));
                 var horizontalAlignment = HorizontalAlignment;
                 var verticalAlignment = VerticalAlignment;
-                var size = sizeMinusMargins;
+                var size = availableSizeMinusMargins;
                 var scale = GetLayoutScale();
 
                 if (horizontalAlignment != HorizontalAlignment.Stretch)
                 {
-                    size = size.WithWidth(Math.Min(size.Width, DesiredSize.Width));
+                    size = size.WithWidth(Math.Min(size.Width, DesiredSize.Width) 
+                        - margin.Left - margin.Right);
                 }
 
                 if (verticalAlignment != VerticalAlignment.Stretch)
                 {
-                    size = size.WithHeight(Math.Min(size.Height, DesiredSize.Height));
+                    size = size.WithHeight(Math.Min(size.Height, DesiredSize.Height)
+                        - margin.Top - margin.Bottom);
                 }
 
                 size = LayoutHelper.ApplyLayoutConstraints(this, size);
@@ -548,9 +551,9 @@ namespace Perspex.Layout
                     size = new Size(
                         Math.Ceiling(size.Width * scale) / scale, 
                         Math.Ceiling(size.Height * scale) / scale);
-                    sizeMinusMargins = new Size(
-                        Math.Ceiling(sizeMinusMargins.Width * scale) / scale, 
-                        Math.Ceiling(sizeMinusMargins.Height * scale) / scale);
+                    availableSizeMinusMargins = new Size(
+                        Math.Ceiling(availableSizeMinusMargins.Width * scale) / scale, 
+                        Math.Ceiling(availableSizeMinusMargins.Height * scale) / scale);
                 }
 
                 size = ArrangeOverride(size).Constrain(size);
@@ -559,10 +562,10 @@ namespace Perspex.Layout
                 {
                     case HorizontalAlignment.Center:
                     case HorizontalAlignment.Stretch:
-                        originX += (sizeMinusMargins.Width - size.Width) / 2;
+                        originX += (availableSizeMinusMargins.Width - size.Width) / 2;
                         break;
                     case HorizontalAlignment.Right:
-                        originX += sizeMinusMargins.Width - size.Width;
+                        originX += availableSizeMinusMargins.Width - size.Width;
                         break;
                 }
 
@@ -570,10 +573,10 @@ namespace Perspex.Layout
                 {
                     case VerticalAlignment.Center:
                     case VerticalAlignment.Stretch:
-                        originY += (sizeMinusMargins.Height - size.Height) / 2;
+                        originY += (availableSizeMinusMargins.Height - size.Height) / 2;
                         break;
                     case VerticalAlignment.Bottom:
-                        originY += sizeMinusMargins.Height - size.Height;
+                        originY += availableSizeMinusMargins.Height - size.Height;
                         break;
                 }
 

+ 62 - 2
tests/Perspex.Layout.UnitTests/ArrangeTests.cs

@@ -8,6 +8,56 @@ namespace Perspex.Layout.UnitTests
 {
     public class ArrangeTests
     {
+        [Fact]
+        public void Margin_Should_Be_Subtracted_From_Arrange_FinalSize()
+        {
+            var target = new TestControl
+            {
+                Width = 100,
+                Height = 100,
+                Margin = new Thickness(8),
+            };
+
+            target.Measure(Size.Infinity);
+            target.Arrange(new Rect(target.DesiredSize));
+
+            Assert.Equal(new Size(100, 100), target.ArrangeFinalSize);
+        }
+
+        [Fact]
+        public void ArrangeOverride_Receives_Desired_Size_When_Centered()
+        {
+            var target = new TestControl
+            {
+                MeasureResult = new Size(100, 100),
+                HorizontalAlignment = HorizontalAlignment.Center,
+                VerticalAlignment = VerticalAlignment.Center,
+                Margin = new Thickness(8),
+            };
+
+            target.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
+            target.Arrange(new Rect(0, 0, 200, 200));
+
+            Assert.Equal(new Size(100, 100), target.ArrangeFinalSize);
+        }
+
+        [Fact]
+        public void ArrangeOverride_Receives_Available_Size_Minus_Margin_When_Stretched()
+        {
+            var target = new TestControl
+            {
+                MeasureResult = new Size(100, 100),
+                HorizontalAlignment = HorizontalAlignment.Stretch,
+                VerticalAlignment = VerticalAlignment.Stretch,
+                Margin = new Thickness(8),
+            };
+
+            target.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
+            target.Arrange(new Rect(0, 0, 200, 200));
+
+            Assert.Equal(new Size(184, 184), target.ArrangeFinalSize);
+        }
+
         [Fact]
         public void Arrange_With_IsMeasureValid_False_Calls_Measure()
         {
@@ -32,14 +82,24 @@ namespace Perspex.Layout.UnitTests
             Assert.Equal(new Size(120, 120), target.MeasureConstraint);
         }
 
-        private class TestControl : Border
+        private class TestControl : Decorator
         {
             public Size MeasureConstraint { get; private set; }
 
+            public Size MeasureResult { get; set; }
+
+            public Size ArrangeFinalSize { get; private set; }
+
             protected override Size MeasureOverride(Size constraint)
             {
                 MeasureConstraint = constraint;
-                return base.MeasureOverride(constraint);
+                return MeasureResult;
+            }
+
+            protected override Size ArrangeOverride(Size finalSize)
+            {
+                ArrangeFinalSize = finalSize;
+                return base.ArrangeOverride(finalSize);
             }
         }
     }

+ 15 - 0
tests/Perspex.Layout.UnitTests/MeasureTests.cs

@@ -8,6 +8,21 @@ namespace Perspex.Layout.UnitTests
 {
     public class MeasureTests
     {
+        [Fact]
+        public void Margin_Should_Be_Included_In_DesiredSize()
+        {
+            var decorator = new Decorator
+            {
+                Width = 100,
+                Height = 100,
+                Margin = new Thickness(8),
+            };
+
+            decorator.Measure(Size.Infinity);
+
+            Assert.Equal(new Size(116, 116), decorator.DesiredSize);
+        }
+
         [Fact]
         public void Invalidating_Child_Should_Not_Invalidate_Parent()
         {