More work on file dialog

This commit is contained in:
Miguel de Icaza
2018-05-09 02:03:53 -04:00
parent bf728373a4
commit 31ae05af42
2 changed files with 102 additions and 18 deletions

View File

@@ -211,7 +211,7 @@ static class Demo {
Application.Init ();
var top = Application.Top;
var tframe = top.Frame;
//Open ();
Open ();
#if true
var win = new Window ("Hello") {
X = 0,

View File

@@ -23,11 +23,14 @@ namespace Terminal.Gui {
internal class DirListView : View {
int top, selected;
DirectoryInfo dirInfo;
List<(string,bool)> infos;
List<(string,bool,bool)> infos;
internal bool canChooseFiles = true;
internal bool canChooseDirectories = false;
internal bool allowsMultipleSelection = false;
public DirListView ()
{
infos = new List<(string,bool)> ();
infos = new List<(string,bool,bool)> ();
CanFocus = true;
}
@@ -43,14 +46,14 @@ namespace Terminal.Gui {
return false;
}
void Reload ()
internal void Reload ()
{
dirInfo = new DirectoryInfo (directory.ToString ());
infos = (from x in dirInfo.GetFileSystemInfos ()
where IsAllowed (x)
orderby (!x.Attributes.HasFlag (FileAttributes.Directory)) + x.Name
select (x.Name, x.Attributes.HasFlag (FileAttributes.Directory))).ToList ();
infos.Insert (0, ("..", true));
select (x.Name, x.Attributes.HasFlag (FileAttributes.Directory), false)).ToList ();
infos.Insert (0, ("..", true, false));
top = 0;
selected = 0;
SetNeedsDisplay ();
@@ -78,7 +81,7 @@ namespace Terminal.Gui {
var width = f.Width;
var ustr = ustring.Make (str);
Move (2, line);
Move (allowsMultipleSelection ? 3 : 2, line);
int byteLen = ustr.Length;
int used = 0;
for (int i = 0; i < byteLen;) {
@@ -121,6 +124,10 @@ namespace Terminal.Gui {
var fi = infos [item];
Driver.AddRune (isSelected ? '>' : ' ');
if (allowsMultipleSelection)
Driver.AddRune (fi.Item3 ? '*' : ' ');
if (fi.Item2)
Driver.AddRune ('/');
else
@@ -134,8 +141,10 @@ namespace Terminal.Gui {
void SelectionChanged ()
{
if (SelectedChanged != null)
SelectedChanged (infos [selected]);
if (SelectedChanged != null) {
var sel = infos [selected];
SelectedChanged ((sel.Item1, sel.Item2));
}
}
public override bool ProcessKey (KeyEvent keyEvent)
@@ -201,6 +210,19 @@ namespace Terminal.Gui {
SetNeedsDisplay ();
}
return true;
case Key.Space:
case Key.ControlT:
if (allowsMultipleSelection) {
if ((canChooseFiles && infos [selected].Item2 == false) ||
(canChooseDirectories && infos [selected].Item2 &&
infos [selected].Item1 != "..")){
infos [selected] = (infos [selected].Item1, infos [selected].Item2, !infos [selected].Item3);
SelectionChanged ();
SetNeedsDisplay ();
}
}
return true;
}
return base.ProcessKey (keyEvent);
}
@@ -214,13 +236,42 @@ namespace Terminal.Gui {
}
}
public string MakePath (string relativePath)
{
return Path.GetFullPath (Path.Combine (Directory.ToString (), relativePath));
}
public IReadOnlyList<string> FilePaths {
get {
if (allowsMultipleSelection) {
var res = new List<string> ();
foreach (var item in infos)
if (item.Item3)
res.Add (MakePath (item.Item1));
return res;
} else {
if (infos [selected].Item2) {
if (canChooseDirectories)
return new List<string> () { MakePath (infos [selected].Item1) };
return Array.Empty<string> ();
} else {
if (canChooseFiles)
return new List<string> () { MakePath (infos [selected].Item1) };
return Array.Empty<string> ();
}
}
}
}
}
/// <summary>
/// Base class for the OpenDialog and the SaveDialog
/// </summary>
public class FileDialog : Dialog {
Button prompt, cancel;
Label nameFieldLabel, message, dirLabel;
TextField dirEntry, nameEntry;
DirListView dirListView;
internal DirListView dirListView;
public FileDialog (ustring title, ustring prompt, ustring nameFieldLabel, ustring message) : base (title, Driver.Cols - 20, Driver.Rows - 5, null)
{
@@ -358,6 +409,19 @@ namespace Terminal.Gui {
}
}
/// <summary>
/// The Open Dialog provides an interactive dialog box for users to select files or directories.
/// </summary>
/// <remarks>
/// <para>
/// The open dialog can be used to select files for opening, it can be configured to allow
/// multiple items to be selected (based on the AllowsMultipleSelection) variable and
/// you can control whether this should allow files or directories to be selected.
/// </para>
/// <para>
/// To select more than one file, users can use the spacebar, or control-t.
/// </para>
/// </remarks>
public class OpenDialog : FileDialog {
public OpenDialog (ustring title, ustring message) : base (title, prompt: "Open", nameFieldLabel: "Open", message: message)
{
@@ -366,25 +430,45 @@ namespace Terminal.Gui {
/// <summary>
/// Gets or sets a value indicating whether this <see cref="T:Terminal.Gui.OpenDialog"/> can choose files.
/// </summary>
/// <value><c>true</c> if can choose files; otherwise, <c>false</c>.</value>
public bool CanChooseFiles { get; set; }
/// <value><c>true</c> if can choose files; otherwise, <c>false</c>. Defaults to <c>true</c></value>
public bool CanChooseFiles {
get => dirListView.canChooseFiles;
set {
dirListView.canChooseDirectories = value;
dirListView.Reload ();
}
}
/// <summary>
/// Gets or sets a value indicating whether this <see cref="T:Terminal.Gui.OpenDialog"/> can choose directories.
/// </summary>
/// <value><c>true</c> if can choose directories; otherwise, <c>false</c>.</value>
public bool CanChooseDirectories { get; set; }
/// <value><c>true</c> if can choose directories; otherwise, <c>false</c> defaults to <c>false</c>.</value>
public bool CanChooseDirectories {
get => dirListView.canChooseDirectories;
set {
dirListView.canChooseDirectories = value;
dirListView.Reload ();
}
}
/// <summary>
/// Gets or sets a value indicating whether this <see cref="T:Terminal.Gui.OpenDialog"/> allows multiple selection.
/// </summary>
/// <value><c>true</c> if allows multiple selection; otherwise, <c>false</c>.</value>
public bool AllowsMultipleSelection { get; set; }
/// <value><c>true</c> if allows multiple selection; otherwise, <c>false</c>, defaults to false.</value>
public bool AllowsMultipleSelection {
get => dirListView.allowsMultipleSelection;
set {
dirListView.allowsMultipleSelection = value;
dirListView.Reload ();
}
}
/// <summary>
/// Gets the file paths selected
/// Returns the selected files, or an empty list if nothing has been selected
/// </summary>
/// <value>The file paths.</value>
public IReadOnlyList<ustring> FilePaths { get; }
public IReadOnlyList<string> FilePaths {
get => dirListView.FilePaths;
}
}
}