diff --git a/Terminal.Gui/Windows/FileDialog2.cs b/Terminal.Gui/Windows/FileDialog2.cs
index 2c0afa42a..44f4ffb30 100644
--- a/Terminal.Gui/Windows/FileDialog2.cs
+++ b/Terminal.Gui/Windows/FileDialog2.cs
@@ -8,6 +8,8 @@ using NStack;
using Terminal.Gui.Trees;
using static System.Environment;
using System.Text.RegularExpressions;
+using static Terminal.Gui.OpenDialog;
+using System.Collections.ObjectModel;
namespace Terminal.Gui {
@@ -17,6 +19,13 @@ namespace Terminal.Gui {
///
public class FileDialog2 : Dialog {
+ ///
+ /// Determine which type to open.
+ /// Defaults to (i.e. or
+ /// ).
+ ///
+ public OpenMode OpenMode { get; set; } = OpenMode.Mixed;
+
///
/// The currently selected path in the dialog. This is the result that should
/// be used if is off and
@@ -42,15 +51,7 @@ namespace Terminal.Gui {
/// not or .
///
/// If selecting only a single file/directory then you should use instead.
- public IReadOnlyList MultiSelected {
- get {
- if (!AllowsMultipleSelection || Canceled || state == null) {
- return new List ().AsReadOnly ();
- }
-
- return state.Selected.Select (s => s.FileSystemInfo).ToList ().AsReadOnly ();
- }
- }
+ public IReadOnlyList MultiSelected { get; private set; }
// TODO : expose these somehow for localization without compromising case/switch statements
private const string HeaderFilename = "Filename";
@@ -233,8 +234,6 @@ namespace Terminal.Gui {
treeView.ColorScheme = ColorSchemeDefault;
treeView.KeyDown += (k) => k.Handled = this.TreeView_KeyDown (k.KeyEvent);
- // TODO: delay or consider not doing this to avoid double load
- tbPath.Text = Environment.CurrentDirectory;
this.AllowsMultipleSelection = false;
UpdateNavigationVisibility ();
@@ -270,6 +269,17 @@ namespace Terminal.Gui {
}
}
+ private void Accept (IEnumerable toMultiAccept)
+ {
+ if(!AllowsMultipleSelection) {
+ return;
+ }
+
+ MultiSelected = toMultiAccept.Select(s=>s.FileSystemInfo).ToList().AsReadOnly();
+ tbPath.Text = MultiSelected.Count == 1 ? MultiSelected[0].FullName : "";
+ Canceled = false;
+ Application.RequestStop ();
+ }
private void Accept (FileInfo f)
{
tbPath.Text = f.FullName;
@@ -279,7 +289,13 @@ namespace Terminal.Gui {
private void Accept ()
{
- tbPath.AcceptSelectionIfAny ();
+ // if an autocomplete is showing
+ if (tbPath.AcceptSelectionIfAny ()) {
+
+ // enter just accepts it
+ return;
+ }
+
Canceled = false;
Application.RequestStop ();
}
@@ -298,6 +314,7 @@ namespace Terminal.Gui {
if (e.NewValue == null) {
return;
}
+
tbPath.Text = FileDialogTreeBuilder.NodeToDirectory (e.NewValue).FullName;
}
@@ -357,6 +374,10 @@ namespace Terminal.Gui {
return;
}
+ if(tableView.MultiSelect && tableView.MultiSelectedRegions.Any()) {
+ return;
+ }
+
var stats = RowToStats (obj.NewRow);
if (stats == null) {
@@ -444,6 +465,12 @@ namespace Terminal.Gui {
return currentFragment != null && HasFocus && CursorIsAtEnd ();
}
+ ///
+ /// Accepts the current autocomplete suggestion displaying in the text box.
+ /// Returns true if a valid suggestion was being rendered and acceptable or
+ /// false if no suggestion was showing.
+ ///
+ ///
internal bool AcceptSelectionIfAny ()
{
if (MakingSuggestion ()) {
@@ -544,11 +571,16 @@ namespace Terminal.Gui {
{
base.OnLoaded ();
+ // if no path has been provided
+ if (tbPath.Text.Length <= 0) {
+ tbPath.Text = Environment.CurrentDirectory;
+ }
+
// to streamline user experience and allow direct typing of paths
// with zero navigation we start with focus in the text box and any
// default/current path fully selected and ready to be overwritten
tbPath.FocusFirst ();
- tbPath.SelectAll ();
+ tbPath.SelectAll ();
}
private bool TableView_KeyUp (KeyEvent keyEvent)
{
@@ -620,6 +652,12 @@ namespace Terminal.Gui {
private void CellActivate (TableView.CellActivatedEventArgs obj)
{
+ var multi = MultiRowToStats ();
+ if(multi.Any()) {
+ Accept (multi);
+ }
+
+
var stats = RowToStats (obj.Row);
@@ -656,7 +694,7 @@ namespace Terminal.Gui {
tbPath.MoveCursorToEnd ();
}
- state = new FileDialogState (d);
+ state = new FileDialogState (d, OpenMode);
tbPath.GenerateSuggestions (state);
WriteStateToTableView ();
@@ -712,6 +750,29 @@ namespace Terminal.Gui {
return ColorSchemeDefault;
}
+ ///
+ /// If is on and multiple rows are selected
+ /// this returns a union of all in the selection.
+ ///
+ /// Returns an empty collection if there are not at least 2 rows in the selection
+ ///
+ private IEnumerable MultiRowToStats ()
+ {
+ var toReturn = new HashSet();
+
+ if(AllowsMultipleSelection && tableView.MultiSelectedRegions.Any()) {
+
+ foreach(var p in tableView.GetAllSelectedCells()) {
+
+ var add = state?.Children[(int)tableView.Table.Rows [p.Y] [0]];
+ if(add != null) {
+ toReturn.Add (add);
+ }
+ }
+ }
+
+ return toReturn.Count > 1 ? toReturn : Enumerable.Empty ();
+ }
private FileSystemInfoStats RowToStats (int rowIndex)
{
return state?.Children [(int)tableView.Table.Rows [rowIndex] [0]];
@@ -871,12 +932,19 @@ namespace Terminal.Gui {
public List selected = new List ();
public IReadOnlyCollection Selected => selected.AsReadOnly ();
- public FileDialogState (DirectoryInfo dir)
+ public FileDialogState (DirectoryInfo dir, OpenMode openMode)
{
Directory = dir;
try {
- var children = dir.GetFileSystemInfos ().Select (e => new FileSystemInfoStats (e)).ToList ();
+ List children;
+
+ // if directories only
+ if (openMode == OpenMode.Directory) {
+ children = dir.GetDirectories ().Select (e => new FileSystemInfoStats (e)).ToList ();
+ } else {
+ children = dir.GetFileSystemInfos ().Select (e => new FileSystemInfoStats (e)).ToList ();
+ }
// allow navigating up as '..'
if (dir.Parent != null) {
@@ -947,7 +1015,7 @@ namespace Terminal.Gui {
var parent = dlg.state?.Directory.Parent;
if (parent != null) {
- back.Push (new FileDialogState (parent));
+ back.Push (new FileDialogState (parent, dlg.OpenMode));
dlg.PushState (parent, true);
return true;
}
diff --git a/UICatalog/Scenarios/FileDialog2Examples.cs b/UICatalog/Scenarios/FileDialog2Examples.cs
index e4cbd4f62..3a53de8d6 100644
--- a/UICatalog/Scenarios/FileDialog2Examples.cs
+++ b/UICatalog/Scenarios/FileDialog2Examples.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -11,58 +12,50 @@ namespace UICatalog.Scenarios {
public class FileDialog2Examples : Scenario {
public override void Setup ()
{
- var btnOneFile = new Button ("Select One File") {
- X = 1,
- Y = 1
- };
- btnOneFile.Clicked += BtnOneFile_Clicked;
- Win.Add (btnOneFile);
+ var y = 1;
- var btnManyFiles = new Button ("Select Many Files") {
- X = 1,
- Y = Pos.Bottom(btnOneFile) + 1
- };
- btnManyFiles.Clicked += BtnManyFiles_Clicked;
- Win.Add (btnManyFiles);
- }
-
-
- private void BtnOneFile_Clicked ()
- {
- var fd = new FileDialog2 ();
- Application.Run (fd);
-
- if (fd.Canceled) {
- MessageBox.Query (
- "Dialog Canceled",
- "You canceled file navigation and did not pick anything",
- "Yup!");
- } else {
- MessageBox.Query (
- "File chosen!",
- "You chose " + Environment.NewLine + fd.Path,
- "Oh yeah!");
+ foreach(var multi in new bool [] {false, true }) {
+ foreach (OpenDialog.OpenMode openMode in Enum.GetValues (typeof (OpenDialog.OpenMode))) {
+ var btn = new Button ($"Select {(multi?"Many": "One")} {openMode}") {
+ X = 1,
+ Y = y
+ };
+ SetupHandler (btn, openMode, multi);
+ y += 2;
+ Win.Add (btn);
+ }
}
}
- private void BtnManyFiles_Clicked ()
- {
- var fd = new FileDialog2 {
- AllowsMultipleSelection = true
- };
- Application.Run (fd);
- if (fd.Canceled) {
- MessageBox.Query (
- "Dialog Canceled",
- "You canceled file navigation and did not pick anything",
- "Yup!");
- } else {
- MessageBox.Query (
- "File chosen!",
- "You chose " + Environment.NewLine +
- string.Join(Environment.NewLine,fd.MultiSelected.Select(m=>m.FullName)),
- "Oh yeah!");
- }
+ private void SetupHandler (Button btn, OpenDialog.OpenMode mode, bool isMulti)
+ {
+ btn.Clicked += ()=>{
+ var fd = new FileDialog2 {
+ AllowsMultipleSelection = isMulti,
+ OpenMode = mode,
+ };
+
+ Application.Run (fd);
+
+ if (fd.Canceled) {
+ MessageBox.Query (
+ "Canceled",
+ "You canceled navigation and did not pick anything",
+ "Ok");
+ } else if (isMulti) {
+ MessageBox.Query (
+ "Chosen!",
+ "You chose:" + Environment.NewLine +
+ string.Join (Environment.NewLine, fd.MultiSelected.Select (m => m.FullName)),
+ "Ok");
+ }
+ else{
+ MessageBox.Query (
+ "Chosen!",
+ "You chose:" + Environment.NewLine + fd.Path,
+ "Ok");
+ }
+ };
}
}
}