فهرست منبع

merged v2_develop

Tigger Kindel 2 سال پیش
والد
کامیت
176e622eb6

+ 7 - 5
Terminal.Gui/Views/ComboBox.cs

@@ -188,7 +188,7 @@ namespace Terminal.Gui {
 				if (SuperView != null && SuperView.Subviews.Contains (this)) {
 					SelectedItem = -1;
 					search.Text = "";
-					Search_Changed (this, new TextChangedEventArgs(""));
+					Search_Changed (this, new TextChangedEventArgs (""));
 					SetNeedsDisplay ();
 				}
 			}
@@ -316,7 +316,7 @@ namespace Terminal.Gui {
 				}
 			};
 
-			Added += (s,  e) => {
+			Added += (s, e) => {
 
 				// Determine if this view is hosted inside a dialog and is the only control
 				for (View view = this.SuperView; view != null; view = view.SuperView) {
@@ -328,7 +328,7 @@ namespace Terminal.Gui {
 
 				SetNeedsLayout ();
 				SetNeedsDisplay ();
-				Search_Changed (this, new TextChangedEventArgs( Text));
+				Search_Changed (this, new TextChangedEventArgs (Text));
 			};
 
 			// Things this view knows how to do
@@ -745,15 +745,17 @@ namespace Terminal.Gui {
 			if (listview.Source.Count == 0 || (searchset?.Count ?? 0) == 0) {
 				text = "";
 				HideList ();
+				isShow = false;
 				return;
 			}
 
-			SetValue (searchset [listview.SelectedItem]);
+			SetValue (listview.SelectedItem > -1 ? searchset [listview.SelectedItem] : text);
 			search.CursorPosition = search.Text.ConsoleWidth;
-			Search_Changed (this, new TextChangedEventArgs(search.Text));
+			Search_Changed (this, new TextChangedEventArgs (search.Text));
 			OnOpenSelectedItem ();
 			Reset (keepSearchText: true);
 			HideList ();
+			isShow = false;
 		}
 
 		private int GetSelectedItemFromSource (ustring value)

+ 12 - 14
Terminal.Gui/Views/ListView.cs

@@ -96,7 +96,7 @@ namespace Terminal.Gui {
 	/// </remarks>
 	public class ListView : View {
 		int top, left;
-		int selected;
+		int selected = -1;
 
 		IListDataSource source;
 		/// <summary>
@@ -112,7 +112,7 @@ namespace Terminal.Gui {
 				source = value;
 				KeystrokeNavigator.Collection = source?.ToList ()?.Cast<object> ();
 				top = 0;
-				selected = 0;
+				selected = -1;
 				lastSelectedItem = -1;
 				SetNeedsDisplay ();
 			}
@@ -207,7 +207,7 @@ namespace Terminal.Gui {
 
 				if (value < 0 || (source.Count > 0 && value >= source.Count))
 					throw new ArgumentException ("value");
-				top = value;
+				top = Math.Max (value, 0);
 				SetNeedsDisplay ();
 			}
 		}
@@ -485,7 +485,7 @@ namespace Terminal.Gui {
 				n = 0;
 			if (n != selected) {
 				selected = n;
-				top = selected;
+				top = Math.Max (selected, 0);
 				OnSelectedChanged ();
 				SetNeedsDisplay ();
 			}
@@ -506,7 +506,7 @@ namespace Terminal.Gui {
 			if (n != selected) {
 				selected = n;
 				if (source.Count >= Frame.Height)
-					top = selected;
+					top = Math.Max (selected, 0);
 				else
 					top = 0;
 				OnSelectedChanged ();
@@ -540,9 +540,7 @@ namespace Terminal.Gui {
 				if (selected >= top + Frame.Height) {
 					top++;
 				} else if (selected < top) {
-					top = selected;
-				} else if (selected < top) {
-					top = selected;
+					top = Math.Max (selected, 0);
 				}
 				OnSelectedChanged ();
 				SetNeedsDisplay ();
@@ -550,7 +548,7 @@ namespace Terminal.Gui {
 				OnSelectedChanged ();
 				SetNeedsDisplay ();
 			} else if (selected >= top + Frame.Height) {
-				top = source.Count - Frame.Height;
+				top = Math.Max (source.Count - Frame.Height, 0);
 				SetNeedsDisplay ();
 			}
 
@@ -581,14 +579,14 @@ namespace Terminal.Gui {
 					selected = Source.Count - 1;
 				}
 				if (selected < top) {
-					top = selected;
+					top = Math.Max (selected, 0);
 				} else if (selected > top + Frame.Height) {
 					top = Math.Max (selected - Frame.Height + 1, 0);
 				}
 				OnSelectedChanged ();
 				SetNeedsDisplay ();
 			} else if (selected < top) {
-				top = selected;
+				top = Math.Max (selected, 0);
 				SetNeedsDisplay ();
 			}
 			return true;
@@ -604,7 +602,7 @@ namespace Terminal.Gui {
 			if (source.Count > 0 && selected != source.Count - 1) {
 				selected = source.Count - 1;
 				if (top + selected > Frame.Height - 1) {
-					top = selected;
+					top = Math.Max (selected, 0);
 				}
 				OnSelectedChanged ();
 				SetNeedsDisplay ();
@@ -622,7 +620,7 @@ namespace Terminal.Gui {
 		{
 			if (selected != 0) {
 				selected = 0;
-				top = selected;
+				top = Math.Max (selected, 0);
 				OnSelectedChanged ();
 				SetNeedsDisplay ();
 			}
@@ -750,7 +748,7 @@ namespace Terminal.Gui {
 		{
 			SuperView?.LayoutSubviews ();
 			if (selected < top) {
-				top = selected;
+				top = Math.Max (selected, 0);
 			} else if (Frame.Height > 0 && selected >= top + Frame.Height) {
 				top = Math.Max (selected - Frame.Height + 1, 0);
 			}

+ 11 - 9
Terminal.Gui/Views/TextField.cs

@@ -249,6 +249,16 @@ namespace Terminal.Gui {
 			Autocomplete.PopupInsideContainer = false;
 		}
 
+		///<inheritdoc/>
+		public override bool OnEnter (View view)
+		{
+			if (IsInitialized) {
+				Application.Driver.SetCursorVisibility (DesiredCursorVisibility);
+			}
+
+			return base.OnEnter (view);
+		}
+
 		///<inheritdoc/>
 		public override bool OnLeave (View view)
 		{
@@ -308,7 +318,7 @@ namespace Terminal.Gui {
 						, HistoryText.LineStatus.Replaced);
 				}
 
-				TextChanged?.Invoke (this, new TextChangedEventArgs(oldText));
+				TextChanged?.Invoke (this, new TextChangedEventArgs (oldText));
 
 				if (point > text.Count) {
 					point = Math.Max (TextModel.DisplaySize (text, 0).size - 1, 0);
@@ -1269,14 +1279,6 @@ namespace Terminal.Gui {
 			}
 		}
 
-		///<inheritdoc/>
-		public override bool OnEnter (View view)
-		{
-			Application.Driver.SetCursorVisibility (DesiredCursorVisibility);
-
-			return base.OnEnter (view);
-		}
-
 		/// <summary>
 		/// Inserts the given <paramref name="toAdd"/> text at the current cursor position
 		/// exactly as if the user had just typed it

+ 199 - 13
UnitTests/Core/AbsoluteLayoutTests.cs

@@ -54,13 +54,33 @@ namespace Terminal.Gui.CoreTests {
 
 
 		[Fact]
-		public void AbsoluteLayout_Set_Frame ()
+		public void AbsoluteLayout_Change_Frame ()
 		{
 			var frame = new Rect (1, 2, 3, 4);
 			var newFrame = new Rect (1, 2, 30, 40);
 
 			var v = new View (frame);
 			v.Frame = newFrame;
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute);
+			Assert.Equal (newFrame, v.Frame);
+			Assert.Equal (new Rect (0, 0, newFrame.Width, newFrame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout
+			Assert.Null (v.X);
+			Assert.Null (v.Y);
+			Assert.Null (v.Height);
+			Assert.Null (v.Width);
+
+			v = new View (frame.X, frame.Y, "v");
+			v.Frame = newFrame;
+			Assert.Equal (newFrame, v.Frame);
+			Assert.Equal (new Rect (0, 0, newFrame.Width, newFrame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout
+			Assert.Null (v.X);
+			Assert.Null (v.Y);
+			Assert.Null (v.Height);
+			Assert.Null (v.Width);
+
+			newFrame = new Rect (10, 20, 30, 40);
+			v = new View (frame);
+			v.Frame = newFrame;
 			Assert.Equal (newFrame, v.Frame);
 			Assert.Equal (new Rect (0, 0, newFrame.Width, newFrame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout
 			Assert.Null (v.X);
@@ -81,7 +101,7 @@ namespace Terminal.Gui.CoreTests {
 
 
 		[Fact]
-		public void AbsoluteLayout_Set_Size ()
+		public void AbsoluteLayout_Change_Height_or_Width_Absolute ()
 		{
 			var frame = new Rect (1, 2, 3, 4);
 			var newFrame = new Rect (1, 2, 30, 40);
@@ -94,20 +114,185 @@ namespace Terminal.Gui.CoreTests {
 			Assert.Equal (new Rect (0, 0, newFrame.Width, newFrame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout
 			Assert.Null (v.X);
 			Assert.Null (v.Y);
-			Assert.Null (v.Height);
-			Assert.Null (v.Width);
+			Assert.Equal ($"Absolute({newFrame.Height})", v.Height.ToString());
+			Assert.Equal ($"Absolute({newFrame.Width})", v.Width.ToString ());
+		}
 
-			v = new View (frame.X, frame.Y, "v");
-			v.Height = newFrame.Height;
-			v.Width = newFrame.Width;
+		[Fact]
+		public void AbsoluteLayout_Change_Height_or_Width_NotAbsolute ()
+		{
+			var v = new View (Rect.Empty);
+			v.Height = Dim.Fill ();
+			v.Width = Dim.Fill ();
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute);  // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle
+		}
+
+		[Fact]
+		public void AbsoluteLayout_Change_Height_or_Width_Null ()
+		{
+			var v = new View (Rect.Empty);
+			v.Height = null;
+			v.Width = null;
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute);
+		}
+
+		[Fact]
+		public void AbsoluteLayout_Change_X_or_Y_Absolute ()
+		{
+			var frame = new Rect (1, 2, 3, 4);
+			var newFrame = new Rect (10, 20, 3, 4);
+
+			var v = new View (frame);
+			v.X = newFrame.X;
+			v.Y = newFrame.Y;
 			Assert.True (v.LayoutStyle == LayoutStyle.Absolute);
 			Assert.Equal (newFrame, v.Frame);
 			Assert.Equal (new Rect (0, 0, newFrame.Width, newFrame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout
-			Assert.Null (v.X);
-			Assert.Null (v.Y);
+			Assert.Equal ($"Absolute({newFrame.X})", v.X.ToString ());
+			Assert.Equal ($"Absolute({newFrame.Y})", v.Y.ToString ());
 			Assert.Null (v.Height);
 			Assert.Null (v.Width);
+		}
 
+		[Fact]
+		public void AbsoluteLayout_Change_X_or_Y_NotAbsolute ()
+		{
+			var v = new View (Rect.Empty);
+			v.X = Pos.Center ();
+			v.Y = Pos.Center ();
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle
+		}
+
+		[Fact]
+		public void AbsoluteLayout_Change_X_or_Y_Null ()
+		{
+			var v = new View (Rect.Empty);
+			v.X = null;
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute);
+
+			v = new View (Rect.Empty);
+			v.X = Pos.Center ();
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle
+
+			v.X = null;
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute);
+
+			v = new View (Rect.Empty);
+			v.Y = null;
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute);
+
+			v = new View (Rect.Empty);
+			v.Y = Pos.Center ();
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle
+
+			v.Y = null;
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute);
+		}
+
+		[Fact]
+		public void AbsoluteLayout_Change_X_Y_Height_Width_Absolute ()
+		{
+			var v = new View (Rect.Empty);
+			v.X = 1;
+			v.Y = 2;
+			v.Height = 3;
+			v.Width = 4;
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute);
+
+			v = new View (Rect.Empty);
+			v.X = Pos.Center ();
+			v.Y = Pos.Center ();
+			v.Width = Dim.Fill ();
+			v.Height = Dim.Fill ();
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle
+
+			// BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte?
+			v.X = null;
+			v.Y = null;
+			v.Height = null;
+			v.Width = null;
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed??
+
+			v = new View (Rect.Empty);
+			v.X = Pos.Center ();
+			v.Y = Pos.Center ();
+			v.Width = Dim.Fill ();
+			v.Height = Dim.Fill ();
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle
+
+			// BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte?
+			v.X = 1;
+			v.Y = null;
+			v.Height = null;
+			v.Width = null;
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed??
+
+			v = new View (Rect.Empty);
+			v.X = Pos.Center ();
+			v.Y = Pos.Center ();
+			v.Width = Dim.Fill ();
+			v.Height = Dim.Fill ();
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle
+
+			// BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte?
+			v.X = null;
+			v.Y = 2;
+			v.Height = null;
+			v.Width = null;
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed??
+
+			v = new View (Rect.Empty);
+			v.X = Pos.Center ();
+			v.Y = Pos.Center ();
+			v.Width = Dim.Fill ();
+			v.Height = Dim.Fill ();
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle
+
+			// BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte?
+			v.X = null;
+			v.Y = null;
+			v.Height = 3;
+			v.Width = null;
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed??
+
+			v = new View (Rect.Empty);
+			v.X = Pos.Center ();
+			v.Y = Pos.Center ();
+			v.Width = Dim.Fill ();
+			v.Height = Dim.Fill ();
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle
+
+			// BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte?
+			v.X = null;
+			v.Y = null;
+			v.Height = null;
+			v.Width = 4;
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed??
+		}
+
+		[Fact]
+		public void AbsoluteLayout_Change_X_Y_Height_Width_Null ()
+		{
+			var v = new View (Rect.Empty);
+			v.X = null;
+			v.Y = null;
+			v.Height = null;
+			v.Width = null;
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute);
+
+			v = new View (Rect.Empty);
+			v.X = Pos.Center ();
+			v.Y = Pos.Center ();
+			v.Width = Dim.Fill ();
+			v.Height = Dim.Fill ();
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle
+
+			// BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte?
+			v.X = null;
+			v.Y = null;
+			v.Height = null;
+			v.Width = null;
+			Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed??
 		}
 
 		[Fact]
@@ -115,14 +300,15 @@ namespace Terminal.Gui.CoreTests {
 		{
 			var superRect = new Rect (0, 0, 100, 100);
 			var super = new View (superRect, "super");
-
-
+			Assert.True (super.LayoutStyle == LayoutStyle.Absolute);
 			var v1 = new View () {
 				X = 0,
 				Y = 0,
 				Width = 10,
 				Height = 10
 			};
+			// BUGBUG: v2 - This should be LayoutStyle.Absolute
+			Assert.True (v1.LayoutStyle == LayoutStyle.Computed);
 
 			var v2 = new View () {
 				X = 10,
@@ -130,11 +316,11 @@ namespace Terminal.Gui.CoreTests {
 				Width = 10,
 				Height = 10
 			};
+			// BUGBUG: v2 - This should be LayoutStyle.Absolute
+			Assert.True (v1.LayoutStyle == LayoutStyle.Computed);
 
 			super.Add (v1, v2);
-
 			super.LayoutSubviews ();
-
 			Assert.Equal (new Rect (0, 0, 10, 10), v1.Frame);
 			Assert.Equal (new Rect (10, 10, 10, 10), v2.Frame);
 		}

+ 9 - 0
UnitTests/Text/CollectionNavigatorTests.cs

@@ -35,12 +35,21 @@ namespace Terminal.Gui.TextTests {
 		[Fact]
 		public void Cycling ()
 		{
+			// cycling with 'b'
 			var n = new CollectionNavigator (simpleStrings);
 			Assert.Equal (2, n.GetNextMatchingItem (0, 'b'));
 			Assert.Equal (3, n.GetNextMatchingItem (2, 'b'));
 
 			// if 4 (candle) is selected it should loop back to bat
 			Assert.Equal (2, n.GetNextMatchingItem (4, 'b'));
+
+			// cycling with 'a'
+			n = new CollectionNavigator (simpleStrings);
+			Assert.Equal (0, n.GetNextMatchingItem (-1, 'a'));
+			Assert.Equal (1, n.GetNextMatchingItem (0, 'a'));
+
+			// if 4 (candle) is selected it should loop back to appricot
+			Assert.Equal (0, n.GetNextMatchingItem (4, 'a'));
 		}
 
 		[Fact]

+ 16 - 15
UnitTests/Views/ComboBoxTests.cs

@@ -96,13 +96,14 @@ namespace Terminal.Gui.ViewTests {
 			Assert.Equal (-1, cb.SelectedItem);
 			Assert.Equal (string.Empty, cb.Text);
 			var opened = false;
-			cb.OpenSelectedItem += (s,_) => opened = true;
+			cb.OpenSelectedItem += (s, _) => opened = true;
 			Assert.True (cb.ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ())));
 			Assert.False (opened);
 			cb.Text = "Tw";
 			Assert.True (cb.ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ())));
 			Assert.True (opened);
-			Assert.Equal ("Two", cb.Text);
+			Assert.Equal ("", cb.Text);
+			Assert.False (cb.IsShow);
 			cb.SetSource (null);
 			Assert.False (cb.ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ())));
 			Assert.True (cb.ProcessKey (new KeyEvent (Key.F4, new KeyModifiers ()))); // with no source also expand empty
@@ -261,11 +262,11 @@ Three
 			Assert.True (cb.ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ())));
 			Assert.False (cb.IsShow);
 			Assert.Equal (2, cb.Source.Count);
-			Assert.Equal (1, cb.SelectedItem);
-			Assert.Equal ("Two", cb.Text);
+			Assert.Equal (-1, cb.SelectedItem);
+			Assert.Equal ("", cb.Text);
 			Assert.True (cb.ProcessKey (new KeyEvent (Key.Esc, new KeyModifiers ())));
 			Assert.False (cb.IsShow);
-			Assert.Equal (1, cb.SelectedItem); // retains last accept selected item
+			Assert.Equal (-1, cb.SelectedItem); // retains last accept selected item
 			Assert.Equal ("", cb.Text); // clear text
 			cb.SetSource (new List<string> ());
 			Assert.Equal (0, cb.Source.Count);
@@ -282,7 +283,7 @@ Three
 				Width = 5
 			};
 			cb.SetSource (new List<string> { "One", "Two", "Three" });
-			cb.OpenSelectedItem += (s,e) => selected = e.Value.ToString ();
+			cb.OpenSelectedItem += (s, e) => selected = e.Value.ToString ();
 			Application.Top.Add (cb);
 			Application.Begin (Application.Top);
 
@@ -377,7 +378,7 @@ Three
 				HideDropdownListOnClick = true
 			};
 			cb.SetSource (new List<string> { "One", "Two", "Three" });
-			cb.OpenSelectedItem += (s,e) => selected = e.Value.ToString ();
+			cb.OpenSelectedItem += (s, e) => selected = e.Value.ToString ();
 			Application.Top.Add (cb);
 			Application.Begin (Application.Top);
 
@@ -439,7 +440,7 @@ Three
 				HideDropdownListOnClick = true
 			};
 			cb.SetSource (new List<string> { "One", "Two", "Three" });
-			cb.OpenSelectedItem += (s,e) => selected = e.Value.ToString ();
+			cb.OpenSelectedItem += (s, e) => selected = e.Value.ToString ();
 			Application.Top.Add (cb);
 			Application.Begin (Application.Top);
 
@@ -559,7 +560,7 @@ Three
 				ReadOnly = true
 			};
 			cb.SetSource (new List<string> { "One", "Two", "Three" });
-			cb.OpenSelectedItem += (s,e) => selected = e.Value.ToString ();
+			cb.OpenSelectedItem += (s, e) => selected = e.Value.ToString ();
 			Application.Top.Add (cb);
 			Application.Begin (Application.Top);
 
@@ -619,7 +620,7 @@ Three
 				HideDropdownListOnClick = true
 			};
 			cb.SetSource (new List<string> { "One", "Two", "Three" });
-			cb.OpenSelectedItem += (s,e) => selected = e.Value.ToString ();
+			cb.OpenSelectedItem += (s, e) => selected = e.Value.ToString ();
 			Application.Top.Add (cb);
 			Application.Begin (Application.Top);
 
@@ -656,7 +657,7 @@ Three
 				HideDropdownListOnClick = false
 			};
 			cb.SetSource (new List<string> { "One", "Two", "Three" });
-			cb.OpenSelectedItem += (s,e) => selected = e.Value.ToString ();
+			cb.OpenSelectedItem += (s, e) => selected = e.Value.ToString ();
 			Application.Top.Add (cb);
 			Application.Begin (Application.Top);
 
@@ -693,7 +694,7 @@ Three
 				HideDropdownListOnClick = true
 			};
 			cb.SetSource (new List<string> { "One", "Two", "Three" });
-			cb.OpenSelectedItem += (s,e) => selected = e.Value.ToString ();
+			cb.OpenSelectedItem += (s, e) => selected = e.Value.ToString ();
 			Application.Top.Add (cb);
 			Application.Begin (Application.Top);
 
@@ -798,7 +799,7 @@ Three
 				HideDropdownListOnClick = true,
 			};
 			cb.SetSource (new List<string> { "One", "Two", "Three" });
-			cb.OpenSelectedItem += (s,e) => selected = e.Value.ToString ();
+			cb.OpenSelectedItem += (s, e) => selected = e.Value.ToString ();
 			Application.Top.Add (cb);
 			Application.Begin (Application.Top);
 
@@ -920,8 +921,8 @@ Three ", output);
 			};
 			var list = new List<string> { "One", "Two", "Three" };
 
-			cb.Expanded += (s,e) => cb.SetSource (list);
-			cb.Collapsed += (s,e) => cb.Source = null;
+			cb.Expanded += (s, e) => cb.SetSource (list);
+			cb.Collapsed += (s, e) => cb.Source = null;
 
 			Application.Top.Add (cb);
 			Application.Begin (Application.Top);

+ 30 - 14
UnitTests/Views/ListViewTests.cs

@@ -22,19 +22,24 @@ namespace Terminal.Gui.ViewTests {
 			var lv = new ListView ();
 			Assert.Null (lv.Source);
 			Assert.True (lv.CanFocus);
+			Assert.Equal (-1, lv.SelectedItem);
 
 			lv = new ListView (new List<string> () { "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<string> () { "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);
 		}
 
@@ -46,8 +51,8 @@ namespace Terminal.Gui.ViewTests {
 
 			Assert.NotNull (lv.Source);
 
-			// first item should be selected by default
-			Assert.Equal (0, lv.SelectedItem);
+			// first item should be deselected by default
+			Assert.Equal (-1, lv.SelectedItem);
 
 			// nothing is ticked
 			Assert.False (lv.Source.IsMarked (0));
@@ -61,6 +66,17 @@ namespace Terminal.Gui.ViewTests {
 			// view should indicate that it has accepted and consumed the event
 			Assert.True (lv.ProcessKey (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.ProcessKey (ev));
+
 			// second item should now be selected
 			Assert.Equal (1, lv.SelectedItem);
 
@@ -109,8 +125,8 @@ namespace Terminal.Gui.ViewTests {
 
 			Assert.NotNull (lv.Source);
 
-			// first item should be selected by default
-			Assert.Equal (0, lv.SelectedItem);
+			// first item should be deselected by default
+			Assert.Equal (-1, lv.SelectedItem);
 
 			// bind shift down to move down twice in control
 			lv.AddKeyBinding (Key.CursorDown | Key.ShiftMask, Command.LineDown, Command.LineDown);
@@ -119,8 +135,8 @@ namespace Terminal.Gui.ViewTests {
 
 			Assert.True (lv.ProcessKey (ev), "The first time we move down 2 it should be possible");
 
-			// After moving down twice from One we should be at 'Three'
-			Assert.Equal (2, lv.SelectedItem);
+			// After moving down twice from -1 we should be at 'Two'
+			Assert.Equal (1, lv.SelectedItem);
 
 			// clear the items
 			lv.SetSource (null);
@@ -160,9 +176,9 @@ namespace Terminal.Gui.ViewTests {
 		{
 			List<string> source = new List<string> () { "One", "Two", "Three" };
 			ListView lv = new ListView (source) { Height = 2, AllowsMarking = true };
-			Assert.Equal (0, lv.SelectedItem);
+			Assert.Equal (-1, lv.SelectedItem);
 			Assert.True (lv.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())));
-			Assert.Equal (1, lv.SelectedItem);
+			Assert.Equal (0, lv.SelectedItem);
 			Assert.True (lv.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ())));
 			Assert.Equal (0, lv.SelectedItem);
 			Assert.True (lv.ProcessKey (new KeyEvent (Key.PageDown, new KeyModifiers ())));
@@ -175,7 +191,7 @@ namespace Terminal.Gui.ViewTests {
 			Assert.True (lv.ProcessKey (new KeyEvent (Key.Space, new KeyModifiers ())));
 			Assert.True (lv.Source.IsMarked (lv.SelectedItem));
 			var opened = false;
-			lv.OpenSelectedItem += (s,_) => opened = true;
+			lv.OpenSelectedItem += (s, _) => opened = true;
 			Assert.True (lv.ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ())));
 			Assert.True (opened);
 			Assert.True (lv.ProcessKey (new KeyEvent (Key.End, new KeyModifiers ())));
@@ -191,7 +207,7 @@ namespace Terminal.Gui.ViewTests {
 			var rendered = false;
 			var source = new List<string> () { "one", "two", "three" };
 			var lv = new ListView () { Width = Dim.Fill (), Height = Dim.Fill () };
-			lv.RowRender += (s,_) => rendered = true;
+			lv.RowRender += (s, _) => rendered = true;
 			Application.Top.Add (lv);
 			Application.Begin (Application.Top);
 			Assert.False (rendered);
@@ -246,7 +262,7 @@ namespace Terminal.Gui.ViewTests {
 			((FakeDriver)Application.Driver).SetBufferSize (12, 12);
 			Application.Refresh ();
 
-			Assert.Equal (0, lv.SelectedItem);
+			Assert.Equal (-1, lv.SelectedItem);
 			TestHelpers.AssertDriverContentsWithFrameAre (@"
 ┌──────────┐
 │Line0     │
@@ -263,7 +279,7 @@ namespace Terminal.Gui.ViewTests {
 
 			Assert.True (lv.ScrollDown (10));
 			lv.Redraw (lv.Bounds);
-			Assert.Equal (0, lv.SelectedItem);
+			Assert.Equal (-1, lv.SelectedItem);
 			TestHelpers.AssertDriverContentsWithFrameAre (@"
 ┌──────────┐
 │Line10    │
@@ -280,9 +296,10 @@ namespace Terminal.Gui.ViewTests {
 
 			Assert.True (lv.MoveDown ());
 			lv.Redraw (lv.Bounds);
-			Assert.Equal (1, lv.SelectedItem);
+			Assert.Equal (0, lv.SelectedItem);
 			TestHelpers.AssertDriverContentsWithFrameAre (@"
 ┌──────────┐
+│Line0     │
 │Line1     │
 │Line2     │
 │Line3     │
@@ -292,7 +309,6 @@ namespace Terminal.Gui.ViewTests {
 │Line7     │
 │Line8     │
 │Line9     │
-│Line10    │
 └──────────┘", output);
 
 			Assert.True (lv.MoveEnd ());

+ 15 - 4
UnitTests/Views/TextFieldTests.cs

@@ -663,7 +663,7 @@ namespace Terminal.Gui.ViewTests {
 		{
 			bool cancel = true;
 
-			_textField.TextChanging += (s,e) => {
+			_textField.TextChanging += (s, e) => {
 				Assert.Equal ("changing", e.NewText);
 				if (cancel) {
 					e.Cancel = true;
@@ -681,7 +681,7 @@ namespace Terminal.Gui.ViewTests {
 		[TextFieldTestsAutoInitShutdown]
 		public void TextChanged_Event ()
 		{
-			_textField.TextChanged += (s,e) => {
+			_textField.TextChanged += (s, e) => {
 				Assert.Equal ("TAB to jump between text fields.", e.OldValue);
 			};
 
@@ -781,7 +781,7 @@ namespace Terminal.Gui.ViewTests {
 			Assert.Equal ("A", tf.Text.ToString ());
 
 			// cancel the next keystroke
-			tf.TextChanging += (s,e) => e.Cancel = e.NewText == "AB";
+			tf.TextChanging += (s, e) => e.Cancel = e.NewText == "AB";
 			tf.ProcessKey (new KeyEvent (Key.B, new KeyModifiers ()));
 
 			// B was canceled so should just be A
@@ -1137,7 +1137,7 @@ namespace Terminal.Gui.ViewTests {
 			var oldText = "";
 			var tf = new TextField () { Width = 10, Text = "-1" };
 
-			tf.TextChanging += (s,e) => newText = e.NewText.ToString ();
+			tf.TextChanging += (s, e) => newText = e.NewText.ToString ();
 			tf.TextChanged += (s, e) => oldText = e.OldValue.ToString ();
 
 			Application.Top.Add (tf);
@@ -1440,5 +1440,16 @@ Les Miśerables", output);
 			TestHelpers.AssertDriverContentsWithFrameAre (@"
 ắ", output);
 		}
+
+		[Fact]
+		public void OnEnter_Does_Not_Throw_If_Not_IsInitialized_SetCursorVisibility ()
+		{
+			var top = new Toplevel ();
+			var tf = new TextField () { Width = 10 };
+			top.Add (tf);
+
+			var exception = Record.Exception (tf.SetFocus);
+			Assert.Null (exception);
+		}
 	}
 }