using Annulus; using Azimuth; using UnitTestSharp; namespace Glass.UnitTests { public class ScrollBarTests : TestFixture { [IgnoreTest] private static void SetArrowLength(ScrollBar scrollBar, Scalar arrowLength) { ButtonMaterial buttonMaterial = new ScrollTrackTests.FixedSizeMaterial(new Vector(arrowLength, arrowLength)); scrollBar.DecrementButton.ButtonMaterial = buttonMaterial; scrollBar.IncrementButton.ButtonMaterial = buttonMaterial; } [IgnoreTest] private static ScrollBar NewScrollBar(Orientation orientation, Vector position, Vector boundsSize, Scalar contentSize, Scalar viewportSize, Scalar arrowLength) { var scrollBar = new ScrollBar { Orientation = orientation, ContentSize = contentSize, ViewportSize = viewportSize, }; // Arrow materials before Bounds: Bounds is what triggers the synchronous layout pass, so anything // the layout depends on needs to already be in place by then. SetArrowLength(scrollBar, arrowLength); scrollBar.Bounds = Rect.FromPositionAndSize(position, boundsSize); return scrollBar; } [IgnoreTest] private static ScrollBar NewScrollBar(Orientation orientation, Vector position, Vector boundsSize, Scalar contentSize, Scalar viewportSize) { return NewScrollBar(orientation, position, boundsSize, contentSize, viewportSize, arrowLength: 20); } [IgnoreTest] private static ScrollBar NewScrollBar(Orientation orientation, Vector boundsSize, Scalar contentSize, Scalar viewportSize, Scalar arrowLength) { return NewScrollBar(orientation, Vector.Zero, boundsSize, contentSize, viewportSize, arrowLength); } [IgnoreTest] private static ScrollBar NewScrollBar(Orientation orientation, Vector boundsSize, Scalar contentSize, Scalar viewportSize) { return NewScrollBar(orientation, Vector.Zero, boundsSize, contentSize, viewportSize, arrowLength: 20); } public class ScrollBarMaterialTests : TestFixture { static readonly Material Track = new Material { DebugName = "track" }; static readonly Material Background = new Material { DebugName = "background" }; static readonly ButtonMaterial Decrement = new ButtonMaterial(new Material { DebugName = "decrement" }); static readonly ButtonMaterial Increment = new ButtonMaterial(new Material { DebugName = "increment" }); static readonly ButtonMaterial Thumb = new ButtonMaterial(new Material { DebugName = "thumb" }); static readonly ScrollBarMaterial FullSet = new ScrollBarMaterial { Track = Track, DecrementButton = Decrement, IncrementButton = Increment, Thumb = Thumb, Background = Background, }; public void Setter_AssignsEachChildDirectly() { var scrollBar = new ScrollBar { ScrollBarMaterial = FullSet }; CheckEqual(Track, scrollBar.Track.Material); CheckEqual(Decrement, scrollBar.DecrementButton.ButtonMaterial); CheckEqual(Increment, scrollBar.IncrementButton.ButtonMaterial); CheckEqual(Thumb, scrollBar.Thumb.ButtonMaterial); CheckEqual(Background, scrollBar.Material); } public void Getter_RoundTripsWhatTheSetterAssigned() { var scrollBar = new ScrollBar { ScrollBarMaterial = FullSet }; CheckEqual(FullSet, scrollBar.ScrollBarMaterial); } public void Getter_ReflectsAChildChangedDirectlyAfterwards() { var scrollBar = new ScrollBar { ScrollBarMaterial = FullSet }; var newThumb = new ButtonMaterial(new Material { DebugName = "newThumb" }); scrollBar.Thumb.ButtonMaterial = newThumb; CheckEqual(newThumb, scrollBar.ScrollBarMaterial.Thumb); } } public class LayoutTests : TestFixture { public void Horizontal_LaysOutArrowsAndTrackAlongX() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), contentSize: 400, viewportSize: 100); CheckEqual(Rect.FromPositionAndSize(new Vector(0, 0), new Vector(20, 20)), scrollBar.DecrementButton.Bounds); CheckEqual(Rect.FromPositionAndSize(new Vector(20, 0), new Vector(160, 20)), scrollBar.Track.Bounds); CheckEqual(Rect.FromPositionAndSize(new Vector(180, 0), new Vector(20, 20)), scrollBar.IncrementButton.Bounds); } public void Vertical_LaysOutArrowsAndTrackAlongY() { var scrollBar = NewScrollBar(Orientation.Vertical, new Vector(20, 200), contentSize: 400, viewportSize: 100); CheckEqual(Rect.FromPositionAndSize(new Vector(0, 0), new Vector(20, 20)), scrollBar.DecrementButton.Bounds); CheckEqual(Rect.FromPositionAndSize(new Vector(0, 20), new Vector(20, 160)), scrollBar.Track.Bounds); CheckEqual(Rect.FromPositionAndSize(new Vector(0, 180), new Vector(20, 20)), scrollBar.IncrementButton.Bounds); } public void ResizingBounds_RelaysOutArrowsAndTrack() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), contentSize: 400, viewportSize: 100); scrollBar.Bounds = Rect.FromPositionAndSize(Vector.Zero, new Vector(100, 20)); // trackLength = 100 - 2*20 = 60, so IncrementButton starts at arrowLength + trackLength = 80. CheckEqual(60, scrollBar.Track.Bounds.Size.X); CheckEqual(new Vector(80, 0), scrollBar.IncrementButton.Bounds.TopLeft); } public void NoArrowMaterial_ArrowClaimsNoSpaceAndTrackFillsTheWholeBar() { var scrollBar = new ScrollBar { Orientation = Orientation.Horizontal, ContentSize = 400, ViewportSize = 100, Bounds = Rect.FromPositionAndSize(Vector.Zero, new Vector(200, 20)), }; CheckEqual(0, scrollBar.DecrementButton.Bounds.Size.X); CheckEqual(0, scrollBar.IncrementButton.Bounds.Size.X); CheckEqual(Rect.FromPositionAndSize(Vector.Zero, new Vector(200, 20)), scrollBar.Track.Bounds); } public void ArrowMaterialThinnerThanTheBar_IsCenteredOnTheCrossAxisRatherThanStretched() { var scrollBar = new ScrollBar { Orientation = Orientation.Horizontal, ContentSize = 400, ViewportSize = 100, }; scrollBar.DecrementButton.ButtonMaterial = new ScrollTrackTests.FixedSizeMaterial(new Vector(20, 8)); scrollBar.Bounds = Rect.FromPositionAndSize(Vector.Zero, new Vector(200, 20)); CheckEqual(new Vector(20, 8), scrollBar.DecrementButton.Bounds.Size); // Centered within the bar's 20px cross-axis thickness: (20 - 8) / 2 = 6. CheckEqual(new Vector(0, 6), scrollBar.DecrementButton.Bounds.TopLeft); } public void DifferentlySizedArrows_EachClaimsItsOwnMeasuredLength() { var scrollBar = new ScrollBar { Orientation = Orientation.Horizontal, ContentSize = 400, ViewportSize = 100, }; scrollBar.DecrementButton.ButtonMaterial = new ScrollTrackTests.FixedSizeMaterial(new Vector(10, 20)); scrollBar.IncrementButton.ButtonMaterial = new ScrollTrackTests.FixedSizeMaterial(new Vector(30, 20)); scrollBar.Bounds = Rect.FromPositionAndSize(Vector.Zero, new Vector(200, 20)); CheckEqual(10, scrollBar.DecrementButton.Bounds.Size.X); CheckEqual(30, scrollBar.IncrementButton.Bounds.Size.X); // trackLength = 200 - 10 - 30 = 160; IncrementButton starts after decrement (10) + track (160). CheckEqual(170, scrollBar.IncrementButton.Bounds.TopLeft.X); } public void ArrowMaterialLargerThanTheBar_ClampsToTheBarsOwnLength() { var scrollBar = new ScrollBar { Orientation = Orientation.Horizontal, ContentSize = 400, ViewportSize = 100, }; SetArrowLength(scrollBar, 9999); scrollBar.Bounds = Rect.FromPositionAndSize(Vector.Zero, new Vector(200, 20)); CheckEqual(200, scrollBar.DecrementButton.Bounds.Size.X); } public void SettingArrowMaterialAfterConstruction_TakesEffectImmediately() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100, arrowLength: 20); scrollBar.DecrementButton.ButtonMaterial = new ScrollTrackTests.FixedSizeMaterial(new Vector(30, 20)); CheckEqual(30, scrollBar.DecrementButton.Bounds.Size.X); } public void SettingMaterialAfterConstruction_BorderShrinksTheTrackImmediately() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100, arrowLength: 20); CheckEqual(160, scrollBar.Track.Bounds.Size.X); ScrollBarMaterial material = scrollBar.ScrollBarMaterial; material.Background = new Material { BorderSize = new Rect.BorderSize { Left = 5, Right = 5 } }; scrollBar.ScrollBarMaterial = material; // CanvasRect shrinks by the 10px border, so trackLength = (200 - 10) - 2*20 = 150. CheckEqual(150, scrollBar.Track.Bounds.Size.X); } } public class StepAmountTests : TestFixture { public void Unset_DefaultsToAQuarterOfViewportSize() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); CheckEqual(25, scrollBar.StepAmount.Resolve(scrollBar.ViewportSize)); } public void ExplicitAbsoluteValue_OverridesTheDefault() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); scrollBar.StepAmount = 5; CheckEqual(5, scrollBar.StepAmount.Resolve(scrollBar.ViewportSize)); } public void ExplicitAbsoluteValue_SurvivesAViewportSizeChange() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); scrollBar.StepAmount = 5; scrollBar.ViewportSize = 60; CheckEqual(5, scrollBar.StepAmount.Resolve(scrollBar.ViewportSize)); } public void ExplicitFraction_TracksLaterViewportSizeChanges() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); scrollBar.StepAmount = ScrollAmount.FractionOfViewport(0.5); CheckEqual(50, scrollBar.StepAmount.Resolve(scrollBar.ViewportSize)); scrollBar.ViewportSize = 60; CheckEqual(30, scrollBar.StepAmount.Resolve(scrollBar.ViewportSize)); } } public class ContentSizeTests : TestFixture { public void ForwardsToTrack() { var scrollBar = new ScrollBar { ContentSize = 400 }; CheckEqual(400, scrollBar.Track.ContentSize); } } public class ViewportSizeTests : TestFixture { public void ForwardsToTrack() { var scrollBar = new ScrollBar { ViewportSize = 100 }; CheckEqual(100, scrollBar.Track.ViewportSize); } } public class PageAmountTests : TestFixture { public void ForwardsToTrack() { var scrollBar = new ScrollBar { ViewportSize = 100 }; scrollBar.PageAmount = 50; CheckEqual(50, scrollBar.Track.PageAmount.Resolve(scrollBar.ViewportSize)); } } public class ScrollOffsetTests : TestFixture { public void ForwardsToTrack() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); scrollBar.ScrollTo(150); CheckEqual(scrollBar.Track.ScrollOffset, scrollBar.ScrollOffset); } } public class ScrollToTests : TestFixture { public void ForwardsToTrack() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); scrollBar.ScrollTo(150); CheckEqual(150, scrollBar.ScrollOffset); } } public class ScrollByTests : TestFixture { public void ForwardsToTrack() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); scrollBar.ScrollTo(100); scrollBar.ScrollBy(30); CheckEqual(130, scrollBar.ScrollOffset); } } public class CanScrollTests : TestFixture { public void ContentLongerThanTheViewport_IsTrue() { CheckTrue(NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100).CanScroll); } public void ContentExactlyFittingTheViewport_IsFalse() { CheckFalse(NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 100, 100).CanScroll); } public void ContentShorterThanTheViewport_IsFalse() { CheckFalse(NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 50, 100).CanScroll); } } public class ScrollByStepsTests : TestFixture { public void ScrollsByStepAmountPerStep() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); scrollBar.ScrollBySteps(2); CheckEqual(50, scrollBar.ScrollOffset); } public void NegativeSteps_ScrollBackTowardsTheStart() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); scrollBar.ScrollTo(100); scrollBar.ScrollBySteps(-1); CheckEqual(75, scrollBar.ScrollOffset); } public void PartialSteps_ScrollProportionally() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); scrollBar.ScrollBySteps(0.5); CheckEqual(12.5, scrollBar.ScrollOffset); } public void AnAbsoluteStepAmount_IsMultipliedAsIs() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); scrollBar.StepAmount = 10; scrollBar.ScrollBySteps(3); CheckEqual(30, scrollBar.ScrollOffset); } } public class MouseWheelTests : TestFixture { public void AwayFromTheUser_ScrollsBackTowardsTheStart() { var scrollBar = NewScrollBar(Orientation.Vertical, new Vector(20, 200), 400, 100); scrollBar.ScrollTo(100); CheckTrue(scrollBar.MouseWheel(new MouseState(), notches: 1)); CheckEqual(75, scrollBar.ScrollOffset); } public void TowardTheUser_ScrollsTowardsTheEnd() { var scrollBar = NewScrollBar(Orientation.Vertical, new Vector(20, 200), 400, 100); CheckTrue(scrollBar.MouseWheel(new MouseState(), notches: -1)); CheckEqual(25, scrollBar.ScrollOffset); } public void ScrollsAStepAmountPerNotch() { var scrollBar = NewScrollBar(Orientation.Vertical, new Vector(20, 200), 400, 100); scrollBar.ScrollTo(200); scrollBar.MouseWheel(new MouseState(), notches: 2); CheckEqual(150, scrollBar.ScrollOffset); } public void PartialNotch_ScrollsProportionally() { var scrollBar = NewScrollBar(Orientation.Vertical, new Vector(20, 200), 400, 100); scrollBar.ScrollTo(100); scrollBar.MouseWheel(new MouseState(), notches: 0.5); CheckEqual(87.5, scrollBar.ScrollOffset); } public void HorizontalBar_ScrollsTheSameWay() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); scrollBar.MouseWheel(new MouseState(), notches: -1); CheckEqual(25, scrollBar.ScrollOffset); } public void AlreadyAtTheLimit_StillClaimsTheWheel() { var scrollBar = NewScrollBar(Orientation.Vertical, new Vector(20, 200), 400, 100); CheckTrue(scrollBar.MouseWheel(new MouseState(), notches: 1)); CheckEqual(0, scrollBar.ScrollOffset); } public void NothingToScroll_DeclinesIt() { var scrollBar = NewScrollBar(Orientation.Vertical, new Vector(20, 200), 100, 100); CheckFalse(scrollBar.MouseWheel(new MouseState(), notches: -1)); } public void Disabled_DeclinesItAndStaysPut() { var scrollBar = NewScrollBar(Orientation.Vertical, new Vector(20, 200), 400, 100); scrollBar.Enabled = false; CheckFalse(scrollBar.MouseWheel(new MouseState(), notches: -1)); CheckEqual(0, scrollBar.ScrollOffset); } } public class OnScrollOffsetChangedTests : TestFixture { public void ForwardsToTrack() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); Scalar? raisedWith = null; scrollBar.OnScrollOffsetChanged +=value => raisedWith = value; scrollBar.ScrollTo(150); CheckEqual(150, raisedWith); } } public class EnabledTests : TestFixture { public void SettingFalse_DisablesDecrementIncrementAndThumb() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); scrollBar.Enabled = false; CheckFalse(scrollBar.DecrementButton.Enabled); CheckFalse(scrollBar.IncrementButton.Enabled); CheckFalse(scrollBar.Thumb.Enabled); } public void SettingTrueAfterFalse_ReenablesAllThree() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); scrollBar.Enabled = false; scrollBar.Enabled = true; Check(scrollBar.DecrementButton.Enabled); Check(scrollBar.IncrementButton.Enabled); Check(scrollBar.Thumb.Enabled); } } public class DecrementButtonClickTests : TestFixture { public void ScrollsBackByStepAmount() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); scrollBar.StepAmount = 15; scrollBar.ScrollTo(50); scrollBar.DecrementButton.Click(new MouseState(), MouseButtonFlags.Left); CheckEqual(35, scrollBar.ScrollOffset); } } public class IncrementButtonClickTests : TestFixture { public void ScrollsForwardByStepAmount() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); scrollBar.StepAmount = 15; scrollBar.IncrementButton.Click(new MouseState(), MouseButtonFlags.Left); CheckEqual(15, scrollBar.ScrollOffset); } public void DefaultStepAmount_ScrollsByAQuarterOfViewportSize() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); scrollBar.IncrementButton.Click(new MouseState(), MouseButtonFlags.Left); CheckEqual(25, scrollBar.ScrollOffset); } public void ExplicitFractionStepAmount_ScrollsByThatFractionOfViewport() { var scrollBar = NewScrollBar(Orientation.Horizontal, new Vector(200, 20), 400, 100); scrollBar.StepAmount = ScrollAmount.FractionOfViewport(0.5); scrollBar.IncrementButton.Click(new MouseState(), MouseButtonFlags.Left); CheckEqual(50, scrollBar.ScrollOffset); } } } }