using System.Data;
#nullable enable
using JetBrains.Annotations;
namespace ViewsTests;
[TestSubject (typeof (TableView))]
public class TableViewTests
{
[Fact]
public void CanTabOutOfTableViewUsingCursor_Left ()
{
GetTableViewWithSiblings (out TextField tf1, out TableView tableView, out TextField tf2);
// Make the selected cell one in
tableView.SelectedColumn = 1;
// Pressing left should move us to the first column without changing focus
tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorLeft);
Assert.Same (tableView, tableView.App!.TopRunnableView!.MostFocused);
Assert.True (tableView.HasFocus);
// Because we are now on the leftmost cell a further left press should move focus
tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorLeft);
Assert.NotSame (tableView, tableView.App!.TopRunnableView!.MostFocused);
Assert.False (tableView.HasFocus);
Assert.Same (tf1, tableView.App!.TopRunnableView.MostFocused);
Assert.True (tf1.HasFocus);
}
[Fact]
public void CanTabOutOfTableViewUsingCursor_Up ()
{
GetTableViewWithSiblings (out TextField tf1, out TableView tableView, out TextField tf2);
// Make the selected cell one in
tableView.SelectedRow = 1;
// First press should move us up
tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorUp);
Assert.Same (tableView, tableView.App!.TopRunnableView!.MostFocused);
Assert.True (tableView.HasFocus);
// Because we are now on the top row a further press should move focus
tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorUp);
Assert.NotSame (tableView, tableView.App!.TopRunnableView!.MostFocused);
Assert.False (tableView.HasFocus);
Assert.Same (tf1, tableView.App!.TopRunnableView!.MostFocused);
Assert.True (tf1.HasFocus);
}
[Fact]
public void CanTabOutOfTableViewUsingCursor_Right ()
{
GetTableViewWithSiblings (out TextField tf1, out TableView tableView, out TextField tf2);
// Make the selected cell one in from the rightmost column
tableView.SelectedColumn = tableView.Table.Columns - 2;
// First press should move us to the rightmost column without changing focus
tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorRight);
Assert.Same (tableView, tableView.App!.TopRunnableView!.MostFocused);
Assert.True (tableView.HasFocus);
// Because we are now on the rightmost cell, a further right press should move focus
tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorRight);
Assert.NotSame (tableView, tableView.App!.TopRunnableView!.MostFocused);
Assert.False (tableView.HasFocus);
Assert.Same (tf2, tableView.App!.TopRunnableView!.MostFocused);
Assert.True (tf2.HasFocus);
}
[Fact]
public void CanTabOutOfTableViewUsingCursor_Down ()
{
GetTableViewWithSiblings (out TextField tf1, out TableView tableView, out TextField tf2);
// Make the selected cell one in from the bottommost row
tableView.SelectedRow = tableView.Table.Rows - 2;
// First press should move us to the bottommost row without changing focus
tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorDown);
Assert.Same (tableView, tableView.App!.TopRunnableView!.MostFocused);
Assert.True (tableView.HasFocus);
// Because we are now on the bottommost cell, a further down press should move focus
tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorDown);
Assert.NotSame (tableView, tableView.App!.TopRunnableView!.MostFocused);
Assert.False (tableView.HasFocus);
Assert.Same (tf2, tableView.App!.TopRunnableView!.MostFocused);
Assert.True (tf2.HasFocus);
}
[Fact]
public void CanTabOutOfTableViewUsingCursor_Left_ClearsSelectionFirst ()
{
GetTableViewWithSiblings (out TextField tf1, out TableView tableView, out TextField tf2);
// Make the selected cell one in
tableView.SelectedColumn = 1;
// Pressing shift-left should give us a multi selection
tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorLeft.WithShift);
Assert.Same (tableView, tableView.App!.TopRunnableView!.MostFocused);
Assert.True (tableView.HasFocus);
Assert.Equal (2, tableView.GetAllSelectedCells ().Count ());
// Because we are now on the leftmost cell a further left press would normally move focus
// However there is an ongoing selection so instead the operation clears the selection and
// gets swallowed (not resulting in a focus change)
tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorLeft);
// Selection 'clears' just to the single cell and we remain focused
Assert.Single (tableView.GetAllSelectedCells ());
Assert.Same (tableView, tableView.App!.TopRunnableView!.MostFocused);
Assert.True (tableView.HasFocus);
// A further left will switch focus
tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorLeft);
Assert.NotSame (tableView, tableView.App!.TopRunnableView!.MostFocused);
Assert.False (tableView.HasFocus);
Assert.Same (tf1, tableView.App!.TopRunnableView!.MostFocused);
Assert.True (tf1.HasFocus);
}
///
/// Creates 3 views on with the focus in the
/// . This is a helper method to setup tests that want to
/// explore moving input focus out of a tableview.
///
///
///
///
private void GetTableViewWithSiblings (out TextField tf1, out TableView tableView, out TextField tf2)
{
IApplication? app = Application.Create ();
Runnable? runnable = new ();
app.Begin (runnable);
tableView = new ();
tf1 = new ();
tf2 = new ();
runnable.Add (tf1);
runnable.Add (tableView);
runnable.Add (tf2);
tableView.SetFocus ();
Assert.Same (tableView, runnable.MostFocused);
Assert.True (tableView.HasFocus);
// Set big table
tableView.Table = BuildTable (25, 50);
}
public static DataTableSource BuildTable (int cols, int rows) => BuildTable (cols, rows, out _);
/// Builds a simple table of string columns with the requested number of columns and rows
///
///
///
public static DataTableSource BuildTable (int cols, int rows, out DataTable dt)
{
dt = new ();
for (var c = 0; c < cols; c++)
{
dt.Columns.Add ("Col" + c);
}
for (var r = 0; r < rows; r++)
{
DataRow newRow = dt.NewRow ();
for (var c = 0; c < cols; c++)
{
newRow [c] = $"R{r}C{c}";
}
dt.Rows.Add (newRow);
}
return new (dt);
}
[Fact]
public void TableView_CollectionNavigatorMatcher_KeybindingsOverrideNavigator ()
{
var dt = new DataTable ();
dt.Columns.Add ("blah");
dt.Rows.Add ("apricot");
dt.Rows.Add ("arm");
dt.Rows.Add ("bat");
dt.Rows.Add ("batman");
dt.Rows.Add ("bates hotel");
dt.Rows.Add ("candle");
var tableView = new TableView ();
tableView.Table = new DataTableSource (dt);
tableView.HasFocus = true;
tableView.KeyBindings.Add (Key.B, Command.Down);
Assert.Equal (0, tableView.SelectedRow);
// Keys should be consumed to move down the navigation i.e. to apricot
Assert.True (tableView.NewKeyDownEvent (Key.B));
Assert.Equal (1, tableView.SelectedRow);
Assert.True (tableView.NewKeyDownEvent (Key.B));
Assert.Equal (2, tableView.SelectedRow);
// There is no keybinding for Key.C so it hits collection navigator i.e. we jump to candle
Assert.True (tableView.NewKeyDownEvent (Key.C));
Assert.Equal (5, tableView.SelectedRow);
}
}