mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 07:47:54 +01:00
* Pulled from v2_release * Refactor migration guide for Terminal.Gui v2 Restructured and expanded the migration guide to provide a comprehensive resource for transitioning from Terminal.Gui v1 to v2. Key updates include: - Added a Table of Contents for easier navigation. - Summarized major architectural changes in v2, including the instance-based application model, IRunnable architecture, and 24-bit TrueColor support. - Updated examples to reflect new patterns, such as initializers replacing constructors and explicit disposal using `IDisposable`. - Documented changes to the layout system, including the removal of `Absolute`/`Computed` styles and the introduction of `Viewport`. - Standardized event patterns to use `object sender, EventArgs args`. - Detailed updates to the Keyboard, Mouse, and Navigation APIs, including configurable key bindings and viewport-relative mouse coordinates. - Replaced legacy components like `ScrollView` and `ContextMenu` with built-in scrolling and `PopoverMenu`. - Clarified disposal rules and introduced best practices for resource management. - Provided a complete migration example and a summary of breaking changes. This update aims to simplify the migration process by addressing breaking changes, introducing new features, and aligning with modern .NET conventions. * Refactor to use Application.Instance for lifecycle management Replaced all occurrences of `ApplicationImpl.Instance` with the new `Application.Instance` property across the codebase to align with the updated application lifecycle model. Encapsulated the `ApplicationImpl` class by making it `internal`, ensuring it is no longer directly accessible outside its assembly. Introduced the `[Obsolete]` `Application.Instance` property as a backward-compatible singleton for the legacy static `Application` model, while encouraging the use of `Application.Create()` for new code. Updated `MessageBox` methods to use `Application.Instance` for consistent modal dialog management. Improved documentation to reflect these changes and emphasize the transition to the instance-based application model. Performed code cleanup in multiple classes to ensure consistency and maintainability. These changes maintain backward compatibility while preparing the codebase for the eventual removal of the legacy `ApplicationImpl` class. * Fix doc bug * - Removed obsolete `.cd` class diagram files. - Introduced `IRunnable` interface for decoupling component execution. - Added fluent API for running dialogs and retrieving results. - Enhanced `View` with `App` and `Driver` properties for better decoupling. - Improved testability with support for mock and real applications. - Implemented `IDisposable` for proper resource cleanup. - Replaced `RunnableSessionStack` with `SessionStack` for session management. - Updated driver architecture to align with the new model. - Scoped `IKeyboard` to application contexts for modularity. - Updated documentation with migration strategies and best practices. These changes modernize the library, improve maintainability, and align with current development practices.
283 lines
11 KiB
C#
283 lines
11 KiB
C#
using System.IO.Abstractions;
|
|
|
|
namespace UICatalog.Scenarios;
|
|
|
|
[ScenarioMetadata ("FileDialog", "Demonstrates how to the FileDialog class")]
|
|
[ScenarioCategory ("Dialogs")]
|
|
[ScenarioCategory ("Files and IO")]
|
|
public class FileDialogExamples : Scenario
|
|
{
|
|
private CheckBox _cbAllowMultipleSelection;
|
|
private CheckBox _cbAlwaysTableShowHeaders;
|
|
private CheckBox _cbCaseSensitive;
|
|
private CheckBox _cbDrivesOnlyInTree;
|
|
private CheckBox _cbPreserveFilenameOnDirectoryChanges;
|
|
private CheckBox _cbFlipButtonOrder;
|
|
private CheckBox _cbMustExist;
|
|
private CheckBox _cbShowTreeBranchLines;
|
|
private CheckBox _cbUseColors;
|
|
private OptionSelector _osAllowedTypes;
|
|
private OptionSelector _osCaption;
|
|
private OptionSelector _osIcons;
|
|
private OptionSelector _osOpenMode;
|
|
private TextField _tbCancelButton;
|
|
private TextField _tbOkButton;
|
|
|
|
public override void Main ()
|
|
{
|
|
Application.Init ();
|
|
var y = 0;
|
|
var x = 1;
|
|
var win = new Window { Title = GetQuitKeyAndName () };
|
|
|
|
_cbMustExist = new () { CheckedState = CheckState.Checked, Y = y++, X = x, Text = "Must E_xist" };
|
|
win.Add (_cbMustExist);
|
|
|
|
_cbUseColors = new ()
|
|
{ CheckedState = FileDialogStyle.DefaultUseColors ? CheckState.Checked : CheckState.UnChecked, Y = y++, X = x, Text = "_Use Colors" };
|
|
win.Add (_cbUseColors);
|
|
|
|
_cbCaseSensitive = new () { CheckedState = CheckState.UnChecked, Y = y++, X = x, Text = "_Case Sensitive Search" };
|
|
win.Add (_cbCaseSensitive);
|
|
|
|
_cbAllowMultipleSelection = new () { CheckedState = CheckState.UnChecked, Y = y++, X = x, Text = "_Multiple" };
|
|
win.Add (_cbAllowMultipleSelection);
|
|
|
|
_cbShowTreeBranchLines = new () { CheckedState = CheckState.Checked, Y = y++, X = x, Text = "Tree Branch _Lines" };
|
|
win.Add (_cbShowTreeBranchLines);
|
|
|
|
_cbAlwaysTableShowHeaders = new () { CheckedState = CheckState.Checked, Y = y++, X = x, Text = "Always Show _Headers" };
|
|
win.Add (_cbAlwaysTableShowHeaders);
|
|
|
|
_cbDrivesOnlyInTree = new () { CheckedState = CheckState.UnChecked, Y = y++, X = x, Text = "Only Show _Drives" };
|
|
win.Add (_cbDrivesOnlyInTree);
|
|
|
|
_cbPreserveFilenameOnDirectoryChanges = new () { CheckedState = CheckState.UnChecked, Y = y++, X = x, Text = "Preserve Filename" };
|
|
win.Add (_cbPreserveFilenameOnDirectoryChanges);
|
|
|
|
y = 0;
|
|
x = 24;
|
|
|
|
win.Add (
|
|
new Line { Orientation = Orientation.Vertical, X = x++, Y = 1, Height = 4 }
|
|
);
|
|
win.Add (new Label { X = x++, Y = y++, Text = "Caption" });
|
|
|
|
_osCaption = new () { X = x, Y = y };
|
|
_osCaption.Labels = ["_Ok", "O_pen", "_Save"];
|
|
win.Add (_osCaption);
|
|
|
|
y = 0;
|
|
x = 34;
|
|
|
|
win.Add (
|
|
new Line { Orientation = Orientation.Vertical, X = x++, Y = 1, Height = 4 }
|
|
);
|
|
win.Add (new Label { X = x++, Y = y++, Text = "OpenMode" });
|
|
|
|
_osOpenMode = new () { X = x, Y = y };
|
|
_osOpenMode.Labels = ["_File", "D_irectory", "_Mixed"];
|
|
win.Add (_osOpenMode);
|
|
|
|
y = 0;
|
|
x = 48;
|
|
|
|
win.Add (
|
|
new Line { Orientation = Orientation.Vertical, X = x++, Y = 1, Height = 4 }
|
|
);
|
|
win.Add (new Label { X = x++, Y = y++, Text = "Icons" });
|
|
|
|
_osIcons = new () { X = x, Y = y };
|
|
_osIcons.Labels = ["_None", "_Unicode", "Nerd_*"];
|
|
win.Add (_osIcons);
|
|
|
|
win.Add (new Label { Y = Pos.AnchorEnd (2), Text = "* Requires installing Nerd fonts" });
|
|
win.Add (new Label { Y = Pos.AnchorEnd (1), Text = " (see: https://github.com/devblackops/Terminal-Icons)" });
|
|
|
|
y = 5;
|
|
x = 24;
|
|
|
|
win.Add (
|
|
new Line { Orientation = Orientation.Vertical, X = x++, Y = y + 1, Height = 4 }
|
|
);
|
|
win.Add (new Label { X = x++, Y = y++, Text = "Allowed" });
|
|
|
|
_osAllowedTypes = new () { X = x, Y = y };
|
|
_osAllowedTypes.Labels = ["An_y", "Cs_v (Recommended)", "Csv (S_trict)"];
|
|
win.Add (_osAllowedTypes);
|
|
|
|
y = 5;
|
|
x = 45;
|
|
|
|
win.Add (
|
|
new Line { Orientation = Orientation.Vertical, X = x++, Y = y + 1, Height = 4 }
|
|
);
|
|
win.Add (new Label { X = x++, Y = y++, Text = "Buttons" });
|
|
|
|
win.Add (new Label { X = x, Y = y++, Text = "O_k Text:" });
|
|
_tbOkButton = new () { X = x, Y = y++, Width = 12 };
|
|
win.Add (_tbOkButton);
|
|
win.Add (new Label { X = x, Y = y++, Text = "_Cancel Text:" });
|
|
_tbCancelButton = new () { X = x, Y = y++, Width = 12 };
|
|
win.Add (_tbCancelButton);
|
|
_cbFlipButtonOrder = new () { X = x, Y = y++, Text = "Flip Ord_er" };
|
|
win.Add (_cbFlipButtonOrder);
|
|
|
|
var btn = new Button { X = 1, Y = 9, IsDefault = true, Text = "Run Dialog" };
|
|
|
|
win.Accepting += (s, e) =>
|
|
{
|
|
try
|
|
{
|
|
CreateDialog ();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.ErrorQuery (Application.Instance, "Error", ex.ToString (), "_Ok");
|
|
}
|
|
finally
|
|
{
|
|
e.Handled = true;
|
|
}
|
|
};
|
|
win.Add (btn);
|
|
|
|
Application.Run (win);
|
|
win.Dispose ();
|
|
Application.Shutdown ();
|
|
}
|
|
|
|
private void ConfirmOverwrite (object sender, FilesSelectedEventArgs e)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace (e.Dialog.Path))
|
|
{
|
|
if (File.Exists (e.Dialog.Path))
|
|
{
|
|
int? result = MessageBox.Query (Application.Instance, "Overwrite?", "File already exists", "_Yes", "_No");
|
|
e.Cancel = result == 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CreateDialog ()
|
|
{
|
|
if (_osOpenMode.Value is { })
|
|
{
|
|
var fd = new FileDialog
|
|
{
|
|
OpenMode = Enum.Parse<OpenMode> (
|
|
_osOpenMode.Labels
|
|
.Select (l => TextFormatter.FindHotKey (l, _osOpenMode.HotKeySpecifier, out int hotPos, out Key _)
|
|
|
|
// Remove the hotkey specifier at the found position
|
|
? TextFormatter.RemoveHotKeySpecifier (l, hotPos, _osOpenMode.HotKeySpecifier)
|
|
|
|
// No hotkey found, return the label as is
|
|
: l)
|
|
.ToArray () [_osOpenMode.Value.Value]
|
|
),
|
|
MustExist = _cbMustExist.CheckedState == CheckState.Checked,
|
|
AllowsMultipleSelection = _cbAllowMultipleSelection.CheckedState == CheckState.Checked
|
|
};
|
|
|
|
fd.Style.OkButtonText =
|
|
_osCaption.Labels.Select (l => TextFormatter.RemoveHotKeySpecifier (l, 0, _osCaption.HotKeySpecifier)).ToArray ()
|
|
[_osCaption.Value!.Value];
|
|
|
|
// If Save style dialog then give them an overwrite prompt
|
|
if (_osCaption.Value == 2)
|
|
{
|
|
fd.FilesSelected += ConfirmOverwrite;
|
|
}
|
|
|
|
fd.Style.IconProvider.UseUnicodeCharacters = _osIcons.Value == 1;
|
|
fd.Style.IconProvider.UseNerdIcons = _osIcons.Value == 2;
|
|
|
|
if (_cbCaseSensitive.CheckedState == CheckState.Checked)
|
|
{
|
|
fd.SearchMatcher = new CaseSensitiveSearchMatcher ();
|
|
}
|
|
|
|
fd.Style.UseColors = _cbUseColors.CheckedState == CheckState.Checked;
|
|
|
|
fd.Style.TreeStyle.ShowBranchLines = _cbShowTreeBranchLines.CheckedState == CheckState.Checked;
|
|
fd.Style.TableStyle.AlwaysShowHeaders = _cbAlwaysTableShowHeaders.CheckedState == CheckState.Checked;
|
|
|
|
IDirectoryInfoFactory dirInfoFactory = new FileSystem ().DirectoryInfo;
|
|
|
|
if (_cbDrivesOnlyInTree.CheckedState == CheckState.Checked)
|
|
{
|
|
fd.Style.TreeRootGetter = () => { return Environment.GetLogicalDrives ().ToDictionary (dirInfoFactory.New, k => k); };
|
|
}
|
|
|
|
fd.Style.PreserveFilenameOnDirectoryChanges = _cbPreserveFilenameOnDirectoryChanges.CheckedState == CheckState.Checked;
|
|
|
|
if (_osAllowedTypes.Value > 0)
|
|
{
|
|
fd.AllowedTypes.Add (new AllowedType ("Data File", ".csv", ".tsv"));
|
|
|
|
if (_osAllowedTypes.Value == 1)
|
|
{
|
|
fd.AllowedTypes.Insert (1, new AllowedTypeAny ());
|
|
}
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace (_tbOkButton.Text))
|
|
{
|
|
fd.Style.OkButtonText = _tbOkButton.Text;
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace (_tbCancelButton.Text))
|
|
{
|
|
fd.Style.CancelButtonText = _tbCancelButton.Text;
|
|
}
|
|
|
|
if (_cbFlipButtonOrder.CheckedState == CheckState.Checked)
|
|
{
|
|
fd.Style.FlipOkCancelButtonLayoutOrder = true;
|
|
}
|
|
|
|
Application.Run (fd);
|
|
|
|
bool canceled = fd.Canceled;
|
|
IReadOnlyList<string> multiSelected = fd.MultiSelected;
|
|
string path = fd.Path;
|
|
|
|
// This needs to be disposed before opening other runnable
|
|
fd.Dispose ();
|
|
|
|
if (canceled)
|
|
{
|
|
MessageBox.Query (Application.Instance,
|
|
"Canceled",
|
|
"You canceled navigation and did not pick anything",
|
|
"Ok"
|
|
);
|
|
}
|
|
else if (_cbAllowMultipleSelection.CheckedState == CheckState.Checked)
|
|
{
|
|
MessageBox.Query (Application.Instance,
|
|
"Chosen!",
|
|
"You chose:" + Environment.NewLine + string.Join (Environment.NewLine, multiSelected.Select (m => m)),
|
|
"Ok"
|
|
);
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Query (Application.Instance,
|
|
"Chosen!",
|
|
"You chose:" + Environment.NewLine + path,
|
|
"Ok"
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
private class CaseSensitiveSearchMatcher : ISearchMatcher
|
|
{
|
|
private string _terms;
|
|
public void Initialize (string terms) { _terms = terms; }
|
|
public bool IsMatch (IFileSystemInfo f) { return f.Name.Contains (_terms, StringComparison.CurrentCulture); }
|
|
}
|
|
}
|