Files
Terminal.Gui/Examples/UICatalog/Scenarios/RuneWidthGreaterThanOne.cs
Tig 0f72cf8a74 Fixes #4425 - ApplicationImpl internal (#4426)
* 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.
2025-12-01 14:40:31 -07:00

281 lines
7.5 KiB
C#

#nullable enable
using System;
namespace UICatalog.Scenarios;
[ScenarioMetadata ("RuneWidthGreaterThanOne", "Test rune width greater than one")]
[ScenarioCategory ("Controls")]
[ScenarioCategory ("Text and Formatting")]
[ScenarioCategory ("Tests")]
public class RuneWidthGreaterThanOne : Scenario
{
private Button? _button;
private Label? _label;
private Label? _labelR;
private Label? _labelV;
private string? _lastRunesUsed;
private TextField? _text;
private Window? _win;
public override void Main ()
{
Application.Init ();
// Window (top-level)
Window win = new ()
{
X = 5,
Y = 5,
Width = Dim.Fill (22),
Height = Dim.Fill (5),
Arrangement = ViewArrangement.Overlapped | ViewArrangement.Movable
};
_win = win;
// MenuBar
MenuBar menu = new ();
// Controls
_label = new ()
{
X = Pos.Center (),
Y = 1
};
_text = new ()
{
X = Pos.Center (),
Y = 3,
Width = 20
};
_button = new ()
{
X = Pos.Center (),
Y = 5
};
_labelR = new ()
{
X = Pos.AnchorEnd (30),
Y = 18
};
_labelV = new ()
{
TextDirection = TextDirection.TopBottom_LeftRight,
X = Pos.AnchorEnd (30),
Y = Pos.Bottom (_labelR)
};
menu.Add (
new MenuBarItem (
"Padding",
[
new MenuItem
{
Title = "With Padding",
Action = () =>
{
if (_win is { })
{
_win.Padding!.Thickness = new (1);
}
}
},
new MenuItem
{
Title = "Without Padding",
Action = () =>
{
if (_win is { })
{
_win.Padding!.Thickness = new (0);
}
}
}
]
)
);
menu.Add (
new MenuBarItem (
"BorderStyle",
[
new MenuItem
{
Title = "Single",
Action = () =>
{
if (_win is { })
{
_win.BorderStyle = LineStyle.Single;
}
}
},
new MenuItem
{
Title = "None",
Action = () =>
{
if (_win is { })
{
_win.BorderStyle = LineStyle.None;
}
}
}
]
)
);
menu.Add (
new MenuBarItem (
"Runes length",
[
new MenuItem
{
Title = "Wide",
Action = WideRunes
},
new MenuItem
{
Title = "Narrow",
Action = NarrowRunes
},
new MenuItem
{
Title = "Mixed",
Action = MixedRunes
}
]
)
);
// Add views in order of visual appearance
win.Add (menu, _label, _text, _button, _labelR, _labelV);
WideRunes ();
Application.Run (win);
win.Dispose ();
Application.Shutdown ();
}
private void MixedMessage (object? sender, EventArgs e)
{
if (_text is { })
{
MessageBox.Query (Application.Instance, "Say Hello 你", $"Hello {_text.Text}", "Ok");
}
}
private void MixedRunes ()
{
if (_label is null || _text is null || _button is null || _labelR is null || _labelV is null || _win is null)
{
return;
}
UnsetClickedEvent ();
_label.Text = "Enter your name 你:";
_text.Text = "gui.cs 你:";
_button.Text = "Say Hello 你";
_button.Accepting += MixedMessage;
_labelR.X = Pos.AnchorEnd (21);
_labelR.Y = 18;
_labelR.Text = "This is a test text 你";
_labelV.X = Pos.AnchorEnd (21);
_labelV.Y = Pos.Bottom (_labelR);
_labelV.Text = "This is a test text 你";
_win.Title = "HACC Demo 你";
_lastRunesUsed = "Mixed";
Application.LayoutAndDraw ();
}
private void NarrowMessage (object? sender, EventArgs e)
{
if (_text is { })
{
MessageBox.Query (Application.Instance, "Say Hello", $"Hello {_text.Text}", "Ok");
}
}
private void NarrowRunes ()
{
if (_label is null || _text is null || _button is null || _labelR is null || _labelV is null || _win is null)
{
return;
}
UnsetClickedEvent ();
_label.Text = "Enter your name:";
_text.Text = "gui.cs";
_button.Text = "Say Hello";
_button.Accepting += NarrowMessage;
_labelR.X = Pos.AnchorEnd (19);
_labelR.Y = 18;
_labelR.Text = "This is a test text";
_labelV.X = Pos.AnchorEnd (19);
_labelV.Y = Pos.Bottom (_labelR);
_labelV.Text = "This is a test text";
_win.Title = "HACC Demo";
_lastRunesUsed = "Narrow";
Application.LayoutAndDraw ();
}
private void UnsetClickedEvent ()
{
if (_button is null)
{
return;
}
switch (_lastRunesUsed)
{
case "Narrow":
_button.Accepting -= NarrowMessage;
break;
case "Mixed":
_button.Accepting -= MixedMessage;
break;
case "Wide":
_button.Accepting -= WideMessage;
break;
}
}
private void WideMessage (object? sender, EventArgs e)
{
if (_text is { })
{
MessageBox.Query (Application.Instance, "こんにちはと言う", $"こんにちは {_text.Text}", "Ok");
}
}
private void WideRunes ()
{
if (_label is null || _text is null || _button is null || _labelR is null || _labelV is null || _win is null)
{
return;
}
UnsetClickedEvent ();
_label.Text = "あなたの名前を入力してください:";
_text.Text = "ティラミス";
_button.Text = "こんにちはと言う";
_button.Accepting += WideMessage;
_labelR.X = Pos.AnchorEnd (29);
_labelR.Y = 18;
_labelR.Text = "あなたの名前を入力してください";
_labelV.X = Pos.AnchorEnd (29);
_labelV.Y = Pos.Bottom (_labelR);
_labelV.Text = "あなたの名前を入力してください";
_win.Title = "デモエムポンズ";
_lastRunesUsed = "Wide";
Application.LayoutAndDraw ();
}
}