Fixes #820. Added HideDropdownListOnClick property. (#1983)

* Added HideDropdownListOnClick property.

* Invoking OpenSelectedItem on click.

* Added one more constructor and more unit tests.

* Added the ComboListView derived class.

* Added more features to ComboBox.

* Removes code not featured yet.

* Added HideDropdownListOnClick property to scenario.

* Ensures SetSource having the same behavior as the ListWrapper constructor.
This commit is contained in:
BDisp
2022-09-15 01:10:40 +00:00
committed by GitHub
parent d368215e07
commit b21f203292
5 changed files with 949 additions and 16 deletions

View File

@@ -16,6 +16,161 @@ namespace Terminal.Gui {
/// </summary>
public class ComboBox : View {
private class ComboListView : ListView {
private int highlighted = -1;
private bool isFocusing;
private ComboBox container;
private bool hideDropdownListOnClick;
public ComboListView (ComboBox container, bool hideDropdownListOnClick)
{
Initialize (container, hideDropdownListOnClick);
}
public ComboListView (ComboBox container, Rect rect, IList source, bool hideDropdownListOnClick) : base (rect, source)
{
Initialize (container, hideDropdownListOnClick);
}
public ComboListView (ComboBox container, IList source, bool hideDropdownListOnClick) : base (source)
{
Initialize (container, hideDropdownListOnClick);
}
private void Initialize (ComboBox container, bool hideDropdownListOnClick)
{
if (container == null)
throw new ArgumentNullException ("ComboBox container cannot be null.", nameof (container));
this.container = container;
HideDropdownListOnClick = hideDropdownListOnClick;
}
public bool HideDropdownListOnClick {
get => hideDropdownListOnClick;
set => hideDropdownListOnClick = WantContinuousButtonPressed = value;
}
public override bool MouseEvent (MouseEvent me)
{
var res = false;
var isMousePositionValid = IsMousePositionValid (me);
if (isMousePositionValid) {
res = base.MouseEvent (me);
}
if (HideDropdownListOnClick && me.Flags == MouseFlags.Button1Clicked) {
if (!isMousePositionValid && !isFocusing) {
container.isShow = false;
container.HideList ();
} else if (isMousePositionValid) {
OnOpenSelectedItem ();
} else {
isFocusing = false;
}
return true;
} else if (me.Flags == MouseFlags.ReportMousePosition && HideDropdownListOnClick) {
if (isMousePositionValid) {
highlighted = Math.Min (TopItem + me.Y, Source.Count);
SetNeedsDisplay ();
}
isFocusing = false;
return true;
}
return res;
}
private bool IsMousePositionValid (MouseEvent me)
{
if (me.X >= 0 && me.X < Frame.Width && me.Y >= 0 && me.Y < Frame.Height) {
return true;
}
return false;
}
public override void Redraw (Rect bounds)
{
var current = ColorScheme.Focus;
Driver.SetAttribute (current);
Move (0, 0);
var f = Frame;
var item = TopItem;
bool focused = HasFocus;
int col = AllowsMarking ? 2 : 0;
int start = LeftItem;
for (int row = 0; row < f.Height; row++, item++) {
bool isSelected = item == container.SelectedItem;
bool isHighlighted = hideDropdownListOnClick && item == highlighted;
Attribute newcolor;
if (isHighlighted || (isSelected && !hideDropdownListOnClick)) {
newcolor = focused ? ColorScheme.Focus : ColorScheme.HotNormal;
} else if (isSelected && hideDropdownListOnClick) {
newcolor = focused ? ColorScheme.HotFocus : ColorScheme.HotNormal;
} else {
newcolor = focused ? GetNormalColor () : 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 (' ');
} 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 ? Driver.Checked : Driver.Selected) : (AllowsMultipleSelection ? Driver.UnChecked : Driver.UnSelected));
Driver.AddRune (' ');
}
Source.Render (this, Driver, isSelected, item, col, row, f.Width - col, start);
}
}
}
public override bool OnEnter (View view)
{
if (hideDropdownListOnClick) {
isFocusing = true;
highlighted = container.SelectedItem;
Application.GrabMouse (this);
}
return base.OnEnter (view);
}
public override bool OnLeave (View view)
{
if (hideDropdownListOnClick) {
isFocusing = false;
highlighted = container.SelectedItem;
Application.UngrabMouse ();
}
return base.OnLeave (view);
}
public override bool OnSelectedChanged ()
{
var res = base.OnSelectedChanged ();
highlighted = SelectedItem;
return res;
}
}
IListDataSource source;
/// <summary>
/// Gets or sets the <see cref="IListDataSource"/> backing this <see cref="ComboBox"/>, enabling custom rendering.
@@ -61,6 +216,16 @@ namespace Terminal.Gui {
/// </summary>
public event Action<ListViewItemEventArgs> SelectedItemChanged;
/// <summary>
/// This event is raised when the drop-down list is expanded.
/// </summary>
public event Action Expanded;
/// <summary>
/// This event is raised when the drop-down list is collapsed.
/// </summary>
public event Action Collapsed;
/// <summary>
/// This event is raised when the user Double Clicks on an item or presses ENTER to open the selected item.
/// </summary>
@@ -69,7 +234,7 @@ namespace Terminal.Gui {
readonly IList searchset = new List<object> ();
ustring text = "";
readonly TextField search;
readonly ListView listview;
readonly ComboListView listview;
bool autoHide = true;
int minimumHeight = 2;
@@ -87,7 +252,7 @@ namespace Terminal.Gui {
public ComboBox (ustring text) : base ()
{
search = new TextField ("");
listview = new ListView () { LayoutStyle = LayoutStyle.Computed, CanFocus = true, TabStop = false };
listview = new ComboListView (this, HideDropdownListOnClick) { LayoutStyle = LayoutStyle.Computed, CanFocus = true, TabStop = false };
Initialize ();
Text = text;
@@ -101,7 +266,20 @@ namespace Terminal.Gui {
public ComboBox (Rect rect, IList source) : base (rect)
{
search = new TextField ("") { Width = rect.Width };
listview = new ListView (rect, source) { LayoutStyle = LayoutStyle.Computed, ColorScheme = Colors.Base };
listview = new ComboListView (this, rect, source, HideDropdownListOnClick) { LayoutStyle = LayoutStyle.Computed, ColorScheme = Colors.Base };
Initialize ();
SetSource (source);
}
/// <summary>
/// Initialize with the source.
/// </summary>
/// <param name="source">The source.</param>
public ComboBox (IList source) : this (string.Empty)
{
search = new TextField ("");
listview = new ComboListView (this, source, HideDropdownListOnClick) { LayoutStyle = LayoutStyle.Computed, ColorScheme = Colors.Base };
Initialize ();
SetSource (source);
@@ -133,7 +311,7 @@ namespace Terminal.Gui {
listview.SelectedItemChanged += (ListViewItemEventArgs e) => {
if (searchset.Count > 0) {
if (!HideDropdownListOnClick && searchset.Count > 0) {
SetValue (searchset [listview.SelectedItem]);
}
};
@@ -182,6 +360,8 @@ namespace Terminal.Gui {
private bool isShow = false;
private int selectedItem = -1;
private int lastSelectedItem = -1;
private bool hideDropdownListOnClick;
/// <summary>
/// Gets the index of the currently selected item in the <see cref="Source"/>
@@ -193,7 +373,7 @@ namespace Terminal.Gui {
if (selectedItem != value && (value == -1
|| (source != null && value > -1 && value < source.Count))) {
selectedItem = value;
selectedItem = lastSelectedItem = value;
if (selectedItem != -1) {
SetValue (source.ToList () [selectedItem].ToString (), true);
} else {
@@ -236,6 +416,14 @@ namespace Terminal.Gui {
}
}
/// <summary>
/// Gets or sets if the drop-down list can be hide with a button click event.
/// </summary>
public bool HideDropdownListOnClick {
get => hideDropdownListOnClick;
set => hideDropdownListOnClick = listview.HideDropdownListOnClick = value;
}
///<inheritdoc/>
public override bool MouseEvent (MouseEvent me)
{
@@ -268,10 +456,25 @@ namespace Terminal.Gui {
private void FocusSelectedItem ()
{
listview.SelectedItem = SelectedItem > -1 ? SelectedItem : 0;
if (SelectedItem > -1) {
listview.TabStop = true;
listview.SetFocus ();
}
listview.TabStop = true;
listview.SetFocus ();
OnExpanded ();
}
/// <summary>
/// Virtual method which invokes the <see cref="Expanded"/> event.
/// </summary>
public virtual void OnExpanded ()
{
Expanded?.Invoke ();
}
/// <summary>
/// Virtual method which invokes the <see cref="Collapsed"/> event.
/// </summary>
public virtual void OnCollapsed ()
{
Collapsed?.Invoke ();
}
///<inheritdoc/>
@@ -324,6 +527,7 @@ namespace Terminal.Gui {
public virtual bool OnOpenSelectedItem ()
{
var value = search.Text;
lastSelectedItem = SelectedItem;
OpenSelectedItem?.Invoke (new ListViewItemEventArgs (SelectedItem, value));
return true;
@@ -338,6 +542,7 @@ namespace Terminal.Gui {
return;
}
Driver.SetAttribute (ColorScheme.Focus);
Move (Bounds.Right - 1, 0);
Driver.AddRune (Driver.DownArrow);
}
@@ -362,8 +567,16 @@ namespace Terminal.Gui {
bool CancelSelected ()
{
search.SetFocus ();
search.Text = text = "";
OnSelectedChanged ();
if (ReadOnly || HideDropdownListOnClick) {
SelectedItem = lastSelectedItem;
if (SelectedItem > -1 && listview.Source?.Count > 0) {
search.Text = text = listview.Source.ToList () [SelectedItem].ToString ();
}
} else if (!ReadOnly) {
search.Text = text = "";
selectedItem = lastSelectedItem;
OnSelectedChanged ();
}
Collapse ();
return true;
}
@@ -635,12 +848,16 @@ namespace Terminal.Gui {
/// Consider making public
private void HideList ()
{
if (lastSelectedItem != selectedItem) {
OnOpenSelectedItem ();
}
var rect = listview.ViewToScreen (listview.Bounds);
Reset (SelectedItem > -1);
listview.Clear (rect);
listview.TabStop = false;
SuperView?.SendSubviewToBack (this);
SuperView?.SetNeedsDisplay (rect);
OnCollapsed ();
}
/// <summary>

View File

@@ -140,7 +140,7 @@ namespace Terminal.Gui {
/// </remarks>
public void SetSource (IList source)
{
if (source == null)
if (source == null && (Source == null || !(Source is ListWrapper)))
Source = null;
else {
Source = MakeWrapper (source);
@@ -157,7 +157,7 @@ namespace Terminal.Gui {
public Task SetSourceAsync (IList source)
{
return Task.Factory.StartNew (() => {
if (source == null)
if (source == null && (Source == null || !(Source is ListWrapper)))
Source = null;
else
Source = MakeWrapper (source);
@@ -827,7 +827,7 @@ namespace Terminal.Gui {
int GetMaxLengthItem ()
{
if (src?.Count == 0) {
if (src == null || src?.Count == 0) {
return 0;
}
@@ -883,7 +883,7 @@ namespace Terminal.Gui {
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];
var t = src? [item];
if (t == null) {
RenderUstr (driver, ustring.Make (""), col, line, width);
} else {

View File

@@ -33,7 +33,8 @@ namespace UICatalog.Scenarios {
X = Pos.Right (listview) + 1,
Y = Pos.Bottom (lbListView) + 1,
Height = Dim.Fill (2),
Width = Dim.Percent (40)
Width = Dim.Percent (40),
HideDropdownListOnClick = true
};
comboBox.SetSource (items);

View File

@@ -21,18 +21,42 @@ namespace Terminal.Gui.Views {
Assert.Null (cb.Source);
Assert.False (cb.AutoSize);
Assert.Equal (new Rect (0, 0, 0, 2), cb.Frame);
Assert.Equal (-1, cb.SelectedItem);
cb = new ComboBox ("Test");
Assert.Equal ("Test", cb.Text);
Assert.Null (cb.Source);
Assert.False (cb.AutoSize);
Assert.Equal (new Rect (0, 0, 0, 2), cb.Frame);
Assert.Equal (-1, cb.SelectedItem);
cb = new ComboBox (new Rect (1, 2, 10, 20), new List<string> () { "One", "Two", "Three" });
Assert.Equal (string.Empty, cb.Text);
Assert.NotNull (cb.Source);
Assert.False (cb.AutoSize);
Assert.Equal (new Rect (1, 2, 10, 20), cb.Frame);
Assert.Equal (-1, cb.SelectedItem);
cb = new ComboBox (new List<string> () { "One", "Two", "Three" });
Assert.Equal (string.Empty, cb.Text);
Assert.NotNull (cb.Source);
Assert.False (cb.AutoSize);
Assert.Equal (new Rect (0, 0, 0, 2), cb.Frame);
Assert.Equal (-1, cb.SelectedItem);
}
[Fact]
[AutoInitShutdown]
public void Constructor_With_Source_Initialize_With_The_Passed_SelectedItem ()
{
var cb = new ComboBox (new List<string> () { "One", "Two", "Three" }) {
SelectedItem = 1
};
Assert.Equal ("Two", cb.Text);
Assert.NotNull (cb.Source);
Assert.False (cb.AutoSize);
Assert.Equal (new Rect (0, 0, 0, 2), cb.Frame);
Assert.Equal (1, cb.SelectedItem);
}
[Fact]
@@ -240,5 +264,676 @@ Three
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
}
[Fact, AutoInitShutdown]
public void HideDropdownListOnClick_Gets_Sets ()
{
var selected = "";
var cb = new ComboBox {
Height = 4,
Width = 5
};
cb.SetSource (new List<string> { "One", "Two", "Three" });
cb.OpenSelectedItem += (e) => selected = e.Value.ToString ();
Application.Top.Add (cb);
Application.Begin (Application.Top);
Assert.False (cb.HideDropdownListOnClick);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Pressed
}));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (0, cb.SelectedItem);
Assert.Equal ("One", cb.Text);
Assert.True (cb.Subviews [1].MouseEvent (new MouseEvent {
X = 0,
Y = 1,
Flags = MouseFlags.Button1Clicked
}));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (1, cb.SelectedItem);
Assert.Equal ("Two", cb.Text);
Assert.True (cb.Subviews [1].MouseEvent (new MouseEvent {
X = 0,
Y = 1,
Flags = MouseFlags.Button1Clicked
}));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (1, cb.SelectedItem);
Assert.Equal ("Two", cb.Text);
cb.HideDropdownListOnClick = true;
Assert.True (cb.Subviews [1].MouseEvent (new MouseEvent {
X = 0,
Y = 2,
Flags = MouseFlags.Button1Clicked
}));
Assert.Equal ("Three", selected);
Assert.False (cb.IsShow);
Assert.Equal (2, cb.SelectedItem);
Assert.Equal ("Three", cb.Text);
Assert.True (cb.MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Pressed
}));
Assert.True (cb.Subviews [1].MouseEvent (new MouseEvent {
X = 0,
Y = 2,
Flags = MouseFlags.Button1Clicked
}));
Assert.Equal ("Three", selected);
Assert.False (cb.IsShow);
Assert.Equal (2, cb.SelectedItem);
Assert.Equal ("Three", cb.Text);
Assert.True (cb.MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Pressed
}));
Assert.Equal ("Three", selected);
Assert.True (cb.IsShow);
Assert.Equal (2, cb.SelectedItem);
Assert.Equal ("Three", cb.Text);
Assert.True (cb.Subviews [1].MouseEvent (new MouseEvent {
X = 0,
Y = 0,
Flags = MouseFlags.Button1Clicked
}));
Assert.Equal ("One", selected);
Assert.False (cb.IsShow);
Assert.Equal (0, cb.SelectedItem);
Assert.Equal ("One", cb.Text);
}
[Fact, AutoInitShutdown]
public void HideDropdownListOnClick_True_OpenSelectedItem_With_Mouse_And_Key_And_Mouse ()
{
var selected = "";
var cb = new ComboBox {
Height = 4,
Width = 5,
HideDropdownListOnClick = true
};
cb.SetSource (new List<string> { "One", "Two", "Three" });
cb.OpenSelectedItem += (e) => selected = e.Value.ToString ();
Application.Top.Add (cb);
Application.Begin (Application.Top);
Assert.True (cb.HideDropdownListOnClick);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Pressed
}));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())));
Assert.True (cb.MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Pressed
}));
Assert.Equal ("", selected);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Pressed
}));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ())));
Assert.True (cb.MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Pressed
}));
Assert.Equal ("", selected);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
}
[Fact, AutoInitShutdown]
public void HideDropdownListOnClick_True_OpenSelectedItem_With_Mouse_And_Key_CursorDown_And_Esc ()
{
var selected = "";
var cb = new ComboBox {
Height = 4,
Width = 5,
HideDropdownListOnClick = true
};
cb.SetSource (new List<string> { "One", "Two", "Three" });
cb.OpenSelectedItem += (e) => selected = e.Value.ToString ();
Application.Top.Add (cb);
Application.Begin (Application.Top);
Assert.True (cb.HideDropdownListOnClick);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Pressed
}));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ())));
Assert.Equal ("Two", selected);
Assert.False (cb.IsShow);
Assert.Equal (1, cb.SelectedItem);
Assert.Equal ("Two", cb.Text);
Assert.True (cb.ProcessKey (new KeyEvent (Key.F4, new KeyModifiers ())));
Assert.Equal ("Two", selected);
Assert.True (cb.IsShow);
Assert.Equal (1, cb.SelectedItem);
Assert.Equal ("Two", cb.Text);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())));
Assert.Equal ("Two", selected);
Assert.True (cb.IsShow);
Assert.Equal (1, cb.SelectedItem);
Assert.Equal ("Two", cb.Text);
Assert.True (cb.ProcessKey (new KeyEvent (Key.Esc, new KeyModifiers ())));
Assert.Equal ("Two", selected);
Assert.False (cb.IsShow);
Assert.Equal (1, cb.SelectedItem);
Assert.Equal ("Two", cb.Text);
}
[Fact, AutoInitShutdown]
public void HideDropdownListOnClick_False_OpenSelectedItem_With_Mouse_And_Key_CursorDown_And_Esc ()
{
var selected = "";
var cb = new ComboBox {
Height = 4,
Width = 5,
HideDropdownListOnClick = false
};
cb.SetSource (new List<string> { "One", "Two", "Three" });
cb.OpenSelectedItem += (e) => selected = e.Value.ToString ();
Application.Top.Add (cb);
Application.Begin (Application.Top);
Assert.False (cb.HideDropdownListOnClick);
Assert.False (cb.ReadOnly);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Pressed
}));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (0, cb.SelectedItem);
Assert.Equal ("One", cb.Text);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (1, cb.SelectedItem);
Assert.Equal ("Two", cb.Text);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ())));
Assert.Equal ("Two", selected);
Assert.False (cb.IsShow);
Assert.Equal (1, cb.SelectedItem);
Assert.Equal ("Two", cb.Text);
Assert.True (cb.ProcessKey (new KeyEvent (Key.F4, new KeyModifiers ())));
Assert.Equal ("Two", selected);
Assert.True (cb.IsShow);
Assert.Equal (1, cb.SelectedItem);
Assert.Equal ("Two", cb.Text);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())));
Assert.Equal ("Two", selected);
Assert.True (cb.IsShow);
Assert.Equal (2, cb.SelectedItem);
Assert.Equal ("Three", cb.Text);
Assert.True (cb.ProcessKey (new KeyEvent (Key.Esc, new KeyModifiers ())));
Assert.Equal ("Two", selected);
Assert.False (cb.IsShow);
Assert.Equal (1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
}
[Fact, AutoInitShutdown]
public void HideDropdownListOnClick_False_ReadOnly_True_OpenSelectedItem_With_Mouse_And_Key_CursorDown_And_Esc ()
{
var selected = "";
var cb = new ComboBox {
Height = 4,
Width = 5,
HideDropdownListOnClick = false,
ReadOnly = true
};
cb.SetSource (new List<string> { "One", "Two", "Three" });
cb.OpenSelectedItem += (e) => selected = e.Value.ToString ();
Application.Top.Add (cb);
Application.Begin (Application.Top);
Assert.False (cb.HideDropdownListOnClick);
Assert.True (cb.ReadOnly);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Pressed
}));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (0, cb.SelectedItem);
Assert.Equal ("One", cb.Text);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (1, cb.SelectedItem);
Assert.Equal ("Two", cb.Text);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ())));
Assert.Equal ("Two", selected);
Assert.False (cb.IsShow);
Assert.Equal (1, cb.SelectedItem);
Assert.Equal ("Two", cb.Text);
Assert.True (cb.ProcessKey (new KeyEvent (Key.F4, new KeyModifiers ())));
Assert.Equal ("Two", selected);
Assert.True (cb.IsShow);
Assert.Equal (1, cb.SelectedItem);
Assert.Equal ("Two", cb.Text);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())));
Assert.Equal ("Two", selected);
Assert.True (cb.IsShow);
Assert.Equal (2, cb.SelectedItem);
Assert.Equal ("Three", cb.Text);
Assert.True (cb.ProcessKey (new KeyEvent (Key.Esc, new KeyModifiers ())));
Assert.Equal ("Two", selected);
Assert.False (cb.IsShow);
Assert.Equal (1, cb.SelectedItem);
Assert.Equal ("Two", cb.Text);
}
[Fact, AutoInitShutdown]
public void HideDropdownListOnClick_True_OpenSelectedItem_With_Mouse_And_Key_F4 ()
{
var selected = "";
var cb = new ComboBox {
Height = 4,
Width = 5,
HideDropdownListOnClick = true
};
cb.SetSource (new List<string> { "One", "Two", "Three" });
cb.OpenSelectedItem += (e) => selected = e.Value.ToString ();
Application.Top.Add (cb);
Application.Begin (Application.Top);
Assert.True (cb.HideDropdownListOnClick);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Pressed
}));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())));
Assert.True (cb.ProcessKey (new KeyEvent (Key.F4, new KeyModifiers ())));
Assert.Equal ("", selected);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
}
[Fact, AutoInitShutdown]
public void HideDropdownListOnClick_False_OpenSelectedItem_With_Mouse_And_Key_F4 ()
{
var selected = "";
var cb = new ComboBox {
Height = 4,
Width = 5,
HideDropdownListOnClick = false
};
cb.SetSource (new List<string> { "One", "Two", "Three" });
cb.OpenSelectedItem += (e) => selected = e.Value.ToString ();
Application.Top.Add (cb);
Application.Begin (Application.Top);
Assert.False (cb.HideDropdownListOnClick);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Pressed
}));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (0, cb.SelectedItem);
Assert.Equal ("One", cb.Text);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())));
Assert.True (cb.ProcessKey (new KeyEvent (Key.F4, new KeyModifiers ())));
Assert.Equal ("Two", selected);
Assert.False (cb.IsShow);
Assert.Equal (1, cb.SelectedItem);
Assert.Equal ("Two", cb.Text);
}
[Fact, AutoInitShutdown]
public void HideDropdownListOnClick_True_Colapse_On_Click_Outside_Frame ()
{
var selected = "";
var cb = new ComboBox {
Height = 4,
Width = 5,
HideDropdownListOnClick = true
};
cb.SetSource (new List<string> { "One", "Two", "Three" });
cb.OpenSelectedItem += (e) => selected = e.Value.ToString ();
Application.Top.Add (cb);
Application.Begin (Application.Top);
Assert.True (cb.HideDropdownListOnClick);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Pressed
}));
Assert.True (cb.Subviews [1].MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Clicked
}));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.Subviews [1].MouseEvent (new MouseEvent {
X = -1,
Y = 0,
Flags = MouseFlags.Button1Clicked
}));
Assert.Equal ("", selected);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.ProcessKey (new KeyEvent (Key.F4, new KeyModifiers ())));
Assert.True (cb.Subviews [1].MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Clicked
}));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.Subviews [1].MouseEvent (new MouseEvent {
X = 0,
Y = -1,
Flags = MouseFlags.Button1Clicked
}));
Assert.Equal ("", selected);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.ProcessKey (new KeyEvent (Key.F4, new KeyModifiers ())));
Assert.True (cb.Subviews [1].MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Clicked
}));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.Subviews [1].MouseEvent (new MouseEvent {
X = cb.Frame.Width,
Y = 0,
Flags = MouseFlags.Button1Clicked
}));
Assert.Equal ("", selected);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.ProcessKey (new KeyEvent (Key.F4, new KeyModifiers ())));
Assert.True (cb.Subviews [1].MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Clicked
}));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.Subviews [1].MouseEvent (new MouseEvent {
X = 0,
Y = cb.Frame.Height,
Flags = MouseFlags.Button1Clicked
}));
Assert.Equal ("", selected);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
}
[Fact, AutoInitShutdown]
public void HideDropdownListOnClick_True_Highlight_Current_Item ()
{
var selected = "";
var cb = new ComboBox {
Width = 6,
Height = 4,
HideDropdownListOnClick = true,
};
cb.SetSource (new List<string> { "One", "Two", "Three" });
cb.OpenSelectedItem += (e) => selected = e.Value.ToString ();
Application.Top.Add (cb);
Application.Begin (Application.Top);
Assert.True (cb.HideDropdownListOnClick);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.MouseEvent (new MouseEvent {
X = cb.Bounds.Right - 1,
Y = 0,
Flags = MouseFlags.Button1Pressed
}));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
cb.Redraw (cb.Bounds);
GraphViewTests.AssertDriverContentsWithFrameAre (@"
One
Two
Three ", output);
var attributes = new Attribute [] {
// 0
cb.Subviews [0].ColorScheme.Focus,
// 1
cb.Subviews [1].ColorScheme.HotFocus,
// 2
cb.Subviews [1].GetNormalColor ()
};
GraphViewTests.AssertDriverColorsAre (@"
000000
00000
22222
22222", attributes);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
cb.Redraw (cb.Bounds);
GraphViewTests.AssertDriverColorsAre (@"
000000
22222
00000
22222", attributes);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())));
Assert.Equal ("", selected);
Assert.True (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
cb.Redraw (cb.Bounds);
GraphViewTests.AssertDriverColorsAre (@"
000000
22222
22222
00000", attributes);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ())));
Assert.Equal ("Three", selected);
Assert.False (cb.IsShow);
Assert.Equal (2, cb.SelectedItem);
Assert.Equal ("Three", cb.Text);
Assert.True (cb.ProcessKey (new KeyEvent (Key.F4, new KeyModifiers ())));
Assert.Equal ("Three", selected);
Assert.True (cb.IsShow);
Assert.Equal (2, cb.SelectedItem);
Assert.Equal ("Three", cb.Text);
cb.Redraw (cb.Bounds);
GraphViewTests.AssertDriverColorsAre (@"
000000
22222
22222
00000", attributes);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ())));
Assert.Equal ("Three", selected);
Assert.True (cb.IsShow);
Assert.Equal (2, cb.SelectedItem);
Assert.Equal ("Three", cb.Text);
cb.Redraw (cb.Bounds);
GraphViewTests.AssertDriverColorsAre (@"
000000
22222
00000
11111", attributes);
Assert.True (cb.Subviews [1].ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ())));
Assert.Equal ("Three", selected);
Assert.True (cb.IsShow);
Assert.Equal (2, cb.SelectedItem);
Assert.Equal ("Three", cb.Text);
cb.Redraw (cb.Bounds);
GraphViewTests.AssertDriverColorsAre (@"
000000
00000
22222
11111", attributes);
Assert.True (cb.ProcessKey (new KeyEvent (Key.F4, new KeyModifiers ())));
Assert.Equal ("Three", selected);
Assert.False (cb.IsShow);
Assert.Equal (2, cb.SelectedItem);
Assert.Equal ("Three", cb.Text);
}
[Fact, AutoInitShutdown]
public void Expanded_Collapsed_Events ()
{
var cb = new ComboBox {
Height = 4,
Width = 5
};
var list = new List<string> { "One", "Two", "Three" };
cb.Expanded += () => cb.SetSource (list);
cb.Collapsed += () => cb.Source = null;
Application.Top.Add (cb);
Application.Begin (Application.Top);
Assert.Null (cb.Source);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.ProcessKey (new KeyEvent (Key.F4, new KeyModifiers ())));
Assert.NotNull (cb.Source);
Assert.True (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
Assert.True (cb.ProcessKey (new KeyEvent (Key.F4, new KeyModifiers ())));
Assert.Null (cb.Source);
Assert.False (cb.IsShow);
Assert.Equal (-1, cb.SelectedItem);
Assert.Equal ("", cb.Text);
}
}
}

View File

@@ -431,5 +431,25 @@ namespace Terminal.Gui.Views {
│Line9 │
└──────────┘", output);
}
[Fact]
public void SetSource_Preserves_ListWrapper_Instance_If_Not_Null ()
{
var lv = new ListView (new List<string> { "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<string> { "One", "Two" });
Assert.NotNull (lv.Source);
lv.SetSourceAsync (null);
Assert.NotNull (lv.Source);
}
}
}