mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
* Initial plan * Initial exploration - understanding TextField Caption and Title Co-authored-by: tig <585482+tig@users.noreply.github.com> * Remove TextField.Caption and use Title instead with hotkey support Co-authored-by: tig <585482+tig@users.noreply.github.com> * Add defensive check to ensure TitleTextFormatter.Text is set Co-authored-by: tig <585482+tig@users.noreply.github.com> * Final changes - all tests passing Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fixed bugs. * Add comprehensive tests for caption rendering with attributes validation Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix: Disable TextField hotkey functionality to prevent input interception TextField's Title is used as a caption/placeholder, not for hotkey navigation. Hotkey visual formatting (underline) is still rendered in the caption, but hotkey functionality is disabled to prevent keys like 'E' and 'F' from being intercepted when typing in the field. Updated test to expect "_Find" instead of "Find" to match resource change. Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix: Support Alt+key hotkey navigation while allowing normal typing Override AddKeyBindingsForHotKey to only bind Alt+key combinations (e.g., Alt+F for "_Find"), not the bare keys. This allows: - Alt+F to navigate to the TextField with Title="_Find" - Normal typing of 'F', 'E', etc. without interception Previously, both bare key and Alt+key were bound, causing typing issues. Now TextField properly supports hotkey navigation without interfering with text input. Co-authored-by: tig <585482+tig@users.noreply.github.com> * Changes before error encountered Co-authored-by: tig <585482+tig@users.noreply.github.com> * Refactor hotkey handling to support command context Refactored `RaiseHandlingHotKey` to accept an `ICommandContext? ctx` parameter, enabling context-aware hotkey handling. Updated `Command.HotKey` definitions across multiple classes (`View`, `CheckBox`, `Label`, `MenuBarv2`, `RadioGroup`, `TextField`) to utilize the new context parameter. Enhanced XML documentation for `RaiseHandlingHotKey` to clarify its usage and return values. Added a context-aware hotkey handler to `TextField` with additional logic for focus handling. Refactored attribute initialization and improved code readability in `TextField` by aligning parameters and removing unused `HotKeySpecifier` initialization. These changes improve flexibility, maintainability, and consistency across the codebase. * Remove TextField.Caption property; use Title with hotkey navigation support Co-authored-by: tig <585482+tig@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: tig <585482+tig@users.noreply.github.com> Co-authored-by: Tig <tig@users.noreply.github.com>
813 lines
30 KiB
C#
813 lines
30 KiB
C#
using System.IO.Abstractions.TestingHelpers;
|
|
using System.Runtime.InteropServices;
|
|
using UnitTests;
|
|
using Xunit.Abstractions;
|
|
|
|
namespace UnitTests.FileServicesTests;
|
|
|
|
public class FileDialogTests ()
|
|
{
|
|
[Theory]
|
|
[InlineData (true)]
|
|
[InlineData (false)]
|
|
[AutoInitShutdown]
|
|
public void CancelSelection (bool cancel)
|
|
{
|
|
FileDialog dlg = GetInitializedFileDialog ();
|
|
string openIn = Path.Combine (Environment.CurrentDirectory, "zz");
|
|
Directory.CreateDirectory (openIn);
|
|
dlg.Path = openIn + Path.DirectorySeparatorChar;
|
|
|
|
dlg.FilesSelected += (s, e) => e.Cancel = cancel;
|
|
|
|
//pressing enter will complete the current selection
|
|
// unless the event cancels the confirm
|
|
Application.RaiseKeyDownEvent (Key.Enter);
|
|
|
|
Assert.Equal (cancel, dlg.Canceled);
|
|
dlg.Dispose ();
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void DirectTyping_Allowed ()
|
|
{
|
|
FileDialog dlg = GetInitializedFileDialog ();
|
|
TextField tf = dlg.SubViews.OfType<TextField> ().First (t => t.HasFocus);
|
|
tf.ClearAllSelection ();
|
|
tf.CursorPosition = tf.Text.Length;
|
|
Assert.True (tf.HasFocus);
|
|
|
|
SendSlash ();
|
|
|
|
Assert.Equal (
|
|
new DirectoryInfo (Environment.CurrentDirectory + Path.DirectorySeparatorChar).FullName,
|
|
new DirectoryInfo (dlg.Path + Path.DirectorySeparatorChar).FullName
|
|
);
|
|
|
|
// continue typing the rest of the path
|
|
Send ("Bob");
|
|
Application.RaiseKeyDownEvent ('.');
|
|
Send ("csv");
|
|
|
|
Assert.True (dlg.Canceled);
|
|
|
|
Application.RaiseKeyDownEvent (Key.Enter);
|
|
Assert.False (dlg.Canceled);
|
|
Assert.Equal ("Bob.csv", Path.GetFileName (dlg.Path));
|
|
dlg.Dispose ();
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void DirectTyping_AutoComplete ()
|
|
{
|
|
FileDialog dlg = GetInitializedFileDialog ();
|
|
string openIn = Path.Combine (Environment.CurrentDirectory, "zz");
|
|
|
|
Directory.CreateDirectory (openIn);
|
|
|
|
string expectedDest = Path.Combine (openIn, "xx");
|
|
Directory.CreateDirectory (expectedDest);
|
|
|
|
dlg.Path = openIn + Path.DirectorySeparatorChar;
|
|
|
|
Send ("x");
|
|
|
|
// nothing selected yet
|
|
Assert.True (dlg.Canceled);
|
|
Assert.Equal ("x", Path.GetFileName (dlg.Path));
|
|
|
|
// complete auto typing
|
|
Application.RaiseKeyDownEvent ('\t');
|
|
|
|
// but do not close dialog
|
|
Assert.True (dlg.Canceled);
|
|
Assert.EndsWith ("xx" + Path.DirectorySeparatorChar, dlg.Path);
|
|
|
|
// press enter again to confirm the dialog
|
|
Application.RaiseKeyDownEvent (Key.Enter);
|
|
Assert.False (dlg.Canceled);
|
|
Assert.EndsWith ("xx" + Path.DirectorySeparatorChar, dlg.Path);
|
|
dlg.Dispose ();
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void DoNotConfirmSelectionWhenFindFocused ()
|
|
{
|
|
FileDialog dlg = GetInitializedFileDialog ();
|
|
string openIn = Path.Combine (Environment.CurrentDirectory, "zz");
|
|
Directory.CreateDirectory (openIn);
|
|
dlg.Path = openIn + Path.DirectorySeparatorChar;
|
|
|
|
var tf = dlg.SubViews.First (view => view.Id == "_tableViewContainer").SubViews.First (v => v.Id == "_tbFind") as TextField;
|
|
tf.SetFocus ();
|
|
|
|
Assert.IsType<TextField> (dlg.MostFocused);
|
|
Assert.Same (tf, dlg.MostFocused);
|
|
|
|
Assert.Equal ("_Find", tf.Title);
|
|
|
|
// Dialog has not yet been confirmed with a choice
|
|
Assert.True (dlg.Canceled);
|
|
|
|
//pressing enter while search focused should not confirm path
|
|
Application.RaiseKeyDownEvent (Key.Enter);
|
|
|
|
Assert.True (dlg.Canceled);
|
|
|
|
//// tabbing out of search
|
|
//Application.RaiseKeyDownEvent ('\t');
|
|
|
|
////should allow enter to confirm path
|
|
//Application.RaiseKeyDownEvent (Key.Enter);
|
|
|
|
//// Dialog has not yet been confirmed with a choice
|
|
//Assert.False (dlg.Canceled);
|
|
dlg.Dispose ();
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void DotDot_MovesToRoot_ThenPressBack ()
|
|
{
|
|
FileDialog dlg = GetDialog ();
|
|
dlg.OpenMode = OpenMode.Directory;
|
|
dlg.AllowsMultipleSelection = true;
|
|
var selected = false;
|
|
dlg.FilesSelected += (s, e) => { selected = true; };
|
|
|
|
AssertIsTheStartingDirectory (dlg.Path);
|
|
|
|
Assert.IsType<TextField> (dlg.MostFocused);
|
|
Application.RaiseKeyDownEvent (Key.CursorDown);
|
|
|
|
var tv = GetTableView(dlg);
|
|
tv.SetFocus ();
|
|
|
|
Assert.IsType<TableView> (dlg.MostFocused);
|
|
|
|
// ".." should be the first thing selected
|
|
// ".." should not mess with the displayed path
|
|
AssertIsTheStartingDirectory (dlg.Path);
|
|
|
|
// Accept navigation up a directory
|
|
Application.RaiseKeyDownEvent (Key.Enter);
|
|
|
|
AssertIsTheRootDirectory (dlg.Path);
|
|
|
|
Assert.True (dlg.Canceled);
|
|
Assert.False (selected);
|
|
|
|
Assert.IsType<TableView> (dlg.MostFocused);
|
|
|
|
// Now press Backspace (in table view)
|
|
Application.RaiseKeyDownEvent (Key.Backspace);
|
|
|
|
// Should move us back to the root
|
|
AssertIsTheStartingDirectory (dlg.Path);
|
|
|
|
Assert.True (dlg.Canceled);
|
|
Assert.False (selected);
|
|
dlg.Dispose ();
|
|
}
|
|
|
|
[Theory]
|
|
[AutoInitShutdown]
|
|
[InlineData (true)]
|
|
[InlineData (false)]
|
|
public void MultiSelectDirectory_CannotToggleDotDot (bool acceptWithEnter)
|
|
{
|
|
FileDialog dlg = GetDialog ();
|
|
dlg.OpenMode = OpenMode.Directory;
|
|
dlg.AllowsMultipleSelection = true;
|
|
IReadOnlyCollection<string> eventMultiSelected = null;
|
|
dlg.FilesSelected += (s, e) => { eventMultiSelected = e.Dialog.MultiSelected; };
|
|
|
|
|
|
var tv = GetTableView (dlg);
|
|
tv.SetFocus ();
|
|
|
|
Assert.IsType<TableView> (dlg.MostFocused);
|
|
|
|
// Try to toggle '..'
|
|
Application.RaiseKeyDownEvent (' ');
|
|
Application.RaiseKeyDownEvent (Key.CursorDown);
|
|
|
|
// Toggle subfolder
|
|
Application.RaiseKeyDownEvent (' ');
|
|
|
|
Assert.True (dlg.Canceled);
|
|
|
|
if (acceptWithEnter)
|
|
{
|
|
Application.RaiseKeyDownEvent (Key.Enter);
|
|
}
|
|
else
|
|
{
|
|
Application.RaiseKeyDownEvent ('O');
|
|
}
|
|
|
|
Assert.False (dlg.Canceled);
|
|
|
|
Assert.Multiple (
|
|
() =>
|
|
{
|
|
// Only the subfolder should be selected
|
|
Assert.Single (dlg.MultiSelected);
|
|
AssertIsTheSubfolder (dlg.Path);
|
|
AssertIsTheSubfolder (dlg.MultiSelected.Single ());
|
|
},
|
|
() =>
|
|
{
|
|
// Event should also agree with the final state
|
|
Assert.NotNull (eventMultiSelected);
|
|
Assert.Single (eventMultiSelected);
|
|
AssertIsTheSubfolder (eventMultiSelected.Single ());
|
|
}
|
|
);
|
|
dlg.Dispose ();
|
|
}
|
|
|
|
[Theory]
|
|
[AutoInitShutdown]
|
|
[InlineData (true)]
|
|
[InlineData (false)]
|
|
public void MultiSelectDirectory_CanToggleThenAccept (bool acceptWithEnter)
|
|
{
|
|
FileDialog dlg = GetDialog ();
|
|
dlg.OpenMode = OpenMode.Directory;
|
|
dlg.AllowsMultipleSelection = true;
|
|
IReadOnlyCollection<string> eventMultiSelected = null;
|
|
dlg.FilesSelected += (s, e) => { eventMultiSelected = e.Dialog.MultiSelected; };
|
|
|
|
var tv = GetTableView (dlg);
|
|
tv.SetFocus ();
|
|
|
|
Assert.IsType<TableView> (dlg.MostFocused);
|
|
|
|
// Move selection to subfolder
|
|
Application.RaiseKeyDownEvent (Key.CursorDown);
|
|
|
|
// Toggle subfolder
|
|
Application.RaiseKeyDownEvent (' ');
|
|
|
|
Assert.True (dlg.Canceled);
|
|
|
|
if (acceptWithEnter)
|
|
{
|
|
Application.RaiseKeyDownEvent (Key.Enter);
|
|
}
|
|
else
|
|
{
|
|
Application.RaiseKeyDownEvent (Key.O.WithAlt);
|
|
}
|
|
|
|
Assert.False (dlg.Canceled);
|
|
|
|
Assert.Multiple (
|
|
() =>
|
|
{
|
|
// Only the subfolder should be selected
|
|
Assert.Single (dlg.MultiSelected);
|
|
AssertIsTheSubfolder (dlg.Path);
|
|
AssertIsTheSubfolder (dlg.MultiSelected.Single ());
|
|
},
|
|
() =>
|
|
{
|
|
// Event should also agree with the final state
|
|
Assert.NotNull (eventMultiSelected);
|
|
Assert.Single (eventMultiSelected);
|
|
AssertIsTheSubfolder (eventMultiSelected.Single ());
|
|
}
|
|
);
|
|
dlg.Dispose ();
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void MultiSelectDirectory_EnterOpensFolder ()
|
|
{
|
|
FileDialog dlg = GetDialog ();
|
|
dlg.OpenMode = OpenMode.Directory;
|
|
dlg.AllowsMultipleSelection = true;
|
|
IReadOnlyCollection<string> eventMultiSelected = null;
|
|
dlg.FilesSelected += (s, e) => { eventMultiSelected = e.Dialog.MultiSelected; };
|
|
|
|
var tv = GetTableView (dlg);
|
|
tv.SetFocus ();
|
|
|
|
Assert.IsType<TableView> (dlg.MostFocused);
|
|
|
|
// Move selection to subfolder
|
|
Application.RaiseKeyDownEvent (Key.CursorDown);
|
|
|
|
Application.RaiseKeyDownEvent (Key.Enter);
|
|
|
|
// Path should update to the newly opened folder
|
|
AssertIsTheSubfolder (dlg.Path);
|
|
|
|
// No selection will have been confirmed
|
|
Assert.True (dlg.Canceled);
|
|
Assert.Empty (dlg.MultiSelected);
|
|
Assert.Null (eventMultiSelected);
|
|
dlg.Dispose ();
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void OnLoad_TextBoxIsFocused ()
|
|
{
|
|
FileDialog dlg = GetInitializedFileDialog ();
|
|
|
|
View tf = dlg.SubViews.FirstOrDefault (t => t.HasFocus);
|
|
Assert.NotNull (tf);
|
|
Assert.IsType<TextField> (tf);
|
|
dlg.Dispose ();
|
|
}
|
|
|
|
[Theory]
|
|
[AutoInitShutdown]
|
|
[InlineData (true, true)]
|
|
[InlineData (true, false)]
|
|
[InlineData (false, true)]
|
|
[InlineData (false, false)]
|
|
public void PickDirectory_ArrowNavigation (bool openModeMixed, bool multiple)
|
|
{
|
|
FileDialog dlg = GetDialog ();
|
|
dlg.OpenMode = openModeMixed ? OpenMode.Mixed : OpenMode.Directory;
|
|
dlg.AllowsMultipleSelection = multiple;
|
|
|
|
var tv = GetTableView (dlg);
|
|
tv.SetFocus ();
|
|
|
|
Assert.IsType<TableView> (dlg.MostFocused);
|
|
|
|
// Should be selecting ..
|
|
Application.RaiseKeyDownEvent (Key.CursorDown);
|
|
|
|
// Down to the directory
|
|
Assert.True (dlg.Canceled);
|
|
|
|
// Alt+O to open (enter would just navigate into the child dir)
|
|
Application.RaiseKeyDownEvent (Key.O.WithAlt);
|
|
Assert.False (dlg.Canceled);
|
|
|
|
AssertIsTheSubfolder (dlg.Path);
|
|
dlg.Dispose ();
|
|
}
|
|
|
|
[Theory]
|
|
[AutoInitShutdown]
|
|
[InlineData (true, true)]
|
|
[InlineData (true, false)]
|
|
[InlineData (false, true)]
|
|
[InlineData (false, false)]
|
|
public void PickDirectory_DirectTyping (bool openModeMixed, bool multiple)
|
|
{
|
|
FileDialog dlg = GetDialog ();
|
|
dlg.OpenMode = openModeMixed ? OpenMode.Mixed : OpenMode.Directory;
|
|
dlg.AllowsMultipleSelection = multiple;
|
|
|
|
// whe first opening the text field will have select all on
|
|
// so to add to current path user must press End or right
|
|
Application.RaiseKeyDownEvent (Key.CursorLeft);
|
|
Application.RaiseKeyDownEvent (Key.CursorRight);
|
|
|
|
Send ("subfolder");
|
|
|
|
// Dialog has not yet been confirmed with a choice
|
|
Assert.True (dlg.Canceled);
|
|
|
|
// Now it has
|
|
Application.RaiseKeyDownEvent (Key.Enter);
|
|
Assert.False (dlg.Canceled);
|
|
AssertIsTheSubfolder (dlg.Path);
|
|
dlg.Dispose ();
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData (".csv", null, false)]
|
|
[InlineData (".csv", "", false)]
|
|
[InlineData (".csv", "c:\\MyFile.csv", true)]
|
|
[InlineData (".csv", "c:\\MyFile.CSV", true)]
|
|
[InlineData (".csv", "c:\\MyFile.csv.bak", false)]
|
|
public void TestAllowedType_Basic (string allowed, string candidate, bool expected)
|
|
{
|
|
Assert.Equal (expected, new AllowedType ("Test", allowed).IsAllowed (candidate));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData (".Designer.cs", "c:\\MyView.Designer.cs", true)]
|
|
[InlineData (".Designer.cs", "c:\\temp/MyView.Designer.cs", true)]
|
|
[InlineData (".Designer.cs", "MyView.Designer.cs", true)]
|
|
[InlineData (".Designer.cs", "c:\\MyView.DESIGNER.CS", true)]
|
|
[InlineData (".Designer.cs", "MyView.cs", false)]
|
|
public void TestAllowedType_DoubleBarreled (string allowed, string candidate, bool expected)
|
|
{
|
|
Assert.Equal (expected, new AllowedType ("Test", allowed).IsAllowed (candidate));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData ("Dockerfile", "c:\\temp\\Dockerfile", true)]
|
|
[InlineData ("Dockerfile", "Dockerfile", true)]
|
|
[InlineData ("Dockerfile", "someimg.Dockerfile", true)]
|
|
public void TestAllowedType_SpecificFile (string allowed, string candidate, bool expected)
|
|
{
|
|
Assert.Equal (expected, new AllowedType ("Test", allowed).IsAllowed (candidate));
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void TestDirectoryContents_Linux ()
|
|
{
|
|
if (IsWindows ())
|
|
{
|
|
return;
|
|
}
|
|
|
|
FileDialog fd = GetLinuxDialog ();
|
|
fd.Title = string.Empty;
|
|
|
|
fd.Style.Culture = new ("en-US");
|
|
|
|
fd.Draw ();
|
|
|
|
/*
|
|
*
|
|
*
|
|
┌─────────────────────────────────────────────────────────────────────────┐
|
|
│/demo/ │
|
|
│⟦▲⟧ │
|
|
│┌────────────┬──────────┬──────────────────────────────┬────────────────┐│
|
|
││Filename (▲)│Size │Modified │Type ││
|
|
│├────────────┼──────────┼──────────────────────────────┼────────────────┤│
|
|
││.. │ │ │<Directory> ││
|
|
││/subfolder │ │2002-01-01T22:42:10 │<Directory> ││
|
|
││image.gif │4.00 B │2002-01-01T22:42:10 │.gif ││
|
|
││jQuery.js │7.00 B │2001-01-01T11:44:42 │.js ││
|
|
│ │
|
|
│ │
|
|
│ │
|
|
│⟦ ►► ⟧ Enter Search ⟦► OK ◄⟧ ⟦ Cancel ⟧ │
|
|
└─────────────────────────────────────────────────────────────────────────┘
|
|
|
|
*
|
|
*/
|
|
|
|
var path = fd.SubViews.OfType<TextField> ().ElementAt (0);
|
|
Assert.Equal ("/demo/", path.Text);
|
|
|
|
var tv = GetTableView (fd);
|
|
|
|
// Asserting the headers
|
|
Assert.Equal ("Filename (▲)", tv.Table.ColumnNames.ElementAt (0));
|
|
Assert.Equal ("Size", tv.Table.ColumnNames.ElementAt (1));
|
|
Assert.Equal ("Modified", tv.Table.ColumnNames.ElementAt (2));
|
|
Assert.Equal ("Type", tv.Table.ColumnNames.ElementAt (3));
|
|
|
|
// Asserting the table contents
|
|
Assert.Equal ("..", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [0, 0]));
|
|
Assert.Equal ("/subfolder", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [1, 0]));
|
|
Assert.Equal ("image.gif", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [2, 0]));
|
|
Assert.Equal ("jQuery.js", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [3, 0]));
|
|
|
|
Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [0, 1]));
|
|
Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [1, 1]));
|
|
Assert.Equal ("4.00 B", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [2, 1]));
|
|
Assert.Equal ("7.00 B", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [3, 1]));
|
|
|
|
Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [0, 2]));
|
|
Assert.Equal ("2002-01-01T22:42:10", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [1, 2]));
|
|
Assert.Equal ("2002-01-01T22:42:10", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [2, 2]));
|
|
Assert.Equal ("2001-01-01T11:44:42", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [3, 2]));
|
|
|
|
Assert.Equal ("<Directory>", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [0, 3]));
|
|
Assert.Equal ("<Directory>", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [1, 3]));
|
|
Assert.Equal (".gif", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [2, 3]));
|
|
Assert.Equal (".js", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [3, 3]));
|
|
|
|
fd.Dispose ();
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void TestDirectoryContents_Windows ()
|
|
{
|
|
if (!IsWindows ())
|
|
{
|
|
return;
|
|
}
|
|
|
|
FileDialog fd = GetWindowsDialog ();
|
|
fd.Title = string.Empty;
|
|
|
|
fd.Style.Culture = new ("en-US");
|
|
|
|
fd.Draw ();
|
|
|
|
/*
|
|
*
|
|
*
|
|
┌─────────────────────────────────────────────────────────────────────────┐
|
|
│c:\demo\ │
|
|
│⟦▲⟧ │
|
|
│┌────────────┬──────────┬──────────────────────────────┬────────────────┐│
|
|
││Filename (▲)│Size │Modified │Type ││
|
|
│├────────────┼──────────┼──────────────────────────────┼────────────────┤│
|
|
││.. │ │ │<Directory> ││
|
|
││\subfolder │ │2002-01-01T22:42:10 │<Directory> ││
|
|
││image.gif │4.00 B │2002-01-01T22:42:10 │.gif ││
|
|
││jQuery.js │7.00 B │2001-01-01T11:44:42 │.js ││
|
|
││mybinary.exe│7.00 B │2001-01-01T11:44:42 │.exe ││
|
|
│ │
|
|
│ │
|
|
│⟦ ►► ⟧ Enter Search ⟦► OK ◄⟧ ⟦ Cancel ⟧ │
|
|
└─────────────────────────────────────────────────────────────────────────┘
|
|
|
|
*
|
|
*/
|
|
|
|
var path = fd.SubViews.OfType<TextField> ().ElementAt (0);
|
|
Assert.Equal ("c:\\demo\\",path.Text);
|
|
|
|
var tv = GetTableView (fd);
|
|
|
|
// Asserting the headers
|
|
Assert.Equal ("Filename (▲)", tv.Table.ColumnNames.ElementAt (0));
|
|
Assert.Equal ("Size", tv.Table.ColumnNames.ElementAt (1));
|
|
Assert.Equal ("Modified", tv.Table.ColumnNames.ElementAt (2));
|
|
Assert.Equal ("Type", tv.Table.ColumnNames.ElementAt (3));
|
|
|
|
// Asserting the table contents
|
|
Assert.Equal ("..", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [0, 0]));
|
|
Assert.Equal (@"\subfolder", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [1, 0]));
|
|
Assert.Equal ("image.gif", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [2, 0]));
|
|
Assert.Equal ("jQuery.js", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [3, 0]));
|
|
Assert.Equal ("mybinary.exe", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [4, 0]));
|
|
|
|
Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [0, 1]));
|
|
Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [1, 1]));
|
|
Assert.Equal ("4.00 B", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [2, 1]));
|
|
Assert.Equal ("7.00 B", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [3, 1]));
|
|
Assert.Equal ("7.00 B", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [4, 1]));
|
|
|
|
Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [0, 2]));
|
|
Assert.Equal ("2002-01-01T22:42:10", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [1, 2]));
|
|
Assert.Equal ("2002-01-01T22:42:10", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [2, 2]));
|
|
Assert.Equal ("2001-01-01T11:44:42", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [3, 2]));
|
|
Assert.Equal ("2001-01-01T11:44:42", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [4, 2]));
|
|
|
|
Assert.Equal ("<Directory>", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [0, 3]));
|
|
Assert.Equal ("<Directory>", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [1, 3]));
|
|
Assert.Equal (".gif", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [2, 3]));
|
|
Assert.Equal (".js", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [3, 3]));
|
|
Assert.Equal (".exe", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [4, 3]));
|
|
|
|
fd.Dispose ();
|
|
}
|
|
|
|
private void AssertIsTheRootDirectory (string path)
|
|
{
|
|
if (IsWindows ())
|
|
{
|
|
Assert.Equal (@"c:\", path);
|
|
}
|
|
else
|
|
{
|
|
Assert.Equal ("/", path);
|
|
}
|
|
}
|
|
|
|
private void AssertIsTheStartingDirectory (string path)
|
|
{
|
|
if (IsWindows ())
|
|
{
|
|
Assert.Equal (@"c:\demo\", path);
|
|
}
|
|
else
|
|
{
|
|
Assert.Equal ("/demo/", path);
|
|
}
|
|
}
|
|
|
|
private void AssertIsTheSubfolder (string path)
|
|
{
|
|
if (IsWindows ())
|
|
{
|
|
Assert.Equal (@"c:\demo\subfolder", path);
|
|
}
|
|
else
|
|
{
|
|
Assert.Equal ("/demo/subfolder", path);
|
|
}
|
|
}
|
|
|
|
private void Begin (FileDialog dlg)
|
|
{
|
|
dlg.BeginInit ();
|
|
dlg.EndInit ();
|
|
Application.Begin (dlg);
|
|
}
|
|
|
|
private FileDialog GetDialog () { return IsWindows () ? GetWindowsDialog () : GetLinuxDialog (); }
|
|
|
|
private FileDialog GetInitializedFileDialog ()
|
|
{
|
|
|
|
Window.DefaultBorderStyle = LineStyle.Single;
|
|
Dialog.DefaultButtonAlignment = Alignment.Center;
|
|
Dialog.DefaultBorderStyle = LineStyle.Single;
|
|
Dialog.DefaultShadow = ShadowStyle.None;
|
|
Button.DefaultShadow = ShadowStyle.None;
|
|
|
|
var dlg = new FileDialog ();
|
|
Begin (dlg);
|
|
|
|
return dlg;
|
|
}
|
|
|
|
private FileDialog GetLinuxDialog ()
|
|
{
|
|
Window.DefaultBorderStyle = LineStyle.Single;
|
|
Dialog.DefaultButtonAlignment = Alignment.Center;
|
|
Dialog.DefaultBorderStyle = LineStyle.Single;
|
|
Dialog.DefaultShadow = ShadowStyle.None;
|
|
Button.DefaultShadow = ShadowStyle.None;
|
|
|
|
// Arrange
|
|
var fileSystem = new MockFileSystem (new Dictionary<string, MockFileData> (), "/");
|
|
fileSystem.MockTime (() => new (2010, 01, 01, 11, 12, 43));
|
|
|
|
fileSystem.AddFile (
|
|
@"/myfile.txt",
|
|
new ("Testing is meh.") { LastWriteTime = new DateTime (2001, 01, 01, 11, 12, 11) }
|
|
);
|
|
|
|
fileSystem.AddFile (
|
|
@"/demo/jQuery.js",
|
|
new ("some js") { LastWriteTime = new DateTime (2001, 01, 01, 11, 44, 42) }
|
|
);
|
|
|
|
fileSystem.AddFile (
|
|
@"/demo/image.gif",
|
|
new (new byte [] { 0x12, 0x34, 0x56, 0xd2 })
|
|
{
|
|
LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10)
|
|
}
|
|
);
|
|
|
|
var m = (MockDirectoryInfo)fileSystem.DirectoryInfo.New (@"/demo/subfolder");
|
|
m.Create ();
|
|
m.LastWriteTime = new (2002, 01, 01, 22, 42, 10);
|
|
|
|
fileSystem.AddFile (
|
|
@"/demo/subfolder/image2.gif",
|
|
new (new byte [] { 0x12, 0x34, 0x56, 0xd2 })
|
|
{
|
|
LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10)
|
|
}
|
|
);
|
|
|
|
var fd = new FileDialog (fileSystem) { Height = 15, Width = 75 };
|
|
fd.Path = @"/demo/";
|
|
Begin (fd);
|
|
|
|
return fd;
|
|
}
|
|
|
|
private FileDialog GetWindowsDialog ()
|
|
{
|
|
// Override CM
|
|
Window.DefaultBorderStyle = LineStyle.Single;
|
|
Dialog.DefaultButtonAlignment = Alignment.Center;
|
|
Dialog.DefaultBorderStyle = LineStyle.Single;
|
|
Dialog.DefaultShadow = ShadowStyle.None;
|
|
Button.DefaultShadow = ShadowStyle.None;
|
|
|
|
// Arrange
|
|
var fileSystem = new MockFileSystem (new Dictionary<string, MockFileData> (), @"c:\");
|
|
fileSystem.MockTime (() => new (2010, 01, 01, 11, 12, 43));
|
|
|
|
fileSystem.AddFile (
|
|
@"c:\myfile.txt",
|
|
new ("Testing is meh.") { LastWriteTime = new DateTime (2001, 01, 01, 11, 12, 11) }
|
|
);
|
|
|
|
fileSystem.AddFile (
|
|
@"c:\demo\jQuery.js",
|
|
new ("some js") { LastWriteTime = new DateTime (2001, 01, 01, 11, 44, 42) }
|
|
);
|
|
|
|
fileSystem.AddFile (
|
|
@"c:\demo\mybinary.exe",
|
|
new ("some js") { LastWriteTime = new DateTime (2001, 01, 01, 11, 44, 42) }
|
|
);
|
|
|
|
fileSystem.AddFile (
|
|
@"c:\demo\image.gif",
|
|
new (new byte [] { 0x12, 0x34, 0x56, 0xd2 })
|
|
{
|
|
LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10)
|
|
}
|
|
);
|
|
|
|
var m = (MockDirectoryInfo)fileSystem.DirectoryInfo.New (@"c:\demo\subfolder");
|
|
m.Create ();
|
|
m.LastWriteTime = new (2002, 01, 01, 22, 42, 10);
|
|
|
|
fileSystem.AddFile (
|
|
@"c:\demo\subfolder\image2.gif",
|
|
new (new byte [] { 0x12, 0x34, 0x56, 0xd2 })
|
|
{
|
|
LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10)
|
|
}
|
|
);
|
|
|
|
var fd = new FileDialog (fileSystem) { Height = 15, Width = 75 };
|
|
fd.Path = @"c:\demo\";
|
|
Begin (fd);
|
|
|
|
return fd;
|
|
}
|
|
/*
|
|
[Fact, AutoInitShutdown]
|
|
public void Autocomplete_NoSuggestion_WhenTextMatchesExactly ()
|
|
{
|
|
var tb = new TextFieldWithAppendAutocomplete ();
|
|
ForceFocus (tb);
|
|
|
|
tb.Text = "/bob/fish";
|
|
tb.CursorPosition = tb.Text.Length;
|
|
tb.GenerateSuggestions (null, "fish", "fishes");
|
|
|
|
// should not report success for autocompletion because we already have that exact
|
|
// string
|
|
Assert.False (tb.AcceptSelectionIfAny ());
|
|
}
|
|
|
|
[Fact, AutoInitShutdown]
|
|
public void Autocomplete_AcceptSuggstion ()
|
|
{
|
|
var tb = new TextFieldWithAppendAutocomplete ();
|
|
ForceFocus (tb);
|
|
|
|
tb.Text = @"/bob/fi";
|
|
tb.CursorPosition = tb.Text.Length;
|
|
tb.GenerateSuggestions (null, "fish", "fishes");
|
|
|
|
Assert.True (tb.AcceptSelectionIfAny ());
|
|
Assert.Equal (@"/bob/fish", tb.Text);
|
|
}*/
|
|
|
|
private bool IsWindows () { return RuntimeInformation.IsOSPlatform (OSPlatform.Windows); }
|
|
|
|
private void Send (string chars)
|
|
{
|
|
foreach (char ch in chars)
|
|
{
|
|
Application.RaiseKeyDownEvent (ch);
|
|
}
|
|
}
|
|
|
|
private void SendSlash ()
|
|
{
|
|
if (Path.DirectorySeparatorChar == '/')
|
|
{
|
|
Application.RaiseKeyDownEvent ('/');
|
|
}
|
|
else
|
|
{
|
|
Application.RaiseKeyDownEvent ('\\');
|
|
}
|
|
}
|
|
|
|
private TableView GetTableView (FileDialog dlg)
|
|
{
|
|
// The table view is in the _tableViewContainer which is a direct subview of the dialog
|
|
// We need to search through all subviews recursively
|
|
TableView FindTableView (View view)
|
|
{
|
|
if (view is TableView tv)
|
|
{
|
|
return tv;
|
|
}
|
|
|
|
foreach (View subview in view.SubViews)
|
|
{
|
|
TableView result = FindTableView (subview);
|
|
if (result != null)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
return FindTableView (dlg);
|
|
}
|
|
|
|
}
|