Files
Terminal.Gui/Terminal.Gui/Views/FileDialogs/DefaultFileOperations.cs
Tig bc0634cf44 Fixed all modelusage bugs?
Replaced static `Application` references with instance-based `App`
context across the codebase. Updated calls to `Application.RequestStop()`
and `Application.Screen` to use `App?.RequestStop()` and `App?.Screen`
for better encapsulation and flexibility.

Refactored test infrastructure to align with the new context, including
reintroducing `FakeApplicationFactory` and `FakeApplicationLifecycle`
for testing purposes. Improved logging, error handling, and test
clarity by adding `logWriter` support and simplifying test setup.

Removed redundant or obsolete code, such as `NetSequences` and the old
`FakeApplicationFactory` implementation. Updated documentation to
reflect the new `IApplication.RequestStop()` usage.
2025-11-23 07:13:47 -07:00

176 lines
5.8 KiB
C#

#nullable disable
using System.IO.Abstractions;
namespace Terminal.Gui.Views;
/// <summary>Default file operation handlers using modal dialogs.</summary>
public class DefaultFileOperations : IFileOperations
{
/// <inheritdoc/>
public bool Delete (IEnumerable<IFileSystemInfo> toDelete)
{
// Default implementation does not allow deleting multiple files
if (toDelete.Count () != 1)
{
return false;
}
IFileSystemInfo d = toDelete.Single ();
string adjective = d.Name;
int result = MessageBox.Query (
string.Format (Strings.fdDeleteTitle, adjective),
string.Format (Strings.fdDeleteBody, adjective),
Strings.btnYes,
Strings.btnNo
);
try
{
if (result == 0)
{
if (d is IFileInfo)
{
d.Delete ();
}
else
{
((IDirectoryInfo)d).Delete (true);
}
return true;
}
}
catch (Exception ex)
{
MessageBox.ErrorQuery (Strings.fdDeleteFailedTitle, ex.Message, Strings.btnOk);
}
return false;
}
/// <inheritdoc/>
public IFileSystemInfo Rename (IFileSystem fileSystem, IFileSystemInfo toRename)
{
// Don't allow renaming C: or D: or / (on linux) etc
if (toRename is IDirectoryInfo dir && dir.Parent is null)
{
return null;
}
if (Prompt (Strings.fdRenameTitle, toRename.Name, out string newName))
{
if (!string.IsNullOrWhiteSpace (newName))
{
try
{
if (toRename is IFileInfo f)
{
IFileInfo newLocation =
fileSystem.FileInfo.New (
Path.Combine (
f.Directory.FullName,
newName
)
);
f.MoveTo (newLocation.FullName);
return newLocation;
}
else
{
var d = (IDirectoryInfo)toRename;
IDirectoryInfo newLocation =
fileSystem.DirectoryInfo.New (
Path.Combine (
d.Parent.FullName,
newName
)
);
d.MoveTo (newLocation.FullName);
return newLocation;
}
}
catch (Exception ex)
{
MessageBox.ErrorQuery (Strings.fdRenameFailedTitle, ex.Message, "Ok");
}
}
}
return null;
}
/// <inheritdoc/>
public IFileSystemInfo New (IFileSystem fileSystem, IDirectoryInfo inDirectory)
{
if (Prompt (Strings.fdNewTitle, "", out string named))
{
if (!string.IsNullOrWhiteSpace (named))
{
try
{
IDirectoryInfo newDir =
fileSystem.DirectoryInfo.New (
Path.Combine (inDirectory.FullName, named)
);
newDir.Create ();
return newDir;
}
catch (Exception ex)
{
MessageBox.ErrorQuery (Strings.fdNewFailed, ex.Message, "Ok");
}
}
}
return null;
}
private bool Prompt (string title, string defaultText, out string result)
{
var confirm = false;
var btnOk = new Button { IsDefault = true, Text = Strings.btnOk };
btnOk.Accepting += (s, e) =>
{
confirm = true;
(s as View)?.App?.RequestStop ();
// When Accepting is handled, set e.Handled to true to prevent further processing.
e.Handled = true;
};
var btnCancel = new Button { Text = Strings.btnCancel };
btnCancel.Accepting += (s, e) =>
{
confirm = false;
(s as View)?.App?.RequestStop ();
// When Accepting is handled, set e.Handled to true to prevent further processing.
e.Handled = true;
};
var lbl = new Label { Text = Strings.fdRenamePrompt };
var tf = new TextField { X = Pos.Right (lbl), Width = Dim.Fill (), Text = defaultText };
tf.SelectAll ();
var dlg = new Dialog { Title = title, Width = Dim.Percent (50), Height = 4 };
dlg.Add (lbl);
dlg.Add (tf);
// Add buttons last so tab order is friendly
// and TextField gets focus
dlg.AddButton (btnOk);
dlg.AddButton (btnCancel);
Application.Run (dlg);
dlg.Dispose ();
result = tf.Text;
return confirm;
}
}