docfx/docs/newinv2.md
This document provides an in-depth overview of the new features, improvements, and architectural changes in Terminal.Gui v2 compared to v1.
For migration guidance, see the v1 To v2 Migration Guide.
Terminal.Gui v2 represents a fundamental redesign of the library's architecture, API, and capabilities. Key improvements include:
Terminal.Gui v2 was designed with these core principles:
EventHandler<T> and IDisposableSee the Application Deep Dive for complete details.
v2 introduces an instance-based architecture that eliminates global state and enables multiple application contexts.
IApplication Interface:
View.App Property:
Session Management:
// Instance-based pattern (recommended)
IApplication app = Application.Create ().Init ();
Window window = new () { Title = "My App" };
app.Run (window);
window.Dispose ();
app.Dispose ();
// With using statement for automatic disposal
using (IApplication app = Application.Create ().Init ())
{
Window window = new () { Title = "My App" };
app.Run (window);
window.Dispose ();
} // app.Dispose() called automatically
// Access from within a view
public class MyView : View
{
public void DoWork ()
{
App?.Driver.Move (0, 0);
App?.TopRunnableView?.SetNeedsDraw ();
}
}
v2 implements full IDisposable pattern:
// Recommended: using statement
using (IApplication app = Application.Create ().Init ())
{
app.Run<MyDialog> ();
MyResult? result = app.GetResult<MyResult> ();
}
// Ensures:
// - Input thread stopped cleanly
// - Driver resources released
// - No thread leaks in tests
Important Changes:
Dispose() insteadSee the Application Deep Dive for complete details.
v2 introduces xref:Terminal.Gui.App.IRunnable - an interface-based pattern for runnable views with type-safe results.
Interface-Based:
RunnableType-Safe Results:
TResult parameter provides compile-time type safetynull indicates cancellation/non-acceptanceLifecycle Events (CWP-Compliant):
IsRunningChanging - Cancellable, before stack changeIsRunningChanged - Non-cancellable, after stack changeIsModalChanging - Cancellable, before modal state changeIsModalChanged - Non-cancellable, after modal state changepublic class FileDialog : Runnable<string?>
{
private TextField _pathField;
public FileDialog ()
{
Title = "Select File";
_pathField = new () { Width = Dim.Fill () };
Add (_pathField);
Button okButton = new () { Text = "OK", IsDefault = true };
okButton.Accepting += (s, e) =>
{
Result = _pathField.Text;
Application.RequestStop ();
};
AddButton (okButton);
}
protected override bool OnIsRunningChanging (bool oldValue, bool newValue)
{
if (!newValue) // Stopping - extract result before disposal
{
Result = _pathField?.Text;
// Optionally cancel stop
if (HasUnsavedChanges ())
{
return true; // Cancel
}
}
return base.OnIsRunningChanging (oldValue, newValue);
}
}
// Use with fluent API
using (IApplication app = Application.Create ().Init ())
{
app.Run<FileDialog> ();
string? path = app.GetResult<string> ();
if (path is { })
{
OpenFile (path);
}
}
v2 enables elegant method chaining:
// Concise and readable
using (IApplication app = Application.Create ().Init ())
{
app.Run<ColorPickerDialog> ();
Color? result = app.GetResult<Color> ();
}
Key Methods:
Dispose() - Release all resources"Whoever creates it, owns it":
| Method | Creator | Owner | Disposal |
|---|---|---|---|
| Run<TRunnable>() | Framework | Framework | Automatic when returns |
Run(IRunnable) | Caller | Caller | Manual by caller |
// Framework ownership - automatic disposal
app.Run<MyDialog> (); // Dialog disposed automatically
// Caller ownership - manual disposal
MyDialog dialog = new ();
app.Run (dialog);
dialog.Dispose (); // Caller must dispose
See the Drawing Deep Dive for complete details.
v2 provides full 24-bit color support by default:
IDriver.SupportsTrueColor detection// 24-bit RGB color
Color customColor = new (0xFF, 0x99, 0x00);
// Or use named colors (ANSI-compliant)
Color color = Color.Yellow; // Was "Brown" in v1
See the Layout Deep Dive for complete details.
v2 introduces a comprehensive Adornment system with lightweight adornments that lazily create Views when needed:
view.BorderStyle = LineStyle.Double;
view.Border.Thickness = new (1);
view.Title = "My View";
view.Margin.Thickness = new (2);
view.Padding.Thickness = new (1);
See the Configuration Deep Dive and Scheme Deep Dive for details.
v2 adds comprehensive theme support:
// Apply a theme
ConfigurationManager.Themes.Theme = "Dark";
// Customize text style
view.Scheme.Normal = new (
Color.White,
Color.Black,
TextStyle.Bold | TextStyle.Underline
);
See the Drawing Deep Dive for complete details.
LineCanvas provides sophisticated line drawing:
// Line view uses LineCanvas
Line line = new () { Orientation = Orientation.Horizontal };
line.LineStyle = LineStyle.Double;
See the Drawing Deep Dive for details.
v2 adds gradient support:
Gradient gradient = new (Color.Blue, Color.Cyan);
view.BackgroundGradient = new (gradient, Orientation.Vertical);
v2 consolidates redundant APIs:
EventHandler<T> patternOnHasFocusChanged)Example:
// v1 - Multiple scattered methods
View.MostFocused
View.EnsureFocus ()
View.FocusNext ()
// v2 - Centralized
Application.Navigation.GetFocused ()
view.SetFocus ()
view.AdvanceFocus ()
EventHandler<EventArgs> instead of custom delegatesv2 reduces overhead through:
Result: Snappier UIs, especially with many views or frequent updates
v2 clarifies view ownership:
Application.Run manages Runnable lifecycleSee the Scrolling Deep Dive for complete details.
Every View supports scrolling inherently:
No need for ScrollView wrapper!
// Enable scrolling
view.SetContentSize (new (100, 100));
// Scroll by changing Viewport location
view.ScrollVertical (5);
view.ScrollHorizontal (3);
// Built-in scrollbars with automatic visibility
view.ViewportSettings |= ViewportSettingsFlags.HasVerticalScrollBar;
view.ViewportSettings |= ViewportSettingsFlags.HasHorizontalScrollBar;
v2 replaces ScrollBarView with ScrollBar:
ScrollSliderSee the Layout Deep Dive and DimAuto Deep Dive for details.
xref:Terminal.Gui.ViewBase.Dim.Auto*:
xref:Terminal.Gui.ViewBase.Pos.AnchorEnd*:
// Auto-size based on text
label.Width = Dim.Auto ();
label.Height = Dim.Auto ();
// Anchor to bottom-right
button.X = Pos.AnchorEnd (10);
button.Y = Pos.AnchorEnd (2);
// Center align
label1.X = Pos.Center ();
label2.X = Pos.Center ();
See the Arrangement Deep Dive for complete details.
View.Arrangement enables interactive UI:
Arrangement Key: Press Ctrl+F5 (configurable via Application.DefaultKeyBindings for Command.Arrange) to enter arrange mode
// Movable and resizable window
window.Arrangement = ViewArrangement.Movable | ViewArrangement.Resizable;
// Overlapped windows
container.Arrangement = ViewArrangement.Overlapped;
See the Navigation Deep Dive for complete details.
v2 decouples navigation concepts:
false in v2)Navigation Keys (Configurable):
Tab / Shift+Tab - Next/previous TabStopF6 / Shift+F6 - Next/previous TabGroup// Configure navigation keys via Application.DefaultKeyBindings
Application.DefaultKeyBindings[Command.NextTabStop] = Bind.All (Key.Tab);
Application.DefaultKeyBindings[Command.PreviousTabStop] = Bind.All (Key.Tab.WithShift);
Application.DefaultKeyBindings[Command.NextTabGroup] = Bind.All (Key.F6);
Application.DefaultKeyBindings[Command.PreviousTabGroup] = Bind.All (Key.F6.WithShift);
// Set tab behavior
view.CanFocus = true;
view.TabStop = TabBehavior.TabStop; // Normal tab navigation
See the Views Overview for a complete catalog.
See the Keyboard Deep Dive and Command Deep Dive for details.
Key Class:
KeyEvent struct// Check keys
if (key == Key.Enter) { }
if (key == Key.C.WithCtrl) { }
// Modifiers
if (key.Shift) { }
if (key.Ctrl) { }
Key Bindings:
// Add command handler
view.AddCommand (Command.Accept, HandleAccept);
// Bind key to command
view.KeyBindings.Add (Key.Enter, Command.Accept);
private bool HandleAccept ()
{
// Handle command
return true; // Handled
}
Configurable Keys (via Application.DefaultKeyBindings):
Command.Quit - Close app (default: Esc)Command.Arrange - Arrange mode (default: Ctrl+F5)Command.NextTabStop, Command.NextTabGroup, etc.)See the Mouse Deep Dive for complete details.
MouseEventEventArgsGranular Events:
Highlight and Repeat on Hold:
See the Configuration Deep Dive for complete details.
ConfigurationManager provides:
// Enable configuration
ConfigurationManager.Enable (ConfigLocations.All);
// Load a theme
ConfigurationManager.Themes.Theme = "Dark";
// Save current configuration
ConfigurationManager.Save ();
User Customization:
See the Logging Deep Dive for complete details.
Logging integrates with Microsoft.Extensions.Logging:
// Configure logging
Logging.ConfigureLogging ("myapp.log", LogLevel.Debug);
// Use in code
Logging.Debug ("Rendering view {ViewId}", view.Id);
Logging.Meter provides performance metrics:
Tools: Use dotnet-counters or other metrics tools to monitor
dotnet counters monitor --name MyApp Terminal.Gui
v2 supports the Sixel protocol for rendering images:
Use Cases: Image previews, graphics in terminal apps
v2 ensures compatibility with Ahead-of-Time compilation:
Example: See Examples/NativeAot for AOT deployment
Terminal.Gui v2 represents a comprehensive modernization:
Architecture:
Features:
API:
Views:
v2 provides a robust foundation for building sophisticated, maintainable, and user-friendly terminal applications. The architectural improvements, combined with new features and enhanced APIs, enable developers to create modern terminal UIs that feel responsive and polished.
For detailed migration guidance, see the v1 To v2 Migration Guide.