#region CPL License /* Nuclex Framework Copyright (C) 2002-2010 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion #if UNITTEST using System; using Nuclex.Support; using NUnit.Framework; using NMock; using Nuclex.Input; using Nuclex.UserInterface.Input; namespace Nuclex.UserInterface.Controls.Desktop { /// Unit Test for the list control [TestFixture] internal class ListControlTest { #region class DummyListRowLocator /// Dummy implementation of a list row locator private class DummyListRowLocator : IListRowLocator { /// Calculates the list row the cursor is in /// /// Boundaries of the control, should be in absolute coordinates /// /// /// Position of the thumb in the list's slider /// /// /// Number of items contained in the list /// /// Vertical position of the cursor /// The row the cursor is over public int GetRow(RectangleF bounds, float thumbPosition, int itemCount, float y) { return (int)(y / 10.0f); } /// Determines the height of a row displayed in the list /// /// Boundaries of the control, should be in absolute coordinates /// /// The height of a single row in the list public float GetRowHeight(RectangleF bounds) { return 10.0f; } } #endregion // class DummyListRowLocator #region interface IListSubscriber /// Interface for a subscriber to the list control's events public interface IListSubscriber { /// Called when selection made in the list has changed /// List whose selection has changed /// Not used void SelectionChanged(object sender, EventArgs arguments); } #endregion // interface IListSubscriber /// Initializes a new list control [Test] public void TestConstructor() { ListControl list = new ListControl(); Assert.IsNotNull(list); // nonsense; avoids compiler warning } /// Verifies that the RowLocator property is working [Test] public void TestRowLocatorProperty() { ListControl list = new ListControl(); DummyListRowLocator rowLocator = new DummyListRowLocator(); list.ListRowLocator = rowLocator; Assert.AreSame(rowLocator, list.ListRowLocator); } /// /// Tests whether list rows can be selected with the mouse in /// single-selection mode /// [Test] public void TestDisabledSelectionByMouse() { Screen screen = new Screen(); ListControl list = new ListControl(); list.Bounds = new UniRectangle(10, 10, 100, 100); list.SelectionMode = ListSelectionMode.None; list.ListRowLocator = new DummyListRowLocator(); screen.Desktop.Children.Add(list); // Put 20 items in the list fillList(list, 20); Assert.AreEqual(0, list.SelectedItems.Count); list.ProcessMouseMove(100, 100, 50, 25); list.ProcessMousePress(MouseButtons.Left); list.ProcessMouseRelease(MouseButtons.Left); Assert.AreEqual(0, list.SelectedItems.Count); } /// /// Tests whether list rows can be selected with the mouse in /// single-selection mode /// [Test] public void TestSingleSelectionByMouse() { Screen screen = new Screen(); ListControl list = new ListControl(); list.Bounds = new UniRectangle(10, 10, 100, 100); list.SelectionMode = ListSelectionMode.Single; list.ListRowLocator = new DummyListRowLocator(); screen.Desktop.Children.Add(list); // Put 20 items in the list fillList(list, 20); // At the beginning, no items should be selected Assert.AreEqual(0, list.SelectedItems.Count); // Click on item 2 and verify that it is now selected list.ProcessMouseMove(100, 100, 50, 35); list.ProcessMousePress(MouseButtons.Left); list.ProcessMouseRelease(MouseButtons.Left); Assert.AreEqual(1, list.SelectedItems.Count); Assert.AreEqual(2, list.SelectedItems[0]); // Now click on item 4, which should unselect item 2 and select item 4 list.ProcessMouseMove(100, 100, 50, 55); list.ProcessMousePress(MouseButtons.Left); list.ProcessMouseRelease(MouseButtons.Left); Assert.AreEqual(1, list.SelectedItems.Count); Assert.AreEqual(4, list.SelectedItems[0]); // Repeat the click on item 4, nothing should happen list.ProcessMouseMove(100, 100, 50, 55); list.ProcessMousePress(MouseButtons.Left); list.ProcessMouseRelease(MouseButtons.Left); Assert.AreEqual(1, list.SelectedItems.Count); Assert.AreEqual(4, list.SelectedItems[0]); } /// /// Tests whether list rows can be selected with the mouse in /// single-selection mode /// [Test] public void TestMultiSelectionByMouse() { Screen screen = new Screen(); ListControl list = new ListControl(); list.Bounds = new UniRectangle(10, 10, 100, 100); list.SelectionMode = ListSelectionMode.Multi; list.ListRowLocator = new DummyListRowLocator(); screen.Desktop.Children.Add(list); // Put 20 items in the list fillList(list, 20); Assert.AreEqual(0, list.SelectedItems.Count); list.ProcessMouseMove(100, 100, 50, 35); list.ProcessMousePress(MouseButtons.Left); list.ProcessMouseRelease(MouseButtons.Left); Assert.AreEqual(1, list.SelectedItems.Count); Assert.AreEqual(2, list.SelectedItems[0]); list.ProcessMouseMove(100, 100, 50, 55); list.ProcessMousePress(MouseButtons.Left); list.ProcessMouseRelease(MouseButtons.Left); Assert.AreEqual(2, list.SelectedItems.Count); Assert.AreEqual(2, list.SelectedItems[0]); Assert.AreEqual(4, list.SelectedItems[1]); list.ProcessMouseMove(100, 100, 50, 35); list.ProcessMousePress(MouseButtons.Left); list.ProcessMouseRelease(MouseButtons.Left); Assert.AreEqual(1, list.SelectedItems.Count); Assert.AreEqual(4, list.SelectedItems[0]); } /// Tests whether the selection mode of the list can be toggled [Test] public void TestSelectionModeProperty() { ListControl list = new ListControl(); list.SelectionMode = ListSelectionMode.None; Assert.AreEqual(ListSelectionMode.None, list.SelectionMode); list.SelectionMode = ListSelectionMode.Single; Assert.AreEqual(ListSelectionMode.Single, list.SelectionMode); list.SelectionMode = ListSelectionMode.Multi; Assert.AreEqual(ListSelectionMode.Multi, list.SelectionMode); } /// Tests whether the list control provides access to its slider [Test] public void TestSliderProperty() { ListControl list = new ListControl(); Assert.IsNotNull(list.Slider); } /// /// Tests whether the SelectionChanged event is fired when the selection changes /// [Test] public void TestSelectionChangedEvent() { using(MockFactory mockery = new MockFactory()) { ListControl list = new ListControl(); fillList(list, 20); Mock mockedSubscriber = mockSubscriber(mockery, list); mockedSubscriber.Expects.One.Method( m => m.SelectionChanged(null, null) ).WithAnyArguments(); list.SelectedItems.Add(1); mockedSubscriber.Expects.One.Method( m => m.SelectionChanged(null, null) ).WithAnyArguments(); list.SelectedItems.Remove(1); mockedSubscriber.Expects.One.Method( m => m.SelectionChanged(null, null) ).WithAnyArguments(); list.SelectedItems.Add(2); mockedSubscriber.Expects.One.Method( m => m.SelectionChanged(null, null) ).WithAnyArguments(); list.SelectedItems.Clear(); mockery.VerifyAllExpectationsHaveBeenMet(); } } /// Verifies that the list can be scrolled with the mouse wheel [Test] public void TestMouseWheel() { Screen screen = new Screen(); ListControl list = new ListControl(); list.Bounds = new UniRectangle(10, 10, 100, 100); list.ListRowLocator = new DummyListRowLocator(); screen.Desktop.Children.Add(list); // Put 20 items in the list fillList(list, 20); Assert.AreEqual(0.0f, list.Slider.ThumbPosition); list.ProcessMouseWheel(-1.0f); RectangleF listBounds = list.GetAbsoluteBounds(); float totalitems = list.Items.Count; float itemsInView = listBounds.Height; itemsInView /= list.ListRowLocator.GetRowHeight(listBounds); float scrollableItems = totalitems - itemsInView; float newThumbPosition = 1.0f / scrollableItems * 1.0f; Assert.AreEqual(newThumbPosition, list.Slider.ThumbPosition); } /// /// Tests whether the slider's thumb resizes according to the list /// [Test] public void TestSliderThumbResizing() { Screen screen = new Screen(); ListControl list = new ListControl(); list.Bounds = new UniRectangle(10, 10, 100, 100); list.ListRowLocator = new DummyListRowLocator(); screen.Desktop.Children.Add(list); RectangleF listBounds = list.GetAbsoluteBounds(); float itemsInView = listBounds.Height; itemsInView /= list.ListRowLocator.GetRowHeight(listBounds); // Put 5 items in the list fillList(list, 5); Assert.AreEqual(1.0f, list.Slider.ThumbSize); // Put another 15 items in the list fillList(list, 15); Assert.AreEqual(itemsInView / 20.0f, list.Slider.ThumbSize); // Put another 15 items in the list list.Items.RemoveAt(19); list.Items.RemoveAt(18); list.Items.RemoveAt(17); list.Items.RemoveAt(16); list.Items.RemoveAt(15); Assert.AreEqual(itemsInView / 15.0f, list.Slider.ThumbSize); list.Items.Clear(); Assert.AreEqual(1.0f, list.Slider.ThumbSize); } /// Mocks a subscriber for the events of a list /// Mockery through which the mock will be created /// List to mock an event subscriber for /// The mocked event subscriber private static Mock mockSubscriber(MockFactory mockery, ListControl list) { Mock mockedSubscriber = mockery.CreateMock(); list.SelectionChanged += new EventHandler(mockedSubscriber.MockObject.SelectionChanged); return mockedSubscriber; } /// Fills a list control with dummy items /// List control that will be filled /// Number of dummy items to generate private void fillList(ListControl list, int itemCount) { for(int index = 0; index < itemCount; ++index) { list.Items.Add("Item " + index.ToString()); } } } } // namespace Nuclex.UserInterface.Controls.Desktop #endif // UNITTEST