using Azimuth; using System; using System.Collections.Generic; using UnitTestSharp; namespace Glass.UnitTests { public class GridHeaderTests : TestFixture { private static GridHeader Styled(int columnCount = 3) { var returnMe = new GridHeader(columnCount) { TextStyle = FileDialogTests.LabelStyle }; for (int column = 0; column < columnCount; ++column) { returnMe.SetTitle(column, "Col" + column); } return returnMe; } public class TestCursor : Cursor { } private static GridHeader ArrangedHeader() { GridHeader returnMe = Styled(); returnMe.Arrange(new Scalar[] { 50, 30, 20 }, height: 18); return returnMe; } private static List<(int, Scalar)> RecordResizes(GridHeader header) { var returnMe = new List<(int, Scalar)>(); header.OnResizeRequested += (column, width) => returnMe.Add((column, width)); return returnMe; } private static MouseState At(Scalar x) { return new MouseState { Position = new Vector(x, 5), Buttons = MouseButtonFlags.Left }; } private static void Press( GridHeader header, int column, Scalar x, MouseButtonFlags button = MouseButtonFlags.Left) { header.GripOf(column).MouseDown(At(x), button, NoKeys.Held, NoKeys.Manager); } private static void Drag(GridHeader header, int column, Scalar x) { header.GripOf(column).MouseMove(At(x), NoKeys.Held, NoKeys.Manager); } private static void Release(GridHeader header, int column, Scalar x) { header.GripOf(column).MouseUp(At(x), MouseButtonFlags.Left, NoKeys.Held, NoKeys.Manager); } public class CtorTests : TestFixture { public void Always_HasOneHeaderDividerSortIconAndGripPerColumn() { var header = new GridHeader(3); CheckEqual(3, header.ColumnCount); CheckEqual(12, FileDialogTests.ChildCount(header)); } public void Always_DrawsNothingOfItsOwn() { var header = new GridHeader(1); CheckTrue(ReferenceEquals(Material.Invisible, header.Material)); } public void Always_GivesEachGripNothingToDraw() { var header = new GridHeader(2); CheckTrue(ReferenceEquals(Material.Invisible, header.GripOf(0).Material)); CheckTrue(ReferenceEquals(Material.Invisible, header.GripOf(1).Material)); } public void NoColumns_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new GridHeader(0); } public void Always_StartsWithNothingSorted() { var header = new GridHeader(2); CheckNull(header.SortedColumn); CheckFalse(header.SortedDescending); } } public class HeaderOfTests : TestFixture { public void EachColumn_HasItsOwnButton() { var header = new GridHeader(2); CheckFalse(ReferenceEquals(header.HeaderOf(0), header.HeaderOf(1))); } public void PastTheLastColumn_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new GridHeader(2).HeaderOf(2); } public void Negative_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new GridHeader(2).HeaderOf(-1); } } public class SetTitleTests : TestFixture { public void Always_SizesTheHeaderToTheTitle() { GridHeader header = Styled(); header.SetTitle(1, "A longer title"); CheckEqual(FileDialogTests.TextSize("A longer title").X, header.PreferredSizeOf(1).X); } public void Null_MeansNoTitle() { GridHeader header = Styled(); header.SetTitle(0, null); CheckEqual(FileDialogTests.TextSize("").X, header.PreferredSizeOf(0).X); } public void PastTheLastColumn_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new GridHeader(2).SetTitle(2, "x"); } } public class ShowSortTests : TestFixture { public void Always_RemembersTheColumnAndDirection() { var header = new GridHeader(3); header.ShowSort(2, descending: true); CheckEqual(2, header.SortedColumn); CheckTrue(header.SortedDescending); } public void Null_ShowsNothingSorted() { var header = new GridHeader(3); header.ShowSort(1, descending: false); header.ShowSort(null, descending: false); CheckNull(header.SortedColumn); } public void PastTheLastColumn_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new GridHeader(3).ShowSort(3, descending: false); } } public class MarkTests : TestFixture { public void Properties_AreKept() { var header = new GridHeader(1) { AscendingMark = "^", DescendingMark = "v" }; CheckEqual("^", header.AscendingMark); CheckEqual("v", header.DescendingMark); } public void Null_MeansNoMark() { var header = new GridHeader(1) { AscendingMark = null, DescendingMark = null }; CheckEqual("", header.AscendingMark); CheckEqual("", header.DescendingMark); } public void NullTextStyle_FallsBackToAnUnstyledOne() { var header = new GridHeader(1) { TextStyle = null }; CheckNotNull(header.TextStyle); } public void Chrome_IsKept() { ButtonMaterial chrome = FileDialogTests.ButtonOf(10, 10); var header = new GridHeader(1) { Chrome = chrome }; CheckEqual(chrome, header.Chrome); } } public class PreferredSizeOfTests : TestFixture { public void WithoutMarks_IsTheTitlesSize() { GridHeader header = Styled(); CheckEqual(FileDialogTests.TextSize("Col1"), header.PreferredSizeOf(1)); } public void WithMarks_HoldsTheWidestSoSortingNeverResizesIt() { GridHeader header = Styled(); header.AscendingMark = " up"; header.DescendingMark = " much further down"; Scalar widest = FileDialogTests.TextSize("Col1 much further down").X; CheckEqual(widest, header.PreferredSizeOf(1).X); header.ShowSort(1, descending: false); CheckEqual(widest, header.PreferredSizeOf(1).X); } public void Chrome_AddsToTheSize() { GridHeader header = Styled(); Vector bare = header.PreferredSizeOf(0); header.Chrome = FileDialogTests.ButtonOf(0, 0, border: 3); CheckEqual(bare + new Vector(6, 6), header.PreferredSizeOf(0)); } public void PastTheLastColumn_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); Styled(2).PreferredSizeOf(2); } } public class SortIconTests : TestFixture { [IgnoreTest] private static GridHeader WithIcons() { GridHeader returnMe = Styled(); returnMe.AscendingIcon = new ScrollViewTests.SizedSolidMaterial(new Vector(8, 6)); returnMe.DescendingIcon = new ScrollViewTests.SizedSolidMaterial(new Vector(8, 6)); returnMe.IconInset = 10; returnMe.Arrange(new Scalar[] { 50, 30, 20 }, height: 18); return returnMe; } public void AnUnsortedColumn_DrawsNothing() { GridHeader header = WithIcons(); CheckTrue(ReferenceEquals(Material.Invisible, header.SortIconOf(0).Material)); } public void AColumnSortedForwards_DrawsTheAscendingIcon() { GridHeader header = WithIcons(); header.ShowSort(1, descending: false); CheckTrue(ReferenceEquals(header.AscendingIcon, header.SortIconOf(1).Material)); CheckTrue(ReferenceEquals(Material.Invisible, header.SortIconOf(0).Material)); } public void AColumnSortedInReverse_DrawsTheDescendingIcon() { GridHeader header = WithIcons(); header.ShowSort(1, descending: true); CheckTrue(ReferenceEquals(header.DescendingIcon, header.SortIconOf(1).Material)); } public void SortingAnotherColumn_ClearsTheFirstOnesIcon() { GridHeader header = WithIcons(); header.ShowSort(0, descending: false); header.ShowSort(2, descending: false); CheckTrue(ReferenceEquals(Material.Invisible, header.SortIconOf(0).Material)); } public void NoIconForTheDirection_DrawsNothing() { GridHeader header = WithIcons(); header.DescendingIcon = null; header.ShowSort(1, descending: true); CheckTrue(ReferenceEquals(Material.Invisible, header.SortIconOf(1).Material)); } public void Always_CentresInTheStripAboveTheTitleAcrossTheColumn() { GridHeader header = WithIcons(); CheckEqual(FileDialogTests.Box((Scalar)20.5, 2, 8, 6), header.SortIconOf(0).Bounds); CheckEqual(FileDialogTests.Box((Scalar)60.5, 2, 8, 6), header.SortIconOf(1).Bounds); } public void ATallerInset_MovesTheIconToTheMiddleOfTheStrip() { GridHeader header = WithIcons(); header.IconInset = 14; CheckEqual(FileDialogTests.Box((Scalar)20.5, 4, 8, 6), header.SortIconOf(0).Bounds); } public void AnInsetShorterThanTheIcon_KeepsTheIconInsideTheHeader() { GridHeader header = WithIcons(); header.IconInset = 0; CheckEqual(FileDialogTests.Box((Scalar)20.5, 0, 8, 6), header.SortIconOf(0).Bounds); } public void ScrolledSideways_ShiftsTheIconsLeft() { GridHeader header = WithIcons(); header.Arrange(new Scalar[] { 50, 30, 20 }, height: 18, scrollOffset: 10); CheckEqual(FileDialogTests.Box((Scalar)10.5, 2, 8, 6), header.SortIconOf(0).Bounds); } public void TheLargerIcon_SetsTheSpaceForBoth() { GridHeader header = WithIcons(); header.DescendingIcon = new ScrollViewTests.SizedSolidMaterial(new Vector(10, 4)); CheckEqual(FileDialogTests.Box((Scalar)19.5, 2, 10, 6), header.SortIconOf(0).Bounds); } public void WithIcons_AddsTheInsetToAColumnsPreferredHeightOnly() { GridHeader header = Styled(); Vector bare = header.PreferredSizeOf(1); header.AscendingIcon = new ScrollViewTests.SizedSolidMaterial(new Vector(8, 6)); header.IconInset = 10; CheckEqual(bare + new Vector(0, 10), header.PreferredSizeOf(1)); } public void WithoutIcons_TheInsetAddsNothing() { GridHeader header = Styled(); Vector bare = header.PreferredSizeOf(1); header.IconInset = 10; CheckEqual(bare, header.PreferredSizeOf(1)); } public void PastTheLastColumn_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); Styled(2).SortIconOf(2); } } public class PressingTests : TestFixture { [IgnoreTest] private static List Requests(GridHeader header) { var returnMe = new List(); header.OnSortRequested += (column, descending) => returnMe.Add($"{column}:{descending}"); return returnMe; } public void WithNothingSorted_AsksForForwards() { GridHeader header = Styled(); List requests = Requests(header); FileDialogTests.Click(header.HeaderOf(1)); CheckEqual(new List { "1:False" }, requests); } public void TheSortedColumn_AsksForTheOppositeDirection() { GridHeader header = Styled(); List requests = Requests(header); header.ShowSort(1, descending: false); FileDialogTests.Click(header.HeaderOf(1)); CheckEqual(new List { "1:True" }, requests); } public void TheSortedColumnInReverse_AsksForForwards() { GridHeader header = Styled(); List requests = Requests(header); header.ShowSort(1, descending: true); FileDialogTests.Click(header.HeaderOf(1)); CheckEqual(new List { "1:False" }, requests); } public void AnotherColumn_AsksForForwardsEvenAfterAReverseSort() { GridHeader header = Styled(); List requests = Requests(header); header.ShowSort(1, descending: true); FileDialogTests.Click(header.HeaderOf(2)); CheckEqual(new List { "2:False" }, requests); } public void Pressing_ChangesNothingUntilTheOwnerShowsTheSort() { GridHeader header = Styled(); FileDialogTests.Click(header.HeaderOf(1)); CheckNull(header.SortedColumn); } public void WithNobodyListening_DoesNothing() { GridHeader header = Styled(); FileDialogTests.Click(header.HeaderOf(0)); CheckNull(header.SortedColumn); } } public class GripTests : TestFixture { public void EveryColumnIncludingTheLast_HasAGripCentredOnItsRightBoundary() { GridHeader header = Styled(); header.Arrange(new Scalar[] { 50, 30, 20 }, height: 18); CheckEqual(FileDialogTests.Box(47, 0, 6, 18), header.GripOf(0).Bounds); CheckEqual(FileDialogTests.Box(77, 0, 6, 18), header.GripOf(1).Bounds); CheckEqual(FileDialogTests.Box(97, 0, 6, 18), header.GripOf(2).Bounds); } public void ScrolledSideways_MovesWithTheHeaders() { GridHeader header = Styled(); header.Arrange(new Scalar[] { 50, 30, 20 }, height: 18, scrollOffset: 10); CheckEqual(FileDialogTests.Box(37, 0, 6, 18), header.GripOf(0).Bounds); CheckEqual(FileDialogTests.Box(87, 0, 6, 18), header.GripOf(2).Bounds); } public void ChangingTheGripWidth_KeepsEachGripCentredOnItsBoundary() { GridHeader header = Styled(); header.Arrange(new Scalar[] { 50, 30, 20 }, height: 18); header.GripWidth = 10; CheckEqual(FileDialogTests.Box(45, 0, 10, 18), header.GripOf(0).Bounds); } public void TheGripWidth_StartsAtSix() { CheckEqual(6, new GridHeader(1).GripWidth); } public void TheGrips_DrawOverTheHeaders() { GridHeader header = Styled(columnCount: 2); var drawOrder = new List(); foreach (Control child in header.CanvasChildren.BackToFront()) { drawOrder.Add(child); } CheckEqual(8, drawOrder.Count); CheckTrue(ReferenceEquals(header.GripOf(0), drawOrder[6])); CheckTrue(ReferenceEquals(header.GripOf(1), drawOrder[7])); } public void PastTheLastColumn_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new GridHeader(2).GripOf(2); } public void TheCursor_IsWhatGripCursorSays() { var cursor = new TestCursor(); GridHeader header = Styled(); header.GripCursor = cursor; CheckTrue(ReferenceEquals( cursor, header.GripOf(1).CursorAt(default, NoKeys.Held, NoKeys.Manager))); } public void WithoutAGripCursor_LeavesTheCursorAlone() { CheckNull(Styled().GripOf(1).CursorAt(default, NoKeys.Held, NoKeys.Manager)); } } public class DividerTests : TestFixture { public void EveryColumnIncludingTheLast_HasALineInsideItsRightEdge() { GridHeader header = Styled(); header.Arrange(new Scalar[] { 50, 30, 20 }, height: 18); CheckEqual(FileDialogTests.Box(49, 0, 1, 18), header.DividerOf(0).Bounds); CheckEqual(FileDialogTests.Box(79, 0, 1, 18), header.DividerOf(1).Bounds); CheckEqual(FileDialogTests.Box(99, 0, 1, 18), header.DividerOf(2).Bounds); } public void ScrolledSideways_MovesWithTheHeaders() { GridHeader header = Styled(); header.Arrange(new Scalar[] { 50, 30, 20 }, height: 18, scrollOffset: 10); CheckEqual(FileDialogTests.Box(39, 0, 1, 18), header.DividerOf(0).Bounds); } public void ChangingTheWidth_KeepsEachLineInsideItsRightEdge() { GridHeader header = Styled(); header.Arrange(new Scalar[] { 50, 30, 20 }, height: 18); header.DividerWidth = 2; CheckEqual(FileDialogTests.Box(48, 0, 2, 18), header.DividerOf(0).Bounds); } public void TheWidth_StartsAtOne() { CheckEqual(1, new GridHeader(1).DividerWidth); } public void ByDefault_DrawNothing() { var header = new GridHeader(2); CheckTrue(ReferenceEquals(Material.Invisible, header.Divider)); CheckTrue(ReferenceEquals(Material.Invisible, header.DividerOf(1).Material)); } public void SettingTheMaterial_GivesEveryColumnTheLine() { var line = new SolidColorMaterial(); var header = new GridHeader(2); header.Divider = line; CheckTrue(ReferenceEquals(line, header.DividerOf(0).Material)); CheckTrue(ReferenceEquals(line, header.DividerOf(1).Material)); } public void SettingNull_DrawsNothing() { var header = new GridHeader(2); header.Divider = new SolidColorMaterial(); header.Divider = null; CheckTrue(ReferenceEquals(Material.Invisible, header.DividerOf(1).Material)); } public void PastTheLastColumn_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new GridHeader(2).DividerOf(2); } } public class DragTests : TestFixture { public void Dragging_AsksForTheWidthAtPressPlusTheMovement() { GridHeader header = ArrangedHeader(); List<(int, Scalar)> requests = RecordResizes(header); Press(header, column: 1, x: 77); Drag(header, column: 1, x: 90); Drag(header, column: 1, x: 70); CheckEqual(new List<(int, Scalar)> { (1, 43), (1, 23) }, requests); } public void Dragging_StartsFromTheWidthAtPress_WhenTheColumnChangesMeanwhile() { GridHeader header = ArrangedHeader(); List<(int, Scalar)> requests = RecordResizes(header); Press(header, column: 1, x: 77); Drag(header, column: 1, x: 90); header.Arrange(new Scalar[] { 50, 43, 20 }, height: 18); Drag(header, column: 1, x: 95); CheckEqual(new List<(int, Scalar)> { (1, 43), (1, 48) }, requests); } public void TheLastColumn_CanBeDragged() { GridHeader header = ArrangedHeader(); List<(int, Scalar)> requests = RecordResizes(header); Press(header, column: 2, x: 97); Drag(header, column: 2, x: 107); CheckEqual(new List<(int, Scalar)> { (2, 30) }, requests); } public void MovingWithoutPressing_AsksForNothing() { GridHeader header = ArrangedHeader(); List<(int, Scalar)> requests = RecordResizes(header); Drag(header, column: 1, x: 90); CheckEqual(0, requests.Count); } public void AfterTheRelease_AsksForNothing() { GridHeader header = ArrangedHeader(); List<(int, Scalar)> requests = RecordResizes(header); Press(header, column: 1, x: 77); Release(header, column: 1, x: 77); Drag(header, column: 1, x: 90); CheckEqual(0, requests.Count); } public void PressingWithTheRightButton_StartsNoDrag() { GridHeader header = ArrangedHeader(); List<(int, Scalar)> requests = RecordResizes(header); Press(header, column: 1, x: 77, MouseButtonFlags.Right); Drag(header, column: 1, x: 90); CheckEqual(0, requests.Count); } public void Cancelling_AsksForTheWidthAtPress() { GridHeader header = ArrangedHeader(); List<(int, Scalar)> requests = RecordResizes(header); Press(header, column: 1, x: 77); Drag(header, column: 1, x: 90); header.GripOf(1).CancelMouseInput(); Drag(header, column: 1, x: 95); CheckEqual(new List<(int, Scalar)> { (1, 43), (1, 30) }, requests); } public void CancellingWithoutADrag_AsksForNothing() { GridHeader header = ArrangedHeader(); List<(int, Scalar)> requests = RecordResizes(header); header.GripOf(1).CancelMouseInput(); CheckEqual(0, requests.Count); } public void DraggingAGrip_RequestsNoSort() { GridHeader header = ArrangedHeader(); int sorts = 0; header.OnSortRequested += (column, descending) => ++sorts; Press(header, column: 1, x: 77); Drag(header, column: 1, x: 90); Release(header, column: 1, x: 90); CheckEqual(0, sorts); } } public class FitTests : TestFixture { public void DoubleClickingAGrip_AsksToFitItsColumn() { GridHeader header = ArrangedHeader(); var fits = new List(); header.OnFitRequested += fits.Add; header.GripOf(2).Click(default, MouseButtonFlags.Left, 2, NoKeys.Held, NoKeys.Manager); CheckEqual(new List { 2 }, fits); } public void ASingleClick_AsksForNothing() { GridHeader header = ArrangedHeader(); var fits = new List(); header.OnFitRequested += fits.Add; header.GripOf(1).Click(default, MouseButtonFlags.Left, 1, NoKeys.Held, NoKeys.Manager); CheckEqual(0, fits.Count); } public void DoubleClickingWithTheRightButton_AsksForNothing() { GridHeader header = ArrangedHeader(); var fits = new List(); header.OnFitRequested += fits.Add; header.GripOf(1).Click(default, MouseButtonFlags.Right, 2, NoKeys.Held, NoKeys.Manager); CheckEqual(0, fits.Count); } } public class LeftEdgesOfTests : TestFixture { public void Always_AddsUpTheWidthsBeforeEach() { CheckEqual(new Scalar[] { 0, 10, 30 }, GridHeader.LeftEdgesOf(new Scalar[] { 10, 20, 30 })); } public void NoColumns_GivesNone() { CheckEqual(0, GridHeader.LeftEdgesOf(new Scalar[0]).Length); } public void NullWidths_Throws() { CheckThrow(typeof(ArgumentNullException)); GridHeader.LeftEdgesOf(null); } } public class ArrangeTests : TestFixture { public void Always_PlacesTheHeadersSideBySide() { GridHeader header = Styled(); header.Arrange(new Scalar[] { 50, 30, 20 }, height: 18); CheckEqual(FileDialogTests.Box(0, 0, 50, 18), header.HeaderOf(0).Bounds); CheckEqual(FileDialogTests.Box(50, 0, 30, 18), header.HeaderOf(1).Bounds); CheckEqual(FileDialogTests.Box(80, 0, 20, 18), header.HeaderOf(2).Bounds); } public void ScrolledSideways_ShiftsTheHeadersLeft() { GridHeader header = Styled(); header.Arrange(new Scalar[] { 50, 30, 20 }, height: 18, scrollOffset: 10); CheckEqual(FileDialogTests.Box(-10, 0, 50, 18), header.HeaderOf(0).Bounds); CheckEqual(FileDialogTests.Box(40, 0, 30, 18), header.HeaderOf(1).Bounds); } public void TheWrongNumberOfWidths_Throws() { GridHeader header = Styled(); CheckThrow(typeof(ArgumentException)); header.Arrange(new Scalar[] { 50, 30 }, height: 18); } public void NullWidths_Throws() { GridHeader header = Styled(); CheckThrow(typeof(ArgumentNullException)); header.Arrange(null, height: 18); } } } }