From fa872389c39bed88078d328a7b60496d83fe09e6 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 25 Nov 2015 00:51:02 +0100 Subject: [PATCH] Make ScrollContentViewer.Offset get coerced. Use the same logic as for ScrollViewer. --- .../Presenters/ScrollContentPresenter.cs | 9 +++++++++ src/Perspex.Controls/ScrollViewer.cs | 11 ++++++++--- .../Presenters/ScrollContentPresenterTests.cs | 13 ++++++++++++- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/Perspex.Controls/Presenters/ScrollContentPresenter.cs b/src/Perspex.Controls/Presenters/ScrollContentPresenter.cs index f9e870ea1d..f2ff1e3d5d 100644 --- a/src/Perspex.Controls/Presenters/ScrollContentPresenter.cs +++ b/src/Perspex.Controls/Presenters/ScrollContentPresenter.cs @@ -28,6 +28,7 @@ namespace Perspex.Controls.Presenters static ScrollContentPresenter() { ClipToBoundsProperty.OverrideDefaultValue(typeof(ScrollContentPresenter), true); + OffsetProperty.OverrideValidation(ValidateOffset); AffectsArrange(OffsetProperty); } @@ -143,5 +144,13 @@ namespace Perspex.Controls.Presenters Offset = offset; } + + private static Vector ValidateOffset(ScrollContentPresenter o, Vector value) + { + return ScrollViewer.CoerceOffset( + o.GetValue(ExtentProperty), + o.GetValue(ViewportProperty), + value); + } } } diff --git a/src/Perspex.Controls/ScrollViewer.cs b/src/Perspex.Controls/ScrollViewer.cs index 4bc46dcb8b..2d7da90ac1 100644 --- a/src/Perspex.Controls/ScrollViewer.cs +++ b/src/Perspex.Controls/ScrollViewer.cs @@ -124,6 +124,13 @@ namespace Perspex.Controls set { SetValue(VerticalScrollBarVisibilityProperty, value); } } + internal static Vector CoerceOffset(Size extent, Size viewport, Vector offset) + { + var maxX = Math.Max(extent.Width - viewport.Width, 0); + var maxY = Math.Max(extent.Height - viewport.Height, 0); + return new Vector(Clamp(offset.X, 0, maxX), Clamp(offset.Y, 0, maxY)); + } + protected override Size MeasureOverride(Size availableSize) { return base.MeasureOverride(availableSize); @@ -148,9 +155,7 @@ namespace Perspex.Controls { var extent = scrollViewer.Extent; var viewport = scrollViewer.Viewport; - var maxX = Math.Max(extent.Width - viewport.Width, 0); - var maxY = Math.Max(extent.Height - viewport.Height, 0); - return new Vector(Clamp(value.X, 0, maxX), Clamp(value.Y, 0, maxY)); + return CoerceOffset(extent, viewport, value); } else { diff --git a/tests/Perspex.Controls.UnitTests/Presenters/ScrollContentPresenterTests.cs b/tests/Perspex.Controls.UnitTests/Presenters/ScrollContentPresenterTests.cs index 706790bab0..38d6ca5e1c 100644 --- a/tests/Perspex.Controls.UnitTests/Presenters/ScrollContentPresenterTests.cs +++ b/tests/Perspex.Controls.UnitTests/Presenters/ScrollContentPresenterTests.cs @@ -167,7 +167,7 @@ namespace Perspex.Controls.UnitTests.Presenters { var target = new ScrollContentPresenter { - Content = new Border { Width = 40, Height = 50 } + Content = new Border { Width = 140, Height = 150 } }; target.Measure(new Size(100, 100)); @@ -178,6 +178,17 @@ namespace Perspex.Controls.UnitTests.Presenters Assert.False(target.IsArrangeValid); } + [Fact] + public void Offset_Should_Be_Coerced_To_Viewport() + { + var target = new ScrollContentPresenter(); + target.SetValue(ScrollContentPresenter.ExtentProperty, new Size(20, 20)); + target.SetValue(ScrollContentPresenter.ViewportProperty, new Size(10, 10)); + target.Offset = new Vector(12, 12); + + Assert.Equal(new Vector(10, 10), target.Offset); + } + private class TestControl : Control { protected override Size MeasureOverride(Size availableSize)