Files
Terminal.Gui/docfx/docs/migratingfromv1.md
Copilot dd12df7fb7 Fixes #4176. Removes View.MouseClick (#4450)
* Initial plan

* Add comprehensive MouseClick removal analysis

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Fix code review feedback on analysis document

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Add actual line numbers to analysis document

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Final polish on analysis document - clarify TextView

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Phase 3: Port 6 simple Views from MouseClick to Selecting/MouseBindings

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Phase 2: Port 10 Scenarios from MouseClick to Selecting/remove

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Update analysis document - Phases 2 & 3 complete

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Fix failing tests - Button multi-button support and Label focus handling

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Phase 4: Port ScrollBar from OnMouseClick to OnSelecting; remove analysis doc

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Phase 5: Update/remove tests that explicitly test MouseClick API

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Code cleanup

* Remove MouseClick event

Consolidated mouse event handling by removing the `MouseClick`
event and integrating its functionality into the `MouseEvent`
event. Simplified `MouseEventArgs` documentation and added
support for invoking commands bound to mouse events.

Reorganized code by removing `Mouse Pressed Events` and
`Mouse Click Events` regions, introducing a new `WhenGrabbed
Handlers` region. Updated tests to replace `MouseClick` with
`MouseEvent`, adjusted test logic, and improved variable
naming for clarity.

Removed redundant assertions and unused code related to
`MouseClick`. Improved event propagation logic to ensure
proper handling of unhandled events. Performed general code
cleanup to enhance readability and maintainability.

* Updated deep dives.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: tig <585482+tig@users.noreply.github.com>
Co-authored-by: Tig <tig@users.noreply.github.com>
2025-12-06 14:41:20 -07:00

1218 lines
24 KiB
Markdown

# Migrating From v1 To v2
This document provides a comprehensive guide for migrating applications from Terminal.Gui v1 to v2.
For detailed breaking change documentation, check out this Discussion: https://github.com/gui-cs/Terminal.Gui/discussions/2448
## Table of Contents
- [Overview of Major Changes](#overview-of-major-changes)
- [Application Architecture](#application-architecture)
- [View Construction and Initialization](#view-construction-and-initialization)
- [Layout System Changes](#layout-system-changes)
- [Color and Attribute Changes](#color-and-attribute-changes)
- [Type Changes](#type-changes)
- [Unicode and Text](#unicode-and-text)
- [Keyboard API](#keyboard-api)
- [Mouse API](#mouse-api)
- [Navigation Changes](#navigation-changes)
- [Scrolling Changes](#scrolling-changes)
- [Adornments](#adornments)
- [Event Pattern Changes](#event-pattern-changes)
- [View-Specific Changes](#view-specific-changes)
- [Disposal and Resource Management](#disposal-and-resource-management)
- [API Terminology Changes](#api-terminology-changes)
---
## Overview of Major Changes
Terminal.Gui v2 represents a major architectural evolution with these key improvements:
1. **Instance-Based Application Model** - Move from static `Application` to `IApplication` instances
2. **IRunnable Architecture** - Interface-based runnable pattern with type-safe results
3. **Simplified Layout** - Removed Absolute/Computed distinction, improved adornments
4. **24-bit TrueColor** - Full color support by default
5. **Enhanced Input** - Better keyboard and mouse APIs
6. **Built-in Scrolling** - All views support scrolling inherently
7. **Fluent API** - Method chaining for elegant code
8. **Proper Disposal** - IDisposable pattern throughout
---
## Application Architecture
### Instance-Based Application Model
**v1 Pattern (Static):**
```csharp
// v1 - static Application
Application.Init();
var top = Application.Top;
top.Add(myView);
Application.Run();
Application.Shutdown();
```
**v2 Recommended Pattern (Instance-Based):**
```csharp
// v2 - instance-based with using statement
using (var app = Application.Create().Init())
{
var top = new Window();
top.Add(myView);
app.Run(top);
top.Dispose();
} // app.Dispose() called automatically
```
**v2 Legacy Pattern (Still Works):**
```csharp
// v2 - legacy static (marked obsolete but functional)
Application.Init();
var top = new Window();
top.Add(myView);
Application.Run(top);
top.Dispose();
Application.Shutdown(); // Obsolete - use Dispose() instead
```
### IRunnable Architecture
v2 introduces `IRunnable<TResult>` for type-safe, runnable views:
```csharp
// Create a dialog that returns a typed result
public class FileDialog : Runnable<string?>
{
private TextField _pathField;
public FileDialog()
{
Title = "Select File";
_pathField = new TextField { Width = Dim.Fill() };
Add(_pathField);
var okButton = new Button { 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;
}
return base.OnIsRunningChanging(oldValue, newValue);
}
}
// Use with fluent API
using (var app = Application.Create().Init())
{
app.Run<FileDialog>();
string? result = app.GetResult<string>();
if (result is { })
{
OpenFile(result);
}
}
```
**Key Benefits:**
- Type-safe results (no casting)
- Automatic disposal of framework-created runnables
- CWP-compliant lifecycle events
- Works with any View (not just Toplevel)
### Disposal and Resource Management
v2 requires explicit disposal:
```csharp
// ❌ v1 - Application.Shutdown() disposed everything
Application.Init();
var top = new Window();
Application.Run(top);
Application.Shutdown(); // Disposed top automatically
// ✅ v2 - Dispose views explicitly
using (var app = Application.Create().Init())
{
var top = new Window();
app.Run(top);
top.Dispose(); // Must dispose
}
// ✅ v2 - Framework-created runnables disposed automatically
using (var app = Application.Create().Init())
{
app.Run<MyDialog>(); // Dialog disposed automatically
var result = app.GetResult<MyResult>();
}
```
**Disposal Rules:**
- "Whoever creates it, owns it"
- `Run<TRunnable>()`: Framework creates → Framework disposes
- `Run(IRunnable)`: Caller creates → Caller disposes
- Always dispose `IApplication` (use `using` statement)
### View.App Property
Views now have an `App` property for accessing the application context:
```csharp
// ❌ v1 - Direct static reference
Application.Driver.Move(x, y);
// ✅ v2 - Use View.App
App?.Driver.Move(x, y);
// ✅ v2 - Dependency injection
public class MyView : View
{
private readonly IApplication _app;
public MyView(IApplication app)
{
_app = app;
}
}
```
---
## View Construction and Initialization
### Constructors → Initializers
**v1:**
```csharp
var myView = new View(new Rect(10, 10, 40, 10));
```
**v2:**
```csharp
var myView = new View
{
X = 10,
Y = 10,
Width = 40,
Height = 10
};
```
### Initialization Pattern
v2 uses `ISupportInitializeNotification`:
```csharp
// v1 - No explicit initialization
var view = new View();
Application.Run(view);
// v2 - Automatic initialization via BeginInit/EndInit
var view = new View();
// BeginInit() called automatically when added to SuperView
// EndInit() called automatically
// Initialized event raised after EndInit()
```
---
## Layout System Changes
### Removed LayoutStyle Distinction
v1 had `Absolute` and `Computed` layout styles. v2 removed this distinction.
**v1:**
```csharp
view.LayoutStyle = LayoutStyle.Computed;
```
**v2:**
```csharp
// No LayoutStyle - all layout is declarative via Pos/Dim
view.X = Pos.Center();
view.Y = Pos.Center();
view.Width = Dim.Percent(50);
view.Height = Dim.Fill();
```
### Frame vs Bounds
**v1:**
- `Frame` - Position/size in SuperView coordinates
- `Bounds` - Always `{0, 0, Width, Height}` (location always empty)
**v2:**
- `Frame` - Position/size in SuperView coordinates (same as v1)
- `Viewport` - Visible area in content coordinates (replaces Bounds)
- **Important**: `Viewport.Location` can now be non-zero for scrolling
```csharp
// ❌ v1
var size = view.Bounds.Size;
Debug.Assert(view.Bounds.Location == Point.Empty); // Always true
// ✅ v2
var visibleArea = view.Viewport;
var contentSize = view.GetContentSize();
// Viewport.Location can be non-zero when scrolled
view.ScrollVertical(10);
Debug.Assert(view.Viewport.Location.Y == 10);
```
### Pos and Dim API Changes
| v1 | v2 |
|----|-----|
| `Pos.At(x)` | `Pos.Absolute(x)` |
| `Dim.Sized(width)` | `Dim.Absolute(width)` |
| `Pos.Anchor()` | `Pos.GetAnchor()` |
| `Dim.Anchor()` | `Dim.GetAnchor()` |
```csharp
// ❌ v1
view.X = Pos.At(10);
view.Width = Dim.Sized(20);
// ✅ v2
view.X = Pos.Absolute(10);
view.Width = Dim.Absolute(20);
```
### View.AutoSize Removed
**v1:**
```csharp
view.AutoSize = true;
```
**v2:**
```csharp
view.Width = Dim.Auto();
view.Height = Dim.Auto();
```
See [Dim.Auto Deep Dive](dimauto.md) for details.
---
## Adornments
v2 adds `Border`, `Margin`, and `Padding` as built-in adornments.
**v1:**
```csharp
// Custom border drawing
view.Border = new Border { /* ... */ };
```
**v2:**
```csharp
// Built-in Border adornment
view.BorderStyle = LineStyle.Single;
view.Border.Thickness = new Thickness(1);
view.Title = "My View";
// Built-in Margin and Padding
view.Margin.Thickness = new Thickness(2);
view.Padding.Thickness = new Thickness(1);
```
See [Layout Deep Dive](layout.md) for complete details.
---
## Color and Attribute Changes
### 24-bit TrueColor Default
v2 uses 24-bit color by default.
```csharp
// v1 - Limited color palette
var color = Color.Brown;
// v2 - ANSI-compliant names + TrueColor
var color = Color.Yellow; // Brown renamed
var customColor = new Color(0xFF, 0x99, 0x00); // 24-bit RGB
```
### Attribute.Make Removed
**v1:**
```csharp
var attr = Attribute.Make(Color.BrightMagenta, Color.Blue);
```
**v2:**
```csharp
var attr = new Attribute(Color.BrightMagenta, Color.Blue);
```
### Color Name Changes
| v1 | v2 |
|----|-----|
| `Color.Brown` | `Color.Yellow` |
---
## Type Changes
### Low-Level Types
| v1 | v2 |
|----|-----|
| `Rect` | `Rectangle` |
| `Point` | `Point` |
| `Size` | `Size` |
```csharp
// ❌ v1
Rect rect = new Rect(0, 0, 10, 10);
// ✅ v2
Rectangle rect = new Rectangle(0, 0, 10, 10);
```
---
## Unicode and Text
### NStack.ustring Removed
**v1:**
```csharp
using NStack;
ustring text = "Hello";
var width = text.Sum(c => Rune.ColumnWidth(c));
```
**v2:**
```csharp
using System.Text;
string text = "Hello";
var width = text.GetColumns(); // Extension method
```
### Rune Changes
**v1:**
```csharp
// Implicit cast
myView.AddRune(col, row, '▄');
// Width
var width = Rune.ColumnWidth(rune);
```
**v2:**
```csharp
// Explicit constructor
myView.AddRune(col, row, new Rune('▄'));
// Width
var width = rune.GetColumns();
```
See [Unicode](https://gui-cs.github.io/Terminal.GuiV2Docs/docs/overview.html#unicode) for details.
---
## Keyboard API
v2 has a completely redesigned keyboard API.
### Key Class
**v1:**
```csharp
KeyEvent keyEvent;
if (keyEvent.KeyCode == KeyCode.Enter) { }
```
**v2:**
```csharp
Key key;
if (key == Key.Enter) { }
// Modifiers
if (key.Shift) { }
if (key.Ctrl) { }
// With modifiers
Key ctrlC = Key.C.WithCtrl;
Key shiftF1 = Key.F1.WithShift;
```
### Key Bindings
**v1:**
```csharp
// Override OnKeyPress
protected override bool OnKeyPress(KeyEvent keyEvent)
{
if (keyEvent.KeyCode == KeyCode.Enter)
{
// Handle
return true;
}
return base.OnKeyPress(keyEvent);
}
```
**v2:**
```csharp
// Use KeyBindings + Commands
AddCommand(Command.Accept, HandleAccept);
KeyBindings.Add(Key.Enter, Command.Accept);
private bool HandleAccept()
{
// Handle
return true;
}
```
### Application-Wide Keys
**v1:**
```csharp
// Hard-coded Ctrl+Q
if (keyEvent.Key == Key.CtrlMask | Key.Q)
{
Application.RequestStop();
}
```
**v2:**
```csharp
// Configurable quit key
if (key == Application.QuitKey)
{
Application.RequestStop();
}
// Change the quit key
Application.QuitKey = Key.Esc;
```
### Navigation Keys
v2 has consistent, configurable navigation keys:
| Key | Purpose |
|-----|---------|
| `Tab` | Next TabStop |
| `Shift+Tab` | Previous TabStop |
| `F6` | Next TabGroup |
| `Shift+F6` | Previous TabGroup |
```csharp
// Configurable
Application.NextTabStopKey = Key.Tab;
Application.PrevTabStopKey = Key.Tab.WithShift;
Application.NextTabGroupKey = Key.F6;
Application.PrevTabGroupKey = Key.F6.WithShift;
```
See [Keyboard Deep Dive](keyboard.md) for complete details.
---
## Mouse API
### MouseEventEventArgs → MouseEventArgs
**v1:**
```csharp
void HandleMouse(MouseEventEventArgs args) { }
```
**v2:**
```csharp
void HandleMouse(object? sender, MouseEventArgs args) { }
```
### Mouse Coordinates
**v1:**
- Mouse coordinates were screen-relative
**v2:**
- Mouse coordinates are now **Viewport-relative**
```csharp
// v2 - Viewport-relative coordinates
view.MouseEvent += (s, e) =>
{
// e.Position is relative to view's Viewport
var x = e.Position.X; // 0 = left edge of viewport
var y = e.Position.Y; // 0 = top edge of viewport
};
```
### Mouse Click Handling
**v1:**
```csharp
// v1 - MouseClick event
view.MouseClick += (mouseEvent) =>
{
// Handle click
DoSomething();
};
```
**v2:**
```csharp
// v2 - Use MouseBindings + Commands + Selecting event
view.MouseBindings.Add(MouseFlags.Button1Clicked, Command.Select);
view.Selecting += (s, e) =>
{
// Handle selection (called when Button1Clicked)
DoSomething();
};
// Alternative: Use MouseEvent for low-level handling
view.MouseEvent += (s, e) =>
{
if (e.Flags.HasFlag(MouseFlags.Button1Clicked))
{
DoSomething();
e.Handled = true;
}
};
```
**Key Changes:**
- `View.MouseClick` event has been **removed**
- Use `MouseBindings` to map mouse events to `Command`s
- Default mouse bindings invoke `Command.Select` which raises the `Selecting` event
- For custom behavior, override `OnSelecting` or subscribe to the `Selecting` event
- For low-level mouse handling, use `MouseEvent` directly
**Migration Pattern:**
```csharp
// ❌ v1 - OnMouseClick override
protected override bool OnMouseClick(MouseEventArgs mouseEvent)
{
if (mouseEvent.Flags.HasFlag(MouseFlags.Button1Clicked))
{
PerformAction();
return true;
}
return base.OnMouseClick(mouseEvent);
}
// ✅ v2 - OnSelecting override
protected override bool OnSelecting(CommandEventArgs args)
{
if (args.Context is CommandContext<MouseBinding> { Binding.MouseEventArgs: { } mouseArgs })
{
// Access mouse position and flags via context
if (mouseArgs.Flags.HasFlag(MouseFlags.Button1Clicked))
{
PerformAction();
return true;
}
}
return base.OnSelecting(args);
}
// ✅ v2 - Selecting event (simpler)
view.Selecting += (s, e) =>
{
PerformAction();
e.Handled = true;
};
```
**Accessing Mouse Position in Selecting Event:**
```csharp
view.Selecting += (s, e) =>
{
// Extract mouse event args from command context
if (e.Context is CommandContext<MouseBinding> { Binding.MouseEventArgs: { } mouseArgs })
{
Point position = mouseArgs.Position;
MouseFlags flags = mouseArgs.Flags;
// Use position and flags for custom logic
HandleClick(position, flags);
e.Handled = true;
}
};
```
### Mouse State and Highlighting
v2 adds enhanced mouse state tracking:
```csharp
// Configure which mouse states trigger highlighting
view.HighlightStates = MouseState.In | MouseState.Pressed;
// React to mouse state changes
view.MouseStateChanged += (s, e) =>
{
switch (e.Value)
{
case MouseState.In:
// Mouse entered view
break;
case MouseState.Pressed:
// Mouse button pressed in view
break;
}
};
```
See [Mouse Deep Dive](mouse.md) for complete details.
---
## Navigation Changes
### Focus Properties
**v1:**
```csharp
view.CanFocus = true; // Default was true
```
**v2:**
```csharp
view.CanFocus = true; // Default is FALSE - must opt-in
```
**Important:** In v2, `CanFocus` defaults to `false`. Views that want focus must explicitly set it.
### Focus Changes
**v1:**
```csharp
// HasFocus was read-only
bool hasFocus = view.HasFocus;
```
**v2:**
```csharp
// HasFocus can be set
view.HasFocus = true; // Equivalent to SetFocus()
view.HasFocus = false; // Equivalent to SuperView.AdvanceFocus()
```
### TabStop Behavior
**v1:**
```csharp
view.TabStop = true; // Boolean
```
**v2:**
```csharp
view.TabStop = TabBehavior.TabStop; // Enum with more options
// Options:
// - NoStop: Focusable but not via Tab
// - TabStop: Normal tab navigation
// - TabGroup: Advance via F6
```
### Navigation Events
**v1:**
```csharp
view.Enter += (s, e) => { }; // Gained focus
view.Leave += (s, e) => { }; // Lost focus
```
**v2:**
```csharp
view.HasFocusChanging += (s, e) =>
{
// Before focus changes (cancellable)
if (preventFocusChange)
e.Cancel = true;
};
view.HasFocusChanged += (s, e) =>
{
// After focus changed
if (e.Value)
Console.WriteLine("Gained focus");
else
Console.WriteLine("Lost focus");
};
```
See [Navigation Deep Dive](navigation.md) for complete details.
---
## Scrolling Changes
### ScrollView Removed
**v1:**
```csharp
var scrollView = new ScrollView
{
ContentSize = new Size(100, 100),
ShowHorizontalScrollIndicator = true,
ShowVerticalScrollIndicator = true
};
```
**v2:**
```csharp
// Built-in scrolling on every View
var view = new View();
view.SetContentSize(new Size(100, 100));
// Built-in scrollbars
view.VerticalScrollBar.Visible = true;
view.HorizontalScrollBar.Visible = true;
view.VerticalScrollBar.AutoShow = true;
```
### Scrolling API
**v2:**
```csharp
// Set content larger than viewport
view.SetContentSize(new Size(100, 100));
// Scroll by changing Viewport location
view.Viewport = view.Viewport with { Location = new Point(10, 10) };
// Or use helper methods
view.ScrollVertical(5);
view.ScrollHorizontal(3);
```
See [Scrolling Deep Dive](scrolling.md) for complete details.
---
## Event Pattern Changes
v2 standardizes all events to use `object sender, EventArgs args` pattern.
### Button.Clicked → Button.Accepting
**v1:**
```csharp
button.Clicked += () => { /* do something */ };
```
**v2:**
```csharp
button.Accepting += (s, e) => { /* do something */ };
```
### Event Signatures
**v1:**
```csharp
// Various patterns
event Action SomeEvent;
event Action<string> OtherEvent;
event Action<EventArgs> ThirdEvent;
```
**v2:**
```csharp
// Consistent pattern
event EventHandler<EventArgs>? SomeEvent;
event EventHandler<EventArgs<string>>? OtherEvent;
event EventHandler<CancelEventArgs<bool>>? ThirdEvent;
```
**Benefits:**
- Named parameters
- Cancellable events via `CancelEventArgs`
- Future-proof (new properties can be added)
---
## View-Specific Changes
### CheckBox
**v1:**
```csharp
var cb = new CheckBox("_Checkbox", true);
cb.Toggled += (e) => { };
cb.Toggle();
```
**v2:**
```csharp
var cb = new CheckBox
{
Title = "_Checkbox",
CheckState = CheckState.Checked
};
cb.CheckStateChanging += (s, e) =>
{
e.Cancel = preventChange;
};
cb.AdvanceCheckState();
```
### StatusBar
**v1:**
```csharp
var statusBar = new StatusBar(
new StatusItem[]
{
new StatusItem(Application.QuitKey, "Quit", () => Quit())
}
);
```
**v2:**
```csharp
var statusBar = new StatusBar(
new Shortcut[]
{
new Shortcut(Application.QuitKey, "Quit", Quit)
}
);
```
### PopoverMenu
v2 replaces `ContextMenu` with `PopoverMenu`:
**v1:**
```csharp
var contextMenu = new ContextMenu();
```
**v2:**
```csharp
var popoverMenu = new PopoverMenu();
```
### MenuItem
**v1:**
```csharp
new MenuItem(
"Copy",
"",
CopyGlyph,
null,
null,
(KeyCode)Key.G.WithCtrl
)
```
**v2:**
```csharp
new MenuItem(
"Copy",
"",
CopyGlyph,
Key.G.WithCtrl
)
```
---
## Disposal and Resource Management
v2 implements proper `IDisposable` throughout.
### View Disposal
```csharp
// v1 - No explicit disposal needed
var view = new View();
Application.Run(view);
Application.Shutdown();
// v2 - Explicit disposal required
var view = new View();
app.Run(view);
view.Dispose();
app.Dispose();
```
### Disposal Patterns
```csharp
// ✅ Best practice - using statement
using (var app = Application.Create().Init())
{
using (var view = new View())
{
app.Run(view);
}
}
// ✅ Alternative - explicit try/finally
var app = Application.Create();
try
{
app.Init();
var view = new View();
try
{
app.Run(view);
}
finally
{
view.Dispose();
}
}
finally
{
app.Dispose();
}
```
### SubView Disposal
When a View is disposed, it automatically disposes all SubViews:
```csharp
var container = new View();
var child1 = new View();
var child2 = new View();
container.Add(child1, child2);
// Disposes container, child1, and child2
container.Dispose();
```
See [Resource Management](#disposal-and-resource-management) for complete details.
---
## API Terminology Changes
v2 modernizes terminology for clarity:
### Application.Top → Application.TopRunnable
**v1:**
```csharp
Application.Top.SetNeedsDraw();
```
**v2:**
```csharp
// Use TopRunnable (or TopRunnableView for View reference)
app.TopRunnable?.SetNeedsDraw();
app.TopRunnableView?.SetNeedsDraw();
// From within a view
App?.TopRunnableView?.SetNeedsDraw();
```
**Why "TopRunnable"?**
- Clearly indicates it's the top of the runnable session stack
- Aligns with `IRunnable` architecture
- Works with any `IRunnable`, not just `Toplevel`
### Application.TopLevels → Application.SessionStack
**v1:**
```csharp
foreach (var tl in Application.TopLevels)
{
// Process
}
```
**v2:**
```csharp
foreach (var token in app.SessionStack)
{
var runnable = token.Runnable;
// Process
}
// Count of sessions
int sessionCount = app.SessionStack.Count;
```
**Why "SessionStack"?**
- Describes both content (sessions) and structure (stack)
- Aligns with `SessionToken` terminology
- Follows .NET naming patterns
### View Arrangement
**v1:**
```csharp
view.SendSubViewToBack();
view.SendSubViewBackward();
view.SendSubViewToFront();
view.SendSubViewForward();
```
**v2:**
```csharp
// Fixed naming (methods worked opposite to their names in v1)
view.MoveSubViewToStart();
view.MoveSubViewTowardsStart();
view.MoveSubViewToEnd();
view.MoveSubViewTowardsEnd();
```
### Mdi → ViewArrangement.Overlapped
**v1:**
```csharp
Application.MdiTop = true;
toplevel.IsMdiContainer = true;
```
**v2:**
```csharp
view.Arrangement = ViewArrangement.Overlapped;
// Additional flags
view.Arrangement = ViewArrangement.Movable | ViewArrangement.Resizable;
```
See [Arrangement Deep Dive](arrangement.md) for complete details.
---
## Complete Migration Example
Here's a complete v1 to v2 migration:
**v1:**
```csharp
using NStack;
using Terminal.Gui;
Application.Init();
var win = new Window(new Rect(0, 0, 50, 20), "Hello");
var label = new Label(1, 1, "Name:");
var textField = new TextField(10, 1, 30, "");
var button = new Button(10, 3, "OK");
button.Clicked += () =>
{
MessageBox.Query(50, 7, "Info", $"Hello, {textField.Text}", "Ok");
};
win.Add(label, textField, button);
Application.Top.Add(win);
Application.Run();
Application.Shutdown();
```
**v2:**
```csharp
using System;
using Terminal.Gui;
using (var app = Application.Create().Init())
{
var win = new Window
{
Title = "Hello",
Width = 50,
Height = 20
};
var label = new Label
{
Text = "Name:",
X = 1,
Y = 1
};
var textField = new TextField
{
X = 10,
Y = 1,
Width = 30
};
var button = new Button
{
Text = "OK",
X = 10,
Y = 3
};
button.Accepting += (s, e) =>
{
MessageBox.Query(app, "Info", $"Hello, {textField.Text}", "Ok");
};
win.Add(label, textField, button);
app.Run(win);
win.Dispose();
}
```
---
## Summary of Major Breaking Changes
| Category | v1 | v2 |
|----------|----|----|
| **Application** | Static `Application` | `IApplication` instances via `Application.Create()` |
| **Disposal** | Automatic | Explicit (`IDisposable` pattern) |
| **View Construction** | Constructors with Rect | Initializers with X, Y, Width, Height |
| **Layout** | Absolute/Computed distinction | Unified Pos/Dim system |
| **Colors** | Limited palette | 24-bit TrueColor default |
| **Types** | `Rect`, `NStack.ustring` | `Rectangle`, `System.String` |
| **Keyboard** | `KeyEvent`, hard-coded keys | `Key`, configurable bindings |
| **Mouse** | Screen-relative | Viewport-relative |
| **Scrolling** | `ScrollView` | Built-in on all Views |
| **Focus** | `CanFocus` default true | `CanFocus` default false |
| **Navigation** | `Enter`/`Leave` events | `HasFocusChanging`/`HasFocusChanged` |
| **Events** | Mixed patterns | Standard `EventHandler<EventArgs>` |
| **Terminology** | `Application.Top`, `TopLevels` | `TopRunnable`, `SessionStack` |
---
## Additional Resources
- [Application Deep Dive](application.md) - Complete application architecture
- [View Deep Dive](View.md) - View system details
- [Layout Deep Dive](layout.md) - Comprehensive layout guide
- [Keyboard Deep Dive](keyboard.md) - Keyboard input handling
- [Mouse Deep Dive](mouse.md) - Mouse input handling
- [Navigation Deep Dive](navigation.md) - Focus and navigation
- [Scrolling Deep Dive](scrolling.md) - Built-in scrolling system
- [Arrangement Deep Dive](arrangement.md) - Movable/resizable views
- [Configuration Deep Dive](config.md) - Configuration system
- [What's New in v2](newinv2.md) - New features overview
---
## Getting Help
- [GitHub Discussions](https://github.com/gui-cs/Terminal.Gui/discussions)
- [GitHub Issues](https://github.com/gui-cs/Terminal.Gui/issues)
- [API Documentation](~/api/index.md)