#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