Browse Source

Fixes #1584 - ComboBox is hiding elements below from being clicked/focused (#1585)

* Fixes #1584

* Fixes https://github.com/migueldeicaza/gui.cs/issues/1584#issuecomment-1027987475

* Fixes some bugs with SelectedItem.

* Ensures updating the ComboBox text on leaving the control.

Co-authored-by: BDisp <[email protected]>
Thomas Nind 3 years ago
parent
commit
3e7d2ef570

+ 38 - 9
Terminal.Gui/Views/ComboBox.cs

@@ -31,6 +31,8 @@ namespace Terminal.Gui {
 
 				// Only need to refresh list if its been added to a container view
 				if (SuperView != null && SuperView.Subviews.Contains (this)) {
+					SelectedItem = -1;
+					search.Text = "";
 					Search_Changed ("");
 					SetNeedsDisplay ();
 				}
@@ -64,7 +66,7 @@ namespace Terminal.Gui {
 		/// </summary>
 		public event Action<ListViewItemEventArgs> OpenSelectedItem;
 
-        readonly IList searchset = new List<object> ();
+		readonly IList searchset = new List<object> ();
 		ustring text = "";
 		readonly TextField search;
 		readonly ListView listview;
@@ -156,13 +158,29 @@ namespace Terminal.Gui {
 			};
 		}
 
+		private bool isShow = false;
+		private int selectedItem = -1;
+
 		/// <summary>
 		/// Gets the index of the currently selected item in the <see cref="Source"/>
 		/// </summary>
 		/// <value>The selected item or -1 none selected.</value>
-		public int SelectedItem { private set; get; }
-
-		bool isShow = false;
+		public int SelectedItem {
+			get => selectedItem;
+			set {
+				if (selectedItem != value && (value == -1
+					|| (source != null && value > -1 && value < source.Count))) {
+
+					selectedItem = value;
+					if (selectedItem != -1) {
+						SetValue (source.ToList () [selectedItem].ToString (), true);
+					} else {
+						SetValue ("", true);
+					}
+					OnSelectedChanged ();
+				}
+			}
+		}
 
 		///<inheritdoc/>
 		public new ColorScheme ColorScheme {
@@ -244,6 +262,11 @@ namespace Terminal.Gui {
 		///<inheritdoc/>
 		public override bool OnLeave (View view)
 		{
+			if (source?.Count > 0 && selectedItem > -1 && selectedItem < source.Count - 1
+				&& text != source.ToList () [selectedItem].ToString ()) {
+
+				SetValue (source.ToList () [selectedItem].ToString ());
+			}
 			if (autoHide && isShow && view != this && view != search && view != listview) {
 				isShow = false;
 				HideList ();
@@ -392,22 +415,26 @@ namespace Terminal.Gui {
 			}
 		}
 
-		private void SetValue (object text)
+		private void SetValue (object text, bool isFromSelectedItem = false)
 		{
 			search.TextChanged -= Search_Changed;
 			this.text = search.Text = text.ToString ();
 			search.CursorPosition = 0;
 			search.TextChanged += Search_Changed;
-			SelectedItem = GetSelectedItemFromSource (this.text);
-			OnSelectedChanged ();
+			if (!isFromSelectedItem) {
+				selectedItem = GetSelectedItemFromSource (this.text);
+				OnSelectedChanged ();
+			}
 		}
 
 		private void Selected ()
 		{
 			isShow = false;
 			listview.TabStop = false;
+
 			if (listview.Source.Count == 0 || (searchset?.Count ?? 0) == 0) {
 				text = "";
+				HideList ();
 				return;
 			}
 
@@ -416,6 +443,7 @@ namespace Terminal.Gui {
 			Search_Changed (search.Text);
 			OnOpenSelectedItem ();
 			Reset (keepSearchText: true);
+			HideList ();
 		}
 
 		private int GetSelectedItemFromSource (ustring value)
@@ -452,7 +480,7 @@ namespace Terminal.Gui {
 
 		private void ResetSearchSet (bool noCopy = false)
 		{
-            searchset.Clear ();
+			searchset.Clear ();
 
 			if (autoHide || noCopy)
 				return;
@@ -496,7 +524,7 @@ namespace Terminal.Gui {
 		/// Consider making public
 		private void ShowList ()
 		{
-            listview.SetSource (searchset);
+			listview.SetSource (searchset);
 			listview.Clear (); // Ensure list shrinks in Dialog as you type
 			listview.Height = CalculatetHeight ();
 			this.SuperView?.BringSubviewToFront (this);
@@ -513,6 +541,7 @@ namespace Terminal.Gui {
 			Reset (SelectedItem > -1);
 			listview.Clear (rect);
 			listview.TabStop = false;
+			SuperView?.SendSubviewToBack (this);
 			SuperView?.SetNeedsDisplay (rect);
 		}
 

+ 78 - 0
UICatalog/Scenarios/ComboBoxIteration.cs

@@ -0,0 +1,78 @@
+using System.Collections.Generic;
+using Terminal.Gui;
+
+namespace UICatalog.Scenarios {
+	[ScenarioMetadata (Name: "ComboBoxIteration", Description: "ComboBox iteration.")]
+	[ScenarioCategory ("Controls")]
+	public class ComboBoxIteration : Scenario {
+		public override void Setup ()
+		{
+			var items = new List<string> () { "one", "two", "three" };
+
+			var lbListView = new Label () {
+				AutoSize = false,
+				Width = 10,
+				Height = 1
+			};
+			Win.Add (lbListView);
+
+			var listview = new ListView (items) {
+				Y = Pos.Bottom (lbListView) + 1,
+				Width = 10,
+				Height = Dim.Fill (2)
+			};
+			Win.Add (listview);
+
+			var lbComboBox = new Label () {
+				ColorScheme = Colors.TopLevel,
+				X = Pos.Right (lbListView) + 1,
+				Width = Dim.Percent (40)
+			};
+
+			var comboBox = new ComboBox () {
+				X = Pos.Right (listview) + 1,
+				Y = Pos.Bottom (lbListView) + 1,
+				Height = Dim.Fill (2),
+				Width = Dim.Percent (40)
+			};
+			comboBox.SetSource (items);
+
+			listview.SelectedItemChanged += (e) => {
+				lbListView.Text = items [e.Item];
+				comboBox.SelectedItem = e.Item;
+			};
+
+			comboBox.SelectedItemChanged += (ListViewItemEventArgs text) => {
+				if (text.Item != -1) {
+					lbComboBox.Text = text.Value.ToString ();
+					listview.SelectedItem = text.Item;
+				}
+			};
+			Win.Add (lbComboBox, comboBox);
+			Win.Add (new TextField { X = Pos.Right (listview) + 1, Y = Pos.Top (comboBox) + 3, Height = 1, Width = 20 });
+
+			var btnTwo = new Button ("Two") {
+				X = Pos.Right (comboBox) + 1,
+			};
+			btnTwo.Clicked += () => {
+				items = new List<string> () { "one", "two" };
+				comboBox.SetSource (items);
+				listview.SetSource (items);
+				listview.SelectedItem = 0;
+			};
+			Win.Add (btnTwo);
+
+			var btnThree = new Button ("Three") {
+				X = Pos.Right (comboBox) + 1,
+				Y = Pos.Top (comboBox)
+			};
+			btnThree.Clicked += () => {
+				items = new List<string> () { "one", "two", "three" };
+				comboBox.SetSource (items);
+				listview.SetSource (items);
+				listview.SelectedItem = 0;
+			};
+			Win.Add (btnThree);
+		}
+	}
+}

+ 1 - 1
UICatalog/Scenarios/ListsAndCombos.cs

@@ -80,7 +80,7 @@ namespace UICatalog.Scenarios {
 			};
 			comboBox.SetSource (items);
 
-			comboBox.SelectedItemChanged += (ListViewItemEventArgs text) => lbComboBox.Text = items[comboBox.SelectedItem];
+			comboBox.SelectedItemChanged += (ListViewItemEventArgs text) => lbComboBox.Text = text.Value.ToString ();
 			Win.Add (lbComboBox, comboBox);
 
 			var scrollBarCbx = new ScrollBarView (comboBox.Subviews [1], true);