using Annulus; using Azimuth; using UnitTestSharp; namespace Glass.UnitTests { public class ScrollingPanelTests : TestFixture { [IgnoreTest] private static ScrollingPanel Scroller(Vector boundsSize, Vector contentSize) { return new ScrollingPanel { Bounds = Rect.FromPositionAndSize(Vector.Zero, boundsSize), ContentSize = contentSize, }; } public class ViewportRectTests : TestFixture { public void IsInheritedAsTheMaterialInterior_LikeAPlainPanel() { var bounds = Rect.FromPositionAndSize(new Vector(10, 20), new Vector(200, 100)); var material = new Material { BorderSize = new Rect.BorderSize { Top = 5, Bottom = 5, Left = 5, Right = 5 }, }; var plain = new Glass.Panel { Bounds = bounds, Material = material }; var scrolling = new ScrollingPanel { Bounds = bounds, Material = material, ContentSize = new Vector(999, 999), }; scrolling.ScrollTo(new Vector(40, 60)); CheckEqual(plain.ViewportRect, scrolling.ViewportRect); } public void IgnoresContentSizeAndScrollOffset() { var bounds = Rect.FromPositionAndSize(new Vector(10, 20), new Vector(100, 80)); var small = new ScrollingPanel { Bounds = bounds, ContentSize = bounds.Size }; var large = new ScrollingPanel { Bounds = bounds, ContentSize = new Vector(500, 500) }; large.ScrollTo(new Vector(30, 40)); CheckEqual(small.ViewportRect, large.ViewportRect); } } public class MaxScrollOffsetTests : TestFixture { public void ContentFittingTheViewport_IsZero() { CheckEqual(Vector.Zero, Scroller(new Vector(100, 80), new Vector(100, 80)).MaxScrollOffset); } public void ContentLargerThanTheViewport_IsTheOverhang() { CheckEqual(new Vector(60, 220), Scroller(new Vector(100, 80), new Vector(160, 300)).MaxScrollOffset); } public void OneAxisFitting_IsZeroThereAndPositiveOnTheOther() { CheckEqual(new Vector(0, 220), Scroller(new Vector(100, 80), new Vector(100, 300)).MaxScrollOffset); } public void ContentSmallerThanTheViewport_IsZeroRatherThanNegative() { CheckEqual(Vector.Zero, Scroller(new Vector(100, 80), new Vector(40, 30)).MaxScrollOffset); } } public class ScrollOffsetTests : TestFixture { public void Unset_IsZero() { CheckEqual(Vector.Zero, Scroller(new Vector(100, 80), new Vector(160, 300)).ScrollOffset); } public void WithinRange_ReadsBackWhatWasSet() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(160, 300)); panel.ScrollTo(new Vector(25, 100)); CheckEqual(new Vector(25, 100), panel.ScrollOffset); } public void Negative_ClampsToZero() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(160, 300)); panel.ScrollTo(new Vector(-40, -10)); CheckEqual(Vector.Zero, panel.ScrollOffset); } public void PastTheEnd_ClampsToMaxScrollOffset() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(160, 300)); panel.ScrollTo(new Vector(500, 500)); CheckEqual(panel.MaxScrollOffset, panel.ScrollOffset); } public void AfterContentSizeShrinks_ReadsBackReClampedToTheNewMax() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(100, 400)); panel.ScrollTo(new Vector(0, 320)); panel.ContentSize = new Vector(100, 150); CheckEqual(new Vector(0, 70), panel.ScrollOffset); } } public class CanvasRectTests : TestFixture { public void IsSizedToContentSize() { CheckEqual(new Vector(300, 500), Scroller(new Vector(100, 80), new Vector(300, 500)).CanvasRect.Size); } public void IsAtTheOrigin_ScrollOrNot() { var panel = new ScrollingPanel { Bounds = Rect.FromPositionAndSize(new Vector(10, 20), new Vector(100, 80)), ContentSize = new Vector(300, 500), }; CheckEqual(Vector.Zero, panel.CanvasRect.Position); panel.ScrollTo(new Vector(40, 60)); CheckEqual(Vector.Zero, panel.CanvasRect.Position); } } public class CanvasOriginTests : TestFixture { [IgnoreTest] private static ScrollingPanel PanelAt10_20() => new ScrollingPanel { Bounds = Rect.FromPositionAndSize(new Vector(10, 20), new Vector(100, 80)), ContentSize = new Vector(300, 500), }; public void Unscrolled_IsTheViewportTopLeft() { ScrollingPanel panel = PanelAt10_20(); CheckEqual(panel.ViewportRect.TopLeft, panel.CanvasOrigin); CheckEqual(new Vector(10, 20), panel.CanvasOrigin); } public void Scrolled_IsTheViewportTopLeftMinusTheScroll() { ScrollingPanel panel = PanelAt10_20(); panel.ScrollTo(new Vector(25, 100)); CheckEqual(new Vector(10 - 25, 20 - 100), panel.CanvasOrigin); } public void PastTheEnd_TracksTheClampedScroll() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(160, 300)); panel.ScrollTo(new Vector(5000, 5000)); // ViewportRect.TopLeft is (0, 0) for a Scroller panel, so CanvasOrigin is just -MaxScrollOffset. CheckEqual(-panel.ScrollOffset, panel.CanvasOrigin); CheckEqual(new Vector(-60, -220), panel.CanvasOrigin); } } public class ScrollToTests : TestFixture { public void OverwritesThePreviousTargetRatherThanAccumulating() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(160, 300)); panel.ScrollTo(new Vector(20, 40)); panel.ScrollTo(new Vector(5, 15)); CheckEqual(new Vector(5, 15), panel.ScrollOffset); } } public class ScrollByTests : TestFixture { public void AddsTheDeltaToTheCurrentOffset() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(160, 300)); panel.ScrollTo(new Vector(10, 20)); panel.ScrollBy(new Vector(5, 30)); CheckEqual(new Vector(15, 50), panel.ScrollOffset); } public void RepeatedlyPastTheEnd_SaturatesAtMaxRatherThanRunningAway() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(160, 300)); panel.ScrollBy(new Vector(0, 10000)); panel.ScrollBy(new Vector(0, 10000)); panel.ScrollBy(new Vector(0, -10)); CheckEqual(new Vector(0, 210), panel.ScrollOffset); } } public class StepAmountTests : TestFixture { public void Unset_DefaultsToAQuarterOfTheViewport() { CheckEqual(20, new ScrollingPanel().StepAmount.Resolve(viewportSize: 80)); } public void ExplicitAbsoluteValue_OverridesTheDefault() { var panel = new ScrollingPanel { StepAmount = 7 }; CheckEqual(7, panel.StepAmount.Resolve(viewportSize: 80)); } } public class MouseWheelTests : TestFixture { public void TowardTheUser_ScrollsDownByAQuarterOfTheViewportHeight() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(160, 300)); CheckTrue(panel.MouseWheel(new MouseState(), notches: -1)); CheckEqual(new Vector(0, 20), panel.ScrollOffset); } public void AwayFromTheUser_ScrollsBackUp() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(160, 300)); panel.ScrollTo(new Vector(0, 100)); panel.MouseWheel(new MouseState(), notches: 1); CheckEqual(new Vector(0, 80), panel.ScrollOffset); } public void PartialNotch_ScrollsProportionally() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(160, 300)); panel.MouseWheel(new MouseState(), notches: -0.5); CheckEqual(new Vector(0, 10), panel.ScrollOffset); } public void AnAbsoluteStepAmount_IsMultipliedByTheNotches() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(160, 300)); panel.StepAmount = 7; panel.MouseWheel(new MouseState(), notches: -2); CheckEqual(new Vector(0, 14), panel.ScrollOffset); } public void AFractionalStepAmount_ResolvesAgainstTheViewportHeight() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(160, 300)); panel.StepAmount = ScrollAmount.FractionOfViewport(0.5); panel.MouseWheel(new MouseState(), notches: -1); CheckEqual(new Vector(0, 40), panel.ScrollOffset); } public void OnlyTheHorizontalAxisHavingAnywhereToGo_ScrollsHorizontallyByTheViewportWidth() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(160, 80)); CheckTrue(panel.MouseWheel(new MouseState(), notches: -1)); CheckEqual(new Vector(25, 0), panel.ScrollOffset); } public void ScrollingPastTheEnd_ClampsAtTheEnd() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(160, 300)); panel.MouseWheel(new MouseState(), notches: -100); CheckEqual(new Vector(0, 220), panel.ScrollOffset); } public void AlreadyAtTheLimit_StillClaimsTheWheel() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(160, 300)); CheckTrue(panel.MouseWheel(new MouseState(), notches: 1)); CheckEqual(Vector.Zero, panel.ScrollOffset); } public void ContentThatFits_DeclinesIt() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(100, 80)); CheckFalse(panel.MouseWheel(new MouseState(), notches: -1)); CheckEqual(Vector.Zero, panel.ScrollOffset); } public void Disabled_DeclinesItAndStaysPut() { ScrollingPanel panel = Scroller(new Vector(100, 80), new Vector(160, 300)); panel.Enabled = false; CheckFalse(panel.MouseWheel(new MouseState(), notches: -1)); CheckEqual(Vector.Zero, panel.ScrollOffset); } } } }