Skip to content

Commit 31ae05a

Browse files
committed
More work on file dialog
1 parent bf72837 commit 31ae05a

2 files changed

Lines changed: 102 additions & 18 deletions

File tree

‎Example/demo.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ static void Main ()
211211
Application.Init ();
212212
var top = Application.Top;
213213
var tframe = top.Frame;
214-
//Open ();
214+
Open ();
215215
#if true
216216
var win = new Window ("Hello") {
217217
X = 0,

‎Terminal.Gui/Dialogs/FileDialog.cs‎

Lines changed: 101 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,14 @@ namespace Terminal.Gui {
2323
internal class DirListView : View {
2424
int top, selected;
2525
DirectoryInfo dirInfo;
26-
List<(string,bool)> infos;
26+
List<(string,bool,bool)> infos;
27+
internal bool canChooseFiles = true;
28+
internal bool canChooseDirectories = false;
29+
internal bool allowsMultipleSelection = false;
2730

2831
public DirListView ()
2932
{
30-
infos = new List<(string,bool)> ();
33+
infos = new List<(string,bool,bool)> ();
3134
CanFocus = true;
3235
}
3336

@@ -43,14 +46,14 @@ bool IsAllowed (FileSystemInfo fsi)
4346
return false;
4447
}
4548

46-
void Reload ()
49+
internal void Reload ()
4750
{
4851
dirInfo = new DirectoryInfo (directory.ToString ());
4952
infos = (from x in dirInfo.GetFileSystemInfos ()
5053
where IsAllowed (x)
5154
orderby (!x.Attributes.HasFlag (FileAttributes.Directory)) + x.Name
52-
select (x.Name, x.Attributes.HasFlag (FileAttributes.Directory))).ToList ();
53-
infos.Insert (0, ("..", true));
55+
select (x.Name, x.Attributes.HasFlag (FileAttributes.Directory), false)).ToList ();
56+
infos.Insert (0, ("..", true, false));
5457
top = 0;
5558
selected = 0;
5659
SetNeedsDisplay ();
@@ -78,7 +81,7 @@ void DrawString (int line, string str)
7881
var width = f.Width;
7982
var ustr = ustring.Make (str);
8083

81-
Move (2, line);
84+
Move (allowsMultipleSelection ? 3 : 2, line);
8285
int byteLen = ustr.Length;
8386
int used = 0;
8487
for (int i = 0; i < byteLen;) {
@@ -121,6 +124,10 @@ public override void Redraw (Rect region)
121124
var fi = infos [item];
122125

123126
Driver.AddRune (isSelected ? '>' : ' ');
127+
128+
if (allowsMultipleSelection)
129+
Driver.AddRune (fi.Item3 ? '*' : ' ');
130+
124131
if (fi.Item2)
125132
Driver.AddRune ('/');
126133
else
@@ -134,8 +141,10 @@ public override void Redraw (Rect region)
134141

135142
void SelectionChanged ()
136143
{
137-
if (SelectedChanged != null)
138-
SelectedChanged (infos [selected]);
144+
if (SelectedChanged != null) {
145+
var sel = infos [selected];
146+
SelectedChanged ((sel.Item1, sel.Item2));
147+
}
139148
}
140149

141150
public override bool ProcessKey (KeyEvent keyEvent)
@@ -201,6 +210,19 @@ public override bool ProcessKey (KeyEvent keyEvent)
201210
SetNeedsDisplay ();
202211
}
203212
return true;
213+
214+
case Key.Space:
215+
case Key.ControlT:
216+
if (allowsMultipleSelection) {
217+
if ((canChooseFiles && infos [selected].Item2 == false) ||
218+
(canChooseDirectories && infos [selected].Item2 &&
219+
infos [selected].Item1 != "..")){
220+
infos [selected] = (infos [selected].Item1, infos [selected].Item2, !infos [selected].Item3);
221+
SelectionChanged ();
222+
SetNeedsDisplay ();
223+
}
224+
}
225+
return true;
204226
}
205227
return base.ProcessKey (keyEvent);
206228
}
@@ -214,13 +236,42 @@ public string [] AllowedFileTypes {
214236
}
215237
}
216238

239+
public string MakePath (string relativePath)
240+
{
241+
return Path.GetFullPath (Path.Combine (Directory.ToString (), relativePath));
242+
}
243+
244+
public IReadOnlyList<string> FilePaths {
245+
get {
246+
if (allowsMultipleSelection) {
247+
var res = new List<string> ();
248+
foreach (var item in infos)
249+
if (item.Item3)
250+
res.Add (MakePath (item.Item1));
251+
return res;
252+
} else {
253+
if (infos [selected].Item2) {
254+
if (canChooseDirectories)
255+
return new List<string> () { MakePath (infos [selected].Item1) };
256+
return Array.Empty<string> ();
257+
} else {
258+
if (canChooseFiles)
259+
return new List<string> () { MakePath (infos [selected].Item1) };
260+
return Array.Empty<string> ();
261+
}
262+
}
263+
}
264+
}
217265
}
218266

267+
/// <summary>
268+
/// Base class for the OpenDialog and the SaveDialog
269+
/// </summary>
219270
public class FileDialog : Dialog {
220271
Button prompt, cancel;
221272
Label nameFieldLabel, message, dirLabel;
222273
TextField dirEntry, nameEntry;
223-
DirListView dirListView;
274+
internal DirListView dirListView;
224275

225276
public FileDialog (ustring title, ustring prompt, ustring nameFieldLabel, ustring message) : base (title, Driver.Cols - 20, Driver.Rows - 5, null)
226277
{
@@ -358,6 +409,19 @@ public SaveDialog (ustring title, ustring message) : base (title, prompt: "Save"
358409
}
359410
}
360411

412+
/// <summary>
413+
/// The Open Dialog provides an interactive dialog box for users to select files or directories.
414+
/// </summary>
415+
/// <remarks>
416+
/// <para>
417+
/// The open dialog can be used to select files for opening, it can be configured to allow
418+
/// multiple items to be selected (based on the AllowsMultipleSelection) variable and
419+
/// you can control whether this should allow files or directories to be selected.
420+
/// </para>
421+
/// <para>
422+
/// To select more than one file, users can use the spacebar, or control-t.
423+
/// </para>
424+
/// </remarks>
361425
public class OpenDialog : FileDialog {
362426
public OpenDialog (ustring title, ustring message) : base (title, prompt: "Open", nameFieldLabel: "Open", message: message)
363427
{
@@ -366,25 +430,45 @@ public OpenDialog (ustring title, ustring message) : base (title, prompt: "Open"
366430
/// <summary>
367431
/// Gets or sets a value indicating whether this <see cref="T:Terminal.Gui.OpenDialog"/> can choose files.
368432
/// </summary>
369-
/// <value><c>true</c> if can choose files; otherwise, <c>false</c>.</value>
370-
public bool CanChooseFiles { get; set; }
433+
/// <value><c>true</c> if can choose files; otherwise, <c>false</c>. Defaults to <c>true</c></value>
434+
public bool CanChooseFiles {
435+
get => dirListView.canChooseFiles;
436+
set {
437+
dirListView.canChooseDirectories = value;
438+
dirListView.Reload ();
439+
}
440+
}
371441

372442
/// <summary>
373443
/// Gets or sets a value indicating whether this <see cref="T:Terminal.Gui.OpenDialog"/> can choose directories.
374444
/// </summary>
375-
/// <value><c>true</c> if can choose directories; otherwise, <c>false</c>.</value>
376-
public bool CanChooseDirectories { get; set; }
445+
/// <value><c>true</c> if can choose directories; otherwise, <c>false</c> defaults to <c>false</c>.</value>
446+
public bool CanChooseDirectories {
447+
get => dirListView.canChooseDirectories;
448+
set {
449+
dirListView.canChooseDirectories = value;
450+
dirListView.Reload ();
451+
}
452+
}
377453

378454
/// <summary>
379455
/// Gets or sets a value indicating whether this <see cref="T:Terminal.Gui.OpenDialog"/> allows multiple selection.
380456
/// </summary>
381-
/// <value><c>true</c> if allows multiple selection; otherwise, <c>false</c>.</value>
382-
public bool AllowsMultipleSelection { get; set; }
457+
/// <value><c>true</c> if allows multiple selection; otherwise, <c>false</c>, defaults to false.</value>
458+
public bool AllowsMultipleSelection {
459+
get => dirListView.allowsMultipleSelection;
460+
set {
461+
dirListView.allowsMultipleSelection = value;
462+
dirListView.Reload ();
463+
}
464+
}
383465

384466
/// <summary>
385-
/// Gets the file paths selected
467+
/// Returns the selected files, or an empty list if nothing has been selected
386468
/// </summary>
387469
/// <value>The file paths.</value>
388-
public IReadOnlyList<ustring> FilePaths { get; }
470+
public IReadOnlyList<string> FilePaths {
471+
get => dirListView.FilePaths;
472+
}
389473
}
390474
}

0 commit comments

Comments
 (0)