Browse Source

Merge branch 'v2_develop' into copilot/enable-menubar-replacement

Tig 2 weeks ago
parent
commit
649186cfdd
100 changed files with 1722 additions and 1660 deletions
  1. 79 0
      .github/workflows/README.md
  2. 74 28
      .github/workflows/unit-tests.yml
  3. 1 0
      .gitignore
  4. 21 153
      CONTRIBUTING.md
  5. 0 2
      Examples/CommunityToolkitExample/LoginView.cs
  6. 4 4
      Examples/CommunityToolkitExample/LoginViewModel.cs
  7. 0 1
      Examples/CommunityToolkitExample/Message.cs
  8. 7 8
      Examples/CommunityToolkitExample/Program.cs
  9. 25 21
      Examples/CommunityToolkitExample/README.md
  10. 27 36
      Examples/Example/Example.cs
  11. 1 4
      Examples/Example/README.md
  12. 11 45
      Examples/FluentExample/Program.cs
  13. 2 2
      Examples/NativeAot/Program.cs
  14. 7 8
      Examples/ReactiveExample/Program.cs
  15. 8 4
      Examples/ReactiveExample/README.md
  16. 28 21
      Examples/ReactiveExample/TerminalScheduler.cs
  17. 1 2
      Examples/ReactiveExample/ViewExtensions.cs
  18. 31 28
      Examples/RunnableWrapperExample/Program.cs
  19. 15 15
      Examples/SelfContained/Program.cs
  20. 26 0
      Examples/SelfContained/README.md
  21. 1 1
      Examples/UICatalog/README.md
  22. 2 2
      Examples/UICatalog/Resources/config.json
  23. 5 5
      Examples/UICatalog/Scenario.cs
  24. 8 8
      Examples/UICatalog/Scenarios/Adornments.cs
  25. 7 0
      Examples/UICatalog/Scenarios/AllViewsTester.cs
  26. 1 1
      Examples/UICatalog/Scenarios/AnimationScenario/AnimationScenario.cs
  27. 4 4
      Examples/UICatalog/Scenarios/Arrangement.cs
  28. 15 15
      Examples/UICatalog/Scenarios/Bars.cs
  29. 5 5
      Examples/UICatalog/Scenarios/Buttons.cs
  30. 3 2
      Examples/UICatalog/Scenarios/ChineseUI.cs
  31. 1 1
      Examples/UICatalog/Scenarios/Clipping.cs
  32. 2 2
      Examples/UICatalog/Scenarios/CombiningMarks.cs
  33. 1 1
      Examples/UICatalog/Scenarios/ComboBoxIteration.cs
  34. 1 1
      Examples/UICatalog/Scenarios/ComputedLayout.cs
  35. 5 5
      Examples/UICatalog/Scenarios/ConfigurationEditor.cs
  36. 11 7
      Examples/UICatalog/Scenarios/ContextMenus.cs
  37. 17 17
      Examples/UICatalog/Scenarios/CsvEditor.cs
  38. 8 2
      Examples/UICatalog/Scenarios/Dialogs.cs
  39. 6 6
      Examples/UICatalog/Scenarios/DynamicStatusBar.cs
  40. 19 11
      Examples/UICatalog/Scenarios/Editor.cs
  41. 1 1
      Examples/UICatalog/Scenarios/EditorsAndHelpers/ArrangementEditor.cs
  42. 1 1
      Examples/UICatalog/Scenarios/EditorsAndHelpers/DimEditor.cs
  43. 1 1
      Examples/UICatalog/Scenarios/EditorsAndHelpers/PosEditor.cs
  44. 6 6
      Examples/UICatalog/Scenarios/FileDialogExamples.cs
  45. 1 1
      Examples/UICatalog/Scenarios/Generic.cs
  46. 4 4
      Examples/UICatalog/Scenarios/HexEditor.cs
  47. 3 3
      Examples/UICatalog/Scenarios/Images.cs
  48. 1 1
      Examples/UICatalog/Scenarios/InteractiveTree.cs
  49. 4 4
      Examples/UICatalog/Scenarios/KeyBindings.cs
  50. 4 4
      Examples/UICatalog/Scenarios/Keys.cs
  51. 1 1
      Examples/UICatalog/Scenarios/LineCanvasExperiment.cs
  52. 1 1
      Examples/UICatalog/Scenarios/ListColumns.cs
  53. 1 1
      Examples/UICatalog/Scenarios/ListViewWithSelection.cs
  54. 2 2
      Examples/UICatalog/Scenarios/ListsAndCombos.cs
  55. 1 1
      Examples/UICatalog/Scenarios/Localization.cs
  56. 7 7
      Examples/UICatalog/Scenarios/Mazing.cs
  57. 2 2
      Examples/UICatalog/Scenarios/Menus.cs
  58. 9 9
      Examples/UICatalog/Scenarios/MessageBoxes.cs
  59. 2 2
      Examples/UICatalog/Scenarios/Mouse.cs
  60. 1 1
      Examples/UICatalog/Scenarios/MultiColouredTable.cs
  61. 4 4
      Examples/UICatalog/Scenarios/Navigation.cs
  62. 14 11
      Examples/UICatalog/Scenarios/Notepad.cs
  63. 1 1
      Examples/UICatalog/Scenarios/PosAlignDemo.cs
  64. 14 10
      Examples/UICatalog/Scenarios/ProgressBarStyles.cs
  65. 4 4
      Examples/UICatalog/Scenarios/RunTExample.cs
  66. 3 3
      Examples/UICatalog/Scenarios/RuneWidthGreaterThanOne.cs
  67. 15 15
      Examples/UICatalog/Scenarios/Scrolling.cs
  68. 31 31
      Examples/UICatalog/Scenarios/Shortcuts.cs
  69. 8 9
      Examples/UICatalog/Scenarios/SingleBackgroundWorker.cs
  70. 1 1
      Examples/UICatalog/Scenarios/Sliders.cs
  71. 17 17
      Examples/UICatalog/Scenarios/SpinnerStyles.cs
  72. 1 1
      Examples/UICatalog/Scenarios/SyntaxHighlighting.cs
  73. 8 8
      Examples/UICatalog/Scenarios/TableEditor.cs
  74. 3 6
      Examples/UICatalog/Scenarios/TextEffectsScenario.cs
  75. 1 1
      Examples/UICatalog/Scenarios/TextFormatterDemo.cs
  76. 1 1
      Examples/UICatalog/Scenarios/TextStyles.cs
  77. 1 1
      Examples/UICatalog/Scenarios/Themes.cs
  78. 4 4
      Examples/UICatalog/Scenarios/Threading.cs
  79. 2 2
      Examples/UICatalog/Scenarios/Transparent.cs
  80. 18 15
      Examples/UICatalog/Scenarios/TreeUseCases.cs
  81. 3 3
      Examples/UICatalog/Scenarios/ViewportSettings.cs
  82. 3 3
      Examples/UICatalog/Scenarios/WindowsAndFrameViews.cs
  83. 11 8
      Examples/UICatalog/Scenarios/WizardAsView.cs
  84. 271 268
      Examples/UICatalog/Scenarios/Wizards.cs
  85. 13 25
      Examples/UICatalog/UICatalog.cs
  86. 28 19
      Examples/UICatalog/UICatalogRunnable.cs
  87. 15 0
      Terminal.Gui/App/Application.Clipboard.cs
  88. 0 18
      Terminal.Gui/App/Application.Current.cs
  89. 21 15
      Terminal.Gui/App/Application.Driver.cs
  90. 20 6
      Terminal.Gui/App/Application.Lifecycle.cs
  91. 12 2
      Terminal.Gui/App/Application.Mouse.cs
  92. 49 9
      Terminal.Gui/App/Application.Navigation.cs
  93. 36 22
      Terminal.Gui/App/Application.Run.cs
  94. 0 8
      Terminal.Gui/App/Application.Screen.cs
  95. 16 0
      Terminal.Gui/App/Application.TopRunnable.cs
  96. 182 80
      Terminal.Gui/App/ApplicationImpl.Lifecycle.cs
  97. 171 432
      Terminal.Gui/App/ApplicationImpl.Run.cs
  98. 11 11
      Terminal.Gui/App/ApplicationImpl.Screen.cs
  99. 150 55
      Terminal.Gui/App/ApplicationImpl.cs
  100. 16 0
      Terminal.Gui/App/ApplicationModelUsage.cs

+ 79 - 0
.github/workflows/README.md

@@ -0,0 +1,79 @@
+## CI/CD Workflows
+
+The repository uses multiple GitHub Actions workflows. What runs and when:
+
+### 1) Build Solution (`.github/workflows/build.yml`)
+
+- **Triggers**: push and pull_request to `v2_release`, `v2_develop` (ignores `**.md`); supports `workflow_call`
+- **Runner/timeout**: `ubuntu-latest`, 10 minutes
+- **Steps**:
+- Checkout and setup .NET 8.x GA
+- `dotnet restore`
+- Build Debug: `dotnet build --configuration Debug --no-restore -property:NoWarn=0618%3B0612`
+- Build Release (library): `dotnet build Terminal.Gui/Terminal.Gui.csproj --configuration Release --no-incremental --force -property:NoWarn=0618%3B0612`
+- Pack Release: `dotnet pack Terminal.Gui/Terminal.Gui.csproj --configuration Release --output ./local_packages -property:NoWarn=0618%3B0612`
+- Restore NativeAot/SelfContained examples, then restore solution again
+- Build Release for `Examples/NativeAot` and `Examples/SelfContained`
+- Build Release solution
+- Upload artifacts named `build-artifacts`, retention 1 day
+
+### 2) Build & Run Unit Tests (`.github/workflows/unit-tests.yml`)
+
+- **Triggers**: push and pull_request to `v2_release`, `v2_develop` (ignores `**.md`)
+- **Matrix**: Ubuntu/Windows/macOS
+- **Timeout**: 15 minutes per job
+- **Process**:
+1. Calls build workflow to build solution once
+2. Downloads build artifacts
+3. Runs `dotnet restore` (required for `--no-build` to work)
+4. **Performance optimizations**:
+   - Disables Windows Defender on Windows runners (significant speedup)
+   - Collects code coverage **only on Linux** (ubuntu-latest) for performance
+   - Windows and macOS skip coverage collection to reduce test time
+   - Increased blame-hang-timeout to 120s for Windows/macOS (60s for Linux)
+5. Runs two test jobs:
+   - **Non-parallel UnitTests**: `Tests/UnitTests` with blame/diag flags; `xunit.stopOnFail=false`
+   - **Parallel UnitTestsParallelizable**: `Tests/UnitTestsParallelizable` with blame/diag flags; `xunit.stopOnFail=false`
+6. Uploads test logs and diagnostic data from all runners
+7. **Uploads code coverage to Codecov only from Linux runner**
+
+**Test results**: All tests output to unified `TestResults/` directory at repository root
+
+### 3) Build & Run Integration Tests (`.github/workflows/integration-tests.yml`)
+
+- **Triggers**: push and pull_request to `v2_release`, `v2_develop` (ignores `**.md`)
+- **Matrix**: Ubuntu/Windows/macOS
+- **Timeout**: 15 minutes
+- **Process**:
+1. Calls build workflow
+2. Downloads build artifacts
+3. Runs `dotnet restore`
+4. **Performance optimizations** (same as unit tests):
+   - Disables Windows Defender on Windows runners
+   - Collects code coverage **only on Linux**
+   - Increased blame-hang-timeout to 120s for Windows/macOS
+5. Runs IntegrationTests with blame/diag flags; `xunit.stopOnFail=true`
+6. Uploads logs per-OS
+7. **Uploads coverage to Codecov only from Linux runner**
+
+### 4) Publish to NuGet (`.github/workflows/publish.yml`)
+
+- **Triggers**: push to `v2_release`, `v2_develop`, and tags `v*`(ignores `**.md`)
+- Uses GitVersion to compute SemVer, builds Release, packs with symbols, and pushes to NuGet.org using `NUGET_API_KEY`
+
+### 5) Build and publish API docs (`.github/workflows/api-docs.yml`)
+
+- **Triggers**: push to `v1_release` and `v2_develop`
+- Builds DocFX site on Windows and deploys to GitHub Pages when `ref_name` is `v2_release` or `v2_develop`
+
+
+### Replicating CI Locally
+
+```bash
+# Full CI sequence:
+dotnet restore
+dotnet build --configuration Debug --no-restore
+dotnet test Tests/UnitTests --no-build --verbosity normal
+dotnet test Tests/UnitTestsParallelizable --no-build --verbosity normal
+dotnet build --configuration Release --no-restore
+```

+ 74 - 28
.github/workflows/unit-tests.yml

@@ -120,7 +120,7 @@ jobs:
       matrix:
       matrix:
         os: [ ubuntu-latest, windows-latest, macos-latest ]
         os: [ ubuntu-latest, windows-latest, macos-latest ]
 
 
-    timeout-minutes: 15
+    timeout-minutes: 60
     steps:
     steps:
 
 
     - name: Checkout code
     - name: Checkout code
@@ -154,35 +154,81 @@ jobs:
       shell: bash
       shell: bash
       run: echo "VSTEST_DUMP_PATH=logs/UnitTestsParallelizable/${{ runner.os }}/" >> $GITHUB_ENV
       run: echo "VSTEST_DUMP_PATH=logs/UnitTestsParallelizable/${{ runner.os }}/" >> $GITHUB_ENV
 
 
-    - name: Run UnitTestsParallelizable
+    - name: Run UnitTestsParallelizable (10 iterations with varying parallelization)
       shell: bash
       shell: bash
       run: |
       run: |
-        if [ "${{ runner.os }}" == "Linux" ]; then
-          # Run with coverage on Linux only
-          dotnet test Tests/UnitTestsParallelizable \
-            --no-build \
-            --verbosity normal \
-            --collect:"XPlat Code Coverage" \
-            --settings Tests/UnitTests/runsettings.coverage.xml \
-            --diag:logs/UnitTestsParallelizable/${{ runner.os }}/logs.txt \
-            --blame \
-            --blame-crash \
-            --blame-hang \
-            --blame-hang-timeout 60s \
-            --blame-crash-collect-always
-        else
-          # Run without coverage on Windows/macOS for speed
-          dotnet test Tests/UnitTestsParallelizable \
-            --no-build \
-            --verbosity normal \
-            --settings Tests/UnitTestsParallelizable/runsettings.xml \
-            --diag:logs/UnitTestsParallelizable/${{ runner.os }}/logs.txt \
-            --blame \
-            --blame-crash \
-            --blame-hang \
-            --blame-hang-timeout 60s \
-            --blame-crash-collect-always
-        fi
+        # Run tests 3 times with different parallelization settings to expose concurrency issues
+        for RUN in {1..3}; do
+          echo "============================================"
+          echo "Starting test run $RUN of 3"
+          echo "============================================"
+          
+          # Use a combination of run number and timestamp to create different execution patterns
+          SEED=$((1000 + $RUN + $(date +%s) % 1000))
+          echo "Using randomization seed: $SEED"
+          
+          # Vary the xUnit parallelization based on run number to expose race conditions
+          # Runs 1-3: Default parallelization (2x CPU cores)
+          # Runs 4-6: Max parallelization (unlimited)
+          # Runs 7-9: Single threaded (1)
+          # Run 10: Random (1-4 threads)
+          if [ $RUN -le 3 ]; then
+            XUNIT_MAX_PARALLEL_THREADS="2x"
+            echo "Run $RUN: Using default parallelization (2x)"
+          elif [ $RUN -le 6 ]; then
+            XUNIT_MAX_PARALLEL_THREADS="unlimited"
+            echo "Run $RUN: Using maximum parallelization (unlimited)"
+          elif [ $RUN -le 9 ]; then
+            XUNIT_MAX_PARALLEL_THREADS="1"
+            echo "Run $RUN: Using single-threaded execution"
+          else
+            # Random parallelization based on seed
+            PROC_COUNT=$(( ($SEED % 4) + 1 ))
+            XUNIT_MAX_PARALLEL_THREADS="$PROC_COUNT"
+            echo "Run $RUN: Using random parallelization with $PROC_COUNT threads"
+          fi
+          
+          # Run tests with or without coverage based on OS and run number
+          if [ "${{ runner.os }}" == "Linux" ] && [ $RUN -eq 1 ]; then
+            echo "Run $RUN: Running with coverage collection"
+            dotnet test Tests/UnitTestsParallelizable \
+              --no-build \
+              --verbosity normal \
+              --collect:"XPlat Code Coverage" \
+              --settings Tests/UnitTests/runsettings.coverage.xml \
+              --diag:logs/UnitTestsParallelizable/${{ runner.os }}/run${RUN}-logs.txt \
+              --blame \
+              --blame-crash \
+              --blame-hang \
+              --blame-hang-timeout 60s \
+              --blame-crash-collect-always \
+              -- xUnit.MaxParallelThreads=${XUNIT_MAX_PARALLEL_THREADS}
+          else
+            dotnet test Tests/UnitTestsParallelizable \
+              --no-build \
+              --verbosity normal \
+              --settings Tests/UnitTestsParallelizable/runsettings.xml \
+              --diag:logs/UnitTestsParallelizable/${{ runner.os }}/run${RUN}-logs.txt \
+              --blame \
+              --blame-crash \
+              --blame-hang \
+              --blame-hang-timeout 60s \
+              --blame-crash-collect-always \
+              -- xUnit.MaxParallelThreads=${XUNIT_MAX_PARALLEL_THREADS}
+          fi
+          
+          if [ $? -ne 0 ]; then
+            echo "ERROR: Test run $RUN failed!"
+            exit 1
+          fi
+          
+          echo "Test run $RUN completed successfully"
+          echo ""
+        done
+        
+        echo "============================================"
+        echo "All 10 test runs completed successfully!"
+        echo "============================================"
 
 
     - name: Upload UnitTestsParallelizable Logs
     - name: Upload UnitTestsParallelizable Logs
       if: always()
       if: always()

+ 1 - 0
.gitignore

@@ -73,3 +73,4 @@ log.*
 !/Tests/coverage/.gitkeep   # keep folder in repo
 !/Tests/coverage/.gitkeep   # keep folder in repo
 /Tests/report/
 /Tests/report/
 *.cobertura.xml
 *.cobertura.xml
+/docfx/docs/migratingfromv1.md

+ 21 - 153
CONTRIBUTING.md

@@ -7,19 +7,16 @@ Welcome! This guide provides everything you need to know to contribute effective
 ## Table of Contents
 ## Table of Contents
 
 
 - [Project Overview](#project-overview)
 - [Project Overview](#project-overview)
-- [Building and Testing](#building-and-testing)
+- [Key Architecture Concepts](#key-architecture-concepts)
 - [Coding Conventions](#coding-conventions)
 - [Coding Conventions](#coding-conventions)
+- [Building and Testing](#building-and-testing)
 - [Testing Requirements](#testing-requirements)
 - [Testing Requirements](#testing-requirements)
 - [API Documentation Requirements](#api-documentation-requirements)
 - [API Documentation Requirements](#api-documentation-requirements)
 - [Pull Request Guidelines](#pull-request-guidelines)
 - [Pull Request Guidelines](#pull-request-guidelines)
 - [CI/CD Workflows](#cicd-workflows)
 - [CI/CD Workflows](#cicd-workflows)
 - [Repository Structure](#repository-structure)
 - [Repository Structure](#repository-structure)
 - [Branching Model](#branching-model)
 - [Branching Model](#branching-model)
-- [Key Architecture Concepts](#key-architecture-concepts)
 - [What NOT to Do](#what-not-to-do)
 - [What NOT to Do](#what-not-to-do)
-- [Additional Resources](#additional-resources)
-
----
 
 
 ## Project Overview
 ## Project Overview
 
 
@@ -32,8 +29,18 @@ Welcome! This guide provides everything you need to know to contribute effective
 - **Version**: v2 (Alpha), v1 (maintenance mode)
 - **Version**: v2 (Alpha), v1 (maintenance mode)
 - **Branching**: GitFlow model (v2_develop is default/active development)
 - **Branching**: GitFlow model (v2_develop is default/active development)
 
 
----
+## Key Architecture Concepts
+
+**⚠️ CRITICAL - AI Agents MUST understand these concepts before starting work.**
 
 
+- **Application Lifecycle** - How `Application.Init`, `Application.Run`, and `Application.Shutdown` work - [Application Deep Dive](./docfx/docs/application.md)
+- **Cancellable Workflow Patern** - [CWP Deep Dive](./docfx/docs/cancellable-work-pattern.md)
+- **View Hierarchy** - Understanding `View`, `Runnable`, `Window`, and view containment - [View Deep Dive](./docfx/docs/View.md)
+- **Layout System** - Pos, Dim, and automatic layout -  [Layout System](./docfx/docs/layout.md)
+- **Event System** - How keyboard, mouse, and application events flow - [Events Deep Dive](./docfx/docs/events.md)
+- **Driver Architecture** - How console drivers abstract platform differences - [Drivers](./docfx/docs/drivers.md)
+- **Drawing Model** - How rendering works with Attributes, Colors, and Glyphs  - [Drawing Deep Dive](./docfx/docs/drivers.md)
+ 
 ## Building and Testing
 ## Building and Testing
 
 
 ### Required Tools
 ### Required Tools
@@ -89,28 +96,18 @@ Welcome! This guide provides everything you need to know to contribute effective
 
 
 ### Common Build Issues
 ### Common Build Issues
 
 
-#### Issue: Build Warnings
-- **Expected**: None warnings (~100 currently).
-- **Action**: Don't add new warnings; fix warnings in code you modify
-
 #### Issue: NativeAot/SelfContained Build
 #### Issue: NativeAot/SelfContained Build
+
 - **Solution**: Restore these projects explicitly:
 - **Solution**: Restore these projects explicitly:
   ```bash
   ```bash
   dotnet restore ./Examples/NativeAot/NativeAot.csproj -f
   dotnet restore ./Examples/NativeAot/NativeAot.csproj -f
   dotnet restore ./Examples/SelfContained/SelfContained.csproj -f
   dotnet restore ./Examples/SelfContained/SelfContained.csproj -f
   ```
   ```
 
 
-### Running Examples
-
-**UICatalog** (comprehensive demo app):
-```bash
-dotnet run --project Examples/UICatalog/UICatalog.csproj
-```
-
----
-
 ## Coding Conventions
 ## Coding Conventions
 
 
+**⚠️ CRITICAL - These rules MUST be followed in ALL new or modified code**
+
 ### Code Style Tenets
 ### Code Style Tenets
 
 
 1. **Six-Year-Old Reading Level** - Readability over terseness
 1. **Six-Year-Old Reading Level** - Readability over terseness
@@ -161,8 +158,6 @@ dotnet run --project Examples/UICatalog/UICatalog.csproj
 
 
 **⚠️ CRITICAL - These conventions apply to ALL code - production code, test code, examples, and samples.**
 **⚠️ CRITICAL - These conventions apply to ALL code - production code, test code, examples, and samples.**
 
 
----
-
 ## Testing Requirements
 ## Testing Requirements
 
 
 ### Code Coverage
 ### Code Coverage
@@ -178,19 +173,17 @@ dotnet run --project Examples/UICatalog/UICatalog.csproj
 
 
 ### Test Patterns
 ### Test Patterns
 
 
-- **Parallelizable tests preferred** - Add new tests to `UnitTestsParallelizable` when possible
-- **Avoid static dependencies** - Don't use `Application.Init`, `ConfigurationManager` in tests
-- **Don't use `[AutoInitShutdown]`** - Legacy pattern, being phased out
 - **Make tests granular** - Each test should cover smallest area possible
 - **Make tests granular** - Each test should cover smallest area possible
 - Follow existing test patterns in respective test projects
 - Follow existing test patterns in respective test projects
+- **Avoid adding new tests to the `UnitTests` Project** - Make them parallelizable and add them to `UnitTests.Parallelizable`
+- **Avoid static dependencies** - DO NOT use the legacy/static `Application` API or `ConfigurationManager` in tests unless the tests explicitly test related functionality.
+- **Don't use `[AutoInitShutdown]` or `[SetupFakeApplication]`** - Legacy pattern, being phased out
 
 
 ### Test Configuration
 ### Test Configuration
 
 
 - `xunit.runner.json` - xUnit configuration
 - `xunit.runner.json` - xUnit configuration
 - `coverlet.runsettings` - Coverage settings (OpenCover format)
 - `coverlet.runsettings` - Coverage settings (OpenCover format)
 
 
----
-
 ## API Documentation Requirements
 ## API Documentation Requirements
 
 
 **All public APIs MUST have XML documentation:**
 **All public APIs MUST have XML documentation:**
@@ -202,16 +195,15 @@ dotnet run --project Examples/UICatalog/UICatalog.csproj
 - Complex topics → `docfx/docs/*.md` files
 - Complex topics → `docfx/docs/*.md` files
 - Proper English and grammar - Clear, concise, complete. Use imperative mood.
 - Proper English and grammar - Clear, concise, complete. Use imperative mood.
 
 
----
-
 ## Pull Request Guidelines
 ## Pull Request Guidelines
 
 
 ### PR Requirements
 ### PR Requirements
 
 
+- **ALWAYS** include instructions for pulling down locally at end of Description
+
 - **Title**: "Fixes #issue. Terse description". If multiple issues, list all, separated by commas (e.g. "Fixes #123, #456. Terse description")
 - **Title**: "Fixes #issue. Terse description". If multiple issues, list all, separated by commas (e.g. "Fixes #123, #456. Terse description")
 - **Description**: 
 - **Description**: 
   - Include "- Fixes #issue" for each issue near the top
   - Include "- Fixes #issue" for each issue near the top
-  - **ALWAYS** include instructions for pulling down locally at end of Description
   - Suggest user setup a remote named `copilot` pointing to your fork
   - Suggest user setup a remote named `copilot` pointing to your fork
   - Example:
   - Example:
     ```markdown
     ```markdown
@@ -220,99 +212,14 @@ dotnet run --project Examples/UICatalog/UICatalog.csproj
     git fetch copilot <branch-name>
     git fetch copilot <branch-name>
     git checkout copilot/<branch-name>
     git checkout copilot/<branch-name>
     ```
     ```
-- **Coding Style**: Follow all coding conventions in this document for new and modified code
 - **Tests**: Add tests for new functionality (see [Testing Requirements](#testing-requirements))
 - **Tests**: Add tests for new functionality (see [Testing Requirements](#testing-requirements))
 - **Coverage**: Maintain or increase code coverage
 - **Coverage**: Maintain or increase code coverage
 - **Scenarios**: Update UICatalog scenarios when adding features
 - **Scenarios**: Update UICatalog scenarios when adding features
 - **Warnings**: **CRITICAL - PRs must not introduce any new warnings**
 - **Warnings**: **CRITICAL - PRs must not introduce any new warnings**
   - Any file modified in a PR that currently generates warnings **MUST** be fixed to remove those warnings
   - Any file modified in a PR that currently generates warnings **MUST** be fixed to remove those warnings
   - Exception: Warnings caused by `[Obsolete]` attributes can remain
   - Exception: Warnings caused by `[Obsolete]` attributes can remain
-  - Expected baseline: ~326 warnings (mostly nullable reference warnings, unused variables, xUnit suggestions)
   - Action: Before submitting a PR, verify your changes don't add new warnings and fix any warnings in files you modify
   - Action: Before submitting a PR, verify your changes don't add new warnings and fix any warnings in files you modify
 
 
----
-
-## CI/CD Workflows
-
-The repository uses multiple GitHub Actions workflows. What runs and when:
-
-### 1) Build Solution (`.github/workflows/build.yml`)
-
-- **Triggers**: push and pull_request to `v2_release`, `v2_develop` (ignores `**.md`); supports `workflow_call`
-- **Runner/timeout**: `ubuntu-latest`, 10 minutes
-- **Steps**:
-- Checkout and setup .NET 8.x GA
-- `dotnet restore`
-- Build Debug: `dotnet build --configuration Debug --no-restore -property:NoWarn=0618%3B0612`
-- Build Release (library): `dotnet build Terminal.Gui/Terminal.Gui.csproj --configuration Release --no-incremental --force -property:NoWarn=0618%3B0612`
-- Pack Release: `dotnet pack Terminal.Gui/Terminal.Gui.csproj --configuration Release --output ./local_packages -property:NoWarn=0618%3B0612`
-- Restore NativeAot/SelfContained examples, then restore solution again
-- Build Release for `Examples/NativeAot` and `Examples/SelfContained`
-- Build Release solution
-- Upload artifacts named `build-artifacts`, retention 1 day
-
-### 2) Build & Run Unit Tests (`.github/workflows/unit-tests.yml`)
-
-- **Triggers**: push and pull_request to `v2_release`, `v2_develop` (ignores `**.md`)
-- **Matrix**: Ubuntu/Windows/macOS
-- **Timeout**: 15 minutes per job
-- **Process**:
-1. Calls build workflow to build solution once
-2. Downloads build artifacts
-3. Runs `dotnet restore` (required for `--no-build` to work)
-4. **Performance optimizations**:
-   - Disables Windows Defender on Windows runners (significant speedup)
-   - Collects code coverage **only on Linux** (ubuntu-latest) for performance
-   - Windows and macOS skip coverage collection to reduce test time
-   - Increased blame-hang-timeout to 120s for Windows/macOS (60s for Linux)
-5. Runs two test jobs:
-   - **Non-parallel UnitTests**: `Tests/UnitTests` with blame/diag flags; `xunit.stopOnFail=false`
-   - **Parallel UnitTestsParallelizable**: `Tests/UnitTestsParallelizable` with blame/diag flags; `xunit.stopOnFail=false`
-6. Uploads test logs and diagnostic data from all runners
-7. **Uploads code coverage to Codecov only from Linux runner**
-
-**Test results**: All tests output to unified `TestResults/` directory at repository root
-
-### 3) Build & Run Integration Tests (`.github/workflows/integration-tests.yml`)
-
-- **Triggers**: push and pull_request to `v2_release`, `v2_develop` (ignores `**.md`)
-- **Matrix**: Ubuntu/Windows/macOS
-- **Timeout**: 15 minutes
-- **Process**:
-1. Calls build workflow
-2. Downloads build artifacts
-3. Runs `dotnet restore`
-4. **Performance optimizations** (same as unit tests):
-   - Disables Windows Defender on Windows runners
-   - Collects code coverage **only on Linux**
-   - Increased blame-hang-timeout to 120s for Windows/macOS
-5. Runs IntegrationTests with blame/diag flags; `xunit.stopOnFail=true`
-6. Uploads logs per-OS
-7. **Uploads coverage to Codecov only from Linux runner**
-
-### 4) Publish to NuGet (`.github/workflows/publish.yml`)
-
-- **Triggers**: push to `v2_release`, `v2_develop`, and tags `v*`(ignores `**.md`)
-- Uses GitVersion to compute SemVer, builds Release, packs with symbols, and pushes to NuGet.org using `NUGET_API_KEY`
-
-### 5) Build and publish API docs (`.github/workflows/api-docs.yml`)
-
-- **Triggers**: push to `v1_release` and `v2_develop`
-- Builds DocFX site on Windows and deploys to GitHub Pages when `ref_name` is `v2_release` or `v2_develop`
-
-
-### Replicating CI Locally
-
-```bash
-# Full CI sequence:
-dotnet restore
-dotnet build --configuration Debug --no-restore
-dotnet test Tests/UnitTests --no-build --verbosity normal
-dotnet test Tests/UnitTestsParallelizable --no-build --verbosity normal
-dotnet build --configuration Release --no-restore
-```
-
----
 
 
 ## Repository Structure
 ## Repository Structure
 
 
@@ -364,7 +271,6 @@ dotnet build --configuration Release --no-restore
 
 
 **`/.github/workflows/`** - CI/CD pipelines (see [CI/CD Workflows](#cicd-workflows))
 **`/.github/workflows/`** - CI/CD pipelines (see [CI/CD Workflows](#cicd-workflows))
 
 
----
 
 
 ## Branching Model
 ## Branching Model
 
 
@@ -374,31 +280,6 @@ dotnet build --configuration Release --no-restore
 - `v2_release` - Stable releases, matches NuGet
 - `v2_release` - Stable releases, matches NuGet
 - `v1_develop`, `v1_release` - Legacy v1 (maintenance only)
 - `v1_develop`, `v1_release` - Legacy v1 (maintenance only)
 
 
----
-
-## Key Architecture Concepts
-
-**⚠️ CRITICAL - Contributors should understand these concepts before starting work.**
-
-See `/docfx/docs/` for deep dives on:
-
-- **Application Lifecycle** - How `Application.Init`, `Application.Run`, and `Application.Shutdown` work
-- **View Hierarchy** - Understanding `View`, `Toplevel`, `Window`, and view containment
-- **Layout System** - Pos, Dim, and automatic layout
-- **Event System** - How keyboard, mouse, and application events flow
-- **Driver Architecture** - How console drivers abstract platform differences
-- **Drawing Model** - How rendering works with Attributes, Colors, and Glyphs
-
-Key documentation:
-- [View Documentation](https://gui-cs.github.io/Terminal.Gui/docs/View.html)
-- [Events Deep Dive](https://gui-cs.github.io/Terminal.Gui/docs/events.html)
-- [Layout System](https://gui-cs.github.io/Terminal.Gui/docs/layout.html)
-- [Keyboard Handling](https://gui-cs.github.io/Terminal.Gui/docs/keyboard.html)
-- [Mouse Support](https://gui-cs.github.io/Terminal.Gui/docs/mouse.html)
-- [Drivers](https://gui-cs.github.io/Terminal.Gui/docs/drivers.html)
-
----
-
 ## What NOT to Do
 ## What NOT to Do
 
 
 - ❌ Don't add new linters/formatters (use existing)
 - ❌ Don't add new linters/formatters (use existing)
@@ -412,17 +293,4 @@ Key documentation:
 - ❌ **Don't use redundant type names with `new`** (**ALWAYS PREFER** target-typed `new ()`)
 - ❌ **Don't use redundant type names with `new`** (**ALWAYS PREFER** target-typed `new ()`)
 - ❌ **Don't introduce new warnings** (fix warnings in files you modify; exception: `[Obsolete]` warnings)
 - ❌ **Don't introduce new warnings** (fix warnings in files you modify; exception: `[Obsolete]` warnings)
 
 
----
-
-## Additional Resources
-
-- **Full Documentation**: https://gui-cs.github.io/Terminal.Gui
-- **API Reference**: https://gui-cs.github.io/Terminal.Gui/api/Terminal.Gui.App.html
-- **Deep Dives**: `/docfx/docs/` directory
-- **Getting Started**: https://gui-cs.github.io/Terminal.Gui/docs/getting-started.html
-- **Migrating from v1 to v2**: https://gui-cs.github.io/Terminal.Gui/docs/migratingfromv1.html
-- **Showcase**: https://gui-cs.github.io/Terminal.Gui/docs/showcase.html
-
----
-
 **Thank you for contributing to Terminal.Gui!** 🎉
 **Thank you for contributing to Terminal.Gui!** 🎉

+ 0 - 2
Examples/CommunityToolkitExample/LoginView.cs

@@ -64,8 +64,6 @@ internal partial class LoginView : IRecipient<Message<LoginActions>>
                 }
                 }
         }
         }
         SetText ();
         SetText ();
-        // BUGBUG: This should not be needed:
-        Application.LayoutAndDraw ();
     }
     }
 
 
     private void SetText ()
     private void SetText ()

+ 4 - 4
Examples/CommunityToolkitExample/LoginViewModel.cs

@@ -12,7 +12,7 @@ internal partial class LoginViewModel : ObservableObject
     private const string INVALID_LOGIN_MESSAGE = "Please enter a valid user name and password.";
     private const string INVALID_LOGIN_MESSAGE = "Please enter a valid user name and password.";
     private const string LOGGING_IN_PROGRESS_MESSAGE = "Logging in...";
     private const string LOGGING_IN_PROGRESS_MESSAGE = "Logging in...";
     private const string VALID_LOGIN_MESSAGE = "The input is valid!";
     private const string VALID_LOGIN_MESSAGE = "The input is valid!";
-    
+
     [ObservableProperty]
     [ObservableProperty]
     private bool _canLogin;
     private bool _canLogin;
 
 
@@ -28,7 +28,7 @@ internal partial class LoginViewModel : ObservableObject
 
 
     [ObservableProperty]
     [ObservableProperty]
     private string _usernameLengthMessage;
     private string _usernameLengthMessage;
-    
+
     [ObservableProperty]
     [ObservableProperty]
     private Scheme? _validationScheme;
     private Scheme? _validationScheme;
 
 
@@ -105,7 +105,7 @@ internal partial class LoginViewModel : ObservableObject
     {
     {
         switch (loginAction)
         switch (loginAction)
         {
         {
-             case LoginActions.Clear:
+            case LoginActions.Clear:
                 LoginProgressMessage = message;
                 LoginProgressMessage = message;
                 ValidationMessage = INVALID_LOGIN_MESSAGE;
                 ValidationMessage = INVALID_LOGIN_MESSAGE;
                 ValidationScheme = SchemeManager.GetScheme ("Error");
                 ValidationScheme = SchemeManager.GetScheme ("Error");
@@ -115,7 +115,7 @@ internal partial class LoginViewModel : ObservableObject
                 break;
                 break;
             case LoginActions.Validation:
             case LoginActions.Validation:
                 ValidationMessage = CanLogin ? VALID_LOGIN_MESSAGE : INVALID_LOGIN_MESSAGE;
                 ValidationMessage = CanLogin ? VALID_LOGIN_MESSAGE : INVALID_LOGIN_MESSAGE;
-                ValidationScheme = CanLogin ? SchemeManager.GetScheme ("Base") : SchemeManager.GetScheme("Error");
+                ValidationScheme = CanLogin ? SchemeManager.GetScheme ("Base") : SchemeManager.GetScheme ("Error");
                 break;
                 break;
         }
         }
         WeakReferenceMessenger.Default.Send (new Message<LoginActions> { Value = loginAction });
         WeakReferenceMessenger.Default.Send (new Message<LoginActions> { Value = loginAction });

+ 0 - 1
Examples/CommunityToolkitExample/Message.cs

@@ -1,5 +1,4 @@
 namespace CommunityToolkitExample;
 namespace CommunityToolkitExample;
-
 internal class Message<T>
 internal class Message<T>
 {
 {
     public T? Value { get; set; }
     public T? Value { get; set; }

+ 7 - 8
Examples/CommunityToolkitExample/Program.cs

@@ -1,8 +1,6 @@
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.DependencyInjection;
-using Terminal.Gui.Configuration;
 using Terminal.Gui.App;
 using Terminal.Gui.App;
-using Terminal.Gui.ViewBase;
-
+using Terminal.Gui.Configuration;
 
 
 namespace CommunityToolkitExample;
 namespace CommunityToolkitExample;
 
 
@@ -14,10 +12,10 @@ public static class Program
     {
     {
         ConfigurationManager.Enable (ConfigLocations.All);
         ConfigurationManager.Enable (ConfigLocations.All);
         Services = ConfigureServices ();
         Services = ConfigureServices ();
-        Application.Init ();
-        Application.Run (Services.GetRequiredService<LoginView> ());
-        Application.TopRunnable?.Dispose ();
-        Application.Shutdown ();
+        using IApplication app = Application.Create ();
+        app.Init ();
+        using var loginView = Services.GetRequiredService<LoginView> ();
+        app.Run (loginView);
     }
     }
 
 
     private static IServiceProvider ConfigureServices ()
     private static IServiceProvider ConfigureServices ()
@@ -25,6 +23,7 @@ public static class Program
         var services = new ServiceCollection ();
         var services = new ServiceCollection ();
         services.AddTransient<LoginView> ();
         services.AddTransient<LoginView> ();
         services.AddTransient<LoginViewModel> ();
         services.AddTransient<LoginViewModel> ();
+
         return services.BuildServiceProvider ();
         return services.BuildServiceProvider ();
     }
     }
-}
+}

+ 25 - 21
Examples/CommunityToolkitExample/README.md

@@ -6,9 +6,10 @@ Right away we use IoC to load our views and view models.
 
 
 ``` csharp
 ``` csharp
 // As a public property for access further in the application if needed. 
 // As a public property for access further in the application if needed. 
-public static IServiceProvider Services { get; private set; }
+public static IServiceProvider? Services { get; private set; }
 ...
 ...
 // In Main
 // In Main
+ConfigurationManager.Enable (ConfigLocations.All);
 Services = ConfigureServices ();
 Services = ConfigureServices ();
 ...
 ...
 private static IServiceProvider ConfigureServices ()
 private static IServiceProvider ConfigureServices ()
@@ -20,16 +21,19 @@ private static IServiceProvider ConfigureServices ()
 }
 }
 ```
 ```
 
 
-Now, we start the app and get our main view.
+Now, we start the app using the modern Terminal.Gui model and get our main view.
 
 
 ``` csharp
 ``` csharp
-Application.Run (Services.GetRequiredService<LoginView> ());
+using IApplication app = Application.Create ();
+app.Init ();
+using var loginView = Services.GetRequiredService<LoginView> ();
+app.Run (loginView);
 ```
 ```
 
 
 Our view implements `IRecipient<T>` to demonstrate the use of the `WeakReferenceMessenger`. The binding of the view events is then created.
 Our view implements `IRecipient<T>` to demonstrate the use of the `WeakReferenceMessenger`. The binding of the view events is then created.
 
 
 ``` csharp
 ``` csharp
-internal partial class LoginView : IRecipient<Message<LoginAction>>
+internal partial class LoginView : IRecipient<Message<LoginActions>>
 {
 {
     public LoginView (LoginViewModel viewModel)
     public LoginView (LoginViewModel viewModel)
     {
     {
@@ -41,15 +45,16 @@ internal partial class LoginView : IRecipient<Message<LoginAction>>
         passwordInput.TextChanged += (_, _) =>
         passwordInput.TextChanged += (_, _) =>
                                      {
                                      {
                                          ViewModel.Password = passwordInput.Text;
                                          ViewModel.Password = passwordInput.Text;
-                                         SetText ();
                                      };
                                      };
-        loginButton.Accept += (_, _) =>
+        loginButton.Accepting += (_, e) =>
                               {
                               {
                                   if (!ViewModel.CanLogin) { return; }
                                   if (!ViewModel.CanLogin) { return; }
                                   ViewModel.LoginCommand.Execute (null);
                                   ViewModel.LoginCommand.Execute (null);
+                                  // When Accepting is handled, set e.Handled to true to prevent further processing.
+                                  e.Handled = true;
                               };
                               };
         ...
         ...
-        // Let the view model know the view is intialized.
+        // Let the view model know the view is initialized.
         Initialized += (_, _) => { ViewModel.Initialized (); };
         Initialized += (_, _) => { ViewModel.Initialized (); };
     }
     }
     ...
     ...
@@ -101,54 +106,53 @@ The use of `WeakReferenceMessenger` provides one method of signaling the view fr
 ...
 ...
 private async Task Login ()
 private async Task Login ()
 {
 {
-    SendMessage (LoginAction.LoginProgress, LOGGING_IN_PROGRESS_MESSAGE);
+    SendMessage (LoginActions.LoginProgress, LOGGING_IN_PROGRESS_MESSAGE);
     await Task.Delay (TimeSpan.FromSeconds (1));
     await Task.Delay (TimeSpan.FromSeconds (1));
     Clear ();
     Clear ();
 }
 }
 
 
-private void SendMessage (LoginAction loginAction, string message = "")
+private void SendMessage (LoginActions loginAction, string message = "")
 {
 {
     switch (loginAction)
     switch (loginAction)
     {
     {
-        case LoginAction.LoginProgress:
+        case LoginActions.LoginProgress:
             LoginProgressMessage = message;
             LoginProgressMessage = message;
             break;
             break;
-        case LoginAction.Validation:
+        case LoginActions.Validation:
             ValidationMessage = CanLogin ? VALID_LOGIN_MESSAGE : INVALID_LOGIN_MESSAGE;
             ValidationMessage = CanLogin ? VALID_LOGIN_MESSAGE : INVALID_LOGIN_MESSAGE;
-            ValidationScheme = CanLogin ? Colors.Schemes ["Base"] : Colors.Schemes ["Error"];
+            ValidationScheme = CanLogin ? SchemeManager.GetScheme ("Base") : SchemeManager.GetScheme ("Error");
             break;
             break;
     }
     }
-    WeakReferenceMessenger.Default.Send (new Message<LoginAction> { Value = loginAction });
+    WeakReferenceMessenger.Default.Send (new Message<LoginActions> { Value = loginAction });
 }
 }
 
 
 private void ValidateLogin ()
 private void ValidateLogin ()
 {
 {
     CanLogin = !string.IsNullOrEmpty (Username) && !string.IsNullOrEmpty (Password);
     CanLogin = !string.IsNullOrEmpty (Username) && !string.IsNullOrEmpty (Password);
-    SendMessage (LoginAction.Validation);
+    SendMessage (LoginActions.Validation);
 }
 }
 ...
 ...
 ```
 ```
 
 
-And the view's `Receive` function which provides an `Application.Refresh()` call to update the UI immediately.
+The view's `Receive` function updates the UI based on messages from the view model. In the modern Terminal.Gui model, UI updates are automatically refreshed, so no manual `Application.Refresh()` call is needed.
 
 
 ``` csharp
 ``` csharp
-public void Receive (Message<LoginAction> message)
+public void Receive (Message<LoginActions> message)
 {
 {
     switch (message.Value)
     switch (message.Value)
     {
     {
-        case LoginAction.LoginProgress:
+        case LoginActions.LoginProgress:
             {
             {
                 loginProgressLabel.Text = ViewModel.LoginProgressMessage;
                 loginProgressLabel.Text = ViewModel.LoginProgressMessage;
                 break;
                 break;
             }
             }
-        case LoginAction.Validation:
+        case LoginActions.Validation:
             {
             {
                 validationLabel.Text = ViewModel.ValidationMessage;
                 validationLabel.Text = ViewModel.ValidationMessage;
-                validationLabel.Scheme = ViewModel.ValidationScheme;
+                validationLabel.SetScheme (ViewModel.ValidationScheme);
                 break;
                 break;
             }
             }
     }
     }
-    SetText();
-    Application.Refresh ();
+    SetText ();
 }
 }
 ```
 ```

+ 27 - 36
Examples/Example/Example.cs

@@ -3,30 +3,28 @@
 // This is a simple example application.  For the full range of functionality
 // This is a simple example application.  For the full range of functionality
 // see the UICatalog project
 // see the UICatalog project
 
 
-using Terminal.Gui.Configuration;
 using Terminal.Gui.App;
 using Terminal.Gui.App;
-using Terminal.Gui.Drawing;
+using Terminal.Gui.Configuration;
 using Terminal.Gui.ViewBase;
 using Terminal.Gui.ViewBase;
 using Terminal.Gui.Views;
 using Terminal.Gui.Views;
-using Attribute = Terminal.Gui.Drawing.Attribute;
 
 
 // Override the default configuration for the application to use the Light theme
 // Override the default configuration for the application to use the Light theme
-//ConfigurationManager.RuntimeConfig = """{ "Theme": "Light" }""";
-ConfigurationManager.Enable(ConfigLocations.All);
-
+ConfigurationManager.RuntimeConfig = """{ "Theme": "Light" }""";
+ConfigurationManager.Enable (ConfigLocations.All);
 
 
+IApplication app = Application.Create ();
 
 
-Application.Run<ExampleWindow> ().Dispose ();
+app.Run<ExampleWindow> ();
 
 
-// Before the application exits, reset Terminal.Gui for clean shutdown
-Application.Shutdown ();
+// Dispose the app to clean up and enable Console.WriteLine below
+app.Dispose ();
 
 
 // To see this output on the screen it must be done after shutdown,
 // To see this output on the screen it must be done after shutdown,
 // which restores the previous screen.
 // which restores the previous screen.
 Console.WriteLine ($@"Username: {ExampleWindow.UserName}");
 Console.WriteLine ($@"Username: {ExampleWindow.UserName}");
 
 
 // Defines a top-level window with border and title
 // Defines a top-level window with border and title
-public class ExampleWindow : Window
+public sealed class ExampleWindow : Window
 {
 {
     public static string UserName { get; set; }
     public static string UserName { get; set; }
 
 
@@ -74,39 +72,32 @@ public class ExampleWindow : Window
 
 
         // When login button is clicked display a message popup
         // When login button is clicked display a message popup
         btnLogin.Accepting += (s, e) =>
         btnLogin.Accepting += (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");
-                               }
-                               // When Accepting is handled, set e.Handled to true to prevent further processing.
-                               e.Handled = true;
-                           };
+                              {
+                                  if (userNameText.Text == "admin" && passwordText.Text == "password")
+                                  {
+                                      MessageBox.Query (App, "Logging In", "Login Successful", "Ok");
+                                      UserName = userNameText.Text;
+                                      Application.RequestStop ();
+                                  }
+                                  else
+                                  {
+                                      MessageBox.ErrorQuery (App, "Logging In", "Incorrect username or password", "Ok");
+                                  }
+
+                                  // When Accepting is handled, set e.Handled to true to prevent further processing.
+                                  e.Handled = true;
+                              };
 
 
         // Add the views to the Window
         // Add the views to the Window
         Add (usernameLabel, userNameText, passwordLabel, passwordText, btnLogin);
         Add (usernameLabel, userNameText, passwordLabel, passwordText, btnLogin);
 
 
-        ListView lv = new ListView ()
+        var lv = new ListView
         {
         {
-            Y = Pos.AnchorEnd(),
-            Height= Dim.Auto(),
-            Width = Dim.Auto()
+            Y = Pos.AnchorEnd (),
+            Height = Dim.Auto (),
+            Width = Dim.Auto ()
         };
         };
         lv.SetSource (["One", "Two", "Three", "Four"]);
         lv.SetSource (["One", "Two", "Three", "Four"]);
         Add (lv);
         Add (lv);
     }
     }
-
-    public override void EndInit ()
-    {
-        base.EndInit ();
-        // Set the theme to "Anders" if it exists, otherwise use "Default"
-        ThemeManager.Theme = ThemeManager.GetThemeNames ().FirstOrDefault (x => x == "Anders") ?? "Default";
-    }
 }
 }
- 

+ 1 - 4
Examples/Example/README.md

@@ -1,11 +1,8 @@
 # Terminal.Gui C# Example
 # Terminal.Gui C# Example
 
 
-This example shows how to use the Terminal.Gui library to create a simple GUI application in C#.
+This example shows how to use the Terminal.Gui library to create a simple TUI application in C#.
 
 
 This is the same code found in the Terminal.Gui README.md file.
 This is the same code found in the Terminal.Gui README.md file.
 
 
 To explore the full range of functionality in Terminal.Gui, see the [UICatalog](../UICatalog) project
 To explore the full range of functionality in Terminal.Gui, see the [UICatalog](../UICatalog) project
 
 
-See [README.md](https://github.com/gui-cs/Terminal.Gui) for a list of all Terminal.Gui samples.
-
-Note, the old `demo.cs` example has been deleted because it was not a very good example. It can still be found in the [git history](https://github.com/gui-cs/Terminal.Gui/tree/v1.8.2).

+ 11 - 45
Examples/FluentExample/Program.cs

@@ -5,63 +5,31 @@ using Terminal.Gui.Drawing;
 using Terminal.Gui.ViewBase;
 using Terminal.Gui.ViewBase;
 using Terminal.Gui.Views;
 using Terminal.Gui.Views;
 
 
-#if POST_4148
-// Run the application with fluent API - automatically creates, runs, and disposes the runnable
-
-// Display the result
-if (Application.Create ()
-               .Init ()
-               .Run<ColorPickerView> ()
-               .Shutdown () is Color { } result)
-{
-    Console.WriteLine (@$"Selected Color: {(Color?)result}");
-}
-else
-{
-    Console.WriteLine (@"No color selected");
-}
-#else
-
-// Run using traditional approach
-IApplication app = Application.Create ();
-app.Init ();
-var colorPicker = new ColorPickerView ();
-app.Run (colorPicker);
+IApplication? app = Application.Create ()
+                               .Init ()
+                               .Run<ColorPickerView> ();
 
 
-Color? resultColor = colorPicker.Result;
+// Run the application with fluent API - automatically creates, runs, and disposes the runnable
+Color? result = app.GetResult () as Color?;
 
 
-colorPicker.Dispose ();
-app.Shutdown ();
+// Shut down the app with Dispose before we can use Console.WriteLine
+app.Dispose ();
 
 
-if (resultColor is { } result)
+if (result is { })
 {
 {
-    Console.WriteLine (@$"Selected Color: {(Color?)result}");
+    Console.WriteLine (@$"Selected Color: {result}");
 }
 }
 else
 else
 {
 {
     Console.WriteLine (@"No color selected");
     Console.WriteLine (@"No color selected");
 }
 }
 
 
-#endif
-
-#if POST_4148
 /// <summary>
 /// <summary>
 ///     A runnable view that allows the user to select a color.
 ///     A runnable view that allows the user to select a color.
-///     Demonstrates IRunnable<TResult> pattern with automatic disposal.
+///     Demonstrates the Runnable with type pattern with automatic disposal.
 /// </summary>
 /// </summary>
 public class ColorPickerView : Runnable<Color?>
 public class ColorPickerView : Runnable<Color?>
 {
 {
-
-#else
-/// <summary>
-///     A runnable view that allows the user to select a color.
-///     Uses the traditional approach without automatic disposal/Fluent API.
-/// </summary>
-public class ColorPickerView : Toplevel
-{
-    public Color? Result { get; set; }
-
-#endif
     public ColorPickerView ()
     public ColorPickerView ()
     {
     {
         Title = "Select a Color (Esc to quit)";
         Title = "Select a Color (Esc to quit)";
@@ -126,7 +94,6 @@ public class ColorPickerView : Toplevel
         Add (instructions, colorPicker, okButton, cancelButton);
         Add (instructions, colorPicker, okButton, cancelButton);
     }
     }
 
 
-#if POST_4148
     protected override bool OnIsRunningChanging (bool oldIsRunning, bool newIsRunning)
     protected override bool OnIsRunningChanging (bool oldIsRunning, bool newIsRunning)
     {
     {
         // Alternative place to extract result before stopping
         // Alternative place to extract result before stopping
@@ -134,10 +101,9 @@ public class ColorPickerView : Toplevel
         if (!newIsRunning && Result is null)
         if (!newIsRunning && Result is null)
         {
         {
             // User pressed Esc - could extract current selection here
             // User pressed Esc - could extract current selection here
-            // Result = _colorPicker.SelectedColor;
+            //Result = SelectedColor;
         }
         }
 
 
         return base.OnIsRunningChanging (oldIsRunning, newIsRunning);
         return base.OnIsRunningChanging (oldIsRunning, newIsRunning);
     }
     }
-#endif
 }
 }

+ 2 - 2
Examples/NativeAot/Program.cs

@@ -101,13 +101,13 @@ public class ExampleWindow : Window
         {
         {
             if (userNameText.Text == "admin" && passwordText.Text == "password")
             if (userNameText.Text == "admin" && passwordText.Text == "password")
             {
             {
-                MessageBox.Query ("Logging In", "Login Successful", "Ok");
+                MessageBox.Query (App, "Logging In", "Login Successful", "Ok");
                 UserName = userNameText.Text;
                 UserName = userNameText.Text;
                 Application.RequestStop ();
                 Application.RequestStop ();
             }
             }
             else
             else
             {
             {
-                MessageBox.ErrorQuery ("Logging In", "Incorrect username or password", "Ok");
+                MessageBox.ErrorQuery (App, "Logging In", "Incorrect username or password", "Ok");
             }
             }
             // Anytime Accepting is handled, make sure to set e.Handled to true.
             // Anytime Accepting is handled, make sure to set e.Handled to true.
             e.Handled = true;
             e.Handled = true;

+ 7 - 8
Examples/ReactiveExample/Program.cs

@@ -1,9 +1,7 @@
 using System.Reactive.Concurrency;
 using System.Reactive.Concurrency;
 using ReactiveUI;
 using ReactiveUI;
-using ReactiveUI.SourceGenerators;
-using Terminal.Gui.Configuration;
 using Terminal.Gui.App;
 using Terminal.Gui.App;
-using Terminal.Gui.ViewBase;
+using Terminal.Gui.Configuration;
 
 
 namespace ReactiveExample;
 namespace ReactiveExample;
 
 
@@ -12,11 +10,12 @@ public static class Program
     private static void Main (string [] args)
     private static void Main (string [] args)
     {
     {
         ConfigurationManager.Enable (ConfigLocations.All);
         ConfigurationManager.Enable (ConfigLocations.All);
-        Application.Init ();
-        RxApp.MainThreadScheduler = TerminalScheduler.Default;
+        using IApplication app = Application.Create ();
+        app.Init ();
+        RxApp.MainThreadScheduler = new TerminalScheduler (app);
         RxApp.TaskpoolScheduler = TaskPoolScheduler.Default;
         RxApp.TaskpoolScheduler = TaskPoolScheduler.Default;
-        Application.Run (new LoginView (new LoginViewModel ()));
-        Application.TopRunnable.Dispose ();
-        Application.Shutdown ();
+        var loginView = new LoginView (new ());
+        app.Run (loginView);
+        loginView.Dispose ();
     }
     }
 }
 }

+ 8 - 4
Examples/ReactiveExample/README.md

@@ -7,10 +7,14 @@ This is a sample app that shows how to use `System.Reactive` and `ReactiveUI` wi
 In order to use reactive extensions scheduling, copy-paste the `TerminalScheduler.cs` file into your project, and add the following lines to the composition root of your `Terminal.Gui` application:
 In order to use reactive extensions scheduling, copy-paste the `TerminalScheduler.cs` file into your project, and add the following lines to the composition root of your `Terminal.Gui` application:
 
 
 ```cs
 ```cs
-Application.Init ();
-RxApp.MainThreadScheduler = TerminalScheduler.Default;
+ConfigurationManager.Enable (ConfigLocations.All);
+using IApplication app = Application.Create ();
+app.Init ();
+RxApp.MainThreadScheduler = new TerminalScheduler (app);
 RxApp.TaskpoolScheduler = TaskPoolScheduler.Default;
 RxApp.TaskpoolScheduler = TaskPoolScheduler.Default;
-Application.Run (new RootView (new RootViewModel ()));
+var loginView = new LoginView (new ());
+app.Run (loginView);
+loginView.Dispose ();
 ```
 ```
 
 
 From now on, you can use `.ObserveOn(RxApp.MainThreadScheduler)` to return to the main loop from a background thread. This is useful when you have a `IObservable<TValue>` updated from a background thread, and you wish to update the UI with `TValue`s received from that observable.
 From now on, you can use `.ObserveOn(RxApp.MainThreadScheduler)` to return to the main loop from a background thread. This is useful when you have a `IObservable<TValue>` updated from a background thread, and you wish to update the UI with `TValue`s received from that observable.
@@ -43,6 +47,6 @@ If you combine `OneWay` and `OneWayToSource` data bindings, you get `TwoWay` dat
 // 'clearButton' is 'Button'
 // 'clearButton' is 'Button'
 clearButton
 clearButton
 	.Events ()
 	.Events ()
-	.Clicked
+	.Accepting
 	.InvokeCommand (ViewModel, x => x.Clear);
 	.InvokeCommand (ViewModel, x => x.Clear);
 ```
 ```

+ 28 - 21
Examples/ReactiveExample/TerminalScheduler.cs

@@ -1,4 +1,4 @@
-using System;
+#nullable enable
 using System.Reactive.Concurrency;
 using System.Reactive.Concurrency;
 using System.Reactive.Disposables;
 using System.Reactive.Disposables;
 using Terminal.Gui.App;
 using Terminal.Gui.App;
@@ -7,8 +7,9 @@ namespace ReactiveExample;
 
 
 public class TerminalScheduler : LocalScheduler
 public class TerminalScheduler : LocalScheduler
 {
 {
-    public static readonly TerminalScheduler Default = new ();
-    private TerminalScheduler () { }
+    public TerminalScheduler (IApplication? application) { _application = application; }
+
+    private readonly IApplication? _application = null;
 
 
     public override IDisposable Schedule<TState> (
     public override IDisposable Schedule<TState> (
         TState state,
         TState state,
@@ -21,15 +22,15 @@ public class TerminalScheduler : LocalScheduler
             var composite = new CompositeDisposable (2);
             var composite = new CompositeDisposable (2);
             var cancellation = new CancellationDisposable ();
             var cancellation = new CancellationDisposable ();
 
 
-            Application.Invoke (
-                                (_) =>
-                                {
-                                    if (!cancellation.Token.IsCancellationRequested)
-                                    {
-                                        composite.Add (action (this, state));
-                                    }
-                                }
-                               );
+            _application?.Invoke (
+                                 (_) =>
+                                 {
+                                     if (!cancellation.Token.IsCancellationRequested)
+                                     {
+                                         composite.Add (action (this, state));
+                                     }
+                                 }
+                                );
             composite.Add (cancellation);
             composite.Add (cancellation);
 
 
             return composite;
             return composite;
@@ -39,16 +40,22 @@ public class TerminalScheduler : LocalScheduler
         {
         {
             var composite = new CompositeDisposable (2);
             var composite = new CompositeDisposable (2);
 
 
-            object timeout = Application.AddTimeout (
-                                                     dueTime,
-                                                     () =>
-                                                     {
-                                                         composite.Add (action (this, state));
+            object? timeout = _application?.AddTimeout (
+                                                      dueTime,
+                                                      () =>
+                                                      {
+                                                          composite.Add (action (this, state));
 
 
-                                                         return false;
-                                                     }
-                                                    );
-            composite.Add (Disposable.Create (() => Application.RemoveTimeout (timeout)));
+                                                          return false;
+                                                      }
+                                                     );
+            composite.Add (Disposable.Create (() =>
+                                              {
+                                                  if (timeout is { })
+                                                  {
+                                                      _application?.RemoveTimeout (timeout);
+                                                  }
+                                              }));
 
 
             return composite;
             return composite;
         }
         }

+ 1 - 2
Examples/ReactiveExample/ViewExtensions.cs

@@ -1,5 +1,4 @@
-using System;
-using Terminal.Gui.ViewBase;
+using Terminal.Gui.ViewBase;
 using Terminal.Gui.Views;
 using Terminal.Gui.Views;
 
 
 namespace ReactiveExample;
 namespace ReactiveExample;

+ 31 - 28
Examples/RunnableWrapperExample/Program.cs

@@ -13,41 +13,42 @@ var textField = new TextField { Width = 40, Text = "Default text" };
 textField.Title = "Enter your name";
 textField.Title = "Enter your name";
 textField.BorderStyle = LineStyle.Single;
 textField.BorderStyle = LineStyle.Single;
 
 
-var textRunnable = textField.AsRunnable (tf => tf.Text);
+RunnableWrapper<TextField, string> textRunnable = textField.AsRunnable (tf => tf.Text);
 app.Run (textRunnable);
 app.Run (textRunnable);
 
 
 if (textRunnable.Result is { } name)
 if (textRunnable.Result is { } name)
 {
 {
-    MessageBox.Query ("Result", $"You entered: {name}", "OK");
+    MessageBox.Query (app, "Result", $"You entered: {name}", "OK");
 }
 }
 else
 else
 {
 {
-    MessageBox.Query ("Result", "Canceled", "OK");
+    MessageBox.Query (app, "Result", "Canceled", "OK");
 }
 }
+
 textRunnable.Dispose ();
 textRunnable.Dispose ();
 
 
 // Example 2: Use IApplication.RunView() for one-liner
 // Example 2: Use IApplication.RunView() for one-liner
-var selectedColor = app.RunView (
-    new ColorPicker
-    {
-        Title = "Pick a Color",
-        BorderStyle = LineStyle.Single
-    },
-    cp => cp.SelectedColor);
+Color selectedColor = app.RunView (
+                                   new ColorPicker
+                                   {
+                                       Title = "Pick a Color",
+                                       BorderStyle = LineStyle.Single
+                                   },
+                                   cp => cp.SelectedColor);
 
 
-MessageBox.Query ("Result", $"Selected color: {selectedColor}", "OK");
+MessageBox.Query (app, "Result", $"Selected color: {selectedColor}", "OK");
 
 
 // Example 3: FlagSelector with typed enum result
 // Example 3: FlagSelector with typed enum result
-var flagSelector = new FlagSelector<SelectorStyles>
+FlagSelector<SelectorStyles> flagSelector = new()
 {
 {
     Title = "Choose Styles",
     Title = "Choose Styles",
     BorderStyle = LineStyle.Single
     BorderStyle = LineStyle.Single
 };
 };
 
 
-var flagsRunnable = flagSelector.AsRunnable (fs => fs.Value);
+RunnableWrapper<FlagSelector<SelectorStyles>, SelectorStyles?> flagsRunnable = flagSelector.AsRunnable (fs => fs.Value);
 app.Run (flagsRunnable);
 app.Run (flagsRunnable);
 
 
-MessageBox.Query ("Result", $"Selected styles: {flagsRunnable.Result}", "OK");
+MessageBox.Query (app, "Result", $"Selected styles: {flagsRunnable.Result}", "OK");
 flagsRunnable.Dispose ();
 flagsRunnable.Dispose ();
 
 
 // Example 4: Any View without result extraction
 // Example 4: Any View without result extraction
@@ -58,29 +59,31 @@ var label = new Label
     Y = Pos.Center ()
     Y = Pos.Center ()
 };
 };
 
 
-var labelRunnable = label.AsRunnable ();
+RunnableWrapper<Label, object> labelRunnable = label.AsRunnable ();
 app.Run (labelRunnable);
 app.Run (labelRunnable);
 
 
 // Can still access the wrapped view
 // Can still access the wrapped view
-MessageBox.Query ("Result", $"Label text was: {labelRunnable.WrappedView.Text}", "OK");
+MessageBox.Query (app, "Result", $"Label text was: {labelRunnable.WrappedView.Text}", "OK");
 labelRunnable.Dispose ();
 labelRunnable.Dispose ();
 
 
 // Example 5: Complex custom View made runnable
 // Example 5: Complex custom View made runnable
-var formView = CreateCustomForm ();
-var formRunnable = formView.AsRunnable (ExtractFormData);
+View formView = CreateCustomForm ();
+RunnableWrapper<View, FormData> formRunnable = formView.AsRunnable (ExtractFormData);
 
 
 app.Run (formRunnable);
 app.Run (formRunnable);
 
 
 if (formRunnable.Result is { } formData)
 if (formRunnable.Result is { } formData)
 {
 {
     MessageBox.Query (
     MessageBox.Query (
-        "Form Results",
-        $"Name: {formData.Name}\nAge: {formData.Age}\nAgreed: {formData.Agreed}",
-        "OK");
+                      app,
+                      "Form Results",
+                      $"Name: {formData.Name}\nAge: {formData.Age}\nAgreed: {formData.Agreed}",
+                      "OK");
 }
 }
+
 formRunnable.Dispose ();
 formRunnable.Dispose ();
 
 
-app.Shutdown ();
+app.Dispose ();
 
 
 // Helper method to create a custom form
 // Helper method to create a custom form
 View CreateCustomForm ()
 View CreateCustomForm ()
@@ -126,10 +129,10 @@ View CreateCustomForm ()
     };
     };
 
 
     okButton.Accepting += (s, e) =>
     okButton.Accepting += (s, e) =>
-    {
-        form.App?.RequestStop ();
-        e.Handled = true;
-    };
+                          {
+                              form.App?.RequestStop ();
+                              e.Handled = true;
+                          };
 
 
     form.Add (new Label { Text = "Name:", X = 2, Y = 1 });
     form.Add (new Label { Text = "Name:", X = 2, Y = 1 });
     form.Add (nameField);
     form.Add (nameField);
@@ -148,7 +151,7 @@ FormData ExtractFormData (View form)
     var ageField = form.SubViews.FirstOrDefault (v => v.Id == "ageField") as TextField;
     var ageField = form.SubViews.FirstOrDefault (v => v.Id == "ageField") as TextField;
     var agreeCheckbox = form.SubViews.FirstOrDefault (v => v.Id == "agreeCheckbox") as CheckBox;
     var agreeCheckbox = form.SubViews.FirstOrDefault (v => v.Id == "agreeCheckbox") as CheckBox;
 
 
-    return new FormData
+    return new()
     {
     {
         Name = nameField?.Text ?? string.Empty,
         Name = nameField?.Text ?? string.Empty,
         Age = int.TryParse (ageField?.Text, out int age) ? age : 0,
         Age = int.TryParse (ageField?.Text, out int age) ? age : 0,
@@ -157,7 +160,7 @@ FormData ExtractFormData (View form)
 }
 }
 
 
 // Result type for custom form
 // Result type for custom form
-record FormData
+internal record FormData
 {
 {
     public string Name { get; init; } = string.Empty;
     public string Name { get; init; } = string.Empty;
     public int Age { get; init; }
     public int Age { get; init; }

+ 15 - 15
Examples/SelfContained/Program.cs

@@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Globalization;
 using Terminal.Gui.Configuration;
 using Terminal.Gui.Configuration;
 using Terminal.Gui.App;
 using Terminal.Gui.App;
+using Terminal.Gui.Drawing;
 using Terminal.Gui.ViewBase;
 using Terminal.Gui.ViewBase;
 using Terminal.Gui.Views;
 using Terminal.Gui.Views;
 
 
@@ -16,7 +17,9 @@ public static class Program
     private static void Main (string [] args)
     private static void Main (string [] args)
     {
     {
         ConfigurationManager.Enable (ConfigLocations.All);
         ConfigurationManager.Enable (ConfigLocations.All);
-        Application.Init ();
+
+        IApplication app = Application.Create ();
+        app.Init ();
 
 
         #region The code in this region is not intended for use in a self-contained single-file. It's just here to make sure there is no functionality break with localization in Terminal.Gui using single-file
         #region The code in this region is not intended for use in a self-contained single-file. It's just here to make sure there is no functionality break with localization in Terminal.Gui using single-file
 
 
@@ -33,28 +36,25 @@ public static class Program
 
 
         #endregion
         #endregion
 
 
-        ExampleWindow app = new ();
-        Application.Run (app);
+        using ExampleWindow exampleWindow = new ();
+        string? userName = app.Run (exampleWindow) as string;
 
 
-        // Dispose the app object before shutdown
-        app.Dispose ();
 
 
-        // Before the application exits, reset Terminal.Gui for clean shutdown
-        Application.Shutdown ();
+        // Shutdown the application in order to free resources and clean up the terminal
+        app.Dispose ();
 
 
         // To see this output on the screen it must be done after shutdown,
         // To see this output on the screen it must be done after shutdown,
         // which restores the previous screen.
         // which restores the previous screen.
-        Console.WriteLine ($@"Username: {ExampleWindow.UserName}");
+        Console.WriteLine ($@"Username: {userName}");
     }
     }
 }
 }
 
 
 // Defines a top-level window with border and title
 // Defines a top-level window with border and title
-public class ExampleWindow : Window
+public class ExampleWindow : Runnable<string>
 {
 {
-    public static string? UserName;
-
     public ExampleWindow ()
     public ExampleWindow ()
     {
     {
+        BorderStyle = LineStyle.Single;
         Title = $"Example App ({Application.QuitKey} to quit)";
         Title = $"Example App ({Application.QuitKey} to quit)";
 
 
         // Create input components and labels
         // Create input components and labels
@@ -100,13 +100,13 @@ public class ExampleWindow : Window
                            {
                            {
                                if (userNameText.Text == "admin" && passwordText.Text == "password")
                                if (userNameText.Text == "admin" && passwordText.Text == "password")
                                {
                                {
-                                   MessageBox.Query ("Logging In", "Login Successful", "Ok");
-                                   UserName = userNameText.Text;
-                                   Application.RequestStop ();
+                                   MessageBox.Query (App, "Logging In", "Login Successful", "Ok");
+                                   Result = userNameText.Text;
+                                   App?.RequestStop ();
                                }
                                }
                                else
                                else
                                {
                                {
-                                   MessageBox.ErrorQuery ("Logging In", "Incorrect username or password", "Ok");
+                                   MessageBox.ErrorQuery (App, "Logging In", "Incorrect username or password", "Ok");
                                }
                                }
                                // When Accepting is handled, set e.Handled to true to prevent further processing.
                                // When Accepting is handled, set e.Handled to true to prevent further processing.
                                e.Handled = true;
                                e.Handled = true;

+ 26 - 0
Examples/SelfContained/README.md

@@ -2,6 +2,32 @@
 
 
 This project aims to test the `Terminal.Gui` library to create a simple `self-contained` `single-file` GUI application in C#, ensuring that all its features are available.
 This project aims to test the `Terminal.Gui` library to create a simple `self-contained` `single-file` GUI application in C#, ensuring that all its features are available.
 
 
+## Modern Terminal.Gui API
+
+This example uses the modern Terminal.Gui application model:
+
+```csharp
+ConfigurationManager.Enable (ConfigLocations.All);
+
+IApplication app = Application.Create ();
+app.Init ();
+
+using ExampleWindow exampleWindow = new ();
+string? userName = app.Run (exampleWindow) as string;
+
+app.Dispose ();
+
+Console.WriteLine ($@"Username: {userName}");
+```
+
+Key aspects of the modern model:
+- Use `Application.Create()` to create an `IApplication` instance
+- Call `app.Init()` to initialize the application
+- Use `app.Run(view)` to run views with proper resource management
+- Call `app.Dispose()` to clean up resources and restore the terminal
+- Event handling uses `Accepting` event instead of legacy `Accept` event
+- Set `e.Handled = true` in event handlers to prevent further processing
+
 With `Debug` the `.csproj` is used and with `Release` the latest `nuget package` is used, either in `Solution Configurations` or in `Profile Publish`.
 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`.
 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`.

+ 1 - 1
Examples/UICatalog/README.md

@@ -80,7 +80,7 @@ The default `Window` shows the Scenario name and supports exiting the Scenario t
 
 
 ![screenshot](generic_screenshot.png)
 ![screenshot](generic_screenshot.png)
 
 
-To build a more advanced scenario, where control of the `Toplevel` and `Window` is needed (e.g. for scenarios using `MenuBar` or `StatusBar`), simply use `Application.Top` per normal Terminal.Gui programming, as seen in the `Notepad` scenario.
+To build a more advanced scenario, where control of the `Runnable` and `Window` is needed (e.g. for scenarios using `MenuBar` or `StatusBar`), simply use `Application.Top` per normal Terminal.Gui programming, as seen in the `Notepad` scenario.
 
 
 For complete control, the `Init` and `Run` overrides can be implemented. The `base.Init` creates `Win`. The `base.Run` simply calls `Application.Run(Application.Top)`.
 For complete control, the `Init` and `Run` overrides can be implemented. The `base.Init` creates `Win`. The `base.Run` simply calls `Application.Run(Application.Top)`.
 
 

+ 2 - 2
Examples/UICatalog/Resources/config.json

@@ -11,7 +11,7 @@
       "Hot Dog Stand": {
       "Hot Dog Stand": {
         "Schemes": [
         "Schemes": [
           {
           {
-            "Toplevel": {
+            "Runnable": {
               "Normal": {
               "Normal": {
                 "Foreground": "Black",
                 "Foreground": "Black",
                 "Background": "#FFFF00"
                 "Background": "#FFFF00"
@@ -177,7 +177,7 @@
             }
             }
           },
           },
           {
           {
-            "TopLevel": {
+            "Runnable": {
               "Normal": {
               "Normal": {
                 "Foreground": "DarkGray",
                 "Foreground": "DarkGray",
                 "Background": "White"
                 "Background": "White"

+ 5 - 5
Examples/UICatalog/Scenario.cs

@@ -67,7 +67,7 @@ namespace UICatalog;
 ///         };
 ///         };
 /// 
 /// 
 ///         var button = new Button { X = Pos.Center (), Y = Pos.Center (), Text = "Press me!" };
 ///         var button = new Button { X = Pos.Center (), Y = Pos.Center (), Text = "Press me!" };
-///         button.Accept += (s, e) => MessageBox.ErrorQuery ("Error", "You pressed the button!", "Ok");
+///         button.Accept += (s, e) => MessageBox.ErrorQuery (App, "Error", "You pressed the button!", "Ok");
 ///         appWindow.Add (button);
 ///         appWindow.Add (button);
 /// 
 /// 
 ///         // Run - Start the application.
 ///         // Run - Start the application.
@@ -210,20 +210,20 @@ public class Scenario : IDisposable
         void OnClearedContents (object? sender, EventArgs args) => BenchmarkResults.ClearedContentCount++;
         void OnClearedContents (object? sender, EventArgs args) => BenchmarkResults.ClearedContentCount++;
     }
     }
 
 
-    private void OnApplicationOnIteration (object? s, IterationEventArgs a)
+    private void OnApplicationOnIteration (object? s, EventArgs<IApplication?> a)
     {
     {
         BenchmarkResults.IterationCount++;
         BenchmarkResults.IterationCount++;
         if (BenchmarkResults.IterationCount > BENCHMARK_MAX_NATURAL_ITERATIONS + (_demoKeys!.Count * BENCHMARK_KEY_PACING))
         if (BenchmarkResults.IterationCount > BENCHMARK_MAX_NATURAL_ITERATIONS + (_demoKeys!.Count * BENCHMARK_KEY_PACING))
         {
         {
-            Application.RequestStop ();
+            a.Value?.RequestStop ();
         }
         }
     }
     }
 
 
-    // BUGBUG: This is incompatible with modals. This should be using the new equivalent of Toplevel.Ready 
+    // BUGBUG: This is incompatible with modals. This should be using the new equivalent of Runnable.Ready 
     // BUGBUG: which will be IsRunningChanged with newIsRunning == true
     // BUGBUG: which will be IsRunningChanged with newIsRunning == true
     private void OnApplicationSessionBegun (object? sender, SessionTokenEventArgs e)
     private void OnApplicationSessionBegun (object? sender, SessionTokenEventArgs e)
     {
     {
-        SubscribeAllSubViews (Application.TopRunnable!);
+        SubscribeAllSubViews (Application.TopRunnableView!);
 
 
         _demoKeys = GetDemoKeyStrokes ();
         _demoKeys = GetDemoKeyStrokes ();
 
 

+ 8 - 8
Examples/UICatalog/Scenarios/Adornments.cs

@@ -11,7 +11,7 @@ public class Adornments : Scenario
     {
     {
         Application.Init ();
         Application.Init ();
 
 
-        Window app = new ()
+        Window appWindow = new ()
         {
         {
             Title = GetQuitKeyAndName (),
             Title = GetQuitKeyAndName (),
             BorderStyle = LineStyle.None
             BorderStyle = LineStyle.None
@@ -28,7 +28,7 @@ public class Adornments : Scenario
 
 
         editor.Border!.Thickness = new (1, 2, 1, 1);
         editor.Border!.Thickness = new (1, 2, 1, 1);
 
 
-        app.Add (editor);
+        appWindow.Add (editor);
 
 
         var window = new Window
         var window = new Window
         {
         {
@@ -38,7 +38,7 @@ public class Adornments : Scenario
             Width = Dim.Fill (Dim.Func (_ => editor.Frame.Width)),
             Width = Dim.Fill (Dim.Func (_ => editor.Frame.Width)),
             Height = Dim.Fill ()
             Height = Dim.Fill ()
         };
         };
-        app.Add (window);
+        appWindow.Add (window);
 
 
         var tf1 = new TextField { Width = 10, Text = "TextField" };
         var tf1 = new TextField { Width = 10, Text = "TextField" };
         var color = new ColorPicker16 { Title = "BG", BoxHeight = 1, BoxWidth = 1, X = Pos.AnchorEnd () };
         var color = new ColorPicker16 { Title = "BG", BoxHeight = 1, BoxWidth = 1, X = Pos.AnchorEnd () };
@@ -60,7 +60,7 @@ public class Adornments : Scenario
         var button = new Button { X = Pos.Center (), Y = Pos.Center (), Text = "Press me!" };
         var button = new Button { X = Pos.Center (), Y = Pos.Center (), Text = "Press me!" };
 
 
         button.Accepting += (s, e) =>
         button.Accepting += (s, e) =>
-                             MessageBox.Query (20, 7, "Hi", $"Am I a {window.GetType ().Name}?", "Yes", "No");
+                             MessageBox.Query (appWindow.App, 20, 7, "Hi", $"Am I a {window.GetType ().Name}?", "Yes", "No");
 
 
         var label = new TextView
         var label = new TextView
         {
         {
@@ -121,7 +121,7 @@ public class Adornments : Scenario
                                       Text = "text (Y = 1)",
                                       Text = "text (Y = 1)",
                                       CanFocus = true
                                       CanFocus = true
                                   };
                                   };
-                                  textFieldInPadding.Accepting += (s, e) => MessageBox.Query (20, 7, "TextField", textFieldInPadding.Text, "Ok");
+                                  textFieldInPadding.Accepting += (s, e) => MessageBox.Query (appWindow.App, 20, 7, "TextField", textFieldInPadding.Text, "Ok");
                                   window.Padding.Add (textFieldInPadding);
                                   window.Padding.Add (textFieldInPadding);
 
 
                                   var btnButtonInPadding = new Button
                                   var btnButtonInPadding = new Button
@@ -132,7 +132,7 @@ public class Adornments : Scenario
                                       CanFocus = true,
                                       CanFocus = true,
                                       HighlightStates = MouseState.None,
                                       HighlightStates = MouseState.None,
                                   };
                                   };
-                                  btnButtonInPadding.Accepting += (s, e) => MessageBox.Query (20, 7, "Hi", "Button in Padding Pressed!", "Ok");
+                                  btnButtonInPadding.Accepting += (s, e) => MessageBox.Query (appWindow.App, 20, 7, "Hi", "Button in Padding Pressed!", "Ok");
                                   btnButtonInPadding.BorderStyle = LineStyle.Dashed;
                                   btnButtonInPadding.BorderStyle = LineStyle.Dashed;
                                   btnButtonInPadding.Border!.Thickness = new (1, 1, 1, 1);
                                   btnButtonInPadding.Border!.Thickness = new (1, 1, 1, 1);
                                   window.Padding.Add (btnButtonInPadding);
                                   window.Padding.Add (btnButtonInPadding);
@@ -155,8 +155,8 @@ public class Adornments : Scenario
         editor.AutoSelectSuperView = window;
         editor.AutoSelectSuperView = window;
         editor.AutoSelectAdornments = true;
         editor.AutoSelectAdornments = true;
 
 
-        Application.Run (app);
-        app.Dispose ();
+        Application.Run (appWindow);
+        appWindow.Dispose ();
 
 
         Application.Shutdown ();
         Application.Shutdown ();
     }
     }

+ 7 - 0
Examples/UICatalog/Scenarios/AllViewsTester.cs

@@ -220,6 +220,13 @@ public class AllViewsTester : Scenario
     {
     {
         Debug.Assert (_curView is null);
         Debug.Assert (_curView is null);
 
 
+        // Skip RunnableWrapper types as they have generic constraints that cannot be satisfied
+        if (type.IsGenericType && type.GetGenericTypeDefinition().Name.StartsWith("RunnableWrapper"))
+        {
+            Logging.Warning ($"Cannot create an instance of {type.Name} because it is a RunnableWrapper with unsatisfiable generic constraints.");
+            return;
+        }
+
         // If we are to create a generic Type
         // If we are to create a generic Type
         if (type.IsGenericType)
         if (type.IsGenericType)
         {
         {

+ 1 - 1
Examples/UICatalog/Scenarios/AnimationScenario/AnimationScenario.cs

@@ -78,7 +78,7 @@ public class AnimationScenario : Scenario
         if (!f.Exists)
         if (!f.Exists)
         {
         {
             Debug.WriteLine ($"Could not find {f.FullName}");
             Debug.WriteLine ($"Could not find {f.FullName}");
-            MessageBox.ErrorQuery ("Could not find gif", $"Could not find\n{f.FullName}", "Ok");
+            MessageBox.ErrorQuery (_imageView?.App, "Could not find gif", $"Could not find\n{f.FullName}", "Ok");
 
 
             return;
             return;
         }
         }

+ 4 - 4
Examples/UICatalog/Scenarios/Arrangement.cs

@@ -183,9 +183,9 @@ public class Arrangement : Scenario
 
 
         datePicker.SetScheme (new Scheme (
         datePicker.SetScheme (new Scheme (
                                           new Attribute (
                                           new Attribute (
-                                                         SchemeManager.GetScheme (Schemes.Toplevel).Normal.Foreground.GetBrighterColor (),
-                                                         SchemeManager.GetScheme (Schemes.Toplevel).Normal.Background.GetBrighterColor (),
-                                                         SchemeManager.GetScheme (Schemes.Toplevel).Normal.Style)));
+                                                         SchemeManager.GetScheme (Schemes.Runnable).Normal.Foreground.GetBrighterColor (),
+                                                         SchemeManager.GetScheme (Schemes.Runnable).Normal.Background.GetBrighterColor (),
+                                                         SchemeManager.GetScheme (Schemes.Runnable).Normal.Style)));
 
 
         TransparentView transparentView = new ()
         TransparentView transparentView = new ()
         {
         {
@@ -237,7 +237,7 @@ public class Arrangement : Scenario
             Width = Dim.Auto (minimumContentDim: 15),
             Width = Dim.Auto (minimumContentDim: 15),
             Height = Dim.Auto (minimumContentDim: 3),
             Height = Dim.Auto (minimumContentDim: 3),
             Title = $"Overlapped{id} _{GetNextHotKey ()}",
             Title = $"Overlapped{id} _{GetNextHotKey ()}",
-            SchemeName = SchemeManager.SchemesToSchemeName (Schemes.Toplevel),
+            SchemeName = SchemeManager.SchemesToSchemeName (Schemes.Runnable),
             Id = $"Overlapped{id}",
             Id = $"Overlapped{id}",
             ShadowStyle = ShadowStyle.Transparent,
             ShadowStyle = ShadowStyle.Transparent,
             BorderStyle = LineStyle.Double,
             BorderStyle = LineStyle.Double,

+ 15 - 15
Examples/UICatalog/Scenarios/Bars.cs

@@ -14,9 +14,9 @@ public class Bars : Scenario
     public override void Main ()
     public override void Main ()
     {
     {
         Application.Init ();
         Application.Init ();
-        Toplevel app = new ();
+        Runnable app = new ();
 
 
-        app.Loaded += App_Loaded;
+        app.IsModalChanged += App_Loaded;
 
 
         Application.Run (app);
         Application.Run (app);
         app.Dispose ();
         app.Dispose ();
@@ -28,7 +28,7 @@ public class Bars : Scenario
     // QuitKey and it only sticks if changed after init
     // QuitKey and it only sticks if changed after init
     private void App_Loaded (object sender, EventArgs e)
     private void App_Loaded (object sender, EventArgs e)
     {
     {
-        Application.TopRunnable!.Title = GetQuitKeyAndName ();
+        Application.TopRunnableView!.Title = GetQuitKeyAndName ();
 
 
         ObservableCollection<string> eventSource = new ();
         ObservableCollection<string> eventSource = new ();
         ListView eventLog = new ListView ()
         ListView eventLog = new ListView ()
@@ -37,11 +37,11 @@ public class Bars : Scenario
             X = Pos.AnchorEnd (),
             X = Pos.AnchorEnd (),
             Width = Dim.Auto (),
             Width = Dim.Auto (),
             Height = Dim.Fill (), // Make room for some wide things
             Height = Dim.Fill (), // Make room for some wide things
-            SchemeName = "Toplevel",
+            SchemeName = "Runnable",
             Source = new ListWrapper<string> (eventSource)
             Source = new ListWrapper<string> (eventSource)
         };
         };
         eventLog.Border!.Thickness = new (0, 1, 0, 0);
         eventLog.Border!.Thickness = new (0, 1, 0, 0);
-        Application.TopRunnable.Add (eventLog);
+        Application.TopRunnableView.Add (eventLog);
 
 
         FrameView menuBarLikeExamples = new ()
         FrameView menuBarLikeExamples = new ()
         {
         {
@@ -51,7 +51,7 @@ public class Bars : Scenario
             Width = Dim.Fill () - Dim.Width (eventLog),
             Width = Dim.Fill () - Dim.Width (eventLog),
             Height = Dim.Percent(33),
             Height = Dim.Percent(33),
         };
         };
-        Application.TopRunnable.Add (menuBarLikeExamples);
+        Application.TopRunnableView.Add (menuBarLikeExamples);
 
 
         Label label = new Label ()
         Label label = new Label ()
         {
         {
@@ -98,7 +98,7 @@ public class Bars : Scenario
             Width = Dim.Fill () - Dim.Width (eventLog),
             Width = Dim.Fill () - Dim.Width (eventLog),
             Height = Dim.Percent (33),
             Height = Dim.Percent (33),
         };
         };
-        Application.TopRunnable.Add (menuLikeExamples);
+        Application.TopRunnableView.Add (menuLikeExamples);
 
 
         label = new Label ()
         label = new Label ()
         {
         {
@@ -212,7 +212,7 @@ public class Bars : Scenario
             Width = Dim.Width (menuLikeExamples),
             Width = Dim.Width (menuLikeExamples),
             Height = Dim.Percent (33),
             Height = Dim.Percent (33),
         };
         };
-        Application.TopRunnable.Add (statusBarLikeExamples);
+        Application.TopRunnableView.Add (statusBarLikeExamples);
 
 
         label = new Label ()
         label = new Label ()
         {
         {
@@ -249,7 +249,7 @@ public class Bars : Scenario
         ConfigStatusBar (bar);
         ConfigStatusBar (bar);
         statusBarLikeExamples.Add (bar);
         statusBarLikeExamples.Add (bar);
 
 
-        foreach (FrameView frameView in Application.TopRunnable.SubViews.Where (f => f is FrameView)!)
+        foreach (FrameView frameView in Application.TopRunnableView.SubViews.Where (f => f is FrameView)!)
         {
         {
             foreach (Bar barView in frameView.SubViews.Where (b => b is Bar)!)
             foreach (Bar barView in frameView.SubViews.Where (b => b is Bar)!)
             {
             {
@@ -309,7 +309,7 @@ public class Bars : Scenario
     //                                                  new TimeSpan (0),
     //                                                  new TimeSpan (0),
     //                                                  () =>
     //                                                  () =>
     //                                                  {
     //                                                  {
-    //                                                      MessageBox.Query ("File", "New");
+    //                                                      MessageBox.Query (App, "File", "New");
 
 
     //                                                      return false;
     //                                                      return false;
     //                                                  });
     //                                                  });
@@ -331,7 +331,7 @@ public class Bars : Scenario
     //                                               new TimeSpan (0),
     //                                               new TimeSpan (0),
     //                                               () =>
     //                                               () =>
     //                                               {
     //                                               {
-    //                                                   MessageBox.Query ("File", "Open");
+    //                                                   MessageBox.Query (App, "File", "Open");
 
 
     //                                                   return false;
     //                                                   return false;
     //                                               });
     //                                               });
@@ -353,7 +353,7 @@ public class Bars : Scenario
     //                                               new TimeSpan (0),
     //                                               new TimeSpan (0),
     //                                               () =>
     //                                               () =>
     //                                               {
     //                                               {
-    //                                                   MessageBox.Query ("File", "Save");
+    //                                                   MessageBox.Query (App, "File", "Save");
 
 
     //                                                   return false;
     //                                                   return false;
     //                                               });
     //                                               });
@@ -375,7 +375,7 @@ public class Bars : Scenario
     //                                                 new TimeSpan (0),
     //                                                 new TimeSpan (0),
     //                                                 () =>
     //                                                 () =>
     //                                                 {
     //                                                 {
-    //                                                     MessageBox.Query ("File", "Save As");
+    //                                                     MessageBox.Query (App, "File", "Save As");
 
 
     //                                                     return false;
     //                                                     return false;
     //                                                 });
     //                                                 });
@@ -383,7 +383,7 @@ public class Bars : Scenario
 
 
     //    contextMenu.Add (newMenu, open, save, saveAs);
     //    contextMenu.Add (newMenu, open, save, saveAs);
 
 
-    //    contextMenu.KeyBindings.Add (Key.Esc, Command.QuitToplevel);
+    //    contextMenu.KeyBindings.Add (Key.Esc, Command.Quit);
 
 
     //    contextMenu.Initialized += Menu_Initialized;
     //    contextMenu.Initialized += Menu_Initialized;
 
 
@@ -555,7 +555,7 @@ public class Bars : Scenario
 
 
         return;
         return;
 
 
-        void Button_Clicked (object sender, EventArgs e) { MessageBox.Query ("Hi", $"You clicked {sender}"); }
+        void Button_Clicked (object sender, EventArgs e) { MessageBox.Query ((sender as View)?.App, "Hi", $"You clicked {sender}"); }
 
 
     }
     }
 
 

+ 5 - 5
Examples/UICatalog/Scenarios/Buttons.cs

@@ -59,7 +59,7 @@ public class Buttons : Scenario
 
 
                                     if (e.Handled)
                                     if (e.Handled)
                                     {
                                     {
-                                        MessageBox.ErrorQuery ("Error", "This button is no longer the Quit button; the Swap Default button is.", "_Ok");
+                                        MessageBox.ErrorQuery ((s as View)?.App, "Error", "This button is no longer the Quit button; the Swap Default button is.", "_Ok");
                                     }
                                     }
                                 };
                                 };
         main.Add (swapButton);
         main.Add (swapButton);
@@ -69,7 +69,7 @@ public class Buttons : Scenario
             button.Accepting += (s, e) =>
             button.Accepting += (s, e) =>
                              {
                              {
                                  string btnText = button.Text;
                                  string btnText = button.Text;
-                                 MessageBox.Query ("Message", $"Did you click {txt}?", "Yes", "No");
+                                 MessageBox.Query ((s as View)?.App, "Message", $"Did you click {txt}?", "Yes", "No");
                                  e.Handled = true;
                                  e.Handled = true;
                              };
                              };
         }
         }
@@ -112,7 +112,7 @@ public class Buttons : Scenario
                  );
                  );
         button.Accepting += (s, e) =>
         button.Accepting += (s, e) =>
                          {
                          {
-                             MessageBox.Query ("Message", "Question?", "Yes", "No");
+                             MessageBox.Query ((s as View)?.App, "Message", "Question?", "Yes", "No");
                              e.Handled = true;
                              e.Handled = true;
                          };
                          };
 
 
@@ -294,7 +294,7 @@ public class Buttons : Scenario
             X = 2,
             X = 2,
             Y = Pos.Bottom (osAlignment) + 1,
             Y = Pos.Bottom (osAlignment) + 1,
             Width = Dim.Width (computedFrame) - 2,
             Width = Dim.Width (computedFrame) - 2,
-            SchemeName = "TopLevel",
+            SchemeName = "Runnable",
             Text = mhkb
             Text = mhkb
         };
         };
         moveHotKeyBtn.Accepting += (s, e) =>
         moveHotKeyBtn.Accepting += (s, e) =>
@@ -311,7 +311,7 @@ public class Buttons : Scenario
             X = Pos.Left (absoluteFrame) + 1,
             X = Pos.Left (absoluteFrame) + 1,
             Y = Pos.Bottom (osAlignment) + 1,
             Y = Pos.Bottom (osAlignment) + 1,
             Width = Dim.Width (absoluteFrame) - 2,
             Width = Dim.Width (absoluteFrame) - 2,
-            SchemeName = "TopLevel",
+            SchemeName = "Runnable",
             Text = muhkb
             Text = muhkb
         };
         };
         moveUnicodeHotKeyBtn.Accepting += (s, e) =>
         moveUnicodeHotKeyBtn.Accepting += (s, e) =>

+ 3 - 2
Examples/UICatalog/Scenarios/ChineseUI.cs

@@ -32,8 +32,9 @@ public class ChineseUI : Scenario
 
 
         btn.Accepting += (s, e) =>
         btn.Accepting += (s, e) =>
                       {
                       {
-                          int result = MessageBox.Query (
-                                                         "Confirm",
+                          int? result = MessageBox.Query (
+                                                          (s as View)?.App,
+                                                          "Confirm",
                                                          "Are you sure you want to quit ui?",
                                                          "Are you sure you want to quit ui?",
                                                          0,
                                                          0,
                                                          "Yes",
                                                          "Yes",

+ 1 - 1
Examples/UICatalog/Scenarios/Clipping.cs

@@ -118,7 +118,7 @@ public class Clipping : Scenario
             Height = Dim.Auto (minimumContentDim: 4),
             Height = Dim.Auto (minimumContentDim: 4),
             Width = Dim.Auto (minimumContentDim: 14),
             Width = Dim.Auto (minimumContentDim: 14),
             Title = $"Overlapped{id} _{GetNextHotKey ()}",
             Title = $"Overlapped{id} _{GetNextHotKey ()}",
-            SchemeName = SchemeManager.SchemesToSchemeName(Schemes.Toplevel),
+            SchemeName = SchemeManager.SchemesToSchemeName(Schemes.Runnable),
             Id = $"Overlapped{id}",
             Id = $"Overlapped{id}",
             ShadowStyle = ShadowStyle.Transparent,
             ShadowStyle = ShadowStyle.Transparent,
             BorderStyle = LineStyle.Double,
             BorderStyle = LineStyle.Double,

+ 2 - 2
Examples/UICatalog/Scenarios/CombiningMarks.cs

@@ -8,12 +8,12 @@ public class CombiningMarks : Scenario
     public override void Main ()
     public override void Main ()
     {
     {
         Application.Init ();
         Application.Init ();
-        var top = new Toplevel ();
+        var top = new Runnable ();
 
 
         top.DrawComplete += (s, e) =>
         top.DrawComplete += (s, e) =>
         {
         {
             // Forces reset _lineColsOffset because we're dealing with direct draw
             // Forces reset _lineColsOffset because we're dealing with direct draw
-            Application.TopRunnable!.SetNeedsDraw ();
+            Application.TopRunnableView!.SetNeedsDraw ();
 
 
             var i = -1;
             var i = -1;
             top.Move (0, ++i);
             top.Move (0, ++i);

+ 1 - 1
Examples/UICatalog/Scenarios/ComboBoxIteration.cs

@@ -25,7 +25,7 @@ public class ComboBoxIteration : Scenario
 
 
         var lbComboBox = new Label
         var lbComboBox = new Label
         {
         {
-            SchemeName = "TopLevel",
+            SchemeName = "Runnable",
             X = Pos.Right (lbListView) + 1,
             X = Pos.Right (lbListView) + 1,
             Width = Dim.Percent (40)
             Width = Dim.Percent (40)
         };
         };

+ 1 - 1
Examples/UICatalog/Scenarios/ComputedLayout.cs

@@ -280,7 +280,7 @@ public class ComputedLayout : Scenario
             Y = Pos.Percent (50),
             Y = Pos.Percent (50),
             Width = Dim.Percent (80),
             Width = Dim.Percent (80),
             Height = Dim.Percent (10),
             Height = Dim.Percent (10),
-            SchemeName = "TopLevel"
+            SchemeName = "Runnable"
         };
         };
 
 
         textView.Text =
         textView.Text =

+ 5 - 5
Examples/UICatalog/Scenarios/ConfigurationEditor.cs

@@ -60,7 +60,7 @@ public class ConfigurationEditor : Scenario
 
 
         win.Add (_tabView, statusBar);
         win.Add (_tabView, statusBar);
 
 
-        win.Loaded += (s, a) =>
+        win.IsModalChanged += (s, a) =>
                       {
                       {
                           Open ();
                           Open ();
                       };
                       };
@@ -75,7 +75,7 @@ public class ConfigurationEditor : Scenario
 
 
         void ConfigurationManagerOnApplied (object? sender, ConfigurationManagerEventArgs e)
         void ConfigurationManagerOnApplied (object? sender, ConfigurationManagerEventArgs e)
         {
         {
-            Application.TopRunnable?.SetNeedsDraw ();
+            Application.TopRunnableView?.SetNeedsDraw ();
         }
         }
     }
     }
     public void Save ()
     public void Save ()
@@ -153,9 +153,9 @@ public class ConfigurationEditor : Scenario
                 continue;
                 continue;
             }
             }
 
 
-            int result = MessageBox.Query (
+            int? result = MessageBox.Query (editor?.App,
                                            "Save Changes",
                                            "Save Changes",
-                                           $"Save changes to {editor.FileInfo!.Name}",
+                                           $"Save changes to {editor?.FileInfo!.Name}",
                                            "_Yes",
                                            "_Yes",
                                            "_No",
                                            "_No",
                                            "_Cancel"
                                            "_Cancel"
@@ -164,7 +164,7 @@ public class ConfigurationEditor : Scenario
             switch (result)
             switch (result)
             {
             {
                 case 0:
                 case 0:
-                    editor.Save ();
+                    editor?.Save ();
 
 
                     break;
                     break;
 
 

+ 11 - 7
Examples/UICatalog/Scenarios/ContextMenus.cs

@@ -26,7 +26,7 @@ public class ContextMenus : Scenario
         {
         {
             Title = GetQuitKeyAndName (),
             Title = GetQuitKeyAndName (),
             Arrangement = ViewArrangement.Fixed,
             Arrangement = ViewArrangement.Fixed,
-            SchemeName = "Toplevel"
+            SchemeName = "Runnable"
         };
         };
 
 
         _appWindow.Initialized += AppWindowOnInitialized;
         _appWindow.Initialized += AppWindowOnInitialized;
@@ -49,7 +49,7 @@ public class ContextMenus : Scenario
             var text = "Context Menu";
             var text = "Context Menu";
             var width = 20;
             var width = 20;
 
 
-            CreateWinContextMenu ();
+            CreateWinContextMenu (ApplicationImpl.Instance);
 
 
             var label = new Label
             var label = new Label
             {
             {
@@ -84,7 +84,11 @@ public class ContextMenus : Scenario
             _appWindow.MouseClick += OnAppWindowOnMouseClick;
             _appWindow.MouseClick += OnAppWindowOnMouseClick;
 
 
             CultureInfo originalCulture = Thread.CurrentThread.CurrentUICulture;
             CultureInfo originalCulture = Thread.CurrentThread.CurrentUICulture;
-            _appWindow.Closed += (s, e) => { Thread.CurrentThread.CurrentUICulture = originalCulture; };
+            _appWindow.IsRunningChanged += (s, e) => {
+                                               if (!e.Value)
+                                               {
+                                                   Thread.CurrentThread.CurrentUICulture = originalCulture;
+                                               } };
         }
         }
 
 
         void OnAppWindowOnMouseClick (object? s, MouseEventArgs e)
         void OnAppWindowOnMouseClick (object? s, MouseEventArgs e)
@@ -108,7 +112,7 @@ public class ContextMenus : Scenario
         }
         }
     }
     }
 
 
-    private void CreateWinContextMenu ()
+    private void CreateWinContextMenu (IApplication? app)
     {
     {
         _winContextMenu = new (
         _winContextMenu = new (
                                [
                                [
@@ -122,7 +126,7 @@ public class ContextMenus : Scenario
                                    {
                                    {
                                        Title = "_Configuration...",
                                        Title = "_Configuration...",
                                        HelpText = "Show configuration",
                                        HelpText = "Show configuration",
-                                       Action = () => MessageBox.Query (
+                                       Action = () => MessageBox.Query (app,
                                                                         50,
                                                                         50,
                                                                         10,
                                                                         10,
                                                                         "Configuration",
                                                                         "Configuration",
@@ -140,7 +144,7 @@ public class ContextMenus : Scenario
                                                               Title = "_Setup...",
                                                               Title = "_Setup...",
                                                               HelpText = "Perform setup",
                                                               HelpText = "Perform setup",
                                                               Action = () => MessageBox
                                                               Action = () => MessageBox
-                                                                           .Query (
+                                                                           .Query (app,
                                                                                    50,
                                                                                    50,
                                                                                    10,
                                                                                    10,
                                                                                    "Setup",
                                                                                    "Setup",
@@ -154,7 +158,7 @@ public class ContextMenus : Scenario
                                                               Title = "_Maintenance...",
                                                               Title = "_Maintenance...",
                                                               HelpText = "Maintenance mode",
                                                               HelpText = "Maintenance mode",
                                                               Action = () => MessageBox
                                                               Action = () => MessageBox
-                                                                           .Query (
+                                                                           .Query (app,
                                                                                    50,
                                                                                    50,
                                                                                    10,
                                                                                    10,
                                                                                    "Maintenance",
                                                                                    "Maintenance",

+ 17 - 17
Examples/UICatalog/Scenarios/CsvEditor.cs

@@ -215,7 +215,7 @@ public class CsvEditor : Scenario
                                       _tableView.Table.Columns
                                       _tableView.Table.Columns
                                      );
                                      );
 
 
-            int result = MessageBox.Query (
+            int? result = MessageBox.Query (ApplicationImpl.Instance,
                                            "Column Type",
                                            "Column Type",
                                            "Pick a data type for the column",
                                            "Pick a data type for the column",
                                            "Date",
                                            "Date",
@@ -225,7 +225,7 @@ public class CsvEditor : Scenario
                                            "Cancel"
                                            "Cancel"
                                           );
                                           );
 
 
-            if (result <= -1 || result >= 4)
+            if (result is null || result >= 4)
             {
             {
                 return;
                 return;
             }
             }
@@ -308,7 +308,7 @@ public class CsvEditor : Scenario
 
 
         if (_tableView.SelectedColumn == -1)
         if (_tableView.SelectedColumn == -1)
         {
         {
-            MessageBox.ErrorQuery ("No Column", "No column selected", "Ok");
+            MessageBox.ErrorQuery (ApplicationImpl.Instance, "No Column", "No column selected", "Ok");
 
 
             return;
             return;
         }
         }
@@ -320,7 +320,7 @@ public class CsvEditor : Scenario
         }
         }
         catch (Exception ex)
         catch (Exception ex)
         {
         {
-            MessageBox.ErrorQuery ("Could not remove column", ex.Message, "Ok");
+            MessageBox.ErrorQuery (ApplicationImpl.Instance, "Could not remove column", ex.Message, "Ok");
         }
         }
     }
     }
 
 
@@ -342,7 +342,7 @@ public class CsvEditor : Scenario
             }
             }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
-                MessageBox.ErrorQuery (60, 20, "Failed to set text", ex.Message, "Ok");
+                MessageBox.ErrorQuery (ApplicationImpl.Instance, 60, 20, "Failed to set text", ex.Message, "Ok");
             }
             }
 
 
             _tableView.Update ();
             _tableView.Update ();
@@ -388,7 +388,7 @@ public class CsvEditor : Scenario
 
 
         if (_tableView.SelectedColumn == -1)
         if (_tableView.SelectedColumn == -1)
         {
         {
-            MessageBox.ErrorQuery ("No Column", "No column selected", "Ok");
+            MessageBox.ErrorQuery (ApplicationImpl.Instance, "No Column", "No column selected", "Ok");
 
 
             return;
             return;
         }
         }
@@ -413,7 +413,7 @@ public class CsvEditor : Scenario
         }
         }
         catch (Exception ex)
         catch (Exception ex)
         {
         {
-            MessageBox.ErrorQuery ("Error moving column", ex.Message, "Ok");
+            MessageBox.ErrorQuery (ApplicationImpl.Instance, "Error moving column", ex.Message, "Ok");
         }
         }
     }
     }
 
 
@@ -426,7 +426,7 @@ public class CsvEditor : Scenario
 
 
         if (_tableView.SelectedRow == -1)
         if (_tableView.SelectedRow == -1)
         {
         {
-            MessageBox.ErrorQuery ("No Rows", "No row selected", "Ok");
+            MessageBox.ErrorQuery (ApplicationImpl.Instance, "No Rows", "No row selected", "Ok");
 
 
             return;
             return;
         }
         }
@@ -446,7 +446,7 @@ public class CsvEditor : Scenario
                     return;
                     return;
                 }
                 }
 
 
-                object?[] arrayItems = currentRow.ItemArray;
+                object? [] arrayItems = currentRow.ItemArray;
                 _currentTable.Rows.Remove (currentRow);
                 _currentTable.Rows.Remove (currentRow);
 
 
                 // Removing and Inserting the same DataRow seems to result in it loosing its values so we have to create a new instance
                 // Removing and Inserting the same DataRow seems to result in it loosing its values so we have to create a new instance
@@ -462,7 +462,7 @@ public class CsvEditor : Scenario
         }
         }
         catch (Exception ex)
         catch (Exception ex)
         {
         {
-            MessageBox.ErrorQuery ("Error moving column", ex.Message, "Ok");
+            MessageBox.ErrorQuery (ApplicationImpl.Instance, "Error moving column", ex.Message, "Ok");
         }
         }
     }
     }
 
 
@@ -470,7 +470,7 @@ public class CsvEditor : Scenario
     {
     {
         if (_tableView?.Table is null)
         if (_tableView?.Table is null)
         {
         {
-            MessageBox.ErrorQuery ("No Table Loaded", "No table has currently be opened", "Ok");
+            MessageBox.ErrorQuery (ApplicationImpl.Instance, "No Table Loaded", "No table has currently be opened", "Ok");
 
 
             return true;
             return true;
         }
         }
@@ -575,14 +575,14 @@ public class CsvEditor : Scenario
                 _selectedCellTextField.SuperView.Enabled = true;
                 _selectedCellTextField.SuperView.Enabled = true;
             }
             }
 
 
-            if (Application.TopRunnable is { })
+            if (Application.TopRunnableView is { })
             {
             {
-                Application.TopRunnable.Title = $"{GetName ()} - {Path.GetFileName (_currentFile)}";
+                Application.TopRunnableView.Title = $"{GetName ()} - {Path.GetFileName (_currentFile)}";
             }
             }
         }
         }
         catch (Exception ex)
         catch (Exception ex)
         {
         {
-            MessageBox.ErrorQuery (
+            MessageBox.ErrorQuery (ApplicationImpl.Instance,
                                    "Open Failed",
                                    "Open Failed",
                                    $"Error on line {lineNumber}{Environment.NewLine}{ex.Message}",
                                    $"Error on line {lineNumber}{Environment.NewLine}{ex.Message}",
                                    "Ok"
                                    "Ok"
@@ -612,7 +612,7 @@ public class CsvEditor : Scenario
     {
     {
         if (_tableView?.Table is null || string.IsNullOrWhiteSpace (_currentFile) || _currentTable is null)
         if (_tableView?.Table is null || string.IsNullOrWhiteSpace (_currentFile) || _currentTable is null)
         {
         {
-            MessageBox.ErrorQuery ("No file loaded", "No file is currently loaded", "Ok");
+            MessageBox.ErrorQuery (ApplicationImpl.Instance, "No file loaded", "No file is currently loaded", "Ok");
 
 
             return;
             return;
         }
         }
@@ -674,7 +674,7 @@ public class CsvEditor : Scenario
 
 
         if (col.DataType == typeof (string))
         if (col.DataType == typeof (string))
         {
         {
-            MessageBox.ErrorQuery (
+            MessageBox.ErrorQuery (ApplicationImpl.Instance,
                                    "Cannot Format Column",
                                    "Cannot Format Column",
                                    "String columns cannot be Formatted, try adding a new column to the table with a date/numerical Type",
                                    "String columns cannot be Formatted, try adding a new column to the table with a date/numerical Type",
                                    "Ok"
                                    "Ok"
@@ -711,7 +711,7 @@ public class CsvEditor : Scenario
 
 
         if (_tableView.SelectedColumn == -1)
         if (_tableView.SelectedColumn == -1)
         {
         {
-            MessageBox.ErrorQuery ("No Column", "No column selected", "Ok");
+            MessageBox.ErrorQuery (ApplicationImpl.Instance, "No Column", "No column selected", "Ok");
 
 
             return;
             return;
         }
         }

+ 8 - 2
Examples/UICatalog/Scenarios/Dialogs.cs

@@ -266,7 +266,7 @@ public class Dialogs : Scenario
             {
             {
                 Title = titleEdit.Text,
                 Title = titleEdit.Text,
                 Text = "Dialog Text",
                 Text = "Dialog Text",
-                ButtonAlignment = (Alignment)Enum.Parse (typeof (Alignment), alignmentGroup.Labels! [(int)alignmentGroup.Value!.Value] [1..]),
+                ButtonAlignment = (Alignment)Enum.Parse (typeof (Alignment), alignmentGroup.Labels! [(int)alignmentGroup.Value!.Value] [0..]),
 
 
                 Buttons = buttons.ToArray ()
                 Buttons = buttons.ToArray ()
             };
             };
@@ -340,7 +340,13 @@ public class Dialogs : Scenario
                               };
                               };
             dialog.Add (addChar);
             dialog.Add (addChar);
 
 
-            dialog.Closed += (s, e) => { buttonPressedLabel.Text = $"{clicked}"; };
+            dialog.IsRunningChanged += (s, e) =>
+                                       {
+                                           if (!e.Value)
+                                           {
+                                               buttonPressedLabel.Text = $"{clicked}";
+                                           }
+                                       };
         }
         }
         catch (FormatException)
         catch (FormatException)
         {
         {

+ 6 - 6
Examples/UICatalog/Scenarios/DynamicStatusBar.cs

@@ -15,7 +15,7 @@ public class DynamicStatusBar : Scenario
     public override void Main ()
     public override void Main ()
     {
     {
         Application.Init ();
         Application.Init ();
-        Application.Run<DynamicStatusBarSample> ().Dispose ();
+        Application.Run<DynamicStatusBarSample> ();
         Application.Shutdown ();
         Application.Shutdown ();
     }
     }
 
 
@@ -79,7 +79,7 @@ public class DynamicStatusBar : Scenario
             }
             }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
-                MessageBox.ErrorQuery ("Binding Error", $"Binding failed: {ex}.", "Ok");
+                MessageBox.ErrorQuery (ApplicationImpl.Instance, "Binding Error", $"Binding failed: {ex}.", "Ok");
             }
             }
         }
         }
     }
     }
@@ -140,7 +140,7 @@ public class DynamicStatusBar : Scenario
         public TextView TextAction { get; }
         public TextView TextAction { get; }
         public TextField TextShortcut { get; }
         public TextField TextShortcut { get; }
         public TextField TextTitle { get; }
         public TextField TextTitle { get; }
-        public Action CreateAction (DynamicStatusItem item) { return () => MessageBox.ErrorQuery (item.Title, item.Action, "Ok"); }
+        public Action CreateAction (DynamicStatusItem item) { return () => MessageBox.ErrorQuery (ApplicationImpl.Instance, item.Title, item.Action, "Ok"); }
 
 
         public void EditStatusItem (Shortcut statusItem)
         public void EditStatusItem (Shortcut statusItem)
         {
         {
@@ -184,7 +184,7 @@ public class DynamicStatusBar : Scenario
                               {
                               {
                                   if (string.IsNullOrEmpty (TextTitle.Text))
                                   if (string.IsNullOrEmpty (TextTitle.Text))
                                   {
                                   {
-                                      MessageBox.ErrorQuery ("Invalid title", "Must enter a valid title!.", "Ok");
+                                      MessageBox.ErrorQuery (App, "Invalid title", "Must enter a valid title!.", "Ok");
                                   }
                                   }
                                   else
                                   else
                                   {
                                   {
@@ -200,7 +200,7 @@ public class DynamicStatusBar : Scenario
                                       TextTitle.Text = string.Empty;
                                       TextTitle.Text = string.Empty;
                                       Application.RequestStop ();
                                       Application.RequestStop ();
                                   };
                                   };
-            var dialog = new Dialog { Title = "Enter the menu details.", Buttons = [btnOk, btnCancel], Height = Dim.Auto (DimAutoStyle.Content, 17, Application.Screen.Height) };
+            var dialog = new Dialog { Title = "Enter the menu details.", Buttons = [btnOk, btnCancel], Height = Dim.Auto (DimAutoStyle.Content, 17, App?.Screen.Height) };
 
 
             Width = Dim.Fill ();
             Width = Dim.Fill ();
             Height = Dim.Fill () - 2;
             Height = Dim.Fill () - 2;
@@ -382,7 +382,7 @@ public class DynamicStatusBar : Scenario
                               {
                               {
                                   if (string.IsNullOrEmpty (frmStatusBarDetails.TextTitle.Text) && _currentEditStatusItem != null)
                                   if (string.IsNullOrEmpty (frmStatusBarDetails.TextTitle.Text) && _currentEditStatusItem != null)
                                   {
                                   {
-                                      MessageBox.ErrorQuery ("Invalid title", "Must enter a valid title!.", "Ok");
+                                      MessageBox.ErrorQuery (App, "Invalid title", "Must enter a valid title!.", "Ok");
                                   }
                                   }
                                   else if (_currentEditStatusItem != null)
                                   else if (_currentEditStatusItem != null)
                                   {
                                   {

+ 19 - 11
Examples/UICatalog/Scenarios/Editor.cs

@@ -156,7 +156,7 @@ public class Editor : Scenario
                                        new (Key.F2, "Open", Open),
                                        new (Key.F2, "Open", Open),
                                        new (Key.F3, "Save", () => Save ()),
                                        new (Key.F3, "Save", () => Save ()),
                                        new (Key.F4, "Save As", () => SaveAs ()),
                                        new (Key.F4, "Save As", () => SaveAs ()),
-                                       new (Key.Empty, $"OS Clipboard IsSupported : {Clipboard.IsSupported}", null),
+                                       new (Key.Empty, $"OS Clipboard IsSupported : {Application.Clipboard!.IsSupported}", null),
                                        siCursorPosition
                                        siCursorPosition
                                    ]
                                    ]
                                   )
                                   )
@@ -170,7 +170,14 @@ public class Editor : Scenario
 
 
         _appWindow.Add (statusBar);
         _appWindow.Add (statusBar);
 
 
-        _appWindow.Closed += (s, e) => Thread.CurrentThread.CurrentUICulture = new ("en-US");
+        _appWindow.IsRunningChanged += (s, e) =>
+                                       {
+                                           if (!e.Value)
+                                           {
+                                               // BUGBUG: This should restore the original culture info
+                                               Thread.CurrentThread.CurrentUICulture = new ("en-US");
+                                           }
+                                       };
 
 
         CreateFindReplace ();
         CreateFindReplace ();
 
 
@@ -193,7 +200,8 @@ public class Editor : Scenario
 
 
         Debug.Assert (_textView.IsDirty);
         Debug.Assert (_textView.IsDirty);
 
 
-        int r = MessageBox.ErrorQuery (
+        int? r = MessageBox.ErrorQuery (
+                                       ApplicationImpl.Instance,
                                        "Save File",
                                        "Save File",
                                        $"Do you want save changes in {_appWindow.Title}?",
                                        $"Do you want save changes in {_appWindow.Title}?",
                                        "Yes",
                                        "Yes",
@@ -228,7 +236,7 @@ public class Editor : Scenario
         }
         }
         catch (Exception ex)
         catch (Exception ex)
         {
         {
-            MessageBox.ErrorQuery ("Error", ex.Message, "Ok");
+            MessageBox.ErrorQuery (ApplicationImpl.Instance, "Error", ex.Message, "Ok");
         }
         }
     }
     }
 
 
@@ -307,11 +315,11 @@ public class Editor : Scenario
 
 
         if (!found)
         if (!found)
         {
         {
-            MessageBox.Query ("Find", $"The following specified text was not found: '{_textToFind}'", "Ok");
+            MessageBox.Query (ApplicationImpl.Instance, "Find", $"The following specified text was not found: '{_textToFind}'", "Ok");
         }
         }
         else if (gaveFullTurn)
         else if (gaveFullTurn)
         {
         {
-            MessageBox.Query (
+            MessageBox.Query (ApplicationImpl.Instance,
                               "Find",
                               "Find",
                               $"No more occurrences were found for the following specified text: '{_textToFind}'",
                               $"No more occurrences were found for the following specified text: '{_textToFind}'",
                               "Ok"
                               "Ok"
@@ -887,7 +895,7 @@ public class Editor : Scenario
 
 
         if (_textView.ReplaceAllText (_textToFind, _matchCase, _matchWholeWord, _textToReplace))
         if (_textView.ReplaceAllText (_textToFind, _matchCase, _matchWholeWord, _textToReplace))
         {
         {
-            MessageBox.Query (
+            MessageBox.Query (ApplicationImpl.Instance,
                               "Replace All",
                               "Replace All",
                               $"All occurrences were replaced for the following specified text: '{_textToReplace}'",
                               $"All occurrences were replaced for the following specified text: '{_textToReplace}'",
                               "Ok"
                               "Ok"
@@ -895,7 +903,7 @@ public class Editor : Scenario
         }
         }
         else
         else
         {
         {
-            MessageBox.Query (
+            MessageBox.Query (ApplicationImpl.Instance,
                               "Replace All",
                               "Replace All",
                               $"None of the following specified text was found: '{_textToFind}'",
                               $"None of the following specified text was found: '{_textToFind}'",
                               "Ok"
                               "Ok"
@@ -1147,7 +1155,7 @@ public class Editor : Scenario
         {
         {
             if (File.Exists (path))
             if (File.Exists (path))
             {
             {
-                if (MessageBox.Query (
+                if (MessageBox.Query (ApplicationImpl.Instance,
                                       "Save File",
                                       "Save File",
                                       "File already exists. Overwrite any way?",
                                       "File already exists. Overwrite any way?",
                                       "No",
                                       "No",
@@ -1186,11 +1194,11 @@ public class Editor : Scenario
             _originalText = Encoding.Unicode.GetBytes (_textView.Text);
             _originalText = Encoding.Unicode.GetBytes (_textView.Text);
             _saved = true;
             _saved = true;
             _textView.ClearHistoryChanges ();
             _textView.ClearHistoryChanges ();
-            MessageBox.Query ("Save File", "File was successfully saved.", "Ok");
+            MessageBox.Query (ApplicationImpl.Instance, "Save File", "File was successfully saved.", "Ok");
         }
         }
         catch (Exception ex)
         catch (Exception ex)
         {
         {
-            MessageBox.ErrorQuery ("Error", ex.Message, "Ok");
+            MessageBox.ErrorQuery (ApplicationImpl.Instance, "Error", ex.Message, "Ok");
 
 
             return false;
             return false;
         }
         }

+ 1 - 1
Examples/UICatalog/Scenarios/EditorsAndHelpers/ArrangementEditor.cs

@@ -45,7 +45,7 @@ public sealed class ArrangementEditor : EditorBase
             if (ViewToEdit.Arrangement.HasFlag (ViewArrangement.Overlapped))
             if (ViewToEdit.Arrangement.HasFlag (ViewArrangement.Overlapped))
             {
             {
                 ViewToEdit.ShadowStyle = ShadowStyle.Transparent;
                 ViewToEdit.ShadowStyle = ShadowStyle.Transparent;
-                ViewToEdit.SchemeName = "Toplevel";
+                ViewToEdit.SchemeName = "Runnable";
             }
             }
             else
             else
             {
             {

+ 1 - 1
Examples/UICatalog/Scenarios/EditorsAndHelpers/DimEditor.cs

@@ -157,7 +157,7 @@ public class DimEditor : EditorBase
         }
         }
         catch (Exception e)
         catch (Exception e)
         {
         {
-            MessageBox.ErrorQuery ("Exception", e.Message, "Ok");
+            MessageBox.ErrorQuery (App, "Exception", e.Message, "Ok");
         }
         }
     }
     }
 }
 }

+ 1 - 1
Examples/UICatalog/Scenarios/EditorsAndHelpers/PosEditor.cs

@@ -160,7 +160,7 @@ public class PosEditor : EditorBase
         }
         }
         catch (Exception e)
         catch (Exception e)
         {
         {
-            MessageBox.ErrorQuery ("Exception", e.Message, "Ok");
+            MessageBox.ErrorQuery (App, "Exception", e.Message, "Ok");
         }
         }
     }
     }
 }
 }

+ 6 - 6
Examples/UICatalog/Scenarios/FileDialogExamples.cs

@@ -133,7 +133,7 @@ public class FileDialogExamples : Scenario
                              }
                              }
                              catch (Exception ex)
                              catch (Exception ex)
                              {
                              {
-                                 MessageBox.ErrorQuery ("Error", ex.ToString (), "_Ok");
+                                 MessageBox.ErrorQuery (ApplicationImpl.Instance, "Error", ex.ToString (), "_Ok");
                              }
                              }
                              finally
                              finally
                              {
                              {
@@ -153,7 +153,7 @@ public class FileDialogExamples : Scenario
         {
         {
             if (File.Exists (e.Dialog.Path))
             if (File.Exists (e.Dialog.Path))
             {
             {
-                int result = MessageBox.Query ("Overwrite?", "File already exists", "_Yes", "_No");
+                int? result = MessageBox.Query (ApplicationImpl.Instance, "Overwrite?", "File already exists", "_Yes", "_No");
                 e.Cancel = result == 1;
                 e.Cancel = result == 1;
             }
             }
         }
         }
@@ -243,12 +243,12 @@ public class FileDialogExamples : Scenario
             IReadOnlyList<string> multiSelected = fd.MultiSelected;
             IReadOnlyList<string> multiSelected = fd.MultiSelected;
             string path = fd.Path;
             string path = fd.Path;
 
 
-            // This needs to be disposed before opening other toplevel
+            // This needs to be disposed before opening other runnable
             fd.Dispose ();
             fd.Dispose ();
 
 
             if (canceled)
             if (canceled)
             {
             {
-                MessageBox.Query (
+                MessageBox.Query (ApplicationImpl.Instance,
                                   "Canceled",
                                   "Canceled",
                                   "You canceled navigation and did not pick anything",
                                   "You canceled navigation and did not pick anything",
                                   "Ok"
                                   "Ok"
@@ -256,7 +256,7 @@ public class FileDialogExamples : Scenario
             }
             }
             else if (_cbAllowMultipleSelection.CheckedState == CheckState.Checked)
             else if (_cbAllowMultipleSelection.CheckedState == CheckState.Checked)
             {
             {
-                MessageBox.Query (
+                MessageBox.Query (ApplicationImpl.Instance,
                                   "Chosen!",
                                   "Chosen!",
                                   "You chose:" + Environment.NewLine + string.Join (Environment.NewLine, multiSelected.Select (m => m)),
                                   "You chose:" + Environment.NewLine + string.Join (Environment.NewLine, multiSelected.Select (m => m)),
                                   "Ok"
                                   "Ok"
@@ -264,7 +264,7 @@ public class FileDialogExamples : Scenario
             }
             }
             else
             else
             {
             {
-                MessageBox.Query (
+                MessageBox.Query (ApplicationImpl.Instance,
                                   "Chosen!",
                                   "Chosen!",
                                   "You chose:" + Environment.NewLine + path,
                                   "You chose:" + Environment.NewLine + path,
                                   "Ok"
                                   "Ok"

+ 1 - 1
Examples/UICatalog/Scenarios/Generic.cs

@@ -29,7 +29,7 @@ public sealed class Generic : Scenario
                             {
                             {
                                 // When Accepting is handled, set e.Handled to true to prevent further processing.
                                 // When Accepting is handled, set e.Handled to true to prevent further processing.
                                 e.Handled = true;
                                 e.Handled = true;
-                                MessageBox.ErrorQuery ("Error", "You pressed the button!", "_Ok");
+                                MessageBox.ErrorQuery (ApplicationImpl.Instance, "Error", "You pressed the button!", "_Ok");
                             };
                             };
 
 
         appWindow.Add (button);
         appWindow.Add (button);

+ 4 - 4
Examples/UICatalog/Scenarios/HexEditor.cs

@@ -181,7 +181,7 @@ public class HexEditor : Scenario
         }
         }
     }
     }
 
 
-    private void Copy () { MessageBox.ErrorQuery ("Not Implemented", "Functionality not yet implemented.", "Ok"); }
+    private void Copy () { MessageBox.ErrorQuery (ApplicationImpl.Instance, "Not Implemented", "Functionality not yet implemented.", "Ok"); }
 
 
     private void CreateDemoFile (string fileName)
     private void CreateDemoFile (string fileName)
     {
     {
@@ -208,7 +208,7 @@ public class HexEditor : Scenario
         ms.Close ();
         ms.Close ();
     }
     }
 
 
-    private void Cut () { MessageBox.ErrorQuery ("Not Implemented", "Functionality not yet implemented.", "Ok"); }
+    private void Cut () { MessageBox.ErrorQuery (ApplicationImpl.Instance, "Not Implemented", "Functionality not yet implemented.", "Ok"); }
 
 
     private Stream LoadFile ()
     private Stream LoadFile ()
     {
     {
@@ -216,7 +216,7 @@ public class HexEditor : Scenario
 
 
         if (!_saved && _hexView!.Edits.Count > 0 && _hexView.Source is {})
         if (!_saved && _hexView!.Edits.Count > 0 && _hexView.Source is {})
         {
         {
-            if (MessageBox.ErrorQuery (
+            if (MessageBox.ErrorQuery (ApplicationImpl.Instance,
                                        "Save",
                                        "Save",
                                        "The changes were not saved. Want to open without saving?",
                                        "The changes were not saved. Want to open without saving?",
                                        "_Yes",
                                        "_Yes",
@@ -267,7 +267,7 @@ public class HexEditor : Scenario
         d.Dispose ();
         d.Dispose ();
     }
     }
 
 
-    private void Paste () { MessageBox.ErrorQuery ("Not Implemented", "Functionality not yet implemented.", "_Ok"); }
+    private void Paste () { MessageBox.ErrorQuery (ApplicationImpl.Instance, "Not Implemented", "Functionality not yet implemented.", "_Ok"); }
     private void Quit () { Application.RequestStop (); }
     private void Quit () { Application.RequestStop (); }
 
 
     private void Save ()
     private void Save ()

+ 3 - 3
Examples/UICatalog/Scenarios/Images.cs

@@ -183,7 +183,7 @@ public class Images : Scenario
 
 
         if (!_sixelSupportResult.SupportsTransparency)
         if (!_sixelSupportResult.SupportsTransparency)
         {
         {
-            if (MessageBox.Query (
+            if (MessageBox.Query (ApplicationImpl.Instance,
                                   "Transparency Not Supported",
                                   "Transparency Not Supported",
                                   "It looks like your terminal does not support transparent sixel backgrounds. Do you want to try anyway?",
                                   "It looks like your terminal does not support transparent sixel backgrounds. Do you want to try anyway?",
                                   "Yes",
                                   "Yes",
@@ -288,7 +288,7 @@ public class Images : Scenario
         }
         }
         catch (Exception ex)
         catch (Exception ex)
         {
         {
-            MessageBox.ErrorQuery ("Could not open file", ex.Message, "Ok");
+            MessageBox.ErrorQuery (ApplicationImpl.Instance, "Could not open file", ex.Message, "Ok");
 
 
             return;
             return;
         }
         }
@@ -492,7 +492,7 @@ public class Images : Scenario
     {
     {
         if (_imageView.FullResImage == null)
         if (_imageView.FullResImage == null)
         {
         {
-            MessageBox.Query ("No Image Loaded", "You must first open an image.  Use the 'Open Image' button above.", "Ok");
+            MessageBox.Query (ApplicationImpl.Instance, "No Image Loaded", "You must first open an image.  Use the 'Open Image' button above.", "Ok");
 
 
             return;
             return;
         }
         }

+ 1 - 1
Examples/UICatalog/Scenarios/InteractiveTree.cs

@@ -173,7 +173,7 @@ public class InteractiveTree : Scenario
 
 
                 if (parent is null)
                 if (parent is null)
                 {
                 {
-                    MessageBox.ErrorQuery (
+                    MessageBox.ErrorQuery (ApplicationImpl.Instance,
                                            "Could not delete",
                                            "Could not delete",
                                            $"Parent of '{toDelete}' was unexpectedly null",
                                            $"Parent of '{toDelete}' was unexpectedly null",
                                            "Ok"
                                            "Ok"

+ 4 - 4
Examples/UICatalog/Scenarios/KeyBindings.cs

@@ -164,17 +164,17 @@ public class KeyBindingsDemo : View
 
 
         AddCommand (Command.Save, ctx =>
         AddCommand (Command.Save, ctx =>
                                  {
                                  {
-                                     MessageBox.Query ($"{ctx.Command}", $"Ctx: {ctx}", buttons: "Ok");
+                                     MessageBox.Query (ApplicationImpl.Instance, $"{ctx.Command}", $"Ctx: {ctx}", buttons: "Ok");
                                      return true;
                                      return true;
                                  });
                                  });
         AddCommand (Command.New, ctx =>
         AddCommand (Command.New, ctx =>
                                 {
                                 {
-                                    MessageBox.Query ($"{ctx.Command}", $"Ctx: {ctx}", buttons: "Ok");
+                                    MessageBox.Query (ApplicationImpl.Instance, $"{ctx.Command}", $"Ctx: {ctx}", buttons: "Ok");
                                     return true;
                                     return true;
                                 });
                                 });
         AddCommand (Command.HotKey, ctx =>
         AddCommand (Command.HotKey, ctx =>
         {
         {
-            MessageBox.Query ($"{ctx.Command}", $"Ctx: {ctx}\nCommand: {ctx.Command}", buttons: "Ok");
+            MessageBox.Query (ApplicationImpl.Instance, $"{ctx.Command}", $"Ctx: {ctx}\nCommand: {ctx.Command}", buttons: "Ok");
             SetFocus ();
             SetFocus ();
             return true;
             return true;
         });
         });
@@ -189,7 +189,7 @@ public class KeyBindingsDemo : View
                                              {
                                              {
                                                  return false;
                                                  return false;
                                              }
                                              }
-                                             MessageBox.Query ($"{keyCommandContext.Binding}", $"Key: {keyCommandContext.Binding.Key}\nCommand: {ctx.Command}", buttons: "Ok");
+                                             MessageBox.Query (ApplicationImpl.Instance, $"{keyCommandContext.Binding}", $"Key: {keyCommandContext.Binding.Key}\nCommand: {ctx.Command}", buttons: "Ok");
                                              Application.RequestStop ();
                                              Application.RequestStop ();
                                              return true;
                                              return true;
                                          });
                                          });

+ 4 - 4
Examples/UICatalog/Scenarios/Keys.cs

@@ -86,7 +86,7 @@ public class Keys : Scenario
             Height = Dim.Fill (),
             Height = Dim.Fill (),
             Source = new ListWrapper<string> (keyList)
             Source = new ListWrapper<string> (keyList)
         };
         };
-        appKeyListView.SchemeName = "TopLevel";
+        appKeyListView.SchemeName = "Runnable";
         win.Add (appKeyListView);
         win.Add (appKeyListView);
 
 
         // View key events...
         // View key events...
@@ -114,7 +114,7 @@ public class Keys : Scenario
             Height = Dim.Fill (),
             Height = Dim.Fill (),
             Source = new ListWrapper<string> (keyDownList)
             Source = new ListWrapper<string> (keyDownList)
         };
         };
-        appKeyListView.SchemeName = "TopLevel";
+        appKeyListView.SchemeName = "Runnable";
         win.Add (onKeyDownListView);
         win.Add (onKeyDownListView);
 
 
         // KeyDownNotHandled
         // KeyDownNotHandled
@@ -134,7 +134,7 @@ public class Keys : Scenario
             Height = Dim.Fill (),
             Height = Dim.Fill (),
             Source = new ListWrapper<string> (keyDownNotHandledList)
             Source = new ListWrapper<string> (keyDownNotHandledList)
         };
         };
-        appKeyListView.SchemeName = "TopLevel";
+        appKeyListView.SchemeName = "Runnable";
         win.Add (onKeyDownNotHandledListView);
         win.Add (onKeyDownNotHandledListView);
 
 
 
 
@@ -155,7 +155,7 @@ public class Keys : Scenario
             Height = Dim.Fill (),
             Height = Dim.Fill (),
             Source = new ListWrapper<string> (swallowedList)
             Source = new ListWrapper<string> (swallowedList)
         };
         };
-        appKeyListView.SchemeName = "TopLevel";
+        appKeyListView.SchemeName = "Runnable";
         win.Add (onSwallowedListView);
         win.Add (onSwallowedListView);
 
 
         Application.Driver!.InputProcessor.AnsiSequenceSwallowed += (s, e) => { swallowedList.Add (e.Replace ("\x1b", "Esc")); };
         Application.Driver!.InputProcessor.AnsiSequenceSwallowed += (s, e) => { swallowedList.Add (e.Replace ("\x1b", "Esc")); };

+ 1 - 1
Examples/UICatalog/Scenarios/LineCanvasExperiment.cs

@@ -101,7 +101,7 @@ public class LineCanvasExperiment : Scenario
         //    Width = view4.Width,
         //    Width = view4.Width,
         //    Height = 5,
         //    Height = 5,
 
 
-        //    //Scheme = Colors.Schemes ["TopLevel"],
+        //    //Scheme = Colors.Schemes ["Runnable"],
         //    SuperViewRendersLineCanvas = true,
         //    SuperViewRendersLineCanvas = true,
         //    BorderStyle = LineStyle.Double
         //    BorderStyle = LineStyle.Double
         //};
         //};

+ 1 - 1
Examples/UICatalog/Scenarios/ListColumns.cs

@@ -336,7 +336,7 @@ public class ListColumns : Scenario
             }
             }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
-                MessageBox.ErrorQuery (60, 20, "Failed to set", ex.Message, "Ok");
+                MessageBox.ErrorQuery (ApplicationImpl.Instance, 60, 20, "Failed to set", ex.Message, "Ok");
             }
             }
         }
         }
     }
     }

+ 1 - 1
Examples/UICatalog/Scenarios/ListViewWithSelection.cs

@@ -98,7 +98,7 @@ public class ListViewWithSelection : Scenario
             Height = Dim.Fill (),
             Height = Dim.Fill (),
             Source = new ListWrapper<string> (_eventList)
             Source = new ListWrapper<string> (_eventList)
         };
         };
-        _eventListView.SchemeName = "TopLevel";
+        _eventListView.SchemeName = "Runnable";
         _appWindow.Add (_eventListView);
         _appWindow.Add (_eventListView);
 
 
         _listView.SelectedItemChanged += (s, a) => LogEvent (s as View, a, "SelectedItemChanged");
         _listView.SelectedItemChanged += (s, a) => LogEvent (s as View, a, "SelectedItemChanged");

+ 2 - 2
Examples/UICatalog/Scenarios/ListsAndCombos.cs

@@ -35,7 +35,7 @@ public class ListsAndCombos : Scenario
         // ListView
         // ListView
         var lbListView = new Label
         var lbListView = new Label
         {
         {
-            SchemeName = "TopLevel",
+            SchemeName = "Runnable",
             X = 0,
             X = 0,
 
 
             Width = Dim.Percent (40),
             Width = Dim.Percent (40),
@@ -91,7 +91,7 @@ public class ListsAndCombos : Scenario
         // ComboBox
         // ComboBox
         var lbComboBox = new Label
         var lbComboBox = new Label
         {
         {
-            SchemeName = "TopLevel",
+            SchemeName = "Runnable",
             X = Pos.Right (lbListView) + 1,
             X = Pos.Right (lbListView) + 1,
 
 
             Width = Dim.Percent (40),
             Width = Dim.Percent (40),

+ 1 - 1
Examples/UICatalog/Scenarios/Localization.cs

@@ -181,7 +181,7 @@ public class Localization : Scenario
         wizardButton.Accepting += (sender, e) => ShowWizard ();
         wizardButton.Accepting += (sender, e) => ShowWizard ();
         win.Add (wizardButton);
         win.Add (wizardButton);
 
 
-        win.Unloaded += (sender, e) => Quit ();
+        win.IsRunningChanged += (sender, e) => Quit ();
 
 
         win.Add (menu);
         win.Add (menu);
 
 

+ 7 - 7
Examples/UICatalog/Scenarios/Mazing.cs

@@ -9,7 +9,7 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("Games")]
 [ScenarioCategory ("Games")]
 public class Mazing : Scenario
 public class Mazing : Scenario
 {
 {
-    private Toplevel? _top;
+    private Window? _top;
     private MazeGenerator? _m;
     private MazeGenerator? _m;
 
 
     private List<Point>? _potions;
     private List<Point>? _potions;
@@ -33,17 +33,17 @@ public class Mazing : Scenario
         _top.KeyBindings.Add (Key.CursorDown, Command.Down);
         _top.KeyBindings.Add (Key.CursorDown, Command.Down);
 
 
         // Changing the key-bindings of a View is not allowed, however,
         // Changing the key-bindings of a View is not allowed, however,
-        // by default, Toplevel doesn't bind any of our movement keys, so
+        // by default, Runnable doesn't bind any of our movement keys, so
         // we can take advantage of the CommandNotBound event to handle them
         // we can take advantage of the CommandNotBound event to handle them
         // 
         // 
-        // An alternative implementation would be to create a TopLevel subclass that
+        // An alternative implementation would be to create a Runnable subclass that
         // calls AddCommand/KeyBindings.Add in the constructor. See the Snake game scenario
         // calls AddCommand/KeyBindings.Add in the constructor. See the Snake game scenario
         // for an example.
         // for an example.
         _top.CommandNotBound += TopCommandNotBound;
         _top.CommandNotBound += TopCommandNotBound;
 
 
         _top.DrawingContent += (s, _) =>
         _top.DrawingContent += (s, _) =>
                                {
                                {
-                                   if (s is not Toplevel top)
+                                   if (s is not Runnable top)
                                    {
                                    {
                                        return;
                                        return;
                                    }
                                    }
@@ -171,7 +171,7 @@ public class Mazing : Scenario
                 if (_m.PlayerHp <= 0)
                 if (_m.PlayerHp <= 0)
                 {
                 {
                     _message = "You died!";
                     _message = "You died!";
-                    Application.TopRunnable!.SetNeedsDraw (); // trigger redraw
+                    Application.TopRunnableView!.SetNeedsDraw (); // trigger redraw
                     _dead = true;
                     _dead = true;
 
 
                     return; // Stop further action if dead
                     return; // Stop further action if dead
@@ -190,7 +190,7 @@ public class Mazing : Scenario
                 _message = string.Empty;
                 _message = string.Empty;
             }
             }
 
 
-            Application.TopRunnable!.SetNeedsDraw (); // trigger redraw
+            Application.TopRunnableView!.SetNeedsDraw (); // trigger redraw
         }
         }
 
 
         // Optional win condition:
         // Optional win condition:
@@ -200,7 +200,7 @@ public class Mazing : Scenario
             _m = new (); // Generate a new maze
             _m = new (); // Generate a new maze
             _m.PlayerHp = hp;
             _m.PlayerHp = hp;
             GenerateNpcs ();
             GenerateNpcs ();
-            Application.TopRunnable!.SetNeedsDraw (); // trigger redraw
+            Application.TopRunnableView!.SetNeedsDraw (); // trigger redraw
         }
         }
     }
     }
 }
 }

+ 2 - 2
Examples/UICatalog/Scenarios/Menus.cs

@@ -21,7 +21,7 @@ public class Menus : Scenario
         Logging.Logger = CreateLogger ();
         Logging.Logger = CreateLogger ();
 
 
         Application.Init ();
         Application.Init ();
-        Toplevel app = new ();
+        Runnable app = new ();
         app.Title = GetQuitKeyAndName ();
         app.Title = GetQuitKeyAndName ();
 
 
         ObservableCollection<string> eventSource = new ();
         ObservableCollection<string> eventSource = new ();
@@ -32,7 +32,7 @@ public class Menus : Scenario
             X = Pos.AnchorEnd (),
             X = Pos.AnchorEnd (),
             Width = Dim.Auto (),
             Width = Dim.Auto (),
             Height = Dim.Fill (), // Make room for some wide things
             Height = Dim.Fill (), // Make room for some wide things
-            SchemeName = "TopLevel",
+            SchemeName = "Runnable",
             Source = new ListWrapper<string> (eventSource)
             Source = new ListWrapper<string> (eventSource)
         };
         };
         eventLog.Border!.Thickness = new (0, 1, 0, 0);
         eventLog.Border!.Thickness = new (0, 1, 0, 0);

+ 9 - 9
Examples/UICatalog/Scenarios/MessageBoxes.cs

@@ -251,7 +251,7 @@ public class MessageBoxes : Scenario
                                                {
                                                {
                                                    buttonPressedLabel.Text =
                                                    buttonPressedLabel.Text =
                                                        $"{MessageBox.Query (
                                                        $"{MessageBox.Query (
-                                                                             width,
+                                                                            ApplicationImpl.Instance, width,
                                                                              height,
                                                                              height,
                                                                              titleEdit.Text,
                                                                              titleEdit.Text,
                                                                              messageEdit.Text,
                                                                              messageEdit.Text,
@@ -263,14 +263,14 @@ public class MessageBoxes : Scenario
                                                else
                                                else
                                                {
                                                {
                                                    buttonPressedLabel.Text =
                                                    buttonPressedLabel.Text =
-                                                       $"{MessageBox.ErrorQuery (
-                                                                                  width,
-                                                                                  height,
-                                                                                  titleEdit.Text,
-                                                                                  messageEdit.Text,
-                                                                                  defaultButton,
-                                                                                  ckbWrapMessage.CheckedState == CheckState.Checked,
-                                                                                  btns.ToArray ()
+                                                       $"{MessageBox.ErrorQuery (ApplicationImpl.Instance,
+                                                                                 width,
+                                                                                 height,
+                                                                                 titleEdit.Text,
+                                                                                 messageEdit.Text,
+                                                                                 defaultButton,
+                                                                                 ckbWrapMessage.CheckedState == CheckState.Checked,
+                                                                                 btns.ToArray ()
                                                                                  )}";
                                                                                  )}";
                                                }
                                                }
                                            }
                                            }

+ 2 - 2
Examples/UICatalog/Scenarios/Mouse.cs

@@ -247,7 +247,7 @@ public class Mouse : Scenario
             Y = Pos.Bottom (label),
             Y = Pos.Bottom (label),
             Width = 50,
             Width = 50,
             Height = Dim.Fill (),
             Height = Dim.Fill (),
-            SchemeName = "TopLevel",
+            SchemeName = "Runnable",
             Source = new ListWrapper<string> (appLogList)
             Source = new ListWrapper<string> (appLogList)
         };
         };
         win.Add (label, appLog);
         win.Add (label, appLog);
@@ -278,7 +278,7 @@ public class Mouse : Scenario
             Y = Pos.Bottom (label),
             Y = Pos.Bottom (label),
             Width = Dim.Percent (50),
             Width = Dim.Percent (50),
             Height = Dim.Fill (),
             Height = Dim.Fill (),
-            SchemeName = "TopLevel",
+            SchemeName = "Runnable",
             Source = new ListWrapper<string> (winLogList)
             Source = new ListWrapper<string> (winLogList)
         };
         };
         win.Add (label, winLog);
         win.Add (label, winLog);

+ 1 - 1
Examples/UICatalog/Scenarios/MultiColouredTable.cs

@@ -99,7 +99,7 @@ public class MultiColouredTable : Scenario
             }
             }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
-                MessageBox.ErrorQuery (60, 20, "Failed to set text", ex.Message, "Ok");
+                MessageBox.ErrorQuery (ApplicationImpl.Instance, 60, 20, "Failed to set text", ex.Message, "Ok");
             }
             }
 
 
             _tableView.Update ();
             _tableView.Update ();

+ 4 - 4
Examples/UICatalog/Scenarios/Navigation.cs

@@ -59,7 +59,7 @@ public class Navigation : Scenario
             Y = 0,
             Y = 0,
             Title = $"TopButton _{GetNextHotKey ()}"
             Title = $"TopButton _{GetNextHotKey ()}"
         };
         };
-        button.Accepting += (sender, args) => MessageBox.Query ("hi", button.Title, "_Ok");
+        button.Accepting += (sender, args) => MessageBox.Query (ApplicationImpl.Instance, "hi", button.Title, "_Ok");
 
 
         testFrame.Add (button);
         testFrame.Add (button);
 
 
@@ -180,7 +180,7 @@ public class Navigation : Scenario
             X = 1,
             X = 1,
             Y = 7,
             Y = 7,
             Id = "datePicker",
             Id = "datePicker",
-            SchemeName = "TopLevel",
+            SchemeName = "Runnable",
             ShadowStyle = ShadowStyle.Transparent,
             ShadowStyle = ShadowStyle.Transparent,
             BorderStyle = LineStyle.Double,
             BorderStyle = LineStyle.Double,
             CanFocus = true, // Can't drag without this? BUGBUG
             CanFocus = true, // Can't drag without this? BUGBUG
@@ -210,7 +210,7 @@ public class Navigation : Scenario
 
 
         return;
         return;
 
 
-        void OnApplicationIteration (object sender, IterationEventArgs args)
+        void OnApplicationIteration (object sender, EventArgs<IApplication> args)
         {
         {
             if (progressBar.Fraction == 1.0)
             if (progressBar.Fraction == 1.0)
             {
             {
@@ -237,7 +237,7 @@ public class Navigation : Scenario
             Height = Dim.Auto (),
             Height = Dim.Auto (),
             Width = Dim.Auto (),
             Width = Dim.Auto (),
             Title = $"Overlapped{id} _{GetNextHotKey ()}",
             Title = $"Overlapped{id} _{GetNextHotKey ()}",
-            SchemeName = "TopLevel",
+            SchemeName = "Runnable",
             Id = $"Overlapped{id}",
             Id = $"Overlapped{id}",
             ShadowStyle = ShadowStyle.Transparent,
             ShadowStyle = ShadowStyle.Transparent,
             BorderStyle = LineStyle.Double,
             BorderStyle = LineStyle.Double,

+ 14 - 11
Examples/UICatalog/Scenarios/Notepad.cs

@@ -71,7 +71,7 @@ public class Notepad : Scenario
                                        new MenuItem
                                        new MenuItem
                                        {
                                        {
                                            Title = "_About",
                                            Title = "_About",
-                                           Action = () => MessageBox.Query ("Notepad", "About Notepad...", "Ok")
+                                           Action = () => MessageBox.Query (ApplicationImpl.Instance,  "Notepad", "About Notepad...", "Ok")
                                        }
                                        }
                                    ]
                                    ]
                                   )
                                   )
@@ -110,10 +110,13 @@ public class Notepad : Scenario
         _tabView.SelectedTabChanged += TabView_SelectedTabChanged;
         _tabView.SelectedTabChanged += TabView_SelectedTabChanged;
         _tabView.HasFocusChanging += (s, e) => _focusedTabView = _tabView;
         _tabView.HasFocusChanging += (s, e) => _focusedTabView = _tabView;
 
 
-        top.Ready += (s, e) =>
+        top.IsModalChanged += (s, e) =>
                      {
                      {
-                         New ();
-                         LenShortcut.Title = $"Len:{_focusedTabView?.Text?.Length ?? 0}";
+                         if (e.Value)
+                         {
+                             New ();
+                             LenShortcut.Title = $"Len:{_focusedTabView?.Text?.Length ?? 0}";
+                         }
                      };
                      };
 
 
         Application.Run (top);
         Application.Run (top);
@@ -193,15 +196,15 @@ public class Notepad : Scenario
 
 
         if (tab.UnsavedChanges)
         if (tab.UnsavedChanges)
         {
         {
-            int result = MessageBox.Query (
-                                           "Save Changes",
-                                           $"Save changes to {tab.Text.TrimEnd ('*')}",
-                                           "Yes",
-                                           "No",
-                                           "Cancel"
+            int? result = MessageBox.Query (ApplicationImpl.Instance,
+                                            "Save Changes",
+                                            $"Save changes to {tab.Text.TrimEnd ('*')}",
+                                            "Yes",
+                                            "No",
+                                            "Cancel"
                                           );
                                           );
 
 
-            if (result == -1 || result == 2)
+            if (result is null || result == 2)
             {
             {
                 // user cancelled
                 // user cancelled
                 return;
                 return;

+ 1 - 1
Examples/UICatalog/Scenarios/PosAlignDemo.cs

@@ -20,7 +20,7 @@ public sealed class PosAlignDemo : Scenario
             Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()} - {GetDescription ()}"
             Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()} - {GetDescription ()}"
         };
         };
 
 
-        SetupControls (appWindow, Dimension.Width, Schemes.Toplevel);
+        SetupControls (appWindow, Dimension.Width, Schemes.Runnable);
 
 
         SetupControls (appWindow, Dimension.Height, Schemes.Error);
         SetupControls (appWindow, Dimension.Height, Schemes.Error);
 
 

+ 14 - 10
Examples/UICatalog/Scenarios/ProgressBarStyles.cs

@@ -27,7 +27,7 @@ public class ProgressBarStyles : Scenario
     {
     {
         Application.Init ();
         Application.Init ();
 
 
-        Window app = new ()
+        Window win = new ()
         {
         {
             Title = GetQuitKeyAndName (), BorderStyle = LineStyle.Single,
             Title = GetQuitKeyAndName (), BorderStyle = LineStyle.Single,
         };
         };
@@ -38,7 +38,7 @@ public class ProgressBarStyles : Scenario
             ShowViewIdentifier = true
             ShowViewIdentifier = true
 
 
         };
         };
-        app.Add (editor);
+        win.Add (editor);
 
 
         View container = new ()
         View container = new ()
         {
         {
@@ -47,7 +47,7 @@ public class ProgressBarStyles : Scenario
             Width = Dim.Fill (),
             Width = Dim.Fill (),
             Height = Dim.Fill (),
             Height = Dim.Fill (),
         };
         };
-        app.Add (container);
+        win.Add (container);
 
 
         const float fractionStep = 0.01F;
         const float fractionStep = 0.01F;
 
 
@@ -278,8 +278,8 @@ public class ProgressBarStyles : Scenario
 
 
 
 
 
 
-        app.Initialized += App_Initialized;
-        app.Unloaded += App_Unloaded;
+        win.Initialized += Win_Initialized;
+        win.IsRunningChanged += Win_IsRunningChanged;
 
 
         _pulseTimer = new Timer (
         _pulseTimer = new Timer (
                                  _ =>
                                  _ =>
@@ -292,14 +292,18 @@ public class ProgressBarStyles : Scenario
                                  0,
                                  0,
                                  300
                                  300
                                 );
                                 );
-        Application.Run (app);
-        app.Dispose ();
+        Application.Run (win);
+        win.Dispose ();
         Application.Shutdown ();
         Application.Shutdown ();
 
 
         return;
         return;
 
 
-        void App_Unloaded (object sender, EventArgs args)
+        void Win_IsRunningChanged (object sender, EventArgs<bool> args)
         {
         {
+            if (args.Value)
+            {
+                return;
+            }
             if (_fractionTimer != null)
             if (_fractionTimer != null)
             {
             {
                 _fractionTimer.Dispose ();
                 _fractionTimer.Dispose ();
@@ -312,11 +316,11 @@ public class ProgressBarStyles : Scenario
                 _pulseTimer = null;
                 _pulseTimer = null;
             }
             }
 
 
-            app.Unloaded -= App_Unloaded;
+            win.IsRunningChanged -= Win_IsRunningChanged;
         }
         }
     }
     }
 
 
-    private void App_Initialized (object sender, EventArgs e)
+    private void Win_Initialized (object sender, EventArgs e)
     {
     {
         _pbList.SelectedItem = 0;
         _pbList.SelectedItem = 0;
     }
     }

+ 4 - 4
Examples/UICatalog/Scenarios/RunTExample.cs

@@ -8,7 +8,7 @@ public class RunTExample : Scenario
     public override void Main ()
     public override void Main ()
     {
     {
         // No need to call Init if Application.Run<T> is used
         // No need to call Init if Application.Run<T> is used
-        Application.Run<ExampleWindow> ().Dispose ();
+        Application.Run<ExampleWindow> ();
         Application.Shutdown ();
         Application.Shutdown ();
     }
     }
 
 
@@ -63,12 +63,12 @@ public class RunTExample : Scenario
                                {
                                {
                                    if (_usernameText.Text == "admin" && passwordText.Text == "password")
                                    if (_usernameText.Text == "admin" && passwordText.Text == "password")
                                    {
                                    {
-                                       MessageBox.Query ("Login Successful", $"Username: {_usernameText.Text}", "Ok");
-                                       Application.RequestStop ();
+                                       MessageBox.Query (App, "Login Successful", $"Username: {_usernameText.Text}", "Ok");
+                                       App?.RequestStop ();
                                    }
                                    }
                                    else
                                    else
                                    {
                                    {
-                                       MessageBox.ErrorQuery (
+                                       MessageBox.ErrorQuery (App,
                                                               "Error Logging In",
                                                               "Error Logging In",
                                                               "Incorrect username or password (hint: admin/password)",
                                                               "Incorrect username or password (hint: admin/password)",
                                                               "Ok"
                                                               "Ok"

+ 3 - 3
Examples/UICatalog/Scenarios/RuneWidthGreaterThanOne.cs

@@ -166,7 +166,7 @@ public class RuneWidthGreaterThanOne : Scenario
     {
     {
         if (_text is { })
         if (_text is { })
         {
         {
-            MessageBox.Query ("Say Hello 你", $"Hello {_text.Text}", "Ok");
+            MessageBox.Query (ApplicationImpl.Instance, "Say Hello 你", $"Hello {_text.Text}", "Ok");
         }
         }
     }
     }
 
 
@@ -197,7 +197,7 @@ public class RuneWidthGreaterThanOne : Scenario
     {
     {
         if (_text is { })
         if (_text is { })
         {
         {
-            MessageBox.Query ("Say Hello", $"Hello {_text.Text}", "Ok");
+            MessageBox.Query (ApplicationImpl.Instance, "Say Hello", $"Hello {_text.Text}", "Ok");
         }
         }
     }
     }
 
 
@@ -252,7 +252,7 @@ public class RuneWidthGreaterThanOne : Scenario
     {
     {
         if (_text is { })
         if (_text is { })
         {
         {
-            MessageBox.Query ("こんにちはと言う", $"こんにちは {_text.Text}", "Ok");
+            MessageBox.Query (ApplicationImpl.Instance, "こんにちはと言う", $"こんにちは {_text.Text}", "Ok");
         }
         }
     }
     }
 
 

+ 15 - 15
Examples/UICatalog/Scenarios/Scrolling.cs

@@ -16,13 +16,13 @@ public class Scrolling : Scenario
     {
     {
         Application.Init ();
         Application.Init ();
 
 
-        var app = new Window
+        var win = new Window
         {
         {
             Title = GetQuitKeyAndName ()
             Title = GetQuitKeyAndName ()
         };
         };
 
 
         var label = new Label { X = 0, Y = 0 };
         var label = new Label { X = 0, Y = 0 };
-        app.Add (label);
+        win.Add (label);
 
 
         var demoView = new AllViewsView
         var demoView = new AllViewsView
         {
         {
@@ -42,7 +42,7 @@ public class Scrolling : Scenario
                                             $"{demoView}\nContentSize: {demoView.GetContentSize ()}\nViewport.Location: {demoView.Viewport.Location}";
                                             $"{demoView}\nContentSize: {demoView.GetContentSize ()}\nViewport.Location: {demoView.Viewport.Location}";
                                     };
                                     };
 
 
-        app.Add (demoView);
+        win.Add (demoView);
 
 
         var hCheckBox = new CheckBox
         var hCheckBox = new CheckBox
         {
         {
@@ -51,7 +51,7 @@ public class Scrolling : Scenario
             Text = "_HorizontalScrollBar.Visible",
             Text = "_HorizontalScrollBar.Visible",
             CheckedState = demoView.HorizontalScrollBar.Visible ? CheckState.Checked : CheckState.UnChecked
             CheckedState = demoView.HorizontalScrollBar.Visible ? CheckState.Checked : CheckState.UnChecked
         };
         };
-        app.Add (hCheckBox);
+        win.Add (hCheckBox);
         hCheckBox.CheckedStateChanged += (sender, args) => { demoView.HorizontalScrollBar.Visible = args.Value == CheckState.Checked; };
         hCheckBox.CheckedStateChanged += (sender, args) => { demoView.HorizontalScrollBar.Visible = args.Value == CheckState.Checked; };
 
 
         var vCheckBox = new CheckBox
         var vCheckBox = new CheckBox
@@ -61,7 +61,7 @@ public class Scrolling : Scenario
             Text = "_VerticalScrollBar.Visible",
             Text = "_VerticalScrollBar.Visible",
             CheckedState = demoView.VerticalScrollBar.Visible ? CheckState.Checked : CheckState.UnChecked
             CheckedState = demoView.VerticalScrollBar.Visible ? CheckState.Checked : CheckState.UnChecked
         };
         };
-        app.Add (vCheckBox);
+        win.Add (vCheckBox);
         vCheckBox.CheckedStateChanged += (sender, args) => { demoView.VerticalScrollBar.Visible = args.Value == CheckState.Checked; };
         vCheckBox.CheckedStateChanged += (sender, args) => { demoView.VerticalScrollBar.Visible = args.Value == CheckState.Checked; };
 
 
         var ahCheckBox = new CheckBox
         var ahCheckBox = new CheckBox
@@ -77,7 +77,7 @@ public class Scrolling : Scenario
                                                demoView.HorizontalScrollBar.AutoShow = e.Result == CheckState.Checked;
                                                demoView.HorizontalScrollBar.AutoShow = e.Result == CheckState.Checked;
                                                demoView.VerticalScrollBar.AutoShow = e.Result == CheckState.Checked;
                                                demoView.VerticalScrollBar.AutoShow = e.Result == CheckState.Checked;
                                            };
                                            };
-        app.Add (ahCheckBox);
+        win.Add (ahCheckBox);
 
 
         demoView.VerticalScrollBar.VisibleChanging += (sender, args) => { vCheckBox.CheckedState = args.NewValue ? CheckState.Checked : CheckState.UnChecked; };
         demoView.VerticalScrollBar.VisibleChanging += (sender, args) => { vCheckBox.CheckedState = args.NewValue ? CheckState.Checked : CheckState.UnChecked; };
 
 
@@ -92,19 +92,19 @@ public class Scrolling : Scenario
             X = Pos.Center (), Y = Pos.AnchorEnd (), Width = Dim.Fill ()
             X = Pos.Center (), Y = Pos.AnchorEnd (), Width = Dim.Fill ()
         };
         };
 
 
-        app.Add (progress);
+        win.Add (progress);
 
 
-        app.Initialized += AppOnInitialized;
-        app.Unloaded += AppUnloaded;
+        win.Initialized += WinOnInitialized;
+        win.IsRunningChanged += WinIsRunningChanged;
 
 
-        Application.Run (app);
-        app.Unloaded -= AppUnloaded;
-        app.Dispose ();
+        Application.Run (win);
+        win.IsRunningChanged -= WinIsRunningChanged;
+        win.Dispose ();
         Application.Shutdown ();
         Application.Shutdown ();
 
 
         return;
         return;
 
 
-        void AppOnInitialized (object? sender, EventArgs e)
+        void WinOnInitialized (object? sender, EventArgs e)
         {
         {
             bool TimerFn ()
             bool TimerFn ()
             {
             {
@@ -116,9 +116,9 @@ public class Scrolling : Scenario
             _progressTimer = Application.AddTimeout (TimeSpan.FromMilliseconds (200), TimerFn);
             _progressTimer = Application.AddTimeout (TimeSpan.FromMilliseconds (200), TimerFn);
         }
         }
 
 
-        void AppUnloaded (object? sender, EventArgs args)
+        void WinIsRunningChanged (object? sender, EventArgs<bool> args)
         {
         {
-            if (_progressTimer is { })
+            if (!args.Value && _progressTimer is { })
             {
             {
                 Application.RemoveTimeout (_progressTimer);
                 Application.RemoveTimeout (_progressTimer);
                 _progressTimer = null;
                 _progressTimer = null;

+ 31 - 31
Examples/UICatalog/Scenarios/Shortcuts.cs

@@ -15,7 +15,7 @@ public class Shortcuts : Scenario
         var quitKey = Application.QuitKey;
         var quitKey = Application.QuitKey;
         Window app = new ();
         Window app = new ();
 
 
-        app.Loaded += App_Loaded;
+        app.IsModalChanged += App_Loaded;
 
 
         Application.Run (app);
         Application.Run (app);
         app.Dispose ();
         app.Dispose ();
@@ -28,7 +28,7 @@ public class Shortcuts : Scenario
     private void App_Loaded (object? sender, EventArgs e)
     private void App_Loaded (object? sender, EventArgs e)
     {
     {
         Application.QuitKey = Key.F4.WithCtrl;
         Application.QuitKey = Key.F4.WithCtrl;
-        Application.TopRunnable!.Title = GetQuitKeyAndName ();
+        Application.TopRunnableView!.Title = GetQuitKeyAndName ();
 
 
         ObservableCollection<string> eventSource = new ();
         ObservableCollection<string> eventSource = new ();
 
 
@@ -38,7 +38,7 @@ public class Shortcuts : Scenario
             X = Pos.AnchorEnd (),
             X = Pos.AnchorEnd (),
             Y = 0,
             Y = 0,
             Height = Dim.Fill (4),
             Height = Dim.Fill (4),
-            SchemeName = "TopLevel",
+            SchemeName = "Runnable",
             Source = new ListWrapper<string> (eventSource),
             Source = new ListWrapper<string> (eventSource),
             BorderStyle = LineStyle.Double,
             BorderStyle = LineStyle.Double,
             Title = "E_vents"
             Title = "E_vents"
@@ -46,14 +46,14 @@ public class Shortcuts : Scenario
 
 
         eventLog.Width = Dim.Func (
         eventLog.Width = Dim.Func (
                                    _ => Math.Min (
                                    _ => Math.Min (
-                                                  Application.TopRunnable.Viewport.Width / 2,
+                                                  Application.TopRunnableView.Viewport.Width / 2,
                                                   eventLog?.MaxLength + eventLog!.GetAdornmentsThickness ().Horizontal ?? 0));
                                                   eventLog?.MaxLength + eventLog!.GetAdornmentsThickness ().Horizontal ?? 0));
 
 
         eventLog.Width = Dim.Func (
         eventLog.Width = Dim.Func (
                                    _ => Math.Min (
                                    _ => Math.Min (
                                                   eventLog.SuperView!.Viewport.Width / 2,
                                                   eventLog.SuperView!.Viewport.Width / 2,
                                                   eventLog?.MaxLength + eventLog!.GetAdornmentsThickness ().Horizontal ?? 0));
                                                   eventLog?.MaxLength + eventLog!.GetAdornmentsThickness ().Horizontal ?? 0));
-        Application.TopRunnable.Add (eventLog);
+        Application.TopRunnableView.Add (eventLog);
 
 
         var alignKeysShortcut = new Shortcut
         var alignKeysShortcut = new Shortcut
         {
         {
@@ -86,7 +86,7 @@ public class Shortcuts : Scenario
                                                                           };
                                                                           };
 
 
 
 
-        Application.TopRunnable.Add (alignKeysShortcut);
+        Application.TopRunnableView.Add (alignKeysShortcut);
 
 
         var commandFirstShortcut = new Shortcut
         var commandFirstShortcut = new Shortcut
         {
         {
@@ -115,7 +115,7 @@ public class Shortcuts : Scenario
                                                                                                       $"{commandFirstShortcut.Id}.CommandView.CheckedStateChanging: {cb.Text}");
                                                                                                       $"{commandFirstShortcut.Id}.CommandView.CheckedStateChanging: {cb.Text}");
                                                                                      eventLog.MoveDown ();
                                                                                      eventLog.MoveDown ();
 
 
-                                                                                     IEnumerable<View> toAlign = Application.TopRunnable.SubViews.OfType<Shortcut> ();
+                                                                                     IEnumerable<View> toAlign = Application.TopRunnableView.SubViews.OfType<Shortcut> ();
                                                                                      IEnumerable<View> enumerable = toAlign as View [] ?? toAlign.ToArray ();
                                                                                      IEnumerable<View> enumerable = toAlign as View [] ?? toAlign.ToArray ();
 
 
                                                                                      foreach (View view in enumerable)
                                                                                      foreach (View view in enumerable)
@@ -134,7 +134,7 @@ public class Shortcuts : Scenario
                                                                                  }
                                                                                  }
                                                                              };
                                                                              };
 
 
-        Application.TopRunnable.Add (commandFirstShortcut);
+        Application.TopRunnableView.Add (commandFirstShortcut);
 
 
         var canFocusShortcut = new Shortcut
         var canFocusShortcut = new Shortcut
         {
         {
@@ -159,7 +159,7 @@ public class Shortcuts : Scenario
                                                                                  SetCanFocus (e.Result == CheckState.Checked);
                                                                                  SetCanFocus (e.Result == CheckState.Checked);
                                                                              }
                                                                              }
                                                                          };
                                                                          };
-        Application.TopRunnable.Add (canFocusShortcut);
+        Application.TopRunnableView.Add (canFocusShortcut);
 
 
         var appShortcut = new Shortcut
         var appShortcut = new Shortcut
         {
         {
@@ -173,7 +173,7 @@ public class Shortcuts : Scenario
             BindKeyToApplication = true
             BindKeyToApplication = true
         };
         };
 
 
-        Application.TopRunnable.Add (appShortcut);
+        Application.TopRunnableView.Add (appShortcut);
 
 
         var buttonShortcut = new Shortcut
         var buttonShortcut = new Shortcut
         {
         {
@@ -193,7 +193,7 @@ public class Shortcuts : Scenario
         var button = (Button)buttonShortcut.CommandView;
         var button = (Button)buttonShortcut.CommandView;
         buttonShortcut.Accepting += Button_Clicked;
         buttonShortcut.Accepting += Button_Clicked;
 
 
-        Application.TopRunnable.Add (buttonShortcut);
+        Application.TopRunnableView.Add (buttonShortcut);
 
 
         var optionSelectorShortcut = new Shortcut
         var optionSelectorShortcut = new Shortcut
         {
         {
@@ -221,7 +221,7 @@ public class Shortcuts : Scenario
                                                                                     }
                                                                                     }
                                                                                 };
                                                                                 };
 
 
-        Application.TopRunnable.Add (optionSelectorShortcut);
+        Application.TopRunnableView.Add (optionSelectorShortcut);
 
 
         var sliderShortcut = new Shortcut
         var sliderShortcut = new Shortcut
         {
         {
@@ -248,7 +248,7 @@ public class Shortcuts : Scenario
                                                                            eventLog.MoveDown ();
                                                                            eventLog.MoveDown ();
                                                                        };
                                                                        };
 
 
-        Application.TopRunnable.Add (sliderShortcut);
+        Application.TopRunnableView.Add (sliderShortcut);
 
 
         ListView listView = new ListView ()
         ListView listView = new ListView ()
         {
         {
@@ -270,7 +270,7 @@ public class Shortcuts : Scenario
             Key = Key.F5.WithCtrl,
             Key = Key.F5.WithCtrl,
         };
         };
 
 
-        Application.TopRunnable.Add (listViewShortcut);
+        Application.TopRunnableView.Add (listViewShortcut);
 
 
         var noCommandShortcut = new Shortcut
         var noCommandShortcut = new Shortcut
         {
         {
@@ -282,7 +282,7 @@ public class Shortcuts : Scenario
             Key = Key.D0
             Key = Key.D0
         };
         };
 
 
-        Application.TopRunnable.Add (noCommandShortcut);
+        Application.TopRunnableView.Add (noCommandShortcut);
 
 
         var noKeyShortcut = new Shortcut
         var noKeyShortcut = new Shortcut
         {
         {
@@ -295,7 +295,7 @@ public class Shortcuts : Scenario
             HelpText = "Keyless"
             HelpText = "Keyless"
         };
         };
 
 
-        Application.TopRunnable.Add (noKeyShortcut);
+        Application.TopRunnableView.Add (noKeyShortcut);
 
 
         var noHelpShortcut = new Shortcut
         var noHelpShortcut = new Shortcut
         {
         {
@@ -308,7 +308,7 @@ public class Shortcuts : Scenario
             HelpText = ""
             HelpText = ""
         };
         };
 
 
-        Application.TopRunnable.Add (noHelpShortcut);
+        Application.TopRunnableView.Add (noHelpShortcut);
         noHelpShortcut.SetFocus ();
         noHelpShortcut.SetFocus ();
 
 
         var framedShortcut = new Shortcut
         var framedShortcut = new Shortcut
@@ -339,8 +339,8 @@ public class Shortcuts : Scenario
             framedShortcut.KeyView.SchemeName = framedShortcut.KeyView.SchemeName = SchemeManager.SchemesToSchemeName (Schemes.Base);
             framedShortcut.KeyView.SchemeName = framedShortcut.KeyView.SchemeName = SchemeManager.SchemesToSchemeName (Schemes.Base);
         }
         }
 
 
-        framedShortcut.SchemeName = SchemeManager.SchemesToSchemeName (Schemes.Toplevel);
-        Application.TopRunnable.Add (framedShortcut);
+        framedShortcut.SchemeName = SchemeManager.SchemesToSchemeName (Schemes.Runnable);
+        Application.TopRunnableView.Add (framedShortcut);
 
 
         // Horizontal
         // Horizontal
         var progressShortcut = new Shortcut
         var progressShortcut = new Shortcut
@@ -387,7 +387,7 @@ public class Shortcuts : Scenario
                          };
                          };
         timer.Start ();
         timer.Start ();
 
 
-        Application.TopRunnable.Add (progressShortcut);
+        Application.TopRunnableView.Add (progressShortcut);
 
 
         var textField = new TextField
         var textField = new TextField
         {
         {
@@ -408,7 +408,7 @@ public class Shortcuts : Scenario
         };
         };
         textField.CanFocus = true;
         textField.CanFocus = true;
 
 
-        Application.TopRunnable.Add (textFieldShortcut);
+        Application.TopRunnableView.Add (textFieldShortcut);
 
 
         var bgColorShortcut = new Shortcut
         var bgColorShortcut = new Shortcut
         {
         {
@@ -450,19 +450,19 @@ public class Shortcuts : Scenario
                                         eventSource.Add ($"ColorChanged: {o.GetType ().Name} - {args.Result}");
                                         eventSource.Add ($"ColorChanged: {o.GetType ().Name} - {args.Result}");
                                         eventLog.MoveDown ();
                                         eventLog.MoveDown ();
 
 
-                                        Application.TopRunnable.SetScheme (
-                                                                   new (Application.TopRunnable.GetScheme ())
+                                        Application.TopRunnableView.SetScheme (
+                                                                   new (Application.TopRunnableView.GetScheme ())
                                                                    {
                                                                    {
                                                                        Normal = new (
                                                                        Normal = new (
-                                                                                     Application.TopRunnable!.GetAttributeForRole (VisualRole.Normal).Foreground,
+                                                                                     Application.TopRunnableView!.GetAttributeForRole (VisualRole.Normal).Foreground,
                                                                                      args.Result,
                                                                                      args.Result,
-                                                                                     Application.TopRunnable!.GetAttributeForRole (VisualRole.Normal).Style)
+                                                                                     Application.TopRunnableView!.GetAttributeForRole (VisualRole.Normal).Style)
                                                                    });
                                                                    });
                                     }
                                     }
                                 };
                                 };
         bgColorShortcut.CommandView = bgColor;
         bgColorShortcut.CommandView = bgColor;
 
 
-        Application.TopRunnable.Add (bgColorShortcut);
+        Application.TopRunnableView.Add (bgColorShortcut);
 
 
         var appQuitShortcut = new Shortcut
         var appQuitShortcut = new Shortcut
         {
         {
@@ -476,9 +476,9 @@ public class Shortcuts : Scenario
         };
         };
         appQuitShortcut.Accepting += (o, args) => { Application.RequestStop (); };
         appQuitShortcut.Accepting += (o, args) => { Application.RequestStop (); };
 
 
-        Application.TopRunnable.Add (appQuitShortcut);
+        Application.TopRunnableView.Add (appQuitShortcut);
 
 
-        foreach (Shortcut shortcut in Application.TopRunnable.SubViews.OfType<Shortcut> ())
+        foreach (Shortcut shortcut in Application.TopRunnableView.SubViews.OfType<Shortcut> ())
         {
         {
             shortcut.Selecting += (o, args) =>
             shortcut.Selecting += (o, args) =>
                                   {
                                   {
@@ -529,7 +529,7 @@ public class Shortcuts : Scenario
 
 
         void SetCanFocus (bool canFocus)
         void SetCanFocus (bool canFocus)
         {
         {
-            foreach (Shortcut peer in Application.TopRunnable!.SubViews.OfType<Shortcut> ())
+            foreach (Shortcut peer in Application.TopRunnableView!.SubViews.OfType<Shortcut> ())
             {
             {
                 if (peer.CanFocus)
                 if (peer.CanFocus)
                 {
                 {
@@ -542,7 +542,7 @@ public class Shortcuts : Scenario
         {
         {
             var max = 0;
             var max = 0;
 
 
-            IEnumerable<Shortcut> toAlign = Application.TopRunnable!.SubViews.OfType<Shortcut> ().Where(s => !s.Y.Has<PosAnchorEnd>(out _)).Cast<Shortcut>();
+            IEnumerable<Shortcut> toAlign = Application.TopRunnableView!.SubViews.OfType<Shortcut> ().Where(s => !s.Y.Has<PosAnchorEnd>(out _)).Cast<Shortcut>();
             IEnumerable<Shortcut> enumerable = toAlign as Shortcut [] ?? toAlign.ToArray ();
             IEnumerable<Shortcut> enumerable = toAlign as Shortcut [] ?? toAlign.ToArray ();
 
 
             if (align)
             if (align)
@@ -566,6 +566,6 @@ public class Shortcuts : Scenario
     {
     {
         e.Handled = true;
         e.Handled = true;
         var view = sender as View;
         var view = sender as View;
-        MessageBox.Query ("Hi", $"You clicked {view?.Text}", "_Ok");
+        MessageBox.Query ((sender as View)?.App, "Hi", $"You clicked {view?.Text}", "_Ok");
     }
     }
 }
 }

+ 8 - 9
Examples/UICatalog/Scenarios/SingleBackgroundWorker.cs

@@ -5,7 +5,7 @@ using System.ComponentModel;
 
 
 namespace UICatalog.Scenarios;
 namespace UICatalog.Scenarios;
 
 
-[ScenarioMetadata ("Single BackgroundWorker", "A single BackgroundWorker threading opening another Toplevel")]
+[ScenarioMetadata ("Single BackgroundWorker", "A single BackgroundWorker threading opening another Runnable")]
 [ScenarioCategory ("Threading")]
 [ScenarioCategory ("Threading")]
 [ScenarioCategory ("Arrangement")]
 [ScenarioCategory ("Arrangement")]
 [ScenarioCategory ("Runnable")]
 [ScenarioCategory ("Runnable")]
@@ -13,7 +13,7 @@ public class SingleBackgroundWorker : Scenario
 {
 {
     public override void Main ()
     public override void Main ()
     {
     {
-        Application.Run<MainApp> ().Dispose ();
+        Application.Run<MainApp> ();
         Application.Shutdown ();
         Application.Shutdown ();
     }
     }
 
 
@@ -174,7 +174,7 @@ public class SingleBackgroundWorker : Scenario
 
 
                                                   StagingUIController builderUI =
                                                   StagingUIController builderUI =
                                                       new (_startStaging, e.Result as ObservableCollection<string>);
                                                       new (_startStaging, e.Result as ObservableCollection<string>);
-                                                  Toplevel? top = Application.TopRunnable;
+                                                  View? top = Application.TopRunnableView;
 
 
                                                   if (top is { })
                                                   if (top is { })
                                                   {
                                                   {
@@ -200,7 +200,7 @@ public class SingleBackgroundWorker : Scenario
 
 
     public class StagingUIController : Window
     public class StagingUIController : Window
     {
     {
-        private Toplevel? _top;
+        private Runnable? _top;
 
 
         public StagingUIController (DateTime? start, ObservableCollection<string>? list)
         public StagingUIController (DateTime? start, ObservableCollection<string>? list)
         {
         {
@@ -209,7 +209,6 @@ public class SingleBackgroundWorker : Scenario
                 Title = "_top",
                 Title = "_top",
                 Width = Dim.Fill (),
                 Width = Dim.Fill (),
                 Height = Dim.Fill (),
                 Height = Dim.Fill (),
-                Modal = true
             };
             };
 
 
             _top.KeyDown += (s, e) =>
             _top.KeyDown += (s, e) =>
@@ -224,7 +223,7 @@ public class SingleBackgroundWorker : Scenario
 
 
             bool Close ()
             bool Close ()
             {
             {
-                int n = MessageBox.Query (
+                int? n = MessageBox.Query (App,
                                           50,
                                           50,
                                           7,
                                           7,
                                           "Close Window.",
                                           "Close Window.",
@@ -251,7 +250,7 @@ public class SingleBackgroundWorker : Scenario
                                                         {
                                                         {
                                                             if (Close ())
                                                             if (Close ())
                                                             {
                                                             {
-                                                                Application.RequestStop ();
+                                                                App?.RequestStop ();
                                                             }
                                                             }
                                                         }
                                                         }
                                            }
                                            }
@@ -270,7 +269,7 @@ public class SingleBackgroundWorker : Scenario
                                                 {
                                                 {
                                                     if (Close ())
                                                     if (Close ())
                                                     {
                                                     {
-                                                        Application.RequestStop ();
+                                                        App?.RequestStop ();
                                                     }
                                                     }
                                                 }
                                                 }
                                                )
                                                )
@@ -304,7 +303,7 @@ public class SingleBackgroundWorker : Scenario
         {
         {
             if (_top is { })
             if (_top is { })
             {
             {
-                Application.Run (_top);
+                App?.Run (_top);
                 _top.Dispose ();
                 _top.Dispose ();
                 _top = null;
                 _top = null;
             }
             }

+ 1 - 1
Examples/UICatalog/Scenarios/Sliders.cs

@@ -590,7 +590,7 @@ public class Sliders : Scenario
             Y = Pos.Bottom (spacingOptions),
             Y = Pos.Bottom (spacingOptions),
             Width = Dim.Fill (),
             Width = Dim.Fill (),
             Height = Dim.Fill (),
             Height = Dim.Fill (),
-            SchemeName = "TopLevel",
+            SchemeName = "Runnable",
             Source = new ListWrapper<string> (eventSource)
             Source = new ListWrapper<string> (eventSource)
         };
         };
         configView.Add (eventLog);
         configView.Add (eventLog);

+ 17 - 17
Examples/UICatalog/Scenarios/SpinnerStyles.cs

@@ -14,7 +14,7 @@ public class SpinnerViewStyles : Scenario
     {
     {
         Application.Init ();
         Application.Init ();
 
 
-        Window app = new ()
+        Window win = new ()
         {
         {
             Title = GetQuitKeyAndName ()
             Title = GetQuitKeyAndName ()
         };
         };
@@ -40,7 +40,7 @@ public class SpinnerViewStyles : Scenario
             //Title = "Preview",
             //Title = "Preview",
             BorderStyle = LineStyle.Single
             BorderStyle = LineStyle.Single
         };
         };
-        app.Add (preview);
+        win.Add (preview);
 
 
         var spinner = new SpinnerView { X = Pos.Center (), Y = 0 };
         var spinner = new SpinnerView { X = Pos.Center (), Y = 0 };
         preview.Add (spinner);
         preview.Add (spinner);
@@ -54,7 +54,7 @@ public class SpinnerViewStyles : Scenario
             CheckedState = CheckState.Checked,
             CheckedState = CheckState.Checked,
             Text = "Ascii Only"
             Text = "Ascii Only"
         };
         };
-        app.Add (ckbAscii);
+        win.Add (ckbAscii);
 
 
         var ckbNoSpecial = new CheckBox
         var ckbNoSpecial = new CheckBox
         {
         {
@@ -64,28 +64,28 @@ public class SpinnerViewStyles : Scenario
             CheckedState = CheckState.Checked,
             CheckedState = CheckState.Checked,
             Text = "No Special"
             Text = "No Special"
         };
         };
-        app.Add (ckbNoSpecial);
+        win.Add (ckbNoSpecial);
 
 
         var ckbReverse = new CheckBox
         var ckbReverse = new CheckBox
         {
         {
             X = Pos.Center () - 22, Y = Pos.Bottom (preview) + 1, CheckedState = CheckState.UnChecked, Text = "Reverse"
             X = Pos.Center () - 22, Y = Pos.Bottom (preview) + 1, CheckedState = CheckState.UnChecked, Text = "Reverse"
         };
         };
-        app.Add (ckbReverse);
+        win.Add (ckbReverse);
 
 
         var ckbBounce = new CheckBox
         var ckbBounce = new CheckBox
         {
         {
             X = Pos.Right (ckbReverse) + 2, Y = Pos.Bottom (preview) + 1, CheckedState = CheckState.UnChecked, Text = "Bounce"
             X = Pos.Right (ckbReverse) + 2, Y = Pos.Bottom (preview) + 1, CheckedState = CheckState.UnChecked, Text = "Bounce"
         };
         };
-        app.Add (ckbBounce);
+        win.Add (ckbBounce);
 
 
         var delayLabel = new Label { X = Pos.Right (ckbBounce) + 2, Y = Pos.Bottom (preview) + 1, Text = "Delay:" };
         var delayLabel = new Label { X = Pos.Right (ckbBounce) + 2, Y = Pos.Bottom (preview) + 1, Text = "Delay:" };
-        app.Add (delayLabel);
+        win.Add (delayLabel);
 
 
         var delayField = new TextField
         var delayField = new TextField
         {
         {
             X = Pos.Right (delayLabel), Y = Pos.Bottom (preview) + 1, Width = 5, Text = DEFAULT_DELAY.ToString ()
             X = Pos.Right (delayLabel), Y = Pos.Bottom (preview) + 1, Width = 5, Text = DEFAULT_DELAY.ToString ()
         };
         };
-        app.Add (delayField);
+        win.Add (delayField);
 
 
         delayField.TextChanged += (s, e) =>
         delayField.TextChanged += (s, e) =>
                                   {
                                   {
@@ -96,13 +96,13 @@ public class SpinnerViewStyles : Scenario
                                   };
                                   };
 
 
         var customLabel = new Label { X = Pos.Right (delayField) + 2, Y = Pos.Bottom (preview) + 1, Text = "Custom:" };
         var customLabel = new Label { X = Pos.Right (delayField) + 2, Y = Pos.Bottom (preview) + 1, Text = "Custom:" };
-        app.Add (customLabel);
+        win.Add (customLabel);
 
 
         var customField = new TextField
         var customField = new TextField
         {
         {
             X = Pos.Right (customLabel), Y = Pos.Bottom (preview) + 1, Width = 12, Text = DEFAULT_CUSTOM
             X = Pos.Right (customLabel), Y = Pos.Bottom (preview) + 1, Width = 12, Text = DEFAULT_CUSTOM
         };
         };
-        app.Add (customField);
+        win.Add (customField);
 
 
         string [] styleArray = styleDict.Select (e => e.Value.Key).ToArray ();
         string [] styleArray = styleDict.Select (e => e.Value.Key).ToArray ();
 
 
@@ -117,7 +117,7 @@ public class SpinnerViewStyles : Scenario
         };
         };
         styles.SetSource (new ObservableCollection<string> (styleArray));
         styles.SetSource (new ObservableCollection<string> (styleArray));
         styles.SelectedItem = 0; // SpinnerStyle.Custom;
         styles.SelectedItem = 0; // SpinnerStyle.Custom;
-        app.Add (styles);
+        win.Add (styles);
         SetCustom ();
         SetCustom ();
 
 
         customField.TextChanged += (s, e) =>
         customField.TextChanged += (s, e) =>
@@ -166,7 +166,7 @@ public class SpinnerViewStyles : Scenario
 
 
         ckbBounce.CheckedStateChanging += (s, e) => { spinner.SpinBounce = e.Result == CheckState.Checked; };
         ckbBounce.CheckedStateChanging += (s, e) => { spinner.SpinBounce = e.Result == CheckState.Checked; };
 
 
-        app.Unloaded += App_Unloaded;
+        win.IsRunningChanged += WinIsRunningChanged;
 
 
         void SetCustom ()
         void SetCustom ()
         {
         {
@@ -199,23 +199,23 @@ public class SpinnerViewStyles : Scenario
             }
             }
         }
         }
 
 
-        void App_Unloaded (object sender, EventArgs args)
+        void WinIsRunningChanged (object sender, EventArgs<bool> args)
         {
         {
-            if (spinner is {})
+            if (!args.Value && spinner is {})
             {
             {
                 spinner.Dispose ();
                 spinner.Dispose ();
                 spinner = null;
                 spinner = null;
             }
             }
         }
         }
 
 
-        Application.Run (app);
-        app.Unloaded -= App_Unloaded;
+        Application.Run (win);
+        win.IsRunningChanged -= WinIsRunningChanged;
         if (spinner is { })
         if (spinner is { })
         {
         {
             spinner.Dispose ();
             spinner.Dispose ();
             spinner = null;
             spinner = null;
         }
         }
-        app.Dispose ();
+        win.Dispose ();
 
 
         Application.Shutdown ();
         Application.Shutdown ();
     }
     }

+ 1 - 1
Examples/UICatalog/Scenarios/SyntaxHighlighting.cs

@@ -120,7 +120,7 @@ public class SyntaxHighlighting : Scenario
         Application.Init ();
         Application.Init ();
 
 
         // Setup - Create a top-level application window and configure it.
         // Setup - Create a top-level application window and configure it.
-        Toplevel appWindow = new ();
+        Runnable appWindow = new ();
 
 
         var menu = new MenuBar ();
         var menu = new MenuBar ();
 
 

+ 8 - 8
Examples/UICatalog/Scenarios/TableEditor.cs

@@ -499,7 +499,7 @@ public class TableEditor : Scenario
         Application.Init ();
         Application.Init ();
 
 
         // Setup - Create a top-level application window and configure it.
         // Setup - Create a top-level application window and configure it.
-        Toplevel appWindow = new ();
+        Runnable appWindow = new ();
 
 
         _tableView = new () { X = 0, Y = 1, Width = Dim.Fill (), Height = Dim.Fill (1) };
         _tableView = new () { X = 0, Y = 1, Width = Dim.Fill (), Height = Dim.Fill (1) };
 
 
@@ -1026,7 +1026,7 @@ public class TableEditor : Scenario
             }
             }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
-                MessageBox.ErrorQuery (60, 20, "Failed to set text", ex.Message, "Ok");
+                MessageBox.ErrorQuery ((sender as View)?.App, 60, 20, "Failed to set text", ex.Message, "Ok");
             }
             }
 
 
             _tableView!.Update ();
             _tableView!.Update ();
@@ -1165,7 +1165,7 @@ public class TableEditor : Scenario
         }
         }
         catch (Exception e)
         catch (Exception e)
         {
         {
-            MessageBox.ErrorQuery ("Could not find local drives", e.Message, "Ok");
+            MessageBox.ErrorQuery (_tableView?.App, "Could not find local drives", e.Message, "Ok");
         }
         }
 
 
         _tableView!.Table = source;
         _tableView!.Table = source;
@@ -1199,10 +1199,10 @@ public class TableEditor : Scenario
         ok.Accepting += (s, e) =>
         ok.Accepting += (s, e) =>
                         {
                         {
                             accepted = true;
                             accepted = true;
-                            Application.RequestStop ();
+                            (s as View)?.App?.RequestStop ();
                         };
                         };
         var cancel = new Button { Text = "Cancel" };
         var cancel = new Button { Text = "Cancel" };
-        cancel.Accepting += (s, e) => { Application.RequestStop (); };
+        cancel.Accepting += (s, e) => { (s as View)?.App?.RequestStop (); };
 
 
         var d = new Dialog
         var d = new Dialog
         {
         {
@@ -1218,7 +1218,7 @@ public class TableEditor : Scenario
         d.Add (lbl, tf);
         d.Add (lbl, tf);
         tf.SetFocus ();
         tf.SetFocus ();
 
 
-        Application.Run (d);
+        _tableView.App?.Run (d);
         d.Dispose ();
         d.Dispose ();
 
 
         if (accepted)
         if (accepted)
@@ -1229,7 +1229,7 @@ public class TableEditor : Scenario
             }
             }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
-                MessageBox.ErrorQuery (60, 20, "Failed to set", ex.Message, "Ok");
+                MessageBox.ErrorQuery (_tableView.App, 60, 20, "Failed to set", ex.Message, "Ok");
             }
             }
 
 
             _tableView!.Update ();
             _tableView!.Update ();
@@ -1512,7 +1512,7 @@ public class TableEditor : Scenario
                                                                              _checkedFileSystemInfos!.Contains,
                                                                              _checkedFileSystemInfos!.Contains,
                                                                              CheckOrUncheckFile
                                                                              CheckOrUncheckFile
                                                                             )
                                                                             )
-                { UseRadioButtons = radio };
+            { UseRadioButtons = radio };
         }
         }
         else
         else
         {
         {

+ 3 - 6
Examples/UICatalog/Scenarios/TextEffectsScenario.cs

@@ -23,14 +23,11 @@ public class TextEffectsScenario : Scenario
             Title = "Text Effects Scenario"
             Title = "Text Effects Scenario"
         };
         };
 
 
-        w.Loaded += (s, e) => { SetupGradientLineCanvas (w, w.Frame.Size); };
+        w.IsModalChanged += (s, e) => { SetupGradientLineCanvas (w, w.Frame.Size); };
 
 
-        w.SizeChanging += (s, e) =>
+        w.ViewportChanged += (s, e) =>
                           {
                           {
-                              if (e.Size.HasValue)
-                              {
-                                  SetupGradientLineCanvas (w, e.Size.Value);
-                              }
+                              SetupGradientLineCanvas (w, e.NewViewport.Size);
                           };
                           };
 
 
         w.SetScheme (new ()
         w.SetScheme (new ()

+ 1 - 1
Examples/UICatalog/Scenarios/TextFormatterDemo.cs

@@ -30,7 +30,7 @@ public class TextFormatterDemo : Scenario
 
 
         var blockText = new Label
         var blockText = new Label
         {
         {
-            SchemeName = "TopLevel",
+            SchemeName = "Runnable",
             X = 0,
             X = 0,
             Y = 0,
             Y = 0,
 
 

+ 1 - 1
Examples/UICatalog/Scenarios/TextStyles.cs

@@ -5,7 +5,7 @@ namespace UICatalog.Scenarios;
 [ScenarioMetadata ("Text Styles", "Shows Attribute.TextStyles including bold, italic, etc...")]
 [ScenarioMetadata ("Text Styles", "Shows Attribute.TextStyles including bold, italic, etc...")]
 [ScenarioCategory ("Text and Formatting")]
 [ScenarioCategory ("Text and Formatting")]
 [ScenarioCategory ("Colors")]
 [ScenarioCategory ("Colors")]
-public sealed class TestStyles : Scenario
+public sealed class TextStyles : Scenario
 {
 {
     private CheckBox? _drawDirectly;
     private CheckBox? _drawDirectly;
 
 

+ 1 - 1
Examples/UICatalog/Scenarios/Themes.cs

@@ -129,7 +129,7 @@ public sealed class Themes : Scenario
                                           {
                                           {
                                               if (_view is { })
                                               if (_view is { })
                                               {
                                               {
-                                                  Application.TopRunnable!.SchemeName = args.NewValue;
+                                                  Application.TopRunnableView!.SchemeName = args.NewValue;
 
 
                                                   if (_view.HasScheme)
                                                   if (_view.HasScheme)
                                                   {
                                                   {

+ 4 - 4
Examples/UICatalog/Scenarios/Threading.cs

@@ -75,7 +75,7 @@ public class Threading : Scenario
             Y = Pos.Y (_btnActionCancel) + 6,
             Y = Pos.Y (_btnActionCancel) + 6,
             Width = 10,
             Width = 10,
             Height = 10,
             Height = 10,
-            SchemeName = "TopLevel"
+            SchemeName = "Runnable"
         };
         };
 
 
         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:" });
@@ -86,7 +86,7 @@ public class Threading : Scenario
             Y = Pos.Y (_itemsList),
             Y = Pos.Y (_itemsList),
             Width = 50,
             Width = 50,
             Height = Dim.Fill (),
             Height = Dim.Fill (),
-            SchemeName = "TopLevel",
+            SchemeName = "Runnable",
             Source = new ListWrapper<string> (_log)
             Source = new ListWrapper<string> (_log)
         };
         };
 
 
@@ -162,10 +162,10 @@ public class Threading : Scenario
         void Win_Loaded (object sender, EventArgs args)
         void Win_Loaded (object sender, EventArgs args)
         {
         {
             _btnActionCancel.SetFocus ();
             _btnActionCancel.SetFocus ();
-            win.Loaded -= Win_Loaded;
+            win.IsModalChanged -= Win_Loaded;
         }
         }
 
 
-        win.Loaded += Win_Loaded;
+        win.IsModalChanged += Win_Loaded;
 
 
         Application.Run (win);
         Application.Run (win);
         win.Dispose ();
         win.Dispose ();

+ 2 - 2
Examples/UICatalog/Scenarios/Transparent.cs

@@ -46,7 +46,7 @@ public sealed class Transparent : Scenario
         };
         };
         appButton.Accepting += (sender, args) =>
         appButton.Accepting += (sender, args) =>
                                {
                                {
-                                   MessageBox.Query ("AppButton", "Transparency is cool!", "_Ok");
+                                   MessageBox.Query ((sender as View)?.App, "AppButton", "Transparency is cool!", "_Ok");
                                    args.Handled = true;
                                    args.Handled = true;
                                };
                                };
         appWindow.Add (appButton);
         appWindow.Add (appButton);
@@ -106,7 +106,7 @@ public sealed class Transparent : Scenario
             };
             };
             button.Accepting += (sender, args) =>
             button.Accepting += (sender, args) =>
                                 {
                                 {
-                                    MessageBox.Query ("Clicked!", "Button in Transparent View", "_Ok");
+                                    MessageBox.Query (App, "Clicked!", "Button in Transparent View", "_Ok");
                                     args.Handled = true;
                                     args.Handled = true;
                                 };
                                 };
             //button.Visible = false;
             //button.Visible = false;

+ 18 - 15
Examples/UICatalog/Scenarios/TreeUseCases.cs

@@ -71,10 +71,13 @@ public class TreeUseCases : Scenario
 
 
         appWindow.Add (menu, statusBar);
         appWindow.Add (menu, statusBar);
 
 
-        appWindow.Ready += (sender, args) =>
+        appWindow.IsModalChanged += (sender, args) =>
         {
         {
-            // Start with the most basic use case
-            LoadSimpleNodes ();
+            if (args.Value)
+            {
+                // Start with the most basic use case
+                LoadSimpleNodes ();
+            }
         };
         };
 
 
         Application.Run (appWindow);
         Application.Run (appWindow);
@@ -92,9 +95,9 @@ public class TreeUseCases : Scenario
 
 
         if (_currentTree is { })
         if (_currentTree is { })
         {
         {
-            if (Application.TopRunnable is { })
+            if (Application.TopRunnableView is { })
             {
             {
-                Application.TopRunnable.Remove (_currentTree);
+                Application.TopRunnableView.Remove (_currentTree);
             }
             }
 
 
             _currentTree.Dispose ();
             _currentTree.Dispose ();
@@ -116,9 +119,9 @@ public class TreeUseCases : Scenario
             tree.TreeBuilder = new GameObjectTreeBuilder ();
             tree.TreeBuilder = new GameObjectTreeBuilder ();
         }
         }
 
 
-        if (Application.TopRunnable is { })
+        if (Application.TopRunnableView is { })
         {
         {
-            Application.TopRunnable.Add (tree);
+            Application.TopRunnableView.Add (tree);
         }
         }
 
 
         tree.AddObject (army1);
         tree.AddObject (army1);
@@ -141,9 +144,9 @@ public class TreeUseCases : Scenario
 
 
         if (_currentTree is { })
         if (_currentTree is { })
         {
         {
-            if (Application.TopRunnable is { })
+            if (Application.TopRunnableView is { })
             {
             {
-                Application.TopRunnable.Remove (_currentTree);
+                Application.TopRunnableView.Remove (_currentTree);
             }
             }
 
 
             _currentTree.Dispose ();
             _currentTree.Dispose ();
@@ -151,9 +154,9 @@ public class TreeUseCases : Scenario
 
 
         TreeView tree = new () { X = 0, Y = 1, Width = Dim.Fill (), Height = Dim.Fill (1) };
         TreeView tree = new () { X = 0, Y = 1, Width = Dim.Fill (), Height = Dim.Fill (1) };
 
 
-        if (Application.TopRunnable is { })
+        if (Application.TopRunnableView is { })
         {
         {
-            Application.TopRunnable.Add (tree);
+            Application.TopRunnableView.Add (tree);
         }
         }
 
 
         tree.AddObject (myHouse);
         tree.AddObject (myHouse);
@@ -165,9 +168,9 @@ public class TreeUseCases : Scenario
     {
     {
         if (_currentTree is { })
         if (_currentTree is { })
         {
         {
-            if (Application.TopRunnable is { })
+            if (Application.TopRunnableView is { })
             {
             {
-                Application.TopRunnable.Remove (_currentTree);
+                Application.TopRunnableView.Remove (_currentTree);
             }
             }
 
 
             _currentTree.Dispose ();
             _currentTree.Dispose ();
@@ -175,9 +178,9 @@ public class TreeUseCases : Scenario
 
 
         TreeView tree = new () { X = 0, Y = 1, Width = Dim.Fill (), Height = Dim.Fill (1) };
         TreeView tree = new () { X = 0, Y = 1, Width = Dim.Fill (), Height = Dim.Fill (1) };
 
 
-        if (Application.TopRunnable is { })
+        if (Application.TopRunnableView is { })
         {
         {
-            Application.TopRunnable.Add (tree);
+            Application.TopRunnableView.Add (tree);
         }
         }
 
 
         TreeNode root1 = new ("Root1");
         TreeNode root1 = new ("Root1");

+ 3 - 3
Examples/UICatalog/Scenarios/ViewportSettings.cs

@@ -102,7 +102,7 @@ public class ViewportSettings : Scenario
             Title = GetQuitKeyAndName (),
             Title = GetQuitKeyAndName (),
 
 
             // Use a different colorscheme so ViewSettings.ClearContentOnly is obvious
             // Use a different colorscheme so ViewSettings.ClearContentOnly is obvious
-            SchemeName = "Toplevel",
+            SchemeName = "Runnable",
             BorderStyle = LineStyle.None
             BorderStyle = LineStyle.None
         };
         };
 
 
@@ -169,13 +169,13 @@ public class ViewportSettings : Scenario
         };
         };
 
 
         charMap.Accepting += (s, e) =>
         charMap.Accepting += (s, e) =>
-                              MessageBox.Query (20, 7, "Hi", $"Am I a {view.GetType ().Name}?", "Yes", "No");
+                              MessageBox.Query ((s as View)?.App, 20, 7, "Hi", $"Am I a {view.GetType ().Name}?", "Yes", "No");
 
 
         var buttonAnchored = new Button
         var buttonAnchored = new Button
         {
         {
             X = Pos.AnchorEnd () - 10, Y = Pos.AnchorEnd () - 4, Text = "Bottom Rig_ht"
             X = Pos.AnchorEnd () - 10, Y = Pos.AnchorEnd () - 4, Text = "Bottom Rig_ht"
         };
         };
-        buttonAnchored.Accepting += (sender, args) => MessageBox.Query ("Hi", $"You pressed {((Button)sender)?.Text}", "_Ok");
+        buttonAnchored.Accepting += (sender, args) => MessageBox.Query ((sender as View)?.App, "Hi", $"You pressed {((Button)sender)?.Text}", "_Ok");
 
 
         view.Margin!.Data = "Margin";
         view.Margin!.Data = "Margin";
         view.Margin!.Thickness = new (0);
         view.Margin!.Thickness = new (0);

+ 3 - 3
Examples/UICatalog/Scenarios/WindowsAndFrameViews.cs

@@ -16,9 +16,9 @@ public class WindowsAndFrameViews : Scenario
             Title = GetQuitKeyAndName ()
             Title = GetQuitKeyAndName ()
         };
         };
 
 
-        static int About ()
+        static int? About ()
         {
         {
-            return MessageBox.Query (
+            return MessageBox.Query (ApplicationImpl.Instance,
                                      "About UI Catalog",
                                      "About UI Catalog",
                                      "UI Catalog is a comprehensive sample library for Terminal.Gui",
                                      "UI Catalog is a comprehensive sample library for Terminal.Gui",
                                      "Ok"
                                      "Ok"
@@ -99,7 +99,7 @@ public class WindowsAndFrameViews : Scenario
             };
             };
 
 
             pressMeButton.Accepting += (s, e) =>
             pressMeButton.Accepting += (s, e) =>
-                                        MessageBox.ErrorQuery (loopWin.Title, "Neat?", "Yes", "No");
+                                        MessageBox.ErrorQuery ((s as View)?.App, loopWin.Title, "Neat?", "Yes", "No");
             loopWin.Add (pressMeButton);
             loopWin.Add (pressMeButton);
 
 
             var subWin = new Window
             var subWin = new Window

+ 11 - 8
Examples/UICatalog/Scenarios/WizardAsView.cs

@@ -21,6 +21,7 @@ public class WizardAsView : Scenario
                                        {
                                        {
                                            Title = "_Restart Configuration...",
                                            Title = "_Restart Configuration...",
                                            Action = () => MessageBox.Query (
                                            Action = () => MessageBox.Query (
+                                                                            ApplicationImpl.Instance,
                                                                             "Wizard",
                                                                             "Wizard",
                                                                             "Are you sure you want to reset the Wizard and start over?",
                                                                             "Are you sure you want to reset the Wizard and start over?",
                                                                             "Ok",
                                                                             "Ok",
@@ -31,6 +32,7 @@ public class WizardAsView : Scenario
                                        {
                                        {
                                            Title = "Re_boot Server...",
                                            Title = "Re_boot Server...",
                                            Action = () => MessageBox.Query (
                                            Action = () => MessageBox.Query (
+                                                                            ApplicationImpl.Instance,
                                                                             "Wizard",
                                                                             "Wizard",
                                                                             "Are you sure you want to reboot the server start over?",
                                                                             "Are you sure you want to reboot the server start over?",
                                                                             "Ok",
                                                                             "Ok",
@@ -41,6 +43,7 @@ public class WizardAsView : Scenario
                                        {
                                        {
                                            Title = "_Shutdown Server...",
                                            Title = "_Shutdown Server...",
                                            Action = () => MessageBox.Query (
                                            Action = () => MessageBox.Query (
+                                                                            ApplicationImpl.Instance,
                                                                             "Wizard",
                                                                             "Wizard",
                                                                             "Are you sure you want to cancel setup and shutdown?",
                                                                             "Are you sure you want to cancel setup and shutdown?",
                                                                             "Ok",
                                                                             "Ok",
@@ -63,7 +66,7 @@ public class WizardAsView : Scenario
 
 
         // Set Modal to false to cause the Wizard class to render without a frame and
         // Set Modal to false to cause the Wizard class to render without a frame and
         // behave like an non-modal View (vs. a modal/pop-up Window).
         // behave like an non-modal View (vs. a modal/pop-up Window).
-        wizard.Modal = false;
+       // wizard.Modal = false;
 
 
         wizard.MovingBack += (s, args) =>
         wizard.MovingBack += (s, args) =>
                              {
                              {
@@ -80,13 +83,13 @@ public class WizardAsView : Scenario
         wizard.Finished += (s, args) =>
         wizard.Finished += (s, args) =>
                            {
                            {
                                //args.Cancel = true;
                                //args.Cancel = true;
-                               MessageBox.Query ("Setup Wizard", "Finished", "Ok");
+                               MessageBox.Query ((s as View)?.App, "Setup Wizard", "Finished", "Ok");
                                Application.RequestStop ();
                                Application.RequestStop ();
                            };
                            };
 
 
         wizard.Cancelled += (s, args) =>
         wizard.Cancelled += (s, args) =>
                             {
                             {
-                                int btn = MessageBox.Query ("Setup Wizard", "Are you sure you want to cancel?", "Yes", "No");
+                                int? btn = MessageBox.Query ((s as View)?.App, "Setup Wizard", "Are you sure you want to cancel?", "Yes", "No");
                                 args.Cancel = btn == 1;
                                 args.Cancel = btn == 1;
 
 
                                 if (btn == 0)
                                 if (btn == 0)
@@ -123,7 +126,7 @@ public class WizardAsView : Scenario
                             {
                             {
                                 secondStep.Title = "2nd Step";
                                 secondStep.Title = "2nd Step";
 
 
-                                MessageBox.Query (
+                                MessageBox.Query ((s as View)?.App,
                                                   "Wizard Scenario",
                                                   "Wizard Scenario",
                                                   "This Wizard Step's title was changed to '2nd Step'",
                                                   "This Wizard Step's title was changed to '2nd Step'",
                                                   "Ok"
                                                   "Ok"
@@ -145,11 +148,11 @@ public class WizardAsView : Scenario
         lastStep.HelpText =
         lastStep.HelpText =
             "The wizard is complete!\n\nPress the Finish button to continue.\n\nPressing Esc will cancel.";
             "The wizard is complete!\n\nPress the Finish button to continue.\n\nPressing Esc will cancel.";
 
 
-        Window topLevel = new ();
-        topLevel.Add (menu, wizard);
+        Window window = new ();
+        window.Add (menu, wizard);
 
 
-        Application.Run (topLevel);
-        topLevel.Dispose ();
+        Application.Run (window);
+        window.Dispose ();
         Application.Shutdown ();
         Application.Shutdown ();
     }
     }
 }
 }

+ 271 - 268
Examples/UICatalog/Scenarios/Wizards.cs

@@ -1,13 +1,9 @@
-using System;
-using System.Linq;
-
-namespace UICatalog.Scenarios;
+namespace UICatalog.Scenarios;
 
 
 [ScenarioMetadata ("Wizards", "Demonstrates the Wizard class")]
 [ScenarioMetadata ("Wizards", "Demonstrates the Wizard class")]
 [ScenarioCategory ("Dialogs")]
 [ScenarioCategory ("Dialogs")]
 [ScenarioCategory ("Wizards")]
 [ScenarioCategory ("Wizards")]
 [ScenarioCategory ("Runnable")]
 [ScenarioCategory ("Runnable")]
-
 public class Wizards : Scenario
 public class Wizards : Scenario
 {
 {
     public override void Main ()
     public override void Main ()
@@ -85,10 +81,10 @@ public class Wizards : Scenario
         void Win_Loaded (object sender, EventArgs args)
         void Win_Loaded (object sender, EventArgs args)
         {
         {
             frame.Height = widthEdit.Frame.Height + heightEdit.Frame.Height + titleEdit.Frame.Height + 2;
             frame.Height = widthEdit.Frame.Height + heightEdit.Frame.Height + titleEdit.Frame.Height + 2;
-            win.Loaded -= Win_Loaded;
+            win.IsModalChanged -= Win_Loaded;
         }
         }
 
 
-        win.Loaded += Win_Loaded;
+        win.IsModalChanged += Win_Loaded;
 
 
         label = new ()
         label = new ()
         {
         {
@@ -108,267 +104,277 @@ public class Wizards : Scenario
         };
         };
 
 
         showWizardButton.Accepting += (s, e) =>
         showWizardButton.Accepting += (s, e) =>
-                                   {
-                                       try
-                                       {
-                                           var width = 0;
-                                           int.TryParse (widthEdit.Text, out width);
-                                           var height = 0;
-                                           int.TryParse (heightEdit.Text, out height);
-
-                                           if (width < 1 || height < 1)
-                                           {
-                                               MessageBox.ErrorQuery (
-                                                                      "Nope",
-                                                                      "Height and width must be greater than 0 (much bigger)",
-                                                                      "Ok"
-                                                                     );
-
-                                               return;
-                                           }
-
-                                           actionLabel.Text = string.Empty;
-
-                                           var wizard = new Wizard { Title = titleEdit.Text, Width = width, Height = height };
-
-                                           wizard.MovingBack += (s, args) =>
-                                                                {
-                                                                    //args.Cancel = true;
-                                                                    actionLabel.Text = "Moving Back";
-                                                                };
-
-                                           wizard.MovingNext += (s, args) =>
-                                                                {
-                                                                    //args.Cancel = true;
-                                                                    actionLabel.Text = "Moving Next";
-                                                                };
-
-                                           wizard.Finished += (s, args) =>
-                                                              {
-                                                                  //args.Cancel = true;
-                                                                  actionLabel.Text = "Finished";
-                                                              };
-
-                                           wizard.Cancelled += (s, args) =>
-                                                               {
-                                                                   //args.Cancel = true;
-                                                                   actionLabel.Text = "Cancelled";
-                                                               };
-
-                                           // Add 1st step
-                                           var firstStep = new WizardStep { Title = "End User License Agreement" };
-                                           firstStep.NextButtonText = "Accept!";
-
-                                           firstStep.HelpText =
-                                               "This is the End User License Agreement.\n\n\n\n\n\nThis is a test of the emergency broadcast system. This is a test of the emergency broadcast system.\nThis is a test of the emergency broadcast system.\n\n\nThis is a test of the emergency broadcast system.\n\nThis is a test of the emergency broadcast system.\n\n\n\nThe end of the EULA.";
-
-                                           OptionSelector optionSelector = new ()
-                                           {
-                                               Labels = ["_One", "_Two", "_3"]
-                                           };
-                                           firstStep.Add (optionSelector);
-
-                                           wizard.AddStep (firstStep);
-
-                                           // Add 2nd step
-                                           var secondStep = new WizardStep { Title = "Second Step" };
-                                           wizard.AddStep (secondStep);
-
-                                           secondStep.HelpText =
-                                               "This is the help text for the Second Step.\n\nPress the button to change the Title.\n\nIf First Name is empty the step will prevent moving to the next step.";
-
-                                           var buttonLbl = new Label { Text = "Second Step Button: ", X = 1, Y = 1 };
-
-                                           var button = new Button
-                                           {
-                                               Text = "Press Me to Rename Step", X = Pos.Right (buttonLbl), Y = Pos.Top (buttonLbl)
-                                           };
-
-                                           OptionSelector optionSelecor2 = new ()
-                                           {
-                                               Labels = ["_A", "_B", "_C"],
-                                               Orientation = Orientation.Horizontal
-                                           };
-                                           secondStep.Add (optionSelecor2);
-
-                                           button.Accepting += (s, e) =>
-                                                            {
-                                                                secondStep.Title = "2nd Step";
-
-                                                                MessageBox.Query (
-                                                                                  "Wizard Scenario",
-                                                                                  "This Wizard Step's title was changed to '2nd Step'"
-                                                                                 );
-                                                            };
-                                           secondStep.Add (buttonLbl, button);
-                                           var lbl = new Label { Text = "First Name: ", X = 1, Y = Pos.Bottom (buttonLbl) };
-
-                                           var firstNameField =
-                                               new TextField { Text = "Number", Width = 30, X = Pos.Right (lbl), Y = Pos.Top (lbl) };
-                                           secondStep.Add (lbl, firstNameField);
-                                           lbl = new () { Text = "Last Name:  ", X = 1, Y = Pos.Bottom (lbl) };
-                                           var lastNameField = new TextField { Text = "Six", Width = 30, X = Pos.Right (lbl), Y = Pos.Top (lbl) };
-                                           secondStep.Add (lbl, lastNameField);
-
-                                           var thirdStepEnabledCeckBox = new CheckBox
-                                           {
-                                               Text = "Enable Step _3",
-                                               CheckedState = CheckState.UnChecked,
-                                               X = Pos.Left (lastNameField),
-                                               Y = Pos.Bottom (lastNameField)
-                                           };
-                                           secondStep.Add (thirdStepEnabledCeckBox);
-
-                                           // Add a frame 
-                                           var frame = new FrameView
-                                           {
-                                               X = 0,
-                                               Y = Pos.Bottom (thirdStepEnabledCeckBox) + 2,
-                                               Width = Dim.Fill (),
-                                               Height = 4,
-                                               Title = "A Broken Frame (by Depeche Mode)",
-                                               TabStop = TabBehavior.NoStop
-                                           };
-                                           frame.Add (new TextField { Text = "This is a TextField inside of the frame." });
-                                           secondStep.Add (frame);
-
-                                           wizard.StepChanging += (s, args) =>
+                                      {
+                                          try
+                                          {
+                                              var width = 0;
+                                              int.TryParse (widthEdit.Text, out width);
+                                              var height = 0;
+                                              int.TryParse (heightEdit.Text, out height);
+
+                                              if (width < 1 || height < 1)
+                                              {
+                                                  MessageBox.ErrorQuery (
+                                                                         (s as View)?.App,
+                                                                         "Nope",
+                                                                         "Height and width must be greater than 0 (much bigger)",
+                                                                         "Ok"
+                                                                        );
+
+                                                  return;
+                                              }
+
+                                              actionLabel.Text = string.Empty;
+
+                                              var wizard = new Wizard { Title = titleEdit.Text, Width = width, Height = height };
+
+                                              wizard.MovingBack += (s, args) =>
+                                                                   {
+                                                                       //args.Cancel = true;
+                                                                       actionLabel.Text = "Moving Back";
+                                                                   };
+
+                                              wizard.MovingNext += (s, args) =>
+                                                                   {
+                                                                       //args.Cancel = true;
+                                                                       actionLabel.Text = "Moving Next";
+                                                                   };
+
+                                              wizard.Finished += (s, args) =>
+                                                                 {
+                                                                     //args.Cancel = true;
+                                                                     actionLabel.Text = "Finished";
+                                                                 };
+
+                                              wizard.Cancelled += (s, args) =>
                                                                   {
                                                                   {
-                                                                      if (args.OldStep == secondStep && string.IsNullOrEmpty (firstNameField.Text))
-                                                                      {
-                                                                          args.Cancel = true;
-
-                                                                          int btn = MessageBox.ErrorQuery (
-                                                                               "Second Step",
-                                                                               "You must enter a First Name to continue",
-                                                                               "Ok"
-                                                                              );
-                                                                      }
+                                                                      //args.Cancel = true;
+                                                                      actionLabel.Text = "Cancelled";
                                                                   };
                                                                   };
 
 
-                                           // Add 3rd (optional) step
-                                           var thirdStep = new WizardStep { Title = "Third Step (Optional)" };
-                                           wizard.AddStep (thirdStep);
-
-                                           thirdStep.HelpText =
-                                               "This is step is optional (WizardStep.Enabled = false). Enable it with the checkbox in Step 2.";
-                                           var step3Label = new Label { Text = "This step is optional.", X = 0, Y = 0 };
-                                           thirdStep.Add (step3Label);
-                                           var progLbl = new Label { Text = "Third Step ProgressBar: ", X = 1, Y = 10 };
-
-                                           var progressBar = new ProgressBar
-                                           {
-                                               X = Pos.Right (progLbl), Y = Pos.Top (progLbl), Width = 40, Fraction = 0.42F
-                                           };
-                                           thirdStep.Add (progLbl, progressBar);
-                                           thirdStep.Enabled = thirdStepEnabledCeckBox.CheckedState == CheckState.Checked;
-                                           thirdStepEnabledCeckBox.CheckedStateChanged += (s, e) => { thirdStep.Enabled = thirdStepEnabledCeckBox.CheckedState == CheckState.Checked; };
-
-                                           // Add 4th step
-                                           var fourthStep = new WizardStep { Title = "Step Four" };
-                                           wizard.AddStep (fourthStep);
-
-                                           var someText = new TextView
-                                           {
-                                               Text =
-                                                   "This step (Step Four) shows how to show/hide the Help pane. The step contains this TextView (but it's hard to tell it's a TextView because of Issue #1800).",
-                                               X = 0,
-                                               Y = 0,
-                                               Width = Dim.Fill (),
-                                               WordWrap = true,
-                                               AllowsTab = false,
-                                               SchemeName = "Base"
-                                           };
-
-                                           someText.Height = Dim.Fill (
-                                                                       Dim.Func (
-                                                                                 v => someText.SuperView is { IsInitialized: true }
-                                                                                          ? someText.SuperView.SubViews
-                                                                                                    .First (view => view.Y.Has<PosAnchorEnd> (out _))
-                                                                                                    .Frame.Height
-                                                                                          : 1));
-                                           var help = "This is helpful.";
-                                           fourthStep.Add (someText);
-
-                                           var hideHelpBtn = new Button
-                                           {
-                                               Text = "Press me to show/hide help",
-                                               X = Pos.Center (),
-                                               Y = Pos.AnchorEnd ()
-                                           };
-
-                                           hideHelpBtn.Accepting += (s, e) =>
-                                                                 {
-                                                                     if (fourthStep.HelpText.Length > 0)
-                                                                     {
-                                                                         fourthStep.HelpText = string.Empty;
-                                                                     }
-                                                                     else
+                                              // Add 1st step
+                                              var firstStep = new WizardStep { Title = "End User License Agreement" };
+                                              firstStep.NextButtonText = "Accept!";
+
+                                              firstStep.HelpText =
+                                                  "This is the End User License Agreement.\n\n\n\n\n\nThis is a test of the emergency broadcast system. This is a test of the emergency broadcast system.\nThis is a test of the emergency broadcast system.\n\n\nThis is a test of the emergency broadcast system.\n\nThis is a test of the emergency broadcast system.\n\n\n\nThe end of the EULA.";
+
+                                              OptionSelector optionSelector = new ()
+                                              {
+                                                  Labels = ["_One", "_Two", "_3"]
+                                              };
+                                              firstStep.Add (optionSelector);
+
+                                              wizard.AddStep (firstStep);
+
+                                              // Add 2nd step
+                                              var secondStep = new WizardStep { Title = "Second Step" };
+                                              wizard.AddStep (secondStep);
+
+                                              secondStep.HelpText =
+                                                  "This is the help text for the Second Step.\n\nPress the button to change the Title.\n\nIf First Name is empty the step will prevent moving to the next step.";
+
+                                              var buttonLbl = new Label { Text = "Second Step Button: ", X = 1, Y = 1 };
+
+                                              var button = new Button
+                                              {
+                                                  Text = "Press Me to Rename Step", X = Pos.Right (buttonLbl), Y = Pos.Top (buttonLbl)
+                                              };
+
+                                              OptionSelector optionSelecor2 = new ()
+                                              {
+                                                  Labels = ["_A", "_B", "_C"],
+                                                  Orientation = Orientation.Horizontal
+                                              };
+                                              secondStep.Add (optionSelecor2);
+
+                                              button.Accepting += (s, e) =>
+                                                                  {
+                                                                      secondStep.Title = "2nd Step";
+
+                                                                      MessageBox.Query (
+                                                                                        (s as View)?.App,
+                                                                                        "Wizard Scenario",
+                                                                                        "This Wizard Step's title was changed to '2nd Step'"
+                                                                                       );
+                                                                  };
+                                              secondStep.Add (buttonLbl, button);
+                                              var lbl = new Label { Text = "First Name: ", X = 1, Y = Pos.Bottom (buttonLbl) };
+
+                                              var firstNameField =
+                                                  new TextField { Text = "Number", Width = 30, X = Pos.Right (lbl), Y = Pos.Top (lbl) };
+                                              secondStep.Add (lbl, firstNameField);
+                                              lbl = new () { Text = "Last Name:  ", X = 1, Y = Pos.Bottom (lbl) };
+                                              var lastNameField = new TextField { Text = "Six", Width = 30, X = Pos.Right (lbl), Y = Pos.Top (lbl) };
+                                              secondStep.Add (lbl, lastNameField);
+
+                                              var thirdStepEnabledCeckBox = new CheckBox
+                                              {
+                                                  Text = "Enable Step _3",
+                                                  CheckedState = CheckState.UnChecked,
+                                                  X = Pos.Left (lastNameField),
+                                                  Y = Pos.Bottom (lastNameField)
+                                              };
+                                              secondStep.Add (thirdStepEnabledCeckBox);
+
+                                              // Add a frame 
+                                              var frame = new FrameView
+                                              {
+                                                  X = 0,
+                                                  Y = Pos.Bottom (thirdStepEnabledCeckBox) + 2,
+                                                  Width = Dim.Fill (),
+                                                  Height = 4,
+                                                  Title = "A Broken Frame (by Depeche Mode)",
+                                                  TabStop = TabBehavior.NoStop
+                                              };
+                                              frame.Add (new TextField { Text = "This is a TextField inside of the frame." });
+                                              secondStep.Add (frame);
+
+                                              wizard.StepChanging += (s, args) =>
                                                                      {
                                                                      {
-                                                                         fourthStep.HelpText = help;
-                                                                     }
-                                                                 };
-                                           fourthStep.Add (hideHelpBtn);
-                                           fourthStep.NextButtonText = "_Go To Last Step";
-                                           //var scrollBar = new ScrollBarView (someText, true);
-
-                                           //scrollBar.ChangedPosition += (s, e) =>
-                                           //                             {
-                                           //                                 someText.TopRow = scrollBar.Position;
-
-                                           //                                 if (someText.TopRow != scrollBar.Position)
-                                           //                                 {
-                                           //                                     scrollBar.Position = someText.TopRow;
-                                           //                                 }
-
-                                           //                                 someText.SetNeedsDraw ();
-                                           //                             };
-
-                                           //someText.DrawingContent += (s, e) =>
-                                           //                        {
-                                           //                            scrollBar.Size = someText.Lines;
-                                           //                            scrollBar.Position = someText.TopRow;
-
-                                           //                            if (scrollBar.OtherScrollBarView != null)
-                                           //                            {
-                                           //                                scrollBar.OtherScrollBarView.Size = someText.Maxlength;
-                                           //                                scrollBar.OtherScrollBarView.Position = someText.LeftColumn;
-                                           //                            }
-                                           //                        };
-                                           //fourthStep.Add (scrollBar);
-
-                                           // Add last step
-                                           var lastStep = new WizardStep { Title = "The last step" };
-                                           wizard.AddStep (lastStep);
-
-                                           lastStep.HelpText =
-                                               "The wizard is complete!\n\nPress the Finish button to continue.\n\nPressing ESC will cancel the wizard.";
-
-                                           var finalFinalStepEnabledCeckBox =
-                                               new CheckBox { Text = "Enable _Final Final Step", CheckedState = CheckState.UnChecked, X = 0, Y = 1 };
-                                           lastStep.Add (finalFinalStepEnabledCeckBox);
-
-                                           // Add an optional FINAL last step
-                                           var finalFinalStep = new WizardStep { Title = "The VERY last step" };
-                                           wizard.AddStep (finalFinalStep);
-
-                                           finalFinalStep.HelpText =
-                                               "This step only shows if it was enabled on the other last step.";
-                                           finalFinalStep.Enabled = thirdStepEnabledCeckBox.CheckedState == CheckState.Checked;
-
-                                           finalFinalStepEnabledCeckBox.CheckedStateChanged += (s, e) =>
-                                                                                   {
-                                                                                       finalFinalStep.Enabled = finalFinalStepEnabledCeckBox.CheckedState == CheckState.Checked;
-                                                                                   };
-
-                                           Application.Run (wizard);
-                                           wizard.Dispose ();
-                                       }
-                                       catch (FormatException)
-                                       {
-                                           actionLabel.Text = "Invalid Options";
-                                       }
-                                   };
+                                                                         if (args.OldStep == secondStep && string.IsNullOrEmpty (firstNameField.Text))
+                                                                         {
+                                                                             args.Cancel = true;
+
+                                                                             int? btn = MessageBox.ErrorQuery (
+                                                                                  (s as View)?.App,
+                                                                                  "Second Step",
+                                                                                  "You must enter a First Name to continue",
+                                                                                  "Ok"
+                                                                                 );
+                                                                         }
+                                                                     };
+
+                                              // Add 3rd (optional) step
+                                              var thirdStep = new WizardStep { Title = "Third Step (Optional)" };
+                                              wizard.AddStep (thirdStep);
+
+                                              thirdStep.HelpText =
+                                                  "This is step is optional (WizardStep.Enabled = false). Enable it with the checkbox in Step 2.";
+                                              var step3Label = new Label { Text = "This step is optional.", X = 0, Y = 0 };
+                                              thirdStep.Add (step3Label);
+                                              var progLbl = new Label { Text = "Third Step ProgressBar: ", X = 1, Y = 10 };
+
+                                              var progressBar = new ProgressBar
+                                              {
+                                                  X = Pos.Right (progLbl), Y = Pos.Top (progLbl), Width = 40, Fraction = 0.42F
+                                              };
+                                              thirdStep.Add (progLbl, progressBar);
+                                              thirdStep.Enabled = thirdStepEnabledCeckBox.CheckedState == CheckState.Checked;
+
+                                              thirdStepEnabledCeckBox.CheckedStateChanged += (s, e) =>
+                                                                                             {
+                                                                                                 thirdStep.Enabled =
+                                                                                                     thirdStepEnabledCeckBox.CheckedState == CheckState.Checked;
+                                                                                             };
+
+                                              // Add 4th step
+                                              var fourthStep = new WizardStep { Title = "Step Four" };
+                                              wizard.AddStep (fourthStep);
+
+                                              var someText = new TextView
+                                              {
+                                                  Text =
+                                                      "This step (Step Four) shows how to show/hide the Help pane. The step contains this TextView (but it's hard to tell it's a TextView because of Issue #1800).",
+                                                  X = 0,
+                                                  Y = 0,
+                                                  Width = Dim.Fill (),
+                                                  WordWrap = true,
+                                                  AllowsTab = false,
+                                                  SchemeName = "Base"
+                                              };
+
+                                              someText.Height = Dim.Fill (
+                                                                          Dim.Func (v => someText.SuperView is { IsInitialized: true }
+                                                                                             ? someText.SuperView.SubViews
+                                                                                                       .First (view => view.Y.Has<PosAnchorEnd> (out _))
+                                                                                                       .Frame.Height
+                                                                                             : 1));
+                                              var help = "This is helpful.";
+                                              fourthStep.Add (someText);
+
+                                              var hideHelpBtn = new Button
+                                              {
+                                                  Text = "Press me to show/hide help",
+                                                  X = Pos.Center (),
+                                                  Y = Pos.AnchorEnd ()
+                                              };
+
+                                              hideHelpBtn.Accepting += (s, e) =>
+                                                                       {
+                                                                           if (fourthStep.HelpText.Length > 0)
+                                                                           {
+                                                                               fourthStep.HelpText = string.Empty;
+                                                                           }
+                                                                           else
+                                                                           {
+                                                                               fourthStep.HelpText = help;
+                                                                           }
+                                                                       };
+                                              fourthStep.Add (hideHelpBtn);
+                                              fourthStep.NextButtonText = "_Go To Last Step";
+
+                                              //var scrollBar = new ScrollBarView (someText, true);
+
+                                              //scrollBar.ChangedPosition += (s, e) =>
+                                              //                             {
+                                              //                                 someText.TopRow = scrollBar.Position;
+
+                                              //                                 if (someText.TopRow != scrollBar.Position)
+                                              //                                 {
+                                              //                                     scrollBar.Position = someText.TopRow;
+                                              //                                 }
+
+                                              //                                 someText.SetNeedsDraw ();
+                                              //                             };
+
+                                              //someText.DrawingContent += (s, e) =>
+                                              //                        {
+                                              //                            scrollBar.Size = someText.Lines;
+                                              //                            scrollBar.Position = someText.TopRow;
+
+                                              //                            if (scrollBar.OtherScrollBarView != null)
+                                              //                            {
+                                              //                                scrollBar.OtherScrollBarView.Size = someText.Maxlength;
+                                              //                                scrollBar.OtherScrollBarView.Position = someText.LeftColumn;
+                                              //                            }
+                                              //                        };
+                                              //fourthStep.Add (scrollBar);
+
+                                              // Add last step
+                                              var lastStep = new WizardStep { Title = "The last step" };
+                                              wizard.AddStep (lastStep);
+
+                                              lastStep.HelpText =
+                                                  "The wizard is complete!\n\nPress the Finish button to continue.\n\nPressing ESC will cancel the wizard.";
+
+                                              var finalFinalStepEnabledCeckBox =
+                                                  new CheckBox { Text = "Enable _Final Final Step", CheckedState = CheckState.UnChecked, X = 0, Y = 1 };
+                                              lastStep.Add (finalFinalStepEnabledCeckBox);
+
+                                              // Add an optional FINAL last step
+                                              var finalFinalStep = new WizardStep { Title = "The VERY last step" };
+                                              wizard.AddStep (finalFinalStep);
+
+                                              finalFinalStep.HelpText =
+                                                  "This step only shows if it was enabled on the other last step.";
+                                              finalFinalStep.Enabled = thirdStepEnabledCeckBox.CheckedState == CheckState.Checked;
+
+                                              finalFinalStepEnabledCeckBox.CheckedStateChanged += (s, e) =>
+                                                                                                  {
+                                                                                                      finalFinalStep.Enabled =
+                                                                                                          finalFinalStepEnabledCeckBox.CheckedState
+                                                                                                          == CheckState.Checked;
+                                                                                                  };
+
+                                              Application.Run (wizard);
+                                              wizard.Dispose ();
+                                          }
+                                          catch (FormatException)
+                                          {
+                                              actionLabel.Text = "Invalid Options";
+                                          }
+                                      };
         win.Add (showWizardButton);
         win.Add (showWizardButton);
 
 
         Application.Run (win);
         Application.Run (win);
@@ -376,8 +382,5 @@ public class Wizards : Scenario
         Application.Shutdown ();
         Application.Shutdown ();
     }
     }
 
 
-    private void Wizard_StepChanged (object sender, StepChangeEventArgs e)
-    {
-        throw new NotImplementedException ();
-    }
+    private void Wizard_StepChanged (object sender, StepChangeEventArgs e) { throw new NotImplementedException (); }
 }
 }

+ 13 - 25
Examples/UICatalog/UICatalog.cs

@@ -73,8 +73,8 @@ public class UICatalog
             CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo ("en-US");
             CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo ("en-US");
         }
         }
 
 
-        UICatalogTop.CachedScenarios = Scenario.GetScenarios ();
-        UICatalogTop.CachedCategories = Scenario.GetAllCategories ();
+        UICatalogRunnable.CachedScenarios = Scenario.GetScenarios ();
+        UICatalogRunnable.CachedCategories = Scenario.GetAllCategories ();
 
 
         // Process command line args
         // Process command line args
 
 
@@ -136,7 +136,7 @@ public class UICatalog
                                                                   "The name of the Scenario to run. If not provided, the UI Catalog UI will be shown.",
                                                                   "The name of the Scenario to run. If not provided, the UI Catalog UI will be shown.",
                                                                   getDefaultValue: () => "none"
                                                                   getDefaultValue: () => "none"
                                                                  ).FromAmong (
                                                                  ).FromAmong (
-                                                                              UICatalogTop.CachedScenarios.Select (s => s.GetName ())
+                                                                              UICatalogRunnable.CachedScenarios.Select (s => s.GetName ())
                                                                                           .Append ("none")
                                                                                           .Append ("none")
                                                                                           .ToArray ()
                                                                                           .ToArray ()
                                                                              );
                                                                              );
@@ -249,7 +249,7 @@ public class UICatalog
     ///     killed and the Scenario is run as though it were Application.TopRunnable. When the Scenario exits, this function exits.
     ///     killed and the Scenario is run as though it were Application.TopRunnable. When the Scenario exits, this function exits.
     /// </summary>
     /// </summary>
     /// <returns></returns>
     /// <returns></returns>
-    private static Scenario RunUICatalogTopLevel ()
+    private static Scenario RunUICatalogRunnable ()
     {
     {
         // Run UI Catalog UI. When it exits, if _selectedScenario is != null then
         // Run UI Catalog UI. When it exits, if _selectedScenario is != null then
         // a Scenario was selected. Otherwise, the user wants to quit UI Catalog.
         // a Scenario was selected. Otherwise, the user wants to quit UI Catalog.
@@ -261,12 +261,11 @@ public class UICatalog
 
 
         _uiCatalogDriver = Application.Driver!.GetName ();
         _uiCatalogDriver = Application.Driver!.GetName ();
 
 
-        Toplevel top = Application.Run<UICatalogTop> ();
-        top.Dispose ();
+        Application.Run<UICatalogRunnable> ();
         Application.Shutdown ();
         Application.Shutdown ();
         VerifyObjectsWereDisposed ();
         VerifyObjectsWereDisposed ();
 
 
-        return UICatalogTop.CachedSelectedScenario!;
+        return UICatalogRunnable.CachedSelectedScenario!;
     }
     }
 
 
     [SuppressMessage ("Style", "IDE1006:Naming Styles", Justification = "<Pending>")]
     [SuppressMessage ("Style", "IDE1006:Naming Styles", Justification = "<Pending>")]
@@ -347,7 +346,7 @@ public class UICatalog
 
 
     private static void ConfigFileChanged (object sender, FileSystemEventArgs e)
     private static void ConfigFileChanged (object sender, FileSystemEventArgs e)
     {
     {
-        if (Application.TopRunnable == null)
+        if (Application.TopRunnableView == null)
         {
         {
             return;
             return;
         }
         }
@@ -372,15 +371,15 @@ public class UICatalog
                 ConfigurationManager.Enable (ConfigLocations.All);
                 ConfigurationManager.Enable (ConfigLocations.All);
             }
             }
 
 
-            int item = UICatalogTop.CachedScenarios!.IndexOf (
-                                                              UICatalogTop.CachedScenarios!.FirstOrDefault (
+            int item = UICatalogRunnable.CachedScenarios!.IndexOf (
+                                                              UICatalogRunnable.CachedScenarios!.FirstOrDefault (
                                                                    s =>
                                                                    s =>
                                                                        s.GetName ()
                                                                        s.GetName ()
                                                                         .Equals (options.Scenario, StringComparison.OrdinalIgnoreCase)
                                                                         .Equals (options.Scenario, StringComparison.OrdinalIgnoreCase)
                                                                   )!);
                                                                   )!);
-            UICatalogTop.CachedSelectedScenario = (Scenario)Activator.CreateInstance (UICatalogTop.CachedScenarios [item].GetType ())!;
+            UICatalogRunnable.CachedSelectedScenario = (Scenario)Activator.CreateInstance (UICatalogRunnable.CachedScenarios [item].GetType ())!;
 
 
-            BenchmarkResults? results = RunScenario (UICatalogTop.CachedSelectedScenario, options.Benchmark);
+            BenchmarkResults? results = RunScenario (UICatalogRunnable.CachedSelectedScenario, options.Benchmark);
 
 
             if (results is { })
             if (results is { })
             {
             {
@@ -416,7 +415,7 @@ public class UICatalog
             StartConfigWatcher ();
             StartConfigWatcher ();
         }
         }
 
 
-        while (RunUICatalogTopLevel () is { } scenario)
+        while (RunUICatalogRunnable () is { } scenario)
         {
         {
 #if DEBUG_IDISPOSABLE
 #if DEBUG_IDISPOSABLE
             VerifyObjectsWereDisposed ();
             VerifyObjectsWereDisposed ();
@@ -495,7 +494,7 @@ public class UICatalog
 
 
         var maxScenarios = 5;
         var maxScenarios = 5;
 
 
-        foreach (Scenario s in UICatalogTop.CachedScenarios!)
+        foreach (Scenario s in UICatalogRunnable.CachedScenarios!)
         {
         {
             resultsList.Add (RunScenario (s, true)!);
             resultsList.Add (RunScenario (s, true)!);
             maxScenarios--;
             maxScenarios--;
@@ -654,7 +653,6 @@ public class UICatalog
         if (!View.EnableDebugIDisposableAsserts)
         if (!View.EnableDebugIDisposableAsserts)
         {
         {
             View.Instances.Clear ();
             View.Instances.Clear ();
-            SessionToken.Instances.Clear ();
 
 
             return;
             return;
         }
         }
@@ -668,16 +666,6 @@ public class UICatalog
         }
         }
 
 
         View.Instances.Clear ();
         View.Instances.Clear ();
-
-        // Validate there are no outstanding Application sessions
-        // after a scenario was selected to run. This proves the main UI Catalog
-        // 'app' closed cleanly.
-        foreach (SessionToken? inst in SessionToken.Instances)
-        {
-            Debug.Assert (inst.WasDisposed);
-        }
-
-        SessionToken.Instances.Clear ();
 #endif
 #endif
     }
     }
 }
 }

+ 28 - 19
Examples/UICatalog/UICatalogTop.cs → Examples/UICatalog/UICatalogRunnable.cs

@@ -14,7 +14,7 @@ namespace UICatalog;
 ///     This is the main UI Catalog app view. It is run fresh when the app loads (if a Scenario has not been passed on
 ///     This is the main UI Catalog app view. It is run fresh when the app loads (if a Scenario has not been passed on
 ///     the command line) and each time a Scenario ends.
 ///     the command line) and each time a Scenario ends.
 /// </summary>
 /// </summary>
-public class UICatalogTop : Toplevel
+public class UICatalogRunnable : Runnable
 {
 {
     // When a scenario is run, the main app is killed. The static
     // When a scenario is run, the main app is killed. The static
     // members are cached so that when the scenario exits the
     // members are cached so that when the scenario exits the
@@ -23,12 +23,12 @@ public class UICatalogTop : Toplevel
     // Note, we used to pass this to scenarios that run, but it just added complexity
     // Note, we used to pass this to scenarios that run, but it just added complexity
     // So that was removed. But we still have this here to demonstrate how changing
     // So that was removed. But we still have this here to demonstrate how changing
     // the scheme works.
     // the scheme works.
-    public static string? CachedTopLevelScheme { get; set; }
+    public static string? CachedRunnableScheme { get; set; }
 
 
     // Diagnostics
     // Diagnostics
     private static ViewDiagnosticFlags _diagnosticFlags;
     private static ViewDiagnosticFlags _diagnosticFlags;
 
 
-    public UICatalogTop ()
+    public UICatalogRunnable ()
     {
     {
         _diagnosticFlags = Diagnostics;
         _diagnosticFlags = Diagnostics;
 
 
@@ -39,8 +39,8 @@ public class UICatalogTop : Toplevel
 
 
         Add (_menuBar, _categoryList, _scenarioList, _statusBar);
         Add (_menuBar, _categoryList, _scenarioList, _statusBar);
 
 
-        Loaded += LoadedHandler;
-        Unloaded += UnloadedHandler;
+        IsModalChanged += IsModalChangedHandler;
+        IsRunningChanged += IsRunningChangedHandler;
 
 
         // Restore previous selections
         // Restore previous selections
         if (_categoryList.Source?.Count > 0) {
         if (_categoryList.Source?.Count > 0) {
@@ -50,15 +50,20 @@ public class UICatalogTop : Toplevel
         }
         }
         _scenarioList.SelectedRow = _cachedScenarioIndex;
         _scenarioList.SelectedRow = _cachedScenarioIndex;
 
 
-        SchemeName = CachedTopLevelScheme = SchemeManager.SchemesToSchemeName (Schemes.Base);
+        SchemeName = CachedRunnableScheme = SchemeManager.SchemesToSchemeName (Schemes.Base);
         ConfigurationManager.Applied += ConfigAppliedHandler;
         ConfigurationManager.Applied += ConfigAppliedHandler;
     }
     }
 
 
 
 
     private static bool _isFirstRunning = true;
     private static bool _isFirstRunning = true;
 
 
-    private void LoadedHandler (object? sender, EventArgs? args)
+    private void IsModalChangedHandler (object? sender, EventArgs<bool> args)
     {
     {
+        if (!args.Value)
+        {
+            return;
+        }
+
         if (_disableMouseCb is { })
         if (_disableMouseCb is { })
         {
         {
             _disableMouseCb.CheckedState = Application.IsMouseDisabled ? CheckState.Checked : CheckState.UnChecked;
             _disableMouseCb.CheckedState = Application.IsMouseDisabled ? CheckState.Checked : CheckState.UnChecked;
@@ -85,15 +90,18 @@ public class UICatalogTop : Toplevel
             _statusBar.VisibleChanged += (s, e) => { ShowStatusBar = _statusBar.Visible; };
             _statusBar.VisibleChanged += (s, e) => { ShowStatusBar = _statusBar.Visible; };
         }
         }
 
 
-        Loaded -= LoadedHandler;
+        IsModalChanged -= IsModalChangedHandler;
         _categoryList!.EnsureSelectedItemVisible ();
         _categoryList!.EnsureSelectedItemVisible ();
         _scenarioList.EnsureSelectedCellIsVisible ();
         _scenarioList.EnsureSelectedCellIsVisible ();
     }
     }
 
 
-    private void UnloadedHandler (object? sender, EventArgs? args)
+    private void IsRunningChangedHandler (object? sender, EventArgs<bool> args)
     {
     {
-        ConfigurationManager.Applied -= ConfigAppliedHandler;
-        Unloaded -= UnloadedHandler;
+        if (!args.Value)
+        {
+            ConfigurationManager.Applied -= ConfigAppliedHandler;
+            IsRunningChanged -= IsRunningChangedHandler;
+        }
     }
     }
 
 
     #region MenuBar
     #region MenuBar
@@ -144,6 +152,7 @@ public class UICatalogTop : Toplevel
                                                               "_About...",
                                                               "_About...",
                                                               "About UI Catalog",
                                                               "About UI Catalog",
                                                               () => MessageBox.Query (
                                                               () => MessageBox.Query (
+                                                                                      App,
                                                                                       "",
                                                                                       "",
                                                                                       GetAboutBoxMessage (),
                                                                                       GetAboutBoxMessage (),
                                                                                       wrapMessage: false,
                                                                                       wrapMessage: false,
@@ -239,14 +248,14 @@ public class UICatalogTop : Toplevel
                                                         {
                                                         {
                                                             return;
                                                             return;
                                                         }
                                                         }
-                                                        CachedTopLevelScheme = SchemeManager.GetSchemesForCurrentTheme ()!.Keys.ToArray () [(int)args.Value];
-                                                        SchemeName = CachedTopLevelScheme;
+                                                        CachedRunnableScheme = SchemeManager.GetSchemesForCurrentTheme ()!.Keys.ToArray () [(int)args.Value];
+                                                        SchemeName = CachedRunnableScheme;
                                                         SetNeedsDraw ();
                                                         SetNeedsDraw ();
                                                     };
                                                     };
 
 
                 menuItem = new ()
                 menuItem = new ()
                 {
                 {
-                    Title = "Scheme for Toplevel",
+                    Title = "Scheme for Runnable",
                     SubMenu = new (
                     SubMenu = new (
                                    [
                                    [
                                        new ()
                                        new ()
@@ -391,12 +400,12 @@ public class UICatalogTop : Toplevel
         _topSchemesSelector.Labels = SchemeManager.GetSchemeNames ().ToArray ();
         _topSchemesSelector.Labels = SchemeManager.GetSchemeNames ().ToArray ();
         _topSchemesSelector.Value = selectedScheme;
         _topSchemesSelector.Value = selectedScheme;
 
 
-        if (CachedTopLevelScheme is null || !SchemeManager.GetSchemeNames ().Contains (CachedTopLevelScheme))
+        if (CachedRunnableScheme is null || !SchemeManager.GetSchemeNames ().Contains (CachedRunnableScheme))
         {
         {
-            CachedTopLevelScheme = SchemeManager.SchemesToSchemeName (Schemes.Base);
+            CachedRunnableScheme = SchemeManager.SchemesToSchemeName (Schemes.Base);
         }
         }
 
 
-        int newSelectedItem = SchemeManager.GetSchemeNames ().IndexOf (CachedTopLevelScheme!);
+        int newSelectedItem = SchemeManager.GetSchemeNames ().IndexOf (CachedRunnableScheme!);
         // if the item is in bounds then select it
         // if the item is in bounds then select it
         if (newSelectedItem >= 0 && newSelectedItem < SchemeManager.GetSchemeNames ().Count)
         if (newSelectedItem >= 0 && newSelectedItem < SchemeManager.GetSchemeNames ().Count)
         {
         {
@@ -685,7 +694,7 @@ public class UICatalogTop : Toplevel
     {
     {
         UpdateThemesMenu ();
         UpdateThemesMenu ();
 
 
-        SchemeName = CachedTopLevelScheme;
+        SchemeName = CachedRunnableScheme;
 
 
         if (_shQuit is { })
         if (_shQuit is { })
         {
         {
@@ -700,7 +709,7 @@ public class UICatalogTop : Toplevel
         _disableMouseCb!.CheckedState = Application.IsMouseDisabled ? CheckState.Checked : CheckState.UnChecked;
         _disableMouseCb!.CheckedState = Application.IsMouseDisabled ? CheckState.Checked : CheckState.UnChecked;
         _force16ColorsShortcutCb!.CheckedState = Application.Force16Colors ? CheckState.Checked : CheckState.UnChecked;
         _force16ColorsShortcutCb!.CheckedState = Application.Force16Colors ? CheckState.Checked : CheckState.UnChecked;
 
 
-        Application.TopRunnable?.SetNeedsDraw ();
+        Application.TopRunnableView?.SetNeedsDraw ();
     }
     }
 
 
     private void ConfigAppliedHandler (object? sender, ConfigurationManagerEventArgs? a) { ConfigApplied (); }
     private void ConfigAppliedHandler (object? sender, ConfigurationManagerEventArgs? a) { ConfigApplied (); }

+ 15 - 0
Terminal.Gui/App/Application.Clipboard.cs

@@ -0,0 +1,15 @@
+namespace Terminal.Gui.App;
+
+public static partial class Application // Clipboard handling
+{
+    /// <summary>
+    ///     Gets the clipboard for the application.
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         Provides access to the OS clipboard through the driver.
+    ///     </para>
+    /// </remarks>
+    [Obsolete ("The legacy static Application object is going away. Use IApplication.Clipboard instead.")]
+    public static IClipboard? Clipboard => ApplicationImpl.Instance.Clipboard;
+}

+ 0 - 18
Terminal.Gui/App/Application.Current.cs

@@ -1,18 +0,0 @@
-using System.Collections.Concurrent;
-
-namespace Terminal.Gui.App;
-
-public static partial class Application // Current handling
-{
-    /// <inheritdoc cref="IApplication.SessionStack"/>
-    [Obsolete ("The legacy static Application object is going away.")] public static ConcurrentStack<Toplevel> SessionStack => ApplicationImpl.Instance.SessionStack;
-
-    /// <summary>The <see cref="Toplevel"/> that is on the top of the <see cref="SessionStack"/>.</summary>
-    /// <value>The top runnable.</value>
-    [Obsolete ("The legacy static Application object is going away.")]
-    public static Toplevel? TopRunnable
-    {
-        get => ApplicationImpl.Instance.TopRunnable;
-        internal set => ApplicationImpl.Instance.TopRunnable = value;
-    }
-}

+ 21 - 15
Terminal.Gui/App/Application.Driver.cs

@@ -13,38 +13,44 @@ public static partial class Application // Driver abstractions
         internal set => ApplicationImpl.Instance.Driver = value;
         internal set => ApplicationImpl.Instance.Driver = value;
     }
     }
 
 
+    private static bool _force16Colors = false; // Resources/config.json overrides
+
     /// <inheritdoc cref="IApplication.Force16Colors"/>
     /// <inheritdoc cref="IApplication.Force16Colors"/>
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
     public static bool Force16Colors
     public static bool Force16Colors
     {
     {
-        get => ApplicationImpl.Instance.Force16Colors;
-        set => ApplicationImpl.Instance.Force16Colors = value;
+        get => _force16Colors;
+        set
+        {
+            bool oldValue = _force16Colors;
+            _force16Colors = value;
+            Force16ColorsChanged?.Invoke (null, new ValueChangedEventArgs<bool> (oldValue, _force16Colors));
+        }
     }
     }
 
 
+    /// <summary>Raised when <see cref="Force16Colors"/> changes.</summary>
+    public static event EventHandler<ValueChangedEventArgs<bool>>? Force16ColorsChanged;
+
+    private static string _forceDriver = string.Empty; // Resources/config.json overrides
+
     /// <inheritdoc cref="IApplication.ForceDriver"/>
     /// <inheritdoc cref="IApplication.ForceDriver"/>
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
     public static string ForceDriver
     public static string ForceDriver
     {
     {
-        get => ApplicationImpl.Instance.ForceDriver;
+        get => _forceDriver;
         set
         set
         {
         {
-            if (!string.IsNullOrEmpty (ApplicationImpl.Instance.ForceDriver) && value != Driver?.GetName ())
-            {
-                // ForceDriver cannot be changed if it has a valid value
-                return;
-            }
-
-            if (ApplicationImpl.Instance.Initialized && value != Driver?.GetName ())
-            {
-                throw new InvalidOperationException ($"The {nameof (ForceDriver)} can only be set before initialized.");
-            }
-
-            ApplicationImpl.Instance.ForceDriver = value;
+            string oldValue = _forceDriver;
+            _forceDriver = value;
+            ForceDriverChanged?.Invoke (null, new ValueChangedEventArgs<string> (oldValue, _forceDriver));
         }
         }
     }
     }
 
 
+    /// <summary>Raised when <see cref="ForceDriver"/> changes.</summary>
+    public static event EventHandler<ValueChangedEventArgs<string>>? ForceDriverChanged;
+
     /// <inheritdoc cref="IApplication.Sixel"/>
     /// <inheritdoc cref="IApplication.Sixel"/>
     [Obsolete ("The legacy static Application object is going away.")] 
     [Obsolete ("The legacy static Application object is going away.")] 
     public static List<SixelToRender> Sixel => ApplicationImpl.Instance.Sixel;
     public static List<SixelToRender> Sixel => ApplicationImpl.Instance.Sixel;

+ 20 - 6
Terminal.Gui/App/Application.Lifecycle.cs

@@ -18,7 +18,16 @@ public static partial class Application // Lifecycle (Init/Shutdown)
     ///     <see cref="IApplication"/> instance for all subsequent application operations.
     ///     <see cref="IApplication"/> instance for all subsequent application operations.
     /// </remarks>
     /// </remarks>
     /// <returns>A new <see cref="IApplication"/> instance.</returns>
     /// <returns>A new <see cref="IApplication"/> instance.</returns>
-    public static IApplication Create () { return new ApplicationImpl (); }
+    /// <exception cref="InvalidOperationException">
+    ///     Thrown if the legacy static Application model has already been used in this process.
+    /// </exception>
+    public static IApplication Create ()
+    {
+        //Debug.Fail ("Application.Create() called");
+        ApplicationImpl.MarkInstanceBasedModelUsed ();
+
+        return new ApplicationImpl ();
+    }
 
 
     /// <inheritdoc cref="IApplication.Init"/>
     /// <inheritdoc cref="IApplication.Init"/>
     [RequiresUnreferencedCode ("AOT")]
     [RequiresUnreferencedCode ("AOT")]
@@ -26,6 +35,7 @@ public static partial class Application // Lifecycle (Init/Shutdown)
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
     public static void Init (string? driverName = null)
     public static void Init (string? driverName = null)
     {
     {
+        //Debug.Fail ("Application.Init() called - parallelizable tests should not use legacy static Application model");
         ApplicationImpl.Instance.Init (driverName ?? ForceDriver);
         ApplicationImpl.Instance.Init (driverName ?? ForceDriver);
     }
     }
 
 
@@ -35,13 +45,13 @@ public static partial class Application // Lifecycle (Init/Shutdown)
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
     public static int? MainThreadId
     public static int? MainThreadId
     {
     {
-        get => ((ApplicationImpl)ApplicationImpl.Instance).MainThreadId;
-        set => ((ApplicationImpl)ApplicationImpl.Instance).MainThreadId = value;
+        get => ApplicationImpl.Instance.MainThreadId;
+        internal set => ApplicationImpl.Instance.MainThreadId = value;
     }
     }
 
 
-    /// <inheritdoc cref="IApplication.Shutdown"/>
+    /// <inheritdoc cref="IApplication.Dispose"/>
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
-    public static void Shutdown () => ApplicationImpl.Instance.Shutdown ();
+    public static void Shutdown () => ApplicationImpl.Instance.Dispose ();
 
 
     /// <inheritdoc cref="IApplication.Initialized"/>
     /// <inheritdoc cref="IApplication.Initialized"/>
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
@@ -65,5 +75,9 @@ public static partial class Application // Lifecycle (Init/Shutdown)
     // guaranteeing that the state of this singleton is deterministic when Init
     // guaranteeing that the state of this singleton is deterministic when Init
     // starts running and after Shutdown returns.
     // starts running and after Shutdown returns.
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
-    internal static void ResetState (bool ignoreDisposed = false) => ApplicationImpl.Instance?.ResetState (ignoreDisposed);
+    internal static void ResetState (bool ignoreDisposed = false)
+    {
+        // Use the static reset method to bypass the fence check
+        ApplicationImpl.ResetStateStatic (ignoreDisposed);
+    }
 }
 }

+ 12 - 2
Terminal.Gui/App/Application.Mouse.cs

@@ -4,15 +4,25 @@ namespace Terminal.Gui.App;
 
 
 public static partial class Application // Mouse handling
 public static partial class Application // Mouse handling
 {
 {
+    private static bool _isMouseDisabled = false; // Resources/config.json overrides
+
     /// <summary>Disable or enable the mouse. The mouse is enabled by default.</summary>
     /// <summary>Disable or enable the mouse. The mouse is enabled by default.</summary>
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
     public static bool IsMouseDisabled
     public static bool IsMouseDisabled
     {
     {
-        get => Mouse.IsMouseDisabled;
-        set => Mouse.IsMouseDisabled = value;
+        get => _isMouseDisabled;
+        set
+        {
+            bool oldValue = _isMouseDisabled;
+            _isMouseDisabled = value;
+            IsMouseDisabledChanged?.Invoke (null, new ValueChangedEventArgs<bool> (oldValue, _isMouseDisabled));
+        }
     }
     }
 
 
+    /// <summary>Raised when <see cref="IsMouseDisabled"/> changes.</summary>
+    public static event EventHandler<ValueChangedEventArgs<bool>>? IsMouseDisabledChanged;
+
     /// <summary>
     /// <summary>
     ///     Gets the <see cref="IMouse"/> instance that manages mouse event handling and state.
     ///     Gets the <see cref="IMouse"/> instance that manages mouse event handling and state.
     /// </summary>
     /// </summary>

+ 49 - 9
Terminal.Gui/App/Application.Navigation.cs

@@ -13,22 +13,42 @@ public static partial class Application // Navigation stuff
         internal set => ApplicationImpl.Instance.Navigation = value;
         internal set => ApplicationImpl.Instance.Navigation = value;
     }
     }
 
 
+    private static Key _nextTabGroupKey = Key.F6; // Resources/config.json overrides
+
     /// <summary>Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.</summary>
     /// <summary>Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.</summary>
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
-      [Obsolete ("The legacy static Application object is going away.")]public static Key NextTabGroupKey
+    public static Key NextTabGroupKey
     {
     {
-        get => ApplicationImpl.Instance.Keyboard.NextTabGroupKey;
-        set => ApplicationImpl.Instance.Keyboard.NextTabGroupKey = value;
+        get => _nextTabGroupKey;
+        set
+        {
+            Key oldValue = _nextTabGroupKey;
+            _nextTabGroupKey = value;
+            NextTabGroupKeyChanged?.Invoke (null, new ValueChangedEventArgs<Key> (oldValue, _nextTabGroupKey));
+        }
     }
     }
 
 
+    /// <summary>Raised when <see cref="NextTabGroupKey"/> changes.</summary>
+    public static event EventHandler<ValueChangedEventArgs<Key>>? NextTabGroupKeyChanged;
+
+    private static Key _nextTabKey = Key.Tab; // Resources/config.json overrides
+
     /// <summary>Alternative key to navigate forwards through views. Tab is the primary key.</summary>
     /// <summary>Alternative key to navigate forwards through views. Tab is the primary key.</summary>
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
     public static Key NextTabKey
     public static Key NextTabKey
     {
     {
-        get => ApplicationImpl.Instance.Keyboard.NextTabKey;
-        set => ApplicationImpl.Instance.Keyboard.NextTabKey = value;
+        get => _nextTabKey;
+        set
+        {
+            Key oldValue = _nextTabKey;
+            _nextTabKey = value;
+            NextTabKeyChanged?.Invoke (null, new ValueChangedEventArgs<Key> (oldValue, _nextTabKey));
+        }
     }
     }
 
 
+    /// <summary>Raised when <see cref="NextTabKey"/> changes.</summary>
+    public static event EventHandler<ValueChangedEventArgs<Key>>? NextTabKeyChanged;
+
     /// <summary>
     /// <summary>
     ///     Raised when the user releases a key.
     ///     Raised when the user releases a key.
     ///     <para>
     ///     <para>
@@ -48,19 +68,39 @@ public static partial class Application // Navigation stuff
         remove => ApplicationImpl.Instance.Keyboard.KeyUp -= value;
         remove => ApplicationImpl.Instance.Keyboard.KeyUp -= value;
     }
     }
 
 
+    private static Key _prevTabGroupKey = Key.F6.WithShift; // Resources/config.json overrides
+
     /// <summary>Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.</summary>
     /// <summary>Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.</summary>
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
     public static Key PrevTabGroupKey
     public static Key PrevTabGroupKey
     {
     {
-        get => ApplicationImpl.Instance.Keyboard.PrevTabGroupKey;
-        set => ApplicationImpl.Instance.Keyboard.PrevTabGroupKey = value;
+        get => _prevTabGroupKey;
+        set
+        {
+            Key oldValue = _prevTabGroupKey;
+            _prevTabGroupKey = value;
+            PrevTabGroupKeyChanged?.Invoke (null, new ValueChangedEventArgs<Key> (oldValue, _prevTabGroupKey));
+        }
     }
     }
 
 
+    /// <summary>Raised when <see cref="PrevTabGroupKey"/> changes.</summary>
+    public static event EventHandler<ValueChangedEventArgs<Key>>? PrevTabGroupKeyChanged;
+
+    private static Key _prevTabKey = Key.Tab.WithShift; // Resources/config.json overrides
+
     /// <summary>Alternative key to navigate backwards through views. Shift+Tab is the primary key.</summary>
     /// <summary>Alternative key to navigate backwards through views. Shift+Tab is the primary key.</summary>
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
     public static Key PrevTabKey
     public static Key PrevTabKey
     {
     {
-        get => ApplicationImpl.Instance.Keyboard.PrevTabKey;
-        set => ApplicationImpl.Instance.Keyboard.PrevTabKey = value;
+        get => _prevTabKey;
+        set
+        {
+            Key oldValue = _prevTabKey;
+            _prevTabKey = value;
+            PrevTabKeyChanged?.Invoke (null, new ValueChangedEventArgs<Key> (oldValue, _prevTabKey));
+        }
     }
     }
+
+    /// <summary>Raised when <see cref="PrevTabKey"/> changes.</summary>
+    public static event EventHandler<ValueChangedEventArgs<Key>>? PrevTabKeyChanged;
 }
 }

+ 36 - 22
Terminal.Gui/App/Application.Run.cs

@@ -4,46 +4,60 @@ namespace Terminal.Gui.App;
 
 
 public static partial class Application // Run (Begin -> Run -> Layout/Draw -> End -> Stop)
 public static partial class Application // Run (Begin -> Run -> Layout/Draw -> End -> Stop)
 {
 {
+    private static Key _quitKey = Key.Esc; // Resources/config.json overrides
+
     /// <summary>Gets or sets the key to quit the application.</summary>
     /// <summary>Gets or sets the key to quit the application.</summary>
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
     public static Key QuitKey
     public static Key QuitKey
     {
     {
-        get => ApplicationImpl.Instance.Keyboard.QuitKey;
-        set => ApplicationImpl.Instance.Keyboard.QuitKey = value;
+        get => _quitKey;
+        set
+        {
+            Key oldValue = _quitKey;
+            _quitKey = value;
+            QuitKeyChanged?.Invoke (null, new ValueChangedEventArgs<Key> (oldValue, _quitKey));
+        }
     }
     }
 
 
+    /// <summary>Raised when <see cref="QuitKey"/> changes.</summary>
+    public static event EventHandler<ValueChangedEventArgs<Key>>? QuitKeyChanged;
+
+    private static Key _arrangeKey = Key.F5.WithCtrl; // Resources/config.json overrides
+
     /// <summary>Gets or sets the key to activate arranging views using the keyboard.</summary>
     /// <summary>Gets or sets the key to activate arranging views using the keyboard.</summary>
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
     [ConfigurationProperty (Scope = typeof (SettingsScope))]
     public static Key ArrangeKey
     public static Key ArrangeKey
     {
     {
-        get => ApplicationImpl.Instance.Keyboard.ArrangeKey;
-        set => ApplicationImpl.Instance.Keyboard.ArrangeKey = value;
+        get => _arrangeKey;
+        set
+        {
+            Key oldValue = _arrangeKey;
+            _arrangeKey = value;
+            ArrangeKeyChanged?.Invoke (null, new ValueChangedEventArgs<Key> (oldValue, _arrangeKey));
+        }
     }
     }
 
 
+    /// <summary>Raised when <see cref="ArrangeKey"/> changes.</summary>
+    public static event EventHandler<ValueChangedEventArgs<Key>>? ArrangeKeyChanged;
+
     /// <inheritdoc cref="IApplication.Begin(IRunnable)"/>
     /// <inheritdoc cref="IApplication.Begin(IRunnable)"/>
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
-    public static SessionToken Begin (Toplevel toplevel) => ApplicationImpl.Instance.Begin (toplevel);
+    public static SessionToken Begin (IRunnable runnable) => ApplicationImpl.Instance.Begin (runnable)!;
 
 
     /// <inheritdoc cref="IApplication.PositionCursor"/>
     /// <inheritdoc cref="IApplication.PositionCursor"/>
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
     public static bool PositionCursor () => ApplicationImpl.Instance.PositionCursor ();
     public static bool PositionCursor () => ApplicationImpl.Instance.PositionCursor ();
 
 
-    /// <inheritdoc cref="IApplication.Run(Func{Exception, bool}, string)"/>
-    [RequiresUnreferencedCode ("AOT")]
-    [RequiresDynamicCode ("AOT")]
-    [Obsolete ("The legacy static Application object is going away.")]
-    public static Toplevel Run (Func<Exception, bool>? errorHandler = null, string? driverName = null) => ApplicationImpl.Instance.Run (errorHandler, driverName);
-
-    /// <inheritdoc cref="IApplication.Run{TView}(Func{Exception, bool}, string)"/>
+    /// <inheritdoc cref="IApplication.Run{TRunnable}(Func{Exception, bool}, string)"/>
     [RequiresUnreferencedCode ("AOT")]
     [RequiresUnreferencedCode ("AOT")]
     [RequiresDynamicCode ("AOT")]
     [RequiresDynamicCode ("AOT")]
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
-    public static TView Run<TView> (Func<Exception, bool>? errorHandler = null, string? driverName = null)
-        where TView : Toplevel, new() => ApplicationImpl.Instance.Run<TView> (errorHandler, driverName);
+    public static IApplication Run<TRunnable> (Func<Exception, bool>? errorHandler = null, string? driverName = null)
+        where TRunnable : IRunnable, new() => ApplicationImpl.Instance.Run<TRunnable> (errorHandler, driverName);
 
 
-    /// <inheritdoc cref="IApplication.Run(Toplevel, Func{Exception, bool})"/>
+    /// <inheritdoc cref="IApplication.Run(IRunnable, Func{Exception, bool})"/>
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
-    public static void Run (Toplevel view, Func<Exception, bool>? errorHandler = null) => ApplicationImpl.Instance.Run (view, errorHandler);
+    public static void Run (IRunnable runnable, Func<Exception, bool>? errorHandler = null) => ApplicationImpl.Instance.Run (runnable, errorHandler);
 
 
     /// <inheritdoc cref="IApplication.AddTimeout"/>
     /// <inheritdoc cref="IApplication.AddTimeout"/>
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
@@ -56,7 +70,7 @@ public static partial class Application // Run (Begin -> Run -> Layout/Draw -> E
     /// <inheritdoc cref="IApplication.TimedEvents"/>
     /// <inheritdoc cref="IApplication.TimedEvents"/>
     /// 
     /// 
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
-    public static ITimedEvents? TimedEvents => ApplicationImpl.Instance?.TimedEvents;
+    public static ITimedEvents? TimedEvents => ApplicationImpl.Instance.TimedEvents;
 
 
     /// <inheritdoc cref="IApplication.Invoke(Action{IApplication})"/>
     /// <inheritdoc cref="IApplication.Invoke(Action{IApplication})"/>
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
@@ -78,17 +92,17 @@ public static partial class Application // Run (Begin -> Run -> Layout/Draw -> E
         set => ApplicationImpl.Instance.StopAfterFirstIteration = value;
         set => ApplicationImpl.Instance.StopAfterFirstIteration = value;
     }
     }
 
 
-    /// <inheritdoc cref="IApplication.RequestStop(Toplevel)"/>
+    /// <inheritdoc cref="IApplication.RequestStop(IRunnable)"/>
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
-    public static void RequestStop (Toplevel? top = null) => ApplicationImpl.Instance.RequestStop (top);
+    public static void RequestStop (IRunnable? runnable = null) => ApplicationImpl.Instance.RequestStop (runnable);
 
 
-    /// <inheritdoc cref="IApplication.End(RunnableSessionToken)"/>
+    /// <inheritdoc cref="IApplication.End(SessionToken)"/>
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
     public static void End (SessionToken sessionToken) => ApplicationImpl.Instance.End (sessionToken);
     public static void End (SessionToken sessionToken) => ApplicationImpl.Instance.End (sessionToken);
 
 
     /// <inheritdoc cref="IApplication.Iteration"/>
     /// <inheritdoc cref="IApplication.Iteration"/>
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
-    public static event EventHandler<IterationEventArgs>? Iteration
+    public static event EventHandler<EventArgs<IApplication?>>? Iteration
     {
     {
         add => ApplicationImpl.Instance.Iteration += value;
         add => ApplicationImpl.Instance.Iteration += value;
         remove => ApplicationImpl.Instance.Iteration -= value;
         remove => ApplicationImpl.Instance.Iteration -= value;
@@ -104,7 +118,7 @@ public static partial class Application // Run (Begin -> Run -> Layout/Draw -> E
 
 
     /// <inheritdoc cref="IApplication.SessionEnded"/>
     /// <inheritdoc cref="IApplication.SessionEnded"/>
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]
-    public static event EventHandler<ToplevelEventArgs>? SessionEnded
+    public static event EventHandler<SessionTokenEventArgs>? SessionEnded
     {
     {
         add => ApplicationImpl.Instance.SessionEnded += value;
         add => ApplicationImpl.Instance.SessionEnded += value;
         remove => ApplicationImpl.Instance.SessionEnded -= value;
         remove => ApplicationImpl.Instance.SessionEnded -= value;

+ 0 - 8
Terminal.Gui/App/Application.Screen.cs

@@ -12,14 +12,6 @@ public static partial class Application // Screen related stuff; intended to hid
         set => ApplicationImpl.Instance.Screen = value;
         set => ApplicationImpl.Instance.Screen = value;
     }
     }
 
 
-    /// <inheritdoc cref="IApplication.ScreenChanged"/>
-    [Obsolete ("The legacy static Application object is going away.")]
-    public static event EventHandler<EventArgs<Rectangle>>? ScreenChanged
-    {
-        add => ApplicationImpl.Instance.ScreenChanged += value;
-        remove => ApplicationImpl.Instance.ScreenChanged -= value;
-    }
-
     /// <inheritdoc cref="IApplication.ClearScreenNextIteration"/>
     /// <inheritdoc cref="IApplication.ClearScreenNextIteration"/>
 
 
     [Obsolete ("The legacy static Application object is going away.")]
     [Obsolete ("The legacy static Application object is going away.")]

+ 16 - 0
Terminal.Gui/App/Application.TopRunnable.cs

@@ -0,0 +1,16 @@
+using System.Collections.Concurrent;
+
+namespace Terminal.Gui.App;
+
+public static partial class Application // TopRunnable handling
+{
+    /// <summary>The <see cref="View"/> that is on the top of the <see cref="IApplication.SessionStack"/>.</summary>
+    /// <value>The top runnable.</value>
+    [Obsolete ("The legacy static Application object is going away.")]
+    public static View? TopRunnableView => ApplicationImpl.Instance.TopRunnableView;
+
+    /// <summary>The <see cref="View"/> that is on the top of the <see cref="IApplication.SessionStack"/>.</summary>
+    /// <value>The top runnable.</value>
+    [Obsolete ("The legacy static Application object is going away.")]
+    public static IRunnable? TopRunnable => ApplicationImpl.Instance.TopRunnable;
+}

+ 182 - 80
Terminal.Gui/App/ApplicationImpl.Lifecycle.cs

@@ -5,6 +5,9 @@ namespace Terminal.Gui.App;
 
 
 public partial class ApplicationImpl
 public partial class ApplicationImpl
 {
 {
+    /// <inheritdoc/>
+    public int? MainThreadId { get; set; }
+
     /// <inheritdoc/>
     /// <inheritdoc/>
     public bool Initialized { get; set; }
     public bool Initialized { get; set; }
 
 
@@ -23,6 +26,29 @@ public partial class ApplicationImpl
             throw new InvalidOperationException ("Init called multiple times without Shutdown");
             throw new InvalidOperationException ("Init called multiple times without Shutdown");
         }
         }
 
 
+        // Thread-safe fence check: Ensure we're not mixing application models
+        // Use lock to make check-and-set atomic
+        lock (_modelUsageLock)
+        {
+            // If this is a legacy static instance and instance-based model was used, throw
+            if (this == _instance && ModelUsage == ApplicationModelUsage.InstanceBased)
+            {
+                throw new InvalidOperationException (ERROR_LEGACY_AFTER_MODERN);
+            }
+
+            // If this is an instance-based instance and legacy static model was used, throw
+            if (this != _instance && ModelUsage == ApplicationModelUsage.LegacyStatic)
+            {
+                throw new InvalidOperationException (ERROR_MODERN_AFTER_LEGACY);
+            }
+
+            // If no model has been set yet, set it now based on which instance this is
+            if (ModelUsage == ApplicationModelUsage.None)
+            {
+                ModelUsage = this == _instance ? ApplicationModelUsage.LegacyStatic : ApplicationModelUsage.InstanceBased;
+            }
+        }
+
         if (!string.IsNullOrWhiteSpace (driverName))
         if (!string.IsNullOrWhiteSpace (driverName))
         {
         {
             _driverName = driverName;
             _driverName = driverName;
@@ -41,26 +67,24 @@ public partial class ApplicationImpl
 
 
         // Preserve existing keyboard settings if they exist
         // Preserve existing keyboard settings if they exist
         bool hasExistingKeyboard = _keyboard is { };
         bool hasExistingKeyboard = _keyboard is { };
-        Key existingQuitKey = _keyboard?.QuitKey ?? Key.Esc;
-        Key existingArrangeKey = _keyboard?.ArrangeKey ?? Key.F5.WithCtrl;
-        Key existingNextTabKey = _keyboard?.NextTabKey ?? Key.Tab;
-        Key existingPrevTabKey = _keyboard?.PrevTabKey ?? Key.Tab.WithShift;
-        Key existingNextTabGroupKey = _keyboard?.NextTabGroupKey ?? Key.F6;
-        Key existingPrevTabGroupKey = _keyboard?.PrevTabGroupKey ?? Key.F6.WithShift;
+        Key existingQuitKey = _keyboard?.QuitKey ?? Application.QuitKey;
+        Key existingArrangeKey = _keyboard?.ArrangeKey ?? Application.ArrangeKey;
+        Key existingNextTabKey = _keyboard?.NextTabKey ?? Application.NextTabKey;
+        Key existingPrevTabKey = _keyboard?.PrevTabKey ?? Application.PrevTabKey;
+        Key existingNextTabGroupKey = _keyboard?.NextTabGroupKey ?? Application.NextTabGroupKey;
+        Key existingPrevTabGroupKey = _keyboard?.PrevTabGroupKey ?? Application.PrevTabGroupKey;
 
 
         // Reset keyboard to ensure fresh state with default bindings
         // Reset keyboard to ensure fresh state with default bindings
         _keyboard = new KeyboardImpl { App = this };
         _keyboard = new KeyboardImpl { App = this };
 
 
-        // Restore previously set keys if they existed and were different from defaults
-        if (hasExistingKeyboard)
-        {
-            _keyboard.QuitKey = existingQuitKey;
-            _keyboard.ArrangeKey = existingArrangeKey;
-            _keyboard.NextTabKey = existingNextTabKey;
-            _keyboard.PrevTabKey = existingPrevTabKey;
-            _keyboard.NextTabGroupKey = existingNextTabGroupKey;
-            _keyboard.PrevTabGroupKey = existingPrevTabGroupKey;
-        }
+        // Sync keys from Application static properties (or existing keyboard if it had custom values)
+        // This ensures we respect any Application.QuitKey etc changes made before Init()
+        _keyboard.QuitKey = existingQuitKey;
+        _keyboard.ArrangeKey = existingArrangeKey;
+        _keyboard.NextTabKey = existingNextTabKey;
+        _keyboard.PrevTabKey = existingPrevTabKey;
+        _keyboard.NextTabGroupKey = existingNextTabGroupKey;
+        _keyboard.PrevTabGroupKey = existingPrevTabGroupKey;
 
 
         CreateDriver (_driverName);
         CreateDriver (_driverName);
         Screen = Driver!.Screen;
         Screen = Driver!.Screen;
@@ -72,23 +96,75 @@ public partial class ApplicationImpl
         SynchronizationContext.SetSynchronizationContext (new ());
         SynchronizationContext.SetSynchronizationContext (new ());
         MainThreadId = Thread.CurrentThread.ManagedThreadId;
         MainThreadId = Thread.CurrentThread.ManagedThreadId;
 
 
+        _result = null;
+
         return this;
         return this;
     }
     }
 
 
-    /// <summary>Shutdown an application initialized with <see cref="Init"/>.</summary>
-    public object? Shutdown ()
+    #region IDisposable Implementation
+
+    private bool _disposed;
+
+    /// <summary>
+    ///     Disposes the application instance and releases all resources.
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         This method implements the <see cref="IDisposable"/> pattern and performs the same cleanup
+    ///         as <see cref="IDisposable.Dispose"/>, but without returning a result.
+    ///     </para>
+    ///     <para>
+    ///         After calling <see cref="Dispose()"/>, use <see cref="GetResult"/> or <see cref="IApplication.GetResult{T}"/>
+    ///         to retrieve the result from the last run session.
+    ///     </para>
+    /// </remarks>
+    public void Dispose ()
+    {
+        Dispose (true);
+        GC.SuppressFinalize (this);
+    }
+
+    /// <summary>
+    ///     Disposes the application instance and releases all resources.
+    /// </summary>
+    /// <param name="disposing">
+    ///     <see langword="true"/> if called from <see cref="Dispose()"/>;
+    ///     <see langword="false"/> if called from finalizer.
+    /// </param>
+    protected virtual void Dispose (bool disposing)
     {
     {
-        // Extract result from framework-owned runnable before disposal
-        object? result = null;
-        IRunnable? runnableToDispose = FrameworkOwnedRunnable;
+        if (_disposed)
+        {
+            return;
+        }
+
+        if (disposing)
+        {
+            // Dispose managed resources
+            DisposeCore ();
+        }
 
 
-        if (runnableToDispose is { })
+        // For the singleton instance (legacy Application.Init/Shutdown pattern),
+        // we need to allow re-initialization after disposal. This enables:
+        // Application.Init() -> Application.Shutdown() -> Application.Init()
+        // For modern instance-based usage, this doesn't matter as new instances are created.
+        if (this == _instance)
+        {
+            // Reset disposed flag to allow re-initialization
+            _disposed = false;
+        }
+        else
         {
         {
-            // Extract the result using reflection to get the Result property value
-            var resultProperty = runnableToDispose.GetType().GetProperty("Result");
-            result = resultProperty?.GetValue(runnableToDispose);
+            // For instance-based usage, mark as disposed
+            _disposed = true;
         }
         }
+    }
 
 
+    /// <summary>
+    ///     Core disposal logic - same as Shutdown() but without returning result.
+    /// </summary>
+    private void DisposeCore ()
+    {
         // Stop the coordinator if running
         // Stop the coordinator if running
         Coordinator?.Stop ();
         Coordinator?.Stop ();
 
 
@@ -110,16 +186,6 @@ public partial class ApplicationImpl
         }
         }
 #endif
 #endif
 
 
-        // Dispose the framework-owned runnable if it exists
-        if (runnableToDispose is { })
-        {
-            if (runnableToDispose is IDisposable disposable)
-            {
-                disposable.Dispose();
-            }
-            FrameworkOwnedRunnable = null;
-        }
-
         // Clean up all application state (including sync context)
         // Clean up all application state (including sync context)
         // ResetState handles the case where Initialized is false
         // ResetState handles the case where Initialized is false
         ResetState ();
         ResetState ();
@@ -136,39 +202,25 @@ public partial class ApplicationImpl
 
 
         // Clear the event to prevent memory leaks
         // Clear the event to prevent memory leaks
         InitializedChanged = null;
         InitializedChanged = null;
-
-        return result;
     }
     }
 
 
-#if DEBUG
-    /// <summary>
-    ///     DEBUG ONLY: Asserts that an event has no remaining subscribers.
-    /// </summary>
-    /// <param name="eventName">The name of the event for diagnostic purposes.</param>
-    /// <param name="eventDelegate">The event delegate to check.</param>
-    private static void AssertNoEventSubscribers (string eventName, Delegate? eventDelegate)
+    #endregion IDisposable Implementation
+
+    /// <summary>Shutdown an application initialized with <see cref="Init"/>.</summary>
+    [Obsolete ("Use Dispose() or a using statement instead. This method will be removed in a future version.")]
+    public object? Shutdown ()
     {
     {
-        if (eventDelegate is null)
-        {
-            return;
-        }
+        // Shutdown is now just a wrapper around Dispose that returns the result
+        object? result = GetResult ();
+        Dispose ();
 
 
-        Delegate [] subscribers = eventDelegate.GetInvocationList ();
+        return result;
+    }
 
 
-        if (subscribers.Length > 0)
-        {
-            string subscriberInfo = string.Join (
-                                                 ", ",
-                                                 subscribers.Select (d => $"{d.Method.DeclaringType?.Name}.{d.Method.Name}"
-                                                                    )
-                                                );
+    private object? _result;
 
 
-            Debug.Fail (
-                        $"Application.{eventName} has {subscribers.Length} remaining subscriber(s) after Shutdown: {subscriberInfo}"
-                       );
-        }
-    }
-#endif
+    /// <inheritdoc/>
+    public object? GetResult () => _result;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
     public void ResetState (bool ignoreDisposed = false)
     public void ResetState (bool ignoreDisposed = false)
@@ -180,10 +232,13 @@ public partial class ApplicationImpl
         // === 0. Stop all timers ===
         // === 0. Stop all timers ===
         TimedEvents?.StopAll ();
         TimedEvents?.StopAll ();
 
 
-        // === 1. Stop all running toplevels ===
-        foreach (Toplevel t in SessionStack)
+        // === 1. Stop all running runnables ===
+        foreach (SessionToken token in SessionStack!.Reverse ())
         {
         {
-            t.Running = false;
+            if (token.Runnable is { })
+            {
+                End (token);
+            }
         }
         }
 
 
         // === 2. Close and dispose popover ===
         // === 2. Close and dispose popover ===
@@ -198,29 +253,18 @@ public partial class ApplicationImpl
         Popover?.Dispose ();
         Popover?.Dispose ();
         Popover = null;
         Popover = null;
 
 
-        // === 3. Clean up toplevels ===
-        SessionStack.Clear ();
-        RunnableSessionStack?.Clear ();
+        // === 3. Clean up runnables ===
+        SessionStack?.Clear ();
 
 
 #if DEBUG_IDISPOSABLE
 #if DEBUG_IDISPOSABLE
 
 
         // Don't dispose the TopRunnable. It's up to caller dispose it
         // Don't dispose the TopRunnable. It's up to caller dispose it
-        if (View.EnableDebugIDisposableAsserts && !ignoreDisposed && TopRunnable is { })
+        if (View.EnableDebugIDisposableAsserts && !ignoreDisposed && TopRunnableView is { })
         {
         {
-            Debug.Assert (TopRunnable.WasDisposed, $"Title = {TopRunnable.Title}, Id = {TopRunnable.Id}");
-
-            // If End wasn't called _CachedSessionTokenToplevel may be null
-            if (CachedSessionTokenToplevel is { })
-            {
-                Debug.Assert (CachedSessionTokenToplevel.WasDisposed);
-                Debug.Assert (CachedSessionTokenToplevel == TopRunnable);
-            }
+            Debug.Assert (TopRunnableView.WasDisposed, $"Title = {TopRunnableView.Title}, Id = {TopRunnableView.Id}");
         }
         }
 #endif
 #endif
 
 
-        TopRunnable = null;
-        CachedSessionTokenToplevel = null;
-
         // === 4. Clean up driver ===
         // === 4. Clean up driver ===
         if (Driver is { })
         if (Driver is { })
         {
         {
@@ -241,6 +285,17 @@ public partial class ApplicationImpl
         ClearScreenNextIteration = false;
         ClearScreenNextIteration = false;
 
 
         // === 6. Reset input systems ===
         // === 6. Reset input systems ===
+        // Dispose keyboard and mouse to unsubscribe from events
+        if (_keyboard is IDisposable keyboardDisposable)
+        {
+            keyboardDisposable.Dispose ();
+        }
+
+        if (_mouse is IDisposable mouseDisposable)
+        {
+            mouseDisposable.Dispose ();
+        }
+
         // Mouse and Keyboard will be lazy-initialized on next access
         // Mouse and Keyboard will be lazy-initialized on next access
         _mouse = null;
         _mouse = null;
         _keyboard = null;
         _keyboard = null;
@@ -273,10 +328,57 @@ public partial class ApplicationImpl
         // gui.cs does no longer process any callbacks. See #1084 for more details:
         // gui.cs does no longer process any callbacks. See #1084 for more details:
         // (https://github.com/gui-cs/Terminal.Gui/issues/1084).
         // (https://github.com/gui-cs/Terminal.Gui/issues/1084).
         SynchronizationContext.SetSynchronizationContext (null);
         SynchronizationContext.SetSynchronizationContext (null);
+
+        // === 12. Unsubscribe from Application static property change events ===
+        UnsubscribeApplicationEvents ();
     }
     }
 
 
     /// <summary>
     /// <summary>
     ///     Raises the <see cref="InitializedChanged"/> event.
     ///     Raises the <see cref="InitializedChanged"/> event.
     /// </summary>
     /// </summary>
     internal void RaiseInitializedChanged (object sender, EventArgs<bool> e) { InitializedChanged?.Invoke (sender, e); }
     internal void RaiseInitializedChanged (object sender, EventArgs<bool> e) { InitializedChanged?.Invoke (sender, e); }
+
+#if DEBUG
+    /// <summary>
+    ///     DEBUG ONLY: Asserts that an event has no remaining subscribers.
+    /// </summary>
+    /// <param name="eventName">The name of the event for diagnostic purposes.</param>
+    /// <param name="eventDelegate">The event delegate to check.</param>
+    private static void AssertNoEventSubscribers (string eventName, Delegate? eventDelegate)
+    {
+        if (eventDelegate is null)
+        {
+            return;
+        }
+
+        Delegate [] subscribers = eventDelegate.GetInvocationList ();
+
+        if (subscribers.Length > 0)
+        {
+            string subscriberInfo = string.Join (
+                                                 ", ",
+                                                 subscribers.Select (d => $"{d.Method.DeclaringType?.Name}.{d.Method.Name}"
+                                                                    )
+                                                );
+
+            Debug.Fail (
+                        $"Application.{eventName} has {subscribers.Length} remaining subscriber(s) after Shutdown: {subscriberInfo}"
+                       );
+        }
+    }
+#endif
+
+    // Event handlers for Application static property changes
+    private void OnForce16ColorsChanged (object? sender, ValueChangedEventArgs<bool> e) { Force16Colors = e.NewValue; }
+
+    private void OnForceDriverChanged (object? sender, ValueChangedEventArgs<string> e) { ForceDriver = e.NewValue; }
+
+    /// <summary>
+    ///     Unsubscribes from Application static property change events.
+    /// </summary>
+    private void UnsubscribeApplicationEvents ()
+    {
+        Application.Force16ColorsChanged -= OnForce16ColorsChanged;
+        Application.ForceDriverChanged -= OnForceDriverChanged;
+    }
 }
 }

+ 171 - 432
Terminal.Gui/App/ApplicationImpl.Run.cs

@@ -1,321 +1,44 @@
-using System.Diagnostics;
+using System.Collections.Concurrent;
 using System.Diagnostics.CodeAnalysis;
 using System.Diagnostics.CodeAnalysis;
 
 
 namespace Terminal.Gui.App;
 namespace Terminal.Gui.App;
 
 
 public partial class ApplicationImpl
 public partial class ApplicationImpl
 {
 {
-    /// <summary>
-    ///     INTERNAL: Gets or sets the managed thread ID of the application's main UI thread, which is set during
-    ///     <see cref="Init"/> and used to determine if code is executing on the main thread.
-    /// </summary>
-    /// <value>
-    ///     The managed thread ID of the main UI thread, or <see langword="null"/> if the application is not initialized.
-    /// </value>
-    internal int? MainThreadId { get; set; }
-
-    #region Begin->Run->Stop->End
-
-    // TODO: This API is not used anywhere; it can be deleted
-    /// <inheritdoc/>
-    public event EventHandler<SessionTokenEventArgs>? SessionBegun;
-
-    // TODO: This API is not used anywhere; it can be deleted
-    /// <inheritdoc/>
-    public event EventHandler<ToplevelEventArgs>? SessionEnded;
-
-    /// <inheritdoc/>
-    public SessionToken Begin (Toplevel toplevel)
-    {
-        ArgumentNullException.ThrowIfNull (toplevel);
-
-        // Ensure the mouse is ungrabbed.
-        if (Mouse.MouseGrabView is { })
-        {
-            Mouse.UngrabMouse ();
-        }
-
-        var rs = new SessionToken (toplevel);
-
-#if DEBUG_IDISPOSABLE
-        if (View.EnableDebugIDisposableAsserts && TopRunnable is { } && toplevel != TopRunnable && !SessionStack.Contains (TopRunnable))
-        {
-            // This assertion confirm if the TopRunnable was already disposed
-            Debug.Assert (TopRunnable.WasDisposed);
-            Debug.Assert (TopRunnable == CachedSessionTokenToplevel);
-        }
-#endif
-
-        lock (SessionStack)
-        {
-            if (TopRunnable is { } && toplevel != TopRunnable && !SessionStack.Contains (TopRunnable))
-            {
-                // If TopRunnable was already disposed and isn't on the Toplevels Stack,
-                // clean it up here if is the same as _CachedSessionTokenToplevel
-                if (TopRunnable == CachedSessionTokenToplevel)
-                {
-                    TopRunnable = null;
-                }
-                else
-                {
-                    // Probably this will never hit
-                    throw new ObjectDisposedException (TopRunnable.GetType ().FullName);
-                }
-            }
-
-            // BUGBUG: We should not depend on `Id` internally.
-            // BUGBUG: It is super unclear what this code does anyway.
-            if (string.IsNullOrEmpty (toplevel.Id))
-            {
-                var count = 1;
-                var id = (SessionStack.Count + count).ToString ();
-
-                while (SessionStack.Count > 0 && SessionStack.FirstOrDefault (x => x.Id == id) is { })
-                {
-                    count++;
-                    id = (SessionStack.Count + count).ToString ();
-                }
-
-                toplevel.Id = (SessionStack.Count + count).ToString ();
-
-                SessionStack.Push (toplevel);
-            }
-            else
-            {
-                Toplevel? dup = SessionStack.FirstOrDefault (x => x.Id == toplevel.Id);
-
-                if (dup is null)
-                {
-                    SessionStack.Push (toplevel);
-                }
-            }
-        }
-
-        if (TopRunnable is null)
-        {
-            toplevel.App = this;
-            TopRunnable = toplevel;
-        }
-
-        if ((TopRunnable?.Modal == false && toplevel.Modal)
-            || (TopRunnable?.Modal == false && !toplevel.Modal)
-            || (TopRunnable?.Modal == true && toplevel.Modal))
-        {
-            if (toplevel.Visible)
-            {
-                if (TopRunnable is { HasFocus: true })
-                {
-                    TopRunnable.HasFocus = false;
-                }
-
-                // Force leave events for any entered views in the old TopRunnable
-                if (Mouse.LastMousePosition is { })
-                {
-                    Mouse.RaiseMouseEnterLeaveEvents (Mouse.LastMousePosition!.Value, new ());
-                }
-
-                TopRunnable?.OnDeactivate (toplevel);
-                Toplevel previousTop = TopRunnable!;
-
-                TopRunnable = toplevel;
-                TopRunnable.App = this;
-                TopRunnable.OnActivate (previousTop);
-            }
-        }
-
-        // View implements ISupportInitializeNotification which is derived from ISupportInitialize
-        if (!toplevel.IsInitialized)
-        {
-            toplevel.BeginInit ();
-            toplevel.EndInit (); // Calls Layout
-        }
-
-        // Try to set initial focus to any TabStop
-        if (!toplevel.HasFocus)
-        {
-            toplevel.SetFocus ();
-        }
-
-        toplevel.OnLoaded ();
-
-        LayoutAndDraw (true);
-
-        if (PositionCursor ())
-        {
-            Driver?.UpdateCursor ();
-        }
-
-        SessionBegun?.Invoke (this, new (rs));
-
-        return rs;
-    }
+    // Lock object to protect session stack operations and cached state updates
+    private readonly object _sessionStackLock = new ();
 
 
-    /// <inheritdoc/>
-    public bool StopAfterFirstIteration { get; set; }
+    #region Session State - Stack and TopRunnable
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public void RaiseIteration ()
-    {
-        Iteration?.Invoke (null, new ());
-    }
+    public ConcurrentStack<SessionToken>? SessionStack { get; } = new ();
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public event EventHandler<IterationEventArgs>? Iteration;
+    public IRunnable? TopRunnable { get; private set; }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    [RequiresUnreferencedCode ("AOT")]
-    [RequiresDynamicCode ("AOT")]
-    public Toplevel Run (Func<Exception, bool>? errorHandler = null, string? driverName = null) => Run<Toplevel> (errorHandler, driverName);
+    public View? TopRunnableView => TopRunnable as View;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    [RequiresUnreferencedCode ("AOT")]
-    [RequiresDynamicCode ("AOT")]
-    public TView Run<TView> (Func<Exception, bool>? errorHandler = null, string? driverName = null)
-        where TView : Toplevel, new ()
-    {
-        if (!Initialized)
-        {
-            // Init() has NOT been called. Auto-initialize as per interface contract.
-            Init (driverName);
-        }
-
-        TView top = new ();
-        Run (top, errorHandler);
-
-        return top;
-    }
+    public event EventHandler<SessionTokenEventArgs>? SessionBegun;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public void Run (Toplevel view, Func<Exception, bool>? errorHandler = null)
-    {
-        Logging.Information ($"Run '{view}'");
-        ArgumentNullException.ThrowIfNull (view);
-
-        if (!Initialized)
-        {
-            throw new NotInitializedException (nameof (Run));
-        }
-
-        if (Driver == null)
-        {
-            throw new InvalidOperationException ("Driver was inexplicably null when trying to Run view");
-        }
-
-        TopRunnable = view;
+    public event EventHandler<SessionTokenEventArgs>? SessionEnded;
 
 
-        SessionToken rs = Begin (view);
+    #endregion Session State - Stack and TopRunnable
 
 
-        TopRunnable.Running = true;
-
-        var firstIteration = true;
-
-        while (SessionStack.TryPeek (out Toplevel? found) && found == view && view.Running)
-        {
-            if (Coordinator is null)
-            {
-                throw new ($"{nameof (IMainLoopCoordinator)} inexplicably became null during Run");
-            }
-
-            Coordinator.RunIteration ();
-
-            if (StopAfterFirstIteration && firstIteration)
-            {
-                Logging.Information ("Run - Stopping after first iteration as requested");
-                RequestStop ((Toplevel?)view);
-            }
-
-            firstIteration = false;
-        }
-
-        Logging.Information ("Run - Calling End");
-        End (rs);
-    }
+    #region Main Loop Iteration
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public void End (SessionToken sessionToken)
-    {
-        ArgumentNullException.ThrowIfNull (sessionToken);
-
-        if (Popover?.GetActivePopover () as View is { Visible: true } visiblePopover)
-        {
-            ApplicationPopover.HideWithQuitCommand (visiblePopover);
-        }
-
-        sessionToken.Toplevel?.OnUnloaded ();
-
-        // End the Session
-        // First, take it off the Toplevel Stack
-        if (SessionStack.TryPop (out Toplevel? topOfStack))
-        {
-            if (topOfStack != sessionToken.Toplevel)
-            {
-                // If the top of the stack is not the SessionToken.Toplevel then
-                // this call to End is not balanced with the call to Begin that started the Session
-                throw new ArgumentException ("End must be balanced with calls to Begin");
-            }
-        }
-
-        // Notify that it is closing
-        sessionToken.Toplevel?.OnClosed (sessionToken.Toplevel);
-
-        if (SessionStack.TryPeek (out Toplevel? newTop))
-        {
-            newTop.App = this;
-            TopRunnable = newTop;
-            TopRunnable?.SetNeedsDraw ();
-        }
-
-        if (sessionToken.Toplevel is { HasFocus: true })
-        {
-            sessionToken.Toplevel.HasFocus = false;
-        }
-
-        if (TopRunnable is { HasFocus: false })
-        {
-            TopRunnable.SetFocus ();
-        }
-
-        CachedSessionTokenToplevel = sessionToken.Toplevel;
-
-        sessionToken.Toplevel = null;
-        sessionToken.Dispose ();
-
-        // BUGBUG: Why layout and draw here? This causes the screen to be cleared!
-        //LayoutAndDraw (true);
-
-        // TODO: This API is not used (correctly) anywhere; it can be deleted
-        // TODO: Instead, callers should use the new equivalent of Toplevel.Ready 
-        // TODO: which will be IsRunningChanged with newIsRunning == true
-        SessionEnded?.Invoke (this, new (CachedSessionTokenToplevel));
-    }
+    public bool StopAfterFirstIteration { get; set; }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public void RequestStop () { RequestStop ((Toplevel?)null); }
+    public event EventHandler<EventArgs<IApplication?>>? Iteration;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public void RequestStop (Toplevel? top)
-    {
-        Logging.Trace ($"TopRunnable: '{(top is { } ? top : "null")}'");
-
-        top ??= TopRunnable;
-
-        if (top == null)
-        {
-            return;
-        }
+    public void RaiseIteration () { Iteration?.Invoke (null, new (this)); }
 
 
-        ToplevelClosingEventArgs ev = new (top);
-        top.OnClosing (ev);
-
-        if (ev.Cancel)
-        {
-            return;
-        }
-
-        top.Running = false;
-    }
-
-    #endregion Begin->Run->Stop->End
+    #endregion Main Loop Iteration
 
 
     #region Timeouts and Invoke
     #region Timeouts and Invoke
 
 
@@ -334,7 +57,7 @@ public partial class ApplicationImpl
     public void Invoke (Action<IApplication>? action)
     public void Invoke (Action<IApplication>? action)
     {
     {
         // If we are already on the main UI thread
         // If we are already on the main UI thread
-        if (TopRunnable is { Running: true } && MainThreadId == Thread.CurrentThread.ManagedThreadId)
+        if (TopRunnableView is IRunnable { IsRunning: true } && MainThreadId == Thread.CurrentThread.ManagedThreadId)
         {
         {
             action?.Invoke (this);
             action?.Invoke (this);
 
 
@@ -356,7 +79,7 @@ public partial class ApplicationImpl
     public void Invoke (Action action)
     public void Invoke (Action action)
     {
     {
         // If we are already on the main UI thread
         // If we are already on the main UI thread
-        if (TopRunnable is { Running: true } && MainThreadId == Thread.CurrentThread.ManagedThreadId)
+        if (TopRunnableView is IRunnable { IsRunning: true } && MainThreadId == Thread.CurrentThread.ManagedThreadId)
         {
         {
             action?.Invoke ();
             action?.Invoke ();
 
 
@@ -376,126 +99,148 @@ public partial class ApplicationImpl
 
 
     #endregion Timeouts and Invoke
     #endregion Timeouts and Invoke
 
 
-    #region IRunnable Support
+    #region Session Lifecycle - Begin
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public RunnableSessionToken Begin (IRunnable runnable)
+    public SessionToken? Begin (IRunnable runnable)
     {
     {
         ArgumentNullException.ThrowIfNull (runnable);
         ArgumentNullException.ThrowIfNull (runnable);
 
 
-        // Ensure the mouse is ungrabbed
-        if (Mouse.MouseGrabView is { })
+        if (runnable.IsRunning)
         {
         {
-            Mouse.UngrabMouse ();
+            throw new ArgumentException (@"The runnable is already running.", nameof (runnable));
         }
         }
 
 
         // Create session token
         // Create session token
-        RunnableSessionToken token = new (runnable);
-
-        // Set the App property if the runnable is a View (needed for IsRunning/IsModal checks)
-        if (runnable is View runnableView)
-        {
-            runnableView.App = this;
-        }
+        SessionToken token = new (runnable);
 
 
-        // Get old IsRunning and IsModal values BEFORE any stack changes
+        // Get old IsRunning value BEFORE any stack changes (safe - cached value)
         bool oldIsRunning = runnable.IsRunning;
         bool oldIsRunning = runnable.IsRunning;
-        bool oldIsModalValue = runnable.IsModal;
 
 
-        // Raise IsRunningChanging (false -> true) - can be canceled
+        // Raise IsRunningChanging OUTSIDE lock (false -> true) - can be canceled
         if (runnable.RaiseIsRunningChanging (oldIsRunning, true))
         if (runnable.RaiseIsRunningChanging (oldIsRunning, true))
         {
         {
             // Starting was canceled
             // Starting was canceled
-            return token;
+            return null;
         }
         }
 
 
-        // Push token onto RunnableSessionStack (IsRunning becomes true)
-        RunnableSessionStack?.Push (token);
+        // Set the application reference in the runnable
+        runnable.SetApp (this);
+
+        // Ensure the mouse is ungrabbed
+        Mouse.UngrabMouse ();
 
 
-        // Update TopRunnable to the new top of stack
         IRunnable? previousTop = null;
         IRunnable? previousTop = null;
 
 
-        // In Phase 1, Toplevel doesn't implement IRunnable yet
-        // In Phase 2, it will, and this will work properly
-        if (TopRunnable is IRunnable r)
+        // CRITICAL SECTION - Atomic stack + cached state update
+        lock (_sessionStackLock)
         {
         {
-            previousTop = r;
-        }
+            // Get the previous top BEFORE pushing new token
+            if (SessionStack?.TryPeek (out SessionToken? previousToken) == true && previousToken?.Runnable is { })
+            {
+                previousTop = previousToken.Runnable;
+            }
 
 
-        // Set TopRunnable (handles both Toplevel and IRunnable)
-        if (runnable is Toplevel tl)
-        {
-            TopRunnable = tl;
-        }
-        else if (runnable is View v)
-        {
-            // For now, we can't set a non-Toplevel View as TopRunnable
-            // This is a limitation of the current architecture
-            // In Phase 2, we'll make TopRunnable an IRunnable property
-            Logging.Warning ($"WIP on Issue #4148 - Runnable '{runnable}' is a View but not a Toplevel; cannot set as TopRunnable");
+            if (previousTop == runnable)
+            {
+                throw new ArgumentOutOfRangeException (nameof (runnable), runnable, @"Attempt to Run the runnable that's already the top runnable.");
+            }
+
+            // Push token onto SessionStack
+            SessionStack?.Push (token);
+
+            TopRunnable = runnable;
+
+            // Update cached state atomically - IsRunning and IsModal are now consistent
+            SessionBegun?.Invoke (this, new (token));
+            runnable.SetIsRunning (true);
+            runnable.SetIsModal (true);
+
+            // Previous top is no longer modal
+            if (previousTop != null)
+            {
+                previousTop.SetIsModal (false);
+            }
         }
         }
 
 
-        // Raise IsRunningChanged (now true)
-        runnable.RaiseIsRunningChangedEvent (true);
+        // END CRITICAL SECTION - IsRunning/IsModal now thread-safe
 
 
-        // If there was a previous top, it's no longer modal
+        // Fire events AFTER lock released (avoid deadlocks in event handlers)
         if (previousTop != null)
         if (previousTop != null)
         {
         {
-            // Get old IsModal value (should be true before becoming non-modal)
-            bool oldIsModal = previousTop.IsModal;
-
-            // Raise IsModalChanging (true -> false)
-            previousTop.RaiseIsModalChanging (oldIsModal, false);
-
-            // IsModal is now false (derived property)
             previousTop.RaiseIsModalChangedEvent (false);
             previousTop.RaiseIsModalChangedEvent (false);
         }
         }
 
 
-        // New runnable becomes modal
-        // Raise IsModalChanging (false -> true) using the old value we captured earlier
-        runnable.RaiseIsModalChanging (oldIsModalValue, true);
-
-        // IsModal is now true (derived property)
+        runnable.RaiseIsRunningChangedEvent (true);
         runnable.RaiseIsModalChangedEvent (true);
         runnable.RaiseIsModalChangedEvent (true);
 
 
-        // Initialize if needed
-        if (runnable is View view && !view.IsInitialized)
-        {
-            view.BeginInit ();
-            view.EndInit ();
+        LayoutAndDraw ();
 
 
-            // Initialized event is raised by View.EndInit()
-        }
+        return token;
+    }
+
+    #endregion Session Lifecycle - Begin
 
 
-        // Initial Layout and draw
-        LayoutAndDraw (true);
+    #region Session Lifecycle - Run
+
+    /// <inheritdoc/>
+    [RequiresUnreferencedCode ("AOT")]
+    [RequiresDynamicCode ("AOT")]
+    public IApplication Run<TRunnable> (Func<Exception, bool>? errorHandler = null, string? driverName = null)
+        where TRunnable : IRunnable, new()
+    {
+        if (!Initialized)
+        {
+            // Init() has NOT been called. Auto-initialize as per interface contract.
+            Init (driverName);
+        }
 
 
-        // Set focus
-        if (runnable is View viewToFocus && !viewToFocus.HasFocus)
+        if (Driver is null)
         {
         {
-            viewToFocus.SetFocus ();
+            throw new InvalidOperationException (@"Driver is null after Init.");
         }
         }
 
 
-        if (PositionCursor ())
+        TRunnable runnable = new ();
+        object? result = Run (runnable, errorHandler);
+
+        // We created the runnable, so dispose it if it's disposable
+        if (runnable is IDisposable disposable)
         {
         {
-            Driver?.UpdateCursor ();
+            disposable.Dispose ();
         }
         }
 
 
-        return token;
+        return this;
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public void Run (IRunnable runnable, Func<Exception, bool>? errorHandler = null)
+    public object? Run (IRunnable runnable, Func<Exception, bool>? errorHandler = null)
     {
     {
         ArgumentNullException.ThrowIfNull (runnable);
         ArgumentNullException.ThrowIfNull (runnable);
 
 
         if (!Initialized)
         if (!Initialized)
         {
         {
-            throw new NotInitializedException (nameof (Run));
+            throw new NotInitializedException (@"Init must be called before Run.");
         }
         }
 
 
         // Begin the session (adds to stack, raises IsRunningChanging/IsRunningChanged)
         // Begin the session (adds to stack, raises IsRunningChanging/IsRunningChanged)
-        RunnableSessionToken token = Begin (runnable);
+        SessionToken? token;
+
+        if (runnable.IsRunning)
+        {
+            // Find it on the stack
+            token = SessionStack?.FirstOrDefault (st => st.Runnable == runnable);
+        }
+        else
+        {
+            token = Begin (runnable);
+        }
+
+        if (token is null)
+        {
+            Logging.Trace (@"Run - Begin session failed or was cancelled.");
+
+            return null;
+        }
 
 
         try
         try
         {
         {
@@ -507,33 +252,19 @@ public partial class ApplicationImpl
             // End the session (raises IsRunningChanging/IsRunningChanged, pops from stack)
             // End the session (raises IsRunningChanging/IsRunningChanged, pops from stack)
             End (token);
             End (token);
         }
         }
-    }
 
 
-    /// <inheritdoc/>
-    public IApplication Run<TRunnable> (Func<Exception, bool>? errorHandler = null) where TRunnable : IRunnable, new ()
-    {
-        if (!Initialized)
-        {
-            throw new NotInitializedException (nameof (Run));
-        }
-
-        TRunnable runnable = new ();
-        
-        // Store the runnable for automatic disposal by Shutdown
-        FrameworkOwnedRunnable = runnable;
-        
-        Run (runnable, errorHandler);
-
-        return this;
+        return token.Result;
     }
     }
 
 
     private void RunLoop (IRunnable runnable, Func<Exception, bool>? errorHandler)
     private void RunLoop (IRunnable runnable, Func<Exception, bool>? errorHandler)
     {
     {
+        runnable.StopRequested = false;
+
         // Main loop - blocks until RequestStop() is called
         // Main loop - blocks until RequestStop() is called
-        // Note: IsRunning is a derived property (stack.Contains), so we check it each iteration
+        // Note: IsRunning is now a cached property, safe to check each iteration
         var firstIteration = true;
         var firstIteration = true;
 
 
-        while (runnable.IsRunning)
+        while (runnable is { StopRequested: false, IsRunning: true })
         {
         {
             if (Coordinator is null)
             if (Coordinator is null)
             {
             {
@@ -563,8 +294,12 @@ public partial class ApplicationImpl
         }
         }
     }
     }
 
 
+    #endregion Session Lifecycle - Run
+
+    #region Session Lifecycle - End
+
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public void End (RunnableSessionToken token)
+    public void End (SessionToken token)
     {
     {
         ArgumentNullException.ThrowIfNull (token);
         ArgumentNullException.ThrowIfNull (token);
 
 
@@ -573,76 +308,84 @@ public partial class ApplicationImpl
             return; // Already ended
             return; // Already ended
         }
         }
 
 
+        // TODO: Move Poppover to utilize IRunnable arch; Get all refs to anyting
+        // TODO: View-related out of ApplicationImpl.
+        if (Popover?.GetActivePopover () as View is { Visible: true } visiblePopover)
+        {
+            ApplicationPopover.HideWithQuitCommand (visiblePopover);
+        }
+
         IRunnable runnable = token.Runnable;
         IRunnable runnable = token.Runnable;
 
 
-        // Get old IsRunning value (should be true before stopping)
+        // Get old IsRunning value (safe - cached value)
         bool oldIsRunning = runnable.IsRunning;
         bool oldIsRunning = runnable.IsRunning;
 
 
-        // Raise IsRunningChanging (true -> false) - can be canceled
+        // Raise IsRunningChanging OUTSIDE lock (true -> false) - can be canceled
         // This is where Result should be extracted!
         // This is where Result should be extracted!
         if (runnable.RaiseIsRunningChanging (oldIsRunning, false))
         if (runnable.RaiseIsRunningChanging (oldIsRunning, false))
         {
         {
-            // Stopping was canceled
+            // Stopping was canceled - do not proceed with End
             return;
             return;
         }
         }
 
 
-        // Current runnable is no longer modal
-        // Get old IsModal value (should be true before becoming non-modal)
-        bool oldIsModal = runnable.IsModal;
-
-        // Raise IsModalChanging (true -> false)
-        runnable.RaiseIsModalChanging (oldIsModal, false);
+        bool wasModal = runnable.IsModal;
+        IRunnable? previousRunnable = null;
 
 
-        // IsModal is now false (will be false after pop)
-        runnable.RaiseIsModalChangedEvent (false);
-
-        // Pop token from RunnableSessionStack (IsRunning becomes false)
-        if (RunnableSessionStack?.TryPop (out RunnableSessionToken? popped) == true && popped == token)
+        // CRITICAL SECTION - Atomic stack + cached state update
+        lock (_sessionStackLock)
         {
         {
-            // Restore previous top runnable
-            if (RunnableSessionStack?.TryPeek (out RunnableSessionToken? previousToken) == true && previousToken?.Runnable is { })
+            // Pop token from SessionStack
+            if (wasModal && SessionStack?.TryPop (out SessionToken? popped) == true && popped == token)
             {
             {
-                IRunnable? previousRunnable = previousToken.Runnable;
-
-                // Update TopRunnable if it's a Toplevel
-                if (previousRunnable is Toplevel tl)
+                // Restore previous top runnable
+                if (SessionStack?.TryPeek (out SessionToken? previousToken) == true && previousToken?.Runnable is { })
                 {
                 {
-                    TopRunnable = tl;
+                    previousRunnable = previousToken.Runnable;
+
+                    // Previous runnable becomes modal again
+                    previousRunnable.SetIsModal (true);
                 }
                 }
+            }
 
 
-                // Previous runnable becomes modal again
-                // Get old IsModal value (should be false before becoming modal again)
-                bool oldIsModalValue = previousRunnable.IsModal;
+            // Update cached state atomically - IsRunning and IsModal are now consistent
+            runnable.SetIsRunning (false);
+            runnable.SetIsModal (false);
+        }
 
 
-                // Raise IsModalChanging (false -> true)
-                previousRunnable.RaiseIsModalChanging (oldIsModalValue, true);
+        // END CRITICAL SECTION - IsRunning/IsModal now thread-safe
 
 
-                // IsModal is now true (derived property)
-                previousRunnable.RaiseIsModalChangedEvent (true);
-            }
-            else
-            {
-                // No more runnables, clear TopRunnable
-                if (TopRunnable is IRunnable)
-                {
-                    TopRunnable = null;
-                }
-            }
+        // Fire events AFTER lock released
+        if (wasModal)
+        {
+            runnable.RaiseIsModalChangedEvent (false);
         }
         }
 
 
-        // Raise IsRunningChanged (now false)
-        runnable.RaiseIsRunningChangedEvent (false);
+        TopRunnable = null;
 
 
-        // Set focus to new TopRunnable if exists
-        if (TopRunnable is View viewToFocus && !viewToFocus.HasFocus)
+        if (previousRunnable != null)
         {
         {
-            viewToFocus.SetFocus ();
+            TopRunnable = previousRunnable;
+            previousRunnable.RaiseIsModalChangedEvent (true);
         }
         }
 
 
-        // Clear the token
+        runnable.RaiseIsRunningChangedEvent (false);
+
+        token.Result = runnable.Result;
+
+        _result = token.Result;
+
+        // Clear the Runnable from the token
         token.Runnable = null;
         token.Runnable = null;
+        SessionEnded?.Invoke (this, new (token));
     }
     }
 
 
+    #endregion Session Lifecycle - End
+
+    #region Session Lifecycle - RequestStop
+
+    /// <inheritdoc/>
+    public void RequestStop () { RequestStop (null); }
+
     /// <inheritdoc/>
     /// <inheritdoc/>
     public void RequestStop (IRunnable? runnable)
     public void RequestStop (IRunnable? runnable)
     {
     {
@@ -650,7 +393,7 @@ public partial class ApplicationImpl
         if (runnable is null)
         if (runnable is null)
         {
         {
             // Try to get from TopRunnable
             // Try to get from TopRunnable
-            if (TopRunnable is IRunnable r)
+            if (TopRunnableView is IRunnable r)
             {
             {
                 runnable = r;
                 runnable = r;
             }
             }
@@ -660,15 +403,11 @@ public partial class ApplicationImpl
             }
             }
         }
         }
 
 
-        // For Toplevel, use the existing mechanism
-        if (runnable is Toplevel toplevel)
-        {
-            RequestStop (toplevel);
-        }
+        runnable.StopRequested = true;
 
 
         // Note: The End() method will be called from the finally block in Run()
         // Note: The End() method will be called from the finally block in Run()
         // and that's where IsRunningChanging/IsRunningChanged will be raised
         // and that's where IsRunningChanging/IsRunningChanged will be raised
     }
     }
 
 
-    #endregion IRunnable Support
+    #endregion Session Lifecycle - RequestStop
 }
 }

+ 11 - 11
Terminal.Gui/App/ApplicationImpl.Screen.cs

@@ -126,9 +126,8 @@ public partial class ApplicationImpl
     }
     }
 
 
     /// <summary>
     /// <summary>
-    ///     INTERNAL: Called when the application's size has changed. Sets the size of all <see cref="Toplevel"/>s and fires
-    ///     the
-    ///     <see cref="ScreenChanged"/> event.
+    ///     INTERNAL: Called when the application's screen has changed.
+    ///     Raises the <see cref="ScreenChanged"/> event.
     /// </summary>
     /// </summary>
     /// <param name="screen">The new screen size and position.</param>
     /// <param name="screen">The new screen size and position.</param>
     private void RaiseScreenChangedEvent (Rectangle screen)
     private void RaiseScreenChangedEvent (Rectangle screen)
@@ -137,13 +136,13 @@ public partial class ApplicationImpl
 
 
         ScreenChanged?.Invoke (this, new (screen));
         ScreenChanged?.Invoke (this, new (screen));
 
 
-        foreach (Toplevel t in SessionStack)
+        foreach (SessionToken t in SessionStack!)
         {
         {
-            t.OnSizeChanging (new (screen.Size));
-            t.SetNeedsLayout ();
+            if (t.Runnable is View runnableView)
+            {
+                runnableView.SetNeedsLayout ();
+            }
         }
         }
-
-        LayoutAndDraw (true);
     }
     }
 
 
     private void Driver_SizeChanged (object? sender, SizeChangedEventArgs e) { RaiseScreenChangedEvent (new (new (0, 0), e.Size!.Value)); }
     private void Driver_SizeChanged (object? sender, SizeChangedEventArgs e) { RaiseScreenChangedEvent (new (new (0, 0), e.Size!.Value)); }
@@ -151,7 +150,7 @@ public partial class ApplicationImpl
     /// <inheritdoc/>
     /// <inheritdoc/>
     public void LayoutAndDraw (bool forceRedraw = false)
     public void LayoutAndDraw (bool forceRedraw = false)
     {
     {
-        List<View> tops = [.. SessionStack];
+        List<View?> tops = [.. SessionStack!.Select(r => r.Runnable! as View)!];
 
 
         if (Popover?.GetActivePopover () as View is { Visible: true } visiblePopover)
         if (Popover?.GetActivePopover () as View is { Visible: true } visiblePopover)
         {
         {
@@ -160,7 +159,7 @@ public partial class ApplicationImpl
             tops.Insert (0, visiblePopover);
             tops.Insert (0, visiblePopover);
         }
         }
 
 
-        bool neededLayout = View.Layout (tops.ToArray ().Reverse (), Screen.Size);
+        bool neededLayout = View.Layout (tops.ToArray ().Reverse ()!, Screen.Size);
 
 
         if (ClearScreenNextIteration)
         if (ClearScreenNextIteration)
         {
         {
@@ -176,7 +175,8 @@ public partial class ApplicationImpl
         if (Driver is { })
         if (Driver is { })
         {
         {
             Driver.Clip = new (Screen);
             Driver.Clip = new (Screen);
-            View.Draw (tops, neededLayout || forceRedraw);
+
+            View.Draw (views: tops!, neededLayout || forceRedraw);
             Driver.Clip = new (Screen);
             Driver.Clip = new (Screen);
             Driver?.Refresh ();
             Driver?.Refresh ();
         }
         }

+ 150 - 55
Terminal.Gui/App/ApplicationImpl.cs

@@ -9,23 +9,65 @@ namespace Terminal.Gui.App;
 public partial class ApplicationImpl : IApplication
 public partial class ApplicationImpl : IApplication
 {
 {
     /// <summary>
     /// <summary>
-    ///     INTERNAL: Creates a new instance of the Application backend.
+    ///     INTERNAL: Creates a new instance of the Application backend and subscribes to Application configuration property
+    ///     events.
     /// </summary>
     /// </summary>
-    internal ApplicationImpl () { }
+    internal ApplicationImpl ()
+    {
+        // Subscribe to Application static property change events
+        Application.Force16ColorsChanged += OnForce16ColorsChanged;
+        Application.ForceDriverChanged += OnForceDriverChanged;
+    }
 
 
     /// <summary>
     /// <summary>
     ///     INTERNAL: Creates a new instance of the Application backend.
     ///     INTERNAL: Creates a new instance of the Application backend.
     /// </summary>
     /// </summary>
     /// <param name="componentFactory"></param>
     /// <param name="componentFactory"></param>
-    internal ApplicationImpl (IComponentFactory componentFactory) { _componentFactory = componentFactory; }
+    internal ApplicationImpl (IComponentFactory componentFactory) : this () { _componentFactory = componentFactory; }
+
+    private string? _driverName;
+
+    /// <inheritdoc/>
+    public new string ToString () => Driver?.ToString () ?? string.Empty;
+
+    #region Singleton - Legacy Static Support
+
+    /// <summary>
+    ///     Lock object for synchronizing access to ModelUsage and _instance.
+    /// </summary>
+    private static readonly object _modelUsageLock = new ();
 
 
-    #region Singleton
+    /// <summary>
+    ///     Tracks which application model has been used in this process.
+    /// </summary>
+    public static ApplicationModelUsage ModelUsage { get; private set; } = ApplicationModelUsage.None;
+
+    /// <summary>
+    ///     Error message for when trying to use modern model after legacy static model.
+    /// </summary>
+    internal const string ERROR_MODERN_AFTER_LEGACY =
+        "Cannot use modern instance-based model (Application.Create) after using legacy static Application model (Application.Init/ApplicationImpl.Instance). "
+        + "Use only one model per process.";
+
+    /// <summary>
+    ///     Error message for when trying to use legacy static model after modern model.
+    /// </summary>
+    internal const string ERROR_LEGACY_AFTER_MODERN =
+        "Cannot use legacy static Application model (Application.Init/ApplicationImpl.Instance) after using modern instance-based model (Application.Create). "
+        + "Use only one model per process.";
 
 
     /// <summary>
     /// <summary>
     ///     Configures the singleton instance of <see cref="Application"/> to use the specified backend implementation.
     ///     Configures the singleton instance of <see cref="Application"/> to use the specified backend implementation.
     /// </summary>
     /// </summary>
     /// <param name="app"></param>
     /// <param name="app"></param>
-    public static void SetInstance (IApplication? app) { _instance = app; }
+    public static void SetInstance (IApplication? app)
+    {
+        lock (_modelUsageLock)
+        {
+            ModelUsage = ApplicationModelUsage.LegacyStatic;
+            _instance = app;
+        }
+    }
 
 
     // Private static readonly Lazy instance of Application
     // Private static readonly Lazy instance of Application
     private static IApplication? _instance;
     private static IApplication? _instance;
@@ -33,35 +75,104 @@ public partial class ApplicationImpl : IApplication
     /// <summary>
     /// <summary>
     ///     Gets the currently configured backend implementation of <see cref="Application"/> gateway methods.
     ///     Gets the currently configured backend implementation of <see cref="Application"/> gateway methods.
     /// </summary>
     /// </summary>
-    public static IApplication Instance => _instance ??= new ApplicationImpl ();
-
-    #endregion Singleton
-
-    private string? _driverName;
-
-    #region Input
+    public static IApplication Instance
+    {
+        get
+        {
+            //Debug.Fail ("ApplicationImpl.Instance accessed - parallelizable tests should not use legacy static Application model");
 
 
-    private IMouse? _mouse;
+            // Thread-safe: Use lock to make check-and-create atomic
+            lock (_modelUsageLock)
+            {
+                // If an instance already exists, return it without fence checking
+                // This allows for cleanup/reset operations
+                if (_instance is { })
+                {
+                    return _instance;
+                }
+
+                // Check if the instance-based model has already been used
+                if (ModelUsage == ApplicationModelUsage.InstanceBased)
+                {
+                    throw new InvalidOperationException (ERROR_LEGACY_AFTER_MODERN);
+                }
+
+                // Mark the usage and create the instance
+                ModelUsage = ApplicationModelUsage.LegacyStatic;
+
+                return _instance = new ApplicationImpl ();
+            }
+        }
+    }
 
 
     /// <summary>
     /// <summary>
-    ///     Handles mouse event state and processing.
+    ///     INTERNAL: Marks that the instance-based model has been used. Called by Application.Create().
     /// </summary>
     /// </summary>
-    public IMouse Mouse
+    internal static void MarkInstanceBasedModelUsed ()
     {
     {
-        get
+        lock (_modelUsageLock)
         {
         {
-            _mouse ??= new MouseImpl { App = this };
+            // Check if the legacy static model has already been initialized
+            if (ModelUsage == ApplicationModelUsage.LegacyStatic && _instance?.Initialized == true)
+            {
+                throw new InvalidOperationException (ERROR_MODERN_AFTER_LEGACY);
+            }
 
 
-            return _mouse;
+            ModelUsage = ApplicationModelUsage.InstanceBased;
         }
         }
-        set => _mouse = value ?? throw new ArgumentNullException (nameof (value));
     }
     }
 
 
-    private IKeyboard? _keyboard;
+    /// <summary>
+    ///     INTERNAL: Resets the model usage tracking. Only for testing purposes.
+    /// </summary>
+    internal static void ResetModelUsageTracking ()
+    {
+        lock (_modelUsageLock)
+        {
+            ModelUsage = ApplicationModelUsage.None;
+            _instance = null;
+        }
+    }
 
 
     /// <summary>
     /// <summary>
-    ///     Handles keyboard input and key bindings at the Application level
+    ///     INTERNAL: Resets state without going through the fence-checked Instance property.
+    ///     Used by Application.ResetState() to allow cleanup regardless of which model was used.
     /// </summary>
     /// </summary>
+    internal static void ResetStateStatic (bool ignoreDisposed = false)
+    {
+        // If an instance exists, reset it
+        _instance?.ResetState (ignoreDisposed);
+
+        // Reset Application static properties to their defaults
+        // This ensures tests start with clean state
+        Application.ForceDriver = string.Empty;
+        Application.Force16Colors = false;
+        Application.IsMouseDisabled = false;
+        Application.QuitKey = Key.Esc;
+        Application.ArrangeKey = Key.F5.WithCtrl;
+        Application.NextTabGroupKey = Key.F6;
+        Application.NextTabKey = Key.Tab;
+        Application.PrevTabGroupKey = Key.F6.WithShift;
+        Application.PrevTabKey = Key.Tab.WithShift;
+
+        // Always reset the model tracking to allow tests to use either model after reset
+        ResetModelUsageTracking ();
+    }
+
+    #endregion Singleton - Legacy Static Support
+
+    #region Screen and Driver
+
+    /// <inheritdoc/>
+    public IClipboard? Clipboard => Driver?.Clipboard;
+
+    #endregion Screen and Driver
+
+    #region Keyboard
+
+    private IKeyboard? _keyboard;
+
+    /// <inheritdoc/>
     public IKeyboard Keyboard
     public IKeyboard Keyboard
     {
     {
         get
         get
@@ -73,24 +184,28 @@ public partial class ApplicationImpl : IApplication
         set => _keyboard = value ?? throw new ArgumentNullException (nameof (value));
         set => _keyboard = value ?? throw new ArgumentNullException (nameof (value));
     }
     }
 
 
-    #endregion Input
+    #endregion Keyboard
 
 
-    #region View Management
+    #region Mouse
 
 
-    private ApplicationPopover? _popover;
+    private IMouse? _mouse;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public ApplicationPopover? Popover
+    public IMouse Mouse
     {
     {
         get
         get
         {
         {
-            _popover ??= new () { App = this };
+            _mouse ??= new MouseImpl { App = this };
 
 
-            return _popover;
+            return _mouse;
         }
         }
-        set => _popover = value;
+        set => _mouse = value ?? throw new ArgumentNullException (nameof (value));
     }
     }
 
 
+    #endregion Mouse
+
+    #region Navigation and Popover
+
     private ApplicationNavigation? _navigation;
     private ApplicationNavigation? _navigation;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
@@ -105,39 +220,19 @@ public partial class ApplicationImpl : IApplication
         set => _navigation = value ?? throw new ArgumentNullException (nameof (value));
         set => _navigation = value ?? throw new ArgumentNullException (nameof (value));
     }
     }
 
 
-    private Toplevel? _topRunnable;
+    private ApplicationPopover? _popover;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public Toplevel? TopRunnable
+    public ApplicationPopover? Popover
     {
     {
-        get => _topRunnable;
-        set
+        get
         {
         {
-            _topRunnable = value;
+            _popover ??= new () { App = this };
 
 
-            if (_topRunnable is { })
-            {
-                _topRunnable.App = this;
-            }
+            return _popover;
         }
         }
+        set => _popover = value;
     }
     }
 
 
-    // BUGBUG: Technically, this is not the full lst of sessions. There be dragons here, e.g. see how Toplevel.Id is used. What
-
-    /// <inheritdoc/>
-    public ConcurrentStack<Toplevel> SessionStack { get; } = new ();
-
-    /// <inheritdoc/>
-    public Toplevel? CachedSessionTokenToplevel { get; set; }
-
-    /// <inheritdoc/>
-    public ConcurrentStack<RunnableSessionToken>? RunnableSessionStack { get; } = new ();
-
-    /// <inheritdoc/>
-    public IRunnable? FrameworkOwnedRunnable { get; set; }
-
-    #endregion View Management
-
-    /// <inheritdoc/>
-    public new string ToString () => Driver?.ToString () ?? string.Empty;
+    #endregion Navigation and Popover
 }
 }

+ 16 - 0
Terminal.Gui/App/ApplicationModelUsage.cs

@@ -0,0 +1,16 @@
+namespace Terminal.Gui.App;
+
+/// <summary>
+///     Defines the different application usage models.
+/// </summary>
+public enum ApplicationModelUsage
+{
+    /// <summary>No model has been used yet.</summary>
+    None,
+
+    /// <summary>Legacy static model (Application.Init/ApplicationImpl.Instance).</summary>
+    LegacyStatic,
+
+    /// <summary>Modern instance-based model (Application.Create).</summary>
+    InstanceBased
+}

Some files were not shown because too many files changed in this diff