diff --git a/Example/demo.cs b/Example/demo.cs
index 76e24ddbc..0fc148508 100644
--- a/Example/demo.cs
+++ b/Example/demo.cs
@@ -422,7 +422,7 @@ static class Demo {
var d = new Dialog ("Select source file", 40, 12) { list };
Application.Run (d);
- MessageBox.Query (60, 10, "Selected file", list.Text == null ? "Nothing selected" : list.Text, "Ok");
+ MessageBox.Query (60, 10, "Selected file", list.Text.ToString() == "" ? "Nothing selected" : list.Text.ToString(), "Ok");
}
#endregion
diff --git a/Terminal.Gui/Views/TextFieldAutoComplete.cs b/Terminal.Gui/Views/TextFieldAutoComplete.cs
index 3c8c1f210..57befd95c 100644
--- a/Terminal.Gui/Views/TextFieldAutoComplete.cs
+++ b/Terminal.Gui/Views/TextFieldAutoComplete.cs
@@ -4,6 +4,9 @@
// Author:
// Ross Ferguson (ross.c.ferguson@btinternet.com)
//
+// TODO:
+// * Completion list auto appears when hosted directly in a Window as opposed to a dialog
+//
using System;
using System.Linq;
@@ -15,13 +18,22 @@ namespace Terminal.Gui {
/// TextField with AutoComplete
///
public class TextFieldAutoComplete : View {
+ ///
+ /// Changed event, raised when the selection has been confirmed.
+ ///
+ ///
+ /// Client code can hook up to this event, it is
+ /// raised when the selection has been confirmed.
+ ///
public event EventHandler Changed;
readonly IList listsource;
IList searchset;
+ ustring text = "";
readonly TextField search;
readonly ListView listview;
readonly int height;
+ readonly int width;
///
/// Public constructor
@@ -31,23 +43,34 @@ namespace Terminal.Gui {
/// The width
/// The height
/// Auto completetion source
- public TextFieldAutoComplete(int x, int y, int w, int h, IList source) : base()
+ public TextFieldAutoComplete(int x, int y, int w, int h, IList source)
{
listsource = searchset = source;
height = h;
+ width = w;
search = new TextField(x, y, w, "");
search.Changed += Search_Changed;
- listview = new ListView(new Rect(x, y + 1, w, Math.Min(height, searchset.Count())), listsource.ToList())
- {
- //LayoutStyle = LayoutStyle.Computed,
+ listview = new ListView(new Rect(x, y + 1, w, CalculatetHeight()), listsource.ToList())
+ {
+ LayoutStyle = LayoutStyle.Computed,
+ ColorScheme = Colors.Dialog
};
-
+
+ // Needs to be re-applied for LayoutStyle.Computed
+ listview.X = x;
+ listview.Y = y + 1;
+ listview.Width = w;
+ listview.Height = CalculatetHeight ();
+
this.Add(listview);
this.Add(search);
this.SetFocus(search);
- this.OnEnter += (object sender, EventArgs e) => { this.SetFocus(search); };
+ this.OnEnter += (object sender, EventArgs e) => {
+ this.SetFocus(search);
+ search.CursorPosition = search.Text.Length;
+ };
}
public override bool ProcessKey(KeyEvent e)
@@ -57,23 +80,25 @@ namespace Terminal.Gui {
base.ProcessKey(e);
return false; // allow tab-out to next control
}
-
- if (e.Key == Key.Enter)
- {
- if (Text == null)
- return false; // allow tab-out to next control
- search.Text = Text;
+ if (e.Key == Key.Enter && listview.HasFocus) {
+
+ if (listview.Source.Count == 0 || searchset.Count == 0) {
+ text = "";
+ return true;
+ }
+
+ search.Text = text = searchset [listview.SelectedItem];
search.CursorPosition = search.Text.Length;
+ Changed?.Invoke (this, text);
+
searchset.Clear();
listview.Clear();
this.SetFocus(search);
- Changed?.Invoke(this, search.Text);
-
return true;
}
-
+
if (e.Key == Key.CursorDown && search.HasFocus) // jump to list
{
this.SetFocus(listview);
@@ -87,8 +112,15 @@ namespace Terminal.Gui {
return true;
}
+ if (e.Key == Key.Esc) {
+ this.SetFocus (search);
+ search.Text = text = "";
+ Changed?.Invoke (this, search.Text);
+ return true;
+ }
+
// Unix emulation
- if (e.Key == Key.ControlU || e.Key == Key.Esc)
+ if (e.Key == Key.ControlU)
{
Reset();
return true;
@@ -100,14 +132,14 @@ namespace Terminal.Gui {
///
/// The currenlty selected list item
///
- public string Text
+ public ustring Text
{
get
{
- if (listview.Source.Count == 0 || searchset.Count() == 0)
- return search.Text.ToString();
-
- return searchset.ToList()[listview.SelectedItem] as string;
+ return text;
+ }
+ set {
+ search.Text = text = value;
}
}
@@ -116,22 +148,52 @@ namespace Terminal.Gui {
///
private void Reset()
{
- search.Text = "";
+ search.Text = text = "";
+ Changed?.Invoke (this, search.Text);
searchset = listsource;
+
listview.SetSource(searchset.ToList());
+ listview.Height = CalculatetHeight ();
+ listview.Redraw (new Rect (0, 0, width, height));
+
this.SetFocus(search);
}
- private void Search_Changed(object sender, ustring e)
+ private void Search_Changed (object sender, ustring text)
{
-
- if (string.IsNullOrEmpty(search.Text.ToString()))
+ // Cannot use text argument as its old value (pre-change)
+ if (string.IsNullOrEmpty (search.Text.ToString())) {
searchset = listsource;
+ }
else
- searchset = listsource.Where(x => x.ToLower().Contains(search.Text.ToString().ToLower())).ToList();
+ searchset = listsource.Where (x => x.StartsWith (search.Text.ToString (), StringComparison.CurrentCultureIgnoreCase)).ToList ();
- listview.SetSource(searchset.ToList());
- listview.Height = Math.Min(height, searchset.Count());
+ listview.SetSource (searchset.ToList ());
+ listview.Height = CalculatetHeight ();
+ listview.Redraw (new Rect (0, 0, width, height));
+ }
+
+ ///
+ /// Internal height of dynamic search list
+ ///
+ ///
+ private int CalculatetHeight ()
+ {
+ return Math.Min (height, searchset.Count);
+ }
+
+ ///
+ /// Determine if this view is hosted inside a dialog
+ ///
+ ///
+ private bool IsDialogHosted()
+ {
+ for (View v = this.SuperView; v != null; v = v.SuperView) {
+
+ if (v.GetType () == typeof (Dialog))
+ return true;
+ }
+ return false;
}
}
}