diff --git a/Example/demo.cs b/Example/demo.cs index d4d318aba..127749d7c 100644 --- a/Example/demo.cs +++ b/Example/demo.cs @@ -434,7 +434,7 @@ static class Demo { } } var list = new ComboBox () { X = 0, Y = 0, Width = 36, Height = 7 }; - list.SetSource(items); + list.SetSource(items.ToList()); list.Changed += (object sender, ustring text) => { Application.RequestStop (); }; var d = new Dialog ("Select source file", 40, 12) { list }; diff --git a/Terminal.Gui/Core/PosDim.cs b/Terminal.Gui/Core/PosDim.cs index 72f8024e4..51ea52072 100644 --- a/Terminal.Gui/Core/PosDim.cs +++ b/Terminal.Gui/Core/PosDim.cs @@ -361,7 +361,7 @@ namespace Terminal.Gui { return 0; } - internal class DimFactor : Dim { + class DimFactor : Dim { float factor; public DimFactor (float n) diff --git a/Terminal.Gui/Views/ComboBox.cs b/Terminal.Gui/Views/ComboBox.cs index 08c63f5a3..eb03b7caa 100644 --- a/Terminal.Gui/Views/ComboBox.cs +++ b/Terminal.Gui/Views/ComboBox.cs @@ -9,12 +9,46 @@ using System; using System.Linq; using System.Collections.Generic; using NStack; +using System.Collections; namespace Terminal.Gui { /// /// ComboBox control /// public class ComboBox : View { + + 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; + SetNeedsDisplay (); + } + } + + /// + /// 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) + { + if (source == null) + Source = null; + else { + Source = MakeWrapper (source); + } + } + /// /// Changed event, raised when the selection has been confirmed. /// @@ -22,10 +56,10 @@ namespace Terminal.Gui { /// Client code can hook up to this event, it is /// raised when the selection has been confirmed. /// - public Action SelectedItemChanged; + public event EventHandler Changed; - IList listsource; - IList searchset; + //IList listsource; + IList searchset; ustring text = ""; TextField search; ListView listview; @@ -46,42 +80,49 @@ namespace Terminal.Gui { Initialize (); } - /// - /// Public constructor - /// - /// The x coordinate - /// The y coordinate - /// The width - /// The height - /// Auto completion source - public ComboBox (int x, int y, int w, int h, IList source) + ///// + ///// Public constructor + ///// + ///// + ///// + //public ComboBox (Rect rect, IList source) : base (rect) + //{ + // SetSource (source); + // this.x = rect.X; + // this.y = rect.Y; + // this.height = rect.Height; + // this.width = rect.Width; + + // search = new TextField ("") { X = rect.X, Y = rect.Y, Width = width }; + + // listview = new ListView (new Rect (rect.X, rect.Y + 1, width, 0), source) { LayoutStyle = LayoutStyle.Computed}; + + // Initialize (); + //} + + static IListDataSource MakeWrapper (IList source) { - SetSource (source); - this.x = x; - this.y = y; - height = h; - width = w; - - search = new TextField ("") { X = x, Y = y, Width = w }; - - listview = new ListView (new Rect (x, y + 1, w, 0), listsource.ToList ()) { - LayoutStyle = LayoutStyle.Computed, - }; - - Initialize (); + return new ListWrapper (source); } private void Initialize() { - search.Changed += Search_Changed; + search.TextChanged += Search_Changed; + + LayoutComplete += (LayoutEventArgs a) => { + + search.Width = Frame.Width; + listview.Width = Frame.Width - 1; + }; + + listview.SelectedItemChanged += (ListViewItemEventArgs e) => { - listview.SelectedChanged += (object sender, ListViewItemEventArgs e) => { if(searchset.Count > 0) - SetValue (searchset [listview.SelectedItem]); + SetValue ((string)searchset [listview.SelectedItem]); }; // TODO: LayoutComplete event breaks cursor up/down. Revert to Application.Loaded - Application.Loaded += (object sender, Application.ResizedEventArgs a) => { + Application.Loaded += (Application.ResizedEventArgs a) => { // Determine if this view is hosted inside a dialog for (View view = this.SuperView; view != null; view = view.SuperView) { if (view is Dialog) { @@ -90,7 +131,7 @@ namespace Terminal.Gui { } } - searchset = autoHide ? new List () : listsource; + ResetSearchSet (); // Needs to be re-applied for LayoutStyle.Computed // If Dim or Pos are null, these are the from the parametrized constructor @@ -124,7 +165,7 @@ namespace Terminal.Gui { } if (this.Text != null) - Search_Changed (search, Text); + Search_Changed (Text); if (autoHide) listview.ColorScheme = Colors.Menu; @@ -138,20 +179,12 @@ namespace Terminal.Gui { this.SetFocus(search); } - /// - /// Set search list source - /// - public void SetSource(IList source) - { - listsource = new List (source); - } - - private void Search_MouseClick (object sender, MouseEventArgs e) + private void Search_MouseClick (MouseEventArgs e) { if (e.MouseEvent.Flags != MouseFlags.Button1Clicked) return; - SuperView.SetFocus ((View)sender); + SuperView.SetFocus ((View)search); } /// @@ -179,9 +212,9 @@ namespace Terminal.Gui { return true; } - SetValue( searchset [listview.SelectedItem]); + SetValue((string)searchset [listview.SelectedItem]); search.CursorPosition = search.Text.Length; - Search_Changed (search, search.Text); + Search_Changed (search.Text); Changed?.Invoke (this, text); searchset.Clear(); @@ -194,7 +227,7 @@ namespace Terminal.Gui { if (e.Key == Key.CursorDown && search.HasFocus && listview.SelectedItem == 0 && searchset.Count > 0) { // jump to list this.SetFocus (listview); - SetValue (searchset [listview.SelectedItem]); + SetValue ((string)searchset [listview.SelectedItem]); return true; } @@ -241,10 +274,10 @@ namespace Terminal.Gui { private void SetValue(ustring text) { - search.Changed -= Search_Changed; + search.TextChanged -= Search_Changed; this.text = search.Text = text; search.CursorPosition = 0; - search.Changed += Search_Changed; + search.TextChanged += Search_Changed; } /// @@ -254,25 +287,37 @@ namespace Terminal.Gui { { search.Text = text = ""; Changed?.Invoke (this, search.Text); - searchset = autoHide ? new List () : listsource; - listview.SetSource(searchset.ToList()); + ResetSearchSet (); + + listview.SetSource(searchset); listview.Height = CalculatetHeight (); this.SetFocus(search); } - private void Search_Changed (object sender, ustring text) + private void ResetSearchSet() { - if (listsource == null) // Object initialization + if (autoHide) { + if (searchset == null) + searchset = new List (); + else + searchset.Clear (); + } else + searchset = source.ToList (); + } + + private void Search_Changed (ustring text) + { + if (source == null) // Object initialization return; - if (string.IsNullOrEmpty (search.Text.ToString())) - searchset = autoHide ? new List () : listsource; + if (string.IsNullOrEmpty (search.Text.ToString ())) + ResetSearchSet (); else - searchset = listsource.Where (x => x.StartsWith (search.Text.ToString (), StringComparison.CurrentCultureIgnoreCase)).ToList (); + searchset = source.ToList().Cast().Where (x => x.StartsWith (search.Text.ToString (), StringComparison.CurrentCultureIgnoreCase)).ToList(); - listview.SetSource (searchset.ToList ()); + listview.SetSource (searchset); listview.Height = CalculatetHeight (); listview.Redraw (new Rect (0, 0, width, height)); // for any view behind this @@ -308,11 +353,8 @@ namespace Terminal.Gui { { if (dim is Dim.DimAbsolute) return dim.Anchor (0); - - if (dim is Dim.DimFill || dim is Dim.DimFactor) + else return vertical ? dim.Anchor (a.Rows) : dim.Anchor (a.Cols); - - return 0; } } } diff --git a/UICatalog/Scenarios/ListsAndCombos.cs b/UICatalog/Scenarios/ListsAndCombos.cs index 3d1380b65..c91e8e742 100644 --- a/UICatalog/Scenarios/ListsAndCombos.cs +++ b/UICatalog/Scenarios/ListsAndCombos.cs @@ -22,36 +22,34 @@ namespace UICatalog.Scenarios { } } - Dim width = 30; - // ListView var lbListView = new Label ("Listview") { ColorScheme = Colors.TopLevel, X = 0, - Width = width + Width = 30 }; var listview = new ListView (items) { X = 0, Y = Pos.Bottom (lbListView) + 1, Height = Dim.Fill(2), - Width = width + Width = 30 }; - listview.OpenSelectedItem += (object sender, ListViewItemEventArgs e) => lbListView.Text = items [listview.SelectedItem]; + listview.OpenSelectedItem += (ListViewItemEventArgs e) => lbListView.Text = items [listview.SelectedItem]; Win.Add (lbListView, listview); // ComboBox var lbComboBox = new Label ("ComboBox") { ColorScheme = Colors.TopLevel, X = Pos.Right (lbListView) + 1, - Width = width + Width = Dim.Percent(30) }; var comboBox = new ComboBox () { X = Pos.Right (listview) + 1, Y = Pos.Bottom (lbListView) + 1, Height = Dim.Fill (2), - Width = width + Width = Dim.Percent(30) }; comboBox.SetSource (items);