Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #2491. Deletes Toplevel; introduces formal concept of Overlapped and IRunnable #3623

Closed
wants to merge 102 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
102 commits
Select commit Hold shift + click to select a range
b64db9b
Fixed gitversion
tig Jul 11, 2024
bebf7c6
Fixed publish.yml
tig Jul 11, 2024
3650392
Merged with v2_develop
tig Jul 14, 2024
725855d
Removed accidental stuff
tig Jul 14, 2024
78ab7ec
Progress. WIP
tig Jul 14, 2024
e105643
Updated About box
tig Jul 15, 2024
58e4271
MessageBox works. Dialog broken
tig Jul 15, 2024
8bf0207
Dialog works
tig Jul 15, 2024
a3b606f
New unit tests. Lots of fixes
tig Jul 15, 2024
0c10d4b
More unit tests
tig Jul 15, 2024
f51e38d
Fixed TextFormatter.FormatAndGetSize for wide vertical text
tig Jul 16, 2024
06339c9
Fixed ShadowTests
tig Jul 16, 2024
ce5fc1c
Fixed ShadowTests
tig Jul 16, 2024
3b8319b
Added low-level TextFormatter.FormatAndGetSize tests
tig Jul 16, 2024
0e7e1e2
Fixed bogus Title test
tig Jul 16, 2024
e93eebb
Fixed little things.
tig Jul 17, 2024
dd6d96a
Undid PosCenter change
tig Jul 17, 2024
4654d4a
Undid PosCenter change
tig Jul 17, 2024
a30dbe7
Fixed broken Window test
tig Jul 17, 2024
f6064be
Fixed SetTextFormatterSize
tig Jul 17, 2024
d8bc511
Fixed Shortcut
tig Jul 17, 2024
e566dce
Fixed Horizontal FormatAndGetSize Fill issue; Vertical is still broken
tig Jul 17, 2024
b528ba8
Fixed Vertical FormatAndGetSize Fill issue
tig Jul 17, 2024
3708873
Removed lame title test
tig Jul 17, 2024
51433c0
Refactored DimAuto unit tests
tig Jul 17, 2024
2cecc77
WIP - Trying to make TextFormatter have indepdentent width/height
tig Jul 17, 2024
b4e1b3e
All unit tests pass.
tig Jul 18, 2024
48eba3b
Code cleanup
tig Jul 18, 2024
c4de9fe
Code cleanup
tig Jul 18, 2024
6c07532
Code cleanup
tig Jul 18, 2024
e4e2b59
Code cleanup
tig Jul 18, 2024
7733a69
Code cleanup
tig Jul 19, 2024
c119fc5
Updated DimAuto.md
tig Jul 19, 2024
ee57f41
Fixed @bdisp noted error
tig Jul 19, 2024
153f101
Fixed warnings
tig Jul 19, 2024
c6a9021
Fixed error in Textformatter
tig Jul 19, 2024
c537c34
doc tweak
tig Jul 19, 2024
23737de
rebased against v2_develop
tig Jul 19, 2024
6b5bcce
Fix typo in config.json
csinkers Jul 19, 2024
24e5fbd
Revert "Fix typo in config.json"
tig Jul 19, 2024
fa847f4
Revert "rebased against v2_develop"
tig Jul 19, 2024
4128b51
Merge branch 'v2_develop' into v2_3499-Finish-DimAuto
tig Jul 19, 2024
3ed3076
Addressed review feedback from @dodexahedron.
tig Jul 20, 2024
6550cde
Nuked Textformatter.AutoSize.
tig Jul 20, 2024
0e70444
Renamed Width/Height/Size
tig Jul 20, 2024
71e14c8
API doc improvements
tig Jul 20, 2024
4bdaef7
Nuked TextFormatter.CalcRect and unit tests
tig Jul 20, 2024
31ef0fc
Revamped Messagebox tests
tig Jul 20, 2024
c7ae986
Review feedback
tig Jul 20, 2024
8a8666c
Removed old comments
tig Jul 20, 2024
07d7bbb
reverted bad change
tig Jul 20, 2024
6c6244a
Updated DatePicker BUGBUG
tig Jul 20, 2024
ffc4136
Fixed ExpanderButton
tig Jul 20, 2024
c59f59a
Identified Dim.Auto bug with AnchorEnd
tig Jul 20, 2024
149bedf
Added more AnchorEnd unit tests.
tig Jul 20, 2024
bf852ff
Added BUGBUG
tig Jul 20, 2024
87c5a43
Undid previous change that broke StatusBar
tig Jul 20, 2024
6f9fb1a
Trying to debug @bdisp's About box issue
tig Jul 20, 2024
6da8dab
Trying to figure out aboutbox issue
tig Jul 20, 2024
0073156
added message box unit test for UI Catalog about box
tig Jul 20, 2024
d003d00
Removed verbatim strings
tig Jul 20, 2024
b2cd779
Use .ReplaceLineEndings() in TextFormatter
tig Jul 21, 2024
8ca972b
Learning how to use [CombinatorialData]
tig Jul 21, 2024
f0d4c48
Learning how to use [CombinatorialData] moar
tig Jul 21, 2024
f328f0c
Initial commit.
tig Jul 21, 2024
14d8bf5
Merge branch 'v2_develop' into v2_2491-Toplevel-Redesign
tig Jul 22, 2024
44ce74a
Refactored Application into smaller files.
tig Jul 22, 2024
2e0a9a7
Fixed nullable warnings
tig Jul 22, 2024
0b8e434
Applicaation Toplevel handling moved to separate file
tig Jul 22, 2024
2939108
Added Toplevel to spelling dict
tig Jul 22, 2024
250050c
Toplevel cleanup
tig Jul 22, 2024
4701080
Toplevel.cs organization
tig Jul 23, 2024
d44e8d3
More Toplevel.cs organization & docs
tig Jul 23, 2024
d813b1f
Fixed dumb enum cast in KeyBinding code
tig Jul 23, 2024
fe5cbe4
More Toplevel.cs organization & docs
tig Jul 23, 2024
f8e8aff
More Toplevel.cs organization & docs
tig Jul 23, 2024
feaf5c0
WIP (Very Broken) try to move keybindings out of Toplevel to app
tig Jul 24, 2024
c03dd32
Moved Toplevel keybindings out of Toplevel to Application.
tig Jul 24, 2024
22dcbc1
removed un needed key handling code from TextView
tig Jul 24, 2024
c088f2e
removed unneeded key handling code from Toplevel
tig Jul 24, 2024
4a56b84
removed unneeded AlternateBack/FormardKey code from Toplevel
tig Jul 24, 2024
0c56dfe
Moved view navigation out of Toplevel and into Application (via ViewN…
tig Jul 24, 2024
73a9dc3
Fixed nullable warnings 2
tig Jul 24, 2024
04dbe68
Fixed nullable warnings 3
tig Jul 24, 2024
3b35189
Fixed nullable warnings 4
tig Jul 24, 2024
689c0cd
Fixed nullable warnings 5
tig Jul 24, 2024
ff47aa2
Fixed nullable warnings 6
tig Jul 24, 2024
022050d
Fixed nullable warnings 7
tig Jul 24, 2024
f37ec5e
Moved Overlapped stuff to ApplicationOverlap static class. Fixed null…
tig Jul 24, 2024
cb3e806
Moved Overlapped stuff to ApplicationOverlap static class. Fixed null…
tig Jul 24, 2024
cbecae5
Moved Overlapped stuff to ApplicationOverlap static class. Fixed null…
tig Jul 24, 2024
331d972
nullable enable TopLevel
tig Jul 24, 2024
ca4d10b
WIP: Modify Focus logic to properly deal with ViewArrangement.Overlap…
tig Jul 25, 2024
3a40851
WIP: More - Modify Focus logic to properly deal with ViewArrangement.…
tig Jul 25, 2024
d874f56
Reorganized View source files to get my head straight
tig Jul 25, 2024
9b89fe6
Code cleanup and API docs - getting better understanding of navigatio…
tig Jul 25, 2024
ccec0ee
Documenting focus code
tig Jul 25, 2024
2d2954d
Merge branch 'v2_develop' into v2_3499-Finish-DimAuto
tig Jul 25, 2024
0583d45
Merge pull request #3615 from tig/v2_3499-Finish-DimAuto
tig Jul 25, 2024
15e6b4e
Documenting focus code
tig Jul 25, 2024
a935ef8
Merge remote-tracking branch 'refs/remotes/origin/v2_2491-Toplevel-Re…
tig Jul 25, 2024
78f527e
Fixed post merge errors.
tig Jul 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/api-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Build and publish API docs

on:
push:
branches: [main, v2_develop]
branches: [v1_release, v2_develop]

permissions:
id-token: write
Expand All @@ -17,11 +17,11 @@ jobs:
runs-on: windows-latest
steps:
- name: Checkout
if: github.ref_name == 'main' || github.ref_name == 'develop'
if: github.ref_name == 'v1_release' || github.ref_name == 'v1_develop'
uses: actions/checkout@v4

- name: DocFX Build
if: github.ref_name == 'main' || github.ref_name == 'develop'
if: github.ref_name == 'v1_release' || github.ref_name == 'v1_develop'
working-directory: docfx
run: |
dotnet tool install -g docfx
Expand All @@ -31,17 +31,17 @@ jobs:
continue-on-error: false

- name: Setup Pages
if: github.ref_name == 'main' || github.ref_name == 'develop'
if: github.ref_name == 'v1_release' || github.ref_name == 'v1_develop'
uses: actions/configure-pages@v5

- name: Upload artifact
if: github.ref_name == 'main' || github.ref_name == 'develop'
if: github.ref_name == 'v1_release' || github.ref_name == 'v1_develop'
uses: actions/upload-pages-artifact@v3
with:
path: docfx/_site

- name: Deploy to GitHub Pages
if: github.ref_name == 'main' || github.ref_name == 'develop'
if: github.ref_name == 'v1_release' || github.ref_name == 'v1_develop'
id: deployment
uses: actions/deploy-pages@v4
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Publish Terminal.Gui

on:
push:
branches: [ main, develop, v2_release, v2_develop ]
branches: [ v1_release, v1_develop, v2_release, v2_develop ]
tags:
- v*
paths-ignore:
Expand Down
2 changes: 1 addition & 1 deletion CommunityToolkitExample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ private static void Main (string [] args)
Services = ConfigureServices ();
Application.Init ();
Application.Run (Services.GetRequiredService<LoginView> ());
Application.Top.Dispose();
Application.Top?.Dispose();
Application.Shutdown ();
}

Expand Down
11 changes: 5 additions & 6 deletions GitVersion.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ mode: ContinuousDeployment
tag-prefix: '[vV]'
continuous-delivery-fallback-tag: dev
branches:
develop:
v1_develop:
mode: ContinuousDeployment
tag: dev
regex: develop
regex: v1_develop
source-branches:
- main
- v1_release
pre-release-weight: 100

v2_develop:
Expand All @@ -32,9 +32,8 @@ branches:
tag-number-pattern: '[/-](?<number>\d+)'
regex: ^(pull|pull\-requests|pr)[/-]
source-branches:
- develop
- main
- release
- v1_develop
- v1_release
- v2_develop
- v2_release
- feature
Expand Down
53 changes: 53 additions & 0 deletions Terminal.Gui/Application/Application .Screen.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#nullable enable
namespace Terminal.Gui;

public static partial class Application // Screen related stuff
{
/// <summary>
/// Gets the size of the screen. This is the size of the screen as reported by the <see cref="ConsoleDriver"/>.
/// </summary>
/// <remarks>
/// If the <see cref="ConsoleDriver"/> has not been initialized, this will return a default size of 2048x2048; useful for unit tests.
/// </remarks>
public static Rectangle Screen => Driver?.Screen ?? new (0, 0, 2048, 2048);

/// <summary>Invoked when the terminal's size changed. The new size of the terminal is provided.</summary>
/// <remarks>
/// Event handlers can set <see cref="SizeChangedEventArgs.Cancel"/> to <see langword="true"/> to prevent
/// <see cref="Application"/> from changing it's size to match the new terminal size.
/// </remarks>
public static event EventHandler<SizeChangedEventArgs>? SizeChanging;

/// <summary>
/// Called when the application's size changes. Sets the size of all <see cref="Toplevel"/>s and fires the
/// <see cref="SizeChanging"/> event.
/// </summary>
/// <param name="args">The new size.</param>
/// <returns><see lanword="true"/>if the size was changed.</returns>
public static bool OnSizeChanging (SizeChangedEventArgs args)
{
SizeChanging?.Invoke (null, args);

if (args.Cancel || args.Size is null)
{
return false;
}

foreach (Toplevel t in TopLevels)
{
t.SetRelativeLayout (args.Size.Value);
t.LayoutSubviews ();
t.PositionToplevels ();
t.OnSizeChanging (new (args.Size));

if (PositionCursor (t))
{
Driver?.UpdateCursor ();
}
}

Refresh ();

return true;
}
}
29 changes: 29 additions & 0 deletions Terminal.Gui/Application/Application.Driver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#nullable enable
namespace Terminal.Gui;

public static partial class Application // Driver abstractions
{
internal static bool _forceFakeConsole;

/// <summary>Gets the <see cref="ConsoleDriver"/> that has been selected. See also <see cref="ForceDriver"/>.</summary>
public static ConsoleDriver? Driver { get; internal set; }

/// <summary>
/// Gets or sets whether <see cref="Application.Driver"/> will be forced to output only the 16 colors defined in
/// <see cref="ColorName"/>. The default is <see langword="false"/>, meaning 24-bit (TrueColor) colors will be output
/// as long as the selected <see cref="ConsoleDriver"/> supports TrueColor.
/// </summary>
[SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
public static bool Force16Colors { get; set; }

/// <summary>
/// Forces the use of the specified driver (one of "fake", "ansi", "curses", "net", or "windows"). If not
/// specified, the driver is selected based on the platform.
/// </summary>
/// <remarks>
/// Note, <see cref="Application.Init(ConsoleDriver, string)"/> will override this configuration setting if called
/// with either `driver` or `driverName` specified.
/// </remarks>
[SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
public static string ForceDriver { get; set; } = string.Empty;
}
212 changes: 212 additions & 0 deletions Terminal.Gui/Application/Application.Initialization.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
#nullable enable
using System.Diagnostics.CodeAnalysis;
using System.Reflection;

namespace Terminal.Gui;

public static partial class Application // Initialization (Init/Shutdown)
{
/// <summary>Initializes a new instance of <see cref="Terminal.Gui"/> Application.</summary>
/// <para>Call this method once per instance (or after <see cref="Shutdown"/> has been called).</para>
/// <para>
/// This function loads the right <see cref="ConsoleDriver"/> for the platform, Creates a <see cref="Toplevel"/>. and
/// assigns it to <see cref="Top"/>
/// </para>
/// <para>
/// <see cref="Shutdown"/> must be called when the application is closing (typically after
/// <see cref="Run{T}"/> has returned) to ensure resources are cleaned up and
/// terminal settings
/// restored.
/// </para>
/// <para>
/// The <see cref="Run{T}"/> function combines
/// <see cref="Init(Terminal.Gui.ConsoleDriver,string)"/> and <see cref="Run(Toplevel, Func{Exception, bool})"/>
/// into a single
/// call. An application cam use <see cref="Run{T}"/> without explicitly calling
/// <see cref="Init(Terminal.Gui.ConsoleDriver,string)"/>.
/// </para>
/// <param name="driver">
/// The <see cref="ConsoleDriver"/> to use. If neither <paramref name="driver"/> or
/// <paramref name="driverName"/> are specified the default driver for the platform will be used.
/// </param>
/// <param name="driverName">
/// The short name (e.g. "net", "windows", "ansi", "fake", or "curses") of the
/// <see cref="ConsoleDriver"/> to use. If neither <paramref name="driver"/> or <paramref name="driverName"/> are
/// specified the default driver for the platform will be used.
/// </param>
[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
public static void Init (ConsoleDriver? driver = null, string? driverName = null) { InternalInit (driver, driverName); }

internal static bool IsInitialized { get; set; }
internal static int MainThreadId { get; set; } = -1;

// INTERNAL function for initializing an app with a Toplevel factory object, driver, and mainloop.
//
// Called from:
//
// Init() - When the user wants to use the default Toplevel. calledViaRunT will be false, causing all state to be reset.
// Run<T>() - When the user wants to use a custom Toplevel. calledViaRunT will be true, enabling Run<T>() to be called without calling Init first.
// Unit Tests - To initialize the app with a custom Toplevel, using the FakeDriver. calledViaRunT will be false, causing all state to be reset.
//
// calledViaRunT: If false (default) all state will be reset. If true the state will not be reset.
[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
internal static void InternalInit (
ConsoleDriver? driver = null,
string? driverName = null,
bool calledViaRunT = false
)
{
if (IsInitialized && driver is null)
{
return;
}

if (IsInitialized)
{
throw new InvalidOperationException ("Init has already been called and must be bracketed by Shutdown.");
}

if (!calledViaRunT)
{
// Reset all class variables (Application is a singleton).
ResetState ();
}

// For UnitTests
if (driver is { })
{
Driver = driver;
}

// Start the process of configuration management.
// Note that we end up calling LoadConfigurationFromAllSources
// multiple times. We need to do this because some settings are only
// valid after a Driver is loaded. In this case we need just
// `Settings` so we can determine which driver to use.
// Don't reset, so we can inherit the theme from the previous run.
Load ();
Apply ();

AddApplicationKeyBindings ();

// Ignore Configuration for ForceDriver if driverName is specified
if (!string.IsNullOrEmpty (driverName))
{
ForceDriver = driverName;
}

if (Driver is null)
{
PlatformID p = Environment.OSVersion.Platform;

if (string.IsNullOrEmpty (ForceDriver))
{
if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows)
{
Driver = new WindowsDriver ();
}
else
{
Driver = new CursesDriver ();
}
}
else
{
List<Type?> drivers = GetDriverTypes ();
Type? driverType = drivers.FirstOrDefault (t => t!.Name.Equals (ForceDriver, StringComparison.InvariantCultureIgnoreCase));

if (driverType is { })
{
Driver = (ConsoleDriver)Activator.CreateInstance (driverType)!;
}
else
{
throw new ArgumentException (
$"Invalid driver name: {ForceDriver}. Valid names are {string.Join (", ", drivers.Select (t => t!.Name))}"
);
}
}
}

try
{
MainLoop = Driver!.Init ();
}
catch (InvalidOperationException ex)
{
// This is a case where the driver is unable to initialize the console.
// This can happen if the console is already in use by another process or
// if running in unit tests.
// In this case, we want to throw a more specific exception.
throw new InvalidOperationException (
"Unable to initialize the console. This can happen if the console is already in use by another process or in unit tests.",
ex
);
}

Driver.SizeChanged += Driver_SizeChanged;
Driver.KeyDown += Driver_KeyDown;
Driver.KeyUp += Driver_KeyUp;
Driver.MouseEvent += Driver_MouseEvent;

SynchronizationContext.SetSynchronizationContext (new MainLoopSyncContext ());

SupportedCultures = GetSupportedCultures ();
MainThreadId = Thread.CurrentThread.ManagedThreadId;
bool init = IsInitialized = true;
InitializedChanged?.Invoke (null, new (init));
}

private static void Driver_SizeChanged (object? sender, SizeChangedEventArgs e) { OnSizeChanging (e); }
private static void Driver_KeyDown (object? sender, Key e) { OnKeyDown (e); }
private static void Driver_KeyUp (object? sender, Key e) { OnKeyUp (e); }
private static void Driver_MouseEvent (object? sender, MouseEvent e) { OnMouseEvent (e); }

/// <summary>Gets of list of <see cref="ConsoleDriver"/> types that are available.</summary>
/// <returns></returns>
[RequiresUnreferencedCode ("AOT")]
public static List<Type?> GetDriverTypes ()
{
// use reflection to get the list of drivers
List<Type?> driverTypes = new ();

foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies ())
{
foreach (Type? type in asm.GetTypes ())
{
if (type.IsSubclassOf (typeof (ConsoleDriver)) && !type.IsAbstract)
{
driverTypes.Add (type);
}
}
}

return driverTypes;
}

/// <summary>Shutdown an application initialized with <see cref="Init"/>.</summary>
/// <remarks>
/// Shutdown must be called for every call to <see cref="Init"/> or
/// <see cref="Application.Run(Toplevel, Func{Exception, bool})"/> to ensure all resources are cleaned
/// up (Disposed)
/// and terminal settings are restored.
/// </remarks>
public static void Shutdown ()
{
// TODO: Throw an exception if Init hasn't been called.
ResetState ();
PrintJsonErrors ();
bool init = IsInitialized;
InitializedChanged?.Invoke (null, new (in init));
}

/// <summary>
/// This event is raised after the <see cref="Init"/> and <see cref="Shutdown"/> methods have been called.
/// </summary>
/// <remarks>
/// Intended to support unit tests that need to know when the application has been initialized.
/// </remarks>
public static event EventHandler<EventArgs<bool>>? InitializedChanged;
}
Loading
Loading