Merge branch 'master' of tig:migueldeicaza/gui.cs

This commit is contained in:
Charlie Kindel
2020-05-23 13:41:05 -06:00
3 changed files with 308 additions and 0 deletions

View File

@@ -1,5 +1,7 @@
using Terminal.Gui;
using System;
using System.Linq;
using System.IO;
using Mono.Terminal;
using System.Collections.Generic;
using System.Diagnostics;
@@ -410,6 +412,27 @@ static class Demo {
}
MessageBox.Query (60, 10, "Selected Animals", result == "" ? "No animals selected" : result, "Ok");
}
static void ComboBoxDemo ()
{
IList<string> items = new List<string> ();
foreach (var dir in new [] { "/etc", @"\windows\System32" }) {
if (Directory.Exists (dir)) {
items = Directory.GetFiles (dir)
.Select (Path.GetFileName)
.Where (x => char.IsLetterOrDigit (x [0]))
.Distinct ()
.OrderBy (x => x).ToList ();
}
}
var list = new ComboBox (0, 0, 36, 7, items);
list.Changed += (object sender, ustring text) => { Application.RequestStop (); };
var d = new Dialog ("Select source file", 40, 12) { list };
Application.Run (d);
MessageBox.Query (60, 10, "Selected file", list.Text.ToString() == "" ? "Nothing selected" : list.Text.ToString(), "Ok");
}
#endregion
@@ -540,6 +563,7 @@ static class Demo {
new MenuBarItem ("_List Demos", new MenuItem [] {
new MenuItem ("Select _Multiple Items", "", () => ListSelectionDemo (true)),
new MenuItem ("Select _Single Item", "", () => ListSelectionDemo (false)),
new MenuItem ("Search Single Item", "", ComboBoxDemo)
}),
new MenuBarItem ("A_ssorted", new MenuItem [] {
new MenuItem ("_Show text alignments", "", () => ShowTextAlignments ()),

View File

@@ -0,0 +1,227 @@
//
// ComboBox.cs: ComboBox control
//
// Authors:
// Ross Ferguson (ross.c.ferguson@btinternet.com)
//
using System;
using System.Linq;
using System.Collections.Generic;
using NStack;
namespace Terminal.Gui {
/// <summary>
/// ComboBox control
/// </summary>
public class ComboBox : View {
/// <summary>
/// Changed event, raised when the selection has been confirmed.
/// </summary>
/// <remarks>
/// Client code can hook up to this event, it is
/// raised when the selection has been confirmed.
/// </remarks>
public event EventHandler<ustring> Changed;
readonly IList<string> listsource;
IList<string> searchset;
ustring text = "";
readonly TextField search;
readonly ListView listview;
readonly int height;
readonly int width;
bool autoHide = true;
/// <summary>
/// Public constructor
/// </summary>
/// <param name="x">The x coordinate</param>
/// <param name="y">The y coordinate</param>
/// <param name="w">The width</param>
/// <param name="h">The height</param>
/// <param name="source">Auto completetion source</param>
public ComboBox(int x, int y, int w, int h, IList<string> source)
{
listsource = new List<string>(source);
height = h;
width = w;
search = new TextField(x, y, w, "");
search.Changed += Search_Changed;
listview = new ListView(new Rect(x, y + 1, w, 0), listsource.ToList())
{
LayoutStyle = LayoutStyle.Computed,
};
listview.SelectedChanged += (object sender, ListViewItemEventArgs e) => {
if(searchset.Count > 0)
SetValue (searchset [listview.SelectedItem]);
};
Application.Loaded += (object sender, Application.ResizedEventArgs e) => {
// Determine if this view is hosted inside a dialog
for (View view = this.SuperView; view != null; view = view.SuperView) {
if (view is Dialog) {
autoHide = false;
break;
}
}
searchset = autoHide ? new List<string> () : listsource;
// Needs to be re-applied for LayoutStyle.Computed
listview.X = x;
listview.Y = y + 1;
listview.Width = CalculateWidth();
listview.Height = CalculatetHeight ();
if (autoHide)
listview.ColorScheme = Colors.Menu;
else
search.ColorScheme = Colors.Menu;
};
this.Add(listview);
this.Add(search);
this.SetFocus(search);
}
///<inheritdoc cref="OnEnter"/>
public override bool OnEnter ()
{
if (!search.HasFocus)
this.SetFocus (search);
search.CursorPosition = search.Text.Length;
return true;
}
///<inheritdoc cref="ProcessKey"/>
public override bool ProcessKey(KeyEvent e)
{
if (e.Key == Key.Tab)
{
base.ProcessKey(e);
return false; // allow tab-out to next control
}
if (e.Key == Key.Enter && listview.HasFocus) {
if (listview.Source.Count == 0 || searchset.Count == 0) {
text = "";
return true;
}
SetValue( searchset [listview.SelectedItem]);
search.CursorPosition = search.Text.Length;
Search_Changed (search, search.Text);
Changed?.Invoke (this, text);
searchset.Clear();
listview.SetSource(new List<string> ());
listview.Height = 0;
this.SetFocus(search);
return true;
}
if (e.Key == Key.CursorDown && search.HasFocus && listview.SelectedItem == 0 && searchset.Count > 0) { // jump to list
this.SetFocus (listview);
SetValue (searchset [listview.SelectedItem]);
return true;
}
if (e.Key == Key.CursorUp && listview.HasFocus && listview.SelectedItem == 0 && searchset.Count > 0) // jump back to search
{
search.CursorPosition = search.Text.Length;
this.SetFocus (search);
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)
{
Reset();
return true;
}
return base.ProcessKey(e);
}
/// <summary>
/// The currenlty selected list item
/// </summary>
public ustring Text
{
get
{
return text;
}
set {
search.Text = text = value;
}
}
private void SetValue(ustring text)
{
search.Changed -= Search_Changed;
this.text = search.Text = text;
search.CursorPosition = 0;
search.Changed += Search_Changed;
}
/// <summary>
/// Reset to full original list
/// </summary>
private void Reset()
{
search.Text = text = "";
Changed?.Invoke (this, search.Text);
searchset = autoHide ? new List<string> () : listsource;
listview.SetSource(searchset.ToList());
listview.Height = CalculatetHeight ();
this.SetFocus(search);
}
private void Search_Changed (object sender, ustring text)
{
if (string.IsNullOrEmpty (search.Text.ToString()))
searchset = autoHide ? new List<string> () : listsource;
else
searchset = listsource.Where (x => x.StartsWith (search.Text.ToString (), StringComparison.CurrentCultureIgnoreCase)).ToList ();
listview.SetSource (searchset.ToList ());
listview.Height = CalculatetHeight ();
listview.Redraw (new Rect (0, 0, width, height)); // for any view behind this
this.SuperView?.BringSubviewToFront (this);
}
/// <summary>
/// Internal height of dynamic search list
/// </summary>
/// <returns></returns>
private int CalculatetHeight ()
{
return Math.Min (height, searchset.Count);
}
/// <summary>
/// Internal width
/// </summary>
/// <returns></returns>
private int CalculateWidth()
{
return autoHide? Math.Max (1, width - 1) : width;
}
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.Linq;
using System.IO;
using System.Collections.Generic;
using Terminal.Gui;
using NStack;
namespace UICatalog.Scenarios {
[ScenarioMetadata (Name: "Lists", Description: "Demonstrates list selections")]
[ScenarioCategory ("Controls")]
class ListsAndCombos : Scenario {
public override void Setup ()
{
List<string> items = new List<string> ();
foreach (var dir in new [] { "/etc", @"\windows\System32" }) {
if (Directory.Exists (dir)) {
items = Directory.GetFiles (dir)
.Select (Path.GetFileName)
.Where (x => char.IsLetterOrDigit (x [0]))
.Distinct ()
.OrderBy (x => x).ToList ();
}
}
// ListView
var lbListView = new Label ("Listview") {
ColorScheme = Colors.TopLevel,
X = 0,
Width = 30
};
var listview = new ListView (items) {
X = 0,
Y = Pos.Bottom (lbListView) + 1,
Width = 30
};
listview.OpenSelectedItem += (object sender, 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 = 30
};
var comboBox = new ComboBox (0, 0, 30, 10, items) {
X = Pos.Right(listview) + 1 ,
Y = Pos.Bottom (lbListView) +1,
Width = 30
};
comboBox.Changed += (object sender, ustring text) => lbComboBox.Text = text;
Win.Add (lbComboBox, comboBox);
}
}
}