diff --git a/Terminal.Gui/Views/ComboBox.cs b/Terminal.Gui/Views/ComboBox.cs
index ca48e21d3..8b0422173 100644
--- a/Terminal.Gui/Views/ComboBox.cs
+++ b/Terminal.Gui/Views/ComboBox.cs
@@ -24,8 +24,6 @@ public class ComboBox : View {
public ComboListView (ComboBox container, bool hideDropdownListOnClick) => SetInitialProperties (container, hideDropdownListOnClick);
- public ComboListView (ComboBox container, Rect rect, IList source, bool hideDropdownListOnClick) : base (rect, source) => SetInitialProperties (container, hideDropdownListOnClick);
-
public ComboListView (ComboBox container, IList source, bool hideDropdownListOnClick) : base (source) => SetInitialProperties (container, hideDropdownListOnClick);
void SetInitialProperties (ComboBox container, bool hideDropdownListOnClick)
diff --git a/Terminal.Gui/Views/ListView.cs b/Terminal.Gui/Views/ListView.cs
index 5e57efbe9..b4bb18c42 100644
--- a/Terminal.Gui/Views/ListView.cs
+++ b/Terminal.Gui/Views/ListView.cs
@@ -1,932 +1,906 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Text;
-namespace Terminal.Gui {
+namespace Terminal.Gui;
+///
+/// Implement to provide custom rendering for a .
+///
+public interface IListDataSource {
///
- /// Implement to provide custom rendering for a .
+ /// Returns the number of elements to display
///
- public interface IListDataSource {
- ///
- /// Returns the number of elements to display
- ///
- int Count { get; }
+ int Count { get; }
- ///
- /// Returns the maximum length of elements to display
- ///
- int Length { get; }
+ ///
+ /// Returns the maximum length of elements to display
+ ///
+ int Length { get; }
- ///
- /// This method is invoked to render a specified item, the method should cover the entire provided width.
- ///
- /// The render.
- /// The list view to render.
- /// The console driver to render.
- /// Describes whether the item being rendered is currently selected by the user.
- /// The index of the item to render, zero for the first item and so on.
- /// The column where the rendering will start
- /// The line where the rendering will be done.
- /// The width that must be filled out.
- /// The index of the string to be displayed.
- ///
- /// The default color will be set before this method is invoked, and will be based on whether the item is selected or not.
- ///
- void Render (ListView container, ConsoleDriver driver, bool selected, int item, int col, int line, int width, int start = 0);
+ ///
+ /// This method is invoked to render a specified item, the method should cover the entire provided width.
+ ///
+ /// The render.
+ /// The list view to render.
+ /// The console driver to render.
+ /// Describes whether the item being rendered is currently selected by the user.
+ /// The index of the item to render, zero for the first item and so on.
+ /// The column where the rendering will start
+ /// The line where the rendering will be done.
+ /// The width that must be filled out.
+ /// The index of the string to be displayed.
+ ///
+ /// The default color will be set before this method is invoked, and will be based on whether the item is selected or not.
+ ///
+ void Render (ListView container, ConsoleDriver driver, bool selected, int item, int col, int line, int width, int start = 0);
- ///
- /// Should return whether the specified item is currently marked.
- ///
- /// , if marked, otherwise.
- /// Item index.
- bool IsMarked (int item);
+ ///
+ /// Should return whether the specified item is currently marked.
+ ///
+ /// , if marked, otherwise.
+ /// Item index.
+ bool IsMarked (int item);
- ///
- /// Flags the item as marked.
- ///
- /// Item index.
- /// If set to value.
- void SetMark (int item, bool value);
+ ///
+ /// Flags the item as marked.
+ ///
+ /// Item index.
+ /// If set to value.
+ void SetMark (int item, bool value);
- ///
- /// Return the source as IList.
- ///
- ///
- IList ToList ();
+ ///
+ /// Return the source as IList.
+ ///
+ ///
+ IList ToList ();
+}
+
+///
+/// ListView renders a scrollable list of data where each item can be activated to perform an action.
+///
+///
+///
+/// The displays lists of data and allows the user to scroll through the data.
+/// Items in the can be activated firing an event (with the ENTER key or a mouse double-click).
+/// If the property is true, elements of the list can be marked by the user.
+///
+///
+/// By default uses to render the items of any
+/// object (e.g. arrays, ,
+/// and other collections). Alternatively, an object that implements
+/// can be provided giving full control of what is rendered.
+///
+///
+/// can display any object that implements the interface.
+/// values are converted into values before rendering, and other values are
+/// converted into by calling and then converting to .
+///
+///
+/// To change the contents of the ListView, set the property (when
+/// providing custom rendering via ) or call
+/// an is being used.
+///
+///
+/// When is set to true the rendering will prefix the rendered items with
+/// [x] or [ ] and bind the SPACE key to toggle the selection. To implement a different
+/// marking style set to false and implement custom rendering.
+///
+///
+/// Searching the ListView with the keyboard is supported. Users type the
+/// first characters of an item, and the first item that starts with what the user types will be selected.
+///
+///
+public class ListView : View {
+ int _top, _left;
+ int _selected = -1;
+
+ IListDataSource _source;
+ ///
+ /// Gets or sets the backing this , enabling custom rendering.
+ ///
+ /// The source.
+ ///
+ /// Use to set a new source.
+ ///
+ public IListDataSource Source {
+ get => _source;
+ set {
+ _source = value;
+ KeystrokeNavigator.Collection = _source?.ToList ();
+ _top = 0;
+ _selected = -1;
+ _lastSelectedItem = -1;
+ SetNeedsDisplay ();
+ }
}
///
- /// ListView renders a scrollable list of data where each item can be activated to perform an action.
+ /// Sets the source of the to an .
///
+ /// An object implementing the IList interface.
///
- ///
- /// The displays lists of data and allows the user to scroll through the data.
- /// Items in the can be activated firing an event (with the ENTER key or a mouse double-click).
- /// If the property is true, elements of the list can be marked by the user.
- ///
- ///
- /// By default uses to render the items of any
- /// object (e.g. arrays, ,
- /// and other collections). Alternatively, an object that implements
- /// can be provided giving full control of what is rendered.
- ///
- ///
- /// can display any object that implements the interface.
- /// values are converted into values before rendering, and other values are
- /// converted into by calling and then converting to .
- ///
- ///
- /// To change the contents of the ListView, set the property (when
- /// providing custom rendering via ) or call
- /// an is being used.
- ///
- ///
- /// When is set to true the rendering will prefix the rendered items with
- /// [x] or [ ] and bind the SPACE key to toggle the selection. To implement a different
- /// marking style set to false and implement custom rendering.
- ///
- ///
- /// Searching the ListView with the keyboard is supported. Users type the
- /// first characters of an item, and the first item that starts with what the user types will be selected.
- ///
+ /// Use the property to set a new source and use custome rendering.
///
- public class ListView : View {
- int top, left;
- int selected = -1;
-
- IListDataSource source;
- ///
- /// Gets or sets the backing this , enabling custom rendering.
- ///
- /// The source.
- ///
- /// Use to set a new source.
- ///
- public IListDataSource Source {
- get => source;
- set {
- source = value;
- KeystrokeNavigator.Collection = source?.ToList ();
- top = 0;
- selected = -1;
- lastSelectedItem = -1;
- SetNeedsDisplay ();
- }
+ public void SetSource (IList source)
+ {
+ if (source == null && (Source == null || !(Source is ListWrapper)))
+ Source = null;
+ else {
+ Source = MakeWrapper (source);
}
+ }
- ///
- /// Sets the source of the to an .
- ///
- /// An object implementing the IList interface.
- ///
- /// Use the property to set a new source and use custome rendering.
- ///
- public void SetSource (IList source)
- {
+ ///
+ /// Sets the source to an value asynchronously.
+ ///
+ /// An item implementing the IList interface.
+ ///
+ /// Use the property to set a new source and use custom rendering.
+ ///
+ public Task SetSourceAsync (IList source)
+ {
+ return Task.Factory.StartNew (() => {
if (source == null && (Source == null || !(Source is ListWrapper)))
Source = null;
- else {
+ else
Source = MakeWrapper (source);
+ return source;
+ }, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ }
+
+ bool _allowsMarking;
+ ///
+ /// Gets or sets whether this allows items to be marked.
+ ///
+ /// Set to to allow marking elements of the list.
+ ///
+ /// If set to , will render items marked items with "[x]", and unmarked items with "[ ]"
+ /// spaces. SPACE key will toggle marking. The default is .
+ ///
+ public bool AllowsMarking {
+ get => _allowsMarking;
+ set {
+ _allowsMarking = value;
+ if (_allowsMarking) {
+ KeyBindings.Add (KeyCode.Space, Command.ToggleChecked);
+ } else {
+ KeyBindings.Remove (KeyCode.Space);
}
+
+ SetNeedsDisplay ();
}
+ }
- ///
- /// Sets the source to an value asynchronously.
- ///
- /// An item implementing the IList interface.
- ///
- /// Use the property to set a new source and use custom rendering.
- ///
- public Task SetSourceAsync (IList source)
- {
- return Task.Factory.StartNew (() => {
- if (source == null && (Source == null || !(Source is ListWrapper)))
- Source = null;
- else
- Source = MakeWrapper (source);
- return source;
- }, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
- }
-
- bool allowsMarking;
- ///
- /// Gets or sets whether this allows items to be marked.
- ///
- /// Set to to allow marking elements of the list.
- ///
- /// If set to , will render items marked items with "[x]", and unmarked items with "[ ]"
- /// spaces. SPACE key will toggle marking. The default is .
- ///
- public bool AllowsMarking {
- get => allowsMarking;
- set {
- allowsMarking = value;
- if (allowsMarking) {
- KeyBindings.Add (KeyCode.Space, Command.ToggleChecked);
- } else {
- KeyBindings.Remove (KeyCode.Space);
- }
-
- SetNeedsDisplay ();
- }
- }
-
- ///
- /// If set to more than one item can be selected. If selecting
- /// an item will cause all others to be un-selected. The default is .
- ///
- public bool AllowsMultipleSelection {
- get => allowsMultipleSelection;
- set {
- allowsMultipleSelection = value;
- if (Source != null && !allowsMultipleSelection) {
- // Clear all selections except selected
- for (int i = 0; i < Source.Count; i++) {
- if (Source.IsMarked (i) && i != selected) {
- Source.SetMark (i, false);
- }
+ ///
+ /// If set to more than one item can be selected. If selecting
+ /// an item will cause all others to be un-selected. The default is .
+ ///
+ public bool AllowsMultipleSelection {
+ get => _allowsMultipleSelection;
+ set {
+ _allowsMultipleSelection = value;
+ if (Source != null && !_allowsMultipleSelection) {
+ // Clear all selections except selected
+ for (int i = 0; i < Source.Count; i++) {
+ if (Source.IsMarked (i) && i != _selected) {
+ Source.SetMark (i, false);
}
}
+ }
+ SetNeedsDisplay ();
+ }
+ }
+
+ ///
+ /// Gets or sets the item that is displayed at the top of the .
+ ///
+ /// The top item.
+ public int TopItem {
+ get => _top;
+ set {
+ if (_source == null)
+ return;
+
+ if (value < 0 || (_source.Count > 0 && value >= _source.Count))
+ throw new ArgumentException ("value");
+ _top = Math.Max (value, 0);
+ SetNeedsDisplay ();
+ }
+ }
+
+ ///
+ /// Gets or sets the leftmost column that is currently visible (when scrolling horizontally).
+ ///
+ /// The left position.
+ public int LeftItem {
+ get => _left;
+ set {
+ if (_source == null)
+ return;
+
+ if (value < 0 || (Maxlength > 0 && value >= Maxlength))
+ throw new ArgumentException ("value");
+ _left = value;
+ SetNeedsDisplay ();
+ }
+ }
+
+ ///
+ /// Gets the widest item in the list.
+ ///
+ public int Maxlength => (_source?.Length) ?? 0;
+
+ ///
+ /// Gets or sets the index of the currently selected item.
+ ///
+ /// The selected item.
+ public int SelectedItem {
+ get => _selected;
+ set {
+ if (_source == null || _source.Count == 0) {
+ return;
+ }
+ if (value < -1 || value >= _source.Count) {
+ throw new ArgumentException ("value");
+ }
+ _selected = value;
+ OnSelectedChanged ();
+ }
+ }
+
+ static IListDataSource MakeWrapper (IList source)
+ {
+ return new ListWrapper (source);
+ }
+
+ ///
+ /// Initializes a new instance of . Set the property to display something.
+ ///
+ public ListView ()
+ {
+ SetInitialProperties ();
+ }
+
+ ///
+ /// Initializes a new instance of that will display the provided data source, using relative positioning.
+ ///
+ /// object that provides a mechanism to render the data.
+ /// The number of elements on the collection should not change, if you must change, set
+ /// the "Source" property to reset the internal settings of the ListView.
+ public ListView (IListDataSource source)
+ {
+ this._source = source;
+ SetInitialProperties ();
+ }
+
+ ///
+ /// Initializes a new instance of that will display the contents of the object
+ /// implementing the interface with an absolute position.
+ ///
+ /// An IList data source, if the elements of the IList are strings,
+ /// the string is rendered, otherwise the ToString() method is invoked on the result.
+ public ListView (IList source) : this (MakeWrapper (source))
+ {
+ SetInitialProperties ();
+ }
+
+ void SetInitialProperties ()
+ {
+ Source = _source;
+ CanFocus = true;
+
+ // Things this view knows how to do
+ AddCommand (Command.LineUp, () => MoveUp ());
+ AddCommand (Command.LineDown, () => MoveDown ());
+ AddCommand (Command.ScrollUp, () => ScrollUp (1));
+ AddCommand (Command.ScrollDown, () => ScrollDown (1));
+ AddCommand (Command.PageUp, () => MovePageUp ());
+ AddCommand (Command.PageDown, () => MovePageDown ());
+ AddCommand (Command.TopHome, () => MoveHome ());
+ AddCommand (Command.BottomEnd, () => MoveEnd ());
+ AddCommand (Command.OpenSelectedItem, () => OnOpenSelectedItem ());
+ AddCommand (Command.ToggleChecked, () => MarkUnmarkRow ());
+
+ // Default keybindings for all ListViews
+ KeyBindings.Add (KeyCode.CursorUp, Command.LineUp);
+ KeyBindings.Add (KeyCode.P | KeyCode.CtrlMask, Command.LineUp);
+
+ KeyBindings.Add (KeyCode.CursorDown, Command.LineDown);
+ KeyBindings.Add (KeyCode.N | KeyCode.CtrlMask, Command.LineDown);
+
+ KeyBindings.Add (KeyCode.PageUp, Command.PageUp);
+
+ KeyBindings.Add (KeyCode.PageDown, Command.PageDown);
+ KeyBindings.Add (KeyCode.V | KeyCode.CtrlMask, Command.PageDown);
+
+ KeyBindings.Add (KeyCode.Home, Command.TopHome);
+
+ KeyBindings.Add (KeyCode.End, Command.BottomEnd);
+
+ KeyBindings.Add (KeyCode.Enter, Command.OpenSelectedItem);
+ }
+
+ ///
+ public override void OnDrawContent (Rect contentArea)
+ {
+ base.OnDrawContent (contentArea);
+
+ var current = ColorScheme.Focus;
+ Driver.SetAttribute (current);
+ Move (0, 0);
+ var f = Bounds;
+ var item = _top;
+ bool focused = HasFocus;
+ int col = _allowsMarking ? 2 : 0;
+ int start = _left;
+
+ for (int row = 0; row < f.Height; row++, item++) {
+ bool isSelected = item == _selected;
+
+ var newcolor = focused ? (isSelected ? ColorScheme.Focus : GetNormalColor ())
+ : (isSelected ? ColorScheme.HotNormal : GetNormalColor ());
+
+ if (newcolor != current) {
+ Driver.SetAttribute (newcolor);
+ current = newcolor;
+ }
+
+ Move (0, row);
+ if (_source == null || item >= _source.Count) {
+ for (int c = 0; c < f.Width; c++)
+ Driver.AddRune ((Rune)' ');
+ } else {
+ var rowEventArgs = new ListViewRowEventArgs (item);
+ OnRowRender (rowEventArgs);
+ if (rowEventArgs.RowAttribute != null && current != rowEventArgs.RowAttribute) {
+ current = (Attribute)rowEventArgs.RowAttribute;
+ Driver.SetAttribute (current);
+ }
+ if (_allowsMarking) {
+ Driver.AddRune (_source.IsMarked (item) ? (AllowsMultipleSelection ? CM.Glyphs.Checked : CM.Glyphs.Selected) :
+ (AllowsMultipleSelection ? CM.Glyphs.UnChecked : CM.Glyphs.UnSelected));
+ Driver.AddRune ((Rune)' ');
+ }
+ Source.Render (this, Driver, isSelected, item, col, row, f.Width - col, start);
+ }
+ }
+ }
+
+ ///
+ /// This event is raised when the selected item in the has changed.
+ ///
+ public event EventHandler SelectedItemChanged;
+
+ ///
+ /// This event is raised when the user Double Clicks on an item or presses ENTER to open the selected item.
+ ///
+ public event EventHandler OpenSelectedItem;
+
+ ///
+ /// This event is invoked when this is being drawn before rendering.
+ ///
+ public event EventHandler RowRender;
+
+ ///
+ /// Gets the that searches the collection as
+ /// the user types.
+ ///
+ public CollectionNavigator KeystrokeNavigator { get; private set; } = new CollectionNavigator ();
+
+ ///
+ public override bool OnProcessKeyDown (Key a)
+ {
+ // Enable user to find & select an item by typing text
+ if (CollectionNavigator.IsCompatibleKey (a)) {
+ var newItem = KeystrokeNavigator?.GetNextMatchingItem (SelectedItem, (char)a);
+ if (newItem is int && newItem != -1) {
+ SelectedItem = (int)newItem;
+ EnsureSelectedItemVisible ();
SetNeedsDisplay ();
+ return true;
}
}
+ return false;
+ }
- ///
- /// Gets or sets the item that is displayed at the top of the .
- ///
- /// The top item.
- public int TopItem {
- get => top;
- set {
- if (source == null)
- return;
-
- if (value < 0 || (source.Count > 0 && value >= source.Count))
- throw new ArgumentException ("value");
- top = Math.Max (value, 0);
- SetNeedsDisplay ();
- }
- }
-
- ///
- /// Gets or sets the leftmost column that is currently visible (when scrolling horizontally).
- ///
- /// The left position.
- public int LeftItem {
- get => left;
- set {
- if (source == null)
- return;
-
- if (value < 0 || (Maxlength > 0 && value >= Maxlength))
- throw new ArgumentException ("value");
- left = value;
- SetNeedsDisplay ();
- }
- }
-
- ///
- /// Gets the widest item in the list.
- ///
- public int Maxlength => (source?.Length) ?? 0;
-
- ///
- /// Gets or sets the index of the currently selected item.
- ///
- /// The selected item.
- public int SelectedItem {
- get => selected;
- set {
- if (source == null || source.Count == 0) {
- return;
- }
- if (value < -1 || value >= source.Count) {
- throw new ArgumentException ("value");
- }
- selected = value;
- OnSelectedChanged ();
- }
- }
-
- static IListDataSource MakeWrapper (IList source)
- {
- return new ListWrapper (source);
- }
-
- ///
- /// Initializes a new instance of that will display the
- /// contents of the object implementing the interface,
- /// with relative positioning.
- ///
- /// An data source, if the elements are strings or ustrings,
- /// the string is rendered, otherwise the ToString() method is invoked on the result.
- public ListView (IList source) : this (MakeWrapper (source))
- {
- }
-
- ///
- /// Initializes a new instance of that will display the provided data source, using relative positioning.
- ///
- /// object that provides a mechanism to render the data.
- /// The number of elements on the collection should not change, if you must change, set
- /// the "Source" property to reset the internal settings of the ListView.
- public ListView (IListDataSource source) : base ()
- {
- this.source = source;
- Initialize ();
- }
-
- ///
- /// Initializes a new instance of . Set the property to display something.
- ///
- public ListView () : base ()
- {
- Initialize ();
- }
-
- ///
- /// Initializes a new instance of that will display the contents of the object implementing the interface with an absolute position.
- ///
- /// Frame for the listview.
- /// An IList data source, if the elements of the IList are strings or ustrings,
- /// the string is rendered, otherwise the ToString() method is invoked on the result.
- public ListView (Rect rect, IList source) : this (rect, MakeWrapper (source))
- {
- Initialize ();
- }
-
- ///
- /// Initializes a new instance of with the provided data source and an absolute position
- ///
- /// Frame for the listview.
- /// IListDataSource object that provides a mechanism to render the data.
- /// The number of elements on the collection should not change, if you must change,
- /// set the "Source" property to reset the internal settings of the ListView.
- public ListView (Rect rect, IListDataSource source) : base (rect)
- {
- this.source = source;
- Initialize ();
- }
-
- void Initialize ()
- {
- Source = source;
- CanFocus = true;
-
- // Things this view knows how to do
- AddCommand (Command.LineUp, () => MoveUp ());
- AddCommand (Command.LineDown, () => MoveDown ());
- AddCommand (Command.ScrollUp, () => ScrollUp (1));
- AddCommand (Command.ScrollDown, () => ScrollDown (1));
- AddCommand (Command.PageUp, () => MovePageUp ());
- AddCommand (Command.PageDown, () => MovePageDown ());
- AddCommand (Command.TopHome, () => MoveHome ());
- AddCommand (Command.BottomEnd, () => MoveEnd ());
- AddCommand (Command.OpenSelectedItem, () => OnOpenSelectedItem ());
- AddCommand (Command.ToggleChecked, () => MarkUnmarkRow ());
-
- // Default keybindings for all ListViews
- KeyBindings.Add (KeyCode.CursorUp, Command.LineUp);
- KeyBindings.Add (KeyCode.P | KeyCode.CtrlMask, Command.LineUp);
-
- KeyBindings.Add (KeyCode.CursorDown, Command.LineDown);
- KeyBindings.Add (KeyCode.N | KeyCode.CtrlMask, Command.LineDown);
-
- KeyBindings.Add (KeyCode.PageUp, Command.PageUp);
-
- KeyBindings.Add (KeyCode.PageDown, Command.PageDown);
- KeyBindings.Add (KeyCode.V | KeyCode.CtrlMask, Command.PageDown);
-
- KeyBindings.Add (KeyCode.Home, Command.TopHome);
-
- KeyBindings.Add (KeyCode.End, Command.BottomEnd);
-
- KeyBindings.Add (KeyCode.Enter, Command.OpenSelectedItem);
- }
-
- ///
- public override void OnDrawContent (Rect contentArea)
- {
- base.OnDrawContent (contentArea);
-
- var current = ColorScheme.Focus;
- Driver.SetAttribute (current);
- Move (0, 0);
- var f = Bounds;
- var item = top;
- bool focused = HasFocus;
- int col = allowsMarking ? 2 : 0;
- int start = left;
-
- for (int row = 0; row < f.Height; row++, item++) {
- bool isSelected = item == selected;
-
- var newcolor = focused ? (isSelected ? ColorScheme.Focus : GetNormalColor ())
- : (isSelected ? ColorScheme.HotNormal : GetNormalColor ());
-
- if (newcolor != current) {
- Driver.SetAttribute (newcolor);
- current = newcolor;
- }
-
- Move (0, row);
- if (source == null || item >= source.Count) {
- for (int c = 0; c < f.Width; c++)
- Driver.AddRune ((Rune)' ');
- } else {
- var rowEventArgs = new ListViewRowEventArgs (item);
- OnRowRender (rowEventArgs);
- if (rowEventArgs.RowAttribute != null && current != rowEventArgs.RowAttribute) {
- current = (Attribute)rowEventArgs.RowAttribute;
- Driver.SetAttribute (current);
- }
- if (allowsMarking) {
- Driver.AddRune (source.IsMarked (item) ? (AllowsMultipleSelection ? CM.Glyphs.Checked : CM.Glyphs.Selected) :
- (AllowsMultipleSelection ? CM.Glyphs.UnChecked : CM.Glyphs.UnSelected));
- Driver.AddRune ((Rune)' ');
- }
- Source.Render (this, Driver, isSelected, item, col, row, f.Width - col, start);
- }
- }
- }
-
- ///
- /// This event is raised when the selected item in the has changed.
- ///
- public event EventHandler SelectedItemChanged;
-
- ///
- /// This event is raised when the user Double Clicks on an item or presses ENTER to open the selected item.
- ///
- public event EventHandler OpenSelectedItem;
-
- ///
- /// This event is invoked when this is being drawn before rendering.
- ///
- public event EventHandler RowRender;
-
- ///
- /// Gets the that searches the collection as
- /// the user types.
- ///
- public CollectionNavigator KeystrokeNavigator { get; private set; } = new CollectionNavigator ();
-
- ///
- public override bool OnProcessKeyDown (Key a)
- {
- // Enable user to find & select an item by typing text
- if (CollectionNavigator.IsCompatibleKey (a)) {
- var newItem = KeystrokeNavigator?.GetNextMatchingItem (SelectedItem, (char)a);
- if (newItem is int && newItem != -1) {
- SelectedItem = (int)newItem;
- EnsureSelectedItemVisible ();
- SetNeedsDisplay ();
+ ///
+ /// If and are both ,
+ /// unmarks all marked items other than the currently selected.
+ ///
+ /// if unmarking was successful.
+ public virtual bool AllowsAll ()
+ {
+ if (!_allowsMarking)
+ return false;
+ if (!AllowsMultipleSelection) {
+ for (int i = 0; i < Source.Count; i++) {
+ if (Source.IsMarked (i) && i != _selected) {
+ Source.SetMark (i, false);
return true;
}
}
- return false;
- }
-
- ///
- /// If and are both ,
- /// unmarks all marked items other than the currently selected.
- ///
- /// if unmarking was successful.
- public virtual bool AllowsAll ()
- {
- if (!allowsMarking)
- return false;
- if (!AllowsMultipleSelection) {
- for (int i = 0; i < Source.Count; i++) {
- if (Source.IsMarked (i) && i != selected) {
- Source.SetMark (i, false);
- return true;
- }
- }
- }
- return true;
- }
-
- ///
- /// Marks the if it is not already marked.
- ///
- /// if the was marked.
- public virtual bool MarkUnmarkRow ()
- {
- if (AllowsAll ()) {
- Source.SetMark (SelectedItem, !Source.IsMarked (SelectedItem));
- SetNeedsDisplay ();
- return true;
- }
-
- return false;
- }
-
- ///
- /// Changes the to the item at the top of the visible list.
- ///
- ///
- public virtual bool MovePageUp ()
- {
- int n = (selected - Bounds.Height);
- if (n < 0)
- n = 0;
- if (n != selected) {
- selected = n;
- top = Math.Max (selected, 0);
- OnSelectedChanged ();
- SetNeedsDisplay ();
- }
-
- return true;
- }
-
- ///
- /// Changes the to the item just below the bottom
- /// of the visible list, scrolling if needed.
- ///
- ///
- public virtual bool MovePageDown ()
- {
- var n = (selected + Bounds.Height);
- if (n >= source.Count)
- n = source.Count - 1;
- if (n != selected) {
- selected = n;
- if (source.Count >= Bounds.Height)
- top = Math.Max (selected, 0);
- else
- top = 0;
- OnSelectedChanged ();
- SetNeedsDisplay ();
- }
-
- return true;
- }
-
- ///
- /// Changes the to the next item in the list,
- /// scrolling the list if needed.
- ///
- ///
- public virtual bool MoveDown ()
- {
- if (source.Count == 0) {
- // Do we set lastSelectedItem to -1 here?
- return false; //Nothing for us to move to
- }
- if (selected >= source.Count) {
- // If for some reason we are currently outside of the
- // valid values range, we should select the bottommost valid value.
- // This can occur if the backing data source changes.
- selected = source.Count - 1;
- OnSelectedChanged ();
- SetNeedsDisplay ();
- } else if (selected + 1 < source.Count) { //can move by down by one.
- selected++;
-
- if (selected >= top + Bounds.Height) {
- top++;
- } else if (selected < top) {
- top = Math.Max (selected, 0);
- }
- OnSelectedChanged ();
- SetNeedsDisplay ();
- } else if (selected == 0) {
- OnSelectedChanged ();
- SetNeedsDisplay ();
- } else if (selected >= top + Bounds.Height) {
- top = Math.Max (source.Count - Bounds.Height, 0);
- SetNeedsDisplay ();
- }
-
- return true;
- }
-
- ///
- /// Changes the to the previous item in the list,
- /// scrolling the list if needed.
- ///
- ///
- public virtual bool MoveUp ()
- {
- if (source.Count == 0) {
- // Do we set lastSelectedItem to -1 here?
- return false; //Nothing for us to move to
- }
- if (selected >= source.Count) {
- // If for some reason we are currently outside of the
- // valid values range, we should select the bottommost valid value.
- // This can occur if the backing data source changes.
- selected = source.Count - 1;
- OnSelectedChanged ();
- SetNeedsDisplay ();
- } else if (selected > 0) {
- selected--;
- if (selected > Source.Count) {
- selected = Source.Count - 1;
- }
- if (selected < top) {
- top = Math.Max (selected, 0);
- } else if (selected > top + Bounds.Height) {
- top = Math.Max (selected - Bounds.Height + 1, 0);
- }
- OnSelectedChanged ();
- SetNeedsDisplay ();
- } else if (selected < top) {
- top = Math.Max (selected, 0);
- SetNeedsDisplay ();
- }
- return true;
- }
-
- ///
- /// Changes the to last item in the list,
- /// scrolling the list if needed.
- ///
- ///
- public virtual bool MoveEnd ()
- {
- if (source.Count > 0 && selected != source.Count - 1) {
- selected = source.Count - 1;
- if (top + selected > Bounds.Height - 1) {
- top = Math.Max (selected, 0);
- }
- OnSelectedChanged ();
- SetNeedsDisplay ();
- }
-
- return true;
- }
-
- ///
- /// Changes the to the first item in the list,
- /// scrolling the list if needed.
- ///
- ///
- public virtual bool MoveHome ()
- {
- if (selected != 0) {
- selected = 0;
- top = Math.Max (selected, 0);
- OnSelectedChanged ();
- SetNeedsDisplay ();
- }
-
- return true;
- }
-
- ///
- /// Scrolls the view down by items.
- ///
- /// Number of items to scroll down.
- public virtual bool ScrollDown (int items)
- {
- top = Math.Max (Math.Min (top + items, source.Count - 1), 0);
- SetNeedsDisplay ();
- return true;
- }
-
- ///
- /// Scrolls the view up by items.
- ///
- /// Number of items to scroll up.
- public virtual bool ScrollUp (int items)
- {
- top = Math.Max (top - items, 0);
- SetNeedsDisplay ();
- return true;
- }
-
- ///
- /// Scrolls the view right.
- ///
- /// Number of columns to scroll right.
- public virtual bool ScrollRight (int cols)
- {
- left = Math.Max (Math.Min (left + cols, Maxlength - 1), 0);
- SetNeedsDisplay ();
- return true;
- }
-
- ///
- /// Scrolls the view left.
- ///
- /// Number of columns to scroll left.
- public virtual bool ScrollLeft (int cols)
- {
- left = Math.Max (left - cols, 0);
- SetNeedsDisplay ();
- return true;
- }
-
- int lastSelectedItem = -1;
- private bool allowsMultipleSelection = true;
-
- ///
- /// Invokes the event if it is defined.
- ///
- ///
- public virtual bool OnSelectedChanged ()
- {
- if (selected != lastSelectedItem) {
- var value = source?.Count > 0 ? source.ToList () [selected] : null;
- SelectedItemChanged?.Invoke (this, new ListViewItemEventArgs (selected, value));
- lastSelectedItem = selected;
- EnsureSelectedItemVisible ();
- return true;
- }
-
- return false;
- }
-
- ///
- /// Invokes the event if it is defined.
- ///
- ///
- public virtual bool OnOpenSelectedItem ()
- {
- if (source.Count <= selected || selected < 0 || OpenSelectedItem == null) {
- return false;
- }
-
- var value = source.ToList () [selected];
-
- OpenSelectedItem?.Invoke (this, new ListViewItemEventArgs (selected, value));
-
- return true;
- }
-
- ///
- /// Virtual method that will invoke the .
- ///
- ///
- public virtual void OnRowRender (ListViewRowEventArgs rowEventArgs)
- {
- RowRender?.Invoke (this, rowEventArgs);
- }
-
- ///
- public override bool OnEnter (View view)
- {
- if (IsInitialized) {
- Application.Driver.SetCursorVisibility (CursorVisibility.Invisible);
- }
- if (lastSelectedItem != selected) {
- EnsureSelectedItemVisible ();
- }
-
- return base.OnEnter (view);
- }
-
- ///
- /// Ensures the selected item is always visible on the screen.
- ///
- public void EnsureSelectedItemVisible ()
- {
- if (SuperView?.IsInitialized == true) {
- if (selected < top) {
- top = Math.Max (selected, 0);
- } else if (Bounds.Height > 0 && selected >= top + Bounds.Height) {
- top = Math.Max (selected - Bounds.Height + 1, 0);
- }
- LayoutStarted -= ListView_LayoutStarted;
- } else {
- LayoutStarted += ListView_LayoutStarted;
- }
- }
-
- private void ListView_LayoutStarted (object sender, LayoutEventArgs e)
- {
- EnsureSelectedItemVisible ();
- }
-
- ///
- public override void PositionCursor ()
- {
- if (allowsMarking)
- Move (0, selected - top);
- else
- Move (Bounds.Width - 1, selected - top);
- }
-
- ///
- public override bool MouseEvent (MouseEvent me)
- {
- if (!me.Flags.HasFlag (MouseFlags.Button1Clicked) && !me.Flags.HasFlag (MouseFlags.Button1DoubleClicked) &&
- me.Flags != MouseFlags.WheeledDown && me.Flags != MouseFlags.WheeledUp &&
- me.Flags != MouseFlags.WheeledRight && me.Flags != MouseFlags.WheeledLeft)
- return false;
-
- if (!HasFocus && CanFocus) {
- SetFocus ();
- }
-
- if (source == null) {
- return false;
- }
-
- if (me.Flags == MouseFlags.WheeledDown) {
- ScrollDown (1);
- return true;
- } else if (me.Flags == MouseFlags.WheeledUp) {
- ScrollUp (1);
- return true;
- } else if (me.Flags == MouseFlags.WheeledRight) {
- ScrollRight (1);
- return true;
- } else if (me.Flags == MouseFlags.WheeledLeft) {
- ScrollLeft (1);
- return true;
- }
-
- if (me.Y + top >= source.Count
- || me.Y + top < 0
- || me.Y + top > top + Bounds.Height) {
- return true;
- }
-
- selected = top + me.Y;
- if (AllowsAll ()) {
- Source.SetMark (SelectedItem, !Source.IsMarked (SelectedItem));
- SetNeedsDisplay ();
- return true;
- }
- OnSelectedChanged ();
- SetNeedsDisplay ();
- if (me.Flags == MouseFlags.Button1DoubleClicked) {
- OnOpenSelectedItem ();
- }
-
- return true;
}
+ return true;
}
///
- /// Provides a default implementation of that renders
- /// items using .
+ /// Marks the if it is not already marked.
///
- public class ListWrapper : IListDataSource {
- IList src;
- BitArray marks;
- int count, len;
-
- ///
- public ListWrapper (IList source)
- {
- if (source != null) {
- count = source.Count;
- marks = new BitArray (count);
- src = source;
- len = GetMaxLengthItem ();
- }
+ /// if the was marked.
+ public virtual bool MarkUnmarkRow ()
+ {
+ if (AllowsAll ()) {
+ Source.SetMark (SelectedItem, !Source.IsMarked (SelectedItem));
+ SetNeedsDisplay ();
+ return true;
}
- ///
- public int Count => src != null ? src.Count : 0;
+ return false;
+ }
- ///
- public int Length => len;
-
- int GetMaxLengthItem ()
- {
- if (src == null || src?.Count == 0) {
- return 0;
- }
-
- int maxLength = 0;
- for (int i = 0; i < src.Count; i++) {
- var t = src [i];
- int l;
- if (t is string u) {
- l = u.GetColumns ();
- } else if (t is string s) {
- l = s.Length;
- } else {
- l = t.ToString ().Length;
- }
-
- if (l > maxLength) {
- maxLength = l;
- }
- }
-
- return maxLength;
+ ///
+ /// Changes the to the item at the top of the visible list.
+ ///
+ ///
+ public virtual bool MovePageUp ()
+ {
+ int n = (_selected - Bounds.Height);
+ if (n < 0)
+ n = 0;
+ if (n != _selected) {
+ _selected = n;
+ _top = Math.Max (_selected, 0);
+ OnSelectedChanged ();
+ SetNeedsDisplay ();
}
- void RenderUstr (ConsoleDriver driver, string ustr, int col, int line, int width, int start = 0)
- {
- var u = TextFormatter.ClipAndJustify (ustr, width, TextAlignment.Left);
- driver.AddStr (u);
- width -= u.GetColumns ();
- while (width-- > 0) {
- driver.AddRune ((Rune)' ');
- }
+ return true;
+ }
+
+ ///
+ /// Changes the to the item just below the bottom
+ /// of the visible list, scrolling if needed.
+ ///
+ ///
+ public virtual bool MovePageDown ()
+ {
+ var n = (_selected + Bounds.Height);
+ if (n >= _source.Count)
+ n = _source.Count - 1;
+ if (n != _selected) {
+ _selected = n;
+ if (_source.Count >= Bounds.Height)
+ _top = Math.Max (_selected, 0);
+ else
+ _top = 0;
+ OnSelectedChanged ();
+ SetNeedsDisplay ();
}
- ///
- public void Render (ListView container, ConsoleDriver driver, bool marked, int item, int col, int line, int width, int start = 0)
- {
- container.Move (col, line);
- var t = src? [item];
- if (t == null) {
- RenderUstr (driver, "", col, line, width);
- } else {
- if (t is string u) {
- RenderUstr (driver, u, col, line, width, start);
- } else if (t is string s) {
- RenderUstr (driver, s, col, line, width, start);
- } else {
- RenderUstr (driver, t.ToString (), col, line, width, start);
- }
+ return true;
+ }
+
+ ///
+ /// Changes the to the next item in the list,
+ /// scrolling the list if needed.
+ ///
+ ///
+ public virtual bool MoveDown ()
+ {
+ if (_source.Count == 0) {
+ // Do we set lastSelectedItem to -1 here?
+ return false; //Nothing for us to move to
+ }
+ if (_selected >= _source.Count) {
+ // If for some reason we are currently outside of the
+ // valid values range, we should select the bottommost valid value.
+ // This can occur if the backing data source changes.
+ _selected = _source.Count - 1;
+ OnSelectedChanged ();
+ SetNeedsDisplay ();
+ } else if (_selected + 1 < _source.Count) { //can move by down by one.
+ _selected++;
+
+ if (_selected >= _top + Bounds.Height) {
+ _top++;
+ } else if (_selected < _top) {
+ _top = Math.Max (_selected, 0);
}
+ OnSelectedChanged ();
+ SetNeedsDisplay ();
+ } else if (_selected == 0) {
+ OnSelectedChanged ();
+ SetNeedsDisplay ();
+ } else if (_selected >= _top + Bounds.Height) {
+ _top = Math.Max (_source.Count - Bounds.Height, 0);
+ SetNeedsDisplay ();
}
- ///
- public bool IsMarked (int item)
- {
- if (item >= 0 && item < count)
- return marks [item];
+ return true;
+ }
+
+ ///
+ /// Changes the to the previous item in the list,
+ /// scrolling the list if needed.
+ ///
+ ///
+ public virtual bool MoveUp ()
+ {
+ if (_source.Count == 0) {
+ // Do we set lastSelectedItem to -1 here?
+ return false; //Nothing for us to move to
+ }
+ if (_selected >= _source.Count) {
+ // If for some reason we are currently outside of the
+ // valid values range, we should select the bottommost valid value.
+ // This can occur if the backing data source changes.
+ _selected = _source.Count - 1;
+ OnSelectedChanged ();
+ SetNeedsDisplay ();
+ } else if (_selected > 0) {
+ _selected--;
+ if (_selected > Source.Count) {
+ _selected = Source.Count - 1;
+ }
+ if (_selected < _top) {
+ _top = Math.Max (_selected, 0);
+ } else if (_selected > _top + Bounds.Height) {
+ _top = Math.Max (_selected - Bounds.Height + 1, 0);
+ }
+ OnSelectedChanged ();
+ SetNeedsDisplay ();
+ } else if (_selected < _top) {
+ _top = Math.Max (_selected, 0);
+ SetNeedsDisplay ();
+ }
+ return true;
+ }
+
+ ///
+ /// Changes the to last item in the list,
+ /// scrolling the list if needed.
+ ///
+ ///
+ public virtual bool MoveEnd ()
+ {
+ if (_source.Count > 0 && _selected != _source.Count - 1) {
+ _selected = _source.Count - 1;
+ if (_top + _selected > Bounds.Height - 1) {
+ _top = Math.Max (_selected, 0);
+ }
+ OnSelectedChanged ();
+ SetNeedsDisplay ();
+ }
+
+ return true;
+ }
+
+ ///
+ /// Changes the to the first item in the list,
+ /// scrolling the list if needed.
+ ///
+ ///
+ public virtual bool MoveHome ()
+ {
+ if (_selected != 0) {
+ _selected = 0;
+ _top = Math.Max (_selected, 0);
+ OnSelectedChanged ();
+ SetNeedsDisplay ();
+ }
+
+ return true;
+ }
+
+ ///
+ /// Scrolls the view down by items.
+ ///
+ /// Number of items to scroll down.
+ public virtual bool ScrollDown (int items)
+ {
+ _top = Math.Max (Math.Min (_top + items, _source.Count - 1), 0);
+ SetNeedsDisplay ();
+ return true;
+ }
+
+ ///
+ /// Scrolls the view up by items.
+ ///
+ /// Number of items to scroll up.
+ public virtual bool ScrollUp (int items)
+ {
+ _top = Math.Max (_top - items, 0);
+ SetNeedsDisplay ();
+ return true;
+ }
+
+ ///
+ /// Scrolls the view right.
+ ///
+ /// Number of columns to scroll right.
+ public virtual bool ScrollRight (int cols)
+ {
+ _left = Math.Max (Math.Min (_left + cols, Maxlength - 1), 0);
+ SetNeedsDisplay ();
+ return true;
+ }
+
+ ///
+ /// Scrolls the view left.
+ ///
+ /// Number of columns to scroll left.
+ public virtual bool ScrollLeft (int cols)
+ {
+ _left = Math.Max (_left - cols, 0);
+ SetNeedsDisplay ();
+ return true;
+ }
+
+ int _lastSelectedItem = -1;
+ private bool _allowsMultipleSelection = true;
+
+ ///
+ /// Invokes the event if it is defined.
+ ///
+ ///
+ public virtual bool OnSelectedChanged ()
+ {
+ if (_selected != _lastSelectedItem) {
+ var value = _source?.Count > 0 ? _source.ToList () [_selected] : null;
+ SelectedItemChanged?.Invoke (this, new ListViewItemEventArgs (_selected, value));
+ _lastSelectedItem = _selected;
+ EnsureSelectedItemVisible ();
+ return true;
+ }
+
+ return false;
+ }
+
+ ///
+ /// Invokes the event if it is defined.
+ ///
+ ///
+ public virtual bool OnOpenSelectedItem ()
+ {
+ if (_source.Count <= _selected || _selected < 0 || OpenSelectedItem == null) {
return false;
}
- ///
- public void SetMark (int item, bool value)
- {
- if (item >= 0 && item < count)
- marks [item] = value;
+ var value = _source.ToList () [_selected];
+
+ OpenSelectedItem?.Invoke (this, new ListViewItemEventArgs (_selected, value));
+
+ return true;
+ }
+
+ ///
+ /// Virtual method that will invoke the .
+ ///
+ ///
+ public virtual void OnRowRender (ListViewRowEventArgs rowEventArgs)
+ {
+ RowRender?.Invoke (this, rowEventArgs);
+ }
+
+ ///
+ public override bool OnEnter (View view)
+ {
+ if (IsInitialized) {
+ Application.Driver.SetCursorVisibility (CursorVisibility.Invisible);
+ }
+ if (_lastSelectedItem != _selected) {
+ EnsureSelectedItemVisible ();
}
- ///
- public IList ToList ()
- {
- return src;
- }
+ return base.OnEnter (view);
+ }
- ///
- public int StartsWith (string search)
- {
- if (src == null || src?.Count == 0) {
- return -1;
+ ///
+ /// Ensures the selected item is always visible on the screen.
+ ///
+ public void EnsureSelectedItemVisible ()
+ {
+ if (SuperView?.IsInitialized == true) {
+ if (_selected < _top) {
+ _top = Math.Max (_selected, 0);
+ } else if (Bounds.Height > 0 && _selected >= _top + Bounds.Height) {
+ _top = Math.Max (_selected - Bounds.Height + 1, 0);
}
-
- for (int i = 0; i < src.Count; i++) {
- var t = src [i];
- if (t is string u) {
- if (u.ToUpper ().StartsWith (search.ToUpperInvariant ())) {
- return i;
- }
- } else if (t is string s) {
- if (s.StartsWith (search, StringComparison.InvariantCultureIgnoreCase)) {
- return i;
- }
- }
- }
- return -1;
+ LayoutStarted -= ListView_LayoutStarted;
+ } else {
+ LayoutStarted += ListView_LayoutStarted;
}
}
+
+ private void ListView_LayoutStarted (object sender, LayoutEventArgs e)
+ {
+ EnsureSelectedItemVisible ();
+ }
+
+ ///
+ public override void PositionCursor ()
+ {
+ if (_allowsMarking)
+ Move (0, _selected - _top);
+ else
+ Move (Bounds.Width - 1, _selected - _top);
+ }
+
+ ///
+ public override bool MouseEvent (MouseEvent me)
+ {
+ if (!me.Flags.HasFlag (MouseFlags.Button1Clicked) && !me.Flags.HasFlag (MouseFlags.Button1DoubleClicked) &&
+ me.Flags != MouseFlags.WheeledDown && me.Flags != MouseFlags.WheeledUp &&
+ me.Flags != MouseFlags.WheeledRight && me.Flags != MouseFlags.WheeledLeft)
+ return false;
+
+ if (!HasFocus && CanFocus) {
+ SetFocus ();
+ }
+
+ if (_source == null) {
+ return false;
+ }
+
+ if (me.Flags == MouseFlags.WheeledDown) {
+ ScrollDown (1);
+ return true;
+ } else if (me.Flags == MouseFlags.WheeledUp) {
+ ScrollUp (1);
+ return true;
+ } else if (me.Flags == MouseFlags.WheeledRight) {
+ ScrollRight (1);
+ return true;
+ } else if (me.Flags == MouseFlags.WheeledLeft) {
+ ScrollLeft (1);
+ return true;
+ }
+
+ if (me.Y + _top >= _source.Count
+ || me.Y + _top < 0
+ || me.Y + _top > _top + Bounds.Height) {
+ return true;
+ }
+
+ _selected = _top + me.Y;
+ if (AllowsAll ()) {
+ Source.SetMark (SelectedItem, !Source.IsMarked (SelectedItem));
+ SetNeedsDisplay ();
+ return true;
+ }
+ OnSelectedChanged ();
+ SetNeedsDisplay ();
+ if (me.Flags == MouseFlags.Button1DoubleClicked) {
+ OnOpenSelectedItem ();
+ }
+
+ return true;
+ }
+}
+
+///
+/// Provides a default implementation of that renders
+/// items using .
+///
+public class ListWrapper : IListDataSource {
+ IList src;
+ BitArray marks;
+ int count, len;
+
+ ///
+ public ListWrapper (IList source)
+ {
+ if (source != null) {
+ count = source.Count;
+ marks = new BitArray (count);
+ src = source;
+ len = GetMaxLengthItem ();
+ }
+ }
+
+ ///
+ public int Count => src != null ? src.Count : 0;
+
+ ///
+ public int Length => len;
+
+ int GetMaxLengthItem ()
+ {
+ if (src == null || src?.Count == 0) {
+ return 0;
+ }
+
+ int maxLength = 0;
+ for (int i = 0; i < src.Count; i++) {
+ var t = src [i];
+ int l;
+ if (t is string u) {
+ l = u.GetColumns ();
+ } else if (t is string s) {
+ l = s.Length;
+ } else {
+ l = t.ToString ().Length;
+ }
+
+ if (l > maxLength) {
+ maxLength = l;
+ }
+ }
+
+ return maxLength;
+ }
+
+ void RenderUstr (ConsoleDriver driver, string ustr, int col, int line, int width, int start = 0)
+ {
+ var u = TextFormatter.ClipAndJustify (ustr, width, TextAlignment.Left);
+ driver.AddStr (u);
+ width -= u.GetColumns ();
+ while (width-- > 0) {
+ driver.AddRune ((Rune)' ');
+ }
+ }
+
+ ///
+ public void Render (ListView container, ConsoleDriver driver, bool marked, int item, int col, int line, int width, int start = 0)
+ {
+ container.Move (col, line);
+ var t = src? [item];
+ if (t == null) {
+ RenderUstr (driver, "", col, line, width);
+ } else {
+ if (t is string u) {
+ RenderUstr (driver, u, col, line, width, start);
+ } else if (t is string s) {
+ RenderUstr (driver, s, col, line, width, start);
+ } else {
+ RenderUstr (driver, t.ToString (), col, line, width, start);
+ }
+ }
+ }
+
+ ///
+ public bool IsMarked (int item)
+ {
+ if (item >= 0 && item < count)
+ return marks [item];
+ return false;
+ }
+
+ ///
+ public void SetMark (int item, bool value)
+ {
+ if (item >= 0 && item < count)
+ marks [item] = value;
+ }
+
+ ///
+ public IList ToList ()
+ {
+ return src;
+ }
+
+ ///
+ public int StartsWith (string search)
+ {
+ if (src == null || src?.Count == 0) {
+ return -1;
+ }
+
+ for (int i = 0; i < src.Count; i++) {
+ var t = src [i];
+ if (t is string u) {
+ if (u.ToUpper ().StartsWith (search.ToUpperInvariant ())) {
+ return i;
+ }
+ } else if (t is string s) {
+ if (s.StartsWith (search, StringComparison.InvariantCultureIgnoreCase)) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
}
diff --git a/UnitTests/Views/ListViewTests.cs b/UnitTests/Views/ListViewTests.cs
index a2fb00e38..18f0284e2 100644
--- a/UnitTests/Views/ListViewTests.cs
+++ b/UnitTests/Views/ListViewTests.cs
@@ -1,269 +1,266 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;
-namespace Terminal.Gui.ViewsTests {
- public class ListViewTests {
- readonly ITestOutputHelper output;
+namespace Terminal.Gui.ViewsTests;
+public class ListViewTests {
+ readonly ITestOutputHelper _output;
- public ListViewTests (ITestOutputHelper output)
+ public ListViewTests (ITestOutputHelper output)
+ {
+ this._output = output;
+ }
+
+ [Fact]
+ public void Constructors_Defaults ()
+ {
+ var lv = new ListView ();
+ Assert.Null (lv.Source);
+ Assert.True (lv.CanFocus);
+ Assert.Equal (-1, lv.SelectedItem);
+
+ lv = new ListView (new List () { "One", "Two", "Three" });
+ Assert.NotNull (lv.Source);
+ Assert.Equal (-1, lv.SelectedItem);
+
+ lv = new ListView (new NewListDataSource ());
+ Assert.NotNull (lv.Source);
+ Assert.Equal (-1, lv.SelectedItem);
+
+ lv = new ListView (new List () { "One", "Two", "Three" }) { Y = 1, Width = 10, Height = 20 };
+ Assert.NotNull (lv.Source);
+ Assert.Equal (-1, lv.SelectedItem);
+ Assert.Equal (new Rect (0, 1, 10, 20), lv.Frame);
+
+ lv = new ListView (new NewListDataSource ()) { Y = 1, Width = 10, Height = 20 };
+ Assert.NotNull (lv.Source);
+ Assert.Equal (-1, lv.SelectedItem);
+ Assert.Equal (new Rect (0, 1, 10, 20), lv.Frame);
+ }
+
+ [Fact]
+ public void ListViewSelectThenDown ()
+ {
+ var lv = new ListView (new List () { "One", "Two", "Three" });
+ lv.AllowsMarking = true;
+
+ Assert.NotNull (lv.Source);
+
+ // first item should be deselected by default
+ Assert.Equal (-1, lv.SelectedItem);
+
+ // nothing is ticked
+ Assert.False (lv.Source.IsMarked (0));
+ Assert.False (lv.Source.IsMarked (1));
+ Assert.False (lv.Source.IsMarked (2));
+
+ lv.KeyBindings.Add (KeyCode.Space | KeyCode.ShiftMask, Command.ToggleChecked, Command.LineDown);
+
+ var ev = new Key (KeyCode.Space | KeyCode.ShiftMask);
+
+ // view should indicate that it has accepted and consumed the event
+ Assert.True (lv.NewKeyDownEvent (ev));
+
+ // first item should now be selected
+ Assert.Equal (0, lv.SelectedItem);
+
+ // none of the items should be ticked
+ Assert.False (lv.Source.IsMarked (0));
+ Assert.False (lv.Source.IsMarked (1));
+ Assert.False (lv.Source.IsMarked (2));
+
+ // Press key combo again
+ Assert.True (lv.NewKeyDownEvent (ev));
+
+ // second item should now be selected
+ Assert.Equal (1, lv.SelectedItem);
+
+ // first item only should be ticked
+ Assert.True (lv.Source.IsMarked (0));
+ Assert.False (lv.Source.IsMarked (1));
+ Assert.False (lv.Source.IsMarked (2));
+
+ // Press key combo again
+ Assert.True (lv.NewKeyDownEvent (ev));
+ Assert.Equal (2, lv.SelectedItem);
+ Assert.True (lv.Source.IsMarked (0));
+ Assert.True (lv.Source.IsMarked (1));
+ Assert.False (lv.Source.IsMarked (2));
+
+ // Press key combo again
+ Assert.True (lv.NewKeyDownEvent (ev));
+ Assert.Equal (2, lv.SelectedItem); // cannot move down any further
+ Assert.True (lv.Source.IsMarked (0));
+ Assert.True (lv.Source.IsMarked (1));
+ Assert.True (lv.Source.IsMarked (2)); // but can toggle marked
+
+ // Press key combo again
+ Assert.True (lv.NewKeyDownEvent (ev));
+ Assert.Equal (2, lv.SelectedItem); // cannot move down any further
+ Assert.True (lv.Source.IsMarked (0));
+ Assert.True (lv.Source.IsMarked (1));
+ Assert.False (lv.Source.IsMarked (2)); // untoggle toggle marked
+ }
+ [Fact]
+ public void SettingEmptyKeybindingThrows ()
+ {
+ var lv = new ListView (new List () { "One", "Two", "Three" });
+ Assert.Throws (() => lv.KeyBindings.Add (KeyCode.Space));
+ }
+
+ ///
+ /// Tests that when none of the Commands in a chained keybinding are possible
+ /// the returns the appropriate result
+ ///
+ [Fact]
+ public void ListViewProcessKeyReturnValue_WithMultipleCommands ()
+ {
+ var lv = new ListView (new List () { "One", "Two", "Three", "Four" });
+
+ Assert.NotNull (lv.Source);
+
+ // first item should be deselected by default
+ Assert.Equal (-1, lv.SelectedItem);
+
+ // bind shift down to move down twice in control
+ lv.KeyBindings.Add (KeyCode.CursorDown | KeyCode.ShiftMask, Command.LineDown, Command.LineDown);
+
+ var ev = new Key (KeyCode.CursorDown | KeyCode.ShiftMask);
+
+ Assert.True (lv.NewKeyDownEvent (ev), "The first time we move down 2 it should be possible");
+
+ // After moving down twice from -1 we should be at 'Two'
+ Assert.Equal (1, lv.SelectedItem);
+
+ // clear the items
+ lv.SetSource (null);
+
+ // Press key combo again - return should be false this time as none of the Commands are allowable
+ Assert.False (lv.NewKeyDownEvent (ev), "We cannot move down so will not respond to this");
+ }
+
+ private class NewListDataSource : IListDataSource {
+ public int Count => throw new NotImplementedException ();
+
+ public int Length => throw new NotImplementedException ();
+
+ public bool IsMarked (int item)
{
- this.output = output;
+ throw new NotImplementedException ();
}
- [Fact]
- public void Constructors_Defaults ()
+ public void Render (ListView container, ConsoleDriver driver, bool selected, int item, int col, int line, int width, int start = 0)
{
- var lv = new ListView ();
- Assert.Null (lv.Source);
- Assert.True (lv.CanFocus);
- Assert.Equal (-1, lv.SelectedItem);
-
- lv = new ListView (new List () { "One", "Two", "Three" });
- Assert.NotNull (lv.Source);
- Assert.Equal (-1, lv.SelectedItem);
-
- lv = new ListView (new NewListDataSource ());
- Assert.NotNull (lv.Source);
- Assert.Equal (-1, lv.SelectedItem);
-
- lv = new ListView (new Rect (0, 1, 10, 20), new List () { "One", "Two", "Three" });
- Assert.NotNull (lv.Source);
- Assert.Equal (-1, lv.SelectedItem);
- Assert.Equal (new Rect (0, 1, 10, 20), lv.Frame);
-
- lv = new ListView (new Rect (0, 1, 10, 20), new NewListDataSource ());
- Assert.NotNull (lv.Source);
- Assert.Equal (-1, lv.SelectedItem);
- Assert.Equal (new Rect (0, 1, 10, 20), lv.Frame);
+ throw new NotImplementedException ();
}
- [Fact]
- public void ListViewSelectThenDown ()
+ public void SetMark (int item, bool value)
{
- var lv = new ListView (new List () { "One", "Two", "Three" });
- lv.AllowsMarking = true;
-
- Assert.NotNull (lv.Source);
-
- // first item should be deselected by default
- Assert.Equal (-1, lv.SelectedItem);
-
- // nothing is ticked
- Assert.False (lv.Source.IsMarked (0));
- Assert.False (lv.Source.IsMarked (1));
- Assert.False (lv.Source.IsMarked (2));
-
- lv.KeyBindings.Add (KeyCode.Space | KeyCode.ShiftMask, Command.ToggleChecked, Command.LineDown);
-
- var ev = new Key (KeyCode.Space | KeyCode.ShiftMask);
-
- // view should indicate that it has accepted and consumed the event
- Assert.True (lv.NewKeyDownEvent (ev));
-
- // first item should now be selected
- Assert.Equal (0, lv.SelectedItem);
-
- // none of the items should be ticked
- Assert.False (lv.Source.IsMarked (0));
- Assert.False (lv.Source.IsMarked (1));
- Assert.False (lv.Source.IsMarked (2));
-
- // Press key combo again
- Assert.True (lv.NewKeyDownEvent (ev));
-
- // second item should now be selected
- Assert.Equal (1, lv.SelectedItem);
-
- // first item only should be ticked
- Assert.True (lv.Source.IsMarked (0));
- Assert.False (lv.Source.IsMarked (1));
- Assert.False (lv.Source.IsMarked (2));
-
- // Press key combo again
- Assert.True (lv.NewKeyDownEvent (ev));
- Assert.Equal (2, lv.SelectedItem);
- Assert.True (lv.Source.IsMarked (0));
- Assert.True (lv.Source.IsMarked (1));
- Assert.False (lv.Source.IsMarked (2));
-
- // Press key combo again
- Assert.True (lv.NewKeyDownEvent (ev));
- Assert.Equal (2, lv.SelectedItem); // cannot move down any further
- Assert.True (lv.Source.IsMarked (0));
- Assert.True (lv.Source.IsMarked (1));
- Assert.True (lv.Source.IsMarked (2)); // but can toggle marked
-
- // Press key combo again
- Assert.True (lv.NewKeyDownEvent (ev));
- Assert.Equal (2, lv.SelectedItem); // cannot move down any further
- Assert.True (lv.Source.IsMarked (0));
- Assert.True (lv.Source.IsMarked (1));
- Assert.False (lv.Source.IsMarked (2)); // untoggle toggle marked
- }
- [Fact]
- public void SettingEmptyKeybindingThrows ()
- {
- var lv = new ListView (new List () { "One", "Two", "Three" });
- Assert.Throws (() => lv.KeyBindings.Add (KeyCode.Space));
+ throw new NotImplementedException ();
}
- ///
- /// Tests that when none of the Commands in a chained keybinding are possible
- /// the returns the appropriate result
- ///
- [Fact]
- public void ListViewProcessKeyReturnValue_WithMultipleCommands ()
+ public IList ToList ()
{
- var lv = new ListView (new List () { "One", "Two", "Three", "Four" });
-
- Assert.NotNull (lv.Source);
-
- // first item should be deselected by default
- Assert.Equal (-1, lv.SelectedItem);
-
- // bind shift down to move down twice in control
- lv.KeyBindings.Add (KeyCode.CursorDown | KeyCode.ShiftMask, Command.LineDown, Command.LineDown);
-
- var ev = new Key (KeyCode.CursorDown | KeyCode.ShiftMask);
-
- Assert.True (lv.NewKeyDownEvent (ev), "The first time we move down 2 it should be possible");
-
- // After moving down twice from -1 we should be at 'Two'
- Assert.Equal (1, lv.SelectedItem);
-
- // clear the items
- lv.SetSource (null);
-
- // Press key combo again - return should be false this time as none of the Commands are allowable
- Assert.False (lv.NewKeyDownEvent (ev), "We cannot move down so will not respond to this");
+ return new List () { "One", "Two", "Three" };
}
+ }
- private class NewListDataSource : IListDataSource {
- public int Count => throw new NotImplementedException ();
+ [Fact]
+ public void KeyBindings_Command ()
+ {
+ List source = new List () { "One", "Two", "Three" };
+ ListView lv = new ListView (source) { Height = 2, AllowsMarking = true };
+ lv.BeginInit (); lv.EndInit ();
+ Assert.Equal (-1, lv.SelectedItem);
+ Assert.True (lv.NewKeyDownEvent (new (KeyCode.CursorDown)));
+ Assert.Equal (0, lv.SelectedItem);
+ Assert.True (lv.NewKeyDownEvent (new (KeyCode.CursorUp)));
+ Assert.Equal (0, lv.SelectedItem);
+ Assert.True (lv.NewKeyDownEvent (new (KeyCode.PageDown)));
+ Assert.Equal (2, lv.SelectedItem);
+ Assert.Equal (2, lv.TopItem);
+ Assert.True (lv.NewKeyDownEvent (new (KeyCode.PageUp)));
+ Assert.Equal (0, lv.SelectedItem);
+ Assert.Equal (0, lv.TopItem);
+ Assert.False (lv.Source.IsMarked (lv.SelectedItem));
+ Assert.True (lv.NewKeyDownEvent (new (KeyCode.Space)));
+ Assert.True (lv.Source.IsMarked (lv.SelectedItem));
+ var opened = false;
+ lv.OpenSelectedItem += (s, _) => opened = true;
+ Assert.True (lv.NewKeyDownEvent (new (KeyCode.Enter)));
+ Assert.True (opened);
+ Assert.True (lv.NewKeyDownEvent (new (KeyCode.End)));
+ Assert.Equal (2, lv.SelectedItem);
+ Assert.True (lv.NewKeyDownEvent (new (KeyCode.Home)));
+ Assert.Equal (0, lv.SelectedItem);
+ }
- public int Length => throw new NotImplementedException ();
+ [Fact]
+ [AutoInitShutdown]
+ public void RowRender_Event ()
+ {
+ var rendered = false;
+ var source = new List () { "one", "two", "three" };
+ var lv = new ListView () { Width = Dim.Fill (), Height = Dim.Fill () };
+ lv.RowRender += (s, _) => rendered = true;
+ Application.Top.Add (lv);
+ Application.Begin (Application.Top);
+ Assert.False (rendered);
- public bool IsMarked (int item)
- {
- throw new NotImplementedException ();
- }
-
- public void Render (ListView container, ConsoleDriver driver, bool selected, int item, int col, int line, int width, int start = 0)
- {
- throw new NotImplementedException ();
- }
-
- public void SetMark (int item, bool value)
- {
- throw new NotImplementedException ();
- }
-
- public IList ToList ()
- {
- return new List () { "One", "Two", "Three" };
+ lv.SetSource (source);
+ lv.Draw ();
+ Assert.True (rendered);
+ }
+
+ [Fact]
+ [AutoInitShutdown]
+ public void EnsureSelectedItemVisible_Top ()
+ {
+ var source = new List () { "First", "Second" };
+ ListView lv = new ListView (source) { Width = Dim.Fill (), Height = 1 };
+ lv.SelectedItem = 1;
+ Application.Top.Add (lv);
+ Application.Begin (Application.Top);
+
+ Assert.Equal ("Second ", GetContents (0));
+ Assert.Equal (new (' ', 7), GetContents (1));
+
+ lv.MoveUp ();
+ lv.Draw ();
+
+ Assert.Equal ("First ", GetContents (0));
+ Assert.Equal (new (' ', 7), GetContents (1));
+
+ string GetContents (int line)
+ {
+ var item = "";
+ for (int i = 0; i < 7; i++) {
+ item += Application.Driver.Contents [line, i].Rune;
}
+ return item;
}
+ }
- [Fact]
- public void KeyBindings_Command ()
- {
- List source = new List () { "One", "Two", "Three" };
- ListView lv = new ListView (source) { Height = 2, AllowsMarking = true };
- lv.BeginInit (); lv.EndInit ();
- Assert.Equal (-1, lv.SelectedItem);
- Assert.True (lv.NewKeyDownEvent (new (KeyCode.CursorDown)));
- Assert.Equal (0, lv.SelectedItem);
- Assert.True (lv.NewKeyDownEvent (new (KeyCode.CursorUp)));
- Assert.Equal (0, lv.SelectedItem);
- Assert.True (lv.NewKeyDownEvent (new (KeyCode.PageDown)));
- Assert.Equal (2, lv.SelectedItem);
- Assert.Equal (2, lv.TopItem);
- Assert.True (lv.NewKeyDownEvent (new (KeyCode.PageUp)));
- Assert.Equal (0, lv.SelectedItem);
- Assert.Equal (0, lv.TopItem);
- Assert.False (lv.Source.IsMarked (lv.SelectedItem));
- Assert.True (lv.NewKeyDownEvent (new (KeyCode.Space)));
- Assert.True (lv.Source.IsMarked (lv.SelectedItem));
- var opened = false;
- lv.OpenSelectedItem += (s, _) => opened = true;
- Assert.True (lv.NewKeyDownEvent (new (KeyCode.Enter)));
- Assert.True (opened);
- Assert.True (lv.NewKeyDownEvent (new (KeyCode.End)));
- Assert.Equal (2, lv.SelectedItem);
- Assert.True (lv.NewKeyDownEvent (new (KeyCode.Home)));
- Assert.Equal (0, lv.SelectedItem);
+ [Fact]
+ [AutoInitShutdown]
+ public void Ensures_Visibility_SelectedItem_On_MoveDown_And_MoveUp ()
+ {
+ var source = new List ();
+ for (int i = 0; i < 20; i++) {
+ source.Add ($"Line{i}");
}
+ var lv = new ListView (source) { Width = Dim.Fill (), Height = Dim.Fill () };
+ var win = new Window ();
+ win.Add (lv);
+ Application.Top.Add (win);
+ Application.Begin (Application.Top);
+ ((FakeDriver)Application.Driver).SetBufferSize (12, 12);
+ Application.Refresh ();
- [Fact]
- [AutoInitShutdown]
- public void RowRender_Event ()
- {
- var rendered = false;
- var source = new List () { "one", "two", "three" };
- var lv = new ListView () { Width = Dim.Fill (), Height = Dim.Fill () };
- lv.RowRender += (s, _) => rendered = true;
- Application.Top.Add (lv);
- Application.Begin (Application.Top);
- Assert.False (rendered);
-
- lv.SetSource (source);
- lv.Draw ();
- Assert.True (rendered);
- }
-
- [Fact]
- [AutoInitShutdown]
- public void EnsureSelectedItemVisible_Top ()
- {
- var source = new List () { "First", "Second" };
- ListView lv = new ListView (source) { Width = Dim.Fill (), Height = 1 };
- lv.SelectedItem = 1;
- Application.Top.Add (lv);
- Application.Begin (Application.Top);
-
- Assert.Equal ("Second ", GetContents (0));
- Assert.Equal (new (' ', 7), GetContents (1));
-
- lv.MoveUp ();
- lv.Draw ();
-
- Assert.Equal ("First ", GetContents (0));
- Assert.Equal (new (' ', 7), GetContents (1));
-
- string GetContents (int line)
- {
- var item = "";
- for (int i = 0; i < 7; i++) {
- item += Application.Driver.Contents [line, i].Rune;
- }
- return item;
- }
- }
-
- [Fact]
- [AutoInitShutdown]
- public void Ensures_Visibility_SelectedItem_On_MoveDown_And_MoveUp ()
- {
- var source = new List ();
- for (int i = 0; i < 20; i++) {
- source.Add ($"Line{i}");
- }
- var lv = new ListView (source) { Width = Dim.Fill (), Height = Dim.Fill () };
- var win = new Window ();
- win.Add (lv);
- Application.Top.Add (win);
- Application.Begin (Application.Top);
- ((FakeDriver)Application.Driver).SetBufferSize (12, 12);
- Application.Refresh ();
-
- Assert.Equal (-1, lv.SelectedItem);
- TestHelpers.AssertDriverContentsWithFrameAre (@"
+ Assert.Equal (-1, lv.SelectedItem);
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
┌──────────┐
│Line0 │
│Line1 │
@@ -275,12 +272,12 @@ namespace Terminal.Gui.ViewsTests {
│Line7 │
│Line8 │
│Line9 │
-└──────────┘", output);
+└──────────┘", _output);
- Assert.True (lv.ScrollDown (10));
- lv.Draw ();
- Assert.Equal (-1, lv.SelectedItem);
- TestHelpers.AssertDriverContentsWithFrameAre (@"
+ Assert.True (lv.ScrollDown (10));
+ lv.Draw ();
+ Assert.Equal (-1, lv.SelectedItem);
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
┌──────────┐
│Line10 │
│Line11 │
@@ -292,12 +289,12 @@ namespace Terminal.Gui.ViewsTests {
│Line17 │
│Line18 │
│Line19 │
-└──────────┘", output);
+└──────────┘", _output);
- Assert.True (lv.MoveDown ());
- lv.Draw ();
- Assert.Equal (0, lv.SelectedItem);
- TestHelpers.AssertDriverContentsWithFrameAre (@"
+ Assert.True (lv.MoveDown ());
+ lv.Draw ();
+ Assert.Equal (0, lv.SelectedItem);
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
┌──────────┐
│Line0 │
│Line1 │
@@ -309,12 +306,12 @@ namespace Terminal.Gui.ViewsTests {
│Line7 │
│Line8 │
│Line9 │
-└──────────┘", output);
+└──────────┘", _output);
- Assert.True (lv.MoveEnd ());
- lv.Draw ();
- Assert.Equal (19, lv.SelectedItem);
- TestHelpers.AssertDriverContentsWithFrameAre (@"
+ Assert.True (lv.MoveEnd ());
+ lv.Draw ();
+ Assert.Equal (19, lv.SelectedItem);
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
┌──────────┐
│Line19 │
│ │
@@ -326,12 +323,12 @@ namespace Terminal.Gui.ViewsTests {
│ │
│ │
│ │
-└──────────┘", output);
+└──────────┘", _output);
- Assert.True (lv.ScrollUp (20));
- lv.Draw ();
- Assert.Equal (19, lv.SelectedItem);
- TestHelpers.AssertDriverContentsWithFrameAre (@"
+ Assert.True (lv.ScrollUp (20));
+ lv.Draw ();
+ Assert.Equal (19, lv.SelectedItem);
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
┌──────────┐
│Line0 │
│Line1 │
@@ -343,12 +340,12 @@ namespace Terminal.Gui.ViewsTests {
│Line7 │
│Line8 │
│Line9 │
-└──────────┘", output);
+└──────────┘", _output);
- Assert.True (lv.MoveDown ());
- lv.Draw ();
- Assert.Equal (19, lv.SelectedItem);
- TestHelpers.AssertDriverContentsWithFrameAre (@"
+ Assert.True (lv.MoveDown ());
+ lv.Draw ();
+ Assert.Equal (19, lv.SelectedItem);
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
┌──────────┐
│Line10 │
│Line11 │
@@ -360,12 +357,12 @@ namespace Terminal.Gui.ViewsTests {
│Line17 │
│Line18 │
│Line19 │
-└──────────┘", output);
+└──────────┘", _output);
- Assert.True (lv.ScrollUp (20));
- lv.Draw ();
- Assert.Equal (19, lv.SelectedItem);
- TestHelpers.AssertDriverContentsWithFrameAre (@"
+ Assert.True (lv.ScrollUp (20));
+ lv.Draw ();
+ Assert.Equal (19, lv.SelectedItem);
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
┌──────────┐
│Line0 │
│Line1 │
@@ -377,12 +374,12 @@ namespace Terminal.Gui.ViewsTests {
│Line7 │
│Line8 │
│Line9 │
-└──────────┘", output);
+└──────────┘", _output);
- Assert.True (lv.MoveDown ());
- lv.Draw ();
- Assert.Equal (19, lv.SelectedItem);
- TestHelpers.AssertDriverContentsWithFrameAre (@"
+ Assert.True (lv.MoveDown ());
+ lv.Draw ();
+ Assert.Equal (19, lv.SelectedItem);
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
┌──────────┐
│Line10 │
│Line11 │
@@ -394,12 +391,12 @@ namespace Terminal.Gui.ViewsTests {
│Line17 │
│Line18 │
│Line19 │
-└──────────┘", output);
+└──────────┘", _output);
- Assert.True (lv.MoveHome ());
- lv.Draw ();
- Assert.Equal (0, lv.SelectedItem);
- TestHelpers.AssertDriverContentsWithFrameAre (@"
+ Assert.True (lv.MoveHome ());
+ lv.Draw ();
+ Assert.Equal (0, lv.SelectedItem);
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
┌──────────┐
│Line0 │
│Line1 │
@@ -411,12 +408,12 @@ namespace Terminal.Gui.ViewsTests {
│Line7 │
│Line8 │
│Line9 │
-└──────────┘", output);
+└──────────┘", _output);
- Assert.True (lv.ScrollDown (20));
- lv.Draw ();
- Assert.Equal (0, lv.SelectedItem);
- TestHelpers.AssertDriverContentsWithFrameAre (@"
+ Assert.True (lv.ScrollDown (20));
+ lv.Draw ();
+ Assert.Equal (0, lv.SelectedItem);
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
┌──────────┐
│Line19 │
│ │
@@ -428,12 +425,12 @@ namespace Terminal.Gui.ViewsTests {
│ │
│ │
│ │
-└──────────┘", output);
+└──────────┘", _output);
- Assert.True (lv.MoveUp ());
- lv.Draw ();
- Assert.Equal (0, lv.SelectedItem);
- TestHelpers.AssertDriverContentsWithFrameAre (@"
+ Assert.True (lv.MoveUp ());
+ lv.Draw ();
+ Assert.Equal (0, lv.SelectedItem);
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
┌──────────┐
│Line0 │
│Line1 │
@@ -445,167 +442,166 @@ namespace Terminal.Gui.ViewsTests {
│Line7 │
│Line8 │
│Line9 │
-└──────────┘", output);
+└──────────┘", _output);
+ }
+
+ [Fact]
+ public void SetSource_Preserves_ListWrapper_Instance_If_Not_Null ()
+ {
+ var lv = new ListView (new List { "One", "Two" });
+
+ Assert.NotNull (lv.Source);
+
+ lv.SetSource (null);
+ Assert.NotNull (lv.Source);
+
+ lv.Source = null;
+ Assert.Null (lv.Source);
+
+ lv = new ListView (new List { "One", "Two" });
+ Assert.NotNull (lv.Source);
+
+ lv.SetSourceAsync (null);
+ Assert.NotNull (lv.Source);
+ }
+
+ [Fact]
+ public void ListWrapper_StartsWith ()
+ {
+ var lw = new ListWrapper (new List { "One", "Two", "Three" });
+
+ Assert.Equal (1, lw.StartsWith ("t"));
+ Assert.Equal (1, lw.StartsWith ("tw"));
+ Assert.Equal (2, lw.StartsWith ("th"));
+ Assert.Equal (1, lw.StartsWith ("T"));
+ Assert.Equal (1, lw.StartsWith ("TW"));
+ Assert.Equal (2, lw.StartsWith ("TH"));
+
+ lw = new ListWrapper (new List { "One", "Two", "Three" });
+
+ Assert.Equal (1, lw.StartsWith ("t"));
+ Assert.Equal (1, lw.StartsWith ("tw"));
+ Assert.Equal (2, lw.StartsWith ("th"));
+ Assert.Equal (1, lw.StartsWith ("T"));
+ Assert.Equal (1, lw.StartsWith ("TW"));
+ Assert.Equal (2, lw.StartsWith ("TH"));
+ }
+
+ [Fact, AutoInitShutdown]
+ public void EnsureSelectedItemVisible_SelectedItem ()
+ {
+ var source = new List ();
+ for (int i = 0; i < 10; i++) {
+ source.Add ($"Item {i}");
}
+ var lv = new ListView (source) {
+ Width = 10,
+ Height = 5
+ };
+ Application.Top.Add (lv);
+ Application.Begin (Application.Top);
- [Fact]
- public void SetSource_Preserves_ListWrapper_Instance_If_Not_Null ()
- {
- var lv = new ListView (new List { "One", "Two" });
-
- Assert.NotNull (lv.Source);
-
- lv.SetSource (null);
- Assert.NotNull (lv.Source);
-
- lv.Source = null;
- Assert.Null (lv.Source);
-
- lv = new ListView (new List { "One", "Two" });
- Assert.NotNull (lv.Source);
-
- lv.SetSourceAsync (null);
- Assert.NotNull (lv.Source);
- }
-
- [Fact]
- public void ListWrapper_StartsWith ()
- {
- var lw = new ListWrapper (new List { "One", "Two", "Three" });
-
- Assert.Equal (1, lw.StartsWith ("t"));
- Assert.Equal (1, lw.StartsWith ("tw"));
- Assert.Equal (2, lw.StartsWith ("th"));
- Assert.Equal (1, lw.StartsWith ("T"));
- Assert.Equal (1, lw.StartsWith ("TW"));
- Assert.Equal (2, lw.StartsWith ("TH"));
-
- lw = new ListWrapper (new List { "One", "Two", "Three" });
-
- Assert.Equal (1, lw.StartsWith ("t"));
- Assert.Equal (1, lw.StartsWith ("tw"));
- Assert.Equal (2, lw.StartsWith ("th"));
- Assert.Equal (1, lw.StartsWith ("T"));
- Assert.Equal (1, lw.StartsWith ("TW"));
- Assert.Equal (2, lw.StartsWith ("TH"));
- }
-
- [Fact, AutoInitShutdown]
- public void EnsureSelectedItemVisible_SelectedItem ()
- {
- var source = new List ();
- for (int i = 0; i < 10; i++) {
- source.Add ($"Item {i}");
- }
- var lv = new ListView (source) {
- Width = 10,
- Height = 5
- };
- Application.Top.Add (lv);
- Application.Begin (Application.Top);
-
- TestHelpers.AssertDriverContentsWithFrameAre (@"
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
Item 0
Item 1
Item 2
Item 3
-Item 4", output);
+Item 4", _output);
- // EnsureSelectedItemVisible is auto enabled on the OnSelectedChanged
- lv.SelectedItem = 6;
- Application.Refresh ();
- TestHelpers.AssertDriverContentsWithFrameAre (@"
+ // EnsureSelectedItemVisible is auto enabled on the OnSelectedChanged
+ lv.SelectedItem = 6;
+ Application.Refresh ();
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
Item 2
Item 3
Item 4
Item 5
-Item 6", output);
- }
-
- [Fact]
- public void SelectedItem_Get_Set ()
- {
- var lv = new ListView (new List { "One", "Two", "Three" });
- Assert.Equal (-1, lv.SelectedItem);
- Assert.Throws (() => lv.SelectedItem = 3);
- var exception = Record.Exception (() => lv.SelectedItem = -1);
- Assert.Null (exception);
- }
-
- [Fact]
- public void OnEnter_Does_Not_Throw_Exception ()
- {
- var lv = new ListView ();
- var top = new View ();
- top.Add (lv);
- var exception = Record.Exception (lv.SetFocus);
- Assert.Null (exception);
- }
-
-// No longer needed given PR #2920
-// [Fact, AutoInitShutdown]
-// public void Clicking_On_Border_Is_Ignored ()
-// {
-// var selected = "";
-// var lv = new ListView {
-// Height = 5,
-// Width = 7,
-// BorderStyle = LineStyle.Single
-// };
-// lv.SetSource (new List { "One", "Two", "Three", "Four" });
-// lv.SelectedItemChanged += (s, e) => selected = e.Value.ToString ();
-// Application.Top.Add (lv);
-// Application.Begin (Application.Top);
-
-// Assert.Equal (new Thickness (1), lv.Border.Thickness);
-// Assert.Equal (-1, lv.SelectedItem);
-// Assert.Equal ("", lv.Text);
-// TestHelpers.AssertDriverContentsWithFrameAre (@"
-//┌─────┐
-//│One │
-//│Two │
-//│Three│
-//└─────┘", output);
-
-// Assert.True (lv.MouseEvent (new MouseEvent {
-// X = 0,
-// Y = 0,
-// Flags = MouseFlags.Button1Clicked
-// }));
-// Assert.Equal ("", selected);
-// Assert.Equal (-1, lv.SelectedItem);
-
-// Assert.True (lv.MouseEvent (new MouseEvent {
-// X = 0,
-// Y = 1,
-// Flags = MouseFlags.Button1Clicked
-// }));
-// Assert.Equal ("One", selected);
-// Assert.Equal (0, lv.SelectedItem);
-
-// Assert.True (lv.MouseEvent (new MouseEvent {
-// X = 0,
-// Y = 2,
-// Flags = MouseFlags.Button1Clicked
-// }));
-// Assert.Equal ("Two", selected);
-// Assert.Equal (1, lv.SelectedItem);
-
-// Assert.True (lv.MouseEvent (new MouseEvent {
-// X = 0,
-// Y = 3,
-// Flags = MouseFlags.Button1Clicked
-// }));
-// Assert.Equal ("Three", selected);
-// Assert.Equal (2, lv.SelectedItem);
-
-// Assert.True (lv.MouseEvent (new MouseEvent {
-// X = 0,
-// Y = 4,
-// Flags = MouseFlags.Button1Clicked
-// }));
-// Assert.Equal ("Three", selected);
-// Assert.Equal (2, lv.SelectedItem);
-// }
+Item 6", _output);
}
+
+ [Fact]
+ public void SelectedItem_Get_Set ()
+ {
+ var lv = new ListView (new List { "One", "Two", "Three" });
+ Assert.Equal (-1, lv.SelectedItem);
+ Assert.Throws (() => lv.SelectedItem = 3);
+ var exception = Record.Exception (() => lv.SelectedItem = -1);
+ Assert.Null (exception);
+ }
+
+ [Fact]
+ public void OnEnter_Does_Not_Throw_Exception ()
+ {
+ var lv = new ListView ();
+ var top = new View ();
+ top.Add (lv);
+ var exception = Record.Exception (lv.SetFocus);
+ Assert.Null (exception);
+ }
+
+ // No longer needed given PR #2920
+ // [Fact, AutoInitShutdown]
+ // public void Clicking_On_Border_Is_Ignored ()
+ // {
+ // var selected = "";
+ // var lv = new ListView {
+ // Height = 5,
+ // Width = 7,
+ // BorderStyle = LineStyle.Single
+ // };
+ // lv.SetSource (new List { "One", "Two", "Three", "Four" });
+ // lv.SelectedItemChanged += (s, e) => selected = e.Value.ToString ();
+ // Application.Top.Add (lv);
+ // Application.Begin (Application.Top);
+
+ // Assert.Equal (new Thickness (1), lv.Border.Thickness);
+ // Assert.Equal (-1, lv.SelectedItem);
+ // Assert.Equal ("", lv.Text);
+ // TestHelpers.AssertDriverContentsWithFrameAre (@"
+ //┌─────┐
+ //│One │
+ //│Two │
+ //│Three│
+ //└─────┘", output);
+
+ // Assert.True (lv.MouseEvent (new MouseEvent {
+ // X = 0,
+ // Y = 0,
+ // Flags = MouseFlags.Button1Clicked
+ // }));
+ // Assert.Equal ("", selected);
+ // Assert.Equal (-1, lv.SelectedItem);
+
+ // Assert.True (lv.MouseEvent (new MouseEvent {
+ // X = 0,
+ // Y = 1,
+ // Flags = MouseFlags.Button1Clicked
+ // }));
+ // Assert.Equal ("One", selected);
+ // Assert.Equal (0, lv.SelectedItem);
+
+ // Assert.True (lv.MouseEvent (new MouseEvent {
+ // X = 0,
+ // Y = 2,
+ // Flags = MouseFlags.Button1Clicked
+ // }));
+ // Assert.Equal ("Two", selected);
+ // Assert.Equal (1, lv.SelectedItem);
+
+ // Assert.True (lv.MouseEvent (new MouseEvent {
+ // X = 0,
+ // Y = 3,
+ // Flags = MouseFlags.Button1Clicked
+ // }));
+ // Assert.Equal ("Three", selected);
+ // Assert.Equal (2, lv.SelectedItem);
+
+ // Assert.True (lv.MouseEvent (new MouseEvent {
+ // X = 0,
+ // Y = 4,
+ // Flags = MouseFlags.Button1Clicked
+ // }));
+ // Assert.Equal ("Three", selected);
+ // Assert.Equal (2, lv.SelectedItem);
+ // }
}