From fedae81cb884e3fc9b595c73e633ad44a4757575 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 11 Apr 2018 12:08:33 +0100 Subject: [PATCH 01/11] partial fix for 1436. --- src/Avalonia.Controls/Border.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Border.cs b/src/Avalonia.Controls/Border.cs index 06ad8a4837..2dc42bd923 100644 --- a/src/Avalonia.Controls/Border.cs +++ b/src/Avalonia.Controls/Border.cs @@ -43,7 +43,8 @@ namespace Avalonia.Controls /// static Border() { - AffectsRender(BackgroundProperty, BorderBrushProperty); + AffectsRender(BackgroundProperty, BorderBrushProperty, BorderThicknessProperty); + AffectsMeasure(BorderThicknessProperty); } /// From 272939464eaa6341b718ec8621967df29bc2e826 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 12 Apr 2018 23:28:08 +0200 Subject: [PATCH 02/11] Need to press a button to click it! Only raise a `Button` click event on pointer release when the button has been pressed first! --- src/Avalonia.Controls/Button.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs index 4922761a84..fa69d72d67 100644 --- a/src/Avalonia.Controls/Button.cs +++ b/src/Avalonia.Controls/Button.cs @@ -245,7 +245,7 @@ namespace Avalonia.Controls { base.OnPointerReleased(e); - if (e.MouseButton == MouseButton.Left) + if (IsPressed && e.MouseButton == MouseButton.Left) { e.Device.Capture(null); IsPressed = false; From ef44f2b9083b81289889da46cc2f84159b94b6bd Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 12 Apr 2018 23:28:21 +0200 Subject: [PATCH 03/11] Handle the click that opens a DropDown. --- src/Avalonia.Controls/DropDown.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Avalonia.Controls/DropDown.cs b/src/Avalonia.Controls/DropDown.cs index a7ea2da4a4..932179028e 100644 --- a/src/Avalonia.Controls/DropDown.cs +++ b/src/Avalonia.Controls/DropDown.cs @@ -164,6 +164,7 @@ namespace Avalonia.Controls else { IsDropDownOpen = !IsDropDownOpen; + e.Handled = true; } } base.OnPointerPressed(e); From 27680c35e9355abe3512890e40d36cd6eebb1a28 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 12 Apr 2018 23:25:26 +0100 Subject: [PATCH 04/11] [Border] CornerRadius affects render. --- src/Avalonia.Controls/Border.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Border.cs b/src/Avalonia.Controls/Border.cs index 2dc42bd923..d90f292183 100644 --- a/src/Avalonia.Controls/Border.cs +++ b/src/Avalonia.Controls/Border.cs @@ -43,7 +43,7 @@ namespace Avalonia.Controls /// static Border() { - AffectsRender(BackgroundProperty, BorderBrushProperty, BorderThicknessProperty); + AffectsRender(BackgroundProperty, BorderBrushProperty, BorderThicknessProperty, CornerRadiusProperty); AffectsMeasure(BorderThicknessProperty); } From 653372009aa77e6e05d84ac885cd48106790cc89 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 12 Apr 2018 23:26:06 +0100 Subject: [PATCH 05/11] [ContentPresenter] BorderThickness affects render and measure. --- src/Avalonia.Controls/Presenters/ContentPresenter.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Avalonia.Controls/Presenters/ContentPresenter.cs b/src/Avalonia.Controls/Presenters/ContentPresenter.cs index 6acbc047ae..d2fb838657 100644 --- a/src/Avalonia.Controls/Presenters/ContentPresenter.cs +++ b/src/Avalonia.Controls/Presenters/ContentPresenter.cs @@ -92,6 +92,9 @@ namespace Avalonia.Controls.Presenters ContentProperty.Changed.AddClassHandler(x => x.ContentChanged); ContentTemplateProperty.Changed.AddClassHandler(x => x.ContentChanged); TemplatedParentProperty.Changed.AddClassHandler(x => x.TemplatedParentChanged); + + AffectsRender(BorderThicknessProperty); + AffectsMeasure(BorderThicknessProperty); } /// From 2d1ab0a106f180f154ad5d680320f60950eaf19f Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 13 Apr 2018 14:36:46 +0200 Subject: [PATCH 06/11] Only update clip bounds when ClipToBounds = true. Fixes #1436 --- .../Rendering/SceneGraph/SceneBuilder.cs | 4 +- .../Rendering/SceneGraph/SceneBuilderTests.cs | 48 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs index 6005ee8b8f..799380cb85 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs @@ -167,7 +167,9 @@ namespace Avalonia.Rendering.SceneGraph using (context.PushPostTransform(m)) using (context.PushTransformContainer()) { - var clipBounds = bounds.TransformToAABB(contextImpl.Transform).Intersect(clip); + var clipBounds = clipToBounds ? + bounds.TransformToAABB(contextImpl.Transform).Intersect(clip) : + clip; forceRecurse = forceRecurse || node.ClipBounds != clipBounds || diff --git a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs index 2ada7bdbba..df4584518e 100644 --- a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs @@ -83,6 +83,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph Margin = new Thickness(10, 20, 30, 40), Child = canvas = new Canvas { + ClipToBounds = true, Background = Brushes.AliceBlue, } } @@ -129,6 +130,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph (border = new Border { Background = Brushes.AliceBlue, + ClipToBounds = true, Width = 100, Height = 100, [Canvas.LeftProperty] = 50, @@ -173,6 +175,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph (border = new Border { Background = Brushes.AliceBlue, + ClipToBounds = true, Width = 100, Height = 100, [Canvas.LeftProperty] = 50, @@ -254,6 +257,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph Margin = new Thickness(24, 26), Child = target = new Border { + ClipToBounds = true, Margin = new Thickness(26, 24), Width = 100, Height = 100, @@ -515,6 +519,50 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph } } + [Fact] + public void Should_Update_ClipBounds_For_Negative_Margin() + { + using (TestApplication()) + { + Decorator decorator; + Border border; + var tree = new TestRoot + { + Width = 100, + Height = 100, + Child = decorator = new Decorator + { + Margin = new Thickness(0, 10, 0, 0), + Child = border = new Border + { + Background = Brushes.Red, + ClipToBounds = true, + Margin = new Thickness(0, -5, 0, 0), + } + } + }; + + var layout = AvaloniaLocator.Current.GetService(); + layout.ExecuteInitialLayoutPass(tree); + + var scene = new Scene(tree); + var sceneBuilder = new SceneBuilder(); + sceneBuilder.UpdateAll(scene); + + var borderNode = scene.FindNode(border); + Assert.Equal(new Rect(0, 5, 100, 95), borderNode.ClipBounds); + + border.Margin = new Thickness(0, -8, 0, 0); + layout.ExecuteLayoutPass(); + + scene = scene.CloneScene(); + sceneBuilder.Update(scene, border); + + borderNode = scene.FindNode(border); + Assert.Equal(new Rect(0, 2, 100, 98), borderNode.ClipBounds); + } + } + [Fact] public void Should_Update_Descendent_Tranform_When_Margin_Changed() { From 67003577a0dc9c7aac2326c527f001d075ef9823 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 13 Apr 2018 13:40:56 +0100 Subject: [PATCH 07/11] Add failing unit tests for border and content presenter. --- .../BorderTests.cs | 23 +++++++++++++++++++ .../ContentPresenterTests_Layout.cs | 23 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/BorderTests.cs b/tests/Avalonia.Controls.UnitTests/BorderTests.cs index 3660a7b4ca..4f58e5e780 100644 --- a/tests/Avalonia.Controls.UnitTests/BorderTests.cs +++ b/tests/Avalonia.Controls.UnitTests/BorderTests.cs @@ -20,5 +20,28 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(new Size(20, 20), target.DesiredSize); } + + [Fact] + public void Child_Should_Arrange_With_Zero_Height_Width_If_Padding_Greater_Than_Child_Size() + { + Border content; + + var target = new Border + { + Padding = new Thickness(6), + MaxHeight = 12, + MaxWidth = 12, + Content = content = new Border + { + Height = 0, + Width = 0 + } + }; + + target.Measure(new Size(100, 100)); + target.Arrange(new Rect(0, 0, 100, 100)); + + Assert.Equal(new Rect(0, 0, 0, 0), content.Bounds); + } } } diff --git a/tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Layout.cs b/tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Layout.cs index b3c617c4ab..d88716279a 100644 --- a/tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Layout.cs +++ b/tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Layout.cs @@ -210,5 +210,28 @@ namespace Avalonia.Controls.UnitTests.Presenters Assert.Equal(new Rect(84, 0, 16, 16), content.Bounds); } + + [Fact] + public void Child_Arrange_With_Zero_Height_When_Padding_Height_Greater_Than_Child_Height() + { + Border content; + var target = new ContentPresenter + { + Padding = 32, + MaxHeight = 32, + MaxWidth = 32, + Content = content = new Border + { + MinWidth = 16, + MinHeight = 16, + }, + }; + + target.UpdateChild(); + target.Measure(new Size(100, 100)); + target.Arrange(new Rect(0, 0, 100, 100)); + + Assert.Equal(new Rect(0, 0, 0, 0), content.Bounds); + } } } \ No newline at end of file From a98d289af8abcf50e3b29bdd589b92a6e2ccd72a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 13 Apr 2018 13:42:36 +0100 Subject: [PATCH 08/11] Add arrange fix for border and content presenter. --- src/Avalonia.Controls/Border.cs | 3 ++- src/Avalonia.Controls/Presenters/ContentPresenter.cs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Controls/Border.cs b/src/Avalonia.Controls/Border.cs index 06ad8a4837..6bceba3401 100644 --- a/src/Avalonia.Controls/Border.cs +++ b/src/Avalonia.Controls/Border.cs @@ -111,7 +111,8 @@ namespace Avalonia.Controls if (Child != null) { var padding = Padding + BorderThickness; - Child.Arrange(new Rect(finalSize).Deflate(padding)); + var arrangeRect = new Rect(finalSize).Deflate(padding); + Child.Arrange(new Rect(arrangeRect.X, arrangeRect.Y, Math.Max(0, arrangeRect.Width), Math.Max(0, arrangeRect.Height))); } _borderRenderHelper.Update(finalSize, BorderThickness, CornerRadius); diff --git a/src/Avalonia.Controls/Presenters/ContentPresenter.cs b/src/Avalonia.Controls/Presenters/ContentPresenter.cs index 6acbc047ae..1c5883d980 100644 --- a/src/Avalonia.Controls/Presenters/ContentPresenter.cs +++ b/src/Avalonia.Controls/Presenters/ContentPresenter.cs @@ -386,7 +386,7 @@ namespace Avalonia.Controls.Presenters if (verticalContentAlignment != VerticalAlignment.Stretch) { - size = size.WithHeight(Math.Min(size.Height, DesiredSize.Height - padding.Top - padding.Bottom)); + size = size.WithHeight(Math.Min(size.Height, DesiredSize.Height - padding.Top - padding.Bottom)); } if (useLayoutRounding) @@ -425,7 +425,7 @@ namespace Avalonia.Controls.Presenters originY = Math.Floor(originY * scale) / scale; } - Child.Arrange(new Rect(originX, originY, size.Width, size.Height)); + Child.Arrange(new Rect(originX, originY, Math.Max(0, size.Width), Math.Max(0, size.Height))); return finalSize; } From 2c9f3ede54cf7aca8c2fdd8b1e1af437c81aa805 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 13 Apr 2018 14:12:51 +0100 Subject: [PATCH 09/11] fix tests and and fixes. --- src/Avalonia.Controls/Border.cs | 5 ++--- tests/Avalonia.Controls.UnitTests/BorderTests.cs | 7 +++---- .../Presenters/ContentPresenterTests_Layout.cs | 12 +++++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Avalonia.Controls/Border.cs b/src/Avalonia.Controls/Border.cs index 6bceba3401..e6846978dc 100644 --- a/src/Avalonia.Controls/Border.cs +++ b/src/Avalonia.Controls/Border.cs @@ -110,9 +110,8 @@ namespace Avalonia.Controls { if (Child != null) { - var padding = Padding + BorderThickness; - var arrangeRect = new Rect(finalSize).Deflate(padding); - Child.Arrange(new Rect(arrangeRect.X, arrangeRect.Y, Math.Max(0, arrangeRect.Width), Math.Max(0, arrangeRect.Height))); + var padding = Padding + BorderThickness; + Child.Arrange(new Rect(finalSize).Deflate(padding)); } _borderRenderHelper.Update(finalSize, BorderThickness, CornerRadius); diff --git a/tests/Avalonia.Controls.UnitTests/BorderTests.cs b/tests/Avalonia.Controls.UnitTests/BorderTests.cs index 4f58e5e780..9d6c838bc3 100644 --- a/tests/Avalonia.Controls.UnitTests/BorderTests.cs +++ b/tests/Avalonia.Controls.UnitTests/BorderTests.cs @@ -31,17 +31,16 @@ namespace Avalonia.Controls.UnitTests Padding = new Thickness(6), MaxHeight = 12, MaxWidth = 12, - Content = content = new Border + Child = content = new Border { Height = 0, Width = 0 } }; - - target.Measure(new Size(100, 100)); + target.Arrange(new Rect(0, 0, 100, 100)); - Assert.Equal(new Rect(0, 0, 0, 0), content.Bounds); + Assert.Equal(new Rect(6, 6, 0, 0), content.Bounds); } } } diff --git a/tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Layout.cs b/tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Layout.cs index d88716279a..2c1074aa9a 100644 --- a/tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Layout.cs +++ b/tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Layout.cs @@ -217,21 +217,23 @@ namespace Avalonia.Controls.UnitTests.Presenters Border content; var target = new ContentPresenter { - Padding = 32, + Padding = new Thickness(32), MaxHeight = 32, MaxWidth = 32, + HorizontalContentAlignment = HorizontalAlignment.Center, + VerticalContentAlignment = VerticalAlignment.Center, Content = content = new Border { - MinWidth = 16, - MinHeight = 16, + Height = 0, + Width = 0, }, }; target.UpdateChild(); - target.Measure(new Size(100, 100)); + target.Arrange(new Rect(0, 0, 100, 100)); - Assert.Equal(new Rect(0, 0, 0, 0), content.Bounds); + Assert.Equal(new Rect(48, 48, 0, 0), content.Bounds); } } } \ No newline at end of file From 8d07861e5976fa1930d2da40271031019b242d05 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 13 Apr 2018 14:14:24 +0100 Subject: [PATCH 10/11] white space. --- src/Avalonia.Controls/Border.cs | 4 ++-- src/Avalonia.Controls/Presenters/ContentPresenter.cs | 4 ++-- tests/Avalonia.Controls.UnitTests/BorderTests.cs | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Controls/Border.cs b/src/Avalonia.Controls/Border.cs index e6846978dc..93a6c203c9 100644 --- a/src/Avalonia.Controls/Border.cs +++ b/src/Avalonia.Controls/Border.cs @@ -110,11 +110,11 @@ namespace Avalonia.Controls { if (Child != null) { - var padding = Padding + BorderThickness; + var padding = Padding + BorderThickness; Child.Arrange(new Rect(finalSize).Deflate(padding)); } - _borderRenderHelper.Update(finalSize, BorderThickness, CornerRadius); + _borderRenderHelper.Update(finalSize, BorderThickness, CornerRadius); return finalSize; } diff --git a/src/Avalonia.Controls/Presenters/ContentPresenter.cs b/src/Avalonia.Controls/Presenters/ContentPresenter.cs index 1c5883d980..ce8fe52c22 100644 --- a/src/Avalonia.Controls/Presenters/ContentPresenter.cs +++ b/src/Avalonia.Controls/Presenters/ContentPresenter.cs @@ -383,10 +383,10 @@ namespace Avalonia.Controls.Presenters { size = size.WithWidth(Math.Min(size.Width, DesiredSize.Width - padding.Left - padding.Right)); } - + if (verticalContentAlignment != VerticalAlignment.Stretch) { - size = size.WithHeight(Math.Min(size.Height, DesiredSize.Height - padding.Top - padding.Bottom)); + size = size.WithHeight(Math.Min(size.Height, DesiredSize.Height - padding.Top - padding.Bottom)); } if (useLayoutRounding) diff --git a/tests/Avalonia.Controls.UnitTests/BorderTests.cs b/tests/Avalonia.Controls.UnitTests/BorderTests.cs index 9d6c838bc3..9a6a041ec7 100644 --- a/tests/Avalonia.Controls.UnitTests/BorderTests.cs +++ b/tests/Avalonia.Controls.UnitTests/BorderTests.cs @@ -33,11 +33,11 @@ namespace Avalonia.Controls.UnitTests MaxWidth = 12, Child = content = new Border { - Height = 0, - Width = 0 + Height = 0, + Width = 0 } }; - + target.Arrange(new Rect(0, 0, 100, 100)); Assert.Equal(new Rect(6, 6, 0, 0), content.Bounds); From 4ca13f2e3f7bde9e2735063318701365fb8362c4 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 13 Apr 2018 15:25:52 +0200 Subject: [PATCH 11/11] Added additional invalidation properties... ...to `ContentPresenter` --- src/Avalonia.Controls/Presenters/ContentPresenter.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Controls/Presenters/ContentPresenter.cs b/src/Avalonia.Controls/Presenters/ContentPresenter.cs index d2fb838657..408e777ef8 100644 --- a/src/Avalonia.Controls/Presenters/ContentPresenter.cs +++ b/src/Avalonia.Controls/Presenters/ContentPresenter.cs @@ -89,12 +89,11 @@ namespace Avalonia.Controls.Presenters /// static ContentPresenter() { + AffectsRender(BackgroundProperty, BorderBrushProperty, BorderThicknessProperty, CornerRadiusProperty); + AffectsMeasure(BorderThicknessProperty); ContentProperty.Changed.AddClassHandler(x => x.ContentChanged); ContentTemplateProperty.Changed.AddClassHandler(x => x.ContentChanged); TemplatedParentProperty.Changed.AddClassHandler(x => x.TemplatedParentChanged); - - AffectsRender(BorderThicknessProperty); - AffectsMeasure(BorderThicknessProperty); } ///