Przeglądaj źródła

Merged with v2_develop

Tig 1 rok temu
rodzic
commit
36503921ca
100 zmienionych plików z 1113 dodań i 939 usunięć
  1. 2 2
      .github/workflows/api-docs.yml
  2. 1 1
      .github/workflows/publish.yml
  3. 5 5
      CONTRIBUTING.md
  4. 0 6
      Directory.Build.props
  5. 0 5
      Directory.Build.targets
  6. 21 20
      Example/Example.cs
  7. 3 0
      FSharpExample/FSharpExample.fsproj
  8. 36 442
      FSharpExample/Program.fs
  9. 122 17
      README.md
  10. 2 2
      Release.ps1
  11. 89 0
      SelfContained/Program.cs
  12. 16 0
      SelfContained/Properties/PublishProfiles/FolderProfile_net8.0_linux-x64_Debug.pubxml
  13. 16 0
      SelfContained/Properties/PublishProfiles/FolderProfile_net8.0_linux-x64_Release.pubxml
  14. 16 0
      SelfContained/Properties/PublishProfiles/FolderProfile_net8.0_osx-x64_Debug.pubxml
  15. 16 0
      SelfContained/Properties/PublishProfiles/FolderProfile_net8.0_osx-x64_Release.pubxml
  16. 17 0
      SelfContained/Properties/PublishProfiles/FolderProfile_net8.0_win-x64_Debug.pubxml
  17. 17 0
      SelfContained/Properties/PublishProfiles/FolderProfile_net8.0_win-x64_Release.pubxml
  18. 9 0
      SelfContained/README.md
  19. 25 0
      SelfContained/SelfContained.csproj
  20. 31 0
      Showcase.md
  21. 11 1
      Terminal.Gui/Application/Application.cs
  22. 3 3
      Terminal.Gui/Configuration/AttributeJsonConverter.cs
  23. 1 1
      Terminal.Gui/Configuration/ColorSchemeJsonConverter.cs
  24. 22 4
      Terminal.Gui/Configuration/ConfigurationManager.cs
  25. 3 3
      Terminal.Gui/Configuration/DictionaryJsonConverter.cs
  26. 1 1
      Terminal.Gui/Configuration/KeyCodeJsonConverter.cs
  27. 13 5
      Terminal.Gui/Configuration/ScopeJsonConverter.cs
  28. 10 1
      Terminal.Gui/Configuration/SettingsScope.cs
  29. 23 0
      Terminal.Gui/Configuration/SourceGenerationContext.cs
  30. 113 0
      Terminal.Gui/Configuration/ThemeManager.cs
  31. 2 0
      Terminal.Gui/ConsoleDrivers/CursesDriver/UnmanagedLibrary.cs
  32. 3 0
      Terminal.Gui/ConsoleDrivers/NetDriver.cs
  33. 3 3
      Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
  34. 3 1
      Terminal.Gui/FileServices/FileDialogStyle.cs
  35. 2 4
      Terminal.Gui/README.md
  36. 5 7
      Terminal.Gui/Terminal.Gui.csproj
  37. 1 1
      Terminal.Gui/Views/Button.cs
  38. 4 4
      Terminal.Gui/Views/Dialog.cs
  39. 1 1
      Terminal.Gui/Views/FrameView.cs
  40. 1 1
      Terminal.Gui/Views/MessageBox.cs
  41. 1 1
      Terminal.Gui/Views/Window.cs
  42. 6 0
      Terminal.sln
  43. 4 80
      UICatalog/Scenario.cs
  44. 1 1
      UICatalog/Scenarios/ASCIICustomButton.cs
  45. 1 1
      UICatalog/Scenarios/Adornments.cs
  46. 1 1
      UICatalog/Scenarios/AllViewsTester.cs
  47. 1 1
      UICatalog/Scenarios/AnimationScenario.cs
  48. 1 1
      UICatalog/Scenarios/Bars.cs
  49. 1 1
      UICatalog/Scenarios/BasicColors.cs
  50. 1 1
      UICatalog/Scenarios/Buttons.cs
  51. 1 1
      UICatalog/Scenarios/ChineseUI.cs
  52. 19 9
      UICatalog/Scenarios/ClassExplorer.cs
  53. 8 12
      UICatalog/Scenarios/Clipping.cs
  54. 13 12
      UICatalog/Scenarios/CollectionNavigatorTester.cs
  55. 1 1
      UICatalog/Scenarios/ColorPicker.cs
  56. 24 24
      UICatalog/Scenarios/CombiningMarks.cs
  57. 13 7
      UICatalog/Scenarios/ComboBoxIteration.cs
  58. 1 1
      UICatalog/Scenarios/ComputedLayout.cs
  59. 1 1
      UICatalog/Scenarios/ContentScrolling.cs
  60. 1 1
      UICatalog/Scenarios/ContextMenus.cs
  61. 1 1
      UICatalog/Scenarios/DatePickers.cs
  62. 1 1
      UICatalog/Scenarios/Dialogs.cs
  63. 1 1
      UICatalog/Scenarios/DimAutoDemo.cs
  64. 1 1
      UICatalog/Scenarios/DynamicMenuBar.cs
  65. 1 1
      UICatalog/Scenarios/DynamicStatusBar.cs
  66. 1 1
      UICatalog/Scenarios/Editor.cs
  67. 36 30
      UICatalog/Scenarios/FileDialogExamples.cs
  68. 1 1
      UICatalog/Scenarios/Generic.cs
  69. 1 1
      UICatalog/Scenarios/HotKeys.cs
  70. 58 52
      UICatalog/Scenarios/Images.cs
  71. 13 4
      UICatalog/Scenarios/InvertColors.cs
  72. 1 1
      UICatalog/Scenarios/KeyBindings.cs
  73. 19 13
      UICatalog/Scenarios/Keys.cs
  74. 1 1
      UICatalog/Scenarios/LineCanvasExperiment.cs
  75. 10 4
      UICatalog/Scenarios/LineDrawing.cs
  76. 7 5
      UICatalog/Scenarios/LineViewExample.cs
  77. 10 9
      UICatalog/Scenarios/ListColumns.cs
  78. 1 1
      UICatalog/Scenarios/ListViewWithSelection.cs
  79. 10 4
      UICatalog/Scenarios/ListsAndCombos.cs
  80. 20 13
      UICatalog/Scenarios/Localization.cs
  81. 1 1
      UICatalog/Scenarios/MenuBarScenario.cs
  82. 1 1
      UICatalog/Scenarios/MessageBoxes.cs
  83. 1 1
      UICatalog/Scenarios/Mouse.cs
  84. 1 1
      UICatalog/Scenarios/MultiColouredTable.cs
  85. 13 5
      UICatalog/Scenarios/ProcessTable.cs
  86. 12 5
      UICatalog/Scenarios/Progress.cs
  87. 1 1
      UICatalog/Scenarios/ProgressBarStyles.cs
  88. 1 1
      UICatalog/Scenarios/Scrolling.cs
  89. 18 12
      UICatalog/Scenarios/SendKeys.cs
  90. 1 1
      UICatalog/Scenarios/ShadowStyles.cs
  91. 1 1
      UICatalog/Scenarios/Shortcuts.cs
  92. 1 1
      UICatalog/Scenarios/Sliders.cs
  93. 8 3
      UICatalog/Scenarios/Snake.cs
  94. 1 1
      UICatalog/Scenarios/SpinnerStyles.cs
  95. 33 27
      UICatalog/Scenarios/Text.cs
  96. 1 1
      UICatalog/Scenarios/TextAlignmentAndDirection.cs
  97. 1 1
      UICatalog/Scenarios/TextFormatterDemo.cs
  98. 13 7
      UICatalog/Scenarios/Threading.cs
  99. 22 12
      UICatalog/Scenarios/TileViewNesting.cs
  100. 19 13
      UICatalog/Scenarios/TimeAndDate.cs

+ 2 - 2
.github/workflows/api-docs.yml

@@ -32,7 +32,7 @@ jobs:
 
     - name: Setup Pages
       if: github.ref_name == 'v1_release' ||  github.ref_name == 'v1_develop'
-      uses: actions/configure-pages@v4
+      uses: actions/configure-pages@v5
       
     - name: Upload artifact
       if: github.ref_name == 'v1_release' ||  github.ref_name == 'v1_develop'
@@ -49,7 +49,7 @@ jobs:
 
     - name: v2_develop Repository Dispatch ${{ github.ref_name }}
       if: github.ref_name == 'v2_develop'
-      uses: peter-evans/repository-dispatch@v2
+      uses: peter-evans/repository-dispatch@v3
       with:
         token: ${{ secrets.V2DOCS_TOKEN }}
         repository: gui-cs/Terminal.GuiV2Docs

+ 1 - 1
.github/workflows/publish.yml

@@ -19,7 +19,7 @@ jobs:
         fetch-depth: 0 # fetch-depth is needed for GitVersion
 
     - name: Install GitVersion 
-      uses: gittools/actions/gitversion/setup@v0
+      uses: gittools/actions/gitversion/setup@v1
       with:
           versionSpec: '5.x'
           includePrerelease: true

+ 5 - 5
CONTRIBUTING.md

@@ -10,8 +10,8 @@ We welcome contributions from the community. See [Issues](https://github.com/gui
 
 Terminal.Gui uses the [GitFlow](https://nvie.com/posts/a-successful-git-branching-model/) branching model. 
 
-* The `main` branch is always stable, and always matches the most recently released Nuget package.
-* The `develop` branch is where new development and bug-fixes happen. It is the default branch.
+* The `v1_release_` and `v2_release` branches are always stable, and always matches the most recently released Nuget package.
+* The `v1__develop` and `v2_develop` branches are where new development and bug-fixes happen. `v2_develop` is the default Github branch.
 
 ### Forking Terminal.Gui
 
@@ -33,11 +33,11 @@ You now have your own fork and a local repo that references it as `origin`. Your
 
 ### Starting to Make a Change
 
-Ensure your local `develop` (for v1) or `v2_develop` (for v2) branch is up-to-date with `upstream` (`github.com/gui-cs/Terminal.Gui`):
+Ensure your local `v1_develop` (for v1) or `v2_develop` (for v2) branch is up-to-date with `upstream` (`github.com/gui-cs/Terminal.Gui`):
 ```powershell
 cd ./Terminal.Gui
-git checkout develop
-git pull upstream develop
+git checkout v2_develop
+git pull upstream v2_develop
 ```
 
 Create a new local branch:

+ 0 - 6
Directory.Build.props

@@ -1,6 +0,0 @@
-<Project>
-  <ItemGroup>
-    <PackageReference Include="JetBrains.Annotations" Version="[2024,)" PrivateAssets="all" />
-    <PackageReference Include="JetBrains.ExternalAnnotations" Version="[10.2.149,)" PrivateAssets="all" />
-  </ItemGroup>
-</Project>

+ 0 - 5
Directory.Build.targets

@@ -1,5 +0,0 @@
-<Project>
-  <PropertyGroup>
-    <DefineConstants>$(DefineConstants);DIMAUTO</DefineConstants>
-  </PropertyGroup>
-</Project>

+ 21 - 20
Example/Example.cs

@@ -6,19 +6,19 @@
 using System;
 using Terminal.Gui;
 
-var app = Application.Run<ExampleWindow> ();
-
-Console.WriteLine ($"Username: {app.UserNameText.Text}");
-
-app.Dispose ();
+Application.Run<ExampleWindow> ().Dispose ();
 
 // Before the application exits, reset Terminal.Gui for clean shutdown
 Application.Shutdown ();
 
+// To see this output on the screen it must be done after shutdown,
+// which restores the previous screen.
+Console.WriteLine ($@"Username: {ExampleWindow.UserName}");
+
 // Defines a top-level window with border and title
 public class ExampleWindow : Window
 {
-    public TextField UserNameText;
+    public static string UserName;
 
     public ExampleWindow ()
     {
@@ -27,7 +27,7 @@ public class ExampleWindow : Window
         // Create input components and labels
         var usernameLabel = new Label { Text = "Username:" };
 
-        UserNameText = new TextField
+        var userNameText = new TextField
         {
             // Position text field adjacent to the label
             X = Pos.Right (usernameLabel) + 1,
@@ -46,7 +46,7 @@ public class ExampleWindow : Window
             Secret = true,
 
             // align with the text box above
-            X = Pos.Left (UserNameText),
+            X = Pos.Left (userNameText),
             Y = Pos.Top (passwordLabel),
             Width = Dim.Fill ()
         };
@@ -64,19 +64,20 @@ public class ExampleWindow : Window
 
         // When login button is clicked display a message popup
         btnLogin.Accept += (s, e) =>
-                            {
-                                if (UserNameText.Text == "admin" && passwordText.Text == "password")
-                                {
-                                    MessageBox.Query ("Logging In", "Login Successful", "Ok");
-                                    Application.RequestStop ();
-                                }
-                                else
-                                {
-                                    MessageBox.ErrorQuery ("Logging In", "Incorrect username or password", "Ok");
-                                }
-                            };
+                           {
+                               if (userNameText.Text == "admin" && passwordText.Text == "password")
+                               {
+                                   MessageBox.Query ("Logging In", "Login Successful", "Ok");
+                                   UserName = userNameText.Text;
+                                   Application.RequestStop ();
+                               }
+                               else
+                               {
+                                   MessageBox.ErrorQuery ("Logging In", "Incorrect username or password", "Ok");
+                               }
+                           };
 
         // Add the views to the Window
-        Add (usernameLabel, UserNameText, passwordLabel, passwordText, btnLogin);
+        Add (usernameLabel, userNameText, passwordLabel, passwordText, btnLogin);
     }
 }

+ 3 - 0
FSharpExample/FSharpExample.fsproj

@@ -13,4 +13,7 @@
   <ItemGroup>
     <ProjectReference Include="..\Terminal.Gui\Terminal.Gui.csproj" />
   </ItemGroup>
+  <ItemGroup>
+    <PackageReference Update="FSharp.Core" Version="8.0.300" />
+  </ItemGroup>
 </Project>

+ 36 - 442
FSharpExample/Program.fs

@@ -1,454 +1,48 @@
-open System
-open System.Diagnostics
-open System.Globalization
-open System.IO
-open NStack
-open Terminal.Gui
+open Terminal.Gui
 
-let ustr (x: string) = ustring.Make(x)
-let mutable ml2 = Unchecked.defaultof<Label>
-let mutable ml = Unchecked.defaultof<Label>
-let mutable menu = Unchecked.defaultof<MenuBar>
-let mutable menuKeysStyle = Unchecked.defaultof<CheckBox>
-let mutable menuAutoMouseNav = Unchecked.defaultof<CheckBox>
-
-type Box10x (x: int, y: int) =
-    inherit View (Rect(x, y, 20, 10))
-    let w = 40
-    let h = 50
-
-    new () =
-        new Box10x ()
-
-    member _.GetContentSize () =
-        Size (w, h)
-
-    member _.SetCursorPosition (_ : Point) =
-        raise (NotImplementedException())
-
-    override this.Redraw (_: Rect) =
-        Application.Driver.SetAttribute this.ColorScheme.Focus
-        do
-        let mutable y = 0
-        while y < h do
-        this.Move (0, y)
-        Application.Driver.AddStr (ustr (string y))
-        do
-        let mutable x = 0
-        while x < w - (y.ToString ()).Length do
-            if (string y).Length < w
-            then Application.Driver.AddStr (ustr " ")
-            x <- x + 1
-        y <- y + 1
-
-type Filler (rect: Rect) =
-    inherit View(rect)
-    new () =
-        new Filler ()
-
-    override this.Redraw (_: Rect) =
-        Application.Driver.SetAttribute this.ColorScheme.Focus
-        let mutable f = this.Frame
-        do
-        let mutable y = 0
-        while y < f.Width do
-        this.Move (0, y)
-        do
-        let mutable x = 0
-        while x < f.Height do
-            let r =
-                match x % 3 with
-                | 0 ->
-                    Application.Driver.AddRune ((Rune ((string y).ToCharArray (0, 1)).[0]))
-                    if y > 9 then
-                        Application.Driver.AddRune ((Rune ((string y).ToCharArray (1, 1)).[0]))
-                    Rune '.'
-                | 1 -> Rune 'o'
-                | _ -> Rune 'O'
-            Application.Driver.AddRune r
-            x <- x + 1
-        y <- y + 1
-
-let ShowTextAlignments () =
-    let okButton = new Button (ustr "Ok", true)
-    okButton.add_Clicked (Action (Application.RequestStop))
-    let cancelButton = new Button (ustr "Cancel", true)
-    cancelButton.add_Clicked (Action (Application.RequestStop))
-
-    let container = new Dialog (ustr "Text Alignments", 50, 20, okButton, cancelButton)
-    let txt = "Hello world, how are you doing today"
-    container.Add (
-        new Label (Rect(0, 1, 40, 3), ustr ((sprintf "%O-%O" 1) txt), TextAlignment = TextAlignment.Left),
-        new Label (Rect(0, 3, 40, 3), ustr ((sprintf "%O-%O" 2) txt), TextAlignment = TextAlignment.Right),
-        new Label (Rect(0, 5, 40, 3), ustr ((sprintf "%O-%O" 3) txt), TextAlignment = TextAlignment.Centered),
-        new Label (Rect(0, 7, 40, 3), ustr ((sprintf "%O-%O" 4) txt), TextAlignment = TextAlignment.Justified))
-    Application.Run container
-
-let ShowEntries (container: View) =
-    let scrollView = 
-        new ScrollView (Rect (50, 10, 20, 8),
-            ContentSize = Size (20, 50),
-            ShowVerticalScrollIndicator = true,
-            ShowHorizontalScrollIndicator = true)
-    scrollView.Add (new Filler (Rect (0, 0, 40, 40)))
-    let scrollView2 = 
-        new ScrollView (Rect (72, 10, 3, 3),
-            ContentSize = Size (100, 100),
-            ShowVerticalScrollIndicator = true,
-            ShowHorizontalScrollIndicator = true)
-    scrollView2.Add (new Box10x (0, 0))
-    let progress = new ProgressBar (Rect(68, 1, 10, 1))
-    let timer = Func<MainLoop, bool> (fun _ ->
-        progress.Pulse ()
-        true)
-
-    Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (300.), timer) |> ignore
-
-    let login =
-        new Label (ustr "Login: ",
-            X = Pos.At 3,
-            Y = Pos.At 6)
-    let password =
-        new Label (ustr "Password: ",
-            X = Pos.Left login,
-            Y = Pos.Bottom login + Pos.At 1)
-    let loginText =
-        new TextField (ustr "",
-            X = Pos.Right password,
-            Y = Pos.Top login,
-            Width = Dim.op_Implicit 40)
-    let passText =
-        new TextField (ustr "",
-            Secret = true,
-            X = Pos.Left loginText,
-            Y = Pos.Top password,
-            Width = Dim.Width loginText)
-    let tf = new Button (3, 19, ustr "Ok")
-    container.Add (login, loginText, password, passText,
-        new FrameView (Rect (3, 10, 25, 6), ustr "Options",
-            [| new CheckBox (1, 0, ustr "Remember me")
-               new RadioGroup (1, 2, 
-                [| ustr "_Personal"; ustr "_Company"|])|]),
-        new ListView (Rect (59, 6, 16, 4),
-                [| "First row"
-                   "<>"
-                   "This is a very long row that should overflow what is shown"
-                   "4th"
-                   "There is an empty slot on the second row"
-                   "Whoa"
-                   "This is so cool" |]),
-        scrollView, scrollView2, tf,
-        new Button (10, 19, ustr "Cancel"),
-        new TimeField (3, 20, DateTime.Now.TimeOfDay),
-        new TimeField (23, 20, DateTime.Now.TimeOfDay, true),
-        new DateField (3, 22, DateTime.Now),
-        new DateField (23, 22, DateTime.Now, true),
-        progress,
-        new Label (3, 24, ustr "Press F9 (on Unix, ESC+9 is an alias) to activate the menubar"),
-        menuKeysStyle,
-        menuAutoMouseNav)
-    container.SendSubviewToBack tf
-
-let NewFile () =
-    let okButton = new Button (ustr "Ok", true)
-    okButton.add_Clicked (Action (Application.RequestStop))
-    let cancelButton = new Button (ustr "Cancel", true)
-    cancelButton.add_Clicked (Action (Application.RequestStop))
-
-    let d = new Dialog (ustr "New File", 50, 20, okButton, cancelButton)
-    ml2 <- new Label (1, 1, ustr "Mouse Debug Line")
-    d.Add ml2
-    Application.Run d
-
-let GetFileName () =
-    let mutable fname = Unchecked.defaultof<_>
-    for s in [| "/etc/passwd"; "c:\\windows\\win.ini" |] do
-        if File.Exists s
-        then fname <- s
-    fname
-
-let Editor (top: Toplevel) =
-    let tframe = top.Frame
-    let ntop = new Toplevel(tframe)
-    let menu = 
-        new MenuBar(
-            [| MenuBarItem (ustr "_File",
-                 [| MenuItem (ustr "_Close", ustring.Empty, (fun () -> Application.RequestStop ())) |]);
-                    MenuBarItem (ustr "_Edit",
-                        [| MenuItem (ustr "_Copy", ustring.Empty, Unchecked.defaultof<_>)
-                           MenuItem (ustr "C_ut", ustring.Empty, Unchecked.defaultof<_>)
-                           MenuItem (ustr "_Paste", ustring.Empty, Unchecked.defaultof<_>) |]) |])
-    ntop.Add menu
-    let fname = GetFileName ()
-    let win = 
-        new Window (
-            ustr (if not (isNull fname) then fname else "Untitled"),
-            X = Pos.At 0,
-            Y = Pos.At 1,
-            Width = Dim.Fill (),
-            Height = Dim.Fill ())
-    ntop.Add win
-    let text = new TextView (Rect(0, 0, (tframe.Width - 2), (tframe.Height - 3)))
-    if fname <> Unchecked.defaultof<_>
-    then text.Text <- ustr (File.ReadAllText fname)
-    win.Add text
-    Application.Run ntop
-
-let Quit () =
-    MessageBox.Query (50, 7, ustr "Quit Demo", ustr "Are you sure you want to quit this demo?", ustr "Yes", ustr "No") = 0
-
-let Close () =
-    MessageBox.ErrorQuery (50, 7, ustr "Error", ustr "There is nothing to close", ustr "Ok")
-    |> ignore
-
-let Open () =
-    let d = new OpenDialog (ustr "Open", ustr "Open a file", AllowsMultipleSelection = true)
-    Application.Run d
-    if not d.Canceled
-        then MessageBox.Query (50, 7, ustr "Selected File", ustr (String.Join (", ", d.FilePaths)), ustr "Ok") |> ignore
-
-let ShowHex (top: Toplevel) =
-    let tframe = top.Frame
-    let ntop = new Toplevel (tframe)
-    let menu = 
-        new MenuBar (
-            [| MenuBarItem (ustr "_File",
-                 [| MenuItem (ustr "_Close", ustring.Empty, (fun () -> Application.RequestStop ())) |]) |])
-    ntop.Add menu
-    let win =
-        new Window (ustr "/etc/passwd",
-            X = Pos.At 0,
-            Y = Pos.At 1,
-            Width = Dim.Fill (),
-            Height = Dim.Fill ())
-    ntop.Add win
-    let fname = GetFileName ()
-    let source = File.OpenRead fname
-    let hex = 
-        new HexView (source,
-            X = Pos.At 0,
-            Y = Pos.At 0,
-            Width = Dim.Fill (),
-            Height = Dim.Fill ())
-    win.Add hex
-    Application.Run ntop
-
-type MenuItemDetails () =
-    inherit MenuItem ()
-    new (title: ustring, help: ustring, action: Action) as this =
-        MenuItemDetails ()
-        then
-            this.Title <- title
-            this.Help <- help
-            this.Action <- action
-
-    static member Instance (mi: MenuItem) =
-        (mi.GetMenuItem ()) :?> MenuItemDetails
-
-type MenuItemDelegate = delegate of MenuItemDetails -> MenuItem
-
-let ShowMenuItem (mi: MenuItemDetails) =
-    MessageBox.Query (70, 7, ustr (mi.Title.ToString ()),
-        ustr ((sprintf "%O selected. Is from submenu: %O" (mi.Title.ToString ())) (mi.GetMenuBarItem ())), ustr "Ok")
-    |> ignore
-
-let MenuKeysStyleToggled (_: bool) =
-    menu.UseKeysUpDownAsKeysLeftRight <- menuKeysStyle.Checked
-
-let MenuAutoMouseNavToggled (_: bool) =
-    menu.WantMousePositionReports <- menuAutoMouseNav.Checked
-
-let Copy () =
-    let textField = menu.LastFocused :?> TextField
-    if textField <> Unchecked.defaultof<_> && textField.SelectedLength <> 0
-    then textField.Copy ()
+type ExampleWindow() as this =
+    inherit Window()
+    
+    do
+        this.Title <- sprintf "Example App (%O to quit)" Application.QuitKey
 
-let Cut () =
-    let textField = menu.LastFocused :?> TextField
-    if textField <> Unchecked.defaultof<_> && textField.SelectedLength <> 0
-    then textField.Cut ()
+        // Create input components and labels
+        let usernameLabel = new Label(Text = "Username:")
 
-let Paste () =
-    let textField = menu.LastFocused :?> TextField
-    if textField <> Unchecked.defaultof<_>
-    then textField.Paste ()
+        let userNameText = new TextField(X = Pos.Right(usernameLabel) + Pos.op_Implicit(1), Width = Dim.Fill())
 
-let Help () =
-    MessageBox.Query (50, 7, ustr "Help", ustr "This is a small help\nBe kind.", ustr "Ok")
-    |> ignore
+        let passwordLabel = new Label(Text = "Password:", X = Pos.Left(usernameLabel), Y = Pos.Bottom(usernameLabel) +  Pos.op_Implicit(1))
 
-let Load () =
-    MessageBox.Query (50, 7, ustr "Load", ustr "This is a small load\nBe kind.", ustr "Ok")
-    |> ignore
+        let passwordText = new TextField(Secret = true, X = Pos.Left(userNameText), Y = Pos.Top(passwordLabel), Width = Dim.Fill())
 
-let Save () =
-    MessageBox.Query (50, 7, ustr "Save ", ustr "This is a small save\nBe kind.", ustr "Ok")
-    |> ignore
+        // Create login button
+        let btnLogin = new Button(Text = "Login", Y = Pos.Bottom(passwordLabel) +  Pos.op_Implicit(1), X = Pos.Center(), IsDefault = true)
 
-let ListSelectionDemo (multiple: bool) =
-    let okButton = new Button (ustr "Ok", true)
-    okButton.add_Clicked (Action (Application.RequestStop))
-    let cancelButton = new Button (ustr "Cancel")
-    cancelButton.add_Clicked (Action (Application.RequestStop))
+        // When login button is clicked display a message popup
+        btnLogin.Accept.Add(fun _ ->
+            if userNameText.Text = "admin" && passwordText.Text = "password" then
+                MessageBox.Query("Logging In", "Login Successful", "Ok") |> ignore
+                ExampleWindow.UserName <- userNameText.Text.ToString()
+                Application.RequestStop()
+            else
+                MessageBox.ErrorQuery("Logging In", "Incorrect username or password", "Ok") |> ignore
+        )
 
-    let d = new Dialog (ustr "Selection Demo", 60, 20, okButton, cancelButton)
-    let animals = ResizeArray<_> ()
-    animals.AddRange([| "Alpaca"; "Llama"; "Lion"; "Shark"; "Goat" |])
-    let msg =
-        new Label (ustr "Use space bar or control-t to toggle selection",
-            X = Pos.At 1,
-            Y = Pos.At 1,
-            Width = Dim.Fill () - Dim.op_Implicit 1,
-            Height = Dim.op_Implicit 1)
-    let list =
-        new ListView (animals,
-            X = Pos.At 1,
-            Y = Pos.At 3,
-            Width = Dim.Fill () - Dim.op_Implicit 4,
-            Height = Dim.Fill () - Dim.op_Implicit 4,
-            AllowsMarking = true,
-            AllowsMultipleSelection = multiple)
-    d.Add (msg, list)
-    Application.Run d
-    let mutable result = ""
-    do
-        let mutable i = 0
-        while i < animals.Count do
-        if list.Source.IsMarked i
-        then result <- result + animals.[i] + " "
-        i <- i + 1
-    MessageBox.Query (60, 10, ustr "Selected Animals", ustr (if result = "" then "No animals selected" else result), ustr "Ok") |> ignore
+        // Add the views to the Window
+        this.Add(usernameLabel, userNameText, passwordLabel, passwordText, btnLogin)
 
-let OnKeyDownPressUpDemo () =
-    let closeButton = new Button (ustr "Close")
-    closeButton.add_Clicked (Action (Application.RequestStop))
+    static member val UserName = "" with get, set
 
-    let container = new Dialog (ustr "KeyDown & KeyPress & KeyUp demo", 80, 20, closeButton, Width = Dim.Fill (), Height = Dim.Fill ())
+[<EntryPoint>]
+let main argv =
+    Application.Init()
+    Application.Run<ExampleWindow>().Dispose()
     
-    let list = ResizeArray<_> ()
-    let listView = 
-        new ListView (list,
-            X = Pos.At 0,
-            Y = Pos.At 0,
-            Width = Dim.Fill () - Dim.op_Implicit 1,
-            Height = Dim.Fill () - Dim.op_Implicit 2,
-            ColorScheme = Colors.TopLevel)
-    container.Add (listView)
+    // Before the application exits, reset Terminal.Gui for clean shutdown
+    Application.Shutdown()
     
-    let keyDownPressUp (keyEvent: KeyEvent, updown: string) =
-        match updown with
-        | "Down"
-        | "Up"
-        | "Press" -> 
-            list.Add (keyEvent.ToString ())    
-        | _ -> failwithf "Unknown: %s" updown
-        listView.MoveDown ()
-
-    container.add_KeyDown(Action<View.KeyEventEventArgs> (fun (e: View.KeyEventEventArgs) -> keyDownPressUp (e.KeyEvent, "Down") |> ignore))
-    container.add_KeyPress(Action<View.KeyEventEventArgs> (fun (e: View.KeyEventEventArgs) -> keyDownPressUp (e.KeyEvent, "Press") |> ignore))
-    container.add_KeyUp(Action<View.KeyEventEventArgs> (fun (e: View.KeyEventEventArgs) -> keyDownPressUp (e.KeyEvent, "Up") |> ignore))
-    Application.Run (container)
-
-let Main () =
-    if Debugger.IsAttached then
-        CultureInfo.DefaultThreadCurrentUICulture <- CultureInfo.GetCultureInfo ("en-US")
-    Application.Init()
-    let top = Application.Top
-    let margin = 3
-    let win = 
-        new Window (ustr "Hello",
-            X = Pos.At 1,
-            Y = Pos.At 1,
-            Width = Dim.Fill () - Dim.op_Implicit margin,
-            Height = Dim.Fill () - Dim.op_Implicit margin)
-    let menuItems =
-        [|MenuItemDetails (ustr "F_ind",ustr "", Unchecked.defaultof<_>);
-            MenuItemDetails (ustr "_Replace", ustr "", Unchecked.defaultof<_>);
-            MenuItemDetails (ustr "_Item1", ustr "", Unchecked.defaultof<_>);
-            MenuItemDetails (ustr "_Also From Sub Menu", ustr "", Unchecked.defaultof<_>)|]
-    menuItems.[0].Action <- fun _ -> ShowMenuItem (menuItems.[0])
-    menuItems.[1].Action <- fun _ -> ShowMenuItem (menuItems.[1])
-    menuItems.[2].Action <- fun _ -> ShowMenuItem (menuItems.[2])
-    menuItems.[3].Action <- fun _ -> ShowMenuItem (menuItems.[3])
-    menu <-
-        new MenuBar (
-            [| MenuBarItem(ustr "_File",
-                    [| MenuItem (ustr "Text _Editor Demo", ustring.Empty, (fun () -> Editor top))
-                       MenuItem (ustr "_New", ustr "Creates new file", fun () -> NewFile())
-                       MenuItem (ustr "_Open", ustring.Empty, fun () -> Open())
-                       MenuItem (ustr "_Hex", ustring.Empty, (fun () -> ShowHex top))
-                       MenuItem (ustr "_Close", ustring.Empty, (fun () -> Close()))
-                       MenuItem (ustr "_Disabled", ustring.Empty, (fun () -> ()), (fun () -> false))
-                       Unchecked.defaultof<_>
-                       MenuItem (ustr "_Quit", ustring.Empty, (fun () -> if Quit() then top.Running <- false)) |])
-               MenuBarItem (ustr "_Edit",
-                    [| MenuItem (ustr "_Copy", ustring.Empty, fun () -> Copy())
-                       MenuItem (ustr "C_ut", ustring.Empty, fun () -> Cut())
-                       MenuItem (ustr "_Paste", ustring.Empty, fun () -> Paste())
-                       MenuBarItem (ustr "_Find and Replace",
-                           [| menuItems.[0] :> MenuItem
-                              menuItems.[1] :> MenuItem |]) :> MenuItem
-                       menuItems.[3] :> MenuItem
-                    |])
-               MenuBarItem (ustr "_List Demos", 
-                    [| MenuItem (ustr "Select _Multiple Items", ustring.Empty, (fun () -> ListSelectionDemo true))
-                       MenuItem (ustr "Select _Single Item", ustring.Empty, (fun () -> ListSelectionDemo false)) |])   
-               MenuBarItem (ustr "A_ssorted",
-                    [| MenuItem (ustr "_Show text alignments", ustring.Empty, (fun () -> ShowTextAlignments())) 
-                       MenuItem (ustr "_OnKeyDown/Press/Up", ustring.Empty, (fun () -> OnKeyDownPressUpDemo())) |])
-               MenuBarItem (ustr "_Test Menu and SubMenus",
-                    [| MenuBarItem (ustr "SubMenu1Item_1",
-                            [| MenuBarItem (ustr "SubMenu2Item_1",
-                                    [| MenuBarItem (ustr "SubMenu3Item_1",
-                                            [| menuItems.[2] :> MenuItem |]) :> MenuItem
-                                    |]) :> MenuItem
-                            |]) :> MenuItem
-                    |])
-               MenuBarItem (ustr "_About...", ustr "Demonstrates top-level menu item", (fun () -> MessageBox.ErrorQuery (50, 7, ustr "Error", ustr "This is a demo app for gui.cs", ustr "Ok") |> ignore)) |])
-    menuKeysStyle <- new CheckBox (3, 25, ustr "UseKeysUpDownAsKeysLeftRight", true)
-    menuKeysStyle.add_Toggled (Action<bool> (MenuKeysStyleToggled))
-    menuAutoMouseNav <- new CheckBox (40, 25, ustr "UseMenuAutoNavigation", true)
-    menuAutoMouseNav.add_Toggled (Action<bool> (MenuAutoMouseNavToggled))
-    ShowEntries win
-    let mutable count = 0
-    ml <- new Label (Rect (3, 17, 47, 1), ustr "Mouse: ")
-    Application.RootMouseEvent <- Action<MouseEvent> (
-            fun (me: MouseEvent) ->
-                ml.Text <- ustr (
-                     (((sprintf "Mouse: (%O,%O) - %O %O" me.X) me.Y) me.Flags) (count <- count + 1; count)))
-    let test = new Label (3, 18, ustr "Se iniciará el análisis")
-    win.Add test
-    win.Add ml
-    let drag = new Label (ustr "Drag: ", X = Pos.At 70, Y = Pos.At 24)
-    let dragText = 
-        new TextField (ustr "",
-            X = Pos.Right drag,
-            Y = Pos.Top drag,
-            Width = Dim.op_Implicit 40)
-    let statusBar = new StatusBar ([|
-        StatusItem(Key.F1, ustr "~F1~ Help", Action Help)
-        StatusItem(Key.F2, ustr "~F2~ Load", Action Load)
-        StatusItem(Key.F3, ustr "~F3~ Save", Action Save)
-        StatusItem(Key.Q, ustr "~^Q~ Quit", fun () -> if (Quit()) then top.Running <- false) |])
-    win.Add (drag, dragText)
-    let bottom = new Label (ustr "This should go on the bottom of the same top-level!")
-    win.Add bottom
-    let bottom2 = new Label (ustr "This should go on the bottom of another top-level!")
-    top.Add bottom2
-    top.add_LayoutComplete (Action<View.LayoutEventArgs>
-        (fun e ->
-            bottom.X <- win.X
-            bottom.Y <- Pos.Bottom win - Pos.Top win - Pos.At margin
-            bottom2.X <- Pos.Left win
-            bottom2.Y <- Pos.Bottom win)
-        )
-    top.Add win
-    top.Add (menu, statusBar)
-    Application.Run ()
-    Application.Shutdown ();
-
-module Demo =
-    [<EntryPoint>]
-    let main _ =
-        Main ()
-        0
+    // To see this output on the screen it must be done after shutdown,
+    // which restores the previous screen.
+    printfn "Username: %s" ExampleWindow.UserName
+    
+    0 // return an integer exit code

+ 122 - 17
README.md

@@ -1,17 +1,16 @@
 ![Terminal.Gui](https://socialify.git.ci/gui-cs/Terminal.Gui/image?description=1&font=Rokkitt&forks=1&language=1&logo=https%3A%2F%2Fraw.githubusercontent.com%2Fgui-cs%2FTerminal.Gui%2Fdevelop%2Fdocfx%2Fimages%2Flogo.png&name=1&owner=1&pattern=Circuit%20Board&stargazers=1&theme=Auto)
 ![.NET Core](https://github.com/gui-cs/Terminal.Gui/workflows/.NET%20Core/badge.svg?branch=develop)
-![Code scanning - action](https://github.com/gui-cs/Terminal.Gui/workflows/Code%20scanning%20-%20action/badge.svg)
 [![Version](https://img.shields.io/nuget/v/Terminal.Gui.svg)](https://www.nuget.org/packages/Terminal.Gui)
 ![Code Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/migueldeicaza/90ef67a684cb71db1817921a970f8d27/raw/code-coverage.json)
 [![Downloads](https://img.shields.io/nuget/dt/Terminal.Gui)](https://www.nuget.org/packages/Terminal.Gui)
 [![License](https://img.shields.io/github/license/gui-cs/gui.cs.svg)](LICENSE)
 ![Bugs](https://img.shields.io/github/issues/gui-cs/gui.cs/bug)
 
-***The current, stable, release of Terminal.Gui is [v1.x](https://www.nuget.org/packages/Terminal.Gui). It is stable, rich, and broadly used. The team is now focused on designing and building a significant upgrade we're referring to as `v2`. Therefore:***
- * *`v1` is now in maintenance mode, meaning we will accept PRs for v1.x (the `develop` branch) only for issues impacting existing functionality.*
- * *All new development happens on the `v2_develop` branch. See the V2 discussion [here](https://github.com/gui-cs/Terminal.GuiV2Docs/discussions/1940).*
- * *Developers are encouraged to continue building on [v1.x](https://www.nuget.org/packages/Terminal.Gui) until we announce `v2` is stable.*
-
+* The current, stable, release of Terminal.Gui v1 is [![Version](https://img.shields.io/nuget/v/Terminal.Gui.svg)](https://www.nuget.org/packages/Terminal.Gui).
+* The current `prealpha` release of Terminal.Gui v2 can be found on [Nuget](https://www.nuget.org/packages/Terminal.Gui).
+* Developers starting new TUI projects are encouraged to target `v2`. The API is signifcantly changed, and significantly improved. There will be breaking changes in the API before Beta, but the core API is stable.
+* `v1` is in maintenance mode and we will only accept PRs for issues impacting existing functionality.
+ 
 **Terminal.Gui**: A toolkit for building rich console apps for .NET, .NET Core, and Mono that works on Windows, the Mac, and Linux/Unix.
 
 ![Sample app](docfx/images/sample.gif)
@@ -36,23 +35,129 @@ dotnet run
 * [API Documentation](https://gui-cs.github.io/Terminal.GuiV2Docs/api/Terminal.Gui.html)
 * [Documentation Home](https://gui-cs.github.io/Terminal.GuiV2Docs)
 
+_The Documentation matches the most recent Nuget release from the `v2_develop` branch. The documentation for v1 is here: ([![Version](https://img.shields.io/nuget/v/Terminal.Gui.svg)](https://www.nuget.org/packages/Terminal.Gui))_
+
+See the [`Terminal.Gui/` README](https://github.com/gui-cs/Terminal.Gui/tree/master/Terminal.Gui) for an overview of how the library is structured. 
+
 ## Showcase & Examples
 
-* **[UI Catalog](https://github.com/gui-cs/Terminal.GuiV2Docs/tree/master/UICatalog)** - The UI Catalog project provides an easy to use and extend sample illustrating the capabilities of **Terminal.Gui**. Run `dotnet run --project UICatalog` to run the UI Catalog.
-* **[C# Example](https://github.com/gui-cs/Terminal.GuiV2Docs/tree/master/Example)** - Run `dotnet run` in the `Example` directory to run the C# Example.
-* **[F# Example](https://github.com/gui-cs/Terminal.GuiV2Docs/tree/master/FSharpExample)** - An example showing how to build a Terminal.Gui app using F#.
-* **[Reactive Example](https://github.com/gui-cs/Terminal.GuiV2Docs/tree/master/ReactiveExample)** - A sample app that shows how to use `System.Reactive` and `ReactiveUI` with `Terminal.Gui`. The app uses the MVVM architecture that may seem familiar to folks coming from WPF, Xamarin Forms, UWP, Avalonia, or Windows Forms. In this app, we implement the data bindings using ReactiveUI `WhenAnyValue` syntax and [Pharmacist](https://github.com/reactiveui/pharmacist) — a tool that converts all events in a NuGet package into observable wrappers.
-* **[PowerShell's `Out-ConsoleGridView`](https://github.com/PowerShell/GraphicalTools)** - `OCGV` sends the output from a command to an interactive table. 
-* **[F7History](https://github.com/gui-cs/F7History)** - Graphical Command History for PowerShell (built on PowerShell's `Out-ConsoleGridView`).
-* **[PoshRedisViewer](https://github.com/En3Tho/PoshRedisViewer)** - A compact Redis viewer module for PowerShell written in F#.
-* **[PoshDotnetDumpAnalyzeViewer](https://github.com/En3Tho/PoshDotnetDumpAnalyzeViewer)** - dotnet-dump UI module for PowerShell.
-* **[TerminalGuiDesigner](https://github.com/tznind/TerminalGuiDesigner)** - Cross platform view designer for building Terminal.Gui applications.
+**Terminal.Gui** can be used with any .Net language to create feature rich and robust applications.  
+[Showcase](https://github.com/gui-cs/Terminal.Gui/blob/develop/Showcase.md) is a place where you can find all kind of projects from simple examples to advanced real world apps that fully utilize capabilities of the toolkit.  
+The team is looking forward to seeing new amazing projects made by the community to be added there!
+
+## Sample Usage in C#
+
+The following example shows a basic Terminal.Gui application in C#:
+
+```csharp
+// This is a simple example application.  For the full range of functionality
+// see the UICatalog project
+
+// A simple Terminal.Gui example in C# - using C# 9.0 Top-level statements
+
+using System;
+using Terminal.Gui;
+
+Application.Run<ExampleWindow> ().Dispose ();
+
+// Before the application exits, reset Terminal.Gui for clean shutdown
+Application.Shutdown ();
+
+// To see this output on the screen it must be done after shutdown,
+// which restores the previous screen.
+Console.WriteLine ($@"Username: {ExampleWindow.UserName}");
+
+// Defines a top-level window with border and title
+public class ExampleWindow : Window
+{
+    public static string UserName;
+
+    public ExampleWindow ()
+    {
+        Title = $"Example App ({Application.QuitKey} to quit)";
+
+        // Create input components and labels
+        var usernameLabel = new Label { Text = "Username:" };
+
+        var userNameText = new TextField
+        {
+            // Position text field adjacent to the label
+            X = Pos.Right (usernameLabel) + 1,
+
+            // Fill remaining horizontal space
+            Width = Dim.Fill ()
+        };
+
+        var passwordLabel = new Label
+        {
+            Text = "Password:", X = Pos.Left (usernameLabel), Y = Pos.Bottom (usernameLabel) + 1
+        };
+
+        var passwordText = new TextField
+        {
+            Secret = true,
+
+            // align with the text box above
+            X = Pos.Left (userNameText),
+            Y = Pos.Top (passwordLabel),
+            Width = Dim.Fill ()
+        };
+
+        // Create login button
+        var btnLogin = new Button
+        {
+            Text = "Login",
+            Y = Pos.Bottom (passwordLabel) + 1,
+
+            // center the login button horizontally
+            X = Pos.Center (),
+            IsDefault = true
+        };
+
+        // When login button is clicked display a message popup
+        btnLogin.Accept += (s, e) =>
+                           {
+                               if (userNameText.Text == "admin" && passwordText.Text == "password")
+                               {
+                                   MessageBox.Query ("Logging In", "Login Successful", "Ok");
+                                   UserName = userNameText.Text;
+                                   Application.RequestStop ();
+                               }
+                               else
+                               {
+                                   MessageBox.ErrorQuery ("Logging In", "Incorrect username or password", "Ok");
+                               }
+                           };
+
+        // Add the views to the Window
+        Add (usernameLabel, userNameText, passwordLabel, passwordText, btnLogin);
+    }
+}
+```
+
+When run the application looks as follows:
+
+![Simple Usage app](./docfx/images/Example.png)
+
+## Installing
+
+Use NuGet to install the `Terminal.Gui` NuGet package: https://www.nuget.org/packages/Terminal.Gui
+
+### Installation in .NET Core Projects
+
+To install Terminal.Gui into a .NET Core project, use the `dotnet` CLI tool with this command.
+
+```
+dotnet add package Terminal.Gui
+```
+
+Or, you can use the [Terminal.Gui.Templates](https://github.com/gui-cs/Terminal.Gui.templates).
 
 ## Contributing
 
-See [CONTRIBUTING.md](https://github.com/gui-cs/Terminal.GuiV2Docs/blob/master/CONTRIBUTING.md).
+See [CONTRIBUTING.md](./CONTRIBUTING.md).
 
-Debates on architecture and design can be found in Issues tagged with [design](https://github.com/gui-cs/Terminal.GuiV2Docs/issues?q=is%3Aopen+is%3Aissue+label%3Adesign).
+Debates on architecture and design can be found in Issues tagged with [design](https://github.com/gui-cs/Terminal.Gui/issues?q=is%3Aopen+is%3Aissue+label%3Av2+label%3Adesign).
 
 ## History
 

+ 2 - 2
Release.ps1

@@ -5,8 +5,8 @@ param(
     [int]$Version
 )
 
-$branch = "v2_develop"
-$tag = "v2.0.0-alpha.$Version"
+$branch = "v2_release"
+$tag = "$Version-prealpha"
 $releaseMessage = "Release $tag"
 
 try {

+ 89 - 0
SelfContained/Program.cs

@@ -0,0 +1,89 @@
+// This is a simple example application for a self-contained single file.
+
+using System.Diagnostics.CodeAnalysis;
+using Terminal.Gui;
+
+namespace SelfContained;
+
+public static class Program
+{
+    [RequiresUnreferencedCode ("Calls Terminal.Gui.Application.Run<T>(Func<Exception, Boolean>, ConsoleDriver)")]
+    private static void Main (string [] args)
+    {
+        Application.Run<ExampleWindow> ().Dispose ();
+
+        // Before the application exits, reset Terminal.Gui for clean shutdown
+        Application.Shutdown ();
+
+        // To see this output on the screen it must be done after shutdown,
+        // which restores the previous screen.
+        Console.WriteLine ($@"Username: {ExampleWindow.UserName}");
+    }
+}
+
+// Defines a top-level window with border and title
+public class ExampleWindow : Window
+{
+    public static string? UserName;
+
+    public ExampleWindow ()
+    {
+        Title = $"Example App ({Application.QuitKey} to quit)";
+
+        // Create input components and labels
+        var usernameLabel = new Label { Text = "Username:" };
+
+        var userNameText = new TextField
+        {
+            // Position text field adjacent to the label
+            X = Pos.Right (usernameLabel) + 1,
+
+            // Fill remaining horizontal space
+            Width = Dim.Fill ()
+        };
+
+        var passwordLabel = new Label
+        {
+            Text = "Password:", X = Pos.Left (usernameLabel), Y = Pos.Bottom (usernameLabel) + 1
+        };
+
+        var passwordText = new TextField
+        {
+            Secret = true,
+
+            // align with the text box above
+            X = Pos.Left (userNameText),
+            Y = Pos.Top (passwordLabel),
+            Width = Dim.Fill ()
+        };
+
+        // Create login button
+        var btnLogin = new Button
+        {
+            Text = "Login",
+            Y = Pos.Bottom (passwordLabel) + 1,
+
+            // center the login button horizontally
+            X = Pos.Center (),
+            IsDefault = true
+        };
+
+        // When login button is clicked display a message popup
+        btnLogin.Accept += (s, e) =>
+                           {
+                               if (userNameText.Text == "admin" && passwordText.Text == "password")
+                               {
+                                   MessageBox.Query ("Logging In", "Login Successful", "Ok");
+                                   UserName = userNameText.Text;
+                                   Application.RequestStop ();
+                               }
+                               else
+                               {
+                                   MessageBox.ErrorQuery ("Logging In", "Incorrect username or password", "Ok");
+                               }
+                           };
+
+        // Add the views to the Window
+        Add (usernameLabel, userNameText, passwordLabel, passwordText, btnLogin);
+    }
+}

+ 16 - 0
SelfContained/Properties/PublishProfiles/FolderProfile_net8.0_linux-x64_Debug.pubxml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+  <PropertyGroup>
+    <Configuration>Debug</Configuration>
+    <Platform>Any CPU</Platform>
+    <PublishDir>bin\Debug\net8.0\publish\linux-x64\</PublishDir>
+    <PublishProtocol>FileSystem</PublishProtocol>
+    <_TargetId>Folder</_TargetId>
+    <TargetFramework>net8.0</TargetFramework>
+    <RuntimeIdentifier>linux-x64</RuntimeIdentifier>
+    <SelfContained>true</SelfContained>
+  </PropertyGroup>
+</Project>

+ 16 - 0
SelfContained/Properties/PublishProfiles/FolderProfile_net8.0_linux-x64_Release.pubxml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+  <PropertyGroup>
+    <Configuration>Release</Configuration>
+    <Platform>Any CPU</Platform>
+    <PublishDir>bin\Release\net8.0\publish\linux-x64\</PublishDir>
+    <PublishProtocol>FileSystem</PublishProtocol>
+    <_TargetId>Folder</_TargetId>
+    <TargetFramework>net8.0</TargetFramework>
+    <RuntimeIdentifier>linux-x64</RuntimeIdentifier>
+    <SelfContained>true</SelfContained>
+  </PropertyGroup>
+</Project>

+ 16 - 0
SelfContained/Properties/PublishProfiles/FolderProfile_net8.0_osx-x64_Debug.pubxml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+  <PropertyGroup>
+    <Configuration>Debug</Configuration>
+    <Platform>Any CPU</Platform>
+    <PublishDir>bin\Debug\net8.0\publish\osx-x64\</PublishDir>
+    <PublishProtocol>FileSystem</PublishProtocol>
+    <_TargetId>Folder</_TargetId>
+    <TargetFramework>net8.0</TargetFramework>
+    <RuntimeIdentifier>osx-x64</RuntimeIdentifier>
+    <SelfContained>true</SelfContained>
+  </PropertyGroup>
+</Project>

+ 16 - 0
SelfContained/Properties/PublishProfiles/FolderProfile_net8.0_osx-x64_Release.pubxml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+  <PropertyGroup>
+    <Configuration>Release</Configuration>
+    <Platform>Any CPU</Platform>
+    <PublishDir>bin\Release\net8.0\publish\osx-x64\</PublishDir>
+    <PublishProtocol>FileSystem</PublishProtocol>
+    <_TargetId>Folder</_TargetId>
+    <TargetFramework>net8.0</TargetFramework>
+    <RuntimeIdentifier>osx-x64</RuntimeIdentifier>
+    <SelfContained>true</SelfContained>
+  </PropertyGroup>
+</Project>

+ 17 - 0
SelfContained/Properties/PublishProfiles/FolderProfile_net8.0_win-x64_Debug.pubxml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+  <PropertyGroup>
+    <Configuration>Debug</Configuration>
+    <Platform>Any CPU</Platform>
+    <PublishDir>bin\Debug\net8.0\publish\win-x64\</PublishDir>
+    <PublishProtocol>FileSystem</PublishProtocol>
+    <_TargetId>Folder</_TargetId>
+    <TargetFramework>net8.0</TargetFramework>
+    <RuntimeIdentifier>win-x64</RuntimeIdentifier>
+    <SelfContained>true</SelfContained>
+    <PublishReadyToRun>false</PublishReadyToRun>
+  </PropertyGroup>
+</Project>

+ 17 - 0
SelfContained/Properties/PublishProfiles/FolderProfile_net8.0_win-x64_Release.pubxml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+  <PropertyGroup>
+    <Configuration>Release</Configuration>
+    <Platform>Any CPU</Platform>
+    <PublishDir>bin\Release\net8.0\publish\win-x64\</PublishDir>
+    <PublishProtocol>FileSystem</PublishProtocol>
+    <_TargetId>Folder</_TargetId>
+    <TargetFramework>net8.0</TargetFramework>
+    <RuntimeIdentifier>win-x64</RuntimeIdentifier>
+    <SelfContained>true</SelfContained>
+    <PublishReadyToRun>false</PublishReadyToRun>
+  </PropertyGroup>
+</Project>

+ 9 - 0
SelfContained/README.md

@@ -0,0 +1,9 @@
+# Terminal.Gui C# SelfContained
+
+This example shows how to use the `Terminal.Gui` library to create a simple `self-contained` `single file` GUI application in C#.
+
+With `Debug` the `.csproj` is used and with `Release` the latest `nuget package` is used, either in `Solution Configurations` or in `Profile Publish`.
+
+To publish the self-contained single file in `Debug` or `Release` mode, it is not necessary to select it in the `Solution Configurations`, just choose the `Debug` or `Release` configuration in the `Publish Profile`.
+
+When executing the file directly from the self-contained single file and needing to debug it, it will be necessary to attach it to the debugger, just like any other standalone application. However, when trying to attach the file running on `Linux` or `macOS` to the debugger, it will issue the error "`Failed to attach to process: Unknown Error: 0x80131c3c`". This issue has already been reported on [Developer Community](https://developercommunity.visualstudio.com/t/Failed-to-attach-to-process:-Unknown-Err/10694351). Maybe it would be a good idea to vote in favor of this fix because I think `Visual Studio for macOS` is going to be discontinued and we need this fix to remotely attach a process running on `Linux` or `macOS` to `Windows 11`.

+ 25 - 0
SelfContained/SelfContained.csproj

@@ -0,0 +1,25 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net8.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+    <PublishTrimmed>true</PublishTrimmed>
+    <TrimMode>Link</TrimMode>
+    <PublishSingleFile>true</PublishSingleFile>
+    <InvariantGlobalization>true</InvariantGlobalization>
+    <DebugType>embedded</DebugType>
+  </PropertyGroup>
+
+  <ItemGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
+    <ProjectReference Include="..\Terminal.Gui\Terminal.Gui.csproj" />
+    <TrimmerRootAssembly Include="Terminal.Gui" />
+  </ItemGroup>
+
+  <ItemGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+    <PackageReference Include="Terminal.Gui" Version="[2.0.0-pre.1788,3)" />
+    <TrimmerRootAssembly Include="Terminal.Gui" />
+  </ItemGroup>
+
+</Project>

+ 31 - 0
Showcase.md

@@ -0,0 +1,31 @@
+# Showcase #
+
+* **[UI Catalog](https://github.com/gui-cs/Terminal.Gui/tree/master/UICatalog)** - The UI Catalog project provides an easy to use and extend sample illustrating the capabilities of **Terminal.Gui**. Run `dotnet run --project UICatalog` to run the UI Catalog.
+  ![Sample app](docfx/images/sample.gif)  
+  ⠀
+* **[PowerShell's `Out-ConsoleGridView`](https://github.com/PowerShell/GraphicalTools)** - `OCGV` sends the output from a command to an interactive table.
+  ![OutConsoleGridView.png](docfx/images/OutConsoleGridView.png)  
+  ⠀
+* **[F7History](https://github.com/gui-cs/F7History)** - Graphical Command History for PowerShell (built on PowerShell's `Out-ConsoleGridView`).
+  ![F7History.gif](docfx/images/F7History.gif)  
+  ⠀
+* **[PoshRedisViewer](https://github.com/En3Tho/PoshRedisViewer)** - A compact Redis viewer module for PowerShell written in F#.
+  ![PoshRedisViewer.png](docfx/images/PoshRedisViewer.png)  
+  ⠀
+* **[PoshDotnetDumpAnalyzeViewer](https://github.com/En3Tho/PoshDotnetDumpAnalyzeViewer)** - dotnet-dump UI module for PowerShell.
+  ![PoshDotnetDumpAnalyzerViewer.png](docfx/images/PoshDotnetDumpAnalyzerViewer.png)  
+  ⠀
+* **[TerminalGuiDesigner](https://github.com/tznind/TerminalGuiDesigner)** - Cross platform view designer for building Terminal.Gui applications.
+  ![TerminalGuiDesigner.gif](docfx/images/TerminalGuiDesigner.gif)
+
+* **[Capital and Cargo](https://github.com/dhorions/Capital-and-Cargo)** - A retro console game where you buy, sell, produce and transport goods built with Terminal.Gui
+ ![image](https://github.com/gui-cs/Terminal.Gui/assets/1682004/ed89f3d6-020f-4a8a-ae18-e057514f4c43)
+
+  
+# Examples #
+
+* **[C# Example](https://github.com/gui-cs/Terminal.Gui/tree/master/Example)** - Run `dotnet run` in the `Example` directory to run the C# Example.
+
+* **[F# Example](https://github.com/gui-cs/Terminal.Gui/tree/master/FSharpExample)** - An example showing how to build a Terminal.Gui app using F#.
+
+* **[Reactive Example](https://github.com/gui-cs/Terminal.Gui/tree/master/ReactiveExample)** - A sample app that shows how to use `System.Reactive` and `ReactiveUI` with `Terminal.Gui`. The app uses the MVVM architecture that may seem familiar to folks coming from WPF, Xamarin Forms, UWP, Avalonia, or Windows Forms. In this app, we implement the data bindings using ReactiveUI `WhenAnyValue` syntax and [Pharmacist](https://github.com/reactiveui/pharmacist) — a tool that converts all events in a NuGet package into observable wrappers. 

+ 11 - 1
Terminal.Gui/Application/Application.cs

@@ -1,4 +1,5 @@
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Reflection;
 
@@ -56,7 +57,7 @@ public static partial class Application
         string assemblyLocation = AppDomain.CurrentDomain.BaseDirectory;
 
         // Find the resource file name of the assembly
-        var resourceFilename = $"{Path.GetFileNameWithoutExtension (assembly.Location)}.resources.dll";
+        var resourceFilename = $"{Path.GetFileNameWithoutExtension (AppContext.BaseDirectory)}.resources.dll";
 
         // Return all culture for which satellite folder found with culture code.
         return culture.Where (
@@ -192,6 +193,8 @@ public static partial class Application
     ///     <see cref="ConsoleDriver"/> to use. If neither <paramref name="driver"/> or <paramref name="driverName"/> are
     ///     specified the default driver for the platform will be used.
     /// </param>
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
     public static void Init (ConsoleDriver driver = null, string driverName = null) { InternalInit (driver, driverName); }
 
     internal static bool _initialized;
@@ -206,6 +209,8 @@ public static partial class Application
     // Unit Tests - To initialize the app with a custom Toplevel, using the FakeDriver. calledViaRunT will be false, causing all state to be reset.
     // 
     // calledViaRunT: If false (default) all state will be reset. If true the state will not be reset.
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
     internal static void InternalInit (
         ConsoleDriver driver = null,
         string driverName = null,
@@ -318,6 +323,7 @@ public static partial class Application
 
     /// <summary>Gets of list of <see cref="ConsoleDriver"/> types that are available.</summary>
     /// <returns></returns>
+    [RequiresUnreferencedCode ("AOT")]
     public static List<Type> GetDriverTypes ()
     {
         // use reflection to get the list of drivers
@@ -660,6 +666,8 @@ public static partial class Application
     ///     </para>
     /// </remarks>
     /// <returns>The created <see cref="Toplevel"/> object. The caller is responsible for disposing this object.</returns>
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
     public static Toplevel Run (Func<Exception, bool> errorHandler = null, ConsoleDriver driver = null) { return Run<Toplevel> (errorHandler, driver); }
 
     /// <summary>
@@ -683,6 +691,8 @@ public static partial class Application
     ///     <see langword="null"/> if <see cref="Init"/> has already been called.
     /// </param>
     /// <returns>The created T object. The caller is responsible for disposing this object.</returns>
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
     public static T Run<T> (Func<Exception, bool> errorHandler = null, ConsoleDriver driver = null)
         where T : Toplevel, new()
     {

+ 3 - 3
Terminal.Gui/Configuration/AttributeJsonConverter.cs

@@ -3,7 +3,7 @@ using System.Text.Json.Serialization;
 
 namespace Terminal.Gui;
 
-/// <summary>Json converter fro the <see cref="Attribute"/> class.</summary>
+/// <summary>Json converter from the <see cref="Attribute"/> class.</summary>
 internal class AttributeJsonConverter : JsonConverter<Attribute>
 {
     private static AttributeJsonConverter _instance;
@@ -57,11 +57,11 @@ internal class AttributeJsonConverter : JsonConverter<Attribute>
             switch (propertyName?.ToLower ())
             {
                 case "foreground":
-                    foreground = JsonSerializer.Deserialize<Color> (color, options);
+                    foreground = JsonSerializer.Deserialize (color, _serializerContext.Color);
 
                     break;
                 case "background":
-                    background = JsonSerializer.Deserialize<Color> (color, options);
+                    background = JsonSerializer.Deserialize (color, _serializerContext.Color);
 
                     break;
 

+ 1 - 1
Terminal.Gui/Configuration/ColorSchemeJsonConverter.cs

@@ -59,7 +59,7 @@ internal class ColorSchemeJsonConverter : JsonConverter<ColorScheme>
 
             string propertyName = reader.GetString ();
             reader.Read ();
-            var attribute = JsonSerializer.Deserialize<Attribute> (ref reader, options);
+            var attribute = JsonSerializer.Deserialize (ref reader, _serializerContext.Attribute);
 
             switch (propertyName.ToLower ())
             {

+ 22 - 4
Terminal.Gui/Configuration/ConfigurationManager.cs

@@ -106,9 +106,12 @@ public static class ConfigurationManager
         },
 
         // Enables Key to be "Ctrl+Q" vs "Ctrl\u002BQ"
-        Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
+        Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
+        TypeInfoResolver = SourceGenerationContext.Default
     };
 
+    internal static readonly SourceGenerationContext _serializerContext = new (_serializerOptions);
+
     [SuppressMessage ("Style", "IDE1006:Naming Styles", Justification = "<Pending>")]
     internal static StringBuilder _jsonErrors = new ();
 
@@ -150,6 +153,8 @@ public static class ConfigurationManager
     /// </summary>
     public static SettingsScope? Settings
     {
+        [RequiresUnreferencedCode ("AOT")]
+        [RequiresDynamicCode ("AOT")]
         get
         {
             if (_settings is null)
@@ -181,6 +186,8 @@ public static class ConfigurationManager
     public static event EventHandler<ConfigurationManagerEventArgs>? Applied;
 
     /// <summary>Applies the configuration settings to the running <see cref="Application"/> instance.</summary>
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
     public static void Apply ()
     {
         var settings = false;
@@ -222,7 +229,7 @@ public static class ConfigurationManager
         var emptyScope = new SettingsScope ();
         emptyScope.Clear ();
 
-        return JsonSerializer.Serialize (emptyScope, _serializerOptions);
+        return JsonSerializer.Serialize (emptyScope, typeof (SettingsScope), _serializerContext);
     }
 
     /// <summary>
@@ -235,6 +242,8 @@ public static class ConfigurationManager
     ///     If <see langword="true"/> the state of <see cref="ConfigurationManager"/> will be reset to the
     ///     defaults.
     /// </param>
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
     public static void Load (bool reset = false)
     {
         Debug.WriteLine ("ConfigurationManager.Load()");
@@ -322,6 +331,8 @@ public static class ConfigurationManager
     ///     <see langword="true"/>.
     /// </summary>
     /// <remarks></remarks>
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
     public static void Reset ()
     {
         Debug.WriteLine (@"ConfigurationManager.Reset()");
@@ -475,6 +486,8 @@ public static class ConfigurationManager
     ///         make sure you copy the Theme definitions from the existing <c>Terminal.Gui.Resources.config.json</c> file.
     ///     </para>
     /// </remarks>
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
     internal static void GetHardCodedDefaults ()
     {
         if (_allConfigProperties is null)
@@ -496,6 +509,7 @@ public static class ConfigurationManager
     ///     Initializes the internal state of ConfigurationManager. Nominally called once as part of application startup
     ///     to initialize global state. Also called from some Unit Tests to ensure correctness (e.g. Reset()).
     /// </summary>
+    [RequiresUnreferencedCode ("AOT")]
     internal static void Initialize ()
     {
         _allConfigProperties = new ();
@@ -585,16 +599,20 @@ public static class ConfigurationManager
 
     /// <summary>Creates a JSON document with the configuration specified.</summary>
     /// <returns></returns>
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
     internal static string ToJson ()
     {
         //Debug.WriteLine ("ConfigurationManager.ToJson()");
 
-        return JsonSerializer.Serialize (Settings!, _serializerOptions);
+        return JsonSerializer.Serialize (Settings!, typeof (SettingsScope), _serializerContext);
     }
 
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
     internal static Stream ToStream ()
     {
-        string json = JsonSerializer.Serialize (Settings!, _serializerOptions);
+        string json = JsonSerializer.Serialize (Settings!, typeof (SettingsScope), _serializerContext);
 
         // turn it into a stream
         var stream = new MemoryStream ();

+ 3 - 3
Terminal.Gui/Configuration/DictionaryJsonConverter.cs

@@ -28,8 +28,8 @@ internal class DictionaryJsonConverter<T> : JsonConverter<Dictionary<string, T>>
                 {
                     string key = reader.GetString ();
                     reader.Read ();
-                    var value = JsonSerializer.Deserialize<T> (ref reader, options);
-                    dictionary.Add (key, value);
+                    var value = JsonSerializer.Deserialize (ref reader, typeof (T), _serializerContext);
+                    dictionary.Add (key, (T)value);
                 }
             }
             else if (reader.TokenType == JsonTokenType.EndArray)
@@ -51,7 +51,7 @@ internal class DictionaryJsonConverter<T> : JsonConverter<Dictionary<string, T>>
 
             //writer.WriteString (item.Key, item.Key);
             writer.WritePropertyName (item.Key);
-            JsonSerializer.Serialize (writer, item.Value, options);
+            JsonSerializer.Serialize (writer, item.Value, typeof (T), _serializerContext);
             writer.WriteEndObject ();
         }
 

+ 1 - 1
Terminal.Gui/Configuration/KeyCodeJsonConverter.cs

@@ -42,7 +42,7 @@ internal class KeyCodeJsonConverter : JsonConverter<KeyCode>
                                 }
 
                                 // The enum uses "D0..D9" for the number keys
-                                if (Enum.TryParse (reader.GetString ().TrimStart ('D', 'd'), false, out key))
+                                if (Enum.TryParse (reader.GetString ()!.TrimStart ('D', 'd'), false, out key))
                                 {
                                     break;
                                 }

+ 13 - 5
Terminal.Gui/Configuration/ScopeJsonConverter.cs

@@ -1,5 +1,6 @@
 #nullable enable
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 using System.Text.Json;
 using System.Text.Json.Serialization;
@@ -11,9 +12,12 @@ namespace Terminal.Gui;
 ///     data to/from <see cref="ConfigurationManager"/> JSON documents.
 /// </summary>
 /// <typeparam name="scopeT"></typeparam>
-internal class ScopeJsonConverter<scopeT> : JsonConverter<scopeT> where scopeT : Scope<scopeT>
+internal class ScopeJsonConverter<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] scopeT> : JsonConverter<scopeT> where scopeT : Scope<scopeT>
 {
+    [RequiresDynamicCode ("Calls System.Type.MakeGenericType(params Type[])")]
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
     public override scopeT Read (ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
     {
         if (reader.TokenType != JsonTokenType.StartObject)
         {
@@ -85,7 +89,7 @@ internal class ScopeJsonConverter<scopeT> : JsonConverter<scopeT> where scopeT :
                     try
                     {
                         scope! [propertyName].PropertyValue =
-                            JsonSerializer.Deserialize (ref reader, propertyType!, options);
+                            JsonSerializer.Deserialize (ref reader, propertyType!, _serializerContext);
                     }
                     catch (Exception ex)
                     {
@@ -133,7 +137,7 @@ internal class ScopeJsonConverter<scopeT> : JsonConverter<scopeT> where scopeT :
                 if (property is { })
                 {
                     PropertyInfo prop = scope.GetType ().GetProperty (propertyName!)!;
-                    prop.SetValue (scope, JsonSerializer.Deserialize (ref reader, prop.PropertyType, options));
+                    prop.SetValue (scope, JsonSerializer.Deserialize (ref reader, prop.PropertyType, _serializerContext));
                 }
                 else
                 {
@@ -160,7 +164,8 @@ internal class ScopeJsonConverter<scopeT> : JsonConverter<scopeT> where scopeT :
         foreach (PropertyInfo p in properties)
         {
             writer.WritePropertyName (ConfigProperty.GetJsonPropertyName (p));
-            JsonSerializer.Serialize (writer, scope.GetType ().GetProperty (p.Name)?.GetValue (scope), options);
+            object? prop = scope.GetType ().GetProperty (p.Name)?.GetValue (scope);
+            JsonSerializer.Serialize (writer, prop, prop!.GetType (), _serializerContext);
         }
 
         foreach (KeyValuePair<string, ConfigProperty> p in from p in scope
@@ -205,7 +210,8 @@ internal class ScopeJsonConverter<scopeT> : JsonConverter<scopeT> where scopeT :
             }
             else
             {
-                JsonSerializer.Serialize (writer, p.Value.PropertyValue, options);
+                object? prop = p.Value.PropertyValue;
+                JsonSerializer.Serialize (writer, prop, prop!.GetType (), _serializerContext);
             }
         }
 
@@ -221,6 +227,8 @@ internal class ScopeJsonConverter<scopeT> : JsonConverter<scopeT> where scopeT :
     internal class ReadHelper<converterT> : ReadHelper
     {
         private readonly ReadDelegate _readDelegate;
+
+        [RequiresUnreferencedCode ("Calls System.Delegate.CreateDelegate(Type, Object, String)")]
         public ReadHelper (object converter) { _readDelegate = (ReadDelegate)Delegate.CreateDelegate (typeof (ReadDelegate), converter, "Read"); }
 
         public override object? Read (ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)

+ 10 - 1
Terminal.Gui/Configuration/SettingsScope.cs

@@ -1,5 +1,6 @@
 #nullable enable
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 using System.Text.Json;
 using System.Text.Json.Serialization;
@@ -37,12 +38,14 @@ public class SettingsScope : Scope<SettingsScope>
     /// <summary>Updates the <see cref="SettingsScope"/> with the settings in a JSON string.</summary>
     /// <param name="stream">Json document to update the settings with.</param>
     /// <param name="source">The source (filename/resource name) the Json document was read from.</param>
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
     public SettingsScope? Update (Stream stream, string source)
     {
         // Update the existing settings with the new settings.
         try
         {
-            Update (JsonSerializer.Deserialize<SettingsScope> (stream, _serializerOptions)!);
+            Update ((SettingsScope)JsonSerializer.Deserialize (stream, typeof (SettingsScope), _serializerOptions)!);
             OnUpdated ();
             Debug.WriteLine ($"ConfigurationManager: Read configuration from \"{source}\"");
             if (!Sources.Contains (source))
@@ -67,6 +70,8 @@ public class SettingsScope : Scope<SettingsScope>
 
     /// <summary>Updates the <see cref="SettingsScope"/> with the settings in a JSON file.</summary>
     /// <param name="filePath"></param>
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
     public SettingsScope? Update (string filePath)
     {
         string realPath = filePath.Replace ("~", Environment.GetFolderPath (Environment.SpecialFolder.UserProfile));
@@ -93,6 +98,8 @@ public class SettingsScope : Scope<SettingsScope>
     /// <summary>Updates the <see cref="SettingsScope"/> with the settings in a JSON string.</summary>
     /// <param name="json">Json document to update the settings with.</param>
     /// <param name="source">The source (filename/resource name) the Json document was read from.</param>
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
     public SettingsScope? Update (string json, string source)
     {
         var stream = new MemoryStream ();
@@ -107,6 +114,8 @@ public class SettingsScope : Scope<SettingsScope>
     /// <summary>Updates the <see cref="SettingsScope"/> with the settings from a Json resource.</summary>
     /// <param name="assembly"></param>
     /// <param name="resourceName"></param>
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
     public SettingsScope? UpdateFromResource (Assembly assembly, string resourceName)
     {
         if (resourceName is null || string.IsNullOrEmpty (resourceName))

+ 23 - 0
Terminal.Gui/Configuration/SourceGenerationContext.cs

@@ -0,0 +1,23 @@
+using System.Text.Json.Serialization;
+
+namespace Terminal.Gui;
+
+/// <summary>
+///     Allow AOT and self-contained single file applications with the <see cref="System.Text.Json.Serialization"/>
+/// </summary>
+[JsonSerializable (typeof (Attribute))]
+[JsonSerializable (typeof (Color))]
+[JsonSerializable (typeof (ThemeScope))]
+[JsonSerializable (typeof (ColorScheme))]
+[JsonSerializable (typeof (SettingsScope))]
+[JsonSerializable (typeof (AppScope))]
+[JsonSerializable (typeof (Key))]
+[JsonSerializable (typeof (GlyphDefinitions))]
+[JsonSerializable (typeof (ConfigProperty))]
+[JsonSerializable (typeof (ShadowStyle))]
+[JsonSerializable (typeof (string))]
+[JsonSerializable (typeof (bool))]
+[JsonSerializable (typeof (bool?))]
+[JsonSerializable (typeof (Dictionary<ColorName, string>))]
+internal partial class SourceGenerationContext : JsonSerializerContext
+{ }

+ 113 - 0
Terminal.Gui/Configuration/ThemeManager.cs

@@ -1,6 +1,7 @@
 #nullable enable
 using System.Collections;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Text.Json.Serialization;
 
 namespace Terminal.Gui;
@@ -64,6 +65,9 @@ public class ThemeManager : IDictionary<string, ThemeScope>
     public string Theme
     {
         get => SelectedTheme;
+
+        [RequiresUnreferencedCode ("AOT")]
+        [RequiresDynamicCode ("AOT")]
         set => SelectedTheme = value;
     }
 
@@ -73,9 +77,14 @@ public class ThemeManager : IDictionary<string, ThemeScope>
     [SerializableConfigurationProperty (Scope = typeof (SettingsScope), OmitClassName = true)]
     public static Dictionary<string, ThemeScope>? Themes
     {
+        [RequiresUnreferencedCode ("AOT")]
+        [RequiresDynamicCode ("AOT")]
         get => Settings? ["Themes"]
                        ?.PropertyValue as
                    Dictionary<string, ThemeScope>; // themes ?? new Dictionary<string, ThemeScope> ();
+
+        [RequiresUnreferencedCode ("AOT")]
+        [RequiresDynamicCode ("AOT")]
         set =>
 
             //if (themes is null || value is null) {
@@ -93,6 +102,9 @@ public class ThemeManager : IDictionary<string, ThemeScope>
     internal static string SelectedTheme
     {
         get => _theme;
+
+        [RequiresUnreferencedCode ("Calls Terminal.Gui.ConfigurationManager.Settings")]
+        [RequiresDynamicCode ("Calls Terminal.Gui.ConfigurationManager.Settings")]
         set
         {
             string oldTheme = _theme;
@@ -109,6 +121,8 @@ public class ThemeManager : IDictionary<string, ThemeScope>
     /// <summary>Event fired he selected theme has changed. application.</summary>
     public event EventHandler<ThemeManagerEventArgs>? ThemeChanged;
 
+    [RequiresUnreferencedCode ("Calls Terminal.Gui.ThemeManager.Themes")]
+    [RequiresDynamicCode ("Calls Terminal.Gui.ThemeManager.Themes")]
     internal static void GetHardCodedDefaults ()
     {
         //Debug.WriteLine ("Themes.GetHardCodedDefaults()");
@@ -129,6 +143,8 @@ public class ThemeManager : IDictionary<string, ThemeScope>
         ThemeChanged?.Invoke (this, new ThemeManagerEventArgs (theme));
     }
 
+    [RequiresUnreferencedCode ("Calls Terminal.Gui.ThemeManager.Themes")]
+    [RequiresDynamicCode ("Calls Terminal.Gui.ThemeManager.Themes")]
     internal static void Reset ()
     {
         Debug.WriteLine ("Themes.Reset()");
@@ -140,33 +156,130 @@ public class ThemeManager : IDictionary<string, ThemeScope>
     #region IDictionary
 
 #pragma warning disable 1591
+    [UnconditionalSuppressMessage ("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>")]
+    [UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")]
     public ICollection<string> Keys => ((IDictionary<string, ThemeScope>)Themes!).Keys;
+
+    [UnconditionalSuppressMessage ("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>")]
+    [UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")]
     public ICollection<ThemeScope> Values => ((IDictionary<string, ThemeScope>)Themes!).Values;
+
+    [UnconditionalSuppressMessage ("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>")]
+    [UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")]
     public int Count => ((ICollection<KeyValuePair<string, ThemeScope>>)Themes!).Count;
+
+    [UnconditionalSuppressMessage ("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>")]
+    [UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")]
     public bool IsReadOnly => ((ICollection<KeyValuePair<string, ThemeScope>>)Themes!).IsReadOnly;
 
     public ThemeScope this [string key]
     {
+        [RequiresUnreferencedCode ("AOT")]
+        [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
         get => ((IDictionary<string, ThemeScope>)Themes!) [key];
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+
+        [RequiresUnreferencedCode ("AOT")]
+        [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
         set => ((IDictionary<string, ThemeScope>)Themes!) [key] = value;
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
     }
 
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
     public void Add (string key, ThemeScope value) { ((IDictionary<string, ThemeScope>)Themes!).Add (key, value); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
     public bool ContainsKey (string key) { return ((IDictionary<string, ThemeScope>)Themes!).ContainsKey (key); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
     public bool Remove (string key) { return ((IDictionary<string, ThemeScope>)Themes!).Remove (key); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
     public bool TryGetValue (string key, out ThemeScope value) { return ((IDictionary<string, ThemeScope>)Themes!).TryGetValue (key, out value!); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
     public void Add (KeyValuePair<string, ThemeScope> item) { ((ICollection<KeyValuePair<string, ThemeScope>>)Themes!).Add (item); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
     public void Clear () { ((ICollection<KeyValuePair<string, ThemeScope>>)Themes!).Clear (); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
     public bool Contains (KeyValuePair<string, ThemeScope> item) { return ((ICollection<KeyValuePair<string, ThemeScope>>)Themes!).Contains (item); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
 
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
     public void CopyTo (KeyValuePair<string, ThemeScope> [] array, int arrayIndex)
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
     {
         ((ICollection<KeyValuePair<string, ThemeScope>>)Themes!).CopyTo (array, arrayIndex);
     }
 
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
     public bool Remove (KeyValuePair<string, ThemeScope> item) { return ((ICollection<KeyValuePair<string, ThemeScope>>)Themes!).Remove (item); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
     public IEnumerator<KeyValuePair<string, ThemeScope>> GetEnumerator () { return ((IEnumerable<KeyValuePair<string, ThemeScope>>)Themes!).GetEnumerator (); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+
+    [RequiresUnreferencedCode ("Calls Terminal.Gui.ThemeManager.Themes")]
+    [RequiresDynamicCode ("Calls Terminal.Gui.ThemeManager.Themes")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
     IEnumerator IEnumerable.GetEnumerator () { return ((IEnumerable)Themes!).GetEnumerator (); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
 #pragma warning restore 1591
 
     #endregion

+ 2 - 0
Terminal.Gui/ConsoleDrivers/CursesDriver/UnmanagedLibrary.cs

@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #define GUICS
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.InteropServices;
 
 namespace Unix.Terminal;
@@ -69,6 +70,7 @@ internal class UnmanagedLibrary
         }
     }
 
+    [UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")]
     static UnmanagedLibrary ()
     {
         PlatformID platform = Environment.OSVersion.Platform;

+ 3 - 0
Terminal.Gui/ConsoleDrivers/NetDriver.cs

@@ -3,6 +3,7 @@
 //
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.InteropServices;
 using static Terminal.Gui.ConsoleDrivers.ConsoleKeyMapping;
 using static Terminal.Gui.NetEvents;
@@ -452,6 +453,7 @@ internal class NetEvents : IDisposable
         HandleKeyboardEvent (newConsoleKeyInfo);
     }
 
+    [UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")]
     private MouseButtonState MapMouseFlags (MouseFlags mouseFlags)
     {
         MouseButtonState mbs = default;
@@ -1249,6 +1251,7 @@ internal class NetDriver : ConsoleDriver
     #region Color Handling
 
     // Cache the list of ConsoleColor values.
+    [UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")]
     private static readonly HashSet<int> ConsoleColorValues = new (
                                                                    Enum.GetValues (typeof (ConsoleColor))
                                                                        .OfType<ConsoleColor> ()

+ 3 - 3
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -116,7 +116,7 @@ internal class WindowsConsole
 
             var s = _stringBuilder.ToString ();
 
-            result = WriteConsole (_screenBuffer, s, (uint)s.Length, out uint _, null);
+            result = WriteConsole (_screenBuffer, s, (uint)s.Length, out uint _, nint.Zero);
         }
 
         if (!result)
@@ -134,7 +134,7 @@ internal class WindowsConsole
 
     public bool WriteANSI (string ansi)
     {
-        return WriteConsole (_screenBuffer, ansi, (uint)ansi.Length, out uint _, null);
+        return WriteConsole (_screenBuffer, ansi, (uint)ansi.Length, out uint _, nint.Zero);
     }
 
     public void ReadFromConsoleOutput (Size size, Coord coords, ref SmallRect window)
@@ -804,7 +804,7 @@ internal class WindowsConsole
         string lpbufer,
         uint NumberOfCharsToWriten,
         out uint lpNumberOfCharsWritten,
-        object lpReserved
+        nint lpReserved
     );
 
     [DllImport ("kernel32.dll")]

+ 3 - 1
Terminal.Gui/FileServices/FileDialogStyle.cs

@@ -1,4 +1,5 @@
-using System.Globalization;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
 using System.IO.Abstractions;
 using Terminal.Gui.Resources;
 using static System.Environment;
@@ -143,6 +144,7 @@ public class FileDialogStyle
     /// </summary>
     public string WrongFileTypeFeedback { get; set; } = Strings.fdWrongFileTypeFeedback;
 
+    [UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")]
     private Dictionary<IDirectoryInfo, string> DefaultTreeRootGetter ()
     {
         Dictionary<IDirectoryInfo, string> roots = new ();

+ 2 - 4
Terminal.Gui/README.md

@@ -6,9 +6,7 @@ All files required to build the **Terminal.Gui** library (and NuGet package).
 
 - `\` - The root folder contains the source code for the library.
 	- `Terminal.Gui.sln` - The Visual Studio solution
-	- `Application.cs` - A `static` class that provides the base 'application driver'. Given it defines a **Terminal.Gui** application it is both logically and literally (because `static`) a singleton. It has direct dependencies on `MainLoop`, `Events.cs` `NetDriver`, `CursesDriver`, `WindowsDriver`, `Responder`, `View`, and `TopLevel` (and nothing else).
-	- `MainLoop.cs` - Defines `IMainLoopDriver` and implements the `MainLoop` class.
-	- A few supporting class files
+	- `Application\` - The core `Application` logic, including `Application.cs`, which is is a `static` class that provides the base 'application engine', `RunState`, and `MainLoop`.
 
 - `ConsoleDrivers\`
 	- `ConsoleDriver.cs` - Definition for the Console Driver API.
@@ -38,7 +36,7 @@ All files required to build the **Terminal.Gui** library (and NuGet package).
 	- `Dialog` -
 	- etc...
 
-- `Types/` - A folder (not namespace) containing implementations of `Point`, `Rect`, and `Size` which are ancient versions of the modern `System.Drawing.Point`, `System.Drawing.Size`, and `System.Drawning.Rectangle`.
+- `FileServcies/` - File services classes.
 
 ## Version numbers
 

+ 5 - 7
Terminal.Gui/Terminal.Gui.csproj

@@ -25,10 +25,13 @@
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <DefineTrace>true</DefineTrace>
     <DebugType>portable</DebugType>
-    <DefineConstants>$(DefineConstants);JETBRAINS_ANNOTATIONS;CONTRACTS_FULL;CODE_ANALYSIS</DefineConstants>
+    <DefineConstants>$(DefineConstants);CONTRACTS_FULL;CODE_ANALYSIS</DefineConstants>
     <ImplicitUsings>enable</ImplicitUsings>
     <NoLogo>true</NoLogo>
     <SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>
+    <JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
+    <IsTrimmable>true</IsTrimmable>
+    <IsAotCompatible>true</IsAotCompatible>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <DefineDebug>true</DefineDebug>
@@ -50,7 +53,7 @@
   <!-- =================================================================== -->
   <ItemGroup>
     <PackageReference Include="ColorHelper" Version="[1.8.1,2)" />
-    <PackageReference Include="JetBrains.Annotations" Version="[2024,)" PrivateAssets="all" />
+    <PackageReference Include="JetBrains.Annotations" Version="[2024.2.0,)" PrivateAssets="all" />
     <PackageReference Include="Microsoft.CodeAnalysis" Version="[4.10,5)" PrivateAssets="all" />
     <PackageReference Include="Microsoft.CodeAnalysis.Common" Version="[4.10,5)" PrivateAssets="all" />
     <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="[4.10,5)" PrivateAssets="all" />
@@ -59,11 +62,6 @@
     <PackageReference Include="System.IO.Abstractions" Version="[21.0.22,22)" />
     <PackageReference Include="System.Text.Json" Version="[8.0.4,9)" />
     <PackageReference Include="Wcwidth" Version="[2,3)" />
-    <ProjectReference Include="..\Analyzers\Terminal.Gui.Analyzers.Internal\Terminal.Gui.Analyzers.Internal.csproj">
-      <PrivateAssets>all</PrivateAssets>
-      <OutputItemType>Analyzer</OutputItemType>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
   </ItemGroup>
   <!-- =================================================================== -->
   <!-- Global Usings and Type Aliases -->

+ 1 - 1
Terminal.Gui/Views/Button.cs

@@ -39,7 +39,7 @@ public class Button : View, IDesignable
     /// Gets or sets whether <see cref="Button"/>s are shown with a shadow effect by default.
     /// </summary>
     [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
-    [JsonConverter (typeof (JsonStringEnumConverter))]
+    [JsonConverter (typeof (JsonStringEnumConverter<ShadowStyle>))]
 
     public static ShadowStyle DefaultShadow { get; set; } = ShadowStyle.None;
 

+ 4 - 4
Terminal.Gui/Views/Dialog.cs

@@ -19,13 +19,13 @@ public class Dialog : Window
     /// <summary>The default <see cref="Alignment"/> for <see cref="Dialog"/>.</summary>
     /// <remarks>This property can be set in a Theme.</remarks>
     [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
-    [JsonConverter (typeof (JsonStringEnumConverter))]
+    [JsonConverter (typeof (JsonStringEnumConverter<Alignment>))]
     public static Alignment DefaultButtonAlignment { get; set; } = Alignment.End;
 
     /// <summary>The default <see cref="Alignment"/> for <see cref="Dialog"/>.</summary>
     /// <remarks>This property can be set in a Theme.</remarks>
     [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
-    [JsonConverter (typeof (JsonStringEnumConverter))]
+    [JsonConverter (typeof (JsonStringEnumConverter<AlignmentModes>))]
     public static AlignmentModes DefaultButtonAlignmentModes { get; set; } = AlignmentModes.StartToEnd | AlignmentModes.AddSpaceBetweenItems;
 
     /// <summary>
@@ -47,7 +47,7 @@ public class Dialog : Window
     /// Gets or sets whether all <see cref="Window"/>s are shown with a shadow effect by default.
     /// </summary>
     [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
-    [JsonConverter (typeof (JsonStringEnumConverter))]
+    [JsonConverter (typeof (JsonStringEnumConverter<ShadowStyle>))]
     public new static ShadowStyle DefaultShadow { get; set; } = ShadowStyle.None;
 
     /// <summary>
@@ -56,7 +56,7 @@ public class Dialog : Window
     /// </summary>
 
     [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
-    [JsonConverter (typeof (JsonStringEnumConverter))]
+    [JsonConverter (typeof (JsonStringEnumConverter<LineStyle>))]
     public new static LineStyle DefaultBorderStyle { get; set; } = LineStyle.Single;
 
     private readonly List<Button> _buttons = new ();

+ 1 - 1
Terminal.Gui/Views/FrameView.cs

@@ -36,6 +36,6 @@ public class FrameView : View
     ///     <see cref="FrameView"/>s.
     /// </remarks>
     [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
-    [JsonConverter (typeof (JsonStringEnumConverter))]
+    [JsonConverter (typeof (JsonStringEnumConverter<LineStyle>))]
     public static LineStyle DefaultBorderStyle { get; set; } = LineStyle.Single;
 }

+ 1 - 1
Terminal.Gui/Views/MessageBox.cs

@@ -31,7 +31,7 @@ public static class MessageBox
     ///     <see cref="ConfigurationManager"/>.
     /// </summary>
     [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
-    [JsonConverter (typeof (JsonStringEnumConverter))]
+    [JsonConverter (typeof (JsonStringEnumConverter<LineStyle>))]
     public static LineStyle DefaultBorderStyle { get; set; } = LineStyle.Single;
 
     /// <summary>

+ 1 - 1
Terminal.Gui/Views/Window.cs

@@ -73,6 +73,6 @@ public class Window : Toplevel
     ///     s.
     /// </remarks>
     [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
-    [JsonConverter (typeof (JsonStringEnumConverter))]
+    [JsonConverter (typeof (JsonStringEnumConverter<LineStyle>))]
     public static LineStyle DefaultBorderStyle { get; set; } = LineStyle.Single;
 }

+ 6 - 0
Terminal.sln

@@ -43,6 +43,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{C7A51224-5
 		README.md = README.md
 	EndProjectSection
 EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SelfContained", "SelfContained\SelfContained.csproj", "{524DEA78-7E7C-474D-B42D-52ED4C04FF14}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -73,6 +75,10 @@ Global
 		{58FDCA8F-08F7-4D80-9DA3-6A9AED01E163}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{58FDCA8F-08F7-4D80-9DA3-6A9AED01E163}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{58FDCA8F-08F7-4D80-9DA3-6A9AED01E163}.Release|Any CPU.Build.0 = Release|Any CPU
+		{524DEA78-7E7C-474D-B42D-52ED4C04FF14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{524DEA78-7E7C-474D-B42D-52ED4C04FF14}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{524DEA78-7E7C-474D-B42D-52ED4C04FF14}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{524DEA78-7E7C-474D-B42D-52ED4C04FF14}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 4 - 80
UICatalog/Scenario.cs

@@ -93,6 +93,10 @@ public class Scenario : IDisposable
     /// <returns></returns>
     public string GetName () { return ScenarioMetadata.GetName (GetType ()); }
 
+    /// <summary>Helper to get the <see cref="Application.QuitKey"/> and the <see cref="Scenario"/> Name (defined in <see cref="ScenarioMetadata"/>)</summary>
+    /// <returns></returns>
+    public string GetQuitKeyAndName () { return $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"; }
+
     /// <summary>
     ///     Returns a list of all <see cref="Scenario"/> instanaces defined in the project, sorted by
     ///     <see cref="ScenarioMetadata.Name"/>.
@@ -132,90 +136,12 @@ public class Scenario : IDisposable
     /// </remarks>
     public virtual void Main ()
     {
-        Init ();
-        Setup ();
-        Run ();
-    }
-
-    /// <summary>
-    ///     Helper that calls <see cref="Application.Init"/> and creates the default <see cref="Terminal.Gui.Window"/>
-    ///     implementation with a frame and label
-    ///     showing the name of the <see cref="Scenario"/> and logic to exit back to the Scenario picker UI. Override
-    ///     <see cref="Init"/> to provide any <see cref="Terminal.Gui.Toplevel"/> behavior needed.
-    /// </summary>
-    /// <remarks>
-    ///     <para>
-    ///         The base implementation calls <see cref="Application.Init"/> and creates a <see cref="Window"/> for
-    ///         <see cref="Win"/> and adds it to <see cref="Application.Top"/>.
-    ///     </para>
-    ///     <para>
-    ///         Overrides that do not call the base.<see cref="Run"/>, must call <see cref="Application.Init"/> before
-    ///         creating any views or calling other Terminal.Gui APIs.
-    ///     </para>
-    /// </remarks>
-    [ObsoleteAttribute ("This method is obsolete and will be removed in v2. Use Main instead.", false)]
-    public virtual void Init ()
-    {
-        Application.Init ();
-
-        ConfigurationManager.Themes.Theme = Theme;
-        ConfigurationManager.Apply ();
-
-        Top = new ();
-
-        Win = new ()
-        {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
-            X = 0,
-            Y = 0,
-            Width = Dim.Fill (),
-            Height = Dim.Fill (),
-            ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]
-        };
-        Top.Add (Win);
     }
 
-    /// <summary>
-    ///     Runs the <see cref="Scenario"/>. Override to start the <see cref="Scenario"/> using a <see cref="Toplevel"/>
-    ///     different than `Top`.
-    /// </summary>
-    /// <remarks>
-    ///     Overrides that do not call the base.<see cref="Run"/>, must call <see cref="Application.Shutdown"/> before
-    ///     returning.
-    /// </remarks>
-    [ObsoleteAttribute ("This method is obsolete and will be removed in v2. Use Main instead.", false)]
-    public virtual void Run ()
-    {
-        // Must explicitly call Application.Shutdown method to shutdown.
-        Application.Run (Top);
-        Top.Dispose ();
-        Application.Shutdown ();
-    }
-
-    /// <summary>Override this to implement the <see cref="Scenario"/> setup logic (create controls, etc...).</summary>
-    /// <remarks>This is typically the best place to put scenario logic code.</remarks>
-    [ObsoleteAttribute ("This method is obsolete and will be removed in v2. Use Main instead.", false)]
-    public virtual void Setup () { }
-
-    /// <summary>
-    ///     The Toplevel for the <see cref="Scenario"/>. This should be set to <see cref="Terminal.Gui.Application.Top"/>.
-    /// </summary>
-
-    //[ObsoleteAttribute ("This property is obsolete and will be removed in v2. Use Main instead.", false)]
-    public Toplevel Top { get; set; }
-
     /// <summary>Gets the Scenario Name + Description with the Description padded based on the longest known Scenario name.</summary>
     /// <returns></returns>
     public override string ToString () { return $"{GetName ().PadRight (_maxScenarioNameLen)}{GetDescription ()}"; }
 
-    /// <summary>
-    ///     The Window for the <see cref="Scenario"/>. This should be set to <see cref="Terminal.Gui.Application.Top"/> in
-    ///     most cases.
-    /// </summary>
-
-    //[ObsoleteAttribute ("This property is obsolete and will be removed in v2. Use Main instead.", false)]
-    public Window Win { get; set; }
-
     #region IDispose
 
     public void Dispose ()
@@ -231,8 +157,6 @@ public class Scenario : IDisposable
         {
             if (disposing)
             {
-                Top?.Dispose ();
-                Win?.Dispose ();
             }
 
             _disposedValue = true;

+ 1 - 1
UICatalog/Scenarios/ASCIICustomButton.cs

@@ -149,7 +149,7 @@ public class ASCIICustomButtonTest : Scenario
 
         public ScrollViewTestWindow ()
         {
-            Title = "ScrollViewTestWindow";
+            Title = $"{Application.QuitKey} to Quit - Scenario: ScrollViewTestWindow";
 
             Label titleLabel = null;
 

+ 1 - 1
UICatalog/Scenarios/Adornments.cs

@@ -13,7 +13,7 @@ public class Adornments : Scenario
 
         Window app = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+            Title = GetQuitKeyAndName ()
         };
 
         var editor = new AdornmentsEditor

+ 1 - 1
UICatalog/Scenarios/AllViewsTester.cs

@@ -53,7 +53,7 @@ public class AllViewsTester : Scenario
 
         var app = new Window
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+            Title = GetQuitKeyAndName (),
             ColorScheme = Colors.ColorSchemes ["TopLevel"]
         };
 

+ 1 - 1
UICatalog/Scenarios/AnimationScenario.cs

@@ -23,7 +23,7 @@ public class AnimationScenario : Scenario
 
         var win = new Window
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+            Title = GetQuitKeyAndName (),
             X = 0,
             Y = 0,
             Width = Dim.Fill (),

+ 1 - 1
UICatalog/Scenarios/Bars.cs

@@ -28,7 +28,7 @@ public class Bars : Scenario
     // QuitKey and it only sticks if changed after init
     private void App_Loaded (object sender, EventArgs e)
     {
-        Application.Top.Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}";
+        Application.Top.Title = GetQuitKeyAndName ();
 
         ObservableCollection<string> eventSource = new ();
         ListView eventLog = new ListView ()

+ 1 - 1
UICatalog/Scenarios/BasicColors.cs

@@ -14,7 +14,7 @@ public class BasicColors : Scenario
 
         Window app = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+            Title = GetQuitKeyAndName (),
         };
 
         var vx = 30;

+ 1 - 1
UICatalog/Scenarios/Buttons.cs

@@ -18,7 +18,7 @@ public class Buttons : Scenario
 
         Window main = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+            Title = GetQuitKeyAndName ()
         };
 
         // Add a label & text field so we can demo IsDefault

+ 1 - 1
UICatalog/Scenarios/ChineseUI.cs

@@ -12,7 +12,7 @@ public class ChineseUI : Scenario
 
         var win = new Window
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+            Title = GetQuitKeyAndName (),
             X = 0,
             Y = 0,
             Width = Dim.Fill (),

+ 19 - 9
UICatalog/Scenarios/ClassExplorer.cs

@@ -17,11 +17,15 @@ public class ClassExplorer : Scenario
     private TextView _textView;
     private TreeView<object> _treeView;
 
-    public override void Setup ()
+    public override void Main ()
     {
-        Win.Title = GetName ();
-        Win.Y = 1; // menu
-        Win.Height = Dim.Fill (1); // status bar
+        Application.Init ();
+        var top = new Toplevel ();
+
+        var win = new Window
+        {
+            Title = GetName ()
+        };
 
         var menu = new MenuBar
         {
@@ -55,15 +59,15 @@ public class ClassExplorer : Scenario
                                 )
             ]
         };
-        Top.Add (menu);
+        top.Add (menu);
 
         _treeView = new TreeView<object> { X = 0, Y = 1, Width = Dim.Percent (50), Height = Dim.Fill () };
 
         var lblSearch = new Label { Text = "Search" };
         var tfSearch = new TextField { Width = 20, X = Pos.Right (lblSearch) };
 
-        Win.Add (lblSearch);
-        Win.Add (tfSearch);
+        win.Add (lblSearch);
+        win.Add (tfSearch);
 
         TreeViewTextFilter<object> filter = new (_treeView);
         _treeView.Filter = filter;
@@ -83,11 +87,17 @@ public class ClassExplorer : Scenario
         _treeView.TreeBuilder = new DelegateTreeBuilder<object> (ChildGetter, CanExpand);
         _treeView.SelectionChanged += TreeView_SelectionChanged;
 
-        Win.Add (_treeView);
+        win.Add (_treeView);
 
         _textView = new TextView { X = Pos.Right (_treeView), Y = 0, Width = Dim.Fill (), Height = Dim.Fill () };
 
-        Win.Add (_textView);
+        win.Add (_textView);
+
+        top.Add (win);
+
+        Application.Run (top);
+        top.Dispose ();
+        Application.Shutdown ();
     }
 
     private bool CanExpand (object arg) { return arg is Assembly || arg is Type || arg is ShowForType; }

+ 8 - 12
UICatalog/Scenarios/Clipping.cs

@@ -8,24 +8,16 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("Scrolling")]
 public class Clipping : Scenario
 {
-    public override void Init ()
+    public override void Main ()
     {
         Application.Init ();
-        Top = new ();
-        Top.ColorScheme = Colors.ColorSchemes ["Base"];
-    }
+        var win = new Window { Title = GetQuitKeyAndName () };
 
-    public override void Setup ()
-    {
-        //Win.X = 1;
-        //Win.Y = 2;
-        //Win.Width = Dim.Fill () - 4;
-        //Win.Height = Dim.Fill () - 2;
         var label = new Label
         {
             X = 0, Y = 0, Text = "ScrollView (new Rectangle (3, 3, 50, 20)) with a 200, 100 GetContentSize ()..."
         };
-        Top.Add (label);
+        win.Add (label);
 
         var scrollView = new ScrollView { X = 3, Y = 3, Width = 50, Height = 20 };
         scrollView.ColorScheme = Colors.ColorSchemes ["Menu"];
@@ -84,6 +76,10 @@ public class Clipping : Scenario
 
         scrollView.Add (embedded1);
 
-        Top.Add (scrollView);
+        win.Add (scrollView);
+
+        Application.Run (win);
+        win.Dispose ();
+        Application.Shutdown ();
     }
 }

+ 13 - 12
UICatalog/Scenarios/CollectionNavigatorTester.cs

@@ -74,19 +74,16 @@ public class CollectionNavigatorTester : Scenario
         "quitter"
     }.ToList ());
 
+    private Toplevel top;
     private ListView _listView;
     private TreeView _treeView;
 
     // Don't create a Window, just return the top-level view
-    public override void Init ()
+    public override void Main ()
     {
         Application.Init ();
-        Top = new ();
-        Top.ColorScheme = Colors.ColorSchemes ["Base"];
-    }
+        top = new Toplevel { ColorScheme = Colors.ColorSchemes ["Base"] };
 
-    public override void Setup ()
-    {
         var allowMarking = new MenuItem ("Allow _Marking", "", null)
         {
             CheckType = MenuItemCheckStyle.Checked, Checked = false
@@ -128,14 +125,18 @@ public class CollectionNavigatorTester : Scenario
             ]
         };
 
-        Top.Add (menu);
+        top.Add (menu);
 
         _items = new (_items.OrderBy (i => i, StringComparer.OrdinalIgnoreCase));
 
         CreateListView ();
         var vsep = new LineView (Orientation.Vertical) { X = Pos.Right (_listView), Y = 1, Height = Dim.Fill () };
-        Top.Add (vsep);
+        top.Add (vsep);
         CreateTreeView ();
+
+        Application.Run (top);
+        top.Dispose ();
+        Application.Shutdown ();
     }
 
     private void CreateListView ()
@@ -149,7 +150,7 @@ public class CollectionNavigatorTester : Scenario
             Width = Dim.Percent (50),
             Height = 1
         };
-        Top.Add (label);
+        top.Add (label);
 
         _listView = new ListView
         {
@@ -160,7 +161,7 @@ public class CollectionNavigatorTester : Scenario
             AllowsMarking = false,
             AllowsMultipleSelection = false
         };
-        Top.Add (_listView);
+        top.Add (_listView);
 
         _listView.SetSource (_items);
 
@@ -178,14 +179,14 @@ public class CollectionNavigatorTester : Scenario
             Width = Dim.Percent (50),
             Height = 1
         };
-        Top.Add (label);
+        top.Add (label);
 
         _treeView = new TreeView
         {
             X = Pos.Right (_listView) + 1, Y = Pos.Bottom (label), Width = Dim.Fill (), Height = Dim.Fill ()
         };
         _treeView.Style.HighlightModelTextOnly = true;
-        Top.Add (_treeView);
+        top.Add (_treeView);
 
         var root = new TreeNode ("IsLetterOrDigit examples");
 

+ 1 - 1
UICatalog/Scenarios/ColorPicker.cs

@@ -30,7 +30,7 @@ public class ColorPickers : Scenario
 
         Window app = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+            Title = GetQuitKeyAndName (),
         };
 
         // Foreground ColorPicker.

+ 24 - 24
UICatalog/Scenarios/CombiningMarks.cs

@@ -6,33 +6,33 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("Text and Formatting")]
 public class CombiningMarks : Scenario
 {
-    public override void Init ()
+    public override void Main ()
     {
         Application.Init ();
-        ConfigurationManager.Themes.Theme = Theme;
+        ConfigurationManager.Themes!.Theme = Theme;
         ConfigurationManager.Apply ();
-        Top = new ();
-        Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme];
-    }
+        var top = new Toplevel { ColorScheme = Colors.ColorSchemes [TopLevelColorScheme] };
 
-    public override void Setup ()
-    {
-        Top.DrawContentComplete += (s, e) =>
-                                               {
-                                                   Application.Driver.Move (0, 0);
-                                                   Application.Driver.AddStr ("Terminal.Gui only supports combining marks that normalize. See Issue #2616.");
-                                                   Application.Driver.Move (0, 2);
-                                                   Application.Driver.AddStr ("\u0301\u0301\u0328<- \"\\u301\\u301\\u328]\" using AddStr.");
-                                                   Application.Driver.Move (0, 3);
-                                                   Application.Driver.AddStr ("[a\u0301\u0301\u0328]<- \"[a\\u301\\u301\\u328]\" using AddStr.");
-                                                   Application.Driver.Move (0, 4);
-                                                   Application.Driver.AddRune ('[');
-                                                   Application.Driver.AddRune ('a');
-                                                   Application.Driver.AddRune ('\u0301');
-                                                   Application.Driver.AddRune ('\u0301');
-                                                   Application.Driver.AddRune ('\u0328');
-                                                   Application.Driver.AddRune (']');
-                                                   Application.Driver.AddStr ("<- \"[a\\u301\\u301\\u328]\" using AddRune for each.");
-                                               };
+        top.DrawContentComplete += (s, e) =>
+                                   {
+                                       Application.Driver.Move (0, 0);
+                                       Application.Driver.AddStr ("Terminal.Gui only supports combining marks that normalize. See Issue #2616.");
+                                       Application.Driver.Move (0, 2);
+                                       Application.Driver.AddStr ("\u0301\u0301\u0328<- \"\\u301\\u301\\u328]\" using AddStr.");
+                                       Application.Driver.Move (0, 3);
+                                       Application.Driver.AddStr ("[a\u0301\u0301\u0328]<- \"[a\\u301\\u301\\u328]\" using AddStr.");
+                                       Application.Driver.Move (0, 4);
+                                       Application.Driver.AddRune ('[');
+                                       Application.Driver.AddRune ('a');
+                                       Application.Driver.AddRune ('\u0301');
+                                       Application.Driver.AddRune ('\u0301');
+                                       Application.Driver.AddRune ('\u0328');
+                                       Application.Driver.AddRune (']');
+                                       Application.Driver.AddStr ("<- \"[a\\u301\\u301\\u328]\" using AddRune for each.");
+                                   };
+
+        Application.Run (top);
+        top.Dispose ();
+        Application.Shutdown ();
     }
 }

+ 13 - 7
UICatalog/Scenarios/ComboBoxIteration.cs

@@ -9,18 +9,20 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("ComboBox")]
 public class ComboBoxIteration : Scenario
 {
-    public override void Setup ()
+    public override void Main ()
     {
+        Application.Init ();
         ObservableCollection<string> items = ["one", "two", "three"];
 
+        var win = new Window { Title = GetQuitKeyAndName () };
         var lbListView = new Label { Width = 10, Height = 1 };
-        Win.Add (lbListView);
+        win.Add (lbListView);
 
         var listview = new ListView
         {
             Y = Pos.Bottom (lbListView) + 1, Width = 10, Height = Dim.Fill (2), Source = new ListWrapper<string> (items)
         };
-        Win.Add (listview);
+        win.Add (listview);
 
         var lbComboBox = new Label
         {
@@ -53,8 +55,8 @@ public class ComboBoxIteration : Scenario
                                                 listview.SelectedItem = text.Item;
                                             }
                                         };
-        Win.Add (lbComboBox, comboBox);
-        Win.Add (new TextField { X = Pos.Right (listview) + 1, Y = Pos.Top (comboBox) + 3, Height = 1, Width = 20 });
+        win.Add (lbComboBox, comboBox);
+        win.Add (new TextField { X = Pos.Right (listview) + 1, Y = Pos.Top (comboBox) + 3, Height = 1, Width = 20 });
 
         var btnTwo = new Button { X = Pos.Right (comboBox) + 1, Text = "Two" };
 
@@ -65,7 +67,7 @@ public class ComboBoxIteration : Scenario
                               listview.SetSource (items);
                               listview.SelectedItem = 0;
                           };
-        Win.Add (btnTwo);
+        win.Add (btnTwo);
 
         var btnThree = new Button { X = Pos.Right (comboBox) + 1, Y = Pos.Top (comboBox), Text = "Three" };
 
@@ -76,6 +78,10 @@ public class ComboBoxIteration : Scenario
                                 listview.SetSource (items);
                                 listview.SelectedItem = 0;
                             };
-        Win.Add (btnThree);
+        win.Add (btnThree);
+
+        Application.Run (win);
+        win.Dispose ();
+        Application.Shutdown ();
     }
 }

+ 1 - 1
UICatalog/Scenarios/ComputedLayout.cs

@@ -20,7 +20,7 @@ public class ComputedLayout : Scenario
 
         Window app = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+            Title = GetQuitKeyAndName (),
         };
 
         // Demonstrate using Dim to create a horizontal ruler that always measures the parent window's width

+ 1 - 1
UICatalog/Scenarios/ContentScrolling.cs

@@ -104,7 +104,7 @@ public class ContentScrolling : Scenario
 
         Window app = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+            Title = GetQuitKeyAndName (),
 
             // Use a different colorscheme so ViewSettings.ClearContentOnly is obvious
             ColorScheme = Colors.ColorSchemes ["Toplevel"]

+ 1 - 1
UICatalog/Scenarios/ContextMenus.cs

@@ -25,7 +25,7 @@ public class ContextMenus : Scenario
         // Setup - Create a top-level application window and configure it.
         Window appWindow = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+            Title = GetQuitKeyAndName ()
         };
 
         var text = "Context Menu";

+ 1 - 1
UICatalog/Scenarios/DatePickers.cs

@@ -13,7 +13,7 @@ public class DatePickers : Scenario
 
         Window app = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+            Title = GetQuitKeyAndName ()
         };
 
         var datePicker = new DatePicker { Y = Pos.Center (), X = Pos.Center () };

+ 1 - 1
UICatalog/Scenarios/Dialogs.cs

@@ -17,7 +17,7 @@ public class Dialogs : Scenario
 
         Window app = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+            Title = GetQuitKeyAndName ()
         };
 
         var frame = new FrameView

+ 1 - 1
UICatalog/Scenarios/DimAutoDemo.cs

@@ -15,7 +15,7 @@ public class DimAutoDemo : Scenario
         // Setup - Create a top-level application window and configure it.
         Window appWindow = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+            Title = GetQuitKeyAndName (),
         };
 
         // For diagnostics

+ 1 - 1
UICatalog/Scenarios/DynamicMenuBar.cs

@@ -21,7 +21,7 @@ public class DynamicMenuBar : Scenario
         // Setup - Create a top-level application window and configure it.
         DynamicMenuBarSample appWindow = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+            Title = GetQuitKeyAndName ()
         };
 
         // Run - Start the application.

+ 1 - 1
UICatalog/Scenarios/DynamicStatusBar.cs

@@ -317,7 +317,7 @@ public class DynamicStatusBar : Scenario
         {
             DataContext = new DynamicStatusItemModel ();
 
-            Title = $"{Application.QuitKey} to Quit";
+            Title = $"{Application.QuitKey} to Quit - Scenario: Dynamic StatusBar";
 
             var _frmStatusBar = new FrameView
             {

+ 1 - 1
UICatalog/Scenarios/Editor.cs

@@ -46,7 +46,7 @@ public class Editor : Scenario
         // Setup - Create a top-level application window and configure it.
         _appWindow = new ()
         {
-            //Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+            //Title = GetQuitKeyAndName (),
             Title = _fileName ?? "Untitled",
             BorderStyle = LineStyle.None
         };

+ 36 - 30
UICatalog/Scenarios/FileDialogExamples.cs

@@ -26,104 +26,110 @@ public class FileDialogExamples : Scenario
     private TextField _tbCancelButton;
     private TextField _tbOkButton;
 
-    public override void Setup ()
+    public override void Main ()
     {
+        Application.Init ();
         var y = 0;
         var x = 1;
+        var win = new Window { Title = GetQuitKeyAndName () };
 
         _cbMustExist = new CheckBox { State = CheckState.Checked, Y = y++, X = x, Text = "Must Exist" };
-        Win.Add (_cbMustExist);
+        win.Add (_cbMustExist);
 
         _cbUseColors = new CheckBox { State = FileDialogStyle.DefaultUseColors ? CheckState.Checked : CheckState.UnChecked, Y = y++, X = x, Text = "Use Colors" };
-        Win.Add (_cbUseColors);
+        win.Add (_cbUseColors);
 
         _cbCaseSensitive = new CheckBox { State = CheckState.UnChecked, Y = y++, X = x, Text = "Case Sensitive Search" };
-        Win.Add (_cbCaseSensitive);
+        win.Add (_cbCaseSensitive);
 
         _cbAllowMultipleSelection = new CheckBox { State = CheckState.UnChecked, Y = y++, X = x, Text = "Multiple" };
-        Win.Add (_cbAllowMultipleSelection);
+        win.Add (_cbAllowMultipleSelection);
 
         _cbShowTreeBranchLines = new CheckBox { State = CheckState.Checked, Y = y++, X = x, Text = "Tree Branch Lines" };
-        Win.Add (_cbShowTreeBranchLines);
+        win.Add (_cbShowTreeBranchLines);
 
         _cbAlwaysTableShowHeaders = new CheckBox { State = CheckState.Checked, Y = y++, X = x, Text = "Always Show Headers" };
-        Win.Add (_cbAlwaysTableShowHeaders);
+        win.Add (_cbAlwaysTableShowHeaders);
 
         _cbDrivesOnlyInTree = new CheckBox { State = CheckState.UnChecked, Y = y++, X = x, Text = "Only Show Drives" };
-        Win.Add (_cbDrivesOnlyInTree);
+        win.Add (_cbDrivesOnlyInTree);
 
         y = 0;
         x = 24;
 
-        Win.Add (
+        win.Add (
                  new LineView (Orientation.Vertical) { X = x++, Y = 1, Height = 4 }
                 );
-        Win.Add (new Label { X = x++, Y = y++, Text = "Caption" });
+        win.Add (new Label { X = x++, Y = y++, Text = "Caption" });
 
         _rgCaption = new RadioGroup { X = x, Y = y };
         _rgCaption.RadioLabels = new [] { "Ok", "Open", "Save" };
-        Win.Add (_rgCaption);
+        win.Add (_rgCaption);
 
         y = 0;
         x = 34;
 
-        Win.Add (
+        win.Add (
                  new LineView (Orientation.Vertical) { X = x++, Y = 1, Height = 4 }
                 );
-        Win.Add (new Label { X = x++, Y = y++, Text = "OpenMode" });
+        win.Add (new Label { X = x++, Y = y++, Text = "OpenMode" });
 
         _rgOpenMode = new RadioGroup { X = x, Y = y };
         _rgOpenMode.RadioLabels = new [] { "File", "Directory", "Mixed" };
-        Win.Add (_rgOpenMode);
+        win.Add (_rgOpenMode);
 
         y = 0;
         x = 48;
 
-        Win.Add (
+        win.Add (
                  new LineView (Orientation.Vertical) { X = x++, Y = 1, Height = 4 }
                 );
-        Win.Add (new Label { X = x++, Y = y++, Text = "Icons" });
+        win.Add (new Label { X = x++, Y = y++, Text = "Icons" });
 
         _rgIcons = new RadioGroup { X = x, Y = y };
         _rgIcons.RadioLabels = new [] { "None", "Unicode", "Nerd*" };
-        Win.Add (_rgIcons);
+        win.Add (_rgIcons);
 
-        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)" });
+        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 (
+        win.Add (
                  new LineView (Orientation.Vertical) { X = x++, Y = y + 1, Height = 4 }
                 );
-        Win.Add (new Label { X = x++, Y = y++, Text = "Allowed" });
+        win.Add (new Label { X = x++, Y = y++, Text = "Allowed" });
 
         _rgAllowedTypes = new RadioGroup { X = x, Y = y };
         _rgAllowedTypes.RadioLabels = new [] { "Any", "Csv (Recommended)", "Csv (Strict)" };
-        Win.Add (_rgAllowedTypes);
+        win.Add (_rgAllowedTypes);
 
         y = 5;
         x = 45;
 
-        Win.Add (
+        win.Add (
                  new LineView (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 = "Buttons" });
 
-        Win.Add (new Label { X = x, Y = y++, Text = "Ok Text:" });
+        win.Add (new Label { X = x, Y = y++, Text = "Ok Text:" });
         _tbOkButton = new TextField { X = x, Y = y++, Width = 12 };
-        Win.Add (_tbOkButton);
-        Win.Add (new Label { X = x, Y = y++, Text = "Cancel Text:" });
+        win.Add (_tbOkButton);
+        win.Add (new Label { X = x, Y = y++, Text = "Cancel Text:" });
         _tbCancelButton = new TextField { X = x, Y = y++, Width = 12 };
-        Win.Add (_tbCancelButton);
+        win.Add (_tbCancelButton);
         _cbFlipButtonOrder = new CheckBox { X = x, Y = y++, Text = "Flip Order" };
-        Win.Add (_cbFlipButtonOrder);
+        win.Add (_cbFlipButtonOrder);
 
         var btn = new Button { X = 1, Y = 9, Text = "Run Dialog" };
 
         SetupHandler (btn);
-        Win.Add (btn);
+        win.Add (btn);
+
+        Application.Run (win);
+        win.Dispose ();
+        Application.Shutdown ();
     }
 
     private void ConfirmOverwrite (object sender, FilesSelectedEventArgs e)

+ 1 - 1
UICatalog/Scenarios/Generic.cs

@@ -14,7 +14,7 @@ public sealed class MyScenario : Scenario
         // Setup - Create a top-level application window and configure it.
         Window appWindow = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+            Title = GetQuitKeyAndName (),
         };
 
         var button = new Button { X = Pos.Center (), Y = Pos.Center (), Text = "Press me!" };

+ 1 - 1
UICatalog/Scenarios/HotKeys.cs

@@ -13,7 +13,7 @@ public class HotKeys : Scenario
 
         Window app = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+            Title = GetQuitKeyAndName ()
         };
 
         var textViewLabel = new Label { Text = "_TextView:", X = 0, Y = 0 };

+ 58 - 52
UICatalog/Scenarios/Images.cs

@@ -15,14 +15,15 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("Drawing")]
 public class Images : Scenario
 {
-    public override void Setup ()
+    public override void Main ()
     {
-        base.Setup ();
+        Application.Init ();
+        var win = new Window { Title = $"{Application.QuitKey} to Quit - Scenario: {GetName()}" };
 
         bool canTrueColor = Application.Driver.SupportsTrueColor;
 
         var lblDriverName = new Label { X = 0, Y = 0, Text = $"Driver is {Application.Driver.GetType ().Name}" };
-        Win.Add (lblDriverName);
+        win.Add (lblDriverName);
 
         var cbSupportsTrueColor = new CheckBox
         {
@@ -32,7 +33,7 @@ public class Images : Scenario
             CanFocus = false,
             Text = "supports true color "
         };
-        Win.Add (cbSupportsTrueColor);
+        win.Add (cbSupportsTrueColor);
 
         var cbUseTrueColor = new CheckBox
         {
@@ -43,63 +44,68 @@ public class Images : Scenario
             Text = "Use true color"
         };
         cbUseTrueColor.Toggle += (_, evt) => Application.Force16Colors = evt.NewValue == CheckState.UnChecked;
-        Win.Add (cbUseTrueColor);
+        win.Add (cbUseTrueColor);
 
         var btnOpenImage = new Button { X = Pos.Right (cbUseTrueColor) + 2, Y = 0, Text = "Open Image" };
-        Win.Add (btnOpenImage);
+        win.Add (btnOpenImage);
 
         var imageView = new ImageView
         {
             X = 0, Y = Pos.Bottom (lblDriverName), Width = Dim.Fill (), Height = Dim.Fill ()
         };
-        Win.Add (imageView);
+        win.Add (imageView);
 
         btnOpenImage.Accept += (_, _) =>
-                                {
-                                    var ofd = new OpenDialog { Title = "Open Image", AllowsMultipleSelection = false };
-                                    Application.Run (ofd);
-
-                                    if (ofd.Path is { })
-                                    {
-                                        Directory.SetCurrentDirectory (Path.GetFullPath (Path.GetDirectoryName (ofd.Path)!));
-                                    }
-
-                                    if (ofd.Canceled)
-                                    {
-                                        ofd.Dispose ();
-                                        return;
-                                    }
-
-                                    string path = ofd.FilePaths [0];
-
-                                    ofd.Dispose ();
-
-                                    if (string.IsNullOrWhiteSpace (path))
-                                    {
-                                        return;
-                                    }
-
-                                    if (!File.Exists (path))
-                                    {
-                                        return;
-                                    }
-
-                                    Image<Rgba32> img;
-
-                                    try
-                                    {
-                                        img = Image.Load<Rgba32> (File.ReadAllBytes (path));
-                                    }
-                                    catch (Exception ex)
-                                    {
-                                        MessageBox.ErrorQuery ("Could not open file", ex.Message, "Ok");
-
-                                        return;
-                                    }
-
-                                    imageView.SetImage (img);
-                                    Application.Refresh ();
-                                };
+                               {
+                                   var ofd = new OpenDialog { Title = "Open Image", AllowsMultipleSelection = false };
+                                   Application.Run (ofd);
+
+                                   if (ofd.Path is { })
+                                   {
+                                       Directory.SetCurrentDirectory (Path.GetFullPath (Path.GetDirectoryName (ofd.Path)!));
+                                   }
+
+                                   if (ofd.Canceled)
+                                   {
+                                       ofd.Dispose ();
+
+                                       return;
+                                   }
+
+                                   string path = ofd.FilePaths [0];
+
+                                   ofd.Dispose ();
+
+                                   if (string.IsNullOrWhiteSpace (path))
+                                   {
+                                       return;
+                                   }
+
+                                   if (!File.Exists (path))
+                                   {
+                                       return;
+                                   }
+
+                                   Image<Rgba32> img;
+
+                                   try
+                                   {
+                                       img = Image.Load<Rgba32> (File.ReadAllBytes (path));
+                                   }
+                                   catch (Exception ex)
+                                   {
+                                       MessageBox.ErrorQuery ("Could not open file", ex.Message, "Ok");
+
+                                       return;
+                                   }
+
+                                   imageView.SetImage (img);
+                                   Application.Refresh ();
+                               };
+
+        Application.Run (win);
+        win.Dispose ();
+        Application.Shutdown ();
     }
 
     private class ImageView : View

+ 13 - 4
UICatalog/Scenarios/InvertColors.cs

@@ -10,9 +10,14 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("Text and Formatting")]
 public class InvertColors : Scenario
 {
-    public override void Setup ()
+    public override void Main ()
     {
-        Win.ColorScheme = Colors.ColorSchemes ["TopLevel"];
+        Application.Init ();
+        var win = new Window
+        {
+            Title = GetQuitKeyAndName (),
+            ColorScheme = Colors.ColorSchemes ["TopLevel"]
+        };
 
         List<Label> labels = new ();
         ColorName [] foreColors = Enum.GetValues (typeof (ColorName)).Cast<ColorName> ().ToArray ();
@@ -25,7 +30,7 @@ public class InvertColors : Scenario
 
             var label = new Label { ColorScheme = new ColorScheme (), Y = y, Text = $"{fore} on {back}" };
             label.ColorScheme = new ColorScheme (label.ColorScheme) { Normal = color };
-            Win.Add (label);
+            win.Add (label);
             labels.Add (label);
         }
 
@@ -43,6 +48,10 @@ public class InvertColors : Scenario
                                   label.SetNeedsDisplay ();
                               }
                           };
-        Win.Add (button);
+        win.Add (button);
+
+        Application.Run (win);
+        win.Dispose ();
+        Application.Shutdown ();
     }
 }

+ 1 - 1
UICatalog/Scenarios/KeyBindings.cs

@@ -22,7 +22,7 @@ public sealed class KeyBindings : Scenario
         // Setup - Create a top-level application window and configure it.
         Window appWindow = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+            Title = GetQuitKeyAndName (),
             SuperViewRendersLineCanvas = true,
         };
 

+ 19 - 13
UICatalog/Scenarios/Keys.cs

@@ -7,16 +7,18 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("Mouse and Keyboard")]
 public class Keys : Scenario
 {
-    public override void Setup ()
+    public override void Main ()
     {
+        Application.Init ();
         ObservableCollection<string> keyPressedList = [];
         ObservableCollection<string> invokingKeyBindingsList = new ();
 
+        var win = new Window { Title = GetQuitKeyAndName () };
         var editLabel = new Label { X = 0, Y = 0, Text = "Type text here:" };
-        Win.Add (editLabel);
+        win.Add (editLabel);
 
         var edit = new TextField { X = Pos.Right (editLabel) + 1, Y = Pos.Top (editLabel), Width = Dim.Fill (2) };
-        Win.Add (edit);
+        win.Add (edit);
 
         edit.KeyDown += (s, a) => { keyPressedList.Add (a.ToString ()); };
 
@@ -33,9 +35,9 @@ public class Keys : Scenario
         {
             X = Pos.Left (editLabel), Y = Pos.Top (editLabel) + 1, Text = "Last TextView.KeyPressed:"
         };
-        Win.Add (keyPressedLabel);
+        win.Add (keyPressedLabel);
         var labelTextViewKeypress = new Label { X = Pos.Right (keyPressedLabel) + 1, Y = Pos.Top (keyPressedLabel) };
-        Win.Add (labelTextViewKeypress);
+        win.Add (labelTextViewKeypress);
 
         edit.KeyDown += (s, e) => labelTextViewKeypress.Text = e.ToString ();
 
@@ -43,9 +45,9 @@ public class Keys : Scenario
         {
             X = Pos.Left (keyPressedLabel), Y = Pos.Bottom (keyPressedLabel), Text = "Last Application.KeyDown:"
         };
-        Win.Add (keyPressedLabel);
+        win.Add (keyPressedLabel);
         var labelAppKeypress = new Label { X = Pos.Right (keyPressedLabel) + 1, Y = Pos.Top (keyPressedLabel) };
-        Win.Add (labelAppKeypress);
+        win.Add (labelAppKeypress);
 
         Application.KeyDown += (s, e) => labelAppKeypress.Text = e.ToString ();
 
@@ -54,7 +56,7 @@ public class Keys : Scenario
         {
             X = Pos.Left (editLabel), Y = Pos.Top (editLabel) + 4, Text = "Application Key Events:"
         };
-        Win.Add (keyLogLabel);
+        win.Add (keyLogLabel);
         int maxKeyString = Key.CursorRight.WithAlt.WithCtrl.WithShift.ToString ().Length;
         var yOffset = 1;
         ObservableCollection<string> keyEventlist = new ();
@@ -68,14 +70,14 @@ public class Keys : Scenario
             Source = new ListWrapper<string> (keyEventlist)
         };
         keyEventListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
-        Win.Add (keyEventListView);
+        win.Add (keyEventListView);
 
         // OnKeyPressed
         var onKeyPressedLabel = new Label
         {
             X = Pos.Right (keyEventListView) + 1, Y = Pos.Top (editLabel) + 4, Text = "TextView KeyDown:"
         };
-        Win.Add (onKeyPressedLabel);
+        win.Add (onKeyPressedLabel);
 
         yOffset = 1;
 
@@ -88,7 +90,7 @@ public class Keys : Scenario
             Source = new ListWrapper<string> (keyPressedList)
         };
         onKeyPressedListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
-        Win.Add (onKeyPressedListView);
+        win.Add (onKeyPressedListView);
 
         // OnInvokeKeyBindings
         var onInvokingKeyBindingsLabel = new Label
@@ -97,7 +99,7 @@ public class Keys : Scenario
             Y = Pos.Top (editLabel) + 4,
             Text = "TextView InvokingKeyBindings:"
         };
-        Win.Add (onInvokingKeyBindingsLabel);
+        win.Add (onInvokingKeyBindingsLabel);
 
         var onInvokingKeyBindingsListView = new ListView
         {
@@ -108,7 +110,7 @@ public class Keys : Scenario
             Source = new ListWrapper<string> (invokingKeyBindingsList)
         };
         onInvokingKeyBindingsListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
-        Win.Add (onInvokingKeyBindingsListView);
+        win.Add (onInvokingKeyBindingsListView);
 
         //Application.KeyDown += (s, a) => KeyDownPressUp (a, "Down");
         Application.KeyDown += (s, a) => KeyDownPressUp (a, "Down");
@@ -123,5 +125,9 @@ public class Keys : Scenario
             onKeyPressedListView.MoveDown ();
             onInvokingKeyBindingsListView.MoveDown ();
         }
+
+        Application.Run (win);
+        win.Dispose ();
+        Application.Shutdown ();
     }
 }

+ 1 - 1
UICatalog/Scenarios/LineCanvasExperiment.cs

@@ -14,7 +14,7 @@ public class LineCanvasExperiment : Scenario
 
         Window app = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+            Title = GetQuitKeyAndName ()
         };
 
         var frame1 = new FrameView

+ 10 - 4
UICatalog/Scenarios/LineDrawing.cs

@@ -10,8 +10,10 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("Drawing")]
 public class LineDrawing : Scenario
 {
-    public override void Setup ()
+    public override void Main ()
     {
+        Application.Init ();
+        var win = new Window { Title = GetQuitKeyAndName () };
         var canvas = new DrawingArea { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () };
 
         var tools = new ToolsView { Title = "Tools", X = Pos.Right (canvas) - 20, Y = 2 };
@@ -20,10 +22,14 @@ public class LineDrawing : Scenario
         tools.SetStyle += b => canvas.LineStyle = b;
         tools.AddLayer += () => canvas.AddLayer ();
 
-        Win.Add (canvas);
-        Win.Add (tools);
+        win.Add (canvas);
+        win.Add (tools);
 
-        Win.KeyDown += (s, e) => { e.Handled = canvas.OnKeyDown (e); };
+        win.KeyDown += (s, e) => { e.Handled = canvas.OnKeyDown (e); };
+
+        Application.Run (win);
+        win.Dispose ();
+        Application.Shutdown ();
     }
 
     private class DrawingArea : View

+ 7 - 5
UICatalog/Scenarios/LineViewExample.cs

@@ -13,7 +13,7 @@ public class LineViewExample : Scenario
     {
         Application.Init ();
         // Setup - Create a top-level application window and configure it.
-        Toplevel appWindow = new ();
+        Toplevel top = new ();
 
         var menu = new MenuBar
         {
@@ -22,8 +22,9 @@ public class LineViewExample : Scenario
                 new ("_File", new MenuItem [] { new ("_Quit", "", () => Quit ()) })
             ]
         };
-        appWindow.Add (menu);
+        top.Add (menu);
 
+        var appWindow = new Window ();
         appWindow.Add (new Label { Y = 1, Text = "Regular Line" });
 
         // creates a horizontal line
@@ -78,11 +79,12 @@ public class LineViewExample : Scenario
                                            new (Application.QuitKey, "Quit", Quit)
                                        }
                                       );
-        appWindow.Add (statusBar);
+        top.Add (statusBar);
+        top.Add (appWindow);
 
         // Run - Start the application.
-        Application.Run (appWindow);
-        appWindow.Dispose ();
+        Application.Run (top);
+        top.Dispose ();
 
         // Shutdown - Calling Application.Shutdown is required.
         Application.Shutdown ();

+ 10 - 9
UICatalog/Scenarios/ListColumns.cs

@@ -53,17 +53,16 @@ public class ListColumns : Scenario
         Application.Init ();
 
         // Setup - Create a top-level application window and configure it.
-        Toplevel appWindow = new ()
+        Toplevel top = new ();
+        Window appWindow = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+            Title = GetQuitKeyAndName ()
         };
 
         _listColView = new ()
         {
-            X = 0,
-            Y = 1,
             Width = Dim.Fill (),
-            Height = Dim.Fill (1),
+            Height = Dim.Fill (),
             Style = new ()
             {
                 ShowHeaders = false,
@@ -212,7 +211,7 @@ public class ListColumns : Scenario
             ]
         };
 
-        appWindow.Add (menu);
+        top.Add (menu);
 
         var statusBar = new StatusBar (
                                        new Shortcut []
@@ -223,7 +222,7 @@ public class ListColumns : Scenario
                                            new (Application.QuitKey, "Quit", Quit)
                                        }
                                       );
-        appWindow.Add (statusBar);
+        top.Add (statusBar);
 
         appWindow.Add (_listColView);
 
@@ -257,9 +256,11 @@ public class ListColumns : Scenario
 
         _listColView.KeyBindings.Add (Key.Space, Command.Accept);
 
+        top.Add (appWindow);
+
         // Run - Start the application.
-        Application.Run (appWindow);
-        appWindow.Dispose ();
+        Application.Run (top);
+        top.Dispose ();
 
         // Shutdown - Calling Application.Shutdown is required.
         Application.Shutdown ();

+ 1 - 1
UICatalog/Scenarios/ListViewWithSelection.cs

@@ -27,7 +27,7 @@ public class ListViewWithSelection : Scenario
 
         _appWindow = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+            Title = GetQuitKeyAndName (),
         };
 
         _scenarios = GetScenarios ();

+ 10 - 4
UICatalog/Scenarios/ListsAndCombos.cs

@@ -12,8 +12,9 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("ComboBox")]
 public class ListsAndCombos : Scenario
 {
-    public override void Setup ()
+    public override void Main ()
     {
+        Application.Init ();
         //TODO: Duplicated code in Demo.cs Consider moving to shared assembly
         ObservableCollection<string> items = [];
 
@@ -31,6 +32,7 @@ public class ListsAndCombos : Scenario
             }
         }
 
+        var win = new Window { Title = GetQuitKeyAndName () };
         // ListView
         var lbListView = new Label
         {
@@ -50,7 +52,7 @@ public class ListsAndCombos : Scenario
             Source = new ListWrapper<string> (items)
         };
         listview.SelectedItemChanged += (s, e) => lbListView.Text = items [listview.SelectedItem];
-        Win.Add (lbListView, listview);
+        win.Add (lbListView, listview);
 
         var scrollBar = new ScrollBarView (listview, true);
 
@@ -107,7 +109,7 @@ public class ListsAndCombos : Scenario
         comboBox.SetSource (items);
 
         comboBox.SelectedItemChanged += (s, text) => lbComboBox.Text = text.Value.ToString ();
-        Win.Add (lbComboBox, comboBox);
+        win.Add (lbComboBox, comboBox);
 
         var scrollBarCbx = new ScrollBarView (comboBox.Subviews [1], true);
 
@@ -153,6 +155,10 @@ public class ListsAndCombos : Scenario
         };
         btnMoveDown.Accept += (s, e) => { listview.MoveDown (); };
 
-        Win.Add (btnMoveUp, btnMoveDown);
+        win.Add (btnMoveUp, btnMoveDown);
+
+        Application.Run (win);
+        win.Dispose ();
+        Application.Shutdown ();
     }
 }

+ 20 - 13
UICatalog/Scenarios/Localization.cs

@@ -41,9 +41,11 @@ public class Localization : Scenario
         Application.Refresh ();
     }
 
-    public override void Setup ()
+    public override void Main ()
     {
-        base.Setup ();
+        Application.Init ();
+        var top = new Toplevel ();
+        var win = new Window { Title = GetQuitKeyAndName () };
         _cultureInfoSource = Application.SupportedCultures.Append (CultureInfo.InvariantCulture).ToArray ();
 
         _cultureInfoNameSource = Application.SupportedCultures.Select (c => $"{c.NativeName} ({c.Name})")
@@ -93,7 +95,7 @@ public class Localization : Scenario
                     )
             ]
         };
-        Top.Add (menu);
+        top.Add (menu);
 
         var selectLanguageLabel = new Label
         {
@@ -103,7 +105,7 @@ public class Localization : Scenario
             Width = Dim.Fill (2),
             Text = "Please select a language."
         };
-        Win.Add (selectLanguageLabel);
+        win.Add (selectLanguageLabel);
 
         _languageComboBox = new()
         {
@@ -117,7 +119,7 @@ public class Localization : Scenario
         };
         _languageComboBox.SetSource<string> (new (_cultureInfoNameSource));
         _languageComboBox.SelectedItemChanged += LanguageComboBox_SelectChanged;
-        Win.Add (_languageComboBox);
+        win.Add (_languageComboBox);
 
         var textAndFileDialogLabel = new Label
         {
@@ -129,13 +131,13 @@ public class Localization : Scenario
             Text =
                 "Right click on the text field to open a context menu, click the button to open a file dialog.\r\nOpen mode will loop through 'File', 'Directory' and 'Mixed' as 'Open' or 'Save' button clicked."
         };
-        Win.Add (textAndFileDialogLabel);
+        win.Add (textAndFileDialogLabel);
 
         var textField = new TextView
         {
             X = 2, Y = Pos.Bottom (textAndFileDialogLabel) + 1, Width = Dim.Fill (32), Height = 1
         };
-        Win.Add (textField);
+        win.Add (textField);
 
         _allowAnyCheckBox = new()
         {
@@ -144,21 +146,21 @@ public class Localization : Scenario
             State = CheckState.UnChecked,
             Text = "Allow any"
         };
-        Win.Add (_allowAnyCheckBox);
+        win.Add (_allowAnyCheckBox);
 
         var openDialogButton = new Button
         {
             X = Pos.Right (_allowAnyCheckBox) + 1, Y = Pos.Bottom (textAndFileDialogLabel) + 1, Text = "Open"
         };
         openDialogButton.Accept += (sender, e) => ShowFileDialog (false);
-        Win.Add (openDialogButton);
+        win.Add (openDialogButton);
 
         var saveDialogButton = new Button
         {
             X = Pos.Right (openDialogButton) + 1, Y = Pos.Bottom (textAndFileDialogLabel) + 1, Text = "Save"
         };
         saveDialogButton.Accept += (sender, e) => ShowFileDialog (true);
-        Win.Add (saveDialogButton);
+        win.Add (saveDialogButton);
 
         var wizardLabel = new Label
         {
@@ -168,13 +170,18 @@ public class Localization : Scenario
             Width = Dim.Fill (2),
             Text = "Click the button to open a wizard."
         };
-        Win.Add (wizardLabel);
+        win.Add (wizardLabel);
 
         var wizardButton = new Button { X = 2, Y = Pos.Bottom (wizardLabel) + 1, Text = "Open _wizard" };
         wizardButton.Accept += (sender, e) => ShowWizard ();
-        Win.Add (wizardButton);
+        win.Add (wizardButton);
 
-        Win.Unloaded += (sender, e) => Quit ();
+        win.Unloaded += (sender, e) => Quit ();
+        top.Add (win);
+
+        Application.Run (top);
+        top.Dispose ();
+        Application.Shutdown ();
     }
 
     public void ShowFileDialog (bool isSaveFile)

+ 1 - 1
UICatalog/Scenarios/MenuBarScenario.cs

@@ -22,7 +22,7 @@ public class MenuBarScenario : Scenario
         // Setup - Create a top-level application window and configure it.
         Window appWindow = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+            Title = GetQuitKeyAndName (),
             BorderStyle = LineStyle.None
         };
 

+ 1 - 1
UICatalog/Scenarios/MessageBoxes.cs

@@ -15,7 +15,7 @@ public class MessageBoxes : Scenario
 
         Window app = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+            Title = GetQuitKeyAndName ()
         };
 
         var frame = new FrameView

+ 1 - 1
UICatalog/Scenarios/Mouse.cs

@@ -15,7 +15,7 @@ public class Mouse : Scenario
 
         Window win = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+            Title = GetQuitKeyAndName ()
         };
 
         Slider<MouseFlags> filterSlider = new ()

+ 1 - 1
UICatalog/Scenarios/MultiColouredTable.cs

@@ -22,7 +22,7 @@ public class MultiColouredTable : Scenario
         // Setup - Create a top-level application window and configure it.
         Toplevel appWindow = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+            Title = GetQuitKeyAndName ()
         };
 
         _tableView = new () { X = 0, Y = 1, Width = Dim.Fill (), Height = Dim.Fill (1) };

+ 13 - 5
UICatalog/Scenarios/ProcessTable.cs

@@ -11,11 +11,15 @@ public class ProcessTable : Scenario
 {
     private TableView tableView;
 
-    public override void Setup ()
+    public override void Main ()
     {
-        Win.Title = GetName ();
-        Win.Y = 1; // menu
-        Win.Height = Dim.Fill (1); // status bar
+        Application.Init ();
+        var win = new Window
+        {
+            Title = GetName (),
+            Y = 1, // menu
+            Height = Dim.Fill (1) // status bar
+        };
 
         tableView = new TableView { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill (1) };
 
@@ -33,7 +37,11 @@ public class ProcessTable : Scenario
                                 }
                                );
 
-        Win.Add (tableView);
+        win.Add (tableView);
+
+        Application.Run (win);
+        win.Dispose ();
+        Application.Shutdown ();
     }
 
     private void CreateProcessTable ()

+ 12 - 5
UICatalog/Scenarios/Progress.cs

@@ -15,13 +15,16 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("Progress")]
 public class Progress : Scenario
 {
+    private Window win;
     private uint _mainLooopTimeoutTick = 100; // ms
     private object _mainLoopTimeout;
     private Timer _systemTimer;
     private uint _systemTimerTick = 100; // ms
 
-    public override void Setup ()
+    public override void Main ()
     {
+        Application.Init ();
+        win = new Window { Title = GetQuitKeyAndName () };
         // Demo #1 - Use System.Timer (and threading)
         var systemTimerDemo = new ProgressDemo
         {
@@ -78,7 +81,7 @@ public class Progress : Scenario
                                                      Debug.WriteLine ("bad entry");
                                                  }
                                              };
-        Win.Add (systemTimerDemo);
+        win.Add (systemTimerDemo);
 
         // Demo #2 - Use Application.AddTimeout (no threads)
         var mainLoopTimeoutDemo = new ProgressDemo
@@ -135,7 +138,7 @@ public class Progress : Scenario
                                                          }
                                                      }
                                                  };
-        Win.Add (mainLoopTimeoutDemo);
+        win.Add (mainLoopTimeoutDemo);
 
         var startBoth = new Button { X = Pos.Center (), Y = Pos.Bottom (mainLoopTimeoutDemo) + 1, Text = "Start Both" };
 
@@ -144,12 +147,16 @@ public class Progress : Scenario
                                  systemTimerDemo.Start ();
                                  mainLoopTimeoutDemo.Start ();
                              };
-        Win.Add (startBoth);
+        win.Add (startBoth);
+
+        Application.Run (win);
+        win.Dispose ();
+        Application.Shutdown ();
     }
 
     protected override void Dispose (bool disposing)
     {
-        foreach (ProgressDemo v in Win.Subviews.OfType<ProgressDemo> ())
+        foreach (ProgressDemo v in win.Subviews.OfType<ProgressDemo> ())
         {
             v?.StopBtnClick ();
         }

+ 1 - 1
UICatalog/Scenarios/ProgressBarStyles.cs

@@ -30,7 +30,7 @@ public class ProgressBarStyles : Scenario
 
         Window app = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}", BorderStyle = LineStyle.Single,
+            Title = GetQuitKeyAndName (), BorderStyle = LineStyle.Single,
         };
 
         var editor = new AdornmentsEditor ()

+ 1 - 1
UICatalog/Scenarios/Scrolling.cs

@@ -19,7 +19,7 @@ public class Scrolling : Scenario
 
         var app = new Window
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+            Title = GetQuitKeyAndName (),
 
             // Offset to stress clipping
             X = 3,

+ 18 - 12
UICatalog/Scenarios/SendKeys.cs

@@ -7,28 +7,30 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("Mouse and Keyboard")]
 public class SendKeys : Scenario
 {
-    public override void Setup ()
+    public override void Main ()
     {
+        Application.Init ();
+        var win = new Window { Title = GetQuitKeyAndName () };
         var label = new Label { X = Pos.Center (), Y = Pos.Center () - 6, Text = "Insert the text to send:" };
-        Win.Add (label);
+        win.Add (label);
 
         var txtInput = new TextField { X = Pos.Center (), Y = Pos.Center () - 5, Width = 20, Text = "MockKeyPresses" };
-        Win.Add (txtInput);
+        win.Add (txtInput);
 
         var ckbShift = new CheckBox { X = Pos.Center (), Y = Pos.Center () - 4, Text = "Shift" };
-        Win.Add (ckbShift);
+        win.Add (ckbShift);
 
         var ckbAlt = new CheckBox { X = Pos.Center (), Y = Pos.Center () - 3, Text = "Alt" };
-        Win.Add (ckbAlt);
+        win.Add (ckbAlt);
 
         var ckbControl = new CheckBox { X = Pos.Center (), Y = Pos.Center () - 2, Text = "Control" };
-        Win.Add (ckbControl);
+        win.Add (ckbControl);
 
         label = new Label { X = Pos.Center (), Y = Pos.Center () + 1, Text = "Result keys:" };
-        Win.Add (label);
+        win.Add (label);
 
         var txtResult = new TextField { X = Pos.Center (), Y = Pos.Center () + 2, Width = 20 };
-        Win.Add (txtResult);
+        win.Add (txtResult);
 
         var rKeys = "";
         var rControlKeys = "";
@@ -60,13 +62,13 @@ public class SendKeys : Scenario
                              };
 
         var lblShippedKeys = new Label { X = Pos.Center (), Y = Pos.Center () + 3 };
-        Win.Add (lblShippedKeys);
+        win.Add (lblShippedKeys);
 
         var lblShippedControlKeys = new Label { X = Pos.Center (), Y = Pos.Center () + 5 };
-        Win.Add (lblShippedControlKeys);
+        win.Add (lblShippedControlKeys);
 
         var button = new Button { X = Pos.Center (), Y = Pos.Center () + 7, IsDefault = true, Text = "Process keys" };
-        Win.Add (button);
+        win.Add (button);
 
         void ProcessInput ()
         {
@@ -100,7 +102,7 @@ public class SendKeys : Scenario
 
         button.Accept += (s, e) => ProcessInput ();
 
-        Win.KeyDown += (s, e) =>
+        win.KeyDown += (s, e) =>
                        {
                            if (e.KeyCode == KeyCode.Enter)
                            {
@@ -108,5 +110,9 @@ public class SendKeys : Scenario
                                e.Handled = true;
                            }
                        };
+
+        Application.Run (win);
+        win.Dispose ();
+        Application.Shutdown ();
     }
 }

+ 1 - 1
UICatalog/Scenarios/ShadowStyles.cs

@@ -17,7 +17,7 @@ public class ShadowStyles : Scenario
 
         Window app = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+            Title = GetQuitKeyAndName ()
         };
 
 

+ 1 - 1
UICatalog/Scenarios/Shortcuts.cs

@@ -31,7 +31,7 @@ public class Shortcuts : Scenario
     private void App_Loaded (object sender, EventArgs e)
     {
         Application.QuitKey = Key.Z.WithCtrl;
-        Application.Top.Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}";
+        Application.Top.Title = GetQuitKeyAndName ();
 
         ObservableCollection<string> eventSource = new ();
 

+ 1 - 1
UICatalog/Scenarios/Sliders.cs

@@ -129,7 +129,7 @@ public class Sliders : Scenario
 
         Window app = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+            Title = GetQuitKeyAndName ()
         };
 
         MakeSliders (

+ 8 - 3
UICatalog/Scenarios/Snake.cs

@@ -15,9 +15,10 @@ public class Snake : Scenario
 {
     private bool isDisposed;
 
-    public override void Setup ()
+    public override void Main ()
     {
-        base.Setup ();
+        Application.Init ();
+        var win = new Window { Title = GetQuitKeyAndName () };
 
         var state = new SnakeState ();
 
@@ -25,7 +26,7 @@ public class Snake : Scenario
 
         var snakeView = new SnakeView (state) { Width = state.Width, Height = state.Height };
 
-        Win.Add (snakeView);
+        win.Add (snakeView);
 
         var sw = new Stopwatch ();
 
@@ -51,6 +52,10 @@ public class Snake : Scenario
                       }
                   }
                  );
+
+        Application.Run (win);
+        win.Dispose ();
+        Application.Shutdown ();
     }
 
     protected override void Dispose (bool disposing)

+ 1 - 1
UICatalog/Scenarios/SpinnerStyles.cs

@@ -18,7 +18,7 @@ public class SpinnerViewStyles : Scenario
 
         Window app = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+            Title = GetQuitKeyAndName ()
         };
 
         const int DEFAULT_DELAY = 130;

+ 33 - 27
UICatalog/Scenarios/Text.cs

@@ -17,11 +17,13 @@ public class Text : Scenario
     private Label _labelMirroringTimeField;
     private TimeField _timeField;
 
-    public override void Setup ()
+    public override void Main ()
     {
+        Application.Init ();
+        var win = new Window { Title = GetQuitKeyAndName () };
         // TextField is a simple, single-line text input control
         var label = new Label { Text = "_TextField:" };
-        Win.Add (label);
+        win.Add (label);
 
         var textField = new TextField
         {
@@ -43,7 +45,7 @@ public class Text : Scenario
                                                       .ToList ();
         }
 
-        Win.Add (textField);
+        win.Add (textField);
 
         var labelMirroringTextField = new Label
         {
@@ -54,12 +56,12 @@ public class Text : Scenario
             Height = 1,
             Text = textField.Text
         };
-        Win.Add (labelMirroringTextField);
+        win.Add (labelMirroringTextField);
         textField.TextChanged += (s, prev) => { labelMirroringTextField.Text = textField.Text; };
 
         // TextView is a rich (as in functionality, not formatting) text editing control
         label = new() { Text = "T_extView:", Y = Pos.Bottom (label) + 1 };
-        Win.Add (label);
+        win.Add (label);
 
         var textView = new TextView
         {
@@ -80,7 +82,7 @@ public class Text : Scenario
                                                       .ToList ();
         }
 
-        Win.Add (textView);
+        win.Add (textView);
 
         var labelMirroringTextView = new Label
         {
@@ -90,7 +92,7 @@ public class Text : Scenario
             Width = Dim.Fill (1) - 1,
             Height = Dim.Height (textView) - 1
         };
-        Win.Add (labelMirroringTextView);
+        win.Add (labelMirroringTextView);
 
         // Use ContentChanged to detect if the user has typed something in a TextView.
         // The TextChanged property is only fired if the TextView.Text property is
@@ -107,7 +109,7 @@ public class Text : Scenario
         {
             X = Pos.Left (textView), Y = Pos.Bottom (textView), State = textView.Multiline ? CheckState.Checked : CheckState.UnChecked, Text = "_Multiline"
         };
-        Win.Add (chxMultiline);
+        win.Add (chxMultiline);
 
         var chxWordWrap = new CheckBox
         {
@@ -117,7 +119,7 @@ public class Text : Scenario
             Text = "_Word Wrap"
         };
         chxWordWrap.Toggle += (s, e) => textView.WordWrap = e.NewValue == CheckState.Checked;
-        Win.Add (chxWordWrap);
+        win.Add (chxWordWrap);
 
         // TextView captures Tabs (so users can enter /t into text) by default;
         // This means using Tab to navigate doesn't work by default. This shows
@@ -163,11 +165,11 @@ public class Text : Scenario
 
                                       textView.AllowsTab = e.NewValue == CheckState.Checked;
                                   };
-        Win.Add (chxCaptureTabs);
+        win.Add (chxCaptureTabs);
 
         // Hex editor
         label = new() { Text = "_HexView:", Y = Pos.Bottom (chxMultiline) + 1 };
-        Win.Add (label);
+        win.Add (label);
 
         var hexEditor =
             new HexView (
@@ -176,7 +178,7 @@ public class Text : Scenario
             {
                 X = Pos.Right (label) + 1, Y = Pos.Bottom (chxMultiline) + 1, Width = Dim.Percent (50) - 1, Height = Dim.Percent (30)
             };
-        Win.Add (hexEditor);
+        win.Add (hexEditor);
 
         var labelMirroringHexEditor = new Label
         {
@@ -195,14 +197,14 @@ public class Text : Scenario
                                 byte [] array = ((MemoryStream)hexEditor.Source).ToArray ();
                                 labelMirroringHexEditor.Text = Encoding.UTF8.GetString (array, 0, array.Length);
                             };
-        Win.Add (labelMirroringHexEditor);
+        win.Add (labelMirroringHexEditor);
 
         // DateField
         label = new() { Text = "_DateField:", Y = Pos.Bottom (hexEditor) + 1 };
-        Win.Add (label);
+        win.Add (label);
 
         var dateField = new DateField (DateTime.Now) { X = Pos.Right (label) + 1, Y = Pos.Bottom (hexEditor) + 1, Width = 20 };
-        Win.Add (dateField);
+        win.Add (dateField);
 
         var labelMirroringDateField = new Label
         {
@@ -213,13 +215,13 @@ public class Text : Scenario
             Height = Dim.Height (dateField),
             Text = dateField.Text
         };
-        Win.Add (labelMirroringDateField);
+        win.Add (labelMirroringDateField);
 
         dateField.TextChanged += (s, prev) => { labelMirroringDateField.Text = dateField.Text; };
 
         // TimeField
         label = new() { Text = "T_imeField:", Y = Pos.Top (dateField), X = Pos.Right (labelMirroringDateField) + 5 };
-        Win.Add (label);
+        win.Add (label);
 
         _timeField = new()
         {
@@ -229,7 +231,7 @@ public class Text : Scenario
             IsShortFormat = false,
             Time = DateTime.Now.TimeOfDay
         };
-        Win.Add (_timeField);
+        win.Add (_timeField);
 
         _labelMirroringTimeField = new()
         {
@@ -240,7 +242,7 @@ public class Text : Scenario
             Height = Dim.Height (_timeField),
             Text = _timeField.Text
         };
-        Win.Add (_labelMirroringTimeField);
+        win.Add (_labelMirroringTimeField);
 
         _timeField.TimeChanged += TimeChanged;
 
@@ -251,7 +253,7 @@ public class Text : Scenario
             Y = Pos.Bottom (dateField) + 1,
             Text = "_NetMaskedTextProvider [ 999 000 LLL >LLL |AAA aaa ]:"
         };
-        Win.Add (netProviderLabel);
+        win.Add (netProviderLabel);
 
         var netProvider = new NetMaskedTextProvider ("999 000 LLL >LLL |AAA aaa");
 
@@ -259,7 +261,7 @@ public class Text : Scenario
         {
             X = Pos.Right (netProviderLabel) + 1, Y = Pos.Y (netProviderLabel), Provider = netProvider
         };
-        Win.Add (netProviderField);
+        win.Add (netProviderField);
 
         var labelMirroringNetProviderField = new Label
         {
@@ -270,7 +272,7 @@ public class Text : Scenario
             Height = Dim.Height (netProviderField),
             Text = netProviderField.Text
         };
-        Win.Add (labelMirroringNetProviderField);
+        win.Add (labelMirroringNetProviderField);
 
         netProviderField.Provider.TextChanged += (s, prev) => { labelMirroringNetProviderField.Text = netProviderField.Text; };
 
@@ -281,7 +283,7 @@ public class Text : Scenario
             Y = Pos.Bottom (netProviderLabel) + 1,
             Text = "Text_RegexProvider [ ^([0-9]?[0-9]?[0-9]|1000)$ ]:"
         };
-        Win.Add (regexProvider);
+        win.Add (regexProvider);
 
         var provider2 = new TextRegexProvider ("^([0-9]?[0-9]?[0-9]|1000)$") { ValidateOnInput = false };
 
@@ -293,7 +295,7 @@ public class Text : Scenario
             TextAlignment = Alignment.Center,
             Provider = provider2
         };
-        Win.Add (regexProviderField);
+        win.Add (regexProviderField);
 
         var labelMirroringRegexProviderField = new Label
         {
@@ -304,7 +306,7 @@ public class Text : Scenario
             Height = Dim.Height (regexProviderField),
             Text = regexProviderField.Text
         };
-        Win.Add (labelMirroringRegexProviderField);
+        win.Add (labelMirroringRegexProviderField);
 
         regexProviderField.Provider.TextChanged += (s, prev) => { labelMirroringRegexProviderField.Text = regexProviderField.Text; };
 
@@ -428,8 +430,12 @@ public class Text : Scenario
             }
         };
 
-        Win.Add (labelAppendAutocomplete);
-        Win.Add (appendAutocompleteTextField);
+        win.Add (labelAppendAutocomplete);
+        win.Add (appendAutocompleteTextField);
+
+        Application.Run (win);
+        win.Dispose ();
+        Application.Shutdown ();
     }
 
     private void TimeChanged (object sender, DateTimeEventArgs<TimeSpan> e) { _labelMirroringTimeField.Text = _timeField.Text; }

+ 1 - 1
UICatalog/Scenarios/TextAlignmentAndDirection.cs

@@ -16,7 +16,7 @@ public class TextAlignmentAndDirection : Scenario
 
         Window app = new ()
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+            Title = GetQuitKeyAndName ()
         };
 
         var txt = $"Hello World{Environment.NewLine}HELLO WORLD{Environment.NewLine}世界 您好";

+ 1 - 1
UICatalog/Scenarios/TextFormatterDemo.cs

@@ -16,7 +16,7 @@ public class TextFormatterDemo : Scenario
 
         var app = new Window
         {
-            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+            Title = GetQuitKeyAndName ()
         };
 
         // Make Win smaller so sizing the window horizontally will make the

+ 13 - 7
UICatalog/Scenarios/Threading.cs

@@ -20,8 +20,10 @@ public class Threading : Scenario
     private ListView _logJob;
     private Action _sync;
 
-    public override void Setup ()
+    public override void Main ()
     {
+        Application.Init ();
+        var win = new Window { Title = GetQuitKeyAndName () };
         _action = LoadData;
 
         _lambda = async () =>
@@ -56,7 +58,7 @@ public class Threading : Scenario
         _btnActionCancel = new Button { X = 1, Y = 1, Text = "Cancelable Load Items" };
         _btnActionCancel.Accept += (s, e) => Application.Invoke (CallLoadItemsAsync);
 
-        Win.Add (new Label { X = Pos.X (_btnActionCancel), Y = Pos.Y (_btnActionCancel) + 4, Text = "Data Items:" });
+        win.Add (new Label { X = Pos.X (_btnActionCancel), Y = Pos.Y (_btnActionCancel) + 4, Text = "Data Items:" });
 
         _itemsList = new ListView
         {
@@ -67,7 +69,7 @@ public class Threading : Scenario
             ColorScheme = Colors.ColorSchemes ["TopLevel"]
         };
 
-        Win.Add (new Label { X = Pos.Right (_itemsList) + 10, Y = Pos.Y (_btnActionCancel) + 4, Text = "Task Logs:" });
+        win.Add (new Label { X = Pos.Right (_itemsList) + 10, Y = Pos.Y (_btnActionCancel) + 4, Text = "Task Logs:" });
 
         _logJob = new ListView
         {
@@ -101,7 +103,7 @@ public class Threading : Scenario
         var btnQuit = new Button { X = 80, Y = 22, Text = "Quit" };
         btnQuit.Accept += (s, e) => Application.RequestStop ();
 
-        Win.Add (
+        win.Add (
                  _itemsList,
                  _btnActionCancel,
                  _logJob,
@@ -115,13 +117,17 @@ public class Threading : Scenario
                  btnQuit
                 );
 
-        void Top_Loaded (object sender, EventArgs args)
+        void Win_Loaded (object sender, EventArgs args)
         {
             _btnActionCancel.SetFocus ();
-            Top.Loaded -= Top_Loaded;
+            win.Loaded -= Win_Loaded;
         }
 
-        Top.Loaded += Top_Loaded;
+        win.Loaded += Win_Loaded;
+
+        Application.Run (win);
+        win.Dispose ();
+        Application.Shutdown ();
     }
 
     private async void CallLoadItemsAsync ()

+ 22 - 12
UICatalog/Scenarios/TileViewNesting.cs

@@ -19,11 +19,15 @@ public class TileViewNesting : Scenario
     private View _workArea;
 
     /// <summary>Setup the scenario.</summary>
-    public override void Setup ()
+    public override void Main ()
     {
+        Application.Init ();
         // Scenario Windows.
-        Win.Title = GetName ();
-        Win.Y = 1;
+        var win = new Window
+        {
+            Title = GetName (),
+            Y = 1
+        };
 
         var lblViews = new Label { Text = "Number Of Views:" };
         _textField = new() { X = Pos.Right (lblViews), Width = 10, Text = "2" };
@@ -52,19 +56,25 @@ public class TileViewNesting : Scenario
             ]
         };
 
-        Win.Add (lblViews);
-        Win.Add (_textField);
-        Win.Add (_cbHorizontal);
-        Win.Add (_cbBorder);
-        Win.Add (_cbTitles);
-        Win.Add (_cbUseLabels);
-        Win.Add (_workArea);
+        win.Add (lblViews);
+        win.Add (_textField);
+        win.Add (_cbHorizontal);
+        win.Add (_cbBorder);
+        win.Add (_cbTitles);
+        win.Add (_cbUseLabels);
+        win.Add (_workArea);
 
         SetupTileView ();
 
-        Top.Add (menu);
+        var top = new Toplevel ();
+        top.Add (menu);
+        top.Add (win);
+
+        top.Loaded += (s, e) => _loaded = true;
 
-        Win.Loaded += (s, e) => _loaded = true;
+        Application.Run (top);
+        top.Dispose ();
+        Application.Shutdown ();
     }
 
     private void AddMoreViews (TileView to)

+ 19 - 13
UICatalog/Scenarios/TimeAndDate.cs

@@ -15,8 +15,10 @@ public class TimeAndDate : Scenario
     private Label _lblOldTime;
     private Label _lblTimeFmt;
 
-    public override void Setup ()
+    public override void Main ()
     {
+        Application.Init ();
+        var win = new Window { Title = GetQuitKeyAndName () };
         var longTime = new TimeField
         {
             X = Pos.Center (),
@@ -26,7 +28,7 @@ public class TimeAndDate : Scenario
             Time = DateTime.Now.TimeOfDay
         };
         longTime.TimeChanged += TimeChanged;
-        Win.Add (longTime);
+        win.Add (longTime);
 
         var shortTime = new TimeField
         {
@@ -37,21 +39,21 @@ public class TimeAndDate : Scenario
             Time = DateTime.Now.TimeOfDay
         };
         shortTime.TimeChanged += TimeChanged;
-        Win.Add (shortTime);
+        win.Add (shortTime);
 
         var shortDate = new DateField (DateTime.Now)
         {
             X = Pos.Center (), Y = Pos.Bottom (shortTime) + 1, ReadOnly = true
         };
         shortDate.DateChanged += DateChanged;
-        Win.Add (shortDate);
+        win.Add (shortDate);
 
         var longDate = new DateField (DateTime.Now)
         {
             X = Pos.Center (), Y = Pos.Bottom (shortDate) + 1, ReadOnly = false
         };
         longDate.DateChanged += DateChanged;
-        Win.Add (longDate);
+        win.Add (longDate);
 
         _lblOldTime = new()
         {
@@ -62,7 +64,7 @@ public class TimeAndDate : Scenario
             Width = Dim.Fill (),
             Text = "Old Time: "
         };
-        Win.Add (_lblOldTime);
+        win.Add (_lblOldTime);
 
         _lblNewTime = new()
         {
@@ -73,7 +75,7 @@ public class TimeAndDate : Scenario
             Width = Dim.Fill (),
             Text = "New Time: "
         };
-        Win.Add (_lblNewTime);
+        win.Add (_lblNewTime);
 
         _lblTimeFmt = new()
         {
@@ -84,7 +86,7 @@ public class TimeAndDate : Scenario
             Width = Dim.Fill (),
             Text = "Time Format: "
         };
-        Win.Add (_lblTimeFmt);
+        win.Add (_lblTimeFmt);
 
         _lblOldDate = new()
         {
@@ -95,7 +97,7 @@ public class TimeAndDate : Scenario
             Width = Dim.Fill (),
             Text = "Old Date: "
         };
-        Win.Add (_lblOldDate);
+        win.Add (_lblOldDate);
 
         _lblNewDate = new()
         {
@@ -106,7 +108,7 @@ public class TimeAndDate : Scenario
             Width = Dim.Fill (),
             Text = "New Date: "
         };
-        Win.Add (_lblNewDate);
+        win.Add (_lblNewDate);
 
         _lblDateFmt = new()
         {
@@ -117,11 +119,11 @@ public class TimeAndDate : Scenario
             Width = Dim.Fill (),
             Text = "Date Format: "
         };
-        Win.Add (_lblDateFmt);
+        win.Add (_lblDateFmt);
 
         var swapButton = new Button
         {
-            X = Pos.Center (), Y = Pos.Bottom (Win) - 5, Text = "Swap Long/Short & Read/Read Only"
+            X = Pos.Center (), Y = Pos.Bottom (win) - 5, Text = "Swap Long/Short & Read/Read Only"
         };
 
         swapButton.Accept += (s, e) =>
@@ -135,7 +137,11 @@ public class TimeAndDate : Scenario
                                  longDate.ReadOnly = !longDate.ReadOnly;
                                  shortDate.ReadOnly = !shortDate.ReadOnly;
                              };
-        Win.Add (swapButton);
+        win.Add (swapButton);
+
+        Application.Run (win);
+        win.Dispose ();
+        Application.Shutdown ();
     }
 
     private void DateChanged (object sender, DateTimeEventArgs<DateTime> e)

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików