mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +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.
301 lines
9.1 KiB
C#
301 lines
9.1 KiB
C#
using System.Text;
|
|
using System.Timers;
|
|
|
|
namespace UICatalog.Scenarios;
|
|
|
|
[ScenarioMetadata ("Navigation", "Navigation Tester")]
|
|
[ScenarioCategory ("Mouse and Keyboard")]
|
|
[ScenarioCategory ("Layout")]
|
|
[ScenarioCategory ("Navigation")]
|
|
public class Navigation : Scenario
|
|
{
|
|
private int _hotkeyCount;
|
|
|
|
public override void Main ()
|
|
{
|
|
Application.Init ();
|
|
|
|
Window app = new ()
|
|
{
|
|
Title = GetQuitKeyAndName (),
|
|
TabStop = TabBehavior.TabGroup
|
|
};
|
|
|
|
var adornmentsEditor = new AdornmentsEditor
|
|
{
|
|
X = 0,
|
|
Y = 0,
|
|
AutoSelectViewToEdit = true,
|
|
ShowViewIdentifier = true,
|
|
TabStop = TabBehavior.NoStop
|
|
};
|
|
app.Add (adornmentsEditor);
|
|
|
|
var arrangementEditor = new ArrangementEditor ()
|
|
{
|
|
X = Pos.Right (adornmentsEditor),
|
|
Y = 0,
|
|
//Height = Dim.Fill(),
|
|
AutoSelectViewToEdit = true,
|
|
TabStop = TabBehavior.NoStop
|
|
};
|
|
app.Add (arrangementEditor);
|
|
|
|
FrameView testFrame = new ()
|
|
{
|
|
Title = "_1 Test Frame",
|
|
X = Pos.Right (arrangementEditor),
|
|
Y = 1,
|
|
Width = Dim.Fill (),
|
|
Height = Dim.Fill ()
|
|
};
|
|
|
|
|
|
app.Add (testFrame);
|
|
|
|
Button button = new ()
|
|
{
|
|
X = 0,
|
|
Y = 0,
|
|
Title = $"TopButton _{GetNextHotKey ()}"
|
|
};
|
|
button.Accepting += (sender, args) => MessageBox.Query (Application.Instance, "hi", button.Title, "_Ok");
|
|
|
|
testFrame.Add (button);
|
|
|
|
View tiledView1 = CreateTiledView (0, 2, 2);
|
|
View tiledView2 = CreateTiledView (1, Pos.Right (tiledView1), Pos.Top (tiledView1));
|
|
|
|
testFrame.Add (tiledView1);
|
|
testFrame.Add (tiledView2);
|
|
|
|
View tiledView3 = CreateTiledView (1, Pos.Right (tiledView2), Pos.Top (tiledView2));
|
|
tiledView3.TabStop = TabBehavior.TabGroup;
|
|
tiledView3.BorderStyle = LineStyle.Double;
|
|
testFrame.Add (tiledView3);
|
|
|
|
View overlappedView1 = CreateOverlappedView (2, 10, Pos.Center ());
|
|
View tiledSubView = CreateTiledView (4, 0, 2);
|
|
overlappedView1.Add (tiledSubView);
|
|
|
|
ProgressBar progressBar = new ()
|
|
{
|
|
X = Pos.AnchorEnd (),
|
|
Y = Pos.AnchorEnd (),
|
|
Width = Dim.Fill (),
|
|
Id = "progressBar",
|
|
BorderStyle = LineStyle.Rounded
|
|
};
|
|
overlappedView1.Add (progressBar);
|
|
|
|
//Timer timer = new (1)
|
|
//{
|
|
// AutoReset = true
|
|
//};
|
|
|
|
//timer.Elapsed += (o, args) =>
|
|
// {
|
|
// if (progressBar.Fraction == 1.0)
|
|
// {
|
|
// progressBar.Fraction = 0;
|
|
// }
|
|
|
|
// progressBar.Fraction += 0.01f;
|
|
|
|
// Application.Invoke (() => progressBar.SetNeedsDraw ());
|
|
// ;
|
|
// };
|
|
//timer.Start ();
|
|
|
|
Application.Iteration += OnApplicationIteration;
|
|
|
|
View overlappedView2 = CreateOverlappedView (3, 8, 10);
|
|
|
|
View overlappedInOverlapped1 = CreateOverlappedView (4, 1, 4);
|
|
overlappedView2.Add (overlappedInOverlapped1);
|
|
|
|
View overlappedInOverlapped2 = CreateOverlappedView (5, 10, 7);
|
|
overlappedView2.Add (overlappedInOverlapped2);
|
|
|
|
StatusBar statusBar = new ();
|
|
|
|
statusBar.Add (
|
|
new Shortcut
|
|
{
|
|
Title = "Hide",
|
|
Text = "Hotkey",
|
|
Key = Key.F4,
|
|
Action = () =>
|
|
{
|
|
// TODO: move this logic into `View.ShowHide()` or similar
|
|
overlappedView2.Visible = false;
|
|
overlappedView2.Enabled = overlappedView2.Visible;
|
|
}
|
|
});
|
|
|
|
statusBar.Add (
|
|
new Shortcut
|
|
{
|
|
Title = "Toggle Hide",
|
|
Text = "App",
|
|
BindKeyToApplication = true,
|
|
Key = Key.F4.WithCtrl,
|
|
Action = () =>
|
|
{
|
|
// TODO: move this logic into `View.ShowHide()` or similar
|
|
overlappedView2.Visible = !overlappedView2.Visible;
|
|
overlappedView2.Enabled = overlappedView2.Visible;
|
|
|
|
if (overlappedView2.Visible)
|
|
{
|
|
overlappedView2.SetFocus ();
|
|
}
|
|
}
|
|
});
|
|
overlappedView2.Add (statusBar);
|
|
|
|
ColorPicker colorPicker = new ()
|
|
{
|
|
Y = 12,
|
|
Width = Dim.Fill (),
|
|
Id = "colorPicker",
|
|
Style = new ()
|
|
{
|
|
ShowTextFields = true,
|
|
ShowColorName = true
|
|
}
|
|
};
|
|
colorPicker.ApplyStyleChanges ();
|
|
|
|
colorPicker.SelectedColor = testFrame.GetAttributeForRole (VisualRole.Normal).Background;
|
|
colorPicker.ColorChanged += ColorPicker_ColorChanged;
|
|
overlappedView2.Add (colorPicker);
|
|
overlappedView2.Width = 50;
|
|
|
|
testFrame.Add (overlappedView1);
|
|
testFrame.Add (overlappedView2);
|
|
|
|
DatePicker datePicker = new ()
|
|
{
|
|
X = 1,
|
|
Y = 7,
|
|
Id = "datePicker",
|
|
SchemeName = "Runnable",
|
|
ShadowStyle = ShadowStyle.Transparent,
|
|
BorderStyle = LineStyle.Double,
|
|
CanFocus = true, // Can't drag without this? BUGBUG
|
|
TabStop = TabBehavior.TabGroup,
|
|
Arrangement = ViewArrangement.Movable | ViewArrangement.Overlapped
|
|
};
|
|
testFrame.Add (datePicker);
|
|
|
|
button = new ()
|
|
{
|
|
X = Pos.AnchorEnd (),
|
|
Y = Pos.AnchorEnd (),
|
|
Title = $"TopButton _{GetNextHotKey ()}"
|
|
};
|
|
|
|
testFrame.Add (button);
|
|
|
|
adornmentsEditor.AutoSelectSuperView = testFrame;
|
|
arrangementEditor.AutoSelectSuperView = testFrame;
|
|
|
|
testFrame.SetFocus ();
|
|
Application.Run (app);
|
|
Application.Iteration -= OnApplicationIteration;
|
|
// timer.Close ();
|
|
app.Dispose ();
|
|
Application.Shutdown ();
|
|
|
|
return;
|
|
|
|
void OnApplicationIteration (object sender, EventArgs<IApplication> args)
|
|
{
|
|
if (progressBar.Fraction == 1.0)
|
|
{
|
|
progressBar.Fraction = 0;
|
|
}
|
|
|
|
progressBar.Fraction += 0.01f;
|
|
|
|
Application.Invoke ((_) => { });
|
|
}
|
|
|
|
void ColorPicker_ColorChanged (object sender, ResultEventArgs<Color> e)
|
|
{
|
|
testFrame.SetScheme (testFrame.GetScheme () with { Normal = new (testFrame.GetAttributeForRole (VisualRole.Normal).Foreground, e.Result) });
|
|
}
|
|
}
|
|
|
|
private View CreateOverlappedView (int id, Pos x, Pos y)
|
|
{
|
|
var overlapped = new View
|
|
{
|
|
X = x,
|
|
Y = y,
|
|
Height = Dim.Auto (),
|
|
Width = Dim.Auto (),
|
|
Title = $"Overlapped{id} _{GetNextHotKey ()}",
|
|
SchemeName = "Runnable",
|
|
Id = $"Overlapped{id}",
|
|
ShadowStyle = ShadowStyle.Transparent,
|
|
BorderStyle = LineStyle.Double,
|
|
CanFocus = true, // Can't drag without this? BUGBUG
|
|
TabStop = TabBehavior.TabGroup,
|
|
Arrangement = ViewArrangement.Movable | ViewArrangement.Overlapped | ViewArrangement.Resizable
|
|
};
|
|
|
|
Button button = new ()
|
|
{
|
|
Title = $"Button{id} _{GetNextHotKey ()}"
|
|
};
|
|
overlapped.Add (button);
|
|
|
|
button = new ()
|
|
{
|
|
Y = Pos.Bottom (button),
|
|
Title = $"Button{id} _{GetNextHotKey ()}"
|
|
};
|
|
overlapped.Add (button);
|
|
|
|
return overlapped;
|
|
}
|
|
|
|
private View CreateTiledView (int id, Pos x, Pos y)
|
|
{
|
|
var overlapped = new View
|
|
{
|
|
X = x,
|
|
Y = y,
|
|
Height = Dim.Auto (),
|
|
Width = Dim.Auto (),
|
|
Title = $"Tiled{id} _{GetNextHotKey ()}",
|
|
Id = $"Tiled{id}",
|
|
BorderStyle = LineStyle.Single,
|
|
CanFocus = true, // Can't drag without this? BUGBUG
|
|
TabStop = TabBehavior.TabStop,
|
|
Arrangement = ViewArrangement.Fixed
|
|
};
|
|
|
|
Button button = new ()
|
|
{
|
|
Title = $"Tiled Button{id} _{GetNextHotKey ()}",
|
|
Y = 1,
|
|
};
|
|
overlapped.Add (button);
|
|
|
|
button = new ()
|
|
{
|
|
Y = Pos.Bottom (button),
|
|
Title = $"Tiled Button{id} _{GetNextHotKey ()}"
|
|
};
|
|
overlapped.Add (button);
|
|
|
|
|
|
return overlapped;
|
|
}
|
|
|
|
private char GetNextHotKey () { return (char)('A' + _hotkeyCount++); }
|
|
}
|