diff --git a/.github/workflows/dotnet-core.yml b/.github/workflows/dotnet-core.yml
index 8a48bfd51..7dd29970b 100644
--- a/.github/workflows/dotnet-core.yml
+++ b/.github/workflows/dotnet-core.yml
@@ -1,4 +1,4 @@
-name: .NET Core
+name: Build Terminal.Gui with .NET Core
on:
push:
@@ -13,13 +13,36 @@ jobs:
steps:
- uses: actions/checkout@v2
+
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.100
+
- name: Install dependencies
run: dotnet restore
+
- name: Build
run: dotnet build --configuration Release --no-restore
+
- name: Test
- run: dotnet test --no-restore --verbosity normal
+ run: |
+ dotnet test --no-restore --verbosity normal --collect:"XPlat Code Coverage" --settings UnitTests/coverlet.runsettings
+ mv -v UnitTests/TestResults/*/*.* UnitTests/TestResults/
+
+ - name: Create Test Coverage Badge
+ uses: simon-k/dotnet-code-coverage-badge@v1.0.0
+ id: create_coverage_badge
+ with:
+ label: Unit Test Coverage
+ color: brightgreen
+ path: UnitTests/TestResults/coverage.opencover.xml
+ gist-filename: code-coverage.json
+ # https://gist.github.com/migueldeicaza/90ef67a684cb71db1817921a970f8d27
+ gist-id: 90ef67a684cb71db1817921a970f8d27
+ gist-auth-token: ${{ secrets.GIST_AUTH_TOKEN }}
+
+ - name: Print Code Coverage
+ run: |
+ echo "Code coverage percentage: ${{steps.create_coverage_badge.outputs.percentage}}%"
+ echo "Badge data: ${{steps.create_coverage_badge.outputs.badge}}"
diff --git a/.gitignore b/.gitignore
index 039166b63..1c9d8c393 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,8 @@ packages
docfx/api
+UnitTests/TestResults
+
#git merge files
*.orig
diff --git a/README.md b/README.md
index 45f20bed3..4f74dfe43 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@


[](https://www.nuget.org/packages/Terminal.Gui)
+
[](https://www.nuget.org/packages/Terminal.Gui)
[](LICENSE)
@@ -10,10 +11,6 @@ A simple toolkit for building console GUI apps for .NET, .NET Core, and Mono tha

-The most recent released [Nuget package is version `0.90.x`](https://www.nuget.org/packages/Terminal.Gui) which is the "Stable, Feature Complete" pre-release of 1.0.
-
-Nuget also contains pre-release versions of 1.0; they are identified with `-pre` or `-beta` in the version number (e.g. `1.0.0-pre.1`)
-
## Controls & Features
*Terminal.Gui* contains various controls for building text user interfaces:
@@ -222,4 +219,4 @@ A presentation of this was part of the [Retro.NET](https://channel9.msdn.com/Eve
Release history can be found in the [Terminal.Gui.csproj](https://github.com/migueldeicaza/gui.cs/blob/master/Terminal.Gui/Terminal.Gui.csproj) file.
-In 2019 and 2020, Charlie Kindel (https://github.com/tig) and @BDisp (https://github.com/BDisp) vastly extended, improved, polished and fixed gui.cs to what it is today.
+In 2019, 2020, and 2021, Charlie Kindel (https://github.com/tig), @BDisp (https://github.com/BDisp), and Thomas Nind (https://github.com/tznind) vastly extended, improved, polished and fixed gui.cs to what it is today.
diff --git a/Terminal.Gui/Core/Application.cs b/Terminal.Gui/Core/Application.cs
index 5424daad0..4807aa60a 100644
--- a/Terminal.Gui/Core/Application.cs
+++ b/Terminal.Gui/Core/Application.cs
@@ -208,6 +208,9 @@ namespace Terminal.Gui {
// System.Diagnostics.Debugger.Break ();
//#endif
+ // Reset all class variables (Application is a singleton).
+ ResetState ();
+
// This supports Unit Tests and the passing of a mock driver/loopdriver
if (driver != null) {
if (mainLoopDriver == null) {
@@ -523,6 +526,14 @@ namespace Terminal.Gui {
///
public static void Shutdown ()
{
+ ResetState ();
+ }
+
+ // Encapsulate all setting of initial state for Application; Having
+ // this in a function like this ensures we don't make mistakes in
+ // guranteeing that the state of this singleton is deterministic when Init
+ // starts running and after Shutdown returns.
+ static void ResetState () {
// Shutdown is the bookend for Init. As such it needs to clean up all resources
// Init created. Apps that do any threading will need to code defensively for this.
// e.g. see Issue #537
@@ -538,6 +549,10 @@ namespace Terminal.Gui {
MainLoop = null;
Driver?.End ();
Driver = null;
+ Iteration = null;
+ UseSystemConsole = false;
+ RootMouseEvent = null;
+ Resized = null;
_initialized = false;
// Reset synchronization context to allow the user to run async/await,
@@ -547,6 +562,7 @@ namespace Terminal.Gui {
SynchronizationContext.SetSynchronizationContext (syncContext: null);
}
+
static void Redraw (View view)
{
view.Redraw (view.Bounds);
diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj
index cf7e761e5..5ff67c76d 100644
--- a/Terminal.Gui/Terminal.Gui.csproj
+++ b/Terminal.Gui/Terminal.Gui.csproj
@@ -5,8 +5,6 @@
Terminal.Gui
bin\Release\Terminal.Gui.xml
true
-
-
true
Terminal.Gui
MIT
diff --git a/Terminal.Gui/Views/TableView.cs b/Terminal.Gui/Views/TableView.cs
index 90c4cde91..d0ae87ae3 100644
--- a/Terminal.Gui/Views/TableView.cs
+++ b/Terminal.Gui/Views/TableView.cs
@@ -145,6 +145,43 @@ namespace Terminal.Gui {
///
public class TableView : View {
+ ///
+ /// Defines the event arguments for event
+ ///
+ public class CellActivatedEventArgs : EventArgs {
+ ///
+ /// The current table to which the new indexes refer. May be null e.g. if selection change is the result of clearing the table from the view
+ ///
+ ///
+ public DataTable Table { get; }
+
+
+ ///
+ /// The column index of the cell that is being activated
+ ///
+ ///
+ public int Col { get; }
+
+ ///
+ /// The row index of the cell that is being activated
+ ///
+ ///
+ public int Row { get; }
+
+ ///
+ /// Creates a new instance of arguments describing a cell being activated in
+ ///
+ ///
+ ///
+ ///
+ public CellActivatedEventArgs (DataTable t, int col, int row)
+ {
+ Table = t;
+ Col = col;
+ Row = row;
+ }
+ }
+
private int columnOffset;
private int rowOffset;
private int selectedRow;
@@ -1307,42 +1344,4 @@ namespace Terminal.Gui {
Rect = rect;
}
}
-
- ///
- /// Defines the event arguments for event
- ///
- public class CellActivatedEventArgs : EventArgs
- {
- ///
- /// The current table to which the new indexes refer. May be null e.g. if selection change is the result of clearing the table from the view
- ///
- ///
- public DataTable Table {get;}
-
-
- ///
- /// The column index of the cell that is being activated
- ///
- ///
- public int Col {get;}
-
- ///
- /// The row index of the cell that is being activated
- ///
- ///
- public int Row {get;}
-
- ///
- /// Creates a new instance of arguments describing a cell being activated in
- ///
- ///
- ///
- ///
- public CellActivatedEventArgs(DataTable t, int col, int row)
- {
- Table = t;
- Col = col;
- Row = row;
- }
- }
}
diff --git a/UICatalog/Scenarios/CsvEditor.cs b/UICatalog/Scenarios/CsvEditor.cs
index 10c57457f..895e934c8 100644
--- a/UICatalog/Scenarios/CsvEditor.cs
+++ b/UICatalog/Scenarios/CsvEditor.cs
@@ -504,7 +504,7 @@ namespace UICatalog.Scenarios {
enteredText = okPressed? tf.Text.ToString() : null;
return okPressed;
}
- private void EditCurrentCell (CellActivatedEventArgs e)
+ private void EditCurrentCell (TableView.CellActivatedEventArgs e)
{
if(e.Table == null)
return;
diff --git a/UICatalog/Scenarios/TableEditor.cs b/UICatalog/Scenarios/TableEditor.cs
index 9e32e9ca9..b82a6b9b0 100644
--- a/UICatalog/Scenarios/TableEditor.cs
+++ b/UICatalog/Scenarios/TableEditor.cs
@@ -273,7 +273,7 @@ namespace UICatalog.Scenarios {
tableView.Table = BuildSimpleDataTable(big ? 30 : 5, big ? 1000 : 5);
}
- private void EditCurrentCell (CellActivatedEventArgs e)
+ private void EditCurrentCell (TableView.CellActivatedEventArgs e)
{
if(e.Table == null)
return;
diff --git a/UnitTests/ApplicationTests.cs b/UnitTests/ApplicationTests.cs
index e88dae6ba..1a89c5615 100644
--- a/UnitTests/ApplicationTests.cs
+++ b/UnitTests/ApplicationTests.cs
@@ -1,18 +1,13 @@
using System;
-using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using Terminal.Gui;
using Xunit;
// Alais Console to MockConsole so we don't accidentally use Console
using Console = Terminal.Gui.FakeConsole;
-// Since Application is a singleton we can't run tests in parallel
-[assembly: CollectionBehavior (DisableTestParallelization = true)]
-
-namespace Terminal.Gui {
+namespace Terminal.Gui.Core {
public class ApplicationTests {
public ApplicationTests ()
{
@@ -24,26 +19,51 @@ namespace Terminal.Gui {
[Fact]
public void Init_Shutdown_Cleans_Up ()
{
- Assert.Null (Application.Current);
- Assert.Null (Application.Top);
- Assert.Null (Application.MainLoop);
- Assert.Null (Application.Driver);
+ // Verify inital state is per spec
+ Pre_Init_State ();
Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
- Assert.NotNull (Application.Current);
- Assert.NotNull (Application.Top);
- Assert.NotNull (Application.MainLoop);
- Assert.NotNull (Application.Driver);
+
+ // Verify post-Init state is correct
+ Post_Init_State ();
// MockDriver is always 80x25
Assert.Equal (80, Application.Driver.Cols);
Assert.Equal (25, Application.Driver.Rows);
Application.Shutdown ();
- Assert.Null (Application.Current);
- Assert.Null (Application.Top);
- Assert.Null (Application.MainLoop);
+
+ // Verify state is back to initial
+ Pre_Init_State ();
+
+ }
+
+ void Pre_Init_State ()
+ {
Assert.Null (Application.Driver);
+ Assert.Null (Application.Top);
+ Assert.Null (Application.Current);
+ Assert.Throws (() => Application.HeightAsBuffer == true);
+ Assert.False (Application.AlwaysSetPosition);
+ Assert.Null (Application.MainLoop);
+ Assert.Null (Application.Iteration);
+ Assert.False (Application.UseSystemConsole);
+ Assert.Null (Application.RootMouseEvent);
+ Assert.Null (Application.Resized);
+ }
+
+ void Post_Init_State ()
+ {
+ Assert.NotNull (Application.Driver);
+ Assert.NotNull (Application.Top);
+ Assert.NotNull (Application.Current);
+ Assert.False (Application.HeightAsBuffer);
+ Assert.False (Application.AlwaysSetPosition);
+ Assert.NotNull (Application.MainLoop);
+ Assert.Null (Application.Iteration);
+ Assert.False (Application.UseSystemConsole);
+ Assert.Null (Application.RootMouseEvent);
+ Assert.Null (Application.Resized);
}
[Fact]
diff --git a/UnitTests/AssemblyInfo.cs b/UnitTests/AssemblyInfo.cs
new file mode 100644
index 000000000..4dbc7cbe9
--- /dev/null
+++ b/UnitTests/AssemblyInfo.cs
@@ -0,0 +1,4 @@
+using Xunit;
+
+// Since Application is a singleton we can't run tests in parallel
+[assembly: CollectionBehavior (DisableTestParallelization = true)]
\ No newline at end of file
diff --git a/UnitTests/ConsoleDriverTests.cs b/UnitTests/ConsoleDriverTests.cs
index c241f9682..302f7c62a 100644
--- a/UnitTests/ConsoleDriverTests.cs
+++ b/UnitTests/ConsoleDriverTests.cs
@@ -5,7 +5,7 @@ using Xunit;
// Alais Console to MockConsole so we don't accidentally use Console
using Console = Terminal.Gui.FakeConsole;
-namespace Terminal.Gui {
+namespace Terminal.Gui.ConsoleDrivers {
public class ConsoleDriverTests {
[Fact]
public void Init_Inits ()
diff --git a/UnitTests/DimTests.cs b/UnitTests/DimTests.cs
index 9bbe6b7f3..074b5425c 100644
--- a/UnitTests/DimTests.cs
+++ b/UnitTests/DimTests.cs
@@ -11,7 +11,7 @@ using Xunit;
// Alais Console to MockConsole so we don't accidentally use Console
using Console = Terminal.Gui.FakeConsole;
-namespace Terminal.Gui {
+namespace Terminal.Gui.Core {
public class DimTests {
public DimTests ()
{
diff --git a/UnitTests/MainLoopTests.cs b/UnitTests/MainLoopTests.cs
index 2e9b85d40..c4b69b14a 100644
--- a/UnitTests/MainLoopTests.cs
+++ b/UnitTests/MainLoopTests.cs
@@ -12,7 +12,7 @@ using Xunit.Sdk;
// Alais Console to MockConsole so we don't accidentally use Console
using Console = Terminal.Gui.FakeConsole;
-namespace Terminal.Gui {
+namespace Terminal.Gui.Core {
public class MainLoopTests {
[Fact]
diff --git a/UnitTests/PointTests.cs b/UnitTests/PointTests.cs
index e04195001..95c1b3cf2 100644
--- a/UnitTests/PointTests.cs
+++ b/UnitTests/PointTests.cs
@@ -1,7 +1,7 @@
using System;
using Xunit;
-namespace Terminal.Gui {
+namespace Terminal.Gui.Types {
public class PointTests {
[Fact]
public void Point_New ()
@@ -20,7 +20,7 @@ namespace Terminal.Gui {
}
[Fact]
- public void Point__SetsValue ()
+ public void Point_SetsValue ()
{
var point = new Point () {
X = 0,
diff --git a/UnitTests/PosTests.cs b/UnitTests/PosTests.cs
index f1ab89b01..ec1e660ad 100644
--- a/UnitTests/PosTests.cs
+++ b/UnitTests/PosTests.cs
@@ -10,7 +10,7 @@ using Xunit;
// Alais Console to MockConsole so we don't accidentally use Console
using Console = Terminal.Gui.FakeConsole;
-namespace Terminal.Gui {
+namespace Terminal.Gui.Core {
public class PosTests {
[Fact]
public void New_Works ()
diff --git a/UnitTests/RectTests.cs b/UnitTests/RectTests.cs
index f2db24635..6a61085ac 100644
--- a/UnitTests/RectTests.cs
+++ b/UnitTests/RectTests.cs
@@ -1,7 +1,7 @@
using System;
using Xunit;
-namespace Terminal.Gui {
+namespace Terminal.Gui.Types {
public class RectTests {
[Fact]
public void Rect_New ()
@@ -33,7 +33,7 @@ namespace Terminal.Gui {
}
[Fact]
- public void Rect__SetsValue ()
+ public void Rect_SetsValue ()
{
var rect = new Rect () {
X = 0,
diff --git a/UnitTests/ResponderTests.cs b/UnitTests/ResponderTests.cs
index 65546e145..3f5ed7e5f 100644
--- a/UnitTests/ResponderTests.cs
+++ b/UnitTests/ResponderTests.cs
@@ -7,7 +7,7 @@ using Xunit;
// Alais Console to MockConsole so we don't accidentally use Console
using Console = Terminal.Gui.FakeConsole;
-namespace Terminal.Gui {
+namespace Terminal.Gui.Core {
public class ResponderTests {
[Fact]
public void New_Initializes ()
diff --git a/UnitTests/ScenarioTests.cs b/UnitTests/ScenarioTests.cs
index 138d60abd..41ddd2702 100644
--- a/UnitTests/ScenarioTests.cs
+++ b/UnitTests/ScenarioTests.cs
@@ -43,10 +43,14 @@ namespace Terminal.Gui {
Assert.NotEmpty (scenarioClasses);
foreach (var scenarioClass in scenarioClasses) {
+
// Setup some fake keypresses
// Passing empty string will cause just a ctrl-q to be fired
Console.MockKeyPresses.Clear ();
int stackSize = CreateInput ("");
+
+ Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
+
int iterations = 0;
Application.Iteration = () => {
iterations++;
@@ -55,7 +59,6 @@ namespace Terminal.Gui {
Application.RequestStop ();
}
};
- Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
var ms = 1000;
var abortCount = 0;
@@ -99,6 +102,8 @@ namespace Terminal.Gui {
// Passing empty string will cause just a ctrl-q to be fired
int stackSize = CreateInput ("");
+ Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
+
int iterations = 0;
Application.Iteration = () => {
iterations++;
@@ -107,7 +112,6 @@ namespace Terminal.Gui {
Application.RequestStop ();
}
};
- Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
var ms = 1000;
var abortCount = 0;
diff --git a/UnitTests/ScrollBarViewTests.cs b/UnitTests/ScrollBarViewTests.cs
index 1c58f9363..8a993a1ad 100644
--- a/UnitTests/ScrollBarViewTests.cs
+++ b/UnitTests/ScrollBarViewTests.cs
@@ -1,7 +1,7 @@
using System;
using Xunit;
-namespace Terminal.Gui {
+namespace Terminal.Gui.Views {
public class ScrollBarViewTests {
public class HostView : View {
public int Top { get; set; }
diff --git a/UnitTests/SizeTests.cs b/UnitTests/SizeTests.cs
index 8f924e9de..6924e9668 100644
--- a/UnitTests/SizeTests.cs
+++ b/UnitTests/SizeTests.cs
@@ -1,7 +1,7 @@
using System;
using Xunit;
-namespace Terminal.Gui {
+namespace Terminal.Gui.Types {
public class SizeTests {
[Fact]
public void Size_New ()
@@ -30,7 +30,7 @@ namespace Terminal.Gui {
}
[Fact]
- public void Size__SetsValue ()
+ public void Size_SetsValue ()
{
var size = new Size () {
Width = 0,
diff --git a/UnitTests/TabViewTests.cs b/UnitTests/TabViewTests.cs
index 45003583a..7bf03de8c 100644
--- a/UnitTests/TabViewTests.cs
+++ b/UnitTests/TabViewTests.cs
@@ -7,7 +7,7 @@ using Terminal.Gui;
using Xunit;
using System.Globalization;
-namespace UnitTests {
+namespace Terminal.Gui.Views {
public class TabViewTests {
private TabView GetTabView ()
{
diff --git a/UnitTests/TableViewTests.cs b/UnitTests/TableViewTests.cs
index fa39627fd..1a6e87029 100644
--- a/UnitTests/TableViewTests.cs
+++ b/UnitTests/TableViewTests.cs
@@ -7,7 +7,7 @@ using Terminal.Gui;
using Xunit;
using System.Globalization;
-namespace UnitTests {
+namespace Terminal.Gui.Views {
public class TableViewTests
{
diff --git a/UnitTests/TextFieldTests.cs b/UnitTests/TextFieldTests.cs
index ac08573c3..451506dce 100644
--- a/UnitTests/TextFieldTests.cs
+++ b/UnitTests/TextFieldTests.cs
@@ -1,6 +1,6 @@
using Xunit;
-namespace Terminal.Gui {
+namespace Terminal.Gui.Views {
public class TextFieldTests {
private TextField _textField;
diff --git a/UnitTests/TextFormatterTests.cs b/UnitTests/TextFormatterTests.cs
index c4b6b91de..4728ae73a 100644
--- a/UnitTests/TextFormatterTests.cs
+++ b/UnitTests/TextFormatterTests.cs
@@ -10,7 +10,7 @@ using Xunit;
// Alias Console to MockConsole so we don't accidentally use Console
using Console = Terminal.Gui.FakeConsole;
-namespace Terminal.Gui {
+namespace Terminal.Gui.Core {
public class TextFormatterTests {
[Fact]
diff --git a/UnitTests/TextViewTests.cs b/UnitTests/TextViewTests.cs
index ad88da55b..e03f93bee 100644
--- a/UnitTests/TextViewTests.cs
+++ b/UnitTests/TextViewTests.cs
@@ -1,7 +1,7 @@
using System;
using Xunit;
-namespace Terminal.Gui {
+namespace Terminal.Gui.Views {
public class TextViewTests {
private TextView _textView;
diff --git a/UnitTests/TreeViewTests.cs b/UnitTests/TreeViewTests.cs
index 8739d1d49..99360fa57 100644
--- a/UnitTests/TreeViewTests.cs
+++ b/UnitTests/TreeViewTests.cs
@@ -6,7 +6,7 @@ using System.Threading.Tasks;
using Terminal.Gui;
using Xunit;
-namespace UnitTests {
+namespace Terminal.Gui.Views {
public class TreeViewTests {
#region Test Setup Methods
class Factory {
diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj
index 7bf794559..6c9b9ff05 100644
--- a/UnitTests/UnitTests.csproj
+++ b/UnitTests/UnitTests.csproj
@@ -1,8 +1,9 @@
-
+
net5.0
false
+
@@ -15,6 +16,7 @@
+
@@ -32,4 +34,25 @@
+
+
+ True
+
+
+ [UICatalog]*
+
+
+
+
+
+
+
+
+
+
+ False
+
+
+
diff --git a/UnitTests/ViewTests.cs b/UnitTests/ViewTests.cs
index 42d1fe3a0..0a895e8e8 100644
--- a/UnitTests/ViewTests.cs
+++ b/UnitTests/ViewTests.cs
@@ -9,7 +9,7 @@ using Xunit;
// Alias Console to MockConsole so we don't accidentally use Console
using Console = Terminal.Gui.FakeConsole;
-namespace Terminal.Gui {
+namespace Terminal.Gui.Views {
public class ViewTests {
[Fact]
public void New_Initializes ()
@@ -944,10 +944,10 @@ namespace Terminal.Gui {
if (count1 == 5) {
log1 = true;
}
- if (count1 > 13 && count < 15) {
+ if (count1 == 14 && count2 == 10 && count == 15) { // count2 is already stopped
fromTopStillKnowFirstIsRunning = true;
}
- if (count2 > 6 && count2 < 8) {
+ if (count1 == 7 && count2 == 7 && count == 8) {
fromTopStillKnowSecondIsRunning = true;
}
if (count == 30) {
@@ -981,7 +981,7 @@ namespace Terminal.Gui {
if (count2 == 5) {
log2 = true;
}
- if (count2 > 3 && count2 < 5) {
+ if (count2 == 4 && count1 == 5 && count == 5) {
fromFirstStillKnowSecondIsRunning = true;
}
if (count1 == 20) {
diff --git a/UnitTests/coverlet.runsettings b/UnitTests/coverlet.runsettings
new file mode 100644
index 000000000..760e3718a
--- /dev/null
+++ b/UnitTests/coverlet.runsettings
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+ opencover
+ [UnitTests]*,[UICatalog]*,[coverlet.*.tests?]*,[*]Coverlet.Core*
+
+
+
+
+ false
+ true
+ true
+ true
+ false
+ TestResults/
+
+
+
+
+
\ No newline at end of file