From 574ed8fec7e63b646765bfa0023624c6f30bf17d Mon Sep 17 00:00:00 2001 From: Tig Date: Thu, 6 Apr 2023 10:09:21 -0600 Subject: [PATCH] Fixes #2469 - Revamp file structure and namespace (#2471) * initial commit * All tests pass * Updated readme * Revert "All tests pass" This reverts commit 94ac462350194307112d9ae0f32a7846299e3d3a. * Revert "initial commit" This reverts commit 36d92cc4e58792d8a2e90f974d2ca8c0463071ff. * Moved Terminal.Gui files around * Nuked .Graphs namespace * Nuked .Graphs namespace * Nuked .Trees namespace * Nuked .Configuration namespace * Nuked .Configuration namespace * All tests pass * tweaked tests * removed unneeded usings * re-enabled scrollview tests * move scrollview test to ScrollViewTests * Moved view navigation related tests to separate cs file * Moved view scrollbarview related tests ScrollBarTestse * Refactored View tests into smaller files * Refactored driver tests * Fixed a ton of BUGBUGs --- README.md | 2 +- Terminal.Gui/{Core => }/Application.cs | 4 +- Terminal.Gui/ClassDiagram1.cd | 2 - .../{Core => }/Clipboard/Clipboard.cs | 0 .../{Core => }/Clipboard/ClipboardBase.cs | 0 .../{Core => }/Clipboard/IClipboard.cs | 0 Terminal.Gui/Configuration/AppScope.cs | 4 +- .../Configuration/AttributeJsonConverter.cs | 2 +- .../Configuration/ColorJsonConverter.cs | 2 +- .../Configuration/ColorSchemeJsonConverter.cs | 2 +- .../Configuration/ConfigurationManager.cs | 4 +- .../ConfigurationManagerEventArgs.cs | 2 +- .../Configuration/DictionaryJsonConverter.cs | 2 +- .../Configuration/KeyJsonConverter.cs | 2 +- Terminal.Gui/Configuration/Scope.cs | 4 +- Terminal.Gui/Configuration/SettingsScope.cs | 2 +- Terminal.Gui/Configuration/ThemeScope.cs | 4 +- .../{Core => ConsoleDrivers}/ConsoleDriver.cs | 8 +- .../{Core/Graphs => Drawing}/LineCanvas.cs | 2 +- Terminal.Gui/Drawing/Ruler.cs | 2 - Terminal.Gui/{Core => Drawing}/Thickness.cs | 3 +- .../{Core => Drawing}/ThicknessEventArgs.cs | 0 Terminal.Gui/{Core => Input}/Command.cs | 0 .../{Core => Input}/ConsoleKeyMapping.cs | 0 .../{Core => Input}/EscSeqUtils/EscSeqReq.cs | 0 .../EscSeqUtils/EscSeqUtils.cs | 0 Terminal.Gui/{Core => Input}/Event.cs | 0 .../{Core => Input}/GrabMouseEventArgs.cs | 0 .../{Core => Input}/KeyChangedEventArgs.cs | 0 .../{Core => Input}/KeyEventEventArgs.cs | 0 .../KeystrokeNavigatorEventArgs.cs | 0 .../{Core => Input}/MouseEventEventArgs.cs | 0 .../MouseFlagsChangedEventArgs.cs | 0 .../{Core => Input}/PointEventArgs.cs | 0 Terminal.Gui/{Core => Input}/Responder.cs | 0 .../{Core => Input}/ShortcutHelper.cs | 0 Terminal.Gui/{Core => }/MainLoop.cs | 0 Terminal.Gui/README.md | 49 +- Terminal.Gui/{Core => }/RunStateEventArgs.cs | 0 Terminal.Gui/{Core => }/StackExtensions.cs | 0 .../Autocomplete/AppendAutocomplete.cs | 0 .../Autocomplete/Autocomplete.cd | 0 .../Autocomplete/AutocompleteBase.cs | 0 .../Autocomplete/AutocompleteContext.cs | 0 .../Autocomplete/IAutocomplete.cs | 0 .../Autocomplete/ISuggestionGenerator.cs | 0 .../Autocomplete/PopupAutocomplete.cs | 0 .../SingleWordSuggestionGenerator.cs | 0 .../{Core => Text}/Autocomplete/Suggestion.cs | 0 .../{Core => Text}/CollectionNavigator.cs | 0 Terminal.Gui/{Core => Text}/TextFormatter.cs | 0 Terminal.Gui/{Core => }/TimeoutEventArgs.cs | 0 Terminal.Gui/{Core => View}/Border.cs | 5 +- Terminal.Gui/{Core => View}/Frame.cs | 1 - Terminal.Gui/{Core => View/Layout}/PosDim.cs | 0 .../{Core => View/Layout}/ResizedEventArgs.cs | 0 .../Layout}/SizeChangedEventArgs.cs | 0 .../SuperViewChangedEventArgs.cs | 0 Terminal.Gui/{Core => View}/TitleEventArgs.cs | 0 .../{Core => View}/ToggleEventArgs.cs | 0 Terminal.Gui/{Core => View}/View.cs | 0 Terminal.Gui/{Core => View}/ViewEventArgs.cs | 0 Terminal.Gui/{Windows => Views}/Dialog.cs | 4 +- Terminal.Gui/{Windows => Views}/FileDialog.cs | 0 Terminal.Gui/Views/FrameView.cs | 2 +- .../Graphs => Views/GraphView}/Annotations.cs | 2 +- .../{Core/Graphs => Views/GraphView}/Axis.cs | 2 +- .../GraphView}/GraphCellToRender.cs | 2 +- .../Views/{ => GraphView}/GraphView.cs | 1 - .../Graphs => Views/GraphView}/Orientation.cs | 2 +- .../Graphs => Views/GraphView}/Series.cs | 2 +- Terminal.Gui/Views/LineView.cs | 1 - Terminal.Gui/{Windows => Views}/MessageBox.cs | 4 +- .../ReadOnlyCollectionExtensions.cs | 0 .../{ => TableView}/CellActivatedEventArgs.cs | 0 .../SelectedCellChangedEventArgs.cs | 0 .../Views/{ => TableView}/TableView.cs | 0 Terminal.Gui/Views/TextView.cs | 1 - Terminal.Gui/Views/TileView.cs | 1 - Terminal.Gui/{Core => Views}/Toplevel.cs | 0 .../{Core => Views}/ToplevelEventArgs.cs | 0 .../TreeView}/AspectGetterDelegate.cs | 2 +- .../{Core/Trees => Views/TreeView}/Branch.cs | 2 +- .../TreeView}/DelegateTreeBuilder.cs | 2 +- .../Trees => Views/TreeView}/ITreeBuilder.cs | 2 +- .../TreeView}/ObjectActivatedEventArgs.cs | 2 +- .../TreeView}/SelectionChangedEventArgs.cs | 2 +- .../Trees => Views/TreeView}/TreeBuilder.cs | 2 +- .../Trees => Views/TreeView}/TreeNode.cs | 2 +- .../TreeView}/TreeNodeBuilder.cs | 2 +- .../Trees => Views/TreeView}/TreeStyle.cs | 2 +- Terminal.Gui/Views/{ => TreeView}/TreeView.cs | 2 +- Terminal.Gui/{Core => Views}/Window.cs | 4 +- .../{Windows => Views/Wizard}/Wizard.cs | 0 .../Wizard}/WizardEventArgs.cs | 0 UICatalog/Scenario.cs | 1 - UICatalog/Scenarios/AllViewsTester.cs | 1 - UICatalog/Scenarios/ClassExplorer.cs | 1 - .../Scenarios/CollectionNavigatorTester.cs | 4 +- UICatalog/Scenarios/ComputedLayout.cs | 1 - UICatalog/Scenarios/ConfigurationEditor.cs | 10 +- UICatalog/Scenarios/CsvEditor.cs | 7 +- UICatalog/Scenarios/Dialogs.cs | 3 - UICatalog/Scenarios/Editor.cs | 3 +- UICatalog/Scenarios/Frames.cs | 7 +- UICatalog/Scenarios/Generic.cs | 5 - UICatalog/Scenarios/GraphViewExample.cs | 1 - UICatalog/Scenarios/InteractiveTree.cs | 5 - UICatalog/Scenarios/Keys.cs | 1 - UICatalog/Scenarios/LineDrawing.cs | 1 - UICatalog/Scenarios/LineViewExample.cs | 4 +- UICatalog/Scenarios/Notepad.cs | 1 - UICatalog/Scenarios/Snake.cs | 1 - UICatalog/Scenarios/TileViewExperiment.cs | 1 - UICatalog/Scenarios/TileViewNesting.cs | 5 +- UICatalog/Scenarios/TreeUseCases.cs | 3 - UICatalog/Scenarios/TreeViewFileSystem.cs | 2 - UICatalog/Scenarios/ViewExperiments.cs | 1 - UICatalog/UICatalog.cs | 12 +- UnitTests/Application/ApplicationTests.cs | 1 - .../{Drivers => Clipboard}/ClipboardTests.cs | 2 +- UnitTests/Configuration/AppScopeTests.cs | 4 +- .../Configuration/ConfigurationMangerTests.cs | 5 +- UnitTests/Configuration/JsonConverterTests.cs | 3 +- UnitTests/Configuration/SettingsScopeTests.cs | 4 +- UnitTests/Configuration/ThemeScopeTests.cs | 4 +- UnitTests/Configuration/ThemeTests.cs | 5 +- .../AttributeTests.cs | 2 +- .../{Drivers => ConsoleDrivers}/ColorTests.cs | 0 .../ConsoleDrivers/ConsoleDriverTests.cs | 298 ++ .../ConsoleDrivers/ConsoleScrolllingTests.cs | 157 + UnitTests/ConsoleDrivers/KeyTests.cs | 349 ++ UnitTests/Core/ViewTests.cs | 3099 ------------ .../{TopLevels => Dialogs}/DialogTests.cs | 2 +- .../{TopLevels => Dialogs}/MessageBoxTests.cs | 2 +- .../{TopLevels => Dialogs}/WizardTests.cs | 2 +- .../{Core => Drawing}/LineCanvasTests.cs | 3 +- UnitTests/Drawing/RulerTests.cs | 1 - UnitTests/{Core => Drawing}/ThicknessTests.cs | 3 +- UnitTests/Drivers/ConsoleDriverTests.cs | 673 --- UnitTests/Drivers/KeyTests.cs | 173 - UnitTests/{Core => Input}/EscSeqReqTests.cs | 2 +- UnitTests/{Core => Input}/EscSeqUtilsTests.cs | 2 +- UnitTests/{Core => Input}/ResponderTests.cs | 2 +- UnitTests/TestHelpers.cs | 6 +- .../{Views => Text}/AutocompleteTests.cs | 2 +- UnitTests/Text/UnicodeTests.cs | 87 + UnitTests/{Core => View}/BorderTests.cs | 2 +- UnitTests/{Core => View}/FrameTests.cs | 3 +- UnitTests/View/KeyboardTests.cs | 181 + .../Layout}/AbsoluteLayoutTests.cs | 3 +- UnitTests/{Types => View/Layout}/DimTests.cs | 8 +- .../{Core => View/Layout}/LayoutTests.cs | 5 +- UnitTests/{Types => View/Layout}/PosTests.cs | 6 +- UnitTests/View/NavigationTests.cs | 1084 ++++ UnitTests/View/TitleTests.cs | 74 + UnitTests/View/ViewTests.cs | 1550 ++++++ UnitTests/Views/AllViewsTests.cs | 2 +- UnitTests/Views/AppendAutocompleteTests.cs | 2 +- UnitTests/Views/ButtonTests.cs | 2 +- UnitTests/Views/CheckBoxTests.cs | 2 +- UnitTests/Views/ColorPickerTests.cs | 2 +- UnitTests/Views/ComboBoxTests.cs | 2 +- .../{Menus => Views}/ContextMenuTests.cs | 3 +- UnitTests/Views/DateFieldTests.cs | 2 +- UnitTests/Views/FrameViewTests.cs | 2 +- UnitTests/Views/GraphViewTests.cs | 4 +- UnitTests/Views/HexViewTests.cs | 2 +- UnitTests/Views/LineViewTests.cs | 5 +- UnitTests/Views/ListViewTests.cs | 2 +- UnitTests/{TopLevels => Views}/MdiTests.cs | 2 +- UnitTests/{Menus => Views}/MenuTests.cs | 38 +- UnitTests/Views/ProgressBarTests.cs | 2 +- UnitTests/Views/RadioGroupTests.cs | 2 +- UnitTests/Views/ScrollBarViewTests.cs | 90 +- UnitTests/Views/ScrollViewTests.cs | 328 +- UnitTests/Views/StatusBarTests.cs | 2 +- UnitTests/Views/TabViewTests.cs | 2 +- UnitTests/Views/TableViewTests.cs | 4 +- UnitTests/Views/TextFieldTests.cs | 2 +- UnitTests/Views/TextValidateFieldTests.cs | 2 +- UnitTests/Views/TextViewTests.cs | 3 +- UnitTests/Views/TileViewTests.cs | 4503 ++++++++--------- UnitTests/Views/TimeFieldTests.cs | 2 +- .../{TopLevels => Views}/ToplevelTests.cs | 4 +- UnitTests/Views/TreeViewTests.cs | 10 +- UnitTests/{TopLevels => Views}/WindowTests.cs | 56 +- 187 files changed, 6591 insertions(+), 6541 deletions(-) rename Terminal.Gui/{Core => }/Application.cs (99%) delete mode 100644 Terminal.Gui/ClassDiagram1.cd rename Terminal.Gui/{Core => }/Clipboard/Clipboard.cs (100%) rename Terminal.Gui/{Core => }/Clipboard/ClipboardBase.cs (100%) rename Terminal.Gui/{Core => }/Clipboard/IClipboard.cs (100%) rename Terminal.Gui/{Core => ConsoleDrivers}/ConsoleDriver.cs (99%) rename Terminal.Gui/{Core/Graphs => Drawing}/LineCanvas.cs (99%) rename Terminal.Gui/{Core => Drawing}/Thickness.cs (99%) rename Terminal.Gui/{Core => Drawing}/ThicknessEventArgs.cs (100%) rename Terminal.Gui/{Core => Input}/Command.cs (100%) rename Terminal.Gui/{Core => Input}/ConsoleKeyMapping.cs (100%) rename Terminal.Gui/{Core => Input}/EscSeqUtils/EscSeqReq.cs (100%) rename Terminal.Gui/{Core => Input}/EscSeqUtils/EscSeqUtils.cs (100%) rename Terminal.Gui/{Core => Input}/Event.cs (100%) rename Terminal.Gui/{Core => Input}/GrabMouseEventArgs.cs (100%) rename Terminal.Gui/{Core => Input}/KeyChangedEventArgs.cs (100%) rename Terminal.Gui/{Core => Input}/KeyEventEventArgs.cs (100%) rename Terminal.Gui/{Core => Input}/KeystrokeNavigatorEventArgs.cs (100%) rename Terminal.Gui/{Core => Input}/MouseEventEventArgs.cs (100%) rename Terminal.Gui/{Core => Input}/MouseFlagsChangedEventArgs.cs (100%) rename Terminal.Gui/{Core => Input}/PointEventArgs.cs (100%) rename Terminal.Gui/{Core => Input}/Responder.cs (100%) rename Terminal.Gui/{Core => Input}/ShortcutHelper.cs (100%) rename Terminal.Gui/{Core => }/MainLoop.cs (100%) rename Terminal.Gui/{Core => }/RunStateEventArgs.cs (100%) rename Terminal.Gui/{Core => }/StackExtensions.cs (100%) rename Terminal.Gui/{Core => Text}/Autocomplete/AppendAutocomplete.cs (100%) rename Terminal.Gui/{Core => Text}/Autocomplete/Autocomplete.cd (100%) rename Terminal.Gui/{Core => Text}/Autocomplete/AutocompleteBase.cs (100%) rename Terminal.Gui/{Core => Text}/Autocomplete/AutocompleteContext.cs (100%) rename Terminal.Gui/{Core => Text}/Autocomplete/IAutocomplete.cs (100%) rename Terminal.Gui/{Core => Text}/Autocomplete/ISuggestionGenerator.cs (100%) rename Terminal.Gui/{Core => Text}/Autocomplete/PopupAutocomplete.cs (100%) rename Terminal.Gui/{Core => Text}/Autocomplete/SingleWordSuggestionGenerator.cs (100%) rename Terminal.Gui/{Core => Text}/Autocomplete/Suggestion.cs (100%) rename Terminal.Gui/{Core => Text}/CollectionNavigator.cs (100%) rename Terminal.Gui/{Core => Text}/TextFormatter.cs (100%) rename Terminal.Gui/{Core => }/TimeoutEventArgs.cs (100%) rename Terminal.Gui/{Core => View}/Border.cs (94%) rename Terminal.Gui/{Core => View}/Frame.cs (99%) rename Terminal.Gui/{Core => View/Layout}/PosDim.cs (100%) rename Terminal.Gui/{Core => View/Layout}/ResizedEventArgs.cs (100%) rename Terminal.Gui/{Core => View/Layout}/SizeChangedEventArgs.cs (100%) rename Terminal.Gui/{Core => View}/SuperViewChangedEventArgs.cs (100%) rename Terminal.Gui/{Core => View}/TitleEventArgs.cs (100%) rename Terminal.Gui/{Core => View}/ToggleEventArgs.cs (100%) rename Terminal.Gui/{Core => View}/View.cs (100%) rename Terminal.Gui/{Core => View}/ViewEventArgs.cs (100%) rename Terminal.Gui/{Windows => Views}/Dialog.cs (98%) rename Terminal.Gui/{Windows => Views}/FileDialog.cs (100%) rename Terminal.Gui/{Core/Graphs => Views/GraphView}/Annotations.cs (99%) rename Terminal.Gui/{Core/Graphs => Views/GraphView}/Axis.cs (99%) rename Terminal.Gui/{Core/Graphs => Views/GraphView}/GraphCellToRender.cs (97%) rename Terminal.Gui/Views/{ => GraphView}/GraphView.cs (99%) rename Terminal.Gui/{Core/Graphs => Views/GraphView}/Orientation.cs (87%) rename Terminal.Gui/{Core/Graphs => Views/GraphView}/Series.cs (99%) rename Terminal.Gui/{Windows => Views}/MessageBox.cs (99%) rename Terminal.Gui/{Core => Views}/ReadOnlyCollectionExtensions.cs (100%) rename Terminal.Gui/Views/{ => TableView}/CellActivatedEventArgs.cs (100%) rename Terminal.Gui/Views/{ => TableView}/SelectedCellChangedEventArgs.cs (100%) rename Terminal.Gui/Views/{ => TableView}/TableView.cs (100%) rename Terminal.Gui/{Core => Views}/Toplevel.cs (100%) rename Terminal.Gui/{Core => Views}/ToplevelEventArgs.cs (100%) rename Terminal.Gui/{Core/Trees => Views/TreeView}/AspectGetterDelegate.cs (90%) rename Terminal.Gui/{Core/Trees => Views/TreeView}/Branch.cs (99%) rename Terminal.Gui/{Core/Trees => Views/TreeView}/DelegateTreeBuilder.cs (98%) rename Terminal.Gui/{Core/Trees => Views/TreeView}/ITreeBuilder.cs (97%) rename Terminal.Gui/{Core/Trees => Views/TreeView}/ObjectActivatedEventArgs.cs (96%) rename Terminal.Gui/{Core/Trees => Views/TreeView}/SelectionChangedEventArgs.cs (96%) rename Terminal.Gui/{Core/Trees => Views/TreeView}/TreeBuilder.cs (97%) rename Terminal.Gui/{Core/Trees => Views/TreeView}/TreeNode.cs (98%) rename Terminal.Gui/{Core/Trees => Views/TreeView}/TreeNodeBuilder.cs (95%) rename Terminal.Gui/{Core/Trees => Views/TreeView}/TreeStyle.cs (98%) rename Terminal.Gui/Views/{ => TreeView}/TreeView.cs (99%) rename Terminal.Gui/{Core => Views}/Window.cs (98%) rename Terminal.Gui/{Windows => Views/Wizard}/Wizard.cs (100%) rename Terminal.Gui/{Windows => Views/Wizard}/WizardEventArgs.cs (100%) rename UnitTests/{Drivers => Clipboard}/ClipboardTests.cs (99%) rename UnitTests/{Colors => ConsoleDrivers}/AttributeTests.cs (99%) rename UnitTests/{Drivers => ConsoleDrivers}/ColorTests.cs (100%) create mode 100644 UnitTests/ConsoleDrivers/ConsoleDriverTests.cs create mode 100644 UnitTests/ConsoleDrivers/ConsoleScrolllingTests.cs create mode 100644 UnitTests/ConsoleDrivers/KeyTests.cs delete mode 100644 UnitTests/Core/ViewTests.cs rename UnitTests/{TopLevels => Dialogs}/DialogTests.cs (99%) rename UnitTests/{TopLevels => Dialogs}/MessageBoxTests.cs (99%) rename UnitTests/{TopLevels => Dialogs}/WizardTests.cs (99%) rename UnitTests/{Core => Drawing}/LineCanvasTests.cs (99%) rename UnitTests/{Core => Drawing}/ThicknessTests.cs (99%) delete mode 100644 UnitTests/Drivers/ConsoleDriverTests.cs delete mode 100644 UnitTests/Drivers/KeyTests.cs rename UnitTests/{Core => Input}/EscSeqReqTests.cs (98%) rename UnitTests/{Core => Input}/EscSeqUtilsTests.cs (99%) rename UnitTests/{Core => Input}/ResponderTests.cs (98%) rename UnitTests/{Views => Text}/AutocompleteTests.cs (99%) create mode 100644 UnitTests/Text/UnicodeTests.cs rename UnitTests/{Core => View}/BorderTests.cs (99%) rename UnitTests/{Core => View}/FrameTests.cs (98%) create mode 100644 UnitTests/View/KeyboardTests.cs rename UnitTests/{Core => View/Layout}/AbsoluteLayoutTests.cs (99%) rename UnitTests/{Types => View/Layout}/DimTests.cs (99%) rename UnitTests/{Core => View/Layout}/LayoutTests.cs (99%) rename UnitTests/{Types => View/Layout}/PosTests.cs (99%) create mode 100644 UnitTests/View/NavigationTests.cs create mode 100644 UnitTests/View/TitleTests.cs create mode 100644 UnitTests/View/ViewTests.cs rename UnitTests/{Menus => Views}/ContextMenuTests.cs (99%) rename UnitTests/{TopLevels => Views}/MdiTests.cs (99%) rename UnitTests/{Menus => Views}/MenuTests.cs (98%) rename UnitTests/{TopLevels => Views}/ToplevelTests.cs (99%) rename UnitTests/{TopLevels => Views}/WindowTests.cs (82%) diff --git a/README.md b/README.md index 7a501dd06..ef01f27fc 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ _The Documentation matches the most recent Nuget release from the `main` branch * **[Flexible Layout](https://gui-cs.github.io/Terminal.Gui/articles/overview.html#layout)** - Supports both *Absolute layout* and an innovative *Computed Layout* system. *Computed Layout* makes it easy to layout controls relative to each other and enables dynamic terminal UIs. * **[Configuration & Themes](https://gui-cs.github.io/Terminal.Gui/articles/config.html)** - Terminal.Gui supports a rich configuration system that allows end-user customization of how the UI looks (e.g. colors) and behaves (e.g. key-bindings). * **Clipboard support** - Cut, Copy, and Paste of text provided through the [`Clipboard`](https://gui-cs.github.io/Terminal.Gui/api/Terminal.Gui/Terminal.Gui.Clipboard.html) class. -* **[Arbitrary Views](https://gui-cs.github.io/Terminal.Gui/api/Terminal.Gui/Terminal.Gui.View.html)** - All visible UI elements are subclasses of the `View` class, and these in turn can contain an arbitrary number of sub-views. +* **[Arbitrary Views](https://gui-cs.github.io/Terminal.Gui/api/Terminal.Gui/Terminal.Gui.ViewTests.html)** - All visible UI elements are subclasses of the `View` class, and these in turn can contain an arbitrary number of sub-views. * **Advanced App Features** - The [Mainloop](https://gui-cs.github.io/Terminal.Gui/api/Terminal.Gui/Terminal.Gui.MainLoop.html) supports processing events, idle handlers, timers, and monitoring file descriptors. Most classes are safe for threading. * **Reactive Extensions** - Use [reactive extensions](https://github.com/dotnet/reactive) and benefit from increased code readability, and the ability to apply the MVVM pattern and [ReactiveUI](https://www.reactiveui.net/) data bindings. See the [source code](https://github.com/gui-cs/Terminal.Gui/tree/master/ReactiveExample) of a sample app in order to learn how to achieve this. diff --git a/Terminal.Gui/Core/Application.cs b/Terminal.Gui/Application.cs similarity index 99% rename from Terminal.Gui/Core/Application.cs rename to Terminal.Gui/Application.cs index c72ec41f5..1939fe0b7 100644 --- a/Terminal.Gui/Core/Application.cs +++ b/Terminal.Gui/Application.cs @@ -20,9 +20,9 @@ using System.ComponentModel; using System.Globalization; using System.Reflection; using System.IO; -using Terminal.Gui.Configuration; +using Terminal.Gui; using System.Text.Json.Serialization; -using static Terminal.Gui.Configuration.ConfigurationManager; +using static Terminal.Gui.ConfigurationManager; namespace Terminal.Gui { diff --git a/Terminal.Gui/ClassDiagram1.cd b/Terminal.Gui/ClassDiagram1.cd deleted file mode 100644 index 7b894197b..000000000 --- a/Terminal.Gui/ClassDiagram1.cd +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/Terminal.Gui/Core/Clipboard/Clipboard.cs b/Terminal.Gui/Clipboard/Clipboard.cs similarity index 100% rename from Terminal.Gui/Core/Clipboard/Clipboard.cs rename to Terminal.Gui/Clipboard/Clipboard.cs diff --git a/Terminal.Gui/Core/Clipboard/ClipboardBase.cs b/Terminal.Gui/Clipboard/ClipboardBase.cs similarity index 100% rename from Terminal.Gui/Core/Clipboard/ClipboardBase.cs rename to Terminal.Gui/Clipboard/ClipboardBase.cs diff --git a/Terminal.Gui/Core/Clipboard/IClipboard.cs b/Terminal.Gui/Clipboard/IClipboard.cs similarity index 100% rename from Terminal.Gui/Core/Clipboard/IClipboard.cs rename to Terminal.Gui/Clipboard/IClipboard.cs diff --git a/Terminal.Gui/Configuration/AppScope.cs b/Terminal.Gui/Configuration/AppScope.cs index 46c7df349..da76d3d4d 100644 --- a/Terminal.Gui/Configuration/AppScope.cs +++ b/Terminal.Gui/Configuration/AppScope.cs @@ -5,11 +5,11 @@ using System.Diagnostics; using System.Linq; using System.Reflection; using System.Text.Json.Serialization; -using static Terminal.Gui.Configuration.ConfigurationManager; +using static Terminal.Gui.ConfigurationManager; #nullable enable -namespace Terminal.Gui.Configuration { +namespace Terminal.Gui { public static partial class ConfigurationManager { /// diff --git a/Terminal.Gui/Configuration/AttributeJsonConverter.cs b/Terminal.Gui/Configuration/AttributeJsonConverter.cs index 3e19fc5f1..5ef2c001e 100644 --- a/Terminal.Gui/Configuration/AttributeJsonConverter.cs +++ b/Terminal.Gui/Configuration/AttributeJsonConverter.cs @@ -3,7 +3,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using Terminal.Gui; -namespace Terminal.Gui.Configuration { +namespace Terminal.Gui { /// /// Json converter fro the class. /// diff --git a/Terminal.Gui/Configuration/ColorJsonConverter.cs b/Terminal.Gui/Configuration/ColorJsonConverter.cs index 24896df69..93ae8317e 100644 --- a/Terminal.Gui/Configuration/ColorJsonConverter.cs +++ b/Terminal.Gui/Configuration/ColorJsonConverter.cs @@ -3,7 +3,7 @@ using System.Text.Json.Serialization; using System.Text.Json; using System.Text.RegularExpressions; -namespace Terminal.Gui.Configuration { +namespace Terminal.Gui { /// /// Json converter for the class. /// diff --git a/Terminal.Gui/Configuration/ColorSchemeJsonConverter.cs b/Terminal.Gui/Configuration/ColorSchemeJsonConverter.cs index 2f4044a22..0c036bd65 100644 --- a/Terminal.Gui/Configuration/ColorSchemeJsonConverter.cs +++ b/Terminal.Gui/Configuration/ColorSchemeJsonConverter.cs @@ -2,7 +2,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace Terminal.Gui.Configuration { +namespace Terminal.Gui { /// /// Implements a JSON converter for . /// diff --git a/Terminal.Gui/Configuration/ConfigurationManager.cs b/Terminal.Gui/Configuration/ConfigurationManager.cs index 6048294dd..d642f863c 100644 --- a/Terminal.Gui/Configuration/ConfigurationManager.cs +++ b/Terminal.Gui/Configuration/ConfigurationManager.cs @@ -9,11 +9,11 @@ using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; -using static Terminal.Gui.Configuration.ConfigurationManager; +using static Terminal.Gui.ConfigurationManager; #nullable enable -namespace Terminal.Gui.Configuration { +namespace Terminal.Gui { /// /// Provides settings and configuration management for Terminal.Gui applications. /// diff --git a/Terminal.Gui/Configuration/ConfigurationManagerEventArgs.cs b/Terminal.Gui/Configuration/ConfigurationManagerEventArgs.cs index 74acce2ec..7e191a7df 100644 --- a/Terminal.Gui/Configuration/ConfigurationManagerEventArgs.cs +++ b/Terminal.Gui/Configuration/ConfigurationManagerEventArgs.cs @@ -2,7 +2,7 @@ #nullable enable -namespace Terminal.Gui.Configuration { +namespace Terminal.Gui { /// /// Event arguments for the events. /// diff --git a/Terminal.Gui/Configuration/DictionaryJsonConverter.cs b/Terminal.Gui/Configuration/DictionaryJsonConverter.cs index aea4bf51e..e8218e5cf 100644 --- a/Terminal.Gui/Configuration/DictionaryJsonConverter.cs +++ b/Terminal.Gui/Configuration/DictionaryJsonConverter.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Text.Json.Serialization; using System.Text.Json; -namespace Terminal.Gui.Configuration { +namespace Terminal.Gui { class DictionaryJsonConverter : JsonConverter> { public override Dictionary Read (ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) diff --git a/Terminal.Gui/Configuration/KeyJsonConverter.cs b/Terminal.Gui/Configuration/KeyJsonConverter.cs index 26a258f54..216689d18 100644 --- a/Terminal.Gui/Configuration/KeyJsonConverter.cs +++ b/Terminal.Gui/Configuration/KeyJsonConverter.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; -namespace Terminal.Gui.Configuration { +namespace Terminal.Gui { /// /// Json converter for the class. /// diff --git a/Terminal.Gui/Configuration/Scope.cs b/Terminal.Gui/Configuration/Scope.cs index da4e5c43f..078ff17e6 100644 --- a/Terminal.Gui/Configuration/Scope.cs +++ b/Terminal.Gui/Configuration/Scope.cs @@ -5,12 +5,12 @@ using System.Linq; using System.Reflection; using System.Text.Json; using System.Text.Json.Serialization; -using static Terminal.Gui.Configuration.ConfigurationManager; +using static Terminal.Gui.ConfigurationManager; #nullable enable -namespace Terminal.Gui.Configuration { +namespace Terminal.Gui { public static partial class ConfigurationManager { /// diff --git a/Terminal.Gui/Configuration/SettingsScope.cs b/Terminal.Gui/Configuration/SettingsScope.cs index 0c36af658..49d6f1839 100644 --- a/Terminal.Gui/Configuration/SettingsScope.cs +++ b/Terminal.Gui/Configuration/SettingsScope.cs @@ -9,7 +9,7 @@ using System.Text.Json.Serialization; #nullable enable -namespace Terminal.Gui.Configuration { +namespace Terminal.Gui { public static partial class ConfigurationManager { /// /// The root object of Terminal.Gui configuration settings / JSON schema. Contains only properties diff --git a/Terminal.Gui/Configuration/ThemeScope.cs b/Terminal.Gui/Configuration/ThemeScope.cs index 6b5ee2eb0..3bab13810 100644 --- a/Terminal.Gui/Configuration/ThemeScope.cs +++ b/Terminal.Gui/Configuration/ThemeScope.cs @@ -5,11 +5,11 @@ using System.Diagnostics; using System.Linq; using System.Reflection; using System.Text.Json.Serialization; -using static Terminal.Gui.Configuration.ConfigurationManager; +using static Terminal.Gui.ConfigurationManager; #nullable enable -namespace Terminal.Gui.Configuration { +namespace Terminal.Gui { public static partial class ConfigurationManager { /// diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs similarity index 99% rename from Terminal.Gui/Core/ConsoleDriver.cs rename to Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs index ce6737329..a357a173f 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs @@ -10,8 +10,8 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Text.Json.Serialization; using System.Threading.Tasks; -using Terminal.Gui.Configuration; -using static Terminal.Gui.Configuration.ConfigurationManager; +using Terminal.Gui; +using static Terminal.Gui.ConfigurationManager; namespace Terminal.Gui { /// @@ -187,13 +187,13 @@ namespace Terminal.Gui { /// /// The foreground color. /// - [JsonConverter (typeof (Configuration.ColorJsonConverter))] + [JsonConverter (typeof (ColorJsonConverter))] public Color Foreground { get; } /// /// The background color. /// - [JsonConverter (typeof (Configuration.ColorJsonConverter))] + [JsonConverter (typeof (ColorJsonConverter))] public Color Background { get; } /// diff --git a/Terminal.Gui/Core/Graphs/LineCanvas.cs b/Terminal.Gui/Drawing/LineCanvas.cs similarity index 99% rename from Terminal.Gui/Core/Graphs/LineCanvas.cs rename to Terminal.Gui/Drawing/LineCanvas.cs index c8c7a126b..a56a18c5d 100644 --- a/Terminal.Gui/Core/Graphs/LineCanvas.cs +++ b/Terminal.Gui/Drawing/LineCanvas.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; -namespace Terminal.Gui.Graphs { +namespace Terminal.Gui { /// diff --git a/Terminal.Gui/Drawing/Ruler.cs b/Terminal.Gui/Drawing/Ruler.cs index 36484e3d8..138f6bde4 100644 --- a/Terminal.Gui/Drawing/Ruler.cs +++ b/Terminal.Gui/Drawing/Ruler.cs @@ -4,8 +4,6 @@ using System.Collections.Generic; using System.Data; using System.Text; using System.Text.Json.Serialization; -using Terminal.Gui.Configuration; -using Terminal.Gui.Graphs; namespace Terminal.Gui { /// diff --git a/Terminal.Gui/Core/Thickness.cs b/Terminal.Gui/Drawing/Thickness.cs similarity index 99% rename from Terminal.Gui/Core/Thickness.cs rename to Terminal.Gui/Drawing/Thickness.cs index 33e584237..e9576746a 100644 --- a/Terminal.Gui/Core/Thickness.cs +++ b/Terminal.Gui/Drawing/Thickness.cs @@ -3,8 +3,7 @@ using System; using System.Collections.Generic; using System.Text; using System.Text.Json.Serialization; -using Terminal.Gui.Configuration; -using Terminal.Gui.Graphs; +using Terminal.Gui; namespace Terminal.Gui { /// diff --git a/Terminal.Gui/Core/ThicknessEventArgs.cs b/Terminal.Gui/Drawing/ThicknessEventArgs.cs similarity index 100% rename from Terminal.Gui/Core/ThicknessEventArgs.cs rename to Terminal.Gui/Drawing/ThicknessEventArgs.cs diff --git a/Terminal.Gui/Core/Command.cs b/Terminal.Gui/Input/Command.cs similarity index 100% rename from Terminal.Gui/Core/Command.cs rename to Terminal.Gui/Input/Command.cs diff --git a/Terminal.Gui/Core/ConsoleKeyMapping.cs b/Terminal.Gui/Input/ConsoleKeyMapping.cs similarity index 100% rename from Terminal.Gui/Core/ConsoleKeyMapping.cs rename to Terminal.Gui/Input/ConsoleKeyMapping.cs diff --git a/Terminal.Gui/Core/EscSeqUtils/EscSeqReq.cs b/Terminal.Gui/Input/EscSeqUtils/EscSeqReq.cs similarity index 100% rename from Terminal.Gui/Core/EscSeqUtils/EscSeqReq.cs rename to Terminal.Gui/Input/EscSeqUtils/EscSeqReq.cs diff --git a/Terminal.Gui/Core/EscSeqUtils/EscSeqUtils.cs b/Terminal.Gui/Input/EscSeqUtils/EscSeqUtils.cs similarity index 100% rename from Terminal.Gui/Core/EscSeqUtils/EscSeqUtils.cs rename to Terminal.Gui/Input/EscSeqUtils/EscSeqUtils.cs diff --git a/Terminal.Gui/Core/Event.cs b/Terminal.Gui/Input/Event.cs similarity index 100% rename from Terminal.Gui/Core/Event.cs rename to Terminal.Gui/Input/Event.cs diff --git a/Terminal.Gui/Core/GrabMouseEventArgs.cs b/Terminal.Gui/Input/GrabMouseEventArgs.cs similarity index 100% rename from Terminal.Gui/Core/GrabMouseEventArgs.cs rename to Terminal.Gui/Input/GrabMouseEventArgs.cs diff --git a/Terminal.Gui/Core/KeyChangedEventArgs.cs b/Terminal.Gui/Input/KeyChangedEventArgs.cs similarity index 100% rename from Terminal.Gui/Core/KeyChangedEventArgs.cs rename to Terminal.Gui/Input/KeyChangedEventArgs.cs diff --git a/Terminal.Gui/Core/KeyEventEventArgs.cs b/Terminal.Gui/Input/KeyEventEventArgs.cs similarity index 100% rename from Terminal.Gui/Core/KeyEventEventArgs.cs rename to Terminal.Gui/Input/KeyEventEventArgs.cs diff --git a/Terminal.Gui/Core/KeystrokeNavigatorEventArgs.cs b/Terminal.Gui/Input/KeystrokeNavigatorEventArgs.cs similarity index 100% rename from Terminal.Gui/Core/KeystrokeNavigatorEventArgs.cs rename to Terminal.Gui/Input/KeystrokeNavigatorEventArgs.cs diff --git a/Terminal.Gui/Core/MouseEventEventArgs.cs b/Terminal.Gui/Input/MouseEventEventArgs.cs similarity index 100% rename from Terminal.Gui/Core/MouseEventEventArgs.cs rename to Terminal.Gui/Input/MouseEventEventArgs.cs diff --git a/Terminal.Gui/Core/MouseFlagsChangedEventArgs.cs b/Terminal.Gui/Input/MouseFlagsChangedEventArgs.cs similarity index 100% rename from Terminal.Gui/Core/MouseFlagsChangedEventArgs.cs rename to Terminal.Gui/Input/MouseFlagsChangedEventArgs.cs diff --git a/Terminal.Gui/Core/PointEventArgs.cs b/Terminal.Gui/Input/PointEventArgs.cs similarity index 100% rename from Terminal.Gui/Core/PointEventArgs.cs rename to Terminal.Gui/Input/PointEventArgs.cs diff --git a/Terminal.Gui/Core/Responder.cs b/Terminal.Gui/Input/Responder.cs similarity index 100% rename from Terminal.Gui/Core/Responder.cs rename to Terminal.Gui/Input/Responder.cs diff --git a/Terminal.Gui/Core/ShortcutHelper.cs b/Terminal.Gui/Input/ShortcutHelper.cs similarity index 100% rename from Terminal.Gui/Core/ShortcutHelper.cs rename to Terminal.Gui/Input/ShortcutHelper.cs diff --git a/Terminal.Gui/Core/MainLoop.cs b/Terminal.Gui/MainLoop.cs similarity index 100% rename from Terminal.Gui/Core/MainLoop.cs rename to Terminal.Gui/MainLoop.cs diff --git a/Terminal.Gui/README.md b/Terminal.Gui/README.md index 81d337f30..a8b431e91 100644 --- a/Terminal.Gui/README.md +++ b/Terminal.Gui/README.md @@ -4,21 +4,42 @@ All files required to build the **Terminal.Gui** library (and NuGet package). ## Project Folder Structure -- `Terminal.Gui.sln` - The Visual Studio solution -- `Core/` - Source files for all types that comprise the core building blocks of **Terminal-Gui** - - `Application` - A `static` class that provides the base 'application driver'. Given it defines a **Terminal.Gui** application it is both logically and literally (because `static`) a singleton. It has direct dependencies on `MainLoop`, `Events.cs` `NetDriver`, `CursesDriver`, `WindowsDriver`, `Responder`, `View`, and `TopLevel` (and nothing else). - - `MainLoop` - Defines `IMainLoopDriver` and implements the `MainLoop` class. - - `ConsoleDriver` - Definition for the Console Driver API. - - `Events.cs` - Defines keyboard and mouse-related structs & classes. - - `PosDim.cs` - Implements *Computed Layout* system. These classes have deep dependencies on `View`. - - `Responder` - Base class for the windowing class hierarchy. Implements support for keyboard & mouse input. - - `View` - Derived from `Responder`, the base class for non-modal visual elements such as controls. - - `Toplevel` - Derived from `View`, the base class for modal visual elements such as top-level windows and dialogs. Supports the concept of `MenuBar` and `StatusBar`. - - `Window` - Derived from `TopLevel`; implements toplevel views with a visible frame and Title. +- `\` - The root folder contains the source code for the library. + - `Terminal.Gui.sln` - The Visual Studio solution + - `Application.cs` - A `static` class that provides the base 'application driver'. Given it defines a **Terminal.Gui** application it is both logically and literally (because `static`) a singleton. It has direct dependencies on `MainLoop`, `Events.cs` `NetDriver`, `CursesDriver`, `WindowsDriver`, `Responder`, `View`, and `TopLevel` (and nothing else). + - `MainLoop.cs` - Defines `IMainLoopDriver` and implements the `MainLoop` class. + - A few supporting class files + +- `ConsoleDrivers\` + - `ConsoleDriver.cs` - Definition for the Console Driver API. + - Source files for the three `ConsoleDriver`-based drivers: .NET: `NetDriver`, Unix & Mac: `UnixDriver`, and Windows: `WindowsDriver`. + +- `Configuration\` - Classes related the `ConfigurationManager`. + +- `Clipboard\` - Classes related to clipboard access. + +- `Input\` - Classes relating to keyboard and mouse input. Includes `Responder`, which is the base class for `View` + - `Events.cs` - Defines keyboard and mouse-related structs & classes. + - `Responder` - Base class for the windowing class hierarchy. Implements support for keyboard & mouse input. + - etc... + +- `Text\` - Classes related to text processing + +- `Drawing\` - Classes related to drawing + +- `View\` - The `View` class heirarchy, not including any sub-classes + - `View.cs` - Derived from `Responder`, the base class for non-modal visual elements such as controls. + - `Layout\` + - `PosDim.cs` - Implements *Computed Layout* system. These classes have deep dependencies on `View`. + +- `Views\` - Sub-classes of `View` + - `Toplevel` - Derived from `View`, the base class for modal visual elements such as top-level windows and dialogs. Supports the concept of `MenuBar` and `StatusBar`. + - `Window` - Derived from `TopLevel`; implements toplevel views with a visible frame and Title. + - `Dialog` - + - etc... + - `Types/` - A folder (not namespace) containing implementations of `Point`, `Rect`, and `Size` which are ancient versions of the modern `System.Drawing.Point`, `System.Drawing.Size`, and `System.Drawning.Rectangle`. -- `ConsoleDrivers/` - Source files for the three `ConsoleDriver`-based drivers: .NET: `NetDriver`, Unix & Mac: `UnixDriver`, and Windows: `WindowsDriver`. -- `Views/` - A folder (not namespace) containing the source for all built-in classes that drive from `View` (non-modals). -- `Windows/` - A folder (not namespace) containing the source of all built-in classes that derive from `Window`. + ## Version numbers diff --git a/Terminal.Gui/Core/RunStateEventArgs.cs b/Terminal.Gui/RunStateEventArgs.cs similarity index 100% rename from Terminal.Gui/Core/RunStateEventArgs.cs rename to Terminal.Gui/RunStateEventArgs.cs diff --git a/Terminal.Gui/Core/StackExtensions.cs b/Terminal.Gui/StackExtensions.cs similarity index 100% rename from Terminal.Gui/Core/StackExtensions.cs rename to Terminal.Gui/StackExtensions.cs diff --git a/Terminal.Gui/Core/Autocomplete/AppendAutocomplete.cs b/Terminal.Gui/Text/Autocomplete/AppendAutocomplete.cs similarity index 100% rename from Terminal.Gui/Core/Autocomplete/AppendAutocomplete.cs rename to Terminal.Gui/Text/Autocomplete/AppendAutocomplete.cs diff --git a/Terminal.Gui/Core/Autocomplete/Autocomplete.cd b/Terminal.Gui/Text/Autocomplete/Autocomplete.cd similarity index 100% rename from Terminal.Gui/Core/Autocomplete/Autocomplete.cd rename to Terminal.Gui/Text/Autocomplete/Autocomplete.cd diff --git a/Terminal.Gui/Core/Autocomplete/AutocompleteBase.cs b/Terminal.Gui/Text/Autocomplete/AutocompleteBase.cs similarity index 100% rename from Terminal.Gui/Core/Autocomplete/AutocompleteBase.cs rename to Terminal.Gui/Text/Autocomplete/AutocompleteBase.cs diff --git a/Terminal.Gui/Core/Autocomplete/AutocompleteContext.cs b/Terminal.Gui/Text/Autocomplete/AutocompleteContext.cs similarity index 100% rename from Terminal.Gui/Core/Autocomplete/AutocompleteContext.cs rename to Terminal.Gui/Text/Autocomplete/AutocompleteContext.cs diff --git a/Terminal.Gui/Core/Autocomplete/IAutocomplete.cs b/Terminal.Gui/Text/Autocomplete/IAutocomplete.cs similarity index 100% rename from Terminal.Gui/Core/Autocomplete/IAutocomplete.cs rename to Terminal.Gui/Text/Autocomplete/IAutocomplete.cs diff --git a/Terminal.Gui/Core/Autocomplete/ISuggestionGenerator.cs b/Terminal.Gui/Text/Autocomplete/ISuggestionGenerator.cs similarity index 100% rename from Terminal.Gui/Core/Autocomplete/ISuggestionGenerator.cs rename to Terminal.Gui/Text/Autocomplete/ISuggestionGenerator.cs diff --git a/Terminal.Gui/Core/Autocomplete/PopupAutocomplete.cs b/Terminal.Gui/Text/Autocomplete/PopupAutocomplete.cs similarity index 100% rename from Terminal.Gui/Core/Autocomplete/PopupAutocomplete.cs rename to Terminal.Gui/Text/Autocomplete/PopupAutocomplete.cs diff --git a/Terminal.Gui/Core/Autocomplete/SingleWordSuggestionGenerator.cs b/Terminal.Gui/Text/Autocomplete/SingleWordSuggestionGenerator.cs similarity index 100% rename from Terminal.Gui/Core/Autocomplete/SingleWordSuggestionGenerator.cs rename to Terminal.Gui/Text/Autocomplete/SingleWordSuggestionGenerator.cs diff --git a/Terminal.Gui/Core/Autocomplete/Suggestion.cs b/Terminal.Gui/Text/Autocomplete/Suggestion.cs similarity index 100% rename from Terminal.Gui/Core/Autocomplete/Suggestion.cs rename to Terminal.Gui/Text/Autocomplete/Suggestion.cs diff --git a/Terminal.Gui/Core/CollectionNavigator.cs b/Terminal.Gui/Text/CollectionNavigator.cs similarity index 100% rename from Terminal.Gui/Core/CollectionNavigator.cs rename to Terminal.Gui/Text/CollectionNavigator.cs diff --git a/Terminal.Gui/Core/TextFormatter.cs b/Terminal.Gui/Text/TextFormatter.cs similarity index 100% rename from Terminal.Gui/Core/TextFormatter.cs rename to Terminal.Gui/Text/TextFormatter.cs diff --git a/Terminal.Gui/Core/TimeoutEventArgs.cs b/Terminal.Gui/TimeoutEventArgs.cs similarity index 100% rename from Terminal.Gui/Core/TimeoutEventArgs.cs rename to Terminal.Gui/TimeoutEventArgs.cs diff --git a/Terminal.Gui/Core/Border.cs b/Terminal.Gui/View/Border.cs similarity index 94% rename from Terminal.Gui/Core/Border.cs rename to Terminal.Gui/View/Border.cs index 8bddc5b80..80fe7c853 100644 --- a/Terminal.Gui/Core/Border.cs +++ b/Terminal.Gui/View/Border.cs @@ -1,6 +1,5 @@ using NStack; using System; -using Terminal.Gui.Graphs; using System.Text.Json.Serialization; using System.Data; using System.Text; @@ -63,7 +62,7 @@ namespace Terminal.Gui { /// /// Gets or sets the that draws the outer border color. /// - [JsonInclude, JsonConverter (typeof (Configuration.ColorJsonConverter))] + [JsonInclude, JsonConverter (typeof (ColorJsonConverter))] public Color ForgroundColor { get => _forgroundColor; set { @@ -75,7 +74,7 @@ namespace Terminal.Gui { /// /// Gets or sets the that fills the area between the bounds of a . /// - [JsonInclude, JsonConverter (typeof (Configuration.ColorJsonConverter))] + [JsonInclude, JsonConverter (typeof (ColorJsonConverter))] public Color BackgroundColor { get => _backgroundColor; set { diff --git a/Terminal.Gui/Core/Frame.cs b/Terminal.Gui/View/Frame.cs similarity index 99% rename from Terminal.Gui/Core/Frame.cs rename to Terminal.Gui/View/Frame.cs index e89752ba2..6bc6c7c5e 100644 --- a/Terminal.Gui/Core/Frame.cs +++ b/Terminal.Gui/View/Frame.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; using System.Xml.Linq; -using Terminal.Gui.Graphs; namespace Terminal.Gui { diff --git a/Terminal.Gui/Core/PosDim.cs b/Terminal.Gui/View/Layout/PosDim.cs similarity index 100% rename from Terminal.Gui/Core/PosDim.cs rename to Terminal.Gui/View/Layout/PosDim.cs diff --git a/Terminal.Gui/Core/ResizedEventArgs.cs b/Terminal.Gui/View/Layout/ResizedEventArgs.cs similarity index 100% rename from Terminal.Gui/Core/ResizedEventArgs.cs rename to Terminal.Gui/View/Layout/ResizedEventArgs.cs diff --git a/Terminal.Gui/Core/SizeChangedEventArgs.cs b/Terminal.Gui/View/Layout/SizeChangedEventArgs.cs similarity index 100% rename from Terminal.Gui/Core/SizeChangedEventArgs.cs rename to Terminal.Gui/View/Layout/SizeChangedEventArgs.cs diff --git a/Terminal.Gui/Core/SuperViewChangedEventArgs.cs b/Terminal.Gui/View/SuperViewChangedEventArgs.cs similarity index 100% rename from Terminal.Gui/Core/SuperViewChangedEventArgs.cs rename to Terminal.Gui/View/SuperViewChangedEventArgs.cs diff --git a/Terminal.Gui/Core/TitleEventArgs.cs b/Terminal.Gui/View/TitleEventArgs.cs similarity index 100% rename from Terminal.Gui/Core/TitleEventArgs.cs rename to Terminal.Gui/View/TitleEventArgs.cs diff --git a/Terminal.Gui/Core/ToggleEventArgs.cs b/Terminal.Gui/View/ToggleEventArgs.cs similarity index 100% rename from Terminal.Gui/Core/ToggleEventArgs.cs rename to Terminal.Gui/View/ToggleEventArgs.cs diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/View/View.cs similarity index 100% rename from Terminal.Gui/Core/View.cs rename to Terminal.Gui/View/View.cs diff --git a/Terminal.Gui/Core/ViewEventArgs.cs b/Terminal.Gui/View/ViewEventArgs.cs similarity index 100% rename from Terminal.Gui/Core/ViewEventArgs.cs rename to Terminal.Gui/View/ViewEventArgs.cs diff --git a/Terminal.Gui/Windows/Dialog.cs b/Terminal.Gui/Views/Dialog.cs similarity index 98% rename from Terminal.Gui/Windows/Dialog.cs rename to Terminal.Gui/Views/Dialog.cs index bed044823..8b7203c6b 100644 --- a/Terminal.Gui/Windows/Dialog.cs +++ b/Terminal.Gui/Views/Dialog.cs @@ -9,8 +9,8 @@ using System.Collections.Generic; using System.Linq; using System.Text.Json.Serialization; using NStack; -using Terminal.Gui.Configuration; -using static Terminal.Gui.Configuration.ConfigurationManager; +using Terminal.Gui; +using static Terminal.Gui.ConfigurationManager; namespace Terminal.Gui { /// diff --git a/Terminal.Gui/Windows/FileDialog.cs b/Terminal.Gui/Views/FileDialog.cs similarity index 100% rename from Terminal.Gui/Windows/FileDialog.cs rename to Terminal.Gui/Views/FileDialog.cs diff --git a/Terminal.Gui/Views/FrameView.cs b/Terminal.Gui/Views/FrameView.cs index 78d67ecdf..5e9133eb8 100644 --- a/Terminal.Gui/Views/FrameView.cs +++ b/Terminal.Gui/Views/FrameView.cs @@ -2,7 +2,7 @@ using System.Linq; using System.Text.Json.Serialization; using NStack; -using static Terminal.Gui.Configuration.ConfigurationManager; +using static Terminal.Gui.ConfigurationManager; namespace Terminal.Gui { /// diff --git a/Terminal.Gui/Core/Graphs/Annotations.cs b/Terminal.Gui/Views/GraphView/Annotations.cs similarity index 99% rename from Terminal.Gui/Core/Graphs/Annotations.cs rename to Terminal.Gui/Views/GraphView/Annotations.cs index 226aab839..bdfbad122 100644 --- a/Terminal.Gui/Core/Graphs/Annotations.cs +++ b/Terminal.Gui/Views/GraphView/Annotations.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; -namespace Terminal.Gui.Graphs { +namespace Terminal.Gui { /// /// Describes an overlay element that is rendered either before or /// after a series. diff --git a/Terminal.Gui/Core/Graphs/Axis.cs b/Terminal.Gui/Views/GraphView/Axis.cs similarity index 99% rename from Terminal.Gui/Core/Graphs/Axis.cs rename to Terminal.Gui/Views/GraphView/Axis.cs index 847d55fce..8e4fbf0ea 100644 --- a/Terminal.Gui/Core/Graphs/Axis.cs +++ b/Terminal.Gui/Views/GraphView/Axis.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace Terminal.Gui.Graphs { +namespace Terminal.Gui { /// /// Renders a continuous line with grid line ticks and labels diff --git a/Terminal.Gui/Core/Graphs/GraphCellToRender.cs b/Terminal.Gui/Views/GraphView/GraphCellToRender.cs similarity index 97% rename from Terminal.Gui/Core/Graphs/GraphCellToRender.cs rename to Terminal.Gui/Views/GraphView/GraphCellToRender.cs index 402fafef3..46586a747 100644 --- a/Terminal.Gui/Core/Graphs/GraphCellToRender.cs +++ b/Terminal.Gui/Views/GraphView/GraphCellToRender.cs @@ -1,6 +1,6 @@ using System; -namespace Terminal.Gui.Graphs { +namespace Terminal.Gui { /// /// Describes how to render a single row/column of a based /// on the value(s) in at that location diff --git a/Terminal.Gui/Views/GraphView.cs b/Terminal.Gui/Views/GraphView/GraphView.cs similarity index 99% rename from Terminal.Gui/Views/GraphView.cs rename to Terminal.Gui/Views/GraphView/GraphView.cs index 48c62a760..668175880 100644 --- a/Terminal.Gui/Views/GraphView.cs +++ b/Terminal.Gui/Views/GraphView/GraphView.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Terminal.Gui.Graphs; namespace Terminal.Gui { diff --git a/Terminal.Gui/Core/Graphs/Orientation.cs b/Terminal.Gui/Views/GraphView/Orientation.cs similarity index 87% rename from Terminal.Gui/Core/Graphs/Orientation.cs rename to Terminal.Gui/Views/GraphView/Orientation.cs index 1b7d34a02..73eb0fe9a 100644 --- a/Terminal.Gui/Core/Graphs/Orientation.cs +++ b/Terminal.Gui/Views/GraphView/Orientation.cs @@ -1,4 +1,4 @@ -namespace Terminal.Gui.Graphs { +namespace Terminal.Gui { /// /// Direction of an element (horizontal or vertical) /// diff --git a/Terminal.Gui/Core/Graphs/Series.cs b/Terminal.Gui/Views/GraphView/Series.cs similarity index 99% rename from Terminal.Gui/Core/Graphs/Series.cs rename to Terminal.Gui/Views/GraphView/Series.cs index 48b66e37d..bf7040a01 100644 --- a/Terminal.Gui/Core/Graphs/Series.cs +++ b/Terminal.Gui/Views/GraphView/Series.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -namespace Terminal.Gui.Graphs { +namespace Terminal.Gui { /// /// Describes a series of data that can be rendered into a > /// diff --git a/Terminal.Gui/Views/LineView.cs b/Terminal.Gui/Views/LineView.cs index fa3f87b0d..a84c8b4cf 100644 --- a/Terminal.Gui/Views/LineView.cs +++ b/Terminal.Gui/Views/LineView.cs @@ -1,5 +1,4 @@ using System; -using Terminal.Gui.Graphs; namespace Terminal.Gui { diff --git a/Terminal.Gui/Windows/MessageBox.cs b/Terminal.Gui/Views/MessageBox.cs similarity index 99% rename from Terminal.Gui/Windows/MessageBox.cs rename to Terminal.Gui/Views/MessageBox.cs index 5af8b9c57..b46d7b9fa 100644 --- a/Terminal.Gui/Windows/MessageBox.cs +++ b/Terminal.Gui/Views/MessageBox.cs @@ -1,8 +1,8 @@ using NStack; using System; using System.Collections.Generic; -using Terminal.Gui.Configuration; -using static Terminal.Gui.Configuration.ConfigurationManager; +using Terminal.Gui; +using static Terminal.Gui.ConfigurationManager; namespace Terminal.Gui { /// diff --git a/Terminal.Gui/Core/ReadOnlyCollectionExtensions.cs b/Terminal.Gui/Views/ReadOnlyCollectionExtensions.cs similarity index 100% rename from Terminal.Gui/Core/ReadOnlyCollectionExtensions.cs rename to Terminal.Gui/Views/ReadOnlyCollectionExtensions.cs diff --git a/Terminal.Gui/Views/CellActivatedEventArgs.cs b/Terminal.Gui/Views/TableView/CellActivatedEventArgs.cs similarity index 100% rename from Terminal.Gui/Views/CellActivatedEventArgs.cs rename to Terminal.Gui/Views/TableView/CellActivatedEventArgs.cs diff --git a/Terminal.Gui/Views/SelectedCellChangedEventArgs.cs b/Terminal.Gui/Views/TableView/SelectedCellChangedEventArgs.cs similarity index 100% rename from Terminal.Gui/Views/SelectedCellChangedEventArgs.cs rename to Terminal.Gui/Views/TableView/SelectedCellChangedEventArgs.cs diff --git a/Terminal.Gui/Views/TableView.cs b/Terminal.Gui/Views/TableView/TableView.cs similarity index 100% rename from Terminal.Gui/Views/TableView.cs rename to Terminal.Gui/Views/TableView/TableView.cs diff --git a/Terminal.Gui/Views/TextView.cs b/Terminal.Gui/Views/TextView.cs index be3b73784..8ca6634ff 100644 --- a/Terminal.Gui/Views/TextView.cs +++ b/Terminal.Gui/Views/TextView.cs @@ -9,7 +9,6 @@ using System.Text; using System.Threading; using NStack; using Terminal.Gui.Resources; -using static Terminal.Gui.Graphs.PathAnnotation; using Rune = System.Rune; namespace Terminal.Gui { diff --git a/Terminal.Gui/Views/TileView.cs b/Terminal.Gui/Views/TileView.cs index 6dc9ef5db..14db0582c 100644 --- a/Terminal.Gui/Views/TileView.cs +++ b/Terminal.Gui/Views/TileView.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Terminal.Gui.Graphs; namespace Terminal.Gui { diff --git a/Terminal.Gui/Core/Toplevel.cs b/Terminal.Gui/Views/Toplevel.cs similarity index 100% rename from Terminal.Gui/Core/Toplevel.cs rename to Terminal.Gui/Views/Toplevel.cs diff --git a/Terminal.Gui/Core/ToplevelEventArgs.cs b/Terminal.Gui/Views/ToplevelEventArgs.cs similarity index 100% rename from Terminal.Gui/Core/ToplevelEventArgs.cs rename to Terminal.Gui/Views/ToplevelEventArgs.cs diff --git a/Terminal.Gui/Core/Trees/AspectGetterDelegate.cs b/Terminal.Gui/Views/TreeView/AspectGetterDelegate.cs similarity index 90% rename from Terminal.Gui/Core/Trees/AspectGetterDelegate.cs rename to Terminal.Gui/Views/TreeView/AspectGetterDelegate.cs index 0afe47f90..3afc1031b 100644 --- a/Terminal.Gui/Core/Trees/AspectGetterDelegate.cs +++ b/Terminal.Gui/Views/TreeView/AspectGetterDelegate.cs @@ -1,5 +1,5 @@  -namespace Terminal.Gui.Trees { +namespace Terminal.Gui { /// /// Delegates of this type are used to fetch string representations of user's model objects diff --git a/Terminal.Gui/Core/Trees/Branch.cs b/Terminal.Gui/Views/TreeView/Branch.cs similarity index 99% rename from Terminal.Gui/Core/Trees/Branch.cs rename to Terminal.Gui/Views/TreeView/Branch.cs index ce699af6b..f09fd14f3 100644 --- a/Terminal.Gui/Core/Trees/Branch.cs +++ b/Terminal.Gui/Views/TreeView/Branch.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; -namespace Terminal.Gui.Trees { +namespace Terminal.Gui { class Branch where T : class { /// /// True if the branch is expanded to reveal child branches. diff --git a/Terminal.Gui/Core/Trees/DelegateTreeBuilder.cs b/Terminal.Gui/Views/TreeView/DelegateTreeBuilder.cs similarity index 98% rename from Terminal.Gui/Core/Trees/DelegateTreeBuilder.cs rename to Terminal.Gui/Views/TreeView/DelegateTreeBuilder.cs index a277b49cc..0c1834851 100644 --- a/Terminal.Gui/Core/Trees/DelegateTreeBuilder.cs +++ b/Terminal.Gui/Views/TreeView/DelegateTreeBuilder.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace Terminal.Gui.Trees { +namespace Terminal.Gui { /// /// Implementation of that uses user defined functions /// diff --git a/Terminal.Gui/Core/Trees/ITreeBuilder.cs b/Terminal.Gui/Views/TreeView/ITreeBuilder.cs similarity index 97% rename from Terminal.Gui/Core/Trees/ITreeBuilder.cs rename to Terminal.Gui/Views/TreeView/ITreeBuilder.cs index d23d00f77..94b7d43bd 100644 --- a/Terminal.Gui/Core/Trees/ITreeBuilder.cs +++ b/Terminal.Gui/Views/TreeView/ITreeBuilder.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Terminal.Gui.Trees { +namespace Terminal.Gui { /// /// Interface for supplying data to a on demand as root level nodes /// are expanded by the user diff --git a/Terminal.Gui/Core/Trees/ObjectActivatedEventArgs.cs b/Terminal.Gui/Views/TreeView/ObjectActivatedEventArgs.cs similarity index 96% rename from Terminal.Gui/Core/Trees/ObjectActivatedEventArgs.cs rename to Terminal.Gui/Views/TreeView/ObjectActivatedEventArgs.cs index e4dd95af7..46c576076 100644 --- a/Terminal.Gui/Core/Trees/ObjectActivatedEventArgs.cs +++ b/Terminal.Gui/Views/TreeView/ObjectActivatedEventArgs.cs @@ -1,4 +1,4 @@ -namespace Terminal.Gui.Trees { +namespace Terminal.Gui { /// /// Event args for the event /// diff --git a/Terminal.Gui/Core/Trees/SelectionChangedEventArgs.cs b/Terminal.Gui/Views/TreeView/SelectionChangedEventArgs.cs similarity index 96% rename from Terminal.Gui/Core/Trees/SelectionChangedEventArgs.cs rename to Terminal.Gui/Views/TreeView/SelectionChangedEventArgs.cs index b84687f4a..eb1b3d70f 100644 --- a/Terminal.Gui/Core/Trees/SelectionChangedEventArgs.cs +++ b/Terminal.Gui/Views/TreeView/SelectionChangedEventArgs.cs @@ -1,6 +1,6 @@ using System; -namespace Terminal.Gui.Trees { +namespace Terminal.Gui { /// /// Event arguments describing a change in selected object in a tree view /// diff --git a/Terminal.Gui/Core/Trees/TreeBuilder.cs b/Terminal.Gui/Views/TreeView/TreeBuilder.cs similarity index 97% rename from Terminal.Gui/Core/Trees/TreeBuilder.cs rename to Terminal.Gui/Views/TreeView/TreeBuilder.cs index 15c4e806d..f93970481 100644 --- a/Terminal.Gui/Core/Trees/TreeBuilder.cs +++ b/Terminal.Gui/Views/TreeView/TreeBuilder.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; -namespace Terminal.Gui.Trees { +namespace Terminal.Gui { /// /// Abstract implementation of . diff --git a/Terminal.Gui/Core/Trees/TreeNode.cs b/Terminal.Gui/Views/TreeView/TreeNode.cs similarity index 98% rename from Terminal.Gui/Core/Trees/TreeNode.cs rename to Terminal.Gui/Views/TreeView/TreeNode.cs index 379f8f7f2..5ae07ae19 100644 --- a/Terminal.Gui/Core/Trees/TreeNode.cs +++ b/Terminal.Gui/Views/TreeView/TreeNode.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Terminal.Gui.Trees { +namespace Terminal.Gui { /// /// Interface to implement when you want the regular (non generic) diff --git a/Terminal.Gui/Core/Trees/TreeNodeBuilder.cs b/Terminal.Gui/Views/TreeView/TreeNodeBuilder.cs similarity index 95% rename from Terminal.Gui/Core/Trees/TreeNodeBuilder.cs rename to Terminal.Gui/Views/TreeView/TreeNodeBuilder.cs index c81aa8aef..8369d0ce0 100644 --- a/Terminal.Gui/Core/Trees/TreeNodeBuilder.cs +++ b/Terminal.Gui/Views/TreeView/TreeNodeBuilder.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Terminal.Gui.Trees { +namespace Terminal.Gui { /// /// implementation for objects /// diff --git a/Terminal.Gui/Core/Trees/TreeStyle.cs b/Terminal.Gui/Views/TreeView/TreeStyle.cs similarity index 98% rename from Terminal.Gui/Core/Trees/TreeStyle.cs rename to Terminal.Gui/Views/TreeView/TreeStyle.cs index 744ed6974..12a636b26 100644 --- a/Terminal.Gui/Core/Trees/TreeStyle.cs +++ b/Terminal.Gui/Views/TreeView/TreeStyle.cs @@ -1,6 +1,6 @@ using System; -namespace Terminal.Gui.Trees { +namespace Terminal.Gui { /// /// Defines rendering options that affect how the tree is displayed. /// diff --git a/Terminal.Gui/Views/TreeView.cs b/Terminal.Gui/Views/TreeView/TreeView.cs similarity index 99% rename from Terminal.Gui/Views/TreeView.cs rename to Terminal.Gui/Views/TreeView/TreeView.cs index 0b619e893..e69c42e34 100644 --- a/Terminal.Gui/Views/TreeView.cs +++ b/Terminal.Gui/Views/TreeView/TreeView.cs @@ -7,7 +7,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using Terminal.Gui.Trees; +using Terminal.Gui; namespace Terminal.Gui { diff --git a/Terminal.Gui/Core/Window.cs b/Terminal.Gui/Views/Window.cs similarity index 98% rename from Terminal.Gui/Core/Window.cs rename to Terminal.Gui/Views/Window.cs index e5cb0f623..b0ac74b57 100644 --- a/Terminal.Gui/Core/Window.cs +++ b/Terminal.Gui/Views/Window.cs @@ -2,8 +2,8 @@ using System.Collections; using System.Text.Json.Serialization; using NStack; -using Terminal.Gui.Configuration; -using static Terminal.Gui.Configuration.ConfigurationManager; +using Terminal.Gui; +using static Terminal.Gui.ConfigurationManager; namespace Terminal.Gui { diff --git a/Terminal.Gui/Windows/Wizard.cs b/Terminal.Gui/Views/Wizard/Wizard.cs similarity index 100% rename from Terminal.Gui/Windows/Wizard.cs rename to Terminal.Gui/Views/Wizard/Wizard.cs diff --git a/Terminal.Gui/Windows/WizardEventArgs.cs b/Terminal.Gui/Views/Wizard/WizardEventArgs.cs similarity index 100% rename from Terminal.Gui/Windows/WizardEventArgs.cs rename to Terminal.Gui/Views/Wizard/WizardEventArgs.cs diff --git a/UICatalog/Scenario.cs b/UICatalog/Scenario.cs index 88c58a114..d52c45ac3 100644 --- a/UICatalog/Scenario.cs +++ b/UICatalog/Scenario.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; using System.Linq; using Terminal.Gui; -using Terminal.Gui.Configuration; namespace UICatalog { /// diff --git a/UICatalog/Scenarios/AllViewsTester.cs b/UICatalog/Scenarios/AllViewsTester.cs index c1db8ba62..febe96012 100644 --- a/UICatalog/Scenarios/AllViewsTester.cs +++ b/UICatalog/Scenarios/AllViewsTester.cs @@ -7,7 +7,6 @@ using System.Linq; using System.Reflection; using System.Text; using Terminal.Gui; -using Terminal.Gui.Configuration; namespace UICatalog.Scenarios { [ScenarioMetadata (Name: "All Views Tester", Description: "Provides a test UI for all classes derived from View.")] diff --git a/UICatalog/Scenarios/ClassExplorer.cs b/UICatalog/Scenarios/ClassExplorer.cs index acbc6b539..7f282bbe1 100644 --- a/UICatalog/Scenarios/ClassExplorer.cs +++ b/UICatalog/Scenarios/ClassExplorer.cs @@ -5,7 +5,6 @@ using System.Reflection; using System.Text; using System.Threading.Tasks; using Terminal.Gui; -using Terminal.Gui.Trees; namespace UICatalog.Scenarios { diff --git a/UICatalog/Scenarios/CollectionNavigatorTester.cs b/UICatalog/Scenarios/CollectionNavigatorTester.cs index ca09bfed3..993e993b8 100644 --- a/UICatalog/Scenarios/CollectionNavigatorTester.cs +++ b/UICatalog/Scenarios/CollectionNavigatorTester.cs @@ -1,8 +1,6 @@ using System; -using System.IO; using System.Linq; using Terminal.Gui; -using Terminal.Gui.Trees; namespace UICatalog.Scenarios { @@ -107,7 +105,7 @@ namespace UICatalog.Scenarios { _items.Sort (StringComparer.OrdinalIgnoreCase); CreateListView (); - var vsep = new LineView (Terminal.Gui.Graphs.Orientation.Vertical) { + var vsep = new LineView (Orientation.Vertical) { X = Pos.Right (_listView), Y = 1, Height = Dim.Fill () diff --git a/UICatalog/Scenarios/ComputedLayout.cs b/UICatalog/Scenarios/ComputedLayout.cs index 6647f062f..62afd54d3 100644 --- a/UICatalog/Scenarios/ComputedLayout.cs +++ b/UICatalog/Scenarios/ComputedLayout.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Reflection; using System.Text; using Terminal.Gui; -using Terminal.Gui.Configuration; namespace UICatalog.Scenarios { /// diff --git a/UICatalog/Scenarios/ConfigurationEditor.cs b/UICatalog/Scenarios/ConfigurationEditor.cs index ebb4bb435..758a48a3f 100644 --- a/UICatalog/Scenarios/ConfigurationEditor.cs +++ b/UICatalog/Scenarios/ConfigurationEditor.cs @@ -1,13 +1,9 @@ -using NStack; -using System; -using System.Diagnostics.Metrics; +using System; using System.IO; using System.Linq; using System.Reflection; -using System.Text.Json.Serialization; using Terminal.Gui; -using Terminal.Gui.Configuration; -using static Terminal.Gui.Configuration.ConfigurationManager; +using static Terminal.Gui.ConfigurationManager; using Attribute = Terminal.Gui.Attribute; namespace UICatalog.Scenarios { @@ -49,7 +45,7 @@ namespace UICatalog.Scenarios { _tileView = new TileView (0) { Width = Dim.Fill (), Height = Dim.Fill (1), - Orientation = Terminal.Gui.Graphs.Orientation.Vertical, + Orientation = Orientation.Vertical, Border = new Border () { BorderStyle = BorderStyle.Single } }; diff --git a/UICatalog/Scenarios/CsvEditor.cs b/UICatalog/Scenarios/CsvEditor.cs index a9e300e6c..971a6587c 100644 --- a/UICatalog/Scenarios/CsvEditor.cs +++ b/UICatalog/Scenarios/CsvEditor.cs @@ -1,14 +1,11 @@ using System; -using System.Collections.Generic; using System.Data; -using Terminal.Gui; -using Terminal.Gui.Trees; using System.Linq; using System.Globalization; using System.IO; -using System.Text; -using NStack; using System.Text.RegularExpressions; +using NStack; +using Terminal.Gui; using CsvHelper; namespace UICatalog.Scenarios { diff --git a/UICatalog/Scenarios/Dialogs.cs b/UICatalog/Scenarios/Dialogs.cs index eb8a43c73..0d7124eac 100644 --- a/UICatalog/Scenarios/Dialogs.cs +++ b/UICatalog/Scenarios/Dialogs.cs @@ -1,10 +1,7 @@ using NStack; using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using Terminal.Gui; -using Terminal.Gui.Configuration; namespace UICatalog.Scenarios { [ScenarioMetadata (Name: "Dialogs", Description: "Demonstrates how to the Dialog class")] diff --git a/UICatalog/Scenarios/Editor.cs b/UICatalog/Scenarios/Editor.cs index 64a03d9a5..b2ae6aa14 100644 --- a/UICatalog/Scenarios/Editor.cs +++ b/UICatalog/Scenarios/Editor.cs @@ -1,12 +1,11 @@ using System; using System.Collections.Generic; using System.Text; -using Terminal.Gui; using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Globalization; -using Terminal.Gui.Configuration; +using Terminal.Gui; namespace UICatalog.Scenarios { [ScenarioMetadata (Name: "Editor", Description: "A Text Editor using the TextView control.")] diff --git a/UICatalog/Scenarios/Frames.cs b/UICatalog/Scenarios/Frames.cs index 0d6041048..39ad35977 100644 --- a/UICatalog/Scenarios/Frames.cs +++ b/UICatalog/Scenarios/Frames.cs @@ -1,9 +1,6 @@ -using System.Globalization; -using System; -using Terminal.Gui; +using System; using System.Linq; -using NStack; -using Terminal.Gui.Configuration; +using Terminal.Gui; namespace UICatalog.Scenarios { [ScenarioMetadata (Name: "Frames Demo", Description: "Demonstrates Margin, Border, and Padding on Views.")] diff --git a/UICatalog/Scenarios/Generic.cs b/UICatalog/Scenarios/Generic.cs index 9f9085a29..f2719bccb 100644 --- a/UICatalog/Scenarios/Generic.cs +++ b/UICatalog/Scenarios/Generic.cs @@ -1,9 +1,4 @@ -using NStack; -using System; -using System.Reflection.Emit; using Terminal.Gui; -using Terminal.Gui.Configuration; -using Label = Terminal.Gui.Label; namespace UICatalog.Scenarios { [ScenarioMetadata (Name: "Generic", Description: "Generic sample - A template for creating new Scenarios")] diff --git a/UICatalog/Scenarios/GraphViewExample.cs b/UICatalog/Scenarios/GraphViewExample.cs index 300250545..d822200ae 100644 --- a/UICatalog/Scenarios/GraphViewExample.cs +++ b/UICatalog/Scenarios/GraphViewExample.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using Terminal.Gui; -using Terminal.Gui.Graphs; using Color = Terminal.Gui.Color; diff --git a/UICatalog/Scenarios/InteractiveTree.cs b/UICatalog/Scenarios/InteractiveTree.cs index cf581b725..e6b576f20 100644 --- a/UICatalog/Scenarios/InteractiveTree.cs +++ b/UICatalog/Scenarios/InteractiveTree.cs @@ -1,11 +1,6 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using Terminal.Gui; -using Terminal.Gui.Trees; -using static UICatalog.Scenario; namespace UICatalog.Scenarios { diff --git a/UICatalog/Scenarios/Keys.cs b/UICatalog/Scenarios/Keys.cs index 796103c2c..2354fb60c 100644 --- a/UICatalog/Scenarios/Keys.cs +++ b/UICatalog/Scenarios/Keys.cs @@ -1,7 +1,6 @@ using NStack; using System.Collections.Generic; using Terminal.Gui; -using Terminal.Gui.Configuration; namespace UICatalog.Scenarios { [ScenarioMetadata (Name: "Keys", Description: "Shows how to handle keyboard input")] diff --git a/UICatalog/Scenarios/LineDrawing.cs b/UICatalog/Scenarios/LineDrawing.cs index f5670c0c4..c31ec65d0 100644 --- a/UICatalog/Scenarios/LineDrawing.cs +++ b/UICatalog/Scenarios/LineDrawing.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Reflection.Metadata.Ecma335; using Terminal.Gui; -using Terminal.Gui.Graphs; namespace UICatalog.Scenarios { diff --git a/UICatalog/Scenarios/LineViewExample.cs b/UICatalog/Scenarios/LineViewExample.cs index a4e4e7ac4..13fe14397 100644 --- a/UICatalog/Scenarios/LineViewExample.cs +++ b/UICatalog/Scenarios/LineViewExample.cs @@ -73,7 +73,7 @@ namespace UICatalog.Scenarios { Win.Add (new Label ("Vertical Line") { Y = 9,X=11 }); // creates a horizontal line - var verticalLine = new LineView (Terminal.Gui.Graphs.Orientation.Vertical) { + var verticalLine = new LineView (Orientation.Vertical) { X = 25, }; @@ -83,7 +83,7 @@ namespace UICatalog.Scenarios { Win.Add (new Label ("Vertical Arrow") { Y = 11, X = 28 }); // creates a horizontal line - var verticalArrow = new LineView (Terminal.Gui.Graphs.Orientation.Vertical) { + var verticalArrow = new LineView (Orientation.Vertical) { X = 27, StartingAnchor = Application.Driver.TopTee, EndingAnchor = 'V' diff --git a/UICatalog/Scenarios/Notepad.cs b/UICatalog/Scenarios/Notepad.cs index d88c42890..33ce0d92a 100644 --- a/UICatalog/Scenarios/Notepad.cs +++ b/UICatalog/Scenarios/Notepad.cs @@ -2,7 +2,6 @@ using System.IO; using System.Linq; using Terminal.Gui; -using Terminal.Gui.Graphs; namespace UICatalog.Scenarios { diff --git a/UICatalog/Scenarios/Snake.cs b/UICatalog/Scenarios/Snake.cs index e07f97c3f..d609dee7d 100644 --- a/UICatalog/Scenarios/Snake.cs +++ b/UICatalog/Scenarios/Snake.cs @@ -4,7 +4,6 @@ using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using Terminal.Gui; -using Terminal.Gui.Graphs; using Attribute = Terminal.Gui.Attribute; namespace UICatalog.Scenarios { diff --git a/UICatalog/Scenarios/TileViewExperiment.cs b/UICatalog/Scenarios/TileViewExperiment.cs index 6182e1e70..47ff81e8b 100644 --- a/UICatalog/Scenarios/TileViewExperiment.cs +++ b/UICatalog/Scenarios/TileViewExperiment.cs @@ -1,6 +1,5 @@ using System; using Terminal.Gui; -using Terminal.Gui.Graphs; using System.Linq; namespace UICatalog.Scenarios { diff --git a/UICatalog/Scenarios/TileViewNesting.cs b/UICatalog/Scenarios/TileViewNesting.cs index f5f58466f..a6b0d1d8f 100644 --- a/UICatalog/Scenarios/TileViewNesting.cs +++ b/UICatalog/Scenarios/TileViewNesting.cs @@ -1,6 +1,5 @@ using System; using Terminal.Gui; -using Terminal.Gui.Graphs; using System.Linq; namespace UICatalog.Scenarios { @@ -104,8 +103,8 @@ namespace UICatalog.Scenarios { } var root = CreateTileView (1, (bool)startHorizontal ? - Terminal.Gui.Graphs.Orientation.Horizontal : - Terminal.Gui.Graphs.Orientation.Vertical); + Orientation.Horizontal : + Orientation.Vertical); root.Tiles.ElementAt (0).ContentView.Add (CreateContentControl (1)); root.Tiles.ElementAt (0).Title = (bool)cbTitles.Checked ? $"View 1" : string.Empty; diff --git a/UICatalog/Scenarios/TreeUseCases.cs b/UICatalog/Scenarios/TreeUseCases.cs index eeba69ee3..00f339bbb 100644 --- a/UICatalog/Scenarios/TreeUseCases.cs +++ b/UICatalog/Scenarios/TreeUseCases.cs @@ -1,9 +1,6 @@ -using System; using System.Collections.Generic; -using System.IO; using System.Linq; using Terminal.Gui; -using Terminal.Gui.Trees; namespace UICatalog.Scenarios { [ScenarioMetadata (Name: "Tree View", Description: "Simple tree view examples.")] diff --git a/UICatalog/Scenarios/TreeViewFileSystem.cs b/UICatalog/Scenarios/TreeViewFileSystem.cs index 73b0d8a94..10be681d7 100644 --- a/UICatalog/Scenarios/TreeViewFileSystem.cs +++ b/UICatalog/Scenarios/TreeViewFileSystem.cs @@ -2,9 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Reflection.PortableExecutable; using Terminal.Gui; -using Terminal.Gui.Trees; namespace UICatalog.Scenarios { [ScenarioMetadata (Name: "File System Explorer", Description: "Hierarchical file system explorer demonstrating TreeView.")] diff --git a/UICatalog/Scenarios/ViewExperiments.cs b/UICatalog/Scenarios/ViewExperiments.cs index f84e94236..3a809dd4e 100644 --- a/UICatalog/Scenarios/ViewExperiments.cs +++ b/UICatalog/Scenarios/ViewExperiments.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using Terminal.Gui; -using Terminal.Gui.Configuration; namespace UICatalog.Scenarios { [ScenarioMetadata (Name: "_ View Experiments", Description: "v2 View Experiments")] diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index 228b7deaf..32ab01163 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -10,10 +10,8 @@ using Terminal.Gui; using System.IO; using System.Reflection; using System.Threading; -using Terminal.Gui.Configuration; -using static Terminal.Gui.Configuration.ConfigurationManager; +using static Terminal.Gui.ConfigurationManager; using System.Text.Json.Serialization; -using System.ComponentModel.DataAnnotations; #nullable enable @@ -243,7 +241,7 @@ namespace UICatalog { static MenuItem []? _themeMenuItems; static MenuBarItem? _themeMenuBarItem; - + /// /// 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. @@ -331,7 +329,7 @@ namespace UICatalog { AllowsMarking = false, CanFocus = true, }; - CategoryListView.OpenSelectedItem += (s,a) => { + CategoryListView.OpenSelectedItem += (s, a) => { ScenarioListView!.SetFocus (); }; CategoryListView.SelectedItemChanged += CategoryListView_SelectedChanged; @@ -370,7 +368,7 @@ namespace UICatalog { ConfigurationManager.Applied += ConfigAppliedHandler; } - + void LoadedHandler (object? sender, EventArgs? args) { ConfigChanged (); @@ -405,7 +403,7 @@ namespace UICatalog { ConfigurationManager.Applied -= ConfigAppliedHandler; Unloaded -= UnloadedHandler; } - + void ConfigAppliedHandler (object? sender, ConfigurationManagerEventArgs? a) { ConfigChanged (); diff --git a/UnitTests/Application/ApplicationTests.cs b/UnitTests/Application/ApplicationTests.cs index 4a291b6c0..12736d9d8 100644 --- a/UnitTests/Application/ApplicationTests.cs +++ b/UnitTests/Application/ApplicationTests.cs @@ -468,7 +468,6 @@ namespace Terminal.Gui.ApplicationTests { ((FakeDriver)Application.Driver).SetBufferSize (5, 5); Application.Begin (Application.Top); - // BUGBUG: v2 - Assert.Equal (new Rect (0, 0, 80, 25), Application.Top.Frame); ((FakeDriver)Application.Driver).SetBufferSize (5, 5); Assert.Equal (new Rect (0, 0, 5, 5), Application.Top.Frame); diff --git a/UnitTests/Drivers/ClipboardTests.cs b/UnitTests/Clipboard/ClipboardTests.cs similarity index 99% rename from UnitTests/Drivers/ClipboardTests.cs rename to UnitTests/Clipboard/ClipboardTests.cs index 90f30bdbd..67d62923d 100644 --- a/UnitTests/Drivers/ClipboardTests.cs +++ b/UnitTests/Clipboard/ClipboardTests.cs @@ -6,7 +6,7 @@ using Xunit; using Xunit.Abstractions; using static AutoInitShutdownAttribute; -namespace Terminal.Gui.DriverTests { +namespace Terminal.Gui.ClipboardTests { public class ClipboardTests { readonly ITestOutputHelper output; diff --git a/UnitTests/Configuration/AppScopeTests.cs b/UnitTests/Configuration/AppScopeTests.cs index a04603041..743de08b1 100644 --- a/UnitTests/Configuration/AppScopeTests.cs +++ b/UnitTests/Configuration/AppScopeTests.cs @@ -1,12 +1,12 @@ using Xunit; -using Terminal.Gui.Configuration; +using Terminal.Gui; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Text.Json; -using static Terminal.Gui.Configuration.ConfigurationManager; +using static Terminal.Gui.ConfigurationManager; namespace Terminal.Gui.ConfigurationTests { public class AppScopeTests { diff --git a/UnitTests/Configuration/ConfigurationMangerTests.cs b/UnitTests/Configuration/ConfigurationMangerTests.cs index 73ae84b14..605f1bcee 100644 --- a/UnitTests/Configuration/ConfigurationMangerTests.cs +++ b/UnitTests/Configuration/ConfigurationMangerTests.cs @@ -5,9 +5,10 @@ using System.Linq; using System.Reflection; using System.Reflection.Metadata; using System.Text.Json; -using Terminal.Gui.Configuration; +using Terminal.Gui; using Xunit; -using static Terminal.Gui.Configuration.ConfigurationManager; +using static Terminal.Gui.ConfigurationManager; +using Attribute = Terminal.Gui.Attribute; namespace Terminal.Gui.ConfigurationTests { public class ConfigurationManagerTests { diff --git a/UnitTests/Configuration/JsonConverterTests.cs b/UnitTests/Configuration/JsonConverterTests.cs index 8e87ab719..ece53145a 100644 --- a/UnitTests/Configuration/JsonConverterTests.cs +++ b/UnitTests/Configuration/JsonConverterTests.cs @@ -1,11 +1,12 @@ using Xunit; -using Terminal.Gui.Configuration; +using Terminal.Gui; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Text.Json; +using Attribute = Terminal.Gui.Attribute; namespace Terminal.Gui.ConfigurationTests { public class ColorJsonConverterTests { diff --git a/UnitTests/Configuration/SettingsScopeTests.cs b/UnitTests/Configuration/SettingsScopeTests.cs index 040c564bd..06777daf1 100644 --- a/UnitTests/Configuration/SettingsScopeTests.cs +++ b/UnitTests/Configuration/SettingsScopeTests.cs @@ -1,11 +1,11 @@ using Xunit; -using Terminal.Gui.Configuration; +using Terminal.Gui; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -using static Terminal.Gui.Configuration.ConfigurationManager; +using static Terminal.Gui.ConfigurationManager; namespace Terminal.Gui.ConfigurationTests { public class SettingsScopeTests { diff --git a/UnitTests/Configuration/ThemeScopeTests.cs b/UnitTests/Configuration/ThemeScopeTests.cs index 24066365f..34199a008 100644 --- a/UnitTests/Configuration/ThemeScopeTests.cs +++ b/UnitTests/Configuration/ThemeScopeTests.cs @@ -1,12 +1,12 @@ using Xunit; -using Terminal.Gui.Configuration; +using Terminal.Gui; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Text.Json; -using static Terminal.Gui.Configuration.ConfigurationManager; +using static Terminal.Gui.ConfigurationManager; namespace Terminal.Gui.ConfigurationTests { public class ThemeScopeTests { diff --git a/UnitTests/Configuration/ThemeTests.cs b/UnitTests/Configuration/ThemeTests.cs index f13dca9d3..f8679324a 100644 --- a/UnitTests/Configuration/ThemeTests.cs +++ b/UnitTests/Configuration/ThemeTests.cs @@ -1,5 +1,5 @@ using Xunit; -using Terminal.Gui.Configuration; +using Terminal.Gui; using System; using System.Collections.Generic; using System.Linq; @@ -7,7 +7,8 @@ using System.Text; using System.Threading.Tasks; using System.IO; using System.Text.Json; -using static Terminal.Gui.Configuration.ConfigurationManager; +using static Terminal.Gui.ConfigurationManager; +using Attribute = Terminal.Gui.Attribute; namespace Terminal.Gui.ConfigurationTests { public class ThemeTests { diff --git a/UnitTests/Colors/AttributeTests.cs b/UnitTests/ConsoleDrivers/AttributeTests.cs similarity index 99% rename from UnitTests/Colors/AttributeTests.cs rename to UnitTests/ConsoleDrivers/AttributeTests.cs index 0bcdc991f..f2130f220 100644 --- a/UnitTests/Colors/AttributeTests.cs +++ b/UnitTests/ConsoleDrivers/AttributeTests.cs @@ -7,7 +7,7 @@ using Xunit; // Alias Console to MockConsole so we don't accidentally use Console using Console = Terminal.Gui.FakeConsole; -namespace Terminal.Gui.ColorTests { +namespace Terminal.Gui.DriverTests { public class AttributeTests { [Fact] public void Constuctors_Constuct () diff --git a/UnitTests/Drivers/ColorTests.cs b/UnitTests/ConsoleDrivers/ColorTests.cs similarity index 100% rename from UnitTests/Drivers/ColorTests.cs rename to UnitTests/ConsoleDrivers/ColorTests.cs diff --git a/UnitTests/ConsoleDrivers/ConsoleDriverTests.cs b/UnitTests/ConsoleDrivers/ConsoleDriverTests.cs new file mode 100644 index 000000000..30757e981 --- /dev/null +++ b/UnitTests/ConsoleDrivers/ConsoleDriverTests.cs @@ -0,0 +1,298 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using Xunit; +using Xunit.Abstractions; + +// Alias Console to MockConsole so we don't accidentally use Console +using Console = Terminal.Gui.FakeConsole; + +namespace Terminal.Gui.DriverTests { + public class ConsoleDriverTests { + readonly ITestOutputHelper output; + + public ConsoleDriverTests (ITestOutputHelper output) + { + this.output = output; + } + + [Theory] + [InlineData (typeof (FakeDriver))] + //[InlineData (typeof (NetDriver))] + //[InlineData (typeof (CursesDriver))] + //[InlineData (typeof (WindowsDriver))] + public void Init_Inits (Type driverType) + { + var driver = (ConsoleDriver)Activator.CreateInstance (driverType); + Application.Init (driver); + driver.Init (() => { }); + + Assert.Equal (80, Console.BufferWidth); + Assert.Equal (25, Console.BufferHeight); + + // MockDriver is always 80x25 + Assert.Equal (Console.BufferWidth, driver.Cols); + Assert.Equal (Console.BufferHeight, driver.Rows); + driver.End (); + + // Shutdown must be called to safely clean up Application if Init has been called + Application.Shutdown (); + } + + [Theory] + [InlineData (typeof (FakeDriver))] + //[InlineData (typeof (NetDriver))] + //[InlineData (typeof (CursesDriver))] + //[InlineData (typeof (WindowsDriver))] + public void End_Cleans_Up (Type driverType) + { + var driver = (ConsoleDriver)Activator.CreateInstance (driverType); + Application.Init (driver); + driver.Init (() => { }); + + Console.ForegroundColor = ConsoleColor.Red; + Assert.Equal (ConsoleColor.Red, Console.ForegroundColor); + + Console.BackgroundColor = ConsoleColor.Green; + Assert.Equal (ConsoleColor.Green, Console.BackgroundColor); + driver.Move (2, 3); + Assert.Equal (2, Console.CursorLeft); + Assert.Equal (3, Console.CursorTop); + + driver.End (); + Assert.Equal (0, Console.CursorLeft); + Assert.Equal (0, Console.CursorTop); + Assert.Equal (ConsoleColor.Gray, Console.ForegroundColor); + Assert.Equal (ConsoleColor.Black, Console.BackgroundColor); + + // Shutdown must be called to safely clean up Application if Init has been called + Application.Shutdown (); + } + + [Theory] + [InlineData (typeof (FakeDriver))] + public void FakeDriver_Only_Sends_Keystrokes_Through_MockKeyPresses (Type driverType) + { + var driver = (ConsoleDriver)Activator.CreateInstance (driverType); + Application.Init (driver); + + var top = Application.Top; + var view = new View (); + var count = 0; + var wasKeyPressed = false; + + view.KeyPress += (s, e) => { + wasKeyPressed = true; + }; + top.Add (view); + + Application.Iteration += () => { + count++; + if (count == 10) Application.RequestStop (); + }; + + Application.Run (); + + Assert.False (wasKeyPressed); + + // Shutdown must be called to safely clean up Application if Init has been called + Application.Shutdown (); + } + + [Theory] + [InlineData (typeof (FakeDriver))] + public void FakeDriver_MockKeyPresses (Type driverType) + { + var driver = (ConsoleDriver)Activator.CreateInstance (driverType); + Application.Init (driver); + + var text = "MockKeyPresses"; + var mKeys = new Stack (); + foreach (var r in text.Reverse ()) { + var ck = char.IsLetter (r) ? (ConsoleKey)char.ToUpper (r) : (ConsoleKey)r; + var cki = new ConsoleKeyInfo (r, ck, false, false, false); + mKeys.Push (cki); + } + Console.MockKeyPresses = mKeys; + + var top = Application.Top; + var view = new View (); + var rText = ""; + var idx = 0; + + view.KeyPress += (s, e) => { + Assert.Equal (text [idx], (char)e.KeyEvent.Key); + rText += (char)e.KeyEvent.Key; + Assert.Equal (rText, text.Substring (0, idx + 1)); + e.Handled = true; + idx++; + }; + top.Add (view); + + Application.Iteration += () => { + if (mKeys.Count == 0) Application.RequestStop (); + }; + + Application.Run (); + + Assert.Equal ("MockKeyPresses", rText); + + // Shutdown must be called to safely clean up Application if Init has been called + Application.Shutdown (); + } + + //[Theory] + //[InlineData (typeof (FakeDriver))] + //public void FakeDriver_MockKeyPresses_Press_AfterTimeOut (Type driverType) + //{ + // var driver = (ConsoleDriver)Activator.CreateInstance (driverType); + // Application.Init (driver); + + // // Simulating pressing of QuitKey after a short period of time + // uint quitTime = 100; + // Func closeCallback = (MainLoop loop) => { + // // Prove the scenario is using Application.QuitKey correctly + // output.WriteLine ($" {quitTime}ms elapsed; Simulating keypresses..."); + // FakeConsole.PushMockKeyPress (Key.F); + // FakeConsole.PushMockKeyPress (Key.U); + // FakeConsole.PushMockKeyPress (Key.C); + // FakeConsole.PushMockKeyPress (Key.K); + // return false; + // }; + // output.WriteLine ($"Add timeout to simulate key presses after {quitTime}ms"); + // _ = Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (quitTime), closeCallback); + + // // If Top doesn't quit within abortTime * 5 (500ms), this will force it + // uint abortTime = quitTime * 5; + // Func forceCloseCallback = (MainLoop loop) => { + // Application.RequestStop (); + // Assert.Fail ($" failed to Quit after {abortTime}ms. Force quit."); + // return false; + // }; + // output.WriteLine ($"Add timeout to force quit after {abortTime}ms"); + // _ = Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (abortTime), forceCloseCallback); + + + // Key key = Key.Unknown; + + // Application.Top.KeyPress += (e) => { + // key = e.KeyEvent.Key; + // output.WriteLine ($" Application.Top.KeyPress: {key}"); + // e.Handled = true; + + // }; + + // int iterations = 0; + // Application.Iteration += () => { + // output.WriteLine ($" iteration {++iterations}"); + + // if (Console.MockKeyPresses.Count == 0) { + // output.WriteLine ($" No more MockKeyPresses; RequestStop"); + // Application.RequestStop (); + // } + // }; + + // Application.Run (); + + // // Shutdown must be called to safely clean up Application if Init has been called + // Application.Shutdown (); + //} + + [Theory] + [InlineData (typeof (FakeDriver))] + public void TerminalResized_Simulation (Type driverType) + { + var driver = (FakeDriver)Activator.CreateInstance (driverType); + Application.Init (driver); + var wasTerminalResized = false; + Application.Resized = (e) => { + wasTerminalResized = true; + Assert.Equal (120, e.Cols); + Assert.Equal (40, e.Rows); + }; + + Assert.Equal (80, Console.BufferWidth); + Assert.Equal (25, Console.BufferHeight); + + // MockDriver is by default 80x25 + Assert.Equal (Console.BufferWidth, driver.Cols); + Assert.Equal (Console.BufferHeight, driver.Rows); + Assert.False (wasTerminalResized); + + // MockDriver will now be sets to 120x40 + driver.SetBufferSize (120, 40); + Assert.Equal (120, Application.Driver.Cols); + Assert.Equal (40, Application.Driver.Rows); + Assert.True (wasTerminalResized); + + // MockDriver will still be 120x40 + wasTerminalResized = false; + Application.EnableConsoleScrolling = true; + driver.SetWindowSize (40, 20); + Assert.Equal (120, Application.Driver.Cols); + Assert.Equal (40, Application.Driver.Rows); + Assert.Equal (120, Console.BufferWidth); + Assert.Equal (40, Console.BufferHeight); + Assert.Equal (40, Console.WindowWidth); + Assert.Equal (20, Console.WindowHeight); + Assert.True (wasTerminalResized); + + Application.Shutdown (); + } + + [Fact, AutoInitShutdown] + public void Write_Do_Not_Change_On_ProcessKey () + { + var win = new Window (); + Application.Begin (win); + ((FakeDriver)Application.Driver).SetBufferSize (20, 8); + + System.Threading.Tasks.Task.Run (() => { + System.Threading.Tasks.Task.Delay (500).Wait (); + Application.MainLoop.Invoke (() => { + var lbl = new Label ("Hello World") { X = Pos.Center () }; + var dlg = new Dialog ("Test", new Button ("Ok")); + dlg.Add (lbl); + Application.Begin (dlg); + + var expected = @" +┌──────────────────┐ +│┌┤Test├─────────┐ │ +││ Hello World │ │ +││ │ │ +││ │ │ +││ [ Ok ] │ │ +│└───────────────┘ │ +└──────────────────┘ +"; + + var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (0, 0, 20, 8), pos); + + Assert.True (dlg.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ()))); + dlg.Redraw (dlg.Bounds); + + expected = @" +┌──────────────────┐ +│┌┤Test├─────────┐ │ +││ Hello World │ │ +││ │ │ +││ │ │ +││ [ Ok ] │ │ +│└───────────────┘ │ +└──────────────────┘ +"; + + pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (0, 0, 20, 8), pos); + + win.RequestStop (); + }); + }); + + Application.Run (win); + Application.Shutdown (); + } + } +} diff --git a/UnitTests/ConsoleDrivers/ConsoleScrolllingTests.cs b/UnitTests/ConsoleDrivers/ConsoleScrolllingTests.cs new file mode 100644 index 000000000..28eeae454 --- /dev/null +++ b/UnitTests/ConsoleDrivers/ConsoleScrolllingTests.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using Xunit; +using Xunit.Abstractions; + +// Alias Console to MockConsole so we don't accidentally use Console +using Console = Terminal.Gui.FakeConsole; + +namespace Terminal.Gui.DriverTests { + public class ConsoleScrollingTests { + readonly ITestOutputHelper output; + + public ConsoleScrollingTests (ITestOutputHelper output) + { + this.output = output; + } + + + [Theory] + [InlineData (typeof (FakeDriver))] + public void EnableConsoleScrolling_Is_False_Left_And_Top_Is_Always_Zero (Type driverType) + { + var driver = (FakeDriver)Activator.CreateInstance (driverType); + Application.Init (driver); + + Assert.False (Application.EnableConsoleScrolling); + Assert.Equal (0, Console.WindowLeft); + Assert.Equal (0, Console.WindowTop); + + driver.SetWindowPosition (5, 5); + Assert.Equal (0, Console.WindowLeft); + Assert.Equal (0, Console.WindowTop); + + Application.Shutdown (); + } + + [Theory] + [InlineData (typeof (FakeDriver))] + public void EnableConsoleScrolling_Is_True_Left_Cannot_Be_Greater_Than_WindowWidth (Type driverType) + { + var driver = (FakeDriver)Activator.CreateInstance (driverType); + Application.Init (driver); + + Application.EnableConsoleScrolling = true; + Assert.True (Application.EnableConsoleScrolling); + + driver.SetWindowPosition (81, 25); + Assert.Equal (0, Console.WindowLeft); + Assert.Equal (0, Console.WindowTop); + + Application.Shutdown (); + } + + [Theory] + [InlineData (typeof (FakeDriver))] + public void EnableConsoleScrolling_Is_True_Left_Cannot_Be_Greater_Than_BufferWidth_Minus_WindowWidth (Type driverType) + { + var driver = (FakeDriver)Activator.CreateInstance (driverType); + Application.Init (driver); + + Application.EnableConsoleScrolling = true; + Assert.True (Application.EnableConsoleScrolling); + + driver.SetWindowPosition (81, 25); + Assert.Equal (0, Console.WindowLeft); + Assert.Equal (0, Console.WindowTop); + + // MockDriver will now be sets to 120x25 + driver.SetBufferSize (120, 25); + Assert.Equal (120, Application.Driver.Cols); + Assert.Equal (25, Application.Driver.Rows); + Assert.Equal (120, Console.BufferWidth); + Assert.Equal (25, Console.BufferHeight); + Assert.Equal (80, Console.WindowWidth); + Assert.Equal (25, Console.WindowHeight); + driver.SetWindowPosition (121, 25); + Assert.Equal (40, Console.WindowLeft); + Assert.Equal (0, Console.WindowTop); + + driver.SetWindowSize (90, 25); + Assert.Equal (120, Application.Driver.Cols); + Assert.Equal (25, Application.Driver.Rows); + Assert.Equal (120, Console.BufferWidth); + Assert.Equal (25, Console.BufferHeight); + Assert.Equal (90, Console.WindowWidth); + Assert.Equal (25, Console.WindowHeight); + driver.SetWindowPosition (121, 25); + Assert.Equal (30, Console.WindowLeft); + Assert.Equal (0, Console.WindowTop); + + Application.Shutdown (); + } + + [Theory] + [InlineData (typeof (FakeDriver))] + public void EnableConsoleScrolling_Is_True_Top_Cannot_Be_Greater_Than_WindowHeight (Type driverType) + { + var driver = (FakeDriver)Activator.CreateInstance (driverType); + Application.Init (driver); + + Application.EnableConsoleScrolling = true; + Assert.True (Application.EnableConsoleScrolling); + + driver.SetWindowPosition (80, 26); + Assert.Equal (0, Console.WindowLeft); + Assert.Equal (0, Console.WindowTop); + + Application.Shutdown (); + } + + [Theory] + [InlineData (typeof (FakeDriver))] + public void EnableConsoleScrolling_Is_True_Top_Cannot_Be_Greater_Than_BufferHeight_Minus_WindowHeight (Type driverType) + { + var driver = (FakeDriver)Activator.CreateInstance (driverType); + Application.Init (driver); + + Application.EnableConsoleScrolling = true; + Assert.True (Application.EnableConsoleScrolling); + + driver.SetWindowPosition (80, 26); + Assert.Equal (0, Console.WindowLeft); + Assert.Equal (0, Console.WindowTop); + + // MockDriver will now be sets to 80x40 + driver.SetBufferSize (80, 40); + Assert.Equal (80, Application.Driver.Cols); + Assert.Equal (40, Application.Driver.Rows); + Assert.Equal (80, Console.BufferWidth); + Assert.Equal (40, Console.BufferHeight); + Assert.Equal (80, Console.WindowWidth); + Assert.Equal (25, Console.WindowHeight); + Assert.Equal (0, Console.WindowLeft); + Assert.Equal (0, Console.WindowTop); + driver.SetWindowPosition (80, 40); + Assert.Equal (0, Console.WindowLeft); + Assert.Equal (15, Console.WindowTop); + + driver.SetWindowSize (80, 20); + Assert.Equal (80, Application.Driver.Cols); + Assert.Equal (40, Application.Driver.Rows); + Assert.Equal (80, Console.BufferWidth); + Assert.Equal (40, Console.BufferHeight); + Assert.Equal (80, Console.WindowWidth); + Assert.Equal (20, Console.WindowHeight); + Assert.Equal (0, Console.WindowLeft); + Assert.Equal (15, Console.WindowTop); + driver.SetWindowPosition (80, 41); + Assert.Equal (0, Console.WindowLeft); + Assert.Equal (20, Console.WindowTop); + + Application.Shutdown (); + } + } +} diff --git a/UnitTests/ConsoleDrivers/KeyTests.cs b/UnitTests/ConsoleDrivers/KeyTests.cs new file mode 100644 index 000000000..f480c2417 --- /dev/null +++ b/UnitTests/ConsoleDrivers/KeyTests.cs @@ -0,0 +1,349 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Terminal.Gui; +using Xunit; + +namespace Terminal.Gui.InputTests { + public class KeyTests { + enum SimpleEnum { Zero, One, Two, Three, Four, Five } + + [Flags] + enum FlaggedEnum { Zero, One, Two, Three, Four, Five } + + + enum SimpleHighValueEnum { Zero, One, Two, Three, Four, Last = 0x40000000 } + + [Flags] + enum FlaggedHighValueEnum { Zero, One, Two, Three, Four, Last = 0x40000000 } + + [Fact] + public void SimpleEnum_And_FlagedEnum () + { + var simple = SimpleEnum.Three | SimpleEnum.Five; + + // Nothing will not be well compared here. + Assert.True (simple.HasFlag (SimpleEnum.Zero | SimpleEnum.Five)); + Assert.True (simple.HasFlag (SimpleEnum.One | SimpleEnum.Five)); + Assert.True (simple.HasFlag (SimpleEnum.Two | SimpleEnum.Five)); + Assert.True (simple.HasFlag (SimpleEnum.Three | SimpleEnum.Five)); + Assert.True (simple.HasFlag (SimpleEnum.Four | SimpleEnum.Five)); + Assert.True ((simple & (SimpleEnum.Zero | SimpleEnum.Five)) != 0); + Assert.True ((simple & (SimpleEnum.One | SimpleEnum.Five)) != 0); + Assert.True ((simple & (SimpleEnum.Two | SimpleEnum.Five)) != 0); + Assert.True ((simple & (SimpleEnum.Three | SimpleEnum.Five)) != 0); + Assert.True ((simple & (SimpleEnum.Four | SimpleEnum.Five)) != 0); + Assert.Equal (7, (int)simple); // As it is not flagged only shows as number. + Assert.Equal ("7", simple.ToString ()); + Assert.False (simple == (SimpleEnum.Zero | SimpleEnum.Five)); + Assert.False (simple == (SimpleEnum.One | SimpleEnum.Five)); + Assert.True (simple == (SimpleEnum.Two | SimpleEnum.Five)); + Assert.True (simple == (SimpleEnum.Three | SimpleEnum.Five)); + Assert.False (simple == (SimpleEnum.Four | SimpleEnum.Five)); + + var flagged = FlaggedEnum.Three | FlaggedEnum.Five; + + // Nothing will not be well compared here. + Assert.True (flagged.HasFlag (FlaggedEnum.Zero | FlaggedEnum.Five)); + Assert.True (flagged.HasFlag (FlaggedEnum.One | FlaggedEnum.Five)); + Assert.True (flagged.HasFlag (FlaggedEnum.Two | FlaggedEnum.Five)); + Assert.True (flagged.HasFlag (FlaggedEnum.Three | FlaggedEnum.Five)); + Assert.True (flagged.HasFlag (FlaggedEnum.Four | FlaggedEnum.Five)); + Assert.True ((flagged & (FlaggedEnum.Zero | FlaggedEnum.Five)) != 0); + Assert.True ((flagged & (FlaggedEnum.One | FlaggedEnum.Five)) != 0); + Assert.True ((flagged & (FlaggedEnum.Two | FlaggedEnum.Five)) != 0); + Assert.True ((flagged & (FlaggedEnum.Three | FlaggedEnum.Five)) != 0); + Assert.True ((flagged & (FlaggedEnum.Four | FlaggedEnum.Five)) != 0); + Assert.Equal (FlaggedEnum.Two | FlaggedEnum.Five, flagged); // As it is flagged shows as bitwise. + Assert.Equal ("Two, Five", flagged.ToString ()); + Assert.False (flagged == (FlaggedEnum.Zero | FlaggedEnum.Five)); + Assert.False (flagged == (FlaggedEnum.One | FlaggedEnum.Five)); + Assert.True (flagged == (FlaggedEnum.Two | FlaggedEnum.Five)); + Assert.True (flagged == (FlaggedEnum.Three | FlaggedEnum.Five)); + Assert.False (flagged == (FlaggedEnum.Four | FlaggedEnum.Five)); + } + + [Fact] + public void SimpleHighValueEnum_And_FlaggedHighValueEnum () + { + var simple = SimpleHighValueEnum.Three | SimpleHighValueEnum.Last; + + // This will not be well compared. + Assert.True (simple.HasFlag (SimpleHighValueEnum.Zero | SimpleHighValueEnum.Last)); + Assert.True (simple.HasFlag (SimpleHighValueEnum.One | SimpleHighValueEnum.Last)); + Assert.True (simple.HasFlag (SimpleHighValueEnum.Two | SimpleHighValueEnum.Last)); + Assert.True (simple.HasFlag (SimpleHighValueEnum.Three | SimpleHighValueEnum.Last)); + Assert.False (simple.HasFlag (SimpleHighValueEnum.Four | SimpleHighValueEnum.Last)); + Assert.True ((simple & (SimpleHighValueEnum.Zero | SimpleHighValueEnum.Last)) != 0); + Assert.True ((simple & (SimpleHighValueEnum.One | SimpleHighValueEnum.Last)) != 0); + Assert.True ((simple & (SimpleHighValueEnum.Two | SimpleHighValueEnum.Last)) != 0); + Assert.True ((simple & (SimpleHighValueEnum.Three | SimpleHighValueEnum.Last)) != 0); + Assert.True ((simple & (SimpleHighValueEnum.Four | SimpleHighValueEnum.Last)) != 0); + + // This will be well compared, because the SimpleHighValueEnum.Last have a high value. + Assert.Equal (1073741827, (int)simple); // As it is not flagged only shows as number. + Assert.Equal ("1073741827", simple.ToString ()); // As it is not flagged only shows as number. + Assert.False (simple == (SimpleHighValueEnum.Zero | SimpleHighValueEnum.Last)); + Assert.False (simple == (SimpleHighValueEnum.One | SimpleHighValueEnum.Last)); + Assert.False (simple == (SimpleHighValueEnum.Two | SimpleHighValueEnum.Last)); + Assert.True (simple == (SimpleHighValueEnum.Three | SimpleHighValueEnum.Last)); + Assert.False (simple == (SimpleHighValueEnum.Four | SimpleHighValueEnum.Last)); + + var flagged = FlaggedHighValueEnum.Three | FlaggedHighValueEnum.Last; + + // This will not be well compared. + Assert.True (flagged.HasFlag (FlaggedHighValueEnum.Zero | FlaggedHighValueEnum.Last)); + Assert.True (flagged.HasFlag (FlaggedHighValueEnum.One | FlaggedHighValueEnum.Last)); + Assert.True (flagged.HasFlag (FlaggedHighValueEnum.Two | FlaggedHighValueEnum.Last)); + Assert.True (flagged.HasFlag (FlaggedHighValueEnum.Three | FlaggedHighValueEnum.Last)); + Assert.False (flagged.HasFlag (FlaggedHighValueEnum.Four | FlaggedHighValueEnum.Last)); + Assert.True ((flagged & (FlaggedHighValueEnum.Zero | FlaggedHighValueEnum.Last)) != 0); + Assert.True ((flagged & (FlaggedHighValueEnum.One | FlaggedHighValueEnum.Last)) != 0); + Assert.True ((flagged & (FlaggedHighValueEnum.Two | FlaggedHighValueEnum.Last)) != 0); + Assert.True ((flagged & (FlaggedHighValueEnum.Three | FlaggedHighValueEnum.Last)) != 0); + Assert.True ((flagged & (FlaggedHighValueEnum.Four | FlaggedHighValueEnum.Last)) != 0); + + // This will be well compared, because the SimpleHighValueEnum.Last have a high value. + Assert.Equal (FlaggedHighValueEnum.Three | FlaggedHighValueEnum.Last, flagged); // As it is flagged shows as bitwise. + Assert.Equal ("Three, Last", flagged.ToString ()); // As it is flagged shows as bitwise. + Assert.False (flagged == (FlaggedHighValueEnum.Zero | FlaggedHighValueEnum.Last)); + Assert.False (flagged == (FlaggedHighValueEnum.One | FlaggedHighValueEnum.Last)); + Assert.False (flagged == (FlaggedHighValueEnum.Two | FlaggedHighValueEnum.Last)); + Assert.True (flagged == (FlaggedHighValueEnum.Three | FlaggedHighValueEnum.Last)); + Assert.False (flagged == (FlaggedHighValueEnum.Four | FlaggedHighValueEnum.Last)); + } + + [Fact] + public void Key_Enum_Ambiguity_Check () + { + var key = Key.Y | Key.CtrlMask; + + // This will not be well compared. + Assert.True (key.HasFlag (Key.Q | Key.CtrlMask)); + Assert.True ((key & (Key.Q | Key.CtrlMask)) != 0); + Assert.Equal (Key.Y | Key.CtrlMask, key); + Assert.Equal ("Y, CtrlMask", key.ToString ()); + + // This will be well compared, because the Key.CtrlMask have a high value. + Assert.False (key == Application.QuitKey); + switch (key) { + case Key.Q | Key.CtrlMask: + // Never goes here. + break; + case Key.Y | Key.CtrlMask: + Assert.True (key == (Key.Y | Key.CtrlMask)); + break; + default: + // Never goes here. + break; + } + } + + [Fact] + public void Key_ToString () + { + var k = Key.Y | Key.CtrlMask; + Assert.Equal ("Y, CtrlMask", k.ToString ()); + + k = Key.CtrlMask | Key.Y; + Assert.Equal ("Y, CtrlMask", k.ToString ()); + + k = Key.Space; + Assert.Equal ("Space", k.ToString ()); + + k = Key.Space | Key.D; + Assert.Equal ("d", k.ToString ()); + + k = (Key)'d'; + Assert.Equal ("d", k.ToString ()); + + k = Key.d; + Assert.Equal ("d", k.ToString ()); + + k = Key.D; + Assert.Equal ("D", k.ToString ()); + + // In a console this will always returns Key.D + k = Key.D | Key.ShiftMask; + Assert.Equal ("D, ShiftMask", k.ToString ()); + + // In a console this will always returns Key.D + k = Key.d | Key.ShiftMask; + Assert.Equal ("d, ShiftMask", k.ToString ()); + } + + + private static object packetLock = new object (); + + /// + /// Sometimes when using remote tools EventKeyRecord sends 'virtual keystrokes'. + /// These are indicated with the wVirtualKeyCode of 231. When we see this code + /// then we need to look to the unicode character (UnicodeChar) instead of the key + /// when telling the rest of the framework what button was pressed. For full details + /// see: https://github.com/gui-cs/Terminal.Gui/issues/2008 + /// + [Theory, AutoInitShutdown] + [ClassData (typeof (PacketTest))] + public void TestVKPacket (uint unicodeCharacter, bool shift, bool alt, bool control, uint initialVirtualKey, uint initialScanCode, Key expectedRemapping, uint expectedVirtualKey, uint expectedScanCode) + { + var modifiers = new ConsoleModifiers (); + if (shift) modifiers |= ConsoleModifiers.Shift; + if (alt) modifiers |= ConsoleModifiers.Alt; + if (control) modifiers |= ConsoleModifiers.Control; + var mappedConsoleKey = ConsoleKeyMapping.GetConsoleKeyFromKey (unicodeCharacter, modifiers, out uint scanCode, out uint outputChar); + + if ((scanCode > 0 || mappedConsoleKey == 0) && mappedConsoleKey == initialVirtualKey) Assert.Equal (mappedConsoleKey, initialVirtualKey); + else Assert.Equal (mappedConsoleKey, outputChar < 0xff ? outputChar & 0xff | 0xff << 8 : outputChar); + Assert.Equal (scanCode, initialScanCode); + + var keyChar = ConsoleKeyMapping.GetKeyCharFromConsoleKey (mappedConsoleKey, modifiers, out uint consoleKey, out scanCode); + + //if (scanCode > 0 && consoleKey == keyChar && consoleKey > 48 && consoleKey > 57 && consoleKey < 65 && consoleKey > 91) { + if (scanCode > 0 && keyChar == 0 && consoleKey == mappedConsoleKey) Assert.Equal (0, (double)keyChar); + else Assert.Equal (keyChar, unicodeCharacter); + Assert.Equal (consoleKey, expectedVirtualKey); + Assert.Equal (scanCode, expectedScanCode); + + var top = Application.Top; + + top.KeyPress += (s, e) => { + var after = ShortcutHelper.GetModifiersKey (e.KeyEvent); + Assert.Equal (expectedRemapping, after); + e.Handled = true; + Application.RequestStop (); + }; + + var iterations = -1; + + Application.Iteration += () => { + iterations++; + if (iterations == 0) Application.Driver.SendKeys ((char)mappedConsoleKey, ConsoleKey.Packet, shift, alt, control); + }; + + + lock (packetLock) { + Application.Run (); + Application.Shutdown (); + } + } + + public class PacketTest : IEnumerable, IEnumerable { + public IEnumerator GetEnumerator () + { + lock (packetLock) { + yield return new object [] { 'a', false, false, false, 'A', 30, Key.a, 'A', 30 }; + yield return new object [] { 'A', true, false, false, 'A', 30, Key.A | Key.ShiftMask, 'A', 30 }; + yield return new object [] { 'A', true, true, false, 'A', 30, Key.A | Key.ShiftMask | Key.AltMask, 'A', 30 }; + yield return new object [] { 'A', true, true, true, 'A', 30, Key.A | Key.ShiftMask | Key.AltMask | Key.CtrlMask, 'A', 30 }; + yield return new object [] { 'z', false, false, false, 'Z', 44, Key.z, 'Z', 44 }; + yield return new object [] { 'Z', true, false, false, 'Z', 44, Key.Z | Key.ShiftMask, 'Z', 44 }; + yield return new object [] { 'Z', true, true, false, 'Z', 44, Key.Z | Key.ShiftMask | Key.AltMask, 'Z', 44 }; + yield return new object [] { 'Z', true, true, true, 'Z', 44, Key.Z | Key.ShiftMask | Key.AltMask | Key.CtrlMask, 'Z', 44 }; + yield return new object [] { '英', false, false, false, '\0', 0, (Key)'英', '\0', 0 }; + yield return new object [] { '英', true, false, false, '\0', 0, (Key)'英' | Key.ShiftMask, '\0', 0 }; + yield return new object [] { '英', true, true, false, '\0', 0, (Key)'英' | Key.ShiftMask | Key.AltMask, '\0', 0 }; + yield return new object [] { '英', true, true, true, '\0', 0, (Key)'英' | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '\0', 0 }; + yield return new object [] { '+', false, false, false, 187, 26, (Key)'+', 187, 26 }; + yield return new object [] { '*', true, false, false, 187, 26, (Key)'*' | Key.ShiftMask, 187, 26 }; + yield return new object [] { '+', true, true, false, 187, 26, (Key)'+' | Key.ShiftMask | Key.AltMask, 187, 26 }; + yield return new object [] { '+', true, true, true, 187, 26, (Key)'+' | Key.ShiftMask | Key.AltMask | Key.CtrlMask, 187, 26 }; + yield return new object [] { '1', false, false, false, '1', 2, Key.D1, '1', 2 }; + yield return new object [] { '!', true, false, false, '1', 2, (Key)'!' | Key.ShiftMask, '1', 2 }; + yield return new object [] { '1', true, true, false, '1', 2, Key.D1 | Key.ShiftMask | Key.AltMask, '1', 2 }; + yield return new object [] { '1', true, true, true, '1', 2, Key.D1 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '1', 2 }; + yield return new object [] { '1', false, true, true, '1', 2, Key.D1 | Key.AltMask | Key.CtrlMask, '1', 2 }; + yield return new object [] { '2', false, false, false, '2', 3, Key.D2, '2', 3 }; + yield return new object [] { '"', true, false, false, '2', 3, (Key)'"' | Key.ShiftMask, '2', 3 }; + yield return new object [] { '2', true, true, false, '2', 3, Key.D2 | Key.ShiftMask | Key.AltMask, '2', 3 }; + yield return new object [] { '2', true, true, true, '2', 3, Key.D2 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '2', 3 }; + yield return new object [] { '@', false, true, true, '2', 3, (Key)'@' | Key.AltMask | Key.CtrlMask, '2', 3 }; + yield return new object [] { '3', false, false, false, '3', 4, Key.D3, '3', 4 }; + yield return new object [] { '#', true, false, false, '3', 4, (Key)'#' | Key.ShiftMask, '3', 4 }; + yield return new object [] { '3', true, true, false, '3', 4, Key.D3 | Key.ShiftMask | Key.AltMask, '3', 4 }; + yield return new object [] { '3', true, true, true, '3', 4, Key.D3 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '3', 4 }; + yield return new object [] { '£', false, true, true, '3', 4, (Key)'£' | Key.AltMask | Key.CtrlMask, '3', 4 }; + yield return new object [] { '4', false, false, false, '4', 5, Key.D4, '4', 5 }; + yield return new object [] { '$', true, false, false, '4', 5, (Key)'$' | Key.ShiftMask, '4', 5 }; + yield return new object [] { '4', true, true, false, '4', 5, Key.D4 | Key.ShiftMask | Key.AltMask, '4', 5 }; + yield return new object [] { '4', true, true, true, '4', 5, Key.D4 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '4', 5 }; + yield return new object [] { '§', false, true, true, '4', 5, (Key)'§' | Key.AltMask | Key.CtrlMask, '4', 5 }; + yield return new object [] { '5', false, false, false, '5', 6, Key.D5, '5', 6 }; + yield return new object [] { '%', true, false, false, '5', 6, (Key)'%' | Key.ShiftMask, '5', 6 }; + yield return new object [] { '5', true, true, false, '5', 6, Key.D5 | Key.ShiftMask | Key.AltMask, '5', 6 }; + yield return new object [] { '5', true, true, true, '5', 6, Key.D5 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '5', 6 }; + yield return new object [] { '€', false, true, true, '5', 6, (Key)'€' | Key.AltMask | Key.CtrlMask, '5', 6 }; + yield return new object [] { '6', false, false, false, '6', 7, Key.D6, '6', 7 }; + yield return new object [] { '&', true, false, false, '6', 7, (Key)'&' | Key.ShiftMask, '6', 7 }; + yield return new object [] { '6', true, true, false, '6', 7, Key.D6 | Key.ShiftMask | Key.AltMask, '6', 7 }; + yield return new object [] { '6', true, true, true, '6', 7, Key.D6 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '6', 7 }; + yield return new object [] { '6', false, true, true, '6', 7, Key.D6 | Key.AltMask | Key.CtrlMask, '6', 7 }; + yield return new object [] { '7', false, false, false, '7', 8, Key.D7, '7', 8 }; + yield return new object [] { '/', true, false, false, '7', 8, (Key)'/' | Key.ShiftMask, '7', 8 }; + yield return new object [] { '7', true, true, false, '7', 8, Key.D7 | Key.ShiftMask | Key.AltMask, '7', 8 }; + yield return new object [] { '7', true, true, true, '7', 8, Key.D7 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '7', 8 }; + yield return new object [] { '{', false, true, true, '7', 8, (Key)'{' | Key.AltMask | Key.CtrlMask, '7', 8 }; + yield return new object [] { '8', false, false, false, '8', 9, Key.D8, '8', 9 }; + yield return new object [] { '(', true, false, false, '8', 9, (Key)'(' | Key.ShiftMask, '8', 9 }; + yield return new object [] { '8', true, true, false, '8', 9, Key.D8 | Key.ShiftMask | Key.AltMask, '8', 9 }; + yield return new object [] { '8', true, true, true, '8', 9, Key.D8 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '8', 9 }; + yield return new object [] { '[', false, true, true, '8', 9, (Key)'[' | Key.AltMask | Key.CtrlMask, '8', 9 }; + yield return new object [] { '9', false, false, false, '9', 10, Key.D9, '9', 10 }; + yield return new object [] { ')', true, false, false, '9', 10, (Key)')' | Key.ShiftMask, '9', 10 }; + yield return new object [] { '9', true, true, false, '9', 10, Key.D9 | Key.ShiftMask | Key.AltMask, '9', 10 }; + yield return new object [] { '9', true, true, true, '9', 10, Key.D9 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '9', 10 }; + yield return new object [] { ']', false, true, true, '9', 10, (Key)']' | Key.AltMask | Key.CtrlMask, '9', 10 }; + yield return new object [] { '0', false, false, false, '0', 11, Key.D0, '0', 11 }; + yield return new object [] { '=', true, false, false, '0', 11, (Key)'=' | Key.ShiftMask, '0', 11 }; + yield return new object [] { '0', true, true, false, '0', 11, Key.D0 | Key.ShiftMask | Key.AltMask, '0', 11 }; + yield return new object [] { '0', true, true, true, '0', 11, Key.D0 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '0', 11 }; + yield return new object [] { '}', false, true, true, '0', 11, (Key)'}' | Key.AltMask | Key.CtrlMask, '0', 11 }; + yield return new object [] { '\'', false, false, false, 219, 12, (Key)'\'', 219, 12 }; + yield return new object [] { '?', true, false, false, 219, 12, (Key)'?' | Key.ShiftMask, 219, 12 }; + yield return new object [] { '\'', true, true, false, 219, 12, (Key)'\'' | Key.ShiftMask | Key.AltMask, 219, 12 }; + yield return new object [] { '\'', true, true, true, 219, 12, (Key)'\'' | Key.ShiftMask | Key.AltMask | Key.CtrlMask, 219, 12 }; + yield return new object [] { '«', false, false, false, 221, 13, (Key)'«', 221, 13 }; + yield return new object [] { '»', true, false, false, 221, 13, (Key)'»' | Key.ShiftMask, 221, 13 }; + yield return new object [] { '«', true, true, false, 221, 13, (Key)'«' | Key.ShiftMask | Key.AltMask, 221, 13 }; + yield return new object [] { '«', true, true, true, 221, 13, (Key)'«' | Key.ShiftMask | Key.AltMask | Key.CtrlMask, 221, 13 }; + yield return new object [] { 'á', false, false, false, 'á', 0, (Key)'á', 'A', 30 }; + yield return new object [] { 'Á', true, false, false, 'Á', 0, (Key)'Á' | Key.ShiftMask, 'A', 30 }; + yield return new object [] { 'à', false, false, false, 'à', 0, (Key)'à', 'A', 30 }; + yield return new object [] { 'À', true, false, false, 'À', 0, (Key)'À' | Key.ShiftMask, 'A', 30 }; + yield return new object [] { 'é', false, false, false, 'é', 0, (Key)'é', 'E', 18 }; + yield return new object [] { 'É', true, false, false, 'É', 0, (Key)'É' | Key.ShiftMask, 'E', 18 }; + yield return new object [] { 'è', false, false, false, 'è', 0, (Key)'è', 'E', 18 }; + yield return new object [] { 'È', true, false, false, 'È', 0, (Key)'È' | Key.ShiftMask, 'E', 18 }; + yield return new object [] { 'í', false, false, false, 'í', 0, (Key)'í', 'I', 23 }; + yield return new object [] { 'Í', true, false, false, 'Í', 0, (Key)'Í' | Key.ShiftMask, 'I', 23 }; + yield return new object [] { 'ì', false, false, false, 'ì', 0, (Key)'ì', 'I', 23 }; + yield return new object [] { 'Ì', true, false, false, 'Ì', 0, (Key)'Ì' | Key.ShiftMask, 'I', 23 }; + yield return new object [] { 'ó', false, false, false, 'ó', 0, (Key)'ó', 'O', 24 }; + yield return new object [] { 'Ó', true, false, false, 'Ó', 0, (Key)'Ó' | Key.ShiftMask, 'O', 24 }; + yield return new object [] { 'ò', false, false, false, 'Ó', 0, (Key)'ò', 'O', 24 }; + yield return new object [] { 'Ò', true, false, false, 'Ò', 0, (Key)'Ò' | Key.ShiftMask, 'O', 24 }; + yield return new object [] { 'ú', false, false, false, 'ú', 0, (Key)'ú', 'U', 22 }; + yield return new object [] { 'Ú', true, false, false, 'Ú', 0, (Key)'Ú' | Key.ShiftMask, 'U', 22 }; + yield return new object [] { 'ù', false, false, false, 'ù', 0, (Key)'ù', 'U', 22 }; + yield return new object [] { 'Ù', true, false, false, 'Ù', 0, (Key)'Ù' | Key.ShiftMask, 'U', 22 }; + yield return new object [] { 'ö', false, false, false, 'ó', 0, (Key)'ö', 'O', 24 }; + yield return new object [] { 'Ö', true, false, false, 'Ó', 0, (Key)'Ö' | Key.ShiftMask, 'O', 24 }; + yield return new object [] { '<', false, false, false, 226, 86, (Key)'<', 226, 86 }; + yield return new object [] { '>', true, false, false, 226, 86, (Key)'>' | Key.ShiftMask, 226, 86 }; + yield return new object [] { '<', true, true, false, 226, 86, (Key)'<' | Key.ShiftMask | Key.AltMask, 226, 86 }; + yield return new object [] { '<', true, true, true, 226, 86, (Key)'<' | Key.ShiftMask | Key.AltMask | Key.CtrlMask, 226, 86 }; + yield return new object [] { 'ç', false, false, false, 192, 39, (Key)'ç', 192, 39 }; + yield return new object [] { 'Ç', true, false, false, 192, 39, (Key)'Ç' | Key.ShiftMask, 192, 39 }; + yield return new object [] { 'ç', true, true, false, 192, 39, (Key)'ç' | Key.ShiftMask | Key.AltMask, 192, 39 }; + yield return new object [] { 'ç', true, true, true, 192, 39, (Key)'ç' | Key.ShiftMask | Key.AltMask | Key.CtrlMask, 192, 39 }; + yield return new object [] { '¨', false, true, true, 187, 26, (Key)'¨' | Key.AltMask | Key.CtrlMask, 187, 26 }; + yield return new object [] { (uint)Key.PageUp, false, false, false, 33, 73, Key.PageUp, 33, 73 }; + yield return new object [] { (uint)Key.PageUp, true, false, false, 33, 73, Key.PageUp | Key.ShiftMask, 33, 73 }; + yield return new object [] { (uint)Key.PageUp, true, true, false, 33, 73, Key.PageUp | Key.ShiftMask | Key.AltMask, 33, 73 }; + yield return new object [] { (uint)Key.PageUp, true, true, true, 33, 73, Key.PageUp | Key.ShiftMask | Key.AltMask | Key.CtrlMask, 33, 73 }; + } + } + + IEnumerator IEnumerable.GetEnumerator () => GetEnumerator (); + } + } +} \ No newline at end of file diff --git a/UnitTests/Core/ViewTests.cs b/UnitTests/Core/ViewTests.cs deleted file mode 100644 index 64b7c0534..000000000 --- a/UnitTests/Core/ViewTests.cs +++ /dev/null @@ -1,3099 +0,0 @@ -using NStack; -using System; -using System.Collections.Generic; -using Terminal.Gui.Graphs; -using Xunit; -using Xunit.Abstractions; - -// Alias Console to MockConsole so we don't accidentally use Console -using Console = Terminal.Gui.FakeConsole; - -namespace Terminal.Gui.CoreTests { - public class ViewTests { - readonly ITestOutputHelper output; - - public ViewTests (ITestOutputHelper output) - { - this.output = output; - } - - [Fact] - public void New_Initializes () - { - // Parameterless - var r = new View (); - Assert.NotNull (r); - Assert.Equal (LayoutStyle.Computed, r.LayoutStyle); - Assert.Equal ("View()({X=0,Y=0,Width=0,Height=0})", r.ToString ()); - Assert.False (r.CanFocus); - Assert.False (r.HasFocus); - Assert.Equal (new Rect (0, 0, 0, 0), r.Bounds); - Assert.Equal (new Rect (0, 0, 0, 0), r.Frame); - Assert.Null (r.Focused); - Assert.Null (r.ColorScheme); - Assert.Null (r.Width); - Assert.Null (r.Height); - Assert.Null (r.X); - Assert.Null (r.Y); - Assert.False (r.IsCurrentTop); - Assert.Empty (r.Id); - Assert.Empty (r.Subviews); - Assert.False (r.WantContinuousButtonPressed); - Assert.False (r.WantMousePositionReports); - Assert.Null (r.SuperView); - Assert.Null (r.MostFocused); - Assert.Equal (TextDirection.LeftRight_TopBottom, r.TextDirection); - - // Empty Rect - r = new View (Rect.Empty); - Assert.NotNull (r); - Assert.Equal (LayoutStyle.Absolute, r.LayoutStyle); - Assert.Equal ("View()({X=0,Y=0,Width=0,Height=0})", r.ToString ()); - Assert.False (r.CanFocus); - Assert.False (r.HasFocus); - Assert.Equal (new Rect (0, 0, 0, 0), r.Bounds); - Assert.Equal (new Rect (0, 0, 0, 0), r.Frame); - Assert.Null (r.Focused); - Assert.Null (r.ColorScheme); - Assert.Null (r.Width); // All view Dim are initialized now in the IsAdded setter, - Assert.Null (r.Height); // avoiding Dim errors. - Assert.Null (r.X); // All view Pos are initialized now in the IsAdded setter, - Assert.Null (r.Y); // avoiding Pos errors. - Assert.False (r.IsCurrentTop); - Assert.Empty (r.Id); - Assert.Empty (r.Subviews); - Assert.False (r.WantContinuousButtonPressed); - Assert.False (r.WantMousePositionReports); - Assert.Null (r.SuperView); - Assert.Null (r.MostFocused); - Assert.Equal (TextDirection.LeftRight_TopBottom, r.TextDirection); - - // Rect with values - r = new View (new Rect (1, 2, 3, 4)); - Assert.NotNull (r); - Assert.Equal (LayoutStyle.Absolute, r.LayoutStyle); - Assert.Equal ("View()({X=1,Y=2,Width=3,Height=4})", r.ToString ()); - Assert.False (r.CanFocus); - Assert.False (r.HasFocus); - Assert.Equal (new Rect (0, 0, 3, 4), r.Bounds); - Assert.Equal (new Rect (1, 2, 3, 4), r.Frame); - Assert.Null (r.Focused); - Assert.Null (r.ColorScheme); - Assert.Null (r.Width); - Assert.Null (r.Height); - Assert.Null (r.X); - Assert.Null (r.Y); - Assert.False (r.IsCurrentTop); - Assert.Empty (r.Id); - Assert.Empty (r.Subviews); - Assert.False (r.WantContinuousButtonPressed); - Assert.False (r.WantMousePositionReports); - Assert.Null (r.SuperView); - Assert.Null (r.MostFocused); - Assert.Equal (TextDirection.LeftRight_TopBottom, r.TextDirection); - - // Initializes a view with a vertical direction - r = new View ("Vertical View", TextDirection.TopBottom_LeftRight); - Assert.NotNull (r); - Assert.Equal (LayoutStyle.Computed, r.LayoutStyle); - Assert.Equal ("View(Vertical View)({X=0,Y=0,Width=1,Height=13})", r.ToString ()); - Assert.False (r.CanFocus); - Assert.False (r.HasFocus); - Assert.Equal (new Rect (0, 0, 1, 13), r.Bounds); - Assert.Equal (new Rect (0, 0, 1, 13), r.Frame); - Assert.Null (r.Focused); - Assert.Null (r.ColorScheme); - Assert.Null (r.Width); // All view Dim are initialized now in the IsAdded setter, - Assert.Null (r.Height); // avoiding Dim errors. - Assert.Null (r.X); // All view Pos are initialized now in the IsAdded setter, - Assert.Null (r.Y); // avoiding Pos errors. - Assert.False (r.IsCurrentTop); - Assert.Equal ("Vertical View", r.Id); - Assert.Empty (r.Subviews); - Assert.False (r.WantContinuousButtonPressed); - Assert.False (r.WantMousePositionReports); - Assert.Null (r.SuperView); - Assert.Null (r.MostFocused); - Assert.Equal (TextDirection.TopBottom_LeftRight, r.TextDirection); - - } - - [Fact] - public void New_Methods_Return_False () - { - var r = new View (); - - Assert.False (r.ProcessKey (new KeyEvent () { Key = Key.Unknown })); - Assert.False (r.ProcessHotKey (new KeyEvent () { Key = Key.Unknown })); - Assert.False (r.ProcessColdKey (new KeyEvent () { Key = Key.Unknown })); - Assert.False (r.OnKeyDown (new KeyEvent () { Key = Key.Unknown })); - Assert.False (r.OnKeyUp (new KeyEvent () { Key = Key.Unknown })); - Assert.False (r.MouseEvent (new MouseEvent () { Flags = MouseFlags.AllEvents })); - Assert.False (r.OnMouseEnter (new MouseEvent () { Flags = MouseFlags.AllEvents })); - Assert.False (r.OnMouseLeave (new MouseEvent () { Flags = MouseFlags.AllEvents })); - Assert.False (r.OnEnter (new View ())); - Assert.False (r.OnLeave (new View ())); - - // TODO: Add more - } - - - [Fact] - public void View_With_No_Difference_Between_An_Object_Initializer_And_A_Constructor () - { - // Object Initializer - var view = new View () { - X = 1, - Y = 2, - Width = 3, - Height = 4 - }; - var super = new View (new Rect (0, 0, 10, 10)); - super.Add (view); - super.BeginInit (); - super.EndInit (); - super.LayoutSubviews (); - - Assert.Equal (1, view.X); - Assert.Equal (2, view.Y); - Assert.Equal (3, view.Width); - Assert.Equal (4, view.Height); - Assert.False (view.Frame.IsEmpty); - Assert.Equal (new Rect (1, 2, 3, 4), view.Frame); - Assert.False (view.Bounds.IsEmpty); - Assert.Equal (new Rect (0, 0, 3, 4), view.Bounds); - - view.LayoutSubviews (); - - Assert.Equal (1, view.X); - Assert.Equal (2, view.Y); - Assert.Equal (3, view.Width); - Assert.Equal (4, view.Height); - Assert.False (view.Frame.IsEmpty); - Assert.False (view.Bounds.IsEmpty); - - // Default Constructor - view = new View (); - Assert.Null (view.X); - Assert.Null (view.Y); - Assert.Null (view.Width); - Assert.Null (view.Height); - Assert.True (view.Frame.IsEmpty); - Assert.True (view.Bounds.IsEmpty); - - // Constructor - view = new View (1, 2, ""); - Assert.Null (view.X); - Assert.Null (view.Y); - Assert.Null (view.Width); - Assert.Null (view.Height); - Assert.False (view.Frame.IsEmpty); - Assert.True (view.Bounds.IsEmpty); - - // Default Constructor and post assignment equivalent to Object Initializer - view = new View (); - view.X = 1; - view.Y = 2; - view.Width = 3; - view.Height = 4; - super = new View (new Rect (0, 0, 10, 10)); - super.Add (view); - super.BeginInit (); - super.EndInit (); - super.LayoutSubviews (); - Assert.Equal (1, view.X); - Assert.Equal (2, view.Y); - Assert.Equal (3, view.Width); - Assert.Equal (4, view.Height); - Assert.False (view.Frame.IsEmpty); - Assert.Equal (new Rect (1, 2, 3, 4), view.Frame); - Assert.False (view.Bounds.IsEmpty); - Assert.Equal (new Rect (0, 0, 3, 4), view.Bounds); - } - - [Fact] - public void FocusNearestView_Ensure_Focus_Ordered () - { - var top = new Toplevel (); - - var win = new Window (); - var winSubview = new View ("WindowSubview") { - CanFocus = true - }; - win.Add (winSubview); - top.Add (win); - - var frm = new FrameView (); - var frmSubview = new View ("FrameSubview") { - CanFocus = true - }; - frm.Add (frmSubview); - top.Add (frm); - - top.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ())); - Assert.Equal ($"WindowSubview", top.MostFocused.Text); - top.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ())); - Assert.Equal ("FrameSubview", top.MostFocused.Text); - top.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ())); - Assert.Equal ($"WindowSubview", top.MostFocused.Text); - - top.ProcessKey (new KeyEvent (Key.BackTab | Key.ShiftMask, new KeyModifiers ())); - Assert.Equal ("FrameSubview", top.MostFocused.Text); - top.ProcessKey (new KeyEvent (Key.BackTab | Key.ShiftMask, new KeyModifiers ())); - Assert.Equal ($"WindowSubview", top.MostFocused.Text); - } - - [Fact] - public void Added_Removed () - { - var v = new View (new Rect (0, 0, 10, 24)); - var t = new View (); - - v.Added += (s, e) => { - Assert.Same (v.SuperView, e.Parent); - Assert.Same (t, e.Parent); - Assert.Same (v, e.Child); - }; - - v.Removed += (s, e) => { - Assert.Same (t, e.Parent); - Assert.Same (v, e.Child); - Assert.True (v.SuperView == null); - }; - - t.Add (v); - Assert.True (t.Subviews.Count == 1); - - t.Remove (v); - Assert.True (t.Subviews.Count == 0); - } - - [Fact] - public void Subviews_TabIndexes_AreEqual () - { - var r = new View (); - var v1 = new View () { CanFocus = true }; - var v2 = new View () { CanFocus = true }; - var v3 = new View () { CanFocus = true }; - - r.Add (v1, v2, v3); - - Assert.True (r.Subviews.IndexOf (v1) == 0); - Assert.True (r.Subviews.IndexOf (v2) == 1); - Assert.True (r.Subviews.IndexOf (v3) == 2); - - Assert.True (r.TabIndexes.IndexOf (v1) == 0); - Assert.True (r.TabIndexes.IndexOf (v2) == 1); - Assert.True (r.TabIndexes.IndexOf (v3) == 2); - - Assert.Equal (r.Subviews.IndexOf (v1), r.TabIndexes.IndexOf (v1)); - Assert.Equal (r.Subviews.IndexOf (v2), r.TabIndexes.IndexOf (v2)); - Assert.Equal (r.Subviews.IndexOf (v3), r.TabIndexes.IndexOf (v3)); - } - - [Fact] - public void BringSubviewToFront_Subviews_vs_TabIndexes () - { - var r = new View (); - var v1 = new View () { CanFocus = true }; - var v2 = new View () { CanFocus = true }; - var v3 = new View () { CanFocus = true }; - - r.Add (v1, v2, v3); - - r.BringSubviewToFront (v1); - Assert.True (r.Subviews.IndexOf (v1) == 2); - Assert.True (r.Subviews.IndexOf (v2) == 0); - Assert.True (r.Subviews.IndexOf (v3) == 1); - - Assert.True (r.TabIndexes.IndexOf (v1) == 0); - Assert.True (r.TabIndexes.IndexOf (v2) == 1); - Assert.True (r.TabIndexes.IndexOf (v3) == 2); - } - - [Fact] - public void BringSubviewForward_Subviews_vs_TabIndexes () - { - var r = new View (); - var v1 = new View () { CanFocus = true }; - var v2 = new View () { CanFocus = true }; - var v3 = new View () { CanFocus = true }; - - r.Add (v1, v2, v3); - - r.BringSubviewForward (v1); - Assert.True (r.Subviews.IndexOf (v1) == 1); - Assert.True (r.Subviews.IndexOf (v2) == 0); - Assert.True (r.Subviews.IndexOf (v3) == 2); - - Assert.True (r.TabIndexes.IndexOf (v1) == 0); - Assert.True (r.TabIndexes.IndexOf (v2) == 1); - Assert.True (r.TabIndexes.IndexOf (v3) == 2); - } - - [Fact] - public void SendSubviewToBack_Subviews_vs_TabIndexes () - { - var r = new View (); - var v1 = new View () { CanFocus = true }; - var v2 = new View () { CanFocus = true }; - var v3 = new View () { CanFocus = true }; - - r.Add (v1, v2, v3); - - r.SendSubviewToBack (v3); - Assert.True (r.Subviews.IndexOf (v1) == 1); - Assert.True (r.Subviews.IndexOf (v2) == 2); - Assert.True (r.Subviews.IndexOf (v3) == 0); - - Assert.True (r.TabIndexes.IndexOf (v1) == 0); - Assert.True (r.TabIndexes.IndexOf (v2) == 1); - Assert.True (r.TabIndexes.IndexOf (v3) == 2); - } - - [Fact] - public void SendSubviewBackwards_Subviews_vs_TabIndexes () - { - var r = new View (); - var v1 = new View () { CanFocus = true }; - var v2 = new View () { CanFocus = true }; - var v3 = new View () { CanFocus = true }; - - r.Add (v1, v2, v3); - - r.SendSubviewBackwards (v3); - Assert.True (r.Subviews.IndexOf (v1) == 0); - Assert.True (r.Subviews.IndexOf (v2) == 2); - Assert.True (r.Subviews.IndexOf (v3) == 1); - - Assert.True (r.TabIndexes.IndexOf (v1) == 0); - Assert.True (r.TabIndexes.IndexOf (v2) == 1); - Assert.True (r.TabIndexes.IndexOf (v3) == 2); - } - - [Fact] - public void TabIndex_Set_CanFocus_ValidValues () - { - var r = new View (); - var v1 = new View () { CanFocus = true }; - var v2 = new View () { CanFocus = true }; - var v3 = new View () { CanFocus = true }; - - r.Add (v1, v2, v3); - - v1.TabIndex = 1; - Assert.True (r.Subviews.IndexOf (v1) == 0); - Assert.True (r.TabIndexes.IndexOf (v1) == 1); - - v1.TabIndex = 2; - Assert.True (r.Subviews.IndexOf (v1) == 0); - Assert.True (r.TabIndexes.IndexOf (v1) == 2); - } - - [Fact] - public void TabIndex_Set_CanFocus_HigherValues () - { - var r = new View (); - var v1 = new View () { CanFocus = true }; - var v2 = new View () { CanFocus = true }; - var v3 = new View () { CanFocus = true }; - - r.Add (v1, v2, v3); - - v1.TabIndex = 3; - Assert.True (r.Subviews.IndexOf (v1) == 0); - Assert.True (r.TabIndexes.IndexOf (v1) == 2); - } - - [Fact] - public void TabIndex_Set_CanFocus_LowerValues () - { - var r = new View (); - var v1 = new View () { CanFocus = true }; - var v2 = new View () { CanFocus = true }; - var v3 = new View () { CanFocus = true }; - - r.Add (v1, v2, v3); - - v1.TabIndex = -1; - Assert.True (r.Subviews.IndexOf (v1) == 0); - Assert.True (r.TabIndexes.IndexOf (v1) == 0); - } - - [Fact] - public void TabIndex_Set_CanFocus_False () - { - var r = new View (); - var v1 = new View () { CanFocus = true }; - var v2 = new View () { CanFocus = true }; - var v3 = new View () { CanFocus = true }; - - r.Add (v1, v2, v3); - - v1.CanFocus = false; - v1.TabIndex = 0; - Assert.True (r.Subviews.IndexOf (v1) == 0); - Assert.True (r.TabIndexes.IndexOf (v1) == 0); - Assert.Equal (-1, v1.TabIndex); - } - - [Fact] - public void TabIndex_Set_CanFocus_False_To_True () - { - var r = new View (); - var v1 = new View (); - var v2 = new View () { CanFocus = true }; - var v3 = new View () { CanFocus = true }; - - r.Add (v1, v2, v3); - - v1.CanFocus = true; - v1.TabIndex = 1; - Assert.True (r.Subviews.IndexOf (v1) == 0); - Assert.True (r.TabIndexes.IndexOf (v1) == 1); - } - - [Fact] - public void TabStop_And_CanFocus_Are_All_True () - { - var r = new View (); - var v1 = new View () { CanFocus = true }; - var v2 = new View () { CanFocus = true }; - var v3 = new View () { CanFocus = true }; - - r.Add (v1, v2, v3); - - r.FocusNext (); - Assert.True (v1.HasFocus); - Assert.False (v2.HasFocus); - Assert.False (v3.HasFocus); - r.FocusNext (); - Assert.False (v1.HasFocus); - Assert.True (v2.HasFocus); - Assert.False (v3.HasFocus); - r.FocusNext (); - Assert.False (v1.HasFocus); - Assert.False (v2.HasFocus); - Assert.True (v3.HasFocus); - } - - [Fact] - public void TabStop_Are_All_True_And_CanFocus_Are_All_False () - { - var r = new View (); - var v1 = new View (); - var v2 = new View (); - var v3 = new View (); - - r.Add (v1, v2, v3); - - r.FocusNext (); - Assert.False (v1.HasFocus); - Assert.False (v2.HasFocus); - Assert.False (v3.HasFocus); - r.FocusNext (); - Assert.False (v1.HasFocus); - Assert.False (v2.HasFocus); - Assert.False (v3.HasFocus); - r.FocusNext (); - Assert.False (v1.HasFocus); - Assert.False (v2.HasFocus); - Assert.False (v3.HasFocus); - } - - [Fact] - public void TabStop_Are_All_False_And_CanFocus_Are_All_True () - { - var r = new View (); - var v1 = new View () { CanFocus = true, TabStop = false }; - var v2 = new View () { CanFocus = true, TabStop = false }; - var v3 = new View () { CanFocus = true, TabStop = false }; - - r.Add (v1, v2, v3); - - r.FocusNext (); - Assert.False (v1.HasFocus); - Assert.False (v2.HasFocus); - Assert.False (v3.HasFocus); - r.FocusNext (); - Assert.False (v1.HasFocus); - Assert.False (v2.HasFocus); - Assert.False (v3.HasFocus); - r.FocusNext (); - Assert.False (v1.HasFocus); - Assert.False (v2.HasFocus); - Assert.False (v3.HasFocus); - } - - [Fact] - public void TabStop_And_CanFocus_Mixed_And_BothFalse () - { - var r = new View (); - var v1 = new View () { CanFocus = true, TabStop = false }; - var v2 = new View () { CanFocus = false, TabStop = true }; - var v3 = new View () { CanFocus = false, TabStop = false }; - - r.Add (v1, v2, v3); - - r.FocusNext (); - Assert.False (v1.HasFocus); - Assert.False (v2.HasFocus); - Assert.False (v3.HasFocus); - r.FocusNext (); - Assert.False (v1.HasFocus); - Assert.False (v2.HasFocus); - Assert.False (v3.HasFocus); - r.FocusNext (); - Assert.False (v1.HasFocus); - Assert.False (v2.HasFocus); - Assert.False (v3.HasFocus); - } - - [Fact] - public void TabStop_All_True_And_Changing_CanFocus_Later () - { - var r = new View (); - var v1 = new View (); - var v2 = new View (); - var v3 = new View (); - - r.Add (v1, v2, v3); - - r.FocusNext (); - Assert.False (v1.HasFocus); - Assert.False (v2.HasFocus); - Assert.False (v3.HasFocus); - - v1.CanFocus = true; - r.FocusNext (); - Assert.True (v1.HasFocus); - Assert.False (v2.HasFocus); - Assert.False (v3.HasFocus); - v2.CanFocus = true; - r.FocusNext (); - Assert.False (v1.HasFocus); - Assert.True (v2.HasFocus); - Assert.False (v3.HasFocus); - v3.CanFocus = true; - r.FocusNext (); - Assert.False (v1.HasFocus); - Assert.False (v2.HasFocus); - Assert.True (v3.HasFocus); - } - - [Fact] - public void TabStop_All_False_And_All_True_And_Changing_TabStop_Later () - { - var r = new View (); - var v1 = new View () { CanFocus = true, TabStop = false }; - var v2 = new View () { CanFocus = true, TabStop = false }; - var v3 = new View () { CanFocus = true, TabStop = false }; - - r.Add (v1, v2, v3); - - r.FocusNext (); - Assert.False (v1.HasFocus); - Assert.False (v2.HasFocus); - Assert.False (v3.HasFocus); - - v1.TabStop = true; - r.FocusNext (); - Assert.True (v1.HasFocus); - Assert.False (v2.HasFocus); - Assert.False (v3.HasFocus); - v2.TabStop = true; - r.FocusNext (); - Assert.False (v1.HasFocus); - Assert.True (v2.HasFocus); - Assert.False (v3.HasFocus); - v3.TabStop = true; - r.FocusNext (); - Assert.False (v1.HasFocus); - Assert.False (v2.HasFocus); - Assert.True (v3.HasFocus); - } - - [Fact] - public void CanFocus_Set_Changes_TabIndex_And_TabStop () - { - var r = new View (); - var v1 = new View ("1"); - var v2 = new View ("2"); - var v3 = new View ("3"); - - r.Add (v1, v2, v3); - - v2.CanFocus = true; - Assert.Equal (r.TabIndexes.IndexOf (v2), v2.TabIndex); - Assert.Equal (0, v2.TabIndex); - Assert.True (v2.TabStop); - - v1.CanFocus = true; - Assert.Equal (r.TabIndexes.IndexOf (v1), v1.TabIndex); - Assert.Equal (1, v1.TabIndex); - Assert.True (v1.TabStop); - - v1.TabIndex = 2; - Assert.Equal (r.TabIndexes.IndexOf (v1), v1.TabIndex); - Assert.Equal (1, v1.TabIndex); - v3.CanFocus = true; - Assert.Equal (r.TabIndexes.IndexOf (v1), v1.TabIndex); - Assert.Equal (1, v1.TabIndex); - Assert.Equal (r.TabIndexes.IndexOf (v3), v3.TabIndex); - Assert.Equal (2, v3.TabIndex); - Assert.True (v3.TabStop); - - v2.CanFocus = false; - Assert.Equal (r.TabIndexes.IndexOf (v1), v1.TabIndex); - Assert.Equal (1, v1.TabIndex); - Assert.True (v1.TabStop); - Assert.NotEqual (r.TabIndexes.IndexOf (v2), v2.TabIndex); - Assert.Equal (-1, v2.TabIndex); - Assert.False (v2.TabStop); - Assert.Equal (r.TabIndexes.IndexOf (v3), v3.TabIndex); - Assert.Equal (2, v3.TabIndex); - Assert.True (v3.TabStop); - } - - [Fact] - public void Initialized_Event_Comparing_With_Added_Event () - { - Application.Init (new FakeDriver ()); - - var t = new Toplevel () { Id = "0", }; - - var w = new Window () { Id = "t", Width = Dim.Fill (), Height = Dim.Fill () }; - var v1 = new View () { Id = "v1", Width = Dim.Fill (), Height = Dim.Fill () }; - var v2 = new View () { Id = "v2", Width = Dim.Fill (), Height = Dim.Fill () }; - var sv1 = new View () { Id = "sv1", Width = Dim.Fill (), Height = Dim.Fill () }; - - int tc = 0, wc = 0, v1c = 0, v2c = 0, sv1c = 0; - - w.Added += (s, e) => { - Assert.Equal (e.Parent.Frame.Width, w.Frame.Width); - Assert.Equal (e.Parent.Frame.Height, w.Frame.Height); - }; - v1.Added += (s, e) => { - Assert.Equal (e.Parent.Frame.Width, v1.Frame.Width); - Assert.Equal (e.Parent.Frame.Height, v1.Frame.Height); - }; - v2.Added += (s, e) => { - Assert.Equal (e.Parent.Frame.Width, v2.Frame.Width); - Assert.Equal (e.Parent.Frame.Height, v2.Frame.Height); - }; - sv1.Added += (s, e) => { - Assert.Equal (e.Parent.Frame.Width, sv1.Frame.Width); - Assert.Equal (e.Parent.Frame.Height, sv1.Frame.Height); - }; - - t.Initialized += (s, e) => { - tc++; - Assert.Equal (1, tc); - Assert.Equal (1, wc); - Assert.Equal (1, v1c); - Assert.Equal (1, v2c); - Assert.Equal (1, sv1c); - - Assert.True (t.CanFocus); - Assert.True (w.CanFocus); - Assert.False (v1.CanFocus); - Assert.False (v2.CanFocus); - Assert.False (sv1.CanFocus); - - Application.Refresh (); - }; - w.Initialized += (s, e) => { - wc++; - Assert.Equal (t.Frame.Width, w.Frame.Width); - Assert.Equal (t.Frame.Height, w.Frame.Height); - }; - v1.Initialized += (s, e) => { - v1c++; - Assert.Equal (t.Frame.Width, v1.Frame.Width); - Assert.Equal (t.Frame.Height, v1.Frame.Height); - }; - v2.Initialized += (s, e) => { - v2c++; - Assert.Equal (t.Frame.Width, v2.Frame.Width); - Assert.Equal (t.Frame.Height, v2.Frame.Height); - }; - sv1.Initialized += (s, e) => { - sv1c++; - Assert.Equal (t.Frame.Width, sv1.Frame.Width); - Assert.Equal (t.Frame.Height, sv1.Frame.Height); - Assert.False (sv1.CanFocus); - Assert.Throws (() => sv1.CanFocus = true); - Assert.False (sv1.CanFocus); - }; - - v1.Add (sv1); - w.Add (v1, v2); - t.Add (w); - - Application.Iteration = () => { - Application.Refresh (); - t.Running = false; - }; - - Application.Run (t); - Application.Shutdown (); - - Assert.Equal (1, tc); - Assert.Equal (1, wc); - Assert.Equal (1, v1c); - Assert.Equal (1, v2c); - Assert.Equal (1, sv1c); - - Assert.True (t.CanFocus); - Assert.True (w.CanFocus); - Assert.False (v1.CanFocus); - Assert.False (v2.CanFocus); - Assert.False (sv1.CanFocus); - - v1.CanFocus = true; - Assert.False (sv1.CanFocus); // False because sv1 was disposed and it isn't a subview of v1. - } - - [Fact] - public void Initialized_Event_Will_Be_Invoked_When_Added_Dynamically () - { - Application.Init (new FakeDriver ()); - - var t = new Toplevel () { Id = "0", }; - - var w = new Window () { Id = "t", Width = Dim.Fill (), Height = Dim.Fill () }; - var v1 = new View () { Id = "v1", Width = Dim.Fill (), Height = Dim.Fill () }; - var v2 = new View () { Id = "v2", Width = Dim.Fill (), Height = Dim.Fill () }; - - int tc = 0, wc = 0, v1c = 0, v2c = 0, sv1c = 0; - - t.Initialized += (s, e) => { - tc++; - Assert.Equal (1, tc); - Assert.Equal (1, wc); - Assert.Equal (1, v1c); - Assert.Equal (1, v2c); - Assert.Equal (0, sv1c); // Added after t in the Application.Iteration. - - Assert.True (t.CanFocus); - Assert.True (w.CanFocus); - Assert.False (v1.CanFocus); - Assert.False (v2.CanFocus); - - Application.Refresh (); - }; - w.Initialized += (s, e) => { - wc++; - Assert.Equal (t.Frame.Width, w.Frame.Width); - Assert.Equal (t.Frame.Height, w.Frame.Height); - }; - v1.Initialized += (s, e) => { - v1c++; - Assert.Equal (t.Frame.Width, v1.Frame.Width); - Assert.Equal (t.Frame.Height, v1.Frame.Height); - }; - v2.Initialized += (s, e) => { - v2c++; - Assert.Equal (t.Frame.Width, v2.Frame.Width); - Assert.Equal (t.Frame.Height, v2.Frame.Height); - }; - w.Add (v1, v2); - t.Add (w); - - Application.Iteration = () => { - var sv1 = new View () { Id = "sv1", Width = Dim.Fill (), Height = Dim.Fill () }; - - sv1.Initialized += (s, e) => { - sv1c++; - Assert.NotEqual (t.Frame.Width, sv1.Frame.Width); - Assert.NotEqual (t.Frame.Height, sv1.Frame.Height); - Assert.False (sv1.CanFocus); - Assert.Throws (() => sv1.CanFocus = true); - Assert.False (sv1.CanFocus); - }; - - v1.Add (sv1); - - Application.Refresh (); - t.Running = false; - }; - - Application.Run (t); - Application.Shutdown (); - - Assert.Equal (1, tc); - Assert.Equal (1, wc); - Assert.Equal (1, v1c); - Assert.Equal (1, v2c); - Assert.Equal (1, sv1c); - - Assert.True (t.CanFocus); - Assert.True (w.CanFocus); - Assert.False (v1.CanFocus); - Assert.False (v2.CanFocus); - } - - [Fact] - [AutoInitShutdown] - public void CanFocus_Faced_With_Container () - { - var t = new Toplevel (); - var w = new Window (); - var f = new FrameView (); - var v = new View () { CanFocus = true }; - f.Add (v); - w.Add (f); - t.Add (w); - - Assert.True (t.CanFocus); - Assert.True (w.CanFocus); - Assert.True (f.CanFocus); - Assert.True (v.CanFocus); - - f.CanFocus = false; - Assert.False (f.CanFocus); - Assert.True (v.CanFocus); - - v.CanFocus = false; - Assert.False (f.CanFocus); - Assert.False (v.CanFocus); - - v.CanFocus = true; - Assert.False (f.CanFocus); - Assert.True (v.CanFocus); - } - - [Fact] - public void CanFocus_Faced_With_Container_Before_Run () - { - Application.Init (new FakeDriver ()); - - var t = Application.Top; - - var w = new Window ("w"); - var f = new FrameView ("f"); - var v = new View ("v") { CanFocus = true }; - f.Add (v); - w.Add (f); - t.Add (w); - - Assert.True (t.CanFocus); - Assert.True (w.CanFocus); - Assert.True (f.CanFocus); - Assert.True (v.CanFocus); - - f.CanFocus = false; - Assert.False (f.CanFocus); - Assert.True (v.CanFocus); - - v.CanFocus = false; - Assert.False (f.CanFocus); - Assert.False (v.CanFocus); - - v.CanFocus = true; - Assert.False (f.CanFocus); - Assert.True (v.CanFocus); - - Application.Iteration += () => Application.RequestStop (); - - Application.Run (); - Application.Shutdown (); - } - - [Fact] - public void CanFocus_Faced_With_Container_After_Run () - { - Application.Init (new FakeDriver ()); - - var t = Application.Top; - - var w = new Window ("w"); - var f = new FrameView ("f"); - var v = new View ("v") { CanFocus = true }; - f.Add (v); - w.Add (f); - t.Add (w); - - t.Ready += (s, e) => { - Assert.True (t.CanFocus); - Assert.True (w.CanFocus); - Assert.True (f.CanFocus); - Assert.True (v.CanFocus); - - f.CanFocus = false; - Assert.False (f.CanFocus); - Assert.False (v.CanFocus); - - v.CanFocus = false; - Assert.False (f.CanFocus); - Assert.False (v.CanFocus); - - Assert.Throws (() => v.CanFocus = true); - Assert.False (f.CanFocus); - Assert.False (v.CanFocus); - - f.CanFocus = true; - Assert.True (f.CanFocus); - Assert.True (v.CanFocus); - }; - - Application.Iteration += () => Application.RequestStop (); - - Application.Run (); - Application.Shutdown (); - } - - [Fact] - public void CanFocus_Container_ToFalse_Turns_All_Subviews_ToFalse_Too () - { - Application.Init (new FakeDriver ()); - - var t = Application.Top; - - var w = new Window ("w"); - var f = new FrameView ("f"); - var v1 = new View ("v1") { CanFocus = true }; - var v2 = new View ("v2") { CanFocus = true }; - f.Add (v1, v2); - w.Add (f); - t.Add (w); - - t.Ready += (s, e) => { - Assert.True (t.CanFocus); - Assert.True (w.CanFocus); - Assert.True (f.CanFocus); - Assert.True (v1.CanFocus); - Assert.True (v2.CanFocus); - - w.CanFocus = false; - Assert.False (w.CanFocus); - Assert.False (f.CanFocus); - Assert.False (v1.CanFocus); - Assert.False (v2.CanFocus); - }; - - Application.Iteration += () => Application.RequestStop (); - - Application.Run (); - Application.Shutdown (); - } - - [Fact] - public void CanFocus_Container_Toggling_All_Subviews_To_Old_Value_When_Is_True () - { - Application.Init (new FakeDriver ()); - - var t = Application.Top; - - var w = new Window ("w"); - var f = new FrameView ("f"); - var v1 = new View ("v1"); - var v2 = new View ("v2") { CanFocus = true }; - f.Add (v1, v2); - w.Add (f); - t.Add (w); - - t.Ready += (s, e) => { - Assert.True (t.CanFocus); - Assert.True (w.CanFocus); - Assert.True (f.CanFocus); - Assert.False (v1.CanFocus); - Assert.True (v2.CanFocus); - - w.CanFocus = false; - Assert.False (w.CanFocus); - Assert.False (f.CanFocus); - Assert.False (v1.CanFocus); - Assert.False (v2.CanFocus); - - w.CanFocus = true; - Assert.True (w.CanFocus); - Assert.True (f.CanFocus); - Assert.False (v1.CanFocus); - Assert.True (v2.CanFocus); - }; - - Application.Iteration += () => Application.RequestStop (); - - Application.Run (); - Application.Shutdown (); - } - - - [Fact] - public void Navigation_With_Null_Focused_View () - { - // Non-regression test for #882 (NullReferenceException during keyboard navigation when Focused is null) - - Application.Init (new FakeDriver ()); - - Application.Top.Ready += (s, e) => { - Assert.Null (Application.Top.Focused); - }; - - // Keyboard navigation with tab - Console.MockKeyPresses.Push (new ConsoleKeyInfo ('\t', ConsoleKey.Tab, false, false, false)); - - Application.Iteration += () => Application.RequestStop (); - - Application.Run (); - Application.Shutdown (); - } - - [Fact] - public void Multi_Thread_Toplevels () - { - Application.Init (new FakeDriver ()); - - var t = Application.Top; - var w = new Window (); - t.Add (w); - - int count = 0, count1 = 0, count2 = 0; - bool log = false, log1 = false, log2 = false; - bool fromTopStillKnowFirstIsRunning = false; - bool fromTopStillKnowSecondIsRunning = false; - bool fromFirstStillKnowSecondIsRunning = false; - - Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (100), (_) => { - count++; - if (count1 == 5) { - log1 = true; - } - if (count1 == 14 && count2 == 10 && count == 15) { // count2 is already stopped - fromTopStillKnowFirstIsRunning = true; - } - if (count1 == 7 && count2 == 7 && count == 8) { - fromTopStillKnowSecondIsRunning = true; - } - if (count == 30) { - Assert.Equal (30, count); - Assert.Equal (20, count1); - Assert.Equal (10, count2); - - Assert.True (log); - Assert.True (log1); - Assert.True (log2); - - Assert.True (fromTopStillKnowFirstIsRunning); - Assert.True (fromTopStillKnowSecondIsRunning); - Assert.True (fromFirstStillKnowSecondIsRunning); - - Application.RequestStop (); - return false; - } - return true; - }); - - t.Ready += FirstDialogToplevel; - - void FirstDialogToplevel (object sender, EventArgs args) - { - var od = new OpenDialog (); - od.Ready += SecondDialogToplevel; - - Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (100), (_) => { - count1++; - if (count2 == 5) { - log2 = true; - } - if (count2 == 4 && count1 == 5 && count == 5) { - fromFirstStillKnowSecondIsRunning = true; - } - if (count1 == 20) { - Assert.Equal (20, count1); - Application.RequestStop (); - return false; - } - return true; - }); - - Application.Run (od); - } - - void SecondDialogToplevel (object sender, EventArgs args) - { - var d = new Dialog (); - - Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (100), (_) => { - count2++; - if (count < 30) { - log = true; - } - if (count2 == 10) { - Assert.Equal (10, count2); - Application.RequestStop (); - return false; - } - return true; - }); - - Application.Run (d); - } - - Application.Run (); - Application.Shutdown (); - } - - [Fact] - public void KeyPress_Handled_To_True_Prevents_Changes () - { - Application.Init (new FakeDriver ()); - - Console.MockKeyPresses.Push (new ConsoleKeyInfo ('N', ConsoleKey.N, false, false, false)); - - var top = Application.Top; - - var text = new TextField (""); - text.KeyPress += (s, e) => { - e.Handled = true; - Assert.True (e.Handled); - Assert.Equal (Key.N, e.KeyEvent.Key); - }; - top.Add (text); - - Application.Iteration += () => { - Console.MockKeyPresses.Push (new ConsoleKeyInfo ('N', ConsoleKey.N, false, false, false)); - Assert.Equal ("", text.Text); - - Application.RequestStop (); - }; - - Application.Run (); - - // Shutdown must be called to safely clean up Application if Init has been called - Application.Shutdown (); - } - - - [Theory] - [InlineData (1)] - [InlineData (2)] - [InlineData (3)] - public void LabelChangeText_RendersCorrectly_Constructors (int choice) - { - var driver = new FakeDriver (); - Application.Init (driver); - - try { - // Create a label with a short text - Label lbl; - var text = "test"; - - if (choice == 1) { - // An object initializer should call the default constructor. - lbl = new Label { Text = text }; - } else if (choice == 2) { - // Calling the default constructor followed by the object initializer. - lbl = new Label () { Text = text }; - } else { - // Calling the Text constructor. - lbl = new Label (text); - } - Application.Top.Add (lbl); - Application.Top.LayoutSubviews (); - Application.Top.Redraw (Application.Top.Bounds); - - // should have the initial text - Assert.Equal ('t', driver.Contents [0, 0, 0]); - Assert.Equal ('e', driver.Contents [0, 1, 0]); - Assert.Equal ('s', driver.Contents [0, 2, 0]); - Assert.Equal ('t', driver.Contents [0, 3, 0]); - Assert.Equal (' ', driver.Contents [0, 4, 0]); - } finally { - Application.Shutdown (); - } - } - - [Fact] - [AutoInitShutdown] - public void Internal_Tests () - { - Assert.Equal (new [] { View.Direction.Forward, View.Direction.Backward }, - Enum.GetValues (typeof (View.Direction))); - - var rect = new Rect (1, 1, 10, 1); - var view = new View (rect); - var top = Application.Top; - top.Add (view); - - Assert.Equal (View.Direction.Forward, view.FocusDirection); - view.FocusDirection = View.Direction.Backward; - Assert.Equal (View.Direction.Backward, view.FocusDirection); - Assert.Empty (view.InternalSubviews); - // BUGBUG: v2 - _needsDisplay needs debugging - test disabled for now. - //Assert.Equal (new Rect (new Point (0, 0), rect.Size), view._needsDisplay); - Assert.True (view.LayoutNeeded); - Assert.False (view._childNeedsDisplay); - Assert.False (view.addingView); - view.addingView = true; - Assert.True (view.addingView); - view.ViewToScreen (0, 0, out int rcol, out int rrow); - Assert.Equal (1, rcol); - Assert.Equal (1, rrow); - Assert.Equal (rect, view.ViewToScreen (view.Bounds)); - Assert.Equal (top.Bounds, view.ScreenClip (top.Bounds)); - Assert.True (view.LayoutStyle == LayoutStyle.Absolute); - - Application.Begin (top); - - view.Width = Dim.Fill (); - view.Height = Dim.Fill (); - Assert.Equal (10, view.Bounds.Width); - Assert.Equal (1, view.Bounds.Height); - view.LayoutStyle = LayoutStyle.Computed; - view.SetRelativeLayout (top.Bounds); - top.LayoutSubviews (); // BUGBUG: v2 - ?? - Assert.Equal (1, view.Frame.X); - Assert.Equal (1, view.Frame.Y); - Assert.Equal (79, view.Frame.Width); - Assert.Equal (24, view.Frame.Height); - Assert.Equal (0, view.Bounds.X); - Assert.Equal (0, view.Bounds.Y); - Assert.Equal (79, view.Bounds.Width); - Assert.Equal (24, view.Bounds.Height); - - - view.X = 0; - view.Y = 0; - Assert.Equal ("Absolute(0)", view.X.ToString ()); - Assert.Equal ("Fill(0)", view.Width.ToString ()); - view.SetRelativeLayout (top.Bounds); - top.LayoutSubviews (); // BUGBUG: v2 - ?? - Assert.Equal (0, view.Frame.X); - Assert.Equal (0, view.Frame.Y); - Assert.Equal (80, view.Frame.Width); - Assert.Equal (25, view.Frame.Height); - Assert.Equal (0, view.Bounds.X); - Assert.Equal (0, view.Bounds.Y); - Assert.Equal (80, view.Bounds.Width); - Assert.Equal (25, view.Bounds.Height); - bool layoutStarted = false; - view.LayoutStarted += (s, e) => layoutStarted = true; - view.OnLayoutStarted (null); - Assert.True (layoutStarted); - view.LayoutComplete += (s, e) => layoutStarted = false; - view.OnLayoutComplete (null); - Assert.False (layoutStarted); - view.X = Pos.Center () - 41; - view.Y = Pos.Center () - 13; - view.SetRelativeLayout (top.Bounds); - top.LayoutSubviews (); // BUGBUG: v2 - ?? - view.ViewToScreen (0, 0, out rcol, out rrow); - Assert.Equal (-41, rcol); - Assert.Equal (-13, rrow); - } - - [Fact] - [AutoInitShutdown] - public void Enabled_False_Sets_HasFocus_To_False () - { - var wasClicked = false; - var view = new Button ("Click Me"); - view.Clicked += (s, e) => wasClicked = !wasClicked; - Application.Top.Add (view); - - view.ProcessKey (new KeyEvent (Key.Enter, null)); - Assert.True (wasClicked); - view.MouseEvent (new MouseEvent () { Flags = MouseFlags.Button1Clicked }); - Assert.False (wasClicked); - Assert.True (view.Enabled); - Assert.True (view.CanFocus); - Assert.True (view.HasFocus); - - view.Enabled = false; - view.ProcessKey (new KeyEvent (Key.Enter, null)); - Assert.False (wasClicked); - view.MouseEvent (new MouseEvent () { Flags = MouseFlags.Button1Clicked }); - Assert.False (wasClicked); - Assert.False (view.Enabled); - Assert.True (view.CanFocus); - Assert.False (view.HasFocus); - view.SetFocus (); - Assert.False (view.HasFocus); - } - - [Fact] - [AutoInitShutdown] - public void Enabled_Sets_Also_Sets_Subviews () - { - var wasClicked = false; - var button = new Button ("Click Me"); - button.Clicked += (s, e) => wasClicked = !wasClicked; - var win = new Window () { Width = Dim.Fill (), Height = Dim.Fill () }; - win.Add (button); - Application.Top.Add (win); - - var iterations = 0; - - Application.Iteration += () => { - iterations++; - - button.ProcessKey (new KeyEvent (Key.Enter, null)); - Assert.True (wasClicked); - button.MouseEvent (new MouseEvent () { Flags = MouseFlags.Button1Clicked }); - Assert.False (wasClicked); - Assert.True (button.Enabled); - Assert.True (button.CanFocus); - Assert.True (button.HasFocus); - Assert.True (win.Enabled); - Assert.True (win.CanFocus); - Assert.True (win.HasFocus); - - win.Enabled = false; - button.ProcessKey (new KeyEvent (Key.Enter, null)); - Assert.False (wasClicked); - button.MouseEvent (new MouseEvent () { Flags = MouseFlags.Button1Clicked }); - Assert.False (wasClicked); - Assert.False (button.Enabled); - Assert.True (button.CanFocus); - Assert.False (button.HasFocus); - Assert.False (win.Enabled); - Assert.True (win.CanFocus); - Assert.False (win.HasFocus); - button.SetFocus (); - Assert.False (button.HasFocus); - Assert.False (win.HasFocus); - win.SetFocus (); - Assert.False (button.HasFocus); - Assert.False (win.HasFocus); - - win.Enabled = true; - win.FocusFirst (); - Assert.True (button.HasFocus); - Assert.True (win.HasFocus); - - Application.RequestStop (); - }; - - Application.Run (); - - Assert.Equal (1, iterations); - } - - [Fact] - [AutoInitShutdown] - public void Visible_Sets_Also_Sets_Subviews () - { - var button = new Button ("Click Me"); - var win = new Window () { Width = Dim.Fill (), Height = Dim.Fill () }; - win.Add (button); - var top = Application.Top; - top.Add (win); - - var iterations = 0; - - Application.Iteration += () => { - iterations++; - - Assert.True (button.Visible); - Assert.True (button.CanFocus); - Assert.True (button.HasFocus); - Assert.True (win.Visible); - Assert.True (win.CanFocus); - Assert.True (win.HasFocus); - Assert.True (RunesCount () > 0); - - win.Visible = false; - Assert.True (button.Visible); - Assert.True (button.CanFocus); - Assert.False (button.HasFocus); - Assert.False (win.Visible); - Assert.True (win.CanFocus); - Assert.False (win.HasFocus); - button.SetFocus (); - Assert.False (button.HasFocus); - Assert.False (win.HasFocus); - win.SetFocus (); - Assert.False (button.HasFocus); - Assert.False (win.HasFocus); - top.Redraw (top.Bounds); - Assert.True (RunesCount () == 0); - - win.Visible = true; - win.FocusFirst (); - Assert.True (button.HasFocus); - Assert.True (win.HasFocus); - top.Redraw (top.Bounds); - Assert.True (RunesCount () > 0); - - Application.RequestStop (); - }; - - Application.Run (); - - Assert.Equal (1, iterations); - - int RunesCount () - { - var contents = ((FakeDriver)Application.Driver).Contents; - var runesCount = 0; - - for (int i = 0; i < Application.Driver.Rows; i++) { - for (int j = 0; j < Application.Driver.Cols; j++) { - if (contents [i, j, 0] != ' ') { - runesCount++; - } - } - } - return runesCount; - } - } - - [Fact] - [AutoInitShutdown] - public void GetTopSuperView_Test () - { - var v1 = new View (); - var fv1 = new FrameView (); - fv1.Add (v1); - var tf1 = new TextField (); - var w1 = new Window (); - w1.Add (fv1, tf1); - var top1 = new Toplevel (); - top1.Add (w1); - - var v2 = new View (); - var fv2 = new FrameView (); - fv2.Add (v2); - var tf2 = new TextField (); - var w2 = new Window (); - w2.Add (fv2, tf2); - var top2 = new Toplevel (); - top2.Add (w2); - - Assert.Equal (top1, v1.GetTopSuperView ()); - Assert.Equal (top2, v2.GetTopSuperView ()); - } - - [Fact] - [AutoInitShutdown] - public void CanFocus_Sets_To_False_Does_Not_Sets_HasFocus_To_True () - { - var view = new View () { CanFocus = true }; - var win = new Window () { Width = Dim.Fill (), Height = Dim.Fill () }; - win.Add (view); - Application.Top.Add (win); - Application.Begin (Application.Top); - - Assert.True (view.CanFocus); - Assert.True (view.HasFocus); - - view.CanFocus = false; - Assert.False (view.CanFocus); - Assert.False (view.HasFocus); - Assert.Null (Application.Current.Focused); - Assert.Null (Application.Current.MostFocused); - } - - [Fact] - [AutoInitShutdown] - public void CanFocus_Sets_To_False_On_Single_View_Focus_View_On_Another_Toplevel () - { - var view1 = new View () { Id = "view1", Width = 10, Height = 1, CanFocus = true }; - var win1 = new Window () { Id = "win1", Width = Dim.Percent (50), Height = Dim.Fill () }; - win1.Add (view1); - var view2 = new View () { Id = "view2", Width = 20, Height = 2, CanFocus = true }; - var win2 = new Window () { Id = "win2", X = Pos.Right (win1), Width = Dim.Fill (), Height = Dim.Fill () }; - win2.Add (view2); - Application.Top.Add (win1, win2); - Application.Begin (Application.Top); - - Assert.True (view1.CanFocus); - Assert.True (view1.HasFocus); - Assert.True (view2.CanFocus); - Assert.False (view2.HasFocus); - - view1.CanFocus = false; - Assert.False (view1.CanFocus); - Assert.False (view1.HasFocus); - Assert.Equal (win2, Application.Current.Focused); - Assert.Equal (view2, Application.Current.MostFocused); - } - - [Fact] - [AutoInitShutdown] - public void CanFocus_Sets_To_False_With_Two_Views_Focus_Another_View_On_The_Same_Toplevel () - { - var view1 = new View () { Id = "view1", Width = 10, Height = 1, CanFocus = true }; - var view12 = new View () { Id = "view12", Y = 5, Width = 10, Height = 1, CanFocus = true }; - var win1 = new Window () { Id = "win1", Width = Dim.Percent (50), Height = Dim.Fill () }; - win1.Add (view1, view12); - var view2 = new View () { Id = "view2", Width = 20, Height = 2, CanFocus = true }; - var win2 = new Window () { Id = "win2", X = Pos.Right (win1), Width = Dim.Fill (), Height = Dim.Fill () }; - win2.Add (view2); - Application.Top.Add (win1, win2); - Application.Begin (Application.Top); - - Assert.True (view1.CanFocus); - Assert.True (view1.HasFocus); - Assert.True (view2.CanFocus); - Assert.False (view2.HasFocus); - - view1.CanFocus = false; - Assert.False (view1.CanFocus); - Assert.False (view1.HasFocus); - Assert.Equal (win1, Application.Current.Focused); - Assert.Equal (view12, Application.Current.MostFocused); - } - - [Fact] - [AutoInitShutdown] - public void CanFocus_Sets_To_False_On_Toplevel_Focus_View_On_Another_Toplevel () - { - var view1 = new View () { Id = "view1", Width = 10, Height = 1, CanFocus = true }; - var win1 = new Window () { Id = "win1", Width = Dim.Percent (50), Height = Dim.Fill () }; - win1.Add (view1); - var view2 = new View () { Id = "view2", Width = 20, Height = 2, CanFocus = true }; - var win2 = new Window () { Id = "win2", X = Pos.Right (win1), Width = Dim.Fill (), Height = Dim.Fill () }; - win2.Add (view2); - Application.Top.Add (win1, win2); - Application.Begin (Application.Top); - - Assert.True (view1.CanFocus); - Assert.True (view1.HasFocus); - Assert.True (view2.CanFocus); - Assert.False (view2.HasFocus); - - win1.CanFocus = false; - Assert.False (view1.CanFocus); - Assert.False (view1.HasFocus); - Assert.False (win1.CanFocus); - Assert.False (win1.HasFocus); - Assert.Equal (win2, Application.Current.Focused); - Assert.Equal (view2, Application.Current.MostFocused); - } - - [Fact] - [AutoInitShutdown] - public void ProcessHotKey_Will_Invoke_ProcessKey_Only_For_The_MostFocused_With_Top_KeyPress_Event () - { - var sbQuiting = false; - var tfQuiting = false; - var topQuiting = false; - var sb = new StatusBar (new StatusItem [] { - new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => sbQuiting = true ) - }); - var tf = new TextField (); - tf.KeyPress += Tf_KeyPress; - - void Tf_KeyPress (object sender, KeyEventEventArgs obj) - { - if (obj.KeyEvent.Key == (Key.Q | Key.CtrlMask)) { - obj.Handled = tfQuiting = true; - } - } - - var win = new Window (); - win.Add (sb, tf); - var top = Application.Top; - top.KeyPress += Top_KeyPress; - - void Top_KeyPress (object sender, KeyEventEventArgs obj) - { - if (obj.KeyEvent.Key == (Key.Q | Key.CtrlMask)) { - obj.Handled = topQuiting = true; - } - } - - top.Add (win); - Application.Begin (top); - - Assert.False (sbQuiting); - Assert.False (tfQuiting); - Assert.False (topQuiting); - - Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true); - Assert.False (sbQuiting); - Assert.True (tfQuiting); - Assert.False (topQuiting); - - tf.KeyPress -= Tf_KeyPress; - tfQuiting = false; - Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true); - Application.MainLoop.MainIteration (); - Assert.True (sbQuiting); - Assert.False (tfQuiting); - Assert.False (topQuiting); - - sb.RemoveItem (0); - sbQuiting = false; - Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true); - Application.MainLoop.MainIteration (); - Assert.False (sbQuiting); - Assert.False (tfQuiting); - Assert.True (topQuiting); - } - - [Fact] - [AutoInitShutdown] - public void ProcessHotKey_Will_Invoke_ProcessKey_Only_For_The_MostFocused_Without_Top_KeyPress_Event () - { - var sbQuiting = false; - var tfQuiting = false; - var sb = new StatusBar (new StatusItem [] { - new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => sbQuiting = true ) - }); - var tf = new TextField (); - tf.KeyPress += Tf_KeyPress; - - void Tf_KeyPress (object sender, KeyEventEventArgs obj) - { - if (obj.KeyEvent.Key == (Key.Q | Key.CtrlMask)) { - obj.Handled = tfQuiting = true; - } - } - - var win = new Window (); - win.Add (sb, tf); - var top = Application.Top; - top.Add (win); - Application.Begin (top); - - Assert.False (sbQuiting); - Assert.False (tfQuiting); - - Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true); - Assert.False (sbQuiting); - Assert.True (tfQuiting); - - tf.KeyPress -= Tf_KeyPress; - tfQuiting = false; - Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true); - Application.MainLoop.MainIteration (); - Assert.True (sbQuiting); - Assert.False (tfQuiting); - } - - [Fact] - [AutoInitShutdown] - public void WindowDispose_CanFocusProblem () - { - // Arrange - Application.Init (); - using var top = Toplevel.Create (); - using var view = new View ( - x: 0, - y: 1, - text: nameof (WindowDispose_CanFocusProblem)); - using var window = new Window (); - top.Add (window); - window.Add (view); - - // Act - Application.Begin (top); - Application.Shutdown (); - - // Assert does Not throw NullReferenceException - top.SetFocus (); - } - - [Fact, AutoInitShutdown] - public void DrawFrame_With_Positive_Positions () - { - var view = new View (new Rect (0, 0, 8, 4)); - - view.DrawContent += (s, e) => view.DrawFrame (view.Bounds, 0, true); - - Assert.Equal (Point.Empty, new Point (view.Frame.X, view.Frame.Y)); - Assert.Equal (new Size (8, 4), new Size (view.Frame.Width, view.Frame.Height)); - - Application.Top.Add (view); - Application.Begin (Application.Top); - - var expected = @" -┌──────┐ -│ │ -│ │ -└──────┘ -"; - - var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (0, 0, 8, 4), pos); - } - - [Fact, AutoInitShutdown] - public void DrawFrame_With_Minimum_Size () - { - var view = new View (new Rect (0, 0, 2, 2)); - - view.DrawContent += (s, e) => view.DrawFrame (view.Bounds, 0, true); - - Assert.Equal (Point.Empty, new Point (view.Frame.X, view.Frame.Y)); - Assert.Equal (new Size (2, 2), new Size (view.Frame.Width, view.Frame.Height)); - - Application.Top.Add (view); - Application.Begin (Application.Top); - - var expected = @" -┌┐ -└┘ -"; - - var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (0, 0, 2, 2), pos); - } - - [Fact, AutoInitShutdown] - public void DrawFrame_With_Negative_Positions () - { - var view = new View (new Rect (-1, 0, 8, 4)); - - view.DrawContent += (s, e) => view.DrawFrame (view.Bounds, 0, true); - - Assert.Equal (new Point (-1, 0), new Point (view.Frame.X, view.Frame.Y)); - Assert.Equal (new Size (8, 4), new Size (view.Frame.Width, view.Frame.Height)); - - Application.Top.Add (view); - Application.Begin (Application.Top); - - var expected = @" -──────┐ - │ - │ -──────┘ -"; - - var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (0, 0, 7, 4), pos); - - view.Frame = new Rect (-1, -1, 8, 4); - Application.Refresh (); - - expected = @" - │ - │ -──────┘ -"; - - pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (6, 0, 7, 3), pos); - - view.Frame = new Rect (0, 0, 8, 4); - ((FakeDriver)Application.Driver).SetBufferSize (7, 4); - - expected = @" -┌────── -│ -│ -└────── -"; - - pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (0, 0, 7, 4), pos); - - view.Frame = new Rect (0, 0, 8, 4); - ((FakeDriver)Application.Driver).SetBufferSize (7, 3); - } - - [Fact, AutoInitShutdown] - public void DrawTextFormatter_Respects_The_Clip_Bounds () - { - // BUGBUG: v2 - scrollview is broken. Disabling test for now - return; - - var view = new View (new Rect (0, 0, 20, 20)); - view.Add (new Label ("0123456789abcdefghij")); - view.Add (new Label (0, 1, "1\n2\n3\n4\n5\n6\n7\n8\n9\n0")); - view.Add (new Button (1, 1, "Press me!")); - var scrollView = new ScrollView (new Rect (1, 1, 15, 10)) { - ContentSize = new Size (40, 40), - ShowHorizontalScrollIndicator = true, - ShowVerticalScrollIndicator = true - }; - scrollView.Add (view); - var win = new Window (new Rect (1, 1, 20, 14), "Test"); - win.Add (scrollView); - Application.Top.Add (win); - Application.Begin (Application.Top); - - var expected = @" - ┌┤Test├────────────┐ - │ │ - │ 0123456789abcd▲ │ - │ 1[ Press me! ]┬ │ - │ 2 │ │ - │ 3 ┴ │ - │ 4 ░ │ - │ 5 ░ │ - │ 6 ░ │ - │ 7 ░ │ - │ 8 ▼ │ - │ ◄├───┤░░░░░░░► │ - │ │ - └──────────────────┘ -"; - - var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (1, 1, 21, 14), pos); - - Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); - Application.Top.Redraw (Application.Top.Bounds); - - expected = @" - ┌┤Test├────────────┐ - │ │ - │ 123456789abcde▲ │ - │ [ Press me! ] ┬ │ - │ │ │ - │ ┴ │ - │ ░ │ - │ ░ │ - │ ░ │ - │ ░ │ - │ ▼ │ - │ ◄├───┤░░░░░░░► │ - │ │ - └──────────────────┘ -"; - - pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (1, 1, 21, 14), pos); - - Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); - Application.Top.Redraw (Application.Top.Bounds); - - expected = @" - ┌┤Test├────────────┐ - │ │ - │ 23456789abcdef▲ │ - │ Press me! ] ┬ │ - │ │ │ - │ ┴ │ - │ ░ │ - │ ░ │ - │ ░ │ - │ ░ │ - │ ▼ │ - │ ◄├────┤░░░░░░► │ - │ │ - └──────────────────┘ -"; - - pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (1, 1, 21, 14), pos); - - Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); - Application.Top.Redraw (Application.Top.Bounds); - - expected = @" - ┌┤Test├────────────┐ - │ │ - │ 3456789abcdefg▲ │ - │ Press me! ] ┬ │ - │ │ │ - │ ┴ │ - │ ░ │ - │ ░ │ - │ ░ │ - │ ░ │ - │ ▼ │ - │ ◄├────┤░░░░░░► │ - │ │ - └──────────────────┘ -"; - - pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (1, 1, 21, 14), pos); - - Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); - Application.Top.Redraw (Application.Top.Bounds); - - expected = @" - ┌┤Test├────────────┐ - │ │ - │ 456789abcdefgh▲ │ - │ ress me! ] ┬ │ - │ │ │ - │ ┴ │ - │ ░ │ - │ ░ │ - │ ░ │ - │ ░ │ - │ ▼ │ - │ ◄░├───┤░░░░░░► │ - │ │ - └──────────────────┘ -"; - - pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (1, 1, 21, 14), pos); - - Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); - Application.Top.Redraw (Application.Top.Bounds); - - expected = @" - ┌┤Test├────────────┐ - │ │ - │ 56789abcdefghi▲ │ - │ ess me! ] ┬ │ - │ │ │ - │ ┴ │ - │ ░ │ - │ ░ │ - │ ░ │ - │ ░ │ - │ ▼ │ - │ ◄░├────┤░░░░░► │ - │ │ - └──────────────────┘ -"; - - pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (1, 1, 21, 14), pos); - - Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); - Application.Top.Redraw (Application.Top.Bounds); - - expected = @" - ┌┤Test├────────────┐ - │ │ - │ 6789abcdefghij▲ │ - │ ss me! ] ┬ │ - │ │ │ - │ ┴ │ - │ ░ │ - │ ░ │ - │ ░ │ - │ ░ │ - │ ▼ │ - │ ◄░├────┤░░░░░► │ - │ │ - └──────────────────┘ -"; - - pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (1, 1, 21, 14), pos); - - Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); - Application.Top.Redraw (Application.Top.Bounds); - - expected = @" - ┌┤Test├────────────┐ - │ │ - │ 789abcdefghij ▲ │ - │ s me! ] ┬ │ - │ │ │ - │ ┴ │ - │ ░ │ - │ ░ │ - │ ░ │ - │ ░ │ - │ ▼ │ - │ ◄░░├───┤░░░░░► │ - │ │ - └──────────────────┘ -"; - - pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (1, 1, 21, 14), pos); - - Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Home, new KeyModifiers ()))); - Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ()))); - Application.Top.Redraw (Application.Top.Bounds); - - expected = @" - ┌┤Test├────────────┐ - │ │ - │ 1[ Press me! ]▲ │ - │ 2 ┬ │ - │ 3 │ │ - │ 4 ┴ │ - │ 5 ░ │ - │ 6 ░ │ - │ 7 ░ │ - │ 8 ░ │ - │ 9 ▼ │ - │ ◄├───┤░░░░░░░► │ - │ │ - └──────────────────┘ -"; - - pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (1, 1, 21, 14), pos); - - Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ()))); - Application.Top.Redraw (Application.Top.Bounds); - - expected = @" - ┌┤Test├────────────┐ - │ │ - │ 2 ▲ │ - │ 3 ┬ │ - │ 4 │ │ - │ 5 ┴ │ - │ 6 ░ │ - │ 7 ░ │ - │ 8 ░ │ - │ 9 ░ │ - │ 0 ▼ │ - │ ◄├───┤░░░░░░░► │ - │ │ - └──────────────────┘ -"; - - pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (1, 1, 21, 14), pos); - - Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ()))); - Application.Top.Redraw (Application.Top.Bounds); - - expected = @" - ┌┤Test├────────────┐ - │ │ - │ 3 ▲ │ - │ 4 ┬ │ - │ 5 │ │ - │ 6 ┴ │ - │ 7 ░ │ - │ 8 ░ │ - │ 9 ░ │ - │ 0 ░ │ - │ ▼ │ - │ ◄├───┤░░░░░░░► │ - │ │ - └──────────────────┘ -"; - - pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (1, 1, 21, 14), pos); - } - - [Fact, AutoInitShutdown] - public void Clear_Can_Use_Driver_AddRune_Or_AddStr_Methods () - { - var view = new View () { - Width = Dim.Fill (), - Height = Dim.Fill () - }; - view.DrawContent += (s, e) => { - view.DrawFrame (view.Bounds); - var savedClip = Application.Driver.Clip; - Application.Driver.Clip = new Rect (1, 1, view.Bounds.Width - 2, view.Bounds.Height - 2); - for (int row = 0; row < view.Bounds.Height - 2; row++) { - Application.Driver.Move (1, row + 1); - for (int col = 0; col < view.Bounds.Width - 2; col++) { - Application.Driver.AddStr ($"{col}"); - } - } - Application.Driver.Clip = savedClip; - }; - Application.Top.Add (view); - Application.Begin (Application.Top); - ((FakeDriver)Application.Driver).SetBufferSize (20, 10); - - var expected = @" -┌──────────────────┐ -│012345678910111213│ -│012345678910111213│ -│012345678910111213│ -│012345678910111213│ -│012345678910111213│ -│012345678910111213│ -│012345678910111213│ -│012345678910111213│ -└──────────────────┘ -"; - - var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (0, 0, 20, 10), pos); - - view.Clear (); - - expected = @" -"; - - pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (Rect.Empty, pos); - } - - [Fact, AutoInitShutdown] - public void Clear_Bounds_Can_Use_Driver_AddRune_Or_AddStr_Methods () - { - var view = new View () { - Width = Dim.Fill (), - Height = Dim.Fill () - }; - view.DrawContent += (s, e) => { - view.DrawFrame (view.Bounds); - var savedClip = Application.Driver.Clip; - Application.Driver.Clip = new Rect (1, 1, view.Bounds.Width - 2, view.Bounds.Height - 2); - for (int row = 0; row < view.Bounds.Height - 2; row++) { - Application.Driver.Move (1, row + 1); - for (int col = 0; col < view.Bounds.Width - 2; col++) { - Application.Driver.AddStr ($"{col}"); - } - } - Application.Driver.Clip = savedClip; - }; - Application.Top.Add (view); - Application.Begin (Application.Top); - ((FakeDriver)Application.Driver).SetBufferSize (20, 10); - - var expected = @" -┌──────────────────┐ -│012345678910111213│ -│012345678910111213│ -│012345678910111213│ -│012345678910111213│ -│012345678910111213│ -│012345678910111213│ -│012345678910111213│ -│012345678910111213│ -└──────────────────┘ -"; - - var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (0, 0, 20, 10), pos); - - view.Clear (view.Bounds); - - expected = @" -"; - - pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (Rect.Empty, pos); - } - - [Fact, AutoInitShutdown] - public void GetTextFormatterBoundsSize_GetSizeNeededForText_HotKeySpecifier () - { - var text = "Say Hello 你"; - var horizontalView = new View () { - Text = text, - AutoSize = true, - HotKeySpecifier = '_' }; - - var verticalView = new View () { - Text = text, - AutoSize = true, - HotKeySpecifier = '_', - TextDirection = TextDirection.TopBottom_LeftRight - }; - Application.Top.Add (horizontalView, verticalView); - Application.Begin (Application.Top); - ((FakeDriver)Application.Driver).SetBufferSize (50, 50); - - Assert.True (horizontalView.AutoSize); - Assert.Equal (new Rect (0, 0, 12, 1), horizontalView.Frame); - Assert.Equal (new Size (12, 1), horizontalView.GetSizeNeededForTextWithoutHotKey ()); - Assert.Equal (new Size (12, 1), horizontalView.GetSizeNeededForTextAndHotKey ()); - Assert.Equal (horizontalView.TextFormatter.Size, horizontalView.GetSizeNeededForTextAndHotKey ()); - Assert.Equal (horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ()); - - Assert.True (verticalView.AutoSize); - // BUGBUG: v2 - Autosize is broken; disabling this test - //Assert.Equal (new Rect (0, 0, 2, 11), verticalView.Frame); - //Assert.Equal (new Size (2, 11), verticalView.GetSizeNeededForTextWithoutHotKey ()); - //Assert.Equal (new Size (2, 11), verticalView.GetSizeNeededForTextAndHotKey ()); - Assert.Equal (verticalView.TextFormatter.Size, verticalView.GetSizeNeededForTextAndHotKey ()); - Assert.Equal (verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ()); - - text = "Say He_llo 你"; - horizontalView.Text = text; - verticalView.Text = text; - - Assert.True (horizontalView.AutoSize); - Assert.Equal (new Rect (0, 0, 12, 1), horizontalView.Frame); - Assert.Equal (new Size (12, 1), horizontalView.GetSizeNeededForTextWithoutHotKey ()); - Assert.Equal (new Size (13, 1), horizontalView.GetSizeNeededForTextAndHotKey ()); - Assert.Equal (horizontalView.TextFormatter.Size, horizontalView.GetSizeNeededForTextAndHotKey ()); - Assert.Equal (horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ()); - - Assert.True (verticalView.AutoSize); - // BUGBUG: v2 - Autosize is broken; disabling this test - //Assert.Equal (new Rect (0, 0, 2, 11), verticalView.Frame); - //Assert.Equal (new Size (2, 11), verticalView.GetSizeNeededForTextWithoutHotKey ()); - //Assert.Equal (new Size (2, 12), verticalView.GetSizeNeededForTextAndHotKey ()); - //Assert.Equal (verticalView.TextFormatter.Size, verticalView.GetSizeNeededForTextAndHotKey ()); - //Assert.Equal (verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ()); - } - - [Fact] - public void IsAdded_Added_Removed () - { - var top = new Toplevel (); - var view = new View (); - Assert.False (view.IsAdded); - top.Add (view); - Assert.True (view.IsAdded); - top.Remove (view); - Assert.False (view.IsAdded); - } - - [Fact, AutoInitShutdown] - public void Visible_Clear_The_View_Output () - { - var label = new Label ("Testing visibility."); - var win = new Window (); - win.Add (label); - var top = Application.Top; - top.Add (win); - Application.Begin (top); - - Assert.True (label.Visible); - ((FakeDriver)Application.Driver).SetBufferSize (30, 5); - TestHelpers.AssertDriverContentsWithFrameAre (@" -┌────────────────────────────┐ -│Testing visibility. │ -│ │ -│ │ -└────────────────────────────┘ -", output); - - label.Visible = false; - TestHelpers.AssertDriverContentsWithFrameAre (@" -┌────────────────────────────┐ -│ │ -│ │ -│ │ -└────────────────────────────┘ -", output); - } - - [Fact, AutoInitShutdown] - public void ClearOnVisibleFalse_Gets_Sets () - { - // BUGBUG: v2 - scrollview is broken. Disabling test for now - return; - - var text = "This is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test"; - var label = new Label (text); - Application.Top.Add (label); - - var sbv = new ScrollBarView (label, true, false) { - Size = 100, - ClearOnVisibleFalse = false - }; - Application.Begin (Application.Top); - - Assert.True (sbv.Visible); - TestHelpers.AssertDriverContentsWithFrameAre (@" -This is a tes▲ -This is a tes┬ -This is a tes┴ -This is a tes░ -This is a tes░ -This is a tes▼ -", output); - - sbv.Visible = false; - Assert.False (sbv.Visible); - Application.Top.Redraw (Application.Top.Bounds); - TestHelpers.AssertDriverContentsWithFrameAre (@" -This is a test -This is a test -This is a test -This is a test -This is a test -This is a test -", output); - - sbv.Visible = true; - Assert.True (sbv.Visible); - Application.Top.Redraw (Application.Top.Bounds); - TestHelpers.AssertDriverContentsWithFrameAre (@" -This is a tes▲ -This is a tes┬ -This is a tes┴ -This is a tes░ -This is a tes░ -This is a tes▼ -", output); - - sbv.ClearOnVisibleFalse = true; - sbv.Visible = false; - Assert.False (sbv.Visible); - TestHelpers.AssertDriverContentsWithFrameAre (@" -This is a tes -This is a tes -This is a tes -This is a tes -This is a tes -This is a tes -", output); - } - - [Fact, AutoInitShutdown] - public void DrawContentComplete_Event_Is_Always_Called () - { - var viewCalled = false; - var tvCalled = false; - - var view = new View ("View") { Width = 10, Height = 10 }; - view.DrawContentComplete += (s, e) => viewCalled = true; - var tv = new TextView () { Y = 11, Width = 10, Height = 10 }; - tv.DrawContentComplete += (s, e) => tvCalled = true; - - Application.Top.Add (view, tv); - Application.Begin (Application.Top); - - Assert.True (viewCalled); - Assert.True (tvCalled); - } - - [Fact, AutoInitShutdown] - public void KeyDown_And_KeyUp_Events_Must_Called_Before_OnKeyDown_And_OnKeyUp () - { - var keyDown = false; - var keyPress = false; - var keyUp = false; - - var view = new DerivedView (); - view.KeyDown += (s, e) => { - Assert.Equal (Key.a, e.KeyEvent.Key); - Assert.False (keyDown); - Assert.False (view.IsKeyDown); - e.Handled = true; - keyDown = true; - }; - view.KeyPress += (s, e) => { - Assert.Equal (Key.a, e.KeyEvent.Key); - Assert.False (keyPress); - Assert.False (view.IsKeyPress); - e.Handled = true; - keyPress = true; - }; - view.KeyUp += (s, e) => { - Assert.Equal (Key.a, e.KeyEvent.Key); - Assert.False (keyUp); - Assert.False (view.IsKeyUp); - e.Handled = true; - keyUp = true; - }; - - Application.Top.Add (view); - - Console.MockKeyPresses.Push (new ConsoleKeyInfo ('a', ConsoleKey.A, false, false, false)); - - Application.Iteration += () => Application.RequestStop (); - - Assert.True (view.CanFocus); - - Application.Run (); - Application.Shutdown (); - - Assert.True (keyDown); - Assert.True (keyPress); - Assert.True (keyUp); - Assert.False (view.IsKeyDown); - Assert.False (view.IsKeyPress); - Assert.False (view.IsKeyUp); - } - - public class DerivedView : View { - public DerivedView () - { - CanFocus = true; - } - - public bool IsKeyDown { get; set; } - public bool IsKeyPress { get; set; } - public bool IsKeyUp { get; set; } - public override ustring Text { get; set; } - - public override bool OnKeyDown (KeyEvent keyEvent) - { - IsKeyDown = true; - return true; - } - - public override bool ProcessKey (KeyEvent keyEvent) - { - IsKeyPress = true; - return true; - } - - public override bool OnKeyUp (KeyEvent keyEvent) - { - IsKeyUp = true; - return true; - } - - public override void Redraw (Rect bounds) - { - var idx = 0; - // BUGBUG: v2 - this should use Boudns, not Frame - for (int r = 0; r < Frame.Height; r++) { - for (int c = 0; c < Frame.Width; c++) { - if (idx < Text.Length) { - var rune = Text [idx]; - if (rune != '\n') { - AddRune (c, r, Text [idx]); - } - idx++; - if (rune == '\n') { - break; - } - } - } - } - ClearLayoutNeeded (); - ClearNeedsDisplay (); - } - } - - [Theory, AutoInitShutdown] - [InlineData (true, false, false)] - [InlineData (true, true, false)] - [InlineData (true, true, true)] - public void KeyDown_And_KeyUp_Events_With_Only_Key_Modifiers (bool shift, bool alt, bool control) - { - var keyDown = false; - var keyPress = false; - var keyUp = false; - - var view = new DerivedView (); - view.KeyDown += (s, e) => { - Assert.Equal (-1, e.KeyEvent.KeyValue); - Assert.Equal (shift, e.KeyEvent.IsShift); - Assert.Equal (alt, e.KeyEvent.IsAlt); - Assert.Equal (control, e.KeyEvent.IsCtrl); - Assert.False (keyDown); - Assert.False (view.IsKeyDown); - keyDown = true; - }; - view.KeyPress += (s, e) => { - keyPress = true; - }; - view.KeyUp += (s, e) => { - Assert.Equal (-1, e.KeyEvent.KeyValue); - Assert.Equal (shift, e.KeyEvent.IsShift); - Assert.Equal (alt, e.KeyEvent.IsAlt); - Assert.Equal (control, e.KeyEvent.IsCtrl); - Assert.False (keyUp); - Assert.False (view.IsKeyUp); - keyUp = true; - }; - - Application.Top.Add (view); - - Console.MockKeyPresses.Push (new ConsoleKeyInfo ('\0', (ConsoleKey)'\0', shift, alt, control)); - - Application.Iteration += () => Application.RequestStop (); - - Assert.True (view.CanFocus); - - Application.Run (); - Application.Shutdown (); - - Assert.True (keyDown); - Assert.False (keyPress); - Assert.True (keyUp); - Assert.True (view.IsKeyDown); - Assert.False (view.IsKeyPress); - Assert.True (view.IsKeyUp); - } - - [Fact, AutoInitShutdown] - public void SetHasFocus_Do_Not_Throws_If_OnLeave_Remove_Focused_Changing_To_Null () - { - var view1Leave = false; - var subView1Leave = false; - var subView1subView1Leave = false; - var top = Application.Top; - var view1 = new View { CanFocus = true }; - var subView1 = new View { CanFocus = true }; - var subView1subView1 = new View { CanFocus = true }; - view1.Leave += (s, e) => { - view1Leave = true; - }; - subView1.Leave += (s, e) => { - subView1.Remove (subView1subView1); - subView1Leave = true; - }; - view1.Add (subView1); - subView1subView1.Leave += (s, e) => { - // This is never invoked - subView1subView1Leave = true; - }; - subView1.Add (subView1subView1); - var view2 = new View { CanFocus = true }; - top.Add (view1, view2); - Application.Begin (top); - - view2.SetFocus (); - Assert.True (view1Leave); - Assert.True (subView1Leave); - Assert.False (subView1subView1Leave); - } - - [Fact, AutoInitShutdown] - public void GetNormalColor_ColorScheme () - { - var view = new View { ColorScheme = Colors.Base }; - - Assert.Equal (view.ColorScheme.Normal, view.GetNormalColor ()); - - view.Enabled = false; - Assert.Equal (view.ColorScheme.Disabled, view.GetNormalColor ()); - } - - [Fact, AutoInitShutdown] - public void GetHotNormalColor_ColorScheme () - { - var view = new View { ColorScheme = Colors.Base }; - - Assert.Equal (view.ColorScheme.HotNormal, view.GetHotNormalColor ()); - - view.Enabled = false; - Assert.Equal (view.ColorScheme.Disabled, view.GetHotNormalColor ()); - } - - [Theory, AutoInitShutdown] - [InlineData (true)] - [InlineData (false)] - public void Clear_Does_Not_Spillover_Its_Parent (bool label) - { - var root = new View () { Width = 20, Height = 10, ColorScheme = Colors.Base }; - - var v = label == true ? - new Label (new string ('c', 100)) { - Width = Dim.Fill (), - } : - (View)new TextView () { - Height = 1, - Text = new string ('c', 100), - Width = Dim.Fill () - }; - - root.Add (v); - - Application.Top.Add (root); - Application.Begin (Application.Top); - - if (label) { - Assert.True (v.AutoSize); - Assert.False (v.CanFocus); - Assert.Equal (new Rect (0, 0, 100, 1), v.Frame); - } else { - Assert.False (v.AutoSize); - Assert.True (v.CanFocus); - Assert.Equal (new Rect (0, 0, 20, 1), v.Frame); - } - - TestHelpers.AssertDriverContentsWithFrameAre (@" -cccccccccccccccccccc", output); - - var attributes = new Attribute [] { - Colors.TopLevel.Normal, - Colors.Base.Normal, - Colors.Base.Focus - }; - if (label) { - TestHelpers.AssertDriverColorsAre (@" -111111111111111111110 -111111111111111111110", attributes); - } else { - TestHelpers.AssertDriverColorsAre (@" -222222222222222222220 -111111111111111111110", attributes); - } - - if (label) { - root.CanFocus = true; - v.CanFocus = true; - Assert.False (v.HasFocus); - v.SetFocus (); - Assert.True (v.HasFocus); - Application.Refresh (); - TestHelpers.AssertDriverColorsAre (@" -222222222222222222220 -111111111111111111110", attributes); - } - } - - [Fact, AutoInitShutdown] - public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Up_Left_Using_Frame () - { - var label = new Label ("At 0,0"); - var view = new DerivedView () { - X = 2, - Y = 2, - Width = 30, - Height = 2, - Text = "A text with some long width\n and also with two lines." - }; - var top = Application.Top; - top.Add (label, view); - Application.Begin (top); - - top.Redraw (top.Bounds); - TestHelpers.AssertDriverContentsWithFrameAre (@" -At 0,0 - - A text with some long width - and also with two lines. ", output); - - view.Frame = new Rect (1, 1, 10, 1); - Assert.Equal (new Rect (1, 1, 10, 1), view.Frame); - Assert.Equal (LayoutStyle.Computed, view.LayoutStyle); - view.LayoutStyle = LayoutStyle.Absolute; - Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); - Assert.Equal (new Rect (0, 0, 10, 1), view._needsDisplay); - top.Redraw (top.Bounds); - TestHelpers.AssertDriverContentsWithFrameAre (@" -At 0,0 - A text wit", output); - } - - [Fact, AutoInitShutdown] - public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Up_Left_Using_Pos_Dim () - { - var label = new Label ("At 0,0"); - var view = new DerivedView () { - X = 2, - Y = 2, - Width = 30, - Height = 2, - Text = "A text with some long width\n and also with two lines." - }; - var top = Application.Top; - top.Add (label, view); - Application.Begin (top); - - top.Redraw (top.Bounds); - TestHelpers.AssertDriverContentsWithFrameAre (@" -At 0,0 - - A text with some long width - and also with two lines. ", output); - - view.X = 1; - view.Y = 1; - view.Width = 10; - view.Height = 1; - Assert.Equal (new Rect (1, 1, 10, 1), view.Frame); - Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); - Assert.Equal (new Rect (0, 0, 30, 2), view._needsDisplay); - top.Redraw (top.Bounds); - TestHelpers.AssertDriverContentsWithFrameAre (@" -At 0,0 - A text wit", output); - } - - [Fact, AutoInitShutdown] - public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Up_Left_Using_Frame () - { - var label = new Label ("At 0,0"); - var view = new DerivedView () { - X = 2, - Y = 2, - Width = 30, - Height = 2, - Text = "A text with some long width\n and also with two lines." - }; - var top = Application.Top; - top.Add (label, view); - Application.Begin (top); - - view.Redraw (view.Bounds); - TestHelpers.AssertDriverContentsWithFrameAre (@" -At 0,0 - - A text with some long width - and also with two lines. ", output); - - view.Frame = new Rect (1, 1, 10, 1); - Assert.Equal (new Rect (1, 1, 10, 1), view.Frame); - Assert.Equal (LayoutStyle.Computed, view.LayoutStyle); - view.LayoutStyle = LayoutStyle.Absolute; - Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); - Assert.Equal (new Rect (0, 0, 10, 1), view._needsDisplay); - view.Redraw (view.Bounds); - TestHelpers.AssertDriverContentsWithFrameAre (@" -At 0,0 - A text wit - A text with some long width - and also with two lines. ", output); - } - - [Fact, AutoInitShutdown] - public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Up_Left_Using_Pos_Dim () - { - var label = new Label ("At 0,0"); - var view = new DerivedView () { - X = 2, - Y = 2, - Width = 30, - Height = 2, - Text = "A text with some long width\n and also with two lines." - }; - var top = Application.Top; - top.Add (label, view); - Application.Begin (top); - - view.Redraw (view.Bounds); - TestHelpers.AssertDriverContentsWithFrameAre (@" -At 0,0 - - A text with some long width - and also with two lines. ", output); - - view.X = 1; - view.Y = 1; - view.Width = 10; - view.Height = 1; - Assert.Equal (new Rect (1, 1, 10, 1), view.Frame); - Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); - Assert.Equal (new Rect (0, 0, 30, 2), view._needsDisplay); - view.Redraw (view.Bounds); - TestHelpers.AssertDriverContentsWithFrameAre (@" -At 0,0 - A text wit - A text with some long width - and also with two lines. ", output); - } - - [Fact, AutoInitShutdown] - public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Down_Right_Using_Frame () - { - var label = new Label ("At 0,0"); - var view = new DerivedView () { - X = 2, - Y = 2, - Width = 30, - Height = 2, - Text = "A text with some long width\n and also with two lines." - }; - var top = Application.Top; - top.Add (label, view); - Application.Begin (top); - - TestHelpers.AssertDriverContentsWithFrameAre (@" -At 0,0 - - A text with some long width - and also with two lines. ", output); - - view.Frame = new Rect (3, 3, 10, 1); - Assert.Equal (new Rect (3, 3, 10, 1), view.Frame); - Assert.Equal (LayoutStyle.Computed, view.LayoutStyle); - view.LayoutStyle = LayoutStyle.Absolute; - Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); - Assert.Equal (new Rect (0, 0, 10, 1), view._needsDisplay); - top.Redraw (top.Bounds); - TestHelpers.AssertDriverContentsWithFrameAre (@" -At 0,0 - - - A text wit", output); - } - - [Fact, AutoInitShutdown] - public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Down_Right_Using_Pos_Dim () - { - var label = new Label ("At 0,0"); - var view = new DerivedView () { - X = 2, - Y = 2, - Width = 30, - Height = 2, - Text = "A text with some long width\n and also with two lines." - }; - var top = Application.Top; - top.Add (label, view); - Application.Begin (top); - - top.Redraw (top.Bounds); - TestHelpers.AssertDriverContentsWithFrameAre (@" -At 0,0 - - A text with some long width - and also with two lines. ", output); - - view.X = 3; - view.Y = 3; - view.Width = 10; - view.Height = 1; - Assert.Equal (new Rect (3, 3, 10, 1), view.Frame); - Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); - Assert.Equal (new Rect (0, 0, 30, 2), view._needsDisplay); - top.Redraw (top.Bounds); - TestHelpers.AssertDriverContentsWithFrameAre (@" -At 0,0 - - - A text wit", output); - } - - [Fact, AutoInitShutdown] - public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Down_Right_Using_Frame () - { - var label = new Label ("At 0,0"); - var view = new DerivedView () { - X = 2, - Y = 2, - Width = 30, - Height = 2, - Text = "A text with some long width\n and also with two lines." - }; - var top = Application.Top; - top.Add (label, view); - Application.Begin (top); - - view.Redraw (view.Bounds); - TestHelpers.AssertDriverContentsWithFrameAre (@" -At 0,0 - - A text with some long width - and also with two lines. ", output); - - view.Frame = new Rect (3, 3, 10, 1); - Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); - Assert.Equal (new Rect (0, 0, 10, 1), view._needsDisplay); - view.Redraw (view.Bounds); - TestHelpers.AssertDriverContentsWithFrameAre (@" -At 0,0 - - A text with some long width - A text witith two lines. ", output); - } - - [Fact, AutoInitShutdown] - public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Down_Right_Using_Pos_Dim () - { - var label = new Label ("At 0,0"); - var view = new DerivedView () { - X = 2, - Y = 2, - Width = 30, - Height = 2, - Text = "A text with some long width\n and also with two lines." - }; - var top = Application.Top; - top.Add (label, view); - Application.Begin (top); - - view.Redraw (view.Bounds); - TestHelpers.AssertDriverContentsWithFrameAre (@" -At 0,0 - - A text with some long width - and also with two lines. ", output); - - view.X = 3; - view.Y = 3; - view.Width = 10; - view.Height = 1; - Assert.Equal (new Rect (3, 3, 10, 1), view.Frame); - Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); - Assert.Equal (new Rect (0, 0, 30, 2), view._needsDisplay); - view.Redraw (view.Bounds); - TestHelpers.AssertDriverContentsWithFrameAre (@" -At 0,0 - - A text with some long width - A text witith two lines. ", output); - } - - [Fact, AutoInitShutdown] - public void Test_Nested_Views_With_Height_Equal_To_One () - { - var v = new View () { Width = 11, Height = 3, ColorScheme = new ColorScheme () }; - - var top = new View () { Width = Dim.Fill (), Height = 1 }; - var bottom = new View () { Width = Dim.Fill (), Height = 1, Y = 2 }; - - top.Add (new Label ("111")); - v.Add (top); - v.Add (new LineView (Orientation.Horizontal) { Y = 1 }); - bottom.Add (new Label ("222")); - v.Add (bottom); - - v.LayoutSubviews (); - v.Redraw (v.Bounds); - - - string looksLike = -@" -111 -─────────── -222"; - TestHelpers.AssertDriverContentsAre (looksLike, output); - } - - [Fact] - [AutoInitShutdown] - public void Frame_Set_After_Initialze_Update_NeededDisplay () - { - var frame = new FrameView (); - - var label = new Label ("This should be the first line.") { - TextAlignment = Terminal.Gui.TextAlignment.Centered, - ColorScheme = Colors.Menu, - Width = Dim.Fill (), - X = Pos.Center (), - Y = Pos.Center () - 2 // center minus 2 minus two lines top and bottom borders equal to zero (4-2-2=0) - }; - - var button = new Button ("Press me!") { - X = Pos.Center (), - Y = Pos.Center () - }; - - frame.Add (label, button); - - frame.X = Pos.Center (); - frame.Y = Pos.Center (); - frame.Width = 40; - frame.Height = 8; - - var top = Application.Top; - - top.Add (frame); - - // BUGBUG: v2 - these tests are bogus because Layout hasn't happened yet - //Assert.Equal (new Rect (0, 0, 80, 25), top.Frame); - //Assert.Equal (new Rect (0, 0, 40, 8), frame.Frame); - //Assert.Equal (new Rect (0, 0, 40, 8), new Rect ( - // frame.Frame.Left, frame.Frame.Top, - // frame.Frame.Right, frame.Frame.Bottom)); - //Assert.Equal (new Rect (0, 0, 30, 1), label.Frame); - //Assert.Equal (new Rect (0, 0, 13, 1), button.Frame); - - //Assert.Equal (new Rect (0, 0, 80, 25), top._needsDisplay); - //Assert.Equal (new Rect (0, 0, 40, 8), frame._needsDisplay); - //Assert.Equal (new Rect (0, 0, 40, 8), new Rect ( - // frame._needsDisplay.Left, frame._needsDisplay.Top, - // frame._needsDisplay.Right, frame._needsDisplay.Bottom)); - //Assert.Equal (new Rect (0, 0, 30, 1), label._needsDisplay); - //Assert.Equal (new Rect (0, 0, 13, 1), button._needsDisplay); - - //top.LayoutComplete += (s, e) => { - // Assert.Equal (new Rect (0, 0, 80, 25), top._needsDisplay); - //}; - - //frame.LayoutComplete += (s, e) => { - // Assert.Equal (new Rect (0, 0, 40, 8), frame._needsDisplay); - //}; - - //label.LayoutComplete += (s, e) => { - // Assert.Equal (new Rect (0, 0, 38, 1), label._needsDisplay); - //}; - - //button.LayoutComplete += (s, e) => { - // Assert.Equal (new Rect (0, 0, 13, 1), button._needsDisplay); - //}; - - Application.Begin (top); - - Assert.True (label.AutoSize); - Assert.Equal (new Rect (0, 0, 80, 25), top.Frame); - Assert.Equal (new Rect (20, 8, 40, 8), frame.Frame); - Assert.Equal (new Rect (20, 8, 60, 16), new Rect ( - frame.Frame.Left, frame.Frame.Top, - frame.Frame.Right, frame.Frame.Bottom)); - Assert.Equal (new Rect (0, 0, 38, 1), label.Frame); - Assert.Equal (new Rect (12, 2, 13, 1), button.Frame); - var expected = @" - ┌──────────────────────────────────────┐ - │ This should be the first line. │ - │ │ - │ [ Press me! ] │ - │ │ - │ │ - │ │ - └──────────────────────────────────────┘ -"; - - TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - } - - [Fact, AutoInitShutdown] - public void Remove_Does_Not_Change_Focus () - { - Assert.True (Application.Top.CanFocus); - Assert.False (Application.Top.HasFocus); - - var container = new View () { Width = 10, Height = 10 }; - var leave = false; - container.Leave += (s, e) => leave = true; - Assert.False (container.CanFocus); - var child = new View () { Width = Dim.Fill (), Height = Dim.Fill (), CanFocus = true }; - container.Add (child); - - Assert.True (container.CanFocus); - Assert.False (container.HasFocus); - Assert.True (child.CanFocus); - Assert.False (child.HasFocus); - - Application.Top.Add (container); - Application.Begin (Application.Top); - - Assert.True (Application.Top.CanFocus); - Assert.True (Application.Top.HasFocus); - Assert.True (container.CanFocus); - Assert.True (container.HasFocus); - Assert.True (child.CanFocus); - Assert.True (child.HasFocus); - - container.Remove (child); - child.Dispose (); - child = null; - Assert.True (Application.Top.HasFocus); - Assert.True (container.CanFocus); - Assert.True (container.HasFocus); - Assert.Null (child); - Assert.False (leave); - } - - [Fact, AutoInitShutdown] - public void SetFocus_View_With_Null_Superview_Does_Not_Throw_Exception () - { - Assert.True (Application.Top.CanFocus); - Assert.False (Application.Top.HasFocus); - - var exception = Record.Exception (Application.Top.SetFocus); - Assert.Null (exception); - Assert.True (Application.Top.CanFocus); - Assert.True (Application.Top.HasFocus); - } - - [Fact, AutoInitShutdown] - public void FocusNext_Does_Not_Throws_If_A_View_Was_Removed_From_The_Collection () - { - var top1 = Application.Top; - var view1 = new View () { Id = "view1", Width = 10, Height = 5, CanFocus = true }; - var top2 = new Toplevel () { Id = "top2", Y = 1, Width = 10, Height = 5 }; - var view2 = new View () { Id = "view2", Y = 1, Width = 10, Height = 5, CanFocus = true }; - View view3 = null; - var removed = false; - view2.Enter += (s, e) => { - if (!removed) { - removed = true; - view3 = new View () { Id = "view3", Y = 1, Width = 10, Height = 5 }; - Application.Current.Add (view3); - Application.Current.BringSubviewToFront (view3); - Assert.False (view3.HasFocus); - } - }; - view2.Leave += (s, e) => { - Application.Current.Remove (view3); - view3.Dispose (); - view3 = null; - }; - top2.Add (view2); - top1.Add (view1, top2); - Application.Begin (top1); - - Assert.True (top1.HasFocus); - Assert.True (view1.HasFocus); - Assert.False (view2.HasFocus); - Assert.False (removed); - Assert.Null (view3); - - Assert.True (top1.ProcessKey (new KeyEvent (Key.Tab | Key.CtrlMask, new KeyModifiers { Ctrl = true }))); - Assert.True (top1.HasFocus); - Assert.False (view1.HasFocus); - Assert.True (view2.HasFocus); - Assert.True (removed); - Assert.NotNull (view3); - - var exception = Record.Exception (() => top1.ProcessKey (new KeyEvent (Key.Tab | Key.CtrlMask, new KeyModifiers { Ctrl = true }))); - Assert.Null (exception); - Assert.True (removed); - Assert.Null (view3); - } - } -} diff --git a/UnitTests/TopLevels/DialogTests.cs b/UnitTests/Dialogs/DialogTests.cs similarity index 99% rename from UnitTests/TopLevels/DialogTests.cs rename to UnitTests/Dialogs/DialogTests.cs index 25d9b15e5..73dc3f546 100644 --- a/UnitTests/TopLevels/DialogTests.cs +++ b/UnitTests/Dialogs/DialogTests.cs @@ -10,7 +10,7 @@ using Xunit.Abstractions; using NStack; using static Terminal.Gui.Application; -namespace Terminal.Gui.TopLevelTests { +namespace Terminal.Gui.DialogTests { public class DialogTests { readonly ITestOutputHelper output; diff --git a/UnitTests/TopLevels/MessageBoxTests.cs b/UnitTests/Dialogs/MessageBoxTests.cs similarity index 99% rename from UnitTests/TopLevels/MessageBoxTests.cs rename to UnitTests/Dialogs/MessageBoxTests.cs index 8f43fe835..22ad82fdb 100644 --- a/UnitTests/TopLevels/MessageBoxTests.cs +++ b/UnitTests/Dialogs/MessageBoxTests.cs @@ -4,7 +4,7 @@ using Xunit.Abstractions; using System.Text; using Terminal.Gui; -namespace Terminal.Gui.TopLevelTests { +namespace Terminal.Gui.DialogTests { public class MessageBoxTests { readonly ITestOutputHelper output; diff --git a/UnitTests/TopLevels/WizardTests.cs b/UnitTests/Dialogs/WizardTests.cs similarity index 99% rename from UnitTests/TopLevels/WizardTests.cs rename to UnitTests/Dialogs/WizardTests.cs index 1d33b1b09..e9e052efd 100644 --- a/UnitTests/TopLevels/WizardTests.cs +++ b/UnitTests/Dialogs/WizardTests.cs @@ -10,7 +10,7 @@ using Xunit.Abstractions; using NStack; using static Terminal.Gui.Application; -namespace Terminal.Gui.TopLevelTests { +namespace Terminal.Gui.DialogTests { public class WizardTests { readonly ITestOutputHelper output; diff --git a/UnitTests/Core/LineCanvasTests.cs b/UnitTests/Drawing/LineCanvasTests.cs similarity index 99% rename from UnitTests/Core/LineCanvasTests.cs rename to UnitTests/Drawing/LineCanvasTests.cs index 68df17452..5b5500766 100644 --- a/UnitTests/Core/LineCanvasTests.cs +++ b/UnitTests/Drawing/LineCanvasTests.cs @@ -1,11 +1,10 @@ using System; using System.Collections.Generic; using System.Text; -using Terminal.Gui.Graphs; using Xunit; using Xunit.Abstractions; -namespace Terminal.Gui.CoreTests { +namespace Terminal.Gui.DrawingTests { public class LineCanvasTests { readonly ITestOutputHelper output; diff --git a/UnitTests/Drawing/RulerTests.cs b/UnitTests/Drawing/RulerTests.cs index 0458daa5e..9c7f9d5f3 100644 --- a/UnitTests/Drawing/RulerTests.cs +++ b/UnitTests/Drawing/RulerTests.cs @@ -3,7 +3,6 @@ using NStack; using System; using System.Collections.Generic; using System.Xml.Linq; -using Terminal.Gui.Graphs; using Xunit; using Xunit.Abstractions; //using GraphViewTests = Terminal.Gui.Views.GraphViewTests; diff --git a/UnitTests/Core/ThicknessTests.cs b/UnitTests/Drawing/ThicknessTests.cs similarity index 99% rename from UnitTests/Core/ThicknessTests.cs rename to UnitTests/Drawing/ThicknessTests.cs index a7398f33d..459515052 100644 --- a/UnitTests/Core/ThicknessTests.cs +++ b/UnitTests/Drawing/ThicknessTests.cs @@ -3,7 +3,6 @@ using NStack; using System; using System.Collections.Generic; using System.Xml.Linq; -using Terminal.Gui.Graphs; using Xunit; using Xunit.Abstractions; //using GraphViewTests = Terminal.Gui.Views.GraphViewTests; @@ -11,7 +10,7 @@ using Xunit.Abstractions; // Alias Console to MockConsole so we don't accidentally use Console using Console = Terminal.Gui.FakeConsole; -namespace Terminal.Gui.CoreTests { +namespace Terminal.Gui.DrawingTests { public class ThicknessTests { readonly ITestOutputHelper output; diff --git a/UnitTests/Drivers/ConsoleDriverTests.cs b/UnitTests/Drivers/ConsoleDriverTests.cs deleted file mode 100644 index bb9d07207..000000000 --- a/UnitTests/Drivers/ConsoleDriverTests.cs +++ /dev/null @@ -1,673 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using Xunit; -using Xunit.Abstractions; - -// Alias Console to MockConsole so we don't accidentally use Console -using Console = Terminal.Gui.FakeConsole; - -namespace Terminal.Gui.DriverTests { - public class ConsoleDriverTests { - readonly ITestOutputHelper output; - - public ConsoleDriverTests (ITestOutputHelper output) - { - this.output = output; - } - - [Theory] - [InlineData (typeof (FakeDriver))] - //[InlineData (typeof (NetDriver))] - //[InlineData (typeof (CursesDriver))] - //[InlineData (typeof (WindowsDriver))] - public void Init_Inits (Type driverType) - { - var driver = (ConsoleDriver)Activator.CreateInstance (driverType); - Application.Init (driver); - driver.Init (() => { }); - - Assert.Equal (80, Console.BufferWidth); - Assert.Equal (25, Console.BufferHeight); - - // MockDriver is always 80x25 - Assert.Equal (Console.BufferWidth, driver.Cols); - Assert.Equal (Console.BufferHeight, driver.Rows); - driver.End (); - - // Shutdown must be called to safely clean up Application if Init has been called - Application.Shutdown (); - } - - [Theory] - [InlineData (typeof (FakeDriver))] - //[InlineData (typeof (NetDriver))] - //[InlineData (typeof (CursesDriver))] - //[InlineData (typeof (WindowsDriver))] - public void End_Cleans_Up (Type driverType) - { - var driver = (ConsoleDriver)Activator.CreateInstance (driverType); - Application.Init (driver); - driver.Init (() => { }); - - Console.ForegroundColor = ConsoleColor.Red; - Assert.Equal (ConsoleColor.Red, Console.ForegroundColor); - - Console.BackgroundColor = ConsoleColor.Green; - Assert.Equal (ConsoleColor.Green, Console.BackgroundColor); - driver.Move (2, 3); - Assert.Equal (2, Console.CursorLeft); - Assert.Equal (3, Console.CursorTop); - - driver.End (); - Assert.Equal (0, Console.CursorLeft); - Assert.Equal (0, Console.CursorTop); - Assert.Equal (ConsoleColor.Gray, Console.ForegroundColor); - Assert.Equal (ConsoleColor.Black, Console.BackgroundColor); - - // Shutdown must be called to safely clean up Application if Init has been called - Application.Shutdown (); - } - - [Theory] - [InlineData (typeof (FakeDriver))] - public void FakeDriver_Only_Sends_Keystrokes_Through_MockKeyPresses (Type driverType) - { - var driver = (ConsoleDriver)Activator.CreateInstance (driverType); - Application.Init (driver); - - var top = Application.Top; - var view = new View (); - var count = 0; - var wasKeyPressed = false; - - view.KeyPress += (s, e) => { - wasKeyPressed = true; - }; - top.Add (view); - - Application.Iteration += () => { - count++; - if (count == 10) Application.RequestStop (); - }; - - Application.Run (); - - Assert.False (wasKeyPressed); - - // Shutdown must be called to safely clean up Application if Init has been called - Application.Shutdown (); - } - - [Theory] - [InlineData (typeof (FakeDriver))] - public void FakeDriver_MockKeyPresses (Type driverType) - { - var driver = (ConsoleDriver)Activator.CreateInstance (driverType); - Application.Init (driver); - - var text = "MockKeyPresses"; - var mKeys = new Stack (); - foreach (var r in text.Reverse ()) { - var ck = char.IsLetter (r) ? (ConsoleKey)char.ToUpper (r) : (ConsoleKey)r; - var cki = new ConsoleKeyInfo (r, ck, false, false, false); - mKeys.Push (cki); - } - Console.MockKeyPresses = mKeys; - - var top = Application.Top; - var view = new View (); - var rText = ""; - var idx = 0; - - view.KeyPress += (s, e) => { - Assert.Equal (text [idx], (char)e.KeyEvent.Key); - rText += (char)e.KeyEvent.Key; - Assert.Equal (rText, text.Substring (0, idx + 1)); - e.Handled = true; - idx++; - }; - top.Add (view); - - Application.Iteration += () => { - if (mKeys.Count == 0) Application.RequestStop (); - }; - - Application.Run (); - - Assert.Equal ("MockKeyPresses", rText); - - // Shutdown must be called to safely clean up Application if Init has been called - Application.Shutdown (); - } - - //[Theory] - //[InlineData (typeof (FakeDriver))] - //public void FakeDriver_MockKeyPresses_Press_AfterTimeOut (Type driverType) - //{ - // var driver = (ConsoleDriver)Activator.CreateInstance (driverType); - // Application.Init (driver); - - // // Simulating pressing of QuitKey after a short period of time - // uint quitTime = 100; - // Func closeCallback = (MainLoop loop) => { - // // Prove the scenario is using Application.QuitKey correctly - // output.WriteLine ($" {quitTime}ms elapsed; Simulating keypresses..."); - // FakeConsole.PushMockKeyPress (Key.F); - // FakeConsole.PushMockKeyPress (Key.U); - // FakeConsole.PushMockKeyPress (Key.C); - // FakeConsole.PushMockKeyPress (Key.K); - // return false; - // }; - // output.WriteLine ($"Add timeout to simulate key presses after {quitTime}ms"); - // _ = Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (quitTime), closeCallback); - - // // If Top doesn't quit within abortTime * 5 (500ms), this will force it - // uint abortTime = quitTime * 5; - // Func forceCloseCallback = (MainLoop loop) => { - // Application.RequestStop (); - // Assert.Fail ($" failed to Quit after {abortTime}ms. Force quit."); - // return false; - // }; - // output.WriteLine ($"Add timeout to force quit after {abortTime}ms"); - // _ = Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (abortTime), forceCloseCallback); - - - // Key key = Key.Unknown; - - // Application.Top.KeyPress += (e) => { - // key = e.KeyEvent.Key; - // output.WriteLine ($" Application.Top.KeyPress: {key}"); - // e.Handled = true; - - // }; - - // int iterations = 0; - // Application.Iteration += () => { - // output.WriteLine ($" iteration {++iterations}"); - - // if (Console.MockKeyPresses.Count == 0) { - // output.WriteLine ($" No more MockKeyPresses; RequestStop"); - // Application.RequestStop (); - // } - // }; - - // Application.Run (); - - // // Shutdown must be called to safely clean up Application if Init has been called - // Application.Shutdown (); - //} - - [Theory] - [InlineData (typeof (FakeDriver))] - public void TerminalResized_Simulation (Type driverType) - { - var driver = (FakeDriver)Activator.CreateInstance (driverType); - Application.Init (driver); - var wasTerminalResized = false; - Application.Resized = (e) => { - wasTerminalResized = true; - Assert.Equal (120, e.Cols); - Assert.Equal (40, e.Rows); - }; - - Assert.Equal (80, Console.BufferWidth); - Assert.Equal (25, Console.BufferHeight); - - // MockDriver is by default 80x25 - Assert.Equal (Console.BufferWidth, driver.Cols); - Assert.Equal (Console.BufferHeight, driver.Rows); - Assert.False (wasTerminalResized); - - // MockDriver will now be sets to 120x40 - driver.SetBufferSize (120, 40); - Assert.Equal (120, Application.Driver.Cols); - Assert.Equal (40, Application.Driver.Rows); - Assert.True (wasTerminalResized); - - // MockDriver will still be 120x40 - wasTerminalResized = false; - Application.EnableConsoleScrolling = true; - driver.SetWindowSize (40, 20); - Assert.Equal (120, Application.Driver.Cols); - Assert.Equal (40, Application.Driver.Rows); - Assert.Equal (120, Console.BufferWidth); - Assert.Equal (40, Console.BufferHeight); - Assert.Equal (40, Console.WindowWidth); - Assert.Equal (20, Console.WindowHeight); - Assert.True (wasTerminalResized); - - Application.Shutdown (); - } - - [Theory] - [InlineData (typeof (FakeDriver))] - public void EnableConsoleScrolling_Is_False_Left_And_Top_Is_Always_Zero (Type driverType) - { - var driver = (FakeDriver)Activator.CreateInstance (driverType); - Application.Init (driver); - - Assert.False (Application.EnableConsoleScrolling); - Assert.Equal (0, Console.WindowLeft); - Assert.Equal (0, Console.WindowTop); - - driver.SetWindowPosition (5, 5); - Assert.Equal (0, Console.WindowLeft); - Assert.Equal (0, Console.WindowTop); - - Application.Shutdown (); - } - - [Theory] - [InlineData (typeof (FakeDriver))] - public void EnableConsoleScrolling_Is_True_Left_Cannot_Be_Greater_Than_WindowWidth (Type driverType) - { - var driver = (FakeDriver)Activator.CreateInstance (driverType); - Application.Init (driver); - - Application.EnableConsoleScrolling = true; - Assert.True (Application.EnableConsoleScrolling); - - driver.SetWindowPosition (81, 25); - Assert.Equal (0, Console.WindowLeft); - Assert.Equal (0, Console.WindowTop); - - Application.Shutdown (); - } - - [Theory] - [InlineData (typeof (FakeDriver))] - public void EnableConsoleScrolling_Is_True_Left_Cannot_Be_Greater_Than_BufferWidth_Minus_WindowWidth (Type driverType) - { - var driver = (FakeDriver)Activator.CreateInstance (driverType); - Application.Init (driver); - - Application.EnableConsoleScrolling = true; - Assert.True (Application.EnableConsoleScrolling); - - driver.SetWindowPosition (81, 25); - Assert.Equal (0, Console.WindowLeft); - Assert.Equal (0, Console.WindowTop); - - // MockDriver will now be sets to 120x25 - driver.SetBufferSize (120, 25); - Assert.Equal (120, Application.Driver.Cols); - Assert.Equal (25, Application.Driver.Rows); - Assert.Equal (120, Console.BufferWidth); - Assert.Equal (25, Console.BufferHeight); - Assert.Equal (80, Console.WindowWidth); - Assert.Equal (25, Console.WindowHeight); - driver.SetWindowPosition (121, 25); - Assert.Equal (40, Console.WindowLeft); - Assert.Equal (0, Console.WindowTop); - - driver.SetWindowSize (90, 25); - Assert.Equal (120, Application.Driver.Cols); - Assert.Equal (25, Application.Driver.Rows); - Assert.Equal (120, Console.BufferWidth); - Assert.Equal (25, Console.BufferHeight); - Assert.Equal (90, Console.WindowWidth); - Assert.Equal (25, Console.WindowHeight); - driver.SetWindowPosition (121, 25); - Assert.Equal (30, Console.WindowLeft); - Assert.Equal (0, Console.WindowTop); - - Application.Shutdown (); - } - - [Theory] - [InlineData (typeof (FakeDriver))] - public void EnableConsoleScrolling_Is_True_Top_Cannot_Be_Greater_Than_WindowHeight (Type driverType) - { - var driver = (FakeDriver)Activator.CreateInstance (driverType); - Application.Init (driver); - - Application.EnableConsoleScrolling = true; - Assert.True (Application.EnableConsoleScrolling); - - driver.SetWindowPosition (80, 26); - Assert.Equal (0, Console.WindowLeft); - Assert.Equal (0, Console.WindowTop); - - Application.Shutdown (); - } - - [Theory] - [InlineData (typeof (FakeDriver))] - public void EnableConsoleScrolling_Is_True_Top_Cannot_Be_Greater_Than_BufferHeight_Minus_WindowHeight (Type driverType) - { - var driver = (FakeDriver)Activator.CreateInstance (driverType); - Application.Init (driver); - - Application.EnableConsoleScrolling = true; - Assert.True (Application.EnableConsoleScrolling); - - driver.SetWindowPosition (80, 26); - Assert.Equal (0, Console.WindowLeft); - Assert.Equal (0, Console.WindowTop); - - // MockDriver will now be sets to 80x40 - driver.SetBufferSize (80, 40); - Assert.Equal (80, Application.Driver.Cols); - Assert.Equal (40, Application.Driver.Rows); - Assert.Equal (80, Console.BufferWidth); - Assert.Equal (40, Console.BufferHeight); - Assert.Equal (80, Console.WindowWidth); - Assert.Equal (25, Console.WindowHeight); - Assert.Equal (0, Console.WindowLeft); - Assert.Equal (0, Console.WindowTop); - driver.SetWindowPosition (80, 40); - Assert.Equal (0, Console.WindowLeft); - Assert.Equal (15, Console.WindowTop); - - driver.SetWindowSize (80, 20); - Assert.Equal (80, Application.Driver.Cols); - Assert.Equal (40, Application.Driver.Rows); - Assert.Equal (80, Console.BufferWidth); - Assert.Equal (40, Console.BufferHeight); - Assert.Equal (80, Console.WindowWidth); - Assert.Equal (20, Console.WindowHeight); - Assert.Equal (0, Console.WindowLeft); - Assert.Equal (15, Console.WindowTop); - driver.SetWindowPosition (80, 41); - Assert.Equal (0, Console.WindowLeft); - Assert.Equal (20, Console.WindowTop); - - Application.Shutdown (); - } - - [Fact, AutoInitShutdown] - public void AddRune_On_Clip_Left_Or_Right_Replace_Previous_Or_Next_Wide_Rune_With_Space () - { - var tv = new TextView () { - Width = Dim.Fill (), - Height = Dim.Fill (), - Text = @"これは広いルーンラインです。 -これは広いルーンラインです。 -これは広いルーンラインです。 -これは広いルーンラインです。 -これは広いルーンラインです。 -これは広いルーンラインです。 -これは広いルーンラインです。 -これは広いルーンラインです。" - }; - var win = new Window ("ワイドルーン") { Width = Dim.Fill (), Height = Dim.Fill () }; - win.Add (tv); - Application.Top.Add (win); - var lbl = new Label ("ワイドルーン。"); - var dg = new Dialog ("テスト", 14, 4, new Button ("選ぶ")); - dg.Add (lbl); - Application.Begin (Application.Top); - Application.Begin (dg); - ((FakeDriver)Application.Driver).SetBufferSize (30, 10); - - var expected = @" -┌┤ワイドルーン├──────────────┐ -│これは広いルーンラインです。│ -│これは広いルーンラインです。│ -│これは ┌┤テスト├────┐ です。│ -│これは │ワイドルーン│ です。│ -│これは │ [ 選ぶ ] │ です。│ -│これは └────────────┘ です。│ -│これは広いルーンラインです。│ -│これは広いルーンラインです。│ -└────────────────────────────┘ -"; - - var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (0, 0, 30, 10), pos); - } - - [Fact, AutoInitShutdown] - public void Write_Do_Not_Change_On_ProcessKey () - { - var win = new Window (); - Application.Begin (win); - ((FakeDriver)Application.Driver).SetBufferSize (20, 8); - - System.Threading.Tasks.Task.Run (() => { - System.Threading.Tasks.Task.Delay (500).Wait (); - Application.MainLoop.Invoke (() => { - var lbl = new Label ("Hello World") { X = Pos.Center () }; - var dlg = new Dialog ("Test", new Button ("Ok")); - dlg.Add (lbl); - Application.Begin (dlg); - - var expected = @" -┌──────────────────┐ -│┌┤Test├─────────┐ │ -││ Hello World │ │ -││ │ │ -││ │ │ -││ [ Ok ] │ │ -│└───────────────┘ │ -└──────────────────┘ -"; - - var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (0, 0, 20, 8), pos); - - Assert.True (dlg.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ()))); - dlg.Redraw (dlg.Bounds); - - expected = @" -┌──────────────────┐ -│┌┤Test├─────────┐ │ -││ Hello World │ │ -││ │ │ -││ │ │ -││ [ Ok ] │ │ -│└───────────────┘ │ -└──────────────────┘ -"; - - pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (0, 0, 20, 8), pos); - - win.RequestStop (); - }); - }); - - Application.Run (win); - Application.Shutdown (); - } - - [Theory] - [InlineData (0x0000001F, 0x241F)] - [InlineData (0x0000007F, 0x247F)] - [InlineData (0x0000009F, 0x249F)] - [InlineData (0x0001001A, 0x1001A)] - public void MakePrintable_Converts_Control_Chars_To_Proper_Unicode (uint code, uint expected) - { - var actual = ConsoleDriver.MakePrintable (code); - - Assert.Equal (expected, actual.Value); - } - - [Theory] - [InlineData (0x20)] - [InlineData (0x7E)] - [InlineData (0xA0)] - [InlineData (0x010020)] - public void MakePrintable_Does_Not_Convert_Ansi_Chars_To_Unicode (uint code) - { - var actual = ConsoleDriver.MakePrintable (code); - - Assert.Equal (code, actual.Value); - } - - private static object packetLock = new object (); - - /// - /// Sometimes when using remote tools EventKeyRecord sends 'virtual keystrokes'. - /// These are indicated with the wVirtualKeyCode of 231. When we see this code - /// then we need to look to the unicode character (UnicodeChar) instead of the key - /// when telling the rest of the framework what button was pressed. For full details - /// see: https://github.com/gui-cs/Terminal.Gui/issues/2008 - /// - [Theory, AutoInitShutdown] - [ClassData (typeof (PacketTest))] - public void TestVKPacket (uint unicodeCharacter, bool shift, bool alt, bool control, uint initialVirtualKey, uint initialScanCode, Key expectedRemapping, uint expectedVirtualKey, uint expectedScanCode) - { - var modifiers = new ConsoleModifiers (); - if (shift) modifiers |= ConsoleModifiers.Shift; - if (alt) modifiers |= ConsoleModifiers.Alt; - if (control) modifiers |= ConsoleModifiers.Control; - var mappedConsoleKey = ConsoleKeyMapping.GetConsoleKeyFromKey (unicodeCharacter, modifiers, out uint scanCode, out uint outputChar); - - if ((scanCode > 0 || mappedConsoleKey == 0) && mappedConsoleKey == initialVirtualKey) Assert.Equal (mappedConsoleKey, initialVirtualKey); - else Assert.Equal (mappedConsoleKey, outputChar < 0xff ? outputChar & 0xff | 0xff << 8 : outputChar); - Assert.Equal (scanCode, initialScanCode); - - var keyChar = ConsoleKeyMapping.GetKeyCharFromConsoleKey (mappedConsoleKey, modifiers, out uint consoleKey, out scanCode); - - //if (scanCode > 0 && consoleKey == keyChar && consoleKey > 48 && consoleKey > 57 && consoleKey < 65 && consoleKey > 91) { - if (scanCode > 0 && keyChar == 0 && consoleKey == mappedConsoleKey) Assert.Equal (0, (double)keyChar); - else Assert.Equal (keyChar, unicodeCharacter); - Assert.Equal (consoleKey, expectedVirtualKey); - Assert.Equal (scanCode, expectedScanCode); - - var top = Application.Top; - - top.KeyPress += (s, e) => { - var after = ShortcutHelper.GetModifiersKey (e.KeyEvent); - Assert.Equal (expectedRemapping, after); - e.Handled = true; - Application.RequestStop (); - }; - - var iterations = -1; - - Application.Iteration += () => { - iterations++; - if (iterations == 0) Application.Driver.SendKeys ((char)mappedConsoleKey, ConsoleKey.Packet, shift, alt, control); - }; - - - lock (packetLock) { - Application.Run (); - Application.Shutdown (); - } - } - - public class PacketTest : IEnumerable, IEnumerable { - public IEnumerator GetEnumerator () - { - lock (packetLock) { - yield return new object [] { 'a', false, false, false, 'A', 30, Key.a, 'A', 30 }; - yield return new object [] { 'A', true, false, false, 'A', 30, Key.A | Key.ShiftMask, 'A', 30 }; - yield return new object [] { 'A', true, true, false, 'A', 30, Key.A | Key.ShiftMask | Key.AltMask, 'A', 30 }; - yield return new object [] { 'A', true, true, true, 'A', 30, Key.A | Key.ShiftMask | Key.AltMask | Key.CtrlMask, 'A', 30 }; - yield return new object [] { 'z', false, false, false, 'Z', 44, Key.z, 'Z', 44 }; - yield return new object [] { 'Z', true, false, false, 'Z', 44, Key.Z | Key.ShiftMask, 'Z', 44 }; - yield return new object [] { 'Z', true, true, false, 'Z', 44, Key.Z | Key.ShiftMask | Key.AltMask, 'Z', 44 }; - yield return new object [] { 'Z', true, true, true, 'Z', 44, Key.Z | Key.ShiftMask | Key.AltMask | Key.CtrlMask, 'Z', 44 }; - yield return new object [] { '英', false, false, false, '\0', 0, (Key)'英', '\0', 0 }; - yield return new object [] { '英', true, false, false, '\0', 0, (Key)'英' | Key.ShiftMask, '\0', 0 }; - yield return new object [] { '英', true, true, false, '\0', 0, (Key)'英' | Key.ShiftMask | Key.AltMask, '\0', 0 }; - yield return new object [] { '英', true, true, true, '\0', 0, (Key)'英' | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '\0', 0 }; - yield return new object [] { '+', false, false, false, 187, 26, (Key)'+', 187, 26 }; - yield return new object [] { '*', true, false, false, 187, 26, (Key)'*' | Key.ShiftMask, 187, 26 }; - yield return new object [] { '+', true, true, false, 187, 26, (Key)'+' | Key.ShiftMask | Key.AltMask, 187, 26 }; - yield return new object [] { '+', true, true, true, 187, 26, (Key)'+' | Key.ShiftMask | Key.AltMask | Key.CtrlMask, 187, 26 }; - yield return new object [] { '1', false, false, false, '1', 2, Key.D1, '1', 2 }; - yield return new object [] { '!', true, false, false, '1', 2, (Key)'!' | Key.ShiftMask, '1', 2 }; - yield return new object [] { '1', true, true, false, '1', 2, Key.D1 | Key.ShiftMask | Key.AltMask, '1', 2 }; - yield return new object [] { '1', true, true, true, '1', 2, Key.D1 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '1', 2 }; - yield return new object [] { '1', false, true, true, '1', 2, Key.D1 | Key.AltMask | Key.CtrlMask, '1', 2 }; - yield return new object [] { '2', false, false, false, '2', 3, Key.D2, '2', 3 }; - yield return new object [] { '"', true, false, false, '2', 3, (Key)'"' | Key.ShiftMask, '2', 3 }; - yield return new object [] { '2', true, true, false, '2', 3, Key.D2 | Key.ShiftMask | Key.AltMask, '2', 3 }; - yield return new object [] { '2', true, true, true, '2', 3, Key.D2 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '2', 3 }; - yield return new object [] { '@', false, true, true, '2', 3, (Key)'@' | Key.AltMask | Key.CtrlMask, '2', 3 }; - yield return new object [] { '3', false, false, false, '3', 4, Key.D3, '3', 4 }; - yield return new object [] { '#', true, false, false, '3', 4, (Key)'#' | Key.ShiftMask, '3', 4 }; - yield return new object [] { '3', true, true, false, '3', 4, Key.D3 | Key.ShiftMask | Key.AltMask, '3', 4 }; - yield return new object [] { '3', true, true, true, '3', 4, Key.D3 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '3', 4 }; - yield return new object [] { '£', false, true, true, '3', 4, (Key)'£' | Key.AltMask | Key.CtrlMask, '3', 4 }; - yield return new object [] { '4', false, false, false, '4', 5, Key.D4, '4', 5 }; - yield return new object [] { '$', true, false, false, '4', 5, (Key)'$' | Key.ShiftMask, '4', 5 }; - yield return new object [] { '4', true, true, false, '4', 5, Key.D4 | Key.ShiftMask | Key.AltMask, '4', 5 }; - yield return new object [] { '4', true, true, true, '4', 5, Key.D4 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '4', 5 }; - yield return new object [] { '§', false, true, true, '4', 5, (Key)'§' | Key.AltMask | Key.CtrlMask, '4', 5 }; - yield return new object [] { '5', false, false, false, '5', 6, Key.D5, '5', 6 }; - yield return new object [] { '%', true, false, false, '5', 6, (Key)'%' | Key.ShiftMask, '5', 6 }; - yield return new object [] { '5', true, true, false, '5', 6, Key.D5 | Key.ShiftMask | Key.AltMask, '5', 6 }; - yield return new object [] { '5', true, true, true, '5', 6, Key.D5 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '5', 6 }; - yield return new object [] { '€', false, true, true, '5', 6, (Key)'€' | Key.AltMask | Key.CtrlMask, '5', 6 }; - yield return new object [] { '6', false, false, false, '6', 7, Key.D6, '6', 7 }; - yield return new object [] { '&', true, false, false, '6', 7, (Key)'&' | Key.ShiftMask, '6', 7 }; - yield return new object [] { '6', true, true, false, '6', 7, Key.D6 | Key.ShiftMask | Key.AltMask, '6', 7 }; - yield return new object [] { '6', true, true, true, '6', 7, Key.D6 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '6', 7 }; - yield return new object [] { '6', false, true, true, '6', 7, Key.D6 | Key.AltMask | Key.CtrlMask, '6', 7 }; - yield return new object [] { '7', false, false, false, '7', 8, Key.D7, '7', 8 }; - yield return new object [] { '/', true, false, false, '7', 8, (Key)'/' | Key.ShiftMask, '7', 8 }; - yield return new object [] { '7', true, true, false, '7', 8, Key.D7 | Key.ShiftMask | Key.AltMask, '7', 8 }; - yield return new object [] { '7', true, true, true, '7', 8, Key.D7 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '7', 8 }; - yield return new object [] { '{', false, true, true, '7', 8, (Key)'{' | Key.AltMask | Key.CtrlMask, '7', 8 }; - yield return new object [] { '8', false, false, false, '8', 9, Key.D8, '8', 9 }; - yield return new object [] { '(', true, false, false, '8', 9, (Key)'(' | Key.ShiftMask, '8', 9 }; - yield return new object [] { '8', true, true, false, '8', 9, Key.D8 | Key.ShiftMask | Key.AltMask, '8', 9 }; - yield return new object [] { '8', true, true, true, '8', 9, Key.D8 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '8', 9 }; - yield return new object [] { '[', false, true, true, '8', 9, (Key)'[' | Key.AltMask | Key.CtrlMask, '8', 9 }; - yield return new object [] { '9', false, false, false, '9', 10, Key.D9, '9', 10 }; - yield return new object [] { ')', true, false, false, '9', 10, (Key)')' | Key.ShiftMask, '9', 10 }; - yield return new object [] { '9', true, true, false, '9', 10, Key.D9 | Key.ShiftMask | Key.AltMask, '9', 10 }; - yield return new object [] { '9', true, true, true, '9', 10, Key.D9 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '9', 10 }; - yield return new object [] { ']', false, true, true, '9', 10, (Key)']' | Key.AltMask | Key.CtrlMask, '9', 10 }; - yield return new object [] { '0', false, false, false, '0', 11, Key.D0, '0', 11 }; - yield return new object [] { '=', true, false, false, '0', 11, (Key)'=' | Key.ShiftMask, '0', 11 }; - yield return new object [] { '0', true, true, false, '0', 11, Key.D0 | Key.ShiftMask | Key.AltMask, '0', 11 }; - yield return new object [] { '0', true, true, true, '0', 11, Key.D0 | Key.ShiftMask | Key.AltMask | Key.CtrlMask, '0', 11 }; - yield return new object [] { '}', false, true, true, '0', 11, (Key)'}' | Key.AltMask | Key.CtrlMask, '0', 11 }; - yield return new object [] { '\'', false, false, false, 219, 12, (Key)'\'', 219, 12 }; - yield return new object [] { '?', true, false, false, 219, 12, (Key)'?' | Key.ShiftMask, 219, 12 }; - yield return new object [] { '\'', true, true, false, 219, 12, (Key)'\'' | Key.ShiftMask | Key.AltMask, 219, 12 }; - yield return new object [] { '\'', true, true, true, 219, 12, (Key)'\'' | Key.ShiftMask | Key.AltMask | Key.CtrlMask, 219, 12 }; - yield return new object [] { '«', false, false, false, 221, 13, (Key)'«', 221, 13 }; - yield return new object [] { '»', true, false, false, 221, 13, (Key)'»' | Key.ShiftMask, 221, 13 }; - yield return new object [] { '«', true, true, false, 221, 13, (Key)'«' | Key.ShiftMask | Key.AltMask, 221, 13 }; - yield return new object [] { '«', true, true, true, 221, 13, (Key)'«' | Key.ShiftMask | Key.AltMask | Key.CtrlMask, 221, 13 }; - yield return new object [] { 'á', false, false, false, 'á', 0, (Key)'á', 'A', 30 }; - yield return new object [] { 'Á', true, false, false, 'Á', 0, (Key)'Á' | Key.ShiftMask, 'A', 30 }; - yield return new object [] { 'à', false, false, false, 'à', 0, (Key)'à', 'A', 30 }; - yield return new object [] { 'À', true, false, false, 'À', 0, (Key)'À' | Key.ShiftMask, 'A', 30 }; - yield return new object [] { 'é', false, false, false, 'é', 0, (Key)'é', 'E', 18 }; - yield return new object [] { 'É', true, false, false, 'É', 0, (Key)'É' | Key.ShiftMask, 'E', 18 }; - yield return new object [] { 'è', false, false, false, 'è', 0, (Key)'è', 'E', 18 }; - yield return new object [] { 'È', true, false, false, 'È', 0, (Key)'È' | Key.ShiftMask, 'E', 18 }; - yield return new object [] { 'í', false, false, false, 'í', 0, (Key)'í', 'I', 23 }; - yield return new object [] { 'Í', true, false, false, 'Í', 0, (Key)'Í' | Key.ShiftMask, 'I', 23 }; - yield return new object [] { 'ì', false, false, false, 'ì', 0, (Key)'ì', 'I', 23 }; - yield return new object [] { 'Ì', true, false, false, 'Ì', 0, (Key)'Ì' | Key.ShiftMask, 'I', 23 }; - yield return new object [] { 'ó', false, false, false, 'ó', 0, (Key)'ó', 'O', 24 }; - yield return new object [] { 'Ó', true, false, false, 'Ó', 0, (Key)'Ó' | Key.ShiftMask, 'O', 24 }; - yield return new object [] { 'ò', false, false, false, 'Ó', 0, (Key)'ò', 'O', 24 }; - yield return new object [] { 'Ò', true, false, false, 'Ò', 0, (Key)'Ò' | Key.ShiftMask, 'O', 24 }; - yield return new object [] { 'ú', false, false, false, 'ú', 0, (Key)'ú', 'U', 22 }; - yield return new object [] { 'Ú', true, false, false, 'Ú', 0, (Key)'Ú' | Key.ShiftMask, 'U', 22 }; - yield return new object [] { 'ù', false, false, false, 'ù', 0, (Key)'ù', 'U', 22 }; - yield return new object [] { 'Ù', true, false, false, 'Ù', 0, (Key)'Ù' | Key.ShiftMask, 'U', 22 }; - yield return new object [] { 'ö', false, false, false, 'ó', 0, (Key)'ö', 'O', 24 }; - yield return new object [] { 'Ö', true, false, false, 'Ó', 0, (Key)'Ö' | Key.ShiftMask, 'O', 24 }; - yield return new object [] { '<', false, false, false, 226, 86, (Key)'<', 226, 86 }; - yield return new object [] { '>', true, false, false, 226, 86, (Key)'>' | Key.ShiftMask, 226, 86 }; - yield return new object [] { '<', true, true, false, 226, 86, (Key)'<' | Key.ShiftMask | Key.AltMask, 226, 86 }; - yield return new object [] { '<', true, true, true, 226, 86, (Key)'<' | Key.ShiftMask | Key.AltMask | Key.CtrlMask, 226, 86 }; - yield return new object [] { 'ç', false, false, false, 192, 39, (Key)'ç', 192, 39 }; - yield return new object [] { 'Ç', true, false, false, 192, 39, (Key)'Ç' | Key.ShiftMask, 192, 39 }; - yield return new object [] { 'ç', true, true, false, 192, 39, (Key)'ç' | Key.ShiftMask | Key.AltMask, 192, 39 }; - yield return new object [] { 'ç', true, true, true, 192, 39, (Key)'ç' | Key.ShiftMask | Key.AltMask | Key.CtrlMask, 192, 39 }; - yield return new object [] { '¨', false, true, true, 187, 26, (Key)'¨' | Key.AltMask | Key.CtrlMask, 187, 26 }; - yield return new object [] { (uint)Key.PageUp, false, false, false, 33, 73, Key.PageUp, 33, 73 }; - yield return new object [] { (uint)Key.PageUp, true, false, false, 33, 73, Key.PageUp | Key.ShiftMask, 33, 73 }; - yield return new object [] { (uint)Key.PageUp, true, true, false, 33, 73, Key.PageUp | Key.ShiftMask | Key.AltMask, 33, 73 }; - yield return new object [] { (uint)Key.PageUp, true, true, true, 33, 73, Key.PageUp | Key.ShiftMask | Key.AltMask | Key.CtrlMask, 33, 73 }; - } - } - - IEnumerator IEnumerable.GetEnumerator () => GetEnumerator (); - } - } -} diff --git a/UnitTests/Drivers/KeyTests.cs b/UnitTests/Drivers/KeyTests.cs deleted file mode 100644 index ef55d5916..000000000 --- a/UnitTests/Drivers/KeyTests.cs +++ /dev/null @@ -1,173 +0,0 @@ -using System; -using Terminal.Gui; -using Xunit; - -namespace Terminal.Gui.DriverTests { - public class KeyTests { - enum SimpleEnum { Zero, One, Two, Three, Four, Five } - - [Flags] - enum FlaggedEnum { Zero, One, Two, Three, Four, Five } - - - enum SimpleHighValueEnum { Zero, One, Two, Three, Four, Last = 0x40000000 } - - [Flags] - enum FlaggedHighValueEnum { Zero, One, Two, Three, Four, Last = 0x40000000 } - - [Fact] - public void SimpleEnum_And_FlagedEnum () - { - var simple = SimpleEnum.Three | SimpleEnum.Five; - - // Nothing will not be well compared here. - Assert.True (simple.HasFlag (SimpleEnum.Zero | SimpleEnum.Five)); - Assert.True (simple.HasFlag (SimpleEnum.One | SimpleEnum.Five)); - Assert.True (simple.HasFlag (SimpleEnum.Two | SimpleEnum.Five)); - Assert.True (simple.HasFlag (SimpleEnum.Three | SimpleEnum.Five)); - Assert.True (simple.HasFlag (SimpleEnum.Four | SimpleEnum.Five)); - Assert.True ((simple & (SimpleEnum.Zero | SimpleEnum.Five)) != 0); - Assert.True ((simple & (SimpleEnum.One | SimpleEnum.Five)) != 0); - Assert.True ((simple & (SimpleEnum.Two | SimpleEnum.Five)) != 0); - Assert.True ((simple & (SimpleEnum.Three | SimpleEnum.Five)) != 0); - Assert.True ((simple & (SimpleEnum.Four | SimpleEnum.Five)) != 0); - Assert.Equal (7, (int)simple); // As it is not flagged only shows as number. - Assert.Equal ("7", simple.ToString ()); - Assert.False (simple == (SimpleEnum.Zero | SimpleEnum.Five)); - Assert.False (simple == (SimpleEnum.One | SimpleEnum.Five)); - Assert.True (simple == (SimpleEnum.Two | SimpleEnum.Five)); - Assert.True (simple == (SimpleEnum.Three | SimpleEnum.Five)); - Assert.False (simple == (SimpleEnum.Four | SimpleEnum.Five)); - - var flagged = FlaggedEnum.Three | FlaggedEnum.Five; - - // Nothing will not be well compared here. - Assert.True (flagged.HasFlag (FlaggedEnum.Zero | FlaggedEnum.Five)); - Assert.True (flagged.HasFlag (FlaggedEnum.One | FlaggedEnum.Five)); - Assert.True (flagged.HasFlag (FlaggedEnum.Two | FlaggedEnum.Five)); - Assert.True (flagged.HasFlag (FlaggedEnum.Three | FlaggedEnum.Five)); - Assert.True (flagged.HasFlag (FlaggedEnum.Four | FlaggedEnum.Five)); - Assert.True ((flagged & (FlaggedEnum.Zero | FlaggedEnum.Five)) != 0); - Assert.True ((flagged & (FlaggedEnum.One | FlaggedEnum.Five)) != 0); - Assert.True ((flagged & (FlaggedEnum.Two | FlaggedEnum.Five)) != 0); - Assert.True ((flagged & (FlaggedEnum.Three | FlaggedEnum.Five)) != 0); - Assert.True ((flagged & (FlaggedEnum.Four | FlaggedEnum.Five)) != 0); - Assert.Equal (FlaggedEnum.Two | FlaggedEnum.Five, flagged); // As it is flagged shows as bitwise. - Assert.Equal ("Two, Five", flagged.ToString ()); - Assert.False (flagged == (FlaggedEnum.Zero | FlaggedEnum.Five)); - Assert.False (flagged == (FlaggedEnum.One | FlaggedEnum.Five)); - Assert.True (flagged == (FlaggedEnum.Two | FlaggedEnum.Five)); - Assert.True (flagged == (FlaggedEnum.Three | FlaggedEnum.Five)); - Assert.False (flagged == (FlaggedEnum.Four | FlaggedEnum.Five)); - } - - [Fact] - public void SimpleHighValueEnum_And_FlaggedHighValueEnum () - { - var simple = SimpleHighValueEnum.Three | SimpleHighValueEnum.Last; - - // This will not be well compared. - Assert.True (simple.HasFlag (SimpleHighValueEnum.Zero | SimpleHighValueEnum.Last)); - Assert.True (simple.HasFlag (SimpleHighValueEnum.One | SimpleHighValueEnum.Last)); - Assert.True (simple.HasFlag (SimpleHighValueEnum.Two | SimpleHighValueEnum.Last)); - Assert.True (simple.HasFlag (SimpleHighValueEnum.Three | SimpleHighValueEnum.Last)); - Assert.False (simple.HasFlag (SimpleHighValueEnum.Four | SimpleHighValueEnum.Last)); - Assert.True ((simple & (SimpleHighValueEnum.Zero | SimpleHighValueEnum.Last)) != 0); - Assert.True ((simple & (SimpleHighValueEnum.One | SimpleHighValueEnum.Last)) != 0); - Assert.True ((simple & (SimpleHighValueEnum.Two | SimpleHighValueEnum.Last)) != 0); - Assert.True ((simple & (SimpleHighValueEnum.Three | SimpleHighValueEnum.Last)) != 0); - Assert.True ((simple & (SimpleHighValueEnum.Four | SimpleHighValueEnum.Last)) != 0); - - // This will be well compared, because the SimpleHighValueEnum.Last have a high value. - Assert.Equal (1073741827, (int)simple); // As it is not flagged only shows as number. - Assert.Equal ("1073741827", simple.ToString ()); // As it is not flagged only shows as number. - Assert.False (simple == (SimpleHighValueEnum.Zero | SimpleHighValueEnum.Last)); - Assert.False (simple == (SimpleHighValueEnum.One | SimpleHighValueEnum.Last)); - Assert.False (simple == (SimpleHighValueEnum.Two | SimpleHighValueEnum.Last)); - Assert.True (simple == (SimpleHighValueEnum.Three | SimpleHighValueEnum.Last)); - Assert.False (simple == (SimpleHighValueEnum.Four | SimpleHighValueEnum.Last)); - - var flagged = FlaggedHighValueEnum.Three | FlaggedHighValueEnum.Last; - - // This will not be well compared. - Assert.True (flagged.HasFlag (FlaggedHighValueEnum.Zero | FlaggedHighValueEnum.Last)); - Assert.True (flagged.HasFlag (FlaggedHighValueEnum.One | FlaggedHighValueEnum.Last)); - Assert.True (flagged.HasFlag (FlaggedHighValueEnum.Two | FlaggedHighValueEnum.Last)); - Assert.True (flagged.HasFlag (FlaggedHighValueEnum.Three | FlaggedHighValueEnum.Last)); - Assert.False (flagged.HasFlag (FlaggedHighValueEnum.Four | FlaggedHighValueEnum.Last)); - Assert.True ((flagged & (FlaggedHighValueEnum.Zero | FlaggedHighValueEnum.Last)) != 0); - Assert.True ((flagged & (FlaggedHighValueEnum.One | FlaggedHighValueEnum.Last)) != 0); - Assert.True ((flagged & (FlaggedHighValueEnum.Two | FlaggedHighValueEnum.Last)) != 0); - Assert.True ((flagged & (FlaggedHighValueEnum.Three | FlaggedHighValueEnum.Last)) != 0); - Assert.True ((flagged & (FlaggedHighValueEnum.Four | FlaggedHighValueEnum.Last)) != 0); - - // This will be well compared, because the SimpleHighValueEnum.Last have a high value. - Assert.Equal (FlaggedHighValueEnum.Three | FlaggedHighValueEnum.Last, flagged); // As it is flagged shows as bitwise. - Assert.Equal ("Three, Last", flagged.ToString ()); // As it is flagged shows as bitwise. - Assert.False (flagged == (FlaggedHighValueEnum.Zero | FlaggedHighValueEnum.Last)); - Assert.False (flagged == (FlaggedHighValueEnum.One | FlaggedHighValueEnum.Last)); - Assert.False (flagged == (FlaggedHighValueEnum.Two | FlaggedHighValueEnum.Last)); - Assert.True (flagged == (FlaggedHighValueEnum.Three | FlaggedHighValueEnum.Last)); - Assert.False (flagged == (FlaggedHighValueEnum.Four | FlaggedHighValueEnum.Last)); - } - - [Fact] - public void Key_Enum_Ambiguity_Check () - { - var key = Key.Y | Key.CtrlMask; - - // This will not be well compared. - Assert.True (key.HasFlag (Key.Q | Key.CtrlMask)); - Assert.True ((key & (Key.Q | Key.CtrlMask)) != 0); - Assert.Equal (Key.Y | Key.CtrlMask, key); - Assert.Equal ("Y, CtrlMask", key.ToString ()); - - // This will be well compared, because the Key.CtrlMask have a high value. - Assert.False (key == Application.QuitKey); - switch (key) { - case Key.Q | Key.CtrlMask: - // Never goes here. - break; - case Key.Y | Key.CtrlMask: - Assert.True (key == (Key.Y | Key.CtrlMask)); - break; - default: - // Never goes here. - break; - } - } - - [Fact] - public void Key_ToString () - { - var k = Key.Y | Key.CtrlMask; - Assert.Equal ("Y, CtrlMask", k.ToString ()); - - k = Key.CtrlMask | Key.Y; - Assert.Equal ("Y, CtrlMask", k.ToString ()); - - k = Key.Space; - Assert.Equal ("Space", k.ToString ()); - - k = Key.Space | Key.D; - Assert.Equal ("d", k.ToString ()); - - k = (Key)'d'; - Assert.Equal ("d", k.ToString ()); - - k = Key.d; - Assert.Equal ("d", k.ToString ()); - - k = Key.D; - Assert.Equal ("D", k.ToString ()); - - // In a console this will always returns Key.D - k = Key.D | Key.ShiftMask; - Assert.Equal ("D, ShiftMask", k.ToString ()); - - // In a console this will always returns Key.D - k = Key.d | Key.ShiftMask; - Assert.Equal ("d, ShiftMask", k.ToString ()); - } - } -} \ No newline at end of file diff --git a/UnitTests/Core/EscSeqReqTests.cs b/UnitTests/Input/EscSeqReqTests.cs similarity index 98% rename from UnitTests/Core/EscSeqReqTests.cs rename to UnitTests/Input/EscSeqReqTests.cs index 33f955d49..53032e266 100644 --- a/UnitTests/Core/EscSeqReqTests.cs +++ b/UnitTests/Input/EscSeqReqTests.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; using Xunit; -namespace Terminal.Gui.CoreTests { +namespace Terminal.Gui.InputTests { public class EscSeqReqTests { [Fact] public void Constructor_Defaults () diff --git a/UnitTests/Core/EscSeqUtilsTests.cs b/UnitTests/Input/EscSeqUtilsTests.cs similarity index 99% rename from UnitTests/Core/EscSeqUtilsTests.cs rename to UnitTests/Input/EscSeqUtilsTests.cs index 6db843ffe..39c34db62 100644 --- a/UnitTests/Core/EscSeqUtilsTests.cs +++ b/UnitTests/Input/EscSeqUtilsTests.cs @@ -4,7 +4,7 @@ using System.Diagnostics; using System.Runtime.InteropServices; using Xunit; -namespace Terminal.Gui.CoreTests { +namespace Terminal.Gui.InputTests { public class EscSeqUtilsTests { [Fact] public void Defaults_Values () diff --git a/UnitTests/Core/ResponderTests.cs b/UnitTests/Input/ResponderTests.cs similarity index 98% rename from UnitTests/Core/ResponderTests.cs rename to UnitTests/Input/ResponderTests.cs index fdd59226b..66b8b85f7 100644 --- a/UnitTests/Core/ResponderTests.cs +++ b/UnitTests/Input/ResponderTests.cs @@ -3,7 +3,7 @@ using Xunit; // Alias Console to MockConsole so we don't accidentally use Console using Console = Terminal.Gui.FakeConsole; -namespace Terminal.Gui.CoreTests { +namespace Terminal.Gui.InputTests { public class ResponderTests { [Fact] public void New_Initializes () diff --git a/UnitTests/TestHelpers.cs b/UnitTests/TestHelpers.cs index b7d280c7f..9ed21f8d6 100644 --- a/UnitTests/TestHelpers.cs +++ b/UnitTests/TestHelpers.cs @@ -2,16 +2,14 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; using Xunit.Abstractions; using Xunit; using Terminal.Gui; -using Rune = System.Rune; -using Attribute = Terminal.Gui.Attribute; using System.Text.RegularExpressions; using System.Reflection; using System.Diagnostics; -using Terminal.Gui.Configuration; +using Rune = System.Rune; +using Attribute = Terminal.Gui.Attribute; // This class enables test functions annotated with the [AutoInitShutdown] attribute to diff --git a/UnitTests/Views/AutocompleteTests.cs b/UnitTests/Text/AutocompleteTests.cs similarity index 99% rename from UnitTests/Views/AutocompleteTests.cs rename to UnitTests/Text/AutocompleteTests.cs index 7e2a99778..f9de6e9c8 100644 --- a/UnitTests/Views/AutocompleteTests.cs +++ b/UnitTests/Text/AutocompleteTests.cs @@ -8,7 +8,7 @@ using Terminal.Gui; using Xunit; using Xunit.Abstractions; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.TextTests { public class AutocompleteTests { readonly ITestOutputHelper output; diff --git a/UnitTests/Text/UnicodeTests.cs b/UnitTests/Text/UnicodeTests.cs new file mode 100644 index 000000000..61041a47a --- /dev/null +++ b/UnitTests/Text/UnicodeTests.cs @@ -0,0 +1,87 @@ +using NStack; +using System; +using System.Collections.Generic; +using System.Linq; +using Terminal.Gui; +using Xunit; +using Xunit.Abstractions; + +// Alias Console to MockConsole so we don't accidentally use Console +using Console = Terminal.Gui.FakeConsole; + +namespace Terminal.Gui.TextTests { + public class UnicodeTests { + readonly ITestOutputHelper output; + + public UnicodeTests (ITestOutputHelper output) + { + this.output = output; + } + + [Theory] + [InlineData (0x0000001F, 0x241F)] + [InlineData (0x0000007F, 0x247F)] + [InlineData (0x0000009F, 0x249F)] + [InlineData (0x0001001A, 0x1001A)] + public void MakePrintable_Converts_Control_Chars_To_Proper_Unicode (uint code, uint expected) + { + var actual = ConsoleDriver.MakePrintable (code); + + Assert.Equal (expected, actual.Value); + } + + [Theory] + [InlineData (0x20)] + [InlineData (0x7E)] + [InlineData (0xA0)] + [InlineData (0x010020)] + public void MakePrintable_Does_Not_Convert_Ansi_Chars_To_Unicode (uint code) + { + var actual = ConsoleDriver.MakePrintable (code); + + Assert.Equal (code, actual.Value); + } + + [Fact, AutoInitShutdown] + public void AddRune_On_Clip_Left_Or_Right_Replace_Previous_Or_Next_Wide_Rune_With_Space () + { + var tv = new TextView () { + Width = Dim.Fill (), + Height = Dim.Fill (), + Text = @"これは広いルーンラインです。 +これは広いルーンラインです。 +これは広いルーンラインです。 +これは広いルーンラインです。 +これは広いルーンラインです。 +これは広いルーンラインです。 +これは広いルーンラインです。 +これは広いルーンラインです。" + }; + var win = new Window ("ワイドルーン") { Width = Dim.Fill (), Height = Dim.Fill () }; + win.Add (tv); + Application.Top.Add (win); + var lbl = new Label ("ワイドルーン。"); + var dg = new Dialog ("テスト", 14, 4, new Button ("選ぶ")); + dg.Add (lbl); + Application.Begin (Application.Top); + Application.Begin (dg); + ((FakeDriver)Application.Driver).SetBufferSize (30, 10); + + var expected = @" +┌┤ワイドルーン├──────────────┐ +│これは広いルーンラインです。│ +│これは広いルーンラインです。│ +│これは ┌┤テスト├────┐ です。│ +│これは │ワイドルーン│ です。│ +│これは │ [ 選ぶ ] │ です。│ +│これは └────────────┘ です。│ +│これは広いルーンラインです。│ +│これは広いルーンラインです。│ +└────────────────────────────┘ +"; + + var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (0, 0, 30, 10), pos); + } + } +} \ No newline at end of file diff --git a/UnitTests/Core/BorderTests.cs b/UnitTests/View/BorderTests.cs similarity index 99% rename from UnitTests/Core/BorderTests.cs rename to UnitTests/View/BorderTests.cs index 2502b944f..61a607cba 100644 --- a/UnitTests/Core/BorderTests.cs +++ b/UnitTests/View/BorderTests.cs @@ -4,7 +4,7 @@ using Xunit; using Xunit.Abstractions; using Rune = System.Rune; -namespace Terminal.Gui.CoreTests { +namespace Terminal.Gui.ViewTests { public class BorderTests { readonly ITestOutputHelper output; diff --git a/UnitTests/Core/FrameTests.cs b/UnitTests/View/FrameTests.cs similarity index 98% rename from UnitTests/Core/FrameTests.cs rename to UnitTests/View/FrameTests.cs index 831c36354..0a8e529e7 100644 --- a/UnitTests/Core/FrameTests.cs +++ b/UnitTests/View/FrameTests.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Xml.Linq; -using Terminal.Gui.Graphs; using Xunit; using Xunit.Abstractions; //using GraphViewTests = Terminal.Gui.Views.GraphViewTests; @@ -10,7 +9,7 @@ using Xunit.Abstractions; // Alias Console to MockConsole so we don't accidentally use Console using Console = Terminal.Gui.FakeConsole; -namespace Terminal.Gui.CoreTests { +namespace Terminal.Gui.ViewTests { public class FrameTests { readonly ITestOutputHelper output; diff --git a/UnitTests/View/KeyboardTests.cs b/UnitTests/View/KeyboardTests.cs new file mode 100644 index 000000000..db0043ded --- /dev/null +++ b/UnitTests/View/KeyboardTests.cs @@ -0,0 +1,181 @@ +using System; +using Xunit; +using Xunit.Abstractions; +using NStack; + +// Alias Console to MockConsole so we don't accidentally use Console +using Console = Terminal.Gui.FakeConsole; + +namespace Terminal.Gui.ViewTests { + public class KeyboardTests { + readonly ITestOutputHelper output; + + public KeyboardTests (ITestOutputHelper output) + { + this.output = output; + } + + [Fact] + public void KeyPress_Handled_To_True_Prevents_Changes () + { + Application.Init (new FakeDriver ()); + + Console.MockKeyPresses.Push (new ConsoleKeyInfo ('N', ConsoleKey.N, false, false, false)); + + var top = Application.Top; + + var text = new TextField (""); + text.KeyPress += (s, e) => { + e.Handled = true; + Assert.True (e.Handled); + Assert.Equal (Key.N, e.KeyEvent.Key); + }; + top.Add (text); + + Application.Iteration += () => { + Console.MockKeyPresses.Push (new ConsoleKeyInfo ('N', ConsoleKey.N, false, false, false)); + Assert.Equal ("", text.Text); + + Application.RequestStop (); + }; + + Application.Run (); + + // Shutdown must be called to safely clean up Application if Init has been called + Application.Shutdown (); + } + + + [Fact, AutoInitShutdown] + public void KeyDown_And_KeyUp_Events_Must_Called_Before_OnKeyDown_And_OnKeyUp () + { + var keyDown = false; + var keyPress = false; + var keyUp = false; + + var view = new DerivedView (); + view.KeyDown += (s, e) => { + Assert.Equal (Key.a, e.KeyEvent.Key); + Assert.False (keyDown); + Assert.False (view.IsKeyDown); + e.Handled = true; + keyDown = true; + }; + view.KeyPress += (s, e) => { + Assert.Equal (Key.a, e.KeyEvent.Key); + Assert.False (keyPress); + Assert.False (view.IsKeyPress); + e.Handled = true; + keyPress = true; + }; + view.KeyUp += (s, e) => { + Assert.Equal (Key.a, e.KeyEvent.Key); + Assert.False (keyUp); + Assert.False (view.IsKeyUp); + e.Handled = true; + keyUp = true; + }; + + Application.Top.Add (view); + + Console.MockKeyPresses.Push (new ConsoleKeyInfo ('a', ConsoleKey.A, false, false, false)); + + Application.Iteration += () => Application.RequestStop (); + + Assert.True (view.CanFocus); + + Application.Run (); + Application.Shutdown (); + + Assert.True (keyDown); + Assert.True (keyPress); + Assert.True (keyUp); + Assert.False (view.IsKeyDown); + Assert.False (view.IsKeyPress); + Assert.False (view.IsKeyUp); + } + + public class DerivedView : View { + public DerivedView () + { + CanFocus = true; + } + + public bool IsKeyDown { get; set; } + public bool IsKeyPress { get; set; } + public bool IsKeyUp { get; set; } + public override ustring Text { get; set; } + + public override bool OnKeyDown (KeyEvent keyEvent) + { + IsKeyDown = true; + return true; + } + + public override bool ProcessKey (KeyEvent keyEvent) + { + IsKeyPress = true; + return true; + } + + public override bool OnKeyUp (KeyEvent keyEvent) + { + IsKeyUp = true; + return true; + } + } + + [Theory, AutoInitShutdown] + [InlineData (true, false, false)] + [InlineData (true, true, false)] + [InlineData (true, true, true)] + public void KeyDown_And_KeyUp_Events_With_Only_Key_Modifiers (bool shift, bool alt, bool control) + { + var keyDown = false; + var keyPress = false; + var keyUp = false; + + var view = new DerivedView (); + view.KeyDown += (s, e) => { + Assert.Equal (-1, e.KeyEvent.KeyValue); + Assert.Equal (shift, e.KeyEvent.IsShift); + Assert.Equal (alt, e.KeyEvent.IsAlt); + Assert.Equal (control, e.KeyEvent.IsCtrl); + Assert.False (keyDown); + Assert.False (view.IsKeyDown); + keyDown = true; + }; + view.KeyPress += (s, e) => { + keyPress = true; + }; + view.KeyUp += (s, e) => { + Assert.Equal (-1, e.KeyEvent.KeyValue); + Assert.Equal (shift, e.KeyEvent.IsShift); + Assert.Equal (alt, e.KeyEvent.IsAlt); + Assert.Equal (control, e.KeyEvent.IsCtrl); + Assert.False (keyUp); + Assert.False (view.IsKeyUp); + keyUp = true; + }; + + Application.Top.Add (view); + + Console.MockKeyPresses.Push (new ConsoleKeyInfo ('\0', (ConsoleKey)'\0', shift, alt, control)); + + Application.Iteration += () => Application.RequestStop (); + + Assert.True (view.CanFocus); + + Application.Run (); + Application.Shutdown (); + + Assert.True (keyDown); + Assert.False (keyPress); + Assert.True (keyUp); + Assert.True (view.IsKeyDown); + Assert.False (view.IsKeyPress); + Assert.True (view.IsKeyUp); + } + + } +} diff --git a/UnitTests/Core/AbsoluteLayoutTests.cs b/UnitTests/View/Layout/AbsoluteLayoutTests.cs similarity index 99% rename from UnitTests/Core/AbsoluteLayoutTests.cs rename to UnitTests/View/Layout/AbsoluteLayoutTests.cs index b767c07ae..6a631197c 100644 --- a/UnitTests/Core/AbsoluteLayoutTests.cs +++ b/UnitTests/View/Layout/AbsoluteLayoutTests.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Xml.Linq; -using Terminal.Gui.Graphs; using Xunit; using Xunit.Abstractions; //using GraphViewTests = Terminal.Gui.Views.GraphViewTests; @@ -10,7 +9,7 @@ using Xunit.Abstractions; // Alias Console to MockConsole so we don't accidentally use Console using Console = Terminal.Gui.FakeConsole; -namespace Terminal.Gui.CoreTests { +namespace Terminal.Gui.ViewTests { public class AbsoluteLayoutTests { readonly ITestOutputHelper output; diff --git a/UnitTests/Types/DimTests.cs b/UnitTests/View/Layout/DimTests.cs similarity index 99% rename from UnitTests/Types/DimTests.cs rename to UnitTests/View/Layout/DimTests.cs index 590fe7b59..39ecf8b5f 100644 --- a/UnitTests/Types/DimTests.cs +++ b/UnitTests/View/Layout/DimTests.cs @@ -12,11 +12,11 @@ using Xunit.Abstractions; // Alias Console to MockConsole so we don't accidentally use Console using Console = Terminal.Gui.FakeConsole; -namespace Terminal.Gui.TypeTests { - public class DimTests { +namespace Terminal.Gui.ViewTests { + public class LayoutTests_DimTests { readonly ITestOutputHelper output; - public DimTests (ITestOutputHelper output) + public LayoutTests_DimTests (ITestOutputHelper output) { this.output = output; Console.OutputEncoding = System.Text.Encoding.Default; @@ -580,7 +580,7 @@ namespace Terminal.Gui.TypeTests { Assert.Equal (25, t.Frame.Height); Assert.Equal (78, w.Frame.Width); Assert.Equal (23, w.Frame.Height); - // BUGBUG: v2 - this no longer works + // BUGBUG: v2 - this no longer works - see above //Assert.Equal (6, f.Frame.Width); //Assert.Equal (6, f.Frame.Height); Assert.Equal (76, v1.Frame.Width); diff --git a/UnitTests/Core/LayoutTests.cs b/UnitTests/View/Layout/LayoutTests.cs similarity index 99% rename from UnitTests/Core/LayoutTests.cs rename to UnitTests/View/Layout/LayoutTests.cs index 357b7c946..53554d85f 100644 --- a/UnitTests/Core/LayoutTests.cs +++ b/UnitTests/View/Layout/LayoutTests.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Xml.Linq; -using Terminal.Gui.Graphs; using Xunit; using Xunit.Abstractions; //using GraphViewTests = Terminal.Gui.Views.GraphViewTests; @@ -10,7 +9,7 @@ using Xunit.Abstractions; // Alias Console to MockConsole so we don't accidentally use Console using Console = Terminal.Gui.FakeConsole; -namespace Terminal.Gui.CoreTests { +namespace Terminal.Gui.ViewTests { public class LayoutTests { readonly ITestOutputHelper output; @@ -1228,7 +1227,7 @@ Y } [Fact, AutoInitShutdown] - public void AutoSize_True_Equal_Before_And_After_IsInitialized_With_Differents_Orders () + public void AutoSize_True_Equal_Before_And_After_IsInitialized_With_Different_Orders () { var view1 = new View () { Text = "Say Hello view1 你", AutoSize = true, Width = 10, Height = 5 }; var view2 = new View () { Text = "Say Hello view2 你", Width = 10, Height = 5, AutoSize = true }; diff --git a/UnitTests/Types/PosTests.cs b/UnitTests/View/Layout/PosTests.cs similarity index 99% rename from UnitTests/Types/PosTests.cs rename to UnitTests/View/Layout/PosTests.cs index 1ed11a254..1088d10d9 100644 --- a/UnitTests/Types/PosTests.cs +++ b/UnitTests/View/Layout/PosTests.cs @@ -11,11 +11,11 @@ using Xunit.Abstractions; // Alias Console to MockConsole so we don't accidentally use Console using Console = Terminal.Gui.FakeConsole; -namespace Terminal.Gui.TypeTests { - public class PosTests { +namespace Terminal.Gui.ViewTests { + public class LayoutTests_PosTests { readonly ITestOutputHelper output; - public PosTests (ITestOutputHelper output) + public LayoutTests_PosTests (ITestOutputHelper output) { this.output = output; } diff --git a/UnitTests/View/NavigationTests.cs b/UnitTests/View/NavigationTests.cs new file mode 100644 index 000000000..3eb1fe4cf --- /dev/null +++ b/UnitTests/View/NavigationTests.cs @@ -0,0 +1,1084 @@ +using System; +using Xunit; +using Xunit.Abstractions; +using NStack; + +// Alias Console to MockConsole so we don't accidentally use Console +using Console = Terminal.Gui.FakeConsole; + +namespace Terminal.Gui.ViewTests { + public class NavigationTests { + readonly ITestOutputHelper output; + + public NavigationTests (ITestOutputHelper output) + { + this.output = output; + } + + [Fact] + public void FocusNearestView_Ensure_Focus_Ordered () + { + var top = new Toplevel (); + + var win = new Window (); + var winSubview = new View ("WindowSubview") { + CanFocus = true + }; + win.Add (winSubview); + top.Add (win); + + var frm = new FrameView (); + var frmSubview = new View ("FrameSubview") { + CanFocus = true + }; + frm.Add (frmSubview); + top.Add (frm); + + top.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ())); + Assert.Equal ($"WindowSubview", top.MostFocused.Text); + top.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ())); + Assert.Equal ("FrameSubview", top.MostFocused.Text); + top.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ())); + Assert.Equal ($"WindowSubview", top.MostFocused.Text); + + top.ProcessKey (new KeyEvent (Key.BackTab | Key.ShiftMask, new KeyModifiers ())); + Assert.Equal ("FrameSubview", top.MostFocused.Text); + top.ProcessKey (new KeyEvent (Key.BackTab | Key.ShiftMask, new KeyModifiers ())); + Assert.Equal ($"WindowSubview", top.MostFocused.Text); + } + + + [Fact] + public void Subviews_TabIndexes_AreEqual () + { + var r = new View (); + var v1 = new View () { CanFocus = true }; + var v2 = new View () { CanFocus = true }; + var v3 = new View () { CanFocus = true }; + + r.Add (v1, v2, v3); + + Assert.True (r.Subviews.IndexOf (v1) == 0); + Assert.True (r.Subviews.IndexOf (v2) == 1); + Assert.True (r.Subviews.IndexOf (v3) == 2); + + Assert.True (r.TabIndexes.IndexOf (v1) == 0); + Assert.True (r.TabIndexes.IndexOf (v2) == 1); + Assert.True (r.TabIndexes.IndexOf (v3) == 2); + + Assert.Equal (r.Subviews.IndexOf (v1), r.TabIndexes.IndexOf (v1)); + Assert.Equal (r.Subviews.IndexOf (v2), r.TabIndexes.IndexOf (v2)); + Assert.Equal (r.Subviews.IndexOf (v3), r.TabIndexes.IndexOf (v3)); + } + + [Fact] + public void BringSubviewToFront_Subviews_vs_TabIndexes () + { + var r = new View (); + var v1 = new View () { CanFocus = true }; + var v2 = new View () { CanFocus = true }; + var v3 = new View () { CanFocus = true }; + + r.Add (v1, v2, v3); + + r.BringSubviewToFront (v1); + Assert.True (r.Subviews.IndexOf (v1) == 2); + Assert.True (r.Subviews.IndexOf (v2) == 0); + Assert.True (r.Subviews.IndexOf (v3) == 1); + + Assert.True (r.TabIndexes.IndexOf (v1) == 0); + Assert.True (r.TabIndexes.IndexOf (v2) == 1); + Assert.True (r.TabIndexes.IndexOf (v3) == 2); + } + + [Fact] + public void BringSubviewForward_Subviews_vs_TabIndexes () + { + var r = new View (); + var v1 = new View () { CanFocus = true }; + var v2 = new View () { CanFocus = true }; + var v3 = new View () { CanFocus = true }; + + r.Add (v1, v2, v3); + + r.BringSubviewForward (v1); + Assert.True (r.Subviews.IndexOf (v1) == 1); + Assert.True (r.Subviews.IndexOf (v2) == 0); + Assert.True (r.Subviews.IndexOf (v3) == 2); + + Assert.True (r.TabIndexes.IndexOf (v1) == 0); + Assert.True (r.TabIndexes.IndexOf (v2) == 1); + Assert.True (r.TabIndexes.IndexOf (v3) == 2); + } + + [Fact] + public void SendSubviewToBack_Subviews_vs_TabIndexes () + { + var r = new View (); + var v1 = new View () { CanFocus = true }; + var v2 = new View () { CanFocus = true }; + var v3 = new View () { CanFocus = true }; + + r.Add (v1, v2, v3); + + r.SendSubviewToBack (v3); + Assert.True (r.Subviews.IndexOf (v1) == 1); + Assert.True (r.Subviews.IndexOf (v2) == 2); + Assert.True (r.Subviews.IndexOf (v3) == 0); + + Assert.True (r.TabIndexes.IndexOf (v1) == 0); + Assert.True (r.TabIndexes.IndexOf (v2) == 1); + Assert.True (r.TabIndexes.IndexOf (v3) == 2); + } + + [Fact] + public void SendSubviewBackwards_Subviews_vs_TabIndexes () + { + var r = new View (); + var v1 = new View () { CanFocus = true }; + var v2 = new View () { CanFocus = true }; + var v3 = new View () { CanFocus = true }; + + r.Add (v1, v2, v3); + + r.SendSubviewBackwards (v3); + Assert.True (r.Subviews.IndexOf (v1) == 0); + Assert.True (r.Subviews.IndexOf (v2) == 2); + Assert.True (r.Subviews.IndexOf (v3) == 1); + + Assert.True (r.TabIndexes.IndexOf (v1) == 0); + Assert.True (r.TabIndexes.IndexOf (v2) == 1); + Assert.True (r.TabIndexes.IndexOf (v3) == 2); + } + + [Fact] + public void TabIndex_Set_CanFocus_ValidValues () + { + var r = new View (); + var v1 = new View () { CanFocus = true }; + var v2 = new View () { CanFocus = true }; + var v3 = new View () { CanFocus = true }; + + r.Add (v1, v2, v3); + + v1.TabIndex = 1; + Assert.True (r.Subviews.IndexOf (v1) == 0); + Assert.True (r.TabIndexes.IndexOf (v1) == 1); + + v1.TabIndex = 2; + Assert.True (r.Subviews.IndexOf (v1) == 0); + Assert.True (r.TabIndexes.IndexOf (v1) == 2); + } + + [Fact] + public void TabIndex_Set_CanFocus_HigherValues () + { + var r = new View (); + var v1 = new View () { CanFocus = true }; + var v2 = new View () { CanFocus = true }; + var v3 = new View () { CanFocus = true }; + + r.Add (v1, v2, v3); + + v1.TabIndex = 3; + Assert.True (r.Subviews.IndexOf (v1) == 0); + Assert.True (r.TabIndexes.IndexOf (v1) == 2); + } + + [Fact] + public void TabIndex_Set_CanFocus_LowerValues () + { + var r = new View (); + var v1 = new View () { CanFocus = true }; + var v2 = new View () { CanFocus = true }; + var v3 = new View () { CanFocus = true }; + + r.Add (v1, v2, v3); + + v1.TabIndex = -1; + Assert.True (r.Subviews.IndexOf (v1) == 0); + Assert.True (r.TabIndexes.IndexOf (v1) == 0); + } + + [Fact] + public void TabIndex_Set_CanFocus_False () + { + var r = new View (); + var v1 = new View () { CanFocus = true }; + var v2 = new View () { CanFocus = true }; + var v3 = new View () { CanFocus = true }; + + r.Add (v1, v2, v3); + + v1.CanFocus = false; + v1.TabIndex = 0; + Assert.True (r.Subviews.IndexOf (v1) == 0); + Assert.True (r.TabIndexes.IndexOf (v1) == 0); + Assert.Equal (-1, v1.TabIndex); + } + + [Fact] + public void TabIndex_Set_CanFocus_False_To_True () + { + var r = new View (); + var v1 = new View (); + var v2 = new View () { CanFocus = true }; + var v3 = new View () { CanFocus = true }; + + r.Add (v1, v2, v3); + + v1.CanFocus = true; + v1.TabIndex = 1; + Assert.True (r.Subviews.IndexOf (v1) == 0); + Assert.True (r.TabIndexes.IndexOf (v1) == 1); + } + + [Fact] + public void TabStop_And_CanFocus_Are_All_True () + { + var r = new View (); + var v1 = new View () { CanFocus = true }; + var v2 = new View () { CanFocus = true }; + var v3 = new View () { CanFocus = true }; + + r.Add (v1, v2, v3); + + r.FocusNext (); + Assert.True (v1.HasFocus); + Assert.False (v2.HasFocus); + Assert.False (v3.HasFocus); + r.FocusNext (); + Assert.False (v1.HasFocus); + Assert.True (v2.HasFocus); + Assert.False (v3.HasFocus); + r.FocusNext (); + Assert.False (v1.HasFocus); + Assert.False (v2.HasFocus); + Assert.True (v3.HasFocus); + } + + [Fact] + public void TabStop_Are_All_True_And_CanFocus_Are_All_False () + { + var r = new View (); + var v1 = new View (); + var v2 = new View (); + var v3 = new View (); + + r.Add (v1, v2, v3); + + r.FocusNext (); + Assert.False (v1.HasFocus); + Assert.False (v2.HasFocus); + Assert.False (v3.HasFocus); + r.FocusNext (); + Assert.False (v1.HasFocus); + Assert.False (v2.HasFocus); + Assert.False (v3.HasFocus); + r.FocusNext (); + Assert.False (v1.HasFocus); + Assert.False (v2.HasFocus); + Assert.False (v3.HasFocus); + } + + [Fact] + public void TabStop_Are_All_False_And_CanFocus_Are_All_True () + { + var r = new View (); + var v1 = new View () { CanFocus = true, TabStop = false }; + var v2 = new View () { CanFocus = true, TabStop = false }; + var v3 = new View () { CanFocus = true, TabStop = false }; + + r.Add (v1, v2, v3); + + r.FocusNext (); + Assert.False (v1.HasFocus); + Assert.False (v2.HasFocus); + Assert.False (v3.HasFocus); + r.FocusNext (); + Assert.False (v1.HasFocus); + Assert.False (v2.HasFocus); + Assert.False (v3.HasFocus); + r.FocusNext (); + Assert.False (v1.HasFocus); + Assert.False (v2.HasFocus); + Assert.False (v3.HasFocus); + } + + [Fact] + public void TabStop_And_CanFocus_Mixed_And_BothFalse () + { + var r = new View (); + var v1 = new View () { CanFocus = true, TabStop = false }; + var v2 = new View () { CanFocus = false, TabStop = true }; + var v3 = new View () { CanFocus = false, TabStop = false }; + + r.Add (v1, v2, v3); + + r.FocusNext (); + Assert.False (v1.HasFocus); + Assert.False (v2.HasFocus); + Assert.False (v3.HasFocus); + r.FocusNext (); + Assert.False (v1.HasFocus); + Assert.False (v2.HasFocus); + Assert.False (v3.HasFocus); + r.FocusNext (); + Assert.False (v1.HasFocus); + Assert.False (v2.HasFocus); + Assert.False (v3.HasFocus); + } + + [Fact] + public void TabStop_All_True_And_Changing_CanFocus_Later () + { + var r = new View (); + var v1 = new View (); + var v2 = new View (); + var v3 = new View (); + + r.Add (v1, v2, v3); + + r.FocusNext (); + Assert.False (v1.HasFocus); + Assert.False (v2.HasFocus); + Assert.False (v3.HasFocus); + + v1.CanFocus = true; + r.FocusNext (); + Assert.True (v1.HasFocus); + Assert.False (v2.HasFocus); + Assert.False (v3.HasFocus); + v2.CanFocus = true; + r.FocusNext (); + Assert.False (v1.HasFocus); + Assert.True (v2.HasFocus); + Assert.False (v3.HasFocus); + v3.CanFocus = true; + r.FocusNext (); + Assert.False (v1.HasFocus); + Assert.False (v2.HasFocus); + Assert.True (v3.HasFocus); + } + + [Fact] + public void TabStop_All_False_And_All_True_And_Changing_TabStop_Later () + { + var r = new View (); + var v1 = new View () { CanFocus = true, TabStop = false }; + var v2 = new View () { CanFocus = true, TabStop = false }; + var v3 = new View () { CanFocus = true, TabStop = false }; + + r.Add (v1, v2, v3); + + r.FocusNext (); + Assert.False (v1.HasFocus); + Assert.False (v2.HasFocus); + Assert.False (v3.HasFocus); + + v1.TabStop = true; + r.FocusNext (); + Assert.True (v1.HasFocus); + Assert.False (v2.HasFocus); + Assert.False (v3.HasFocus); + v2.TabStop = true; + r.FocusNext (); + Assert.False (v1.HasFocus); + Assert.True (v2.HasFocus); + Assert.False (v3.HasFocus); + v3.TabStop = true; + r.FocusNext (); + Assert.False (v1.HasFocus); + Assert.False (v2.HasFocus); + Assert.True (v3.HasFocus); + } + + [Fact] + public void CanFocus_Set_Changes_TabIndex_And_TabStop () + { + var r = new View (); + var v1 = new View ("1"); + var v2 = new View ("2"); + var v3 = new View ("3"); + + r.Add (v1, v2, v3); + + v2.CanFocus = true; + Assert.Equal (r.TabIndexes.IndexOf (v2), v2.TabIndex); + Assert.Equal (0, v2.TabIndex); + Assert.True (v2.TabStop); + + v1.CanFocus = true; + Assert.Equal (r.TabIndexes.IndexOf (v1), v1.TabIndex); + Assert.Equal (1, v1.TabIndex); + Assert.True (v1.TabStop); + + v1.TabIndex = 2; + Assert.Equal (r.TabIndexes.IndexOf (v1), v1.TabIndex); + Assert.Equal (1, v1.TabIndex); + v3.CanFocus = true; + Assert.Equal (r.TabIndexes.IndexOf (v1), v1.TabIndex); + Assert.Equal (1, v1.TabIndex); + Assert.Equal (r.TabIndexes.IndexOf (v3), v3.TabIndex); + Assert.Equal (2, v3.TabIndex); + Assert.True (v3.TabStop); + + v2.CanFocus = false; + Assert.Equal (r.TabIndexes.IndexOf (v1), v1.TabIndex); + Assert.Equal (1, v1.TabIndex); + Assert.True (v1.TabStop); + Assert.NotEqual (r.TabIndexes.IndexOf (v2), v2.TabIndex); + Assert.Equal (-1, v2.TabIndex); + Assert.False (v2.TabStop); + Assert.Equal (r.TabIndexes.IndexOf (v3), v3.TabIndex); + Assert.Equal (2, v3.TabIndex); + Assert.True (v3.TabStop); + } + + [Fact] + [AutoInitShutdown] + public void CanFocus_Faced_With_Container () + { + var t = new Toplevel (); + var w = new Window (); + var f = new FrameView (); + var v = new View () { CanFocus = true }; + f.Add (v); + w.Add (f); + t.Add (w); + + Assert.True (t.CanFocus); + Assert.True (w.CanFocus); + Assert.True (f.CanFocus); + Assert.True (v.CanFocus); + + f.CanFocus = false; + Assert.False (f.CanFocus); + Assert.True (v.CanFocus); + + v.CanFocus = false; + Assert.False (f.CanFocus); + Assert.False (v.CanFocus); + + v.CanFocus = true; + Assert.False (f.CanFocus); + Assert.True (v.CanFocus); + } + + [Fact] + public void CanFocus_Faced_With_Container_Before_Run () + { + Application.Init (new FakeDriver ()); + + var t = Application.Top; + + var w = new Window ("w"); + var f = new FrameView ("f"); + var v = new View ("v") { CanFocus = true }; + f.Add (v); + w.Add (f); + t.Add (w); + + Assert.True (t.CanFocus); + Assert.True (w.CanFocus); + Assert.True (f.CanFocus); + Assert.True (v.CanFocus); + + f.CanFocus = false; + Assert.False (f.CanFocus); + Assert.True (v.CanFocus); + + v.CanFocus = false; + Assert.False (f.CanFocus); + Assert.False (v.CanFocus); + + v.CanFocus = true; + Assert.False (f.CanFocus); + Assert.True (v.CanFocus); + + Application.Iteration += () => Application.RequestStop (); + + Application.Run (); + Application.Shutdown (); + } + + [Fact] + public void CanFocus_Faced_With_Container_After_Run () + { + Application.Init (new FakeDriver ()); + + var t = Application.Top; + + var w = new Window ("w"); + var f = new FrameView ("f"); + var v = new View ("v") { CanFocus = true }; + f.Add (v); + w.Add (f); + t.Add (w); + + t.Ready += (s, e) => { + Assert.True (t.CanFocus); + Assert.True (w.CanFocus); + Assert.True (f.CanFocus); + Assert.True (v.CanFocus); + + f.CanFocus = false; + Assert.False (f.CanFocus); + Assert.False (v.CanFocus); + + v.CanFocus = false; + Assert.False (f.CanFocus); + Assert.False (v.CanFocus); + + Assert.Throws (() => v.CanFocus = true); + Assert.False (f.CanFocus); + Assert.False (v.CanFocus); + + f.CanFocus = true; + Assert.True (f.CanFocus); + Assert.True (v.CanFocus); + }; + + Application.Iteration += () => Application.RequestStop (); + + Application.Run (); + Application.Shutdown (); + } + + [Fact] + public void CanFocus_Container_ToFalse_Turns_All_Subviews_ToFalse_Too () + { + Application.Init (new FakeDriver ()); + + var t = Application.Top; + + var w = new Window ("w"); + var f = new FrameView ("f"); + var v1 = new View ("v1") { CanFocus = true }; + var v2 = new View ("v2") { CanFocus = true }; + f.Add (v1, v2); + w.Add (f); + t.Add (w); + + t.Ready += (s, e) => { + Assert.True (t.CanFocus); + Assert.True (w.CanFocus); + Assert.True (f.CanFocus); + Assert.True (v1.CanFocus); + Assert.True (v2.CanFocus); + + w.CanFocus = false; + Assert.False (w.CanFocus); + Assert.False (f.CanFocus); + Assert.False (v1.CanFocus); + Assert.False (v2.CanFocus); + }; + + Application.Iteration += () => Application.RequestStop (); + + Application.Run (); + Application.Shutdown (); + } + + [Fact] + public void CanFocus_Container_Toggling_All_Subviews_To_Old_Value_When_Is_True () + { + Application.Init (new FakeDriver ()); + + var t = Application.Top; + + var w = new Window ("w"); + var f = new FrameView ("f"); + var v1 = new View ("v1"); + var v2 = new View ("v2") { CanFocus = true }; + f.Add (v1, v2); + w.Add (f); + t.Add (w); + + t.Ready += (s, e) => { + Assert.True (t.CanFocus); + Assert.True (w.CanFocus); + Assert.True (f.CanFocus); + Assert.False (v1.CanFocus); + Assert.True (v2.CanFocus); + + w.CanFocus = false; + Assert.False (w.CanFocus); + Assert.False (f.CanFocus); + Assert.False (v1.CanFocus); + Assert.False (v2.CanFocus); + + w.CanFocus = true; + Assert.True (w.CanFocus); + Assert.True (f.CanFocus); + Assert.False (v1.CanFocus); + Assert.True (v2.CanFocus); + }; + + Application.Iteration += () => Application.RequestStop (); + + Application.Run (); + Application.Shutdown (); + } + + + [Fact] + public void Navigation_With_Null_Focused_View () + { + // Non-regression test for #882 (NullReferenceException during keyboard navigation when Focused is null) + + Application.Init (new FakeDriver ()); + + Application.Top.Ready += (s, e) => { + Assert.Null (Application.Top.Focused); + }; + + // Keyboard navigation with tab + Console.MockKeyPresses.Push (new ConsoleKeyInfo ('\t', ConsoleKey.Tab, false, false, false)); + + Application.Iteration += () => Application.RequestStop (); + + Application.Run (); + Application.Shutdown (); + } + + [Fact] + [AutoInitShutdown] + public void Enabled_False_Sets_HasFocus_To_False () + { + var wasClicked = false; + var view = new Button ("Click Me"); + view.Clicked += (s, e) => wasClicked = !wasClicked; + Application.Top.Add (view); + + view.ProcessKey (new KeyEvent (Key.Enter, null)); + Assert.True (wasClicked); + view.MouseEvent (new MouseEvent () { Flags = MouseFlags.Button1Clicked }); + Assert.False (wasClicked); + Assert.True (view.Enabled); + Assert.True (view.CanFocus); + Assert.True (view.HasFocus); + + view.Enabled = false; + view.ProcessKey (new KeyEvent (Key.Enter, null)); + Assert.False (wasClicked); + view.MouseEvent (new MouseEvent () { Flags = MouseFlags.Button1Clicked }); + Assert.False (wasClicked); + Assert.False (view.Enabled); + Assert.True (view.CanFocus); + Assert.False (view.HasFocus); + view.SetFocus (); + Assert.False (view.HasFocus); + } + + [Fact] + [AutoInitShutdown] + public void Enabled_Sets_Also_Sets_Subviews () + { + var wasClicked = false; + var button = new Button ("Click Me"); + button.Clicked += (s, e) => wasClicked = !wasClicked; + var win = new Window () { Width = Dim.Fill (), Height = Dim.Fill () }; + win.Add (button); + Application.Top.Add (win); + + var iterations = 0; + + Application.Iteration += () => { + iterations++; + + button.ProcessKey (new KeyEvent (Key.Enter, null)); + Assert.True (wasClicked); + button.MouseEvent (new MouseEvent () { Flags = MouseFlags.Button1Clicked }); + Assert.False (wasClicked); + Assert.True (button.Enabled); + Assert.True (button.CanFocus); + Assert.True (button.HasFocus); + Assert.True (win.Enabled); + Assert.True (win.CanFocus); + Assert.True (win.HasFocus); + + win.Enabled = false; + button.ProcessKey (new KeyEvent (Key.Enter, null)); + Assert.False (wasClicked); + button.MouseEvent (new MouseEvent () { Flags = MouseFlags.Button1Clicked }); + Assert.False (wasClicked); + Assert.False (button.Enabled); + Assert.True (button.CanFocus); + Assert.False (button.HasFocus); + Assert.False (win.Enabled); + Assert.True (win.CanFocus); + Assert.False (win.HasFocus); + button.SetFocus (); + Assert.False (button.HasFocus); + Assert.False (win.HasFocus); + win.SetFocus (); + Assert.False (button.HasFocus); + Assert.False (win.HasFocus); + + win.Enabled = true; + win.FocusFirst (); + Assert.True (button.HasFocus); + Assert.True (win.HasFocus); + + Application.RequestStop (); + }; + + Application.Run (); + + Assert.Equal (1, iterations); + } + + + [Fact] + [AutoInitShutdown] + public void CanFocus_Sets_To_False_Does_Not_Sets_HasFocus_To_True () + { + var view = new View () { CanFocus = true }; + var win = new Window () { Width = Dim.Fill (), Height = Dim.Fill () }; + win.Add (view); + Application.Top.Add (win); + Application.Begin (Application.Top); + + Assert.True (view.CanFocus); + Assert.True (view.HasFocus); + + view.CanFocus = false; + Assert.False (view.CanFocus); + Assert.False (view.HasFocus); + Assert.Null (Application.Current.Focused); + Assert.Null (Application.Current.MostFocused); + } + + [Fact] + [AutoInitShutdown] + public void CanFocus_Sets_To_False_On_Single_View_Focus_View_On_Another_Toplevel () + { + var view1 = new View () { Id = "view1", Width = 10, Height = 1, CanFocus = true }; + var win1 = new Window () { Id = "win1", Width = Dim.Percent (50), Height = Dim.Fill () }; + win1.Add (view1); + var view2 = new View () { Id = "view2", Width = 20, Height = 2, CanFocus = true }; + var win2 = new Window () { Id = "win2", X = Pos.Right (win1), Width = Dim.Fill (), Height = Dim.Fill () }; + win2.Add (view2); + Application.Top.Add (win1, win2); + Application.Begin (Application.Top); + + Assert.True (view1.CanFocus); + Assert.True (view1.HasFocus); + Assert.True (view2.CanFocus); + Assert.False (view2.HasFocus); + + view1.CanFocus = false; + Assert.False (view1.CanFocus); + Assert.False (view1.HasFocus); + Assert.Equal (win2, Application.Current.Focused); + Assert.Equal (view2, Application.Current.MostFocused); + } + + [Fact] + [AutoInitShutdown] + public void CanFocus_Sets_To_False_With_Two_Views_Focus_Another_View_On_The_Same_Toplevel () + { + var view1 = new View () { Id = "view1", Width = 10, Height = 1, CanFocus = true }; + var view12 = new View () { Id = "view12", Y = 5, Width = 10, Height = 1, CanFocus = true }; + var win1 = new Window () { Id = "win1", Width = Dim.Percent (50), Height = Dim.Fill () }; + win1.Add (view1, view12); + var view2 = new View () { Id = "view2", Width = 20, Height = 2, CanFocus = true }; + var win2 = new Window () { Id = "win2", X = Pos.Right (win1), Width = Dim.Fill (), Height = Dim.Fill () }; + win2.Add (view2); + Application.Top.Add (win1, win2); + Application.Begin (Application.Top); + + Assert.True (view1.CanFocus); + Assert.True (view1.HasFocus); + Assert.True (view2.CanFocus); + Assert.False (view2.HasFocus); + + view1.CanFocus = false; + Assert.False (view1.CanFocus); + Assert.False (view1.HasFocus); + Assert.Equal (win1, Application.Current.Focused); + Assert.Equal (view12, Application.Current.MostFocused); + } + + [Fact] + [AutoInitShutdown] + public void CanFocus_Sets_To_False_On_Toplevel_Focus_View_On_Another_Toplevel () + { + var view1 = new View () { Id = "view1", Width = 10, Height = 1, CanFocus = true }; + var win1 = new Window () { Id = "win1", Width = Dim.Percent (50), Height = Dim.Fill () }; + win1.Add (view1); + var view2 = new View () { Id = "view2", Width = 20, Height = 2, CanFocus = true }; + var win2 = new Window () { Id = "win2", X = Pos.Right (win1), Width = Dim.Fill (), Height = Dim.Fill () }; + win2.Add (view2); + Application.Top.Add (win1, win2); + Application.Begin (Application.Top); + + Assert.True (view1.CanFocus); + Assert.True (view1.HasFocus); + Assert.True (view2.CanFocus); + Assert.False (view2.HasFocus); + + win1.CanFocus = false; + Assert.False (view1.CanFocus); + Assert.False (view1.HasFocus); + Assert.False (win1.CanFocus); + Assert.False (win1.HasFocus); + Assert.Equal (win2, Application.Current.Focused); + Assert.Equal (view2, Application.Current.MostFocused); + } + + [Fact] + [AutoInitShutdown] + public void ProcessHotKey_Will_Invoke_ProcessKey_Only_For_The_MostFocused_With_Top_KeyPress_Event () + { + var sbQuiting = false; + var tfQuiting = false; + var topQuiting = false; + var sb = new StatusBar (new StatusItem [] { + new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => sbQuiting = true ) + }); + var tf = new TextField (); + tf.KeyPress += Tf_KeyPress; + + void Tf_KeyPress (object sender, KeyEventEventArgs obj) + { + if (obj.KeyEvent.Key == (Key.Q | Key.CtrlMask)) { + obj.Handled = tfQuiting = true; + } + } + + var win = new Window (); + win.Add (sb, tf); + var top = Application.Top; + top.KeyPress += Top_KeyPress; + + void Top_KeyPress (object sender, KeyEventEventArgs obj) + { + if (obj.KeyEvent.Key == (Key.Q | Key.CtrlMask)) { + obj.Handled = topQuiting = true; + } + } + + top.Add (win); + Application.Begin (top); + + Assert.False (sbQuiting); + Assert.False (tfQuiting); + Assert.False (topQuiting); + + Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true); + Assert.False (sbQuiting); + Assert.True (tfQuiting); + Assert.False (topQuiting); + + tf.KeyPress -= Tf_KeyPress; + tfQuiting = false; + Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true); + Application.MainLoop.MainIteration (); + Assert.True (sbQuiting); + Assert.False (tfQuiting); + Assert.False (topQuiting); + + sb.RemoveItem (0); + sbQuiting = false; + Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true); + Application.MainLoop.MainIteration (); + Assert.False (sbQuiting); + Assert.False (tfQuiting); + Assert.True (topQuiting); + } + + [Fact] + [AutoInitShutdown] + public void ProcessHotKey_Will_Invoke_ProcessKey_Only_For_The_MostFocused_Without_Top_KeyPress_Event () + { + var sbQuiting = false; + var tfQuiting = false; + var sb = new StatusBar (new StatusItem [] { + new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => sbQuiting = true ) + }); + var tf = new TextField (); + tf.KeyPress += Tf_KeyPress; + + void Tf_KeyPress (object sender, KeyEventEventArgs obj) + { + if (obj.KeyEvent.Key == (Key.Q | Key.CtrlMask)) { + obj.Handled = tfQuiting = true; + } + } + + var win = new Window (); + win.Add (sb, tf); + var top = Application.Top; + top.Add (win); + Application.Begin (top); + + Assert.False (sbQuiting); + Assert.False (tfQuiting); + + Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true); + Assert.False (sbQuiting); + Assert.True (tfQuiting); + + tf.KeyPress -= Tf_KeyPress; + tfQuiting = false; + Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true); + Application.MainLoop.MainIteration (); + Assert.True (sbQuiting); + Assert.False (tfQuiting); + } + + [Fact] + [AutoInitShutdown] + public void WindowDispose_CanFocusProblem () + { + // Arrange + Application.Init (); + using var top = Toplevel.Create (); + using var view = new View ( + x: 0, + y: 1, + text: nameof (WindowDispose_CanFocusProblem)); + using var window = new Window (); + top.Add (window); + window.Add (view); + + // Act + Application.Begin (top); + Application.Shutdown (); + + // Assert does Not throw NullReferenceException + top.SetFocus (); + } + + [Fact, AutoInitShutdown] + public void SetHasFocus_Do_Not_Throws_If_OnLeave_Remove_Focused_Changing_To_Null () + { + var view1Leave = false; + var subView1Leave = false; + var subView1subView1Leave = false; + var top = Application.Top; + var view1 = new View { CanFocus = true }; + var subView1 = new View { CanFocus = true }; + var subView1subView1 = new View { CanFocus = true }; + view1.Leave += (s, e) => { + view1Leave = true; + }; + subView1.Leave += (s, e) => { + subView1.Remove (subView1subView1); + subView1Leave = true; + }; + view1.Add (subView1); + subView1subView1.Leave += (s, e) => { + // This is never invoked + subView1subView1Leave = true; + }; + subView1.Add (subView1subView1); + var view2 = new View { CanFocus = true }; + top.Add (view1, view2); + Application.Begin (top); + + view2.SetFocus (); + Assert.True (view1Leave); + Assert.True (subView1Leave); + Assert.False (subView1subView1Leave); + } + + [Fact, AutoInitShutdown] + public void Remove_Does_Not_Change_Focus () + { + Assert.True (Application.Top.CanFocus); + Assert.False (Application.Top.HasFocus); + + var container = new View () { Width = 10, Height = 10 }; + var leave = false; + container.Leave += (s, e) => leave = true; + Assert.False (container.CanFocus); + var child = new View () { Width = Dim.Fill (), Height = Dim.Fill (), CanFocus = true }; + container.Add (child); + + Assert.True (container.CanFocus); + Assert.False (container.HasFocus); + Assert.True (child.CanFocus); + Assert.False (child.HasFocus); + + Application.Top.Add (container); + Application.Begin (Application.Top); + + Assert.True (Application.Top.CanFocus); + Assert.True (Application.Top.HasFocus); + Assert.True (container.CanFocus); + Assert.True (container.HasFocus); + Assert.True (child.CanFocus); + Assert.True (child.HasFocus); + + container.Remove (child); + child.Dispose (); + child = null; + Assert.True (Application.Top.HasFocus); + Assert.True (container.CanFocus); + Assert.True (container.HasFocus); + Assert.Null (child); + Assert.False (leave); + } + + [Fact, AutoInitShutdown] + public void SetFocus_View_With_Null_Superview_Does_Not_Throw_Exception () + { + Assert.True (Application.Top.CanFocus); + Assert.False (Application.Top.HasFocus); + + var exception = Record.Exception (Application.Top.SetFocus); + Assert.Null (exception); + Assert.True (Application.Top.CanFocus); + Assert.True (Application.Top.HasFocus); + } + + [Fact, AutoInitShutdown] + public void FocusNext_Does_Not_Throws_If_A_View_Was_Removed_From_The_Collection () + { + var top1 = Application.Top; + var view1 = new View () { Id = "view1", Width = 10, Height = 5, CanFocus = true }; + var top2 = new Toplevel () { Id = "top2", Y = 1, Width = 10, Height = 5 }; + var view2 = new View () { Id = "view2", Y = 1, Width = 10, Height = 5, CanFocus = true }; + View view3 = null; + var removed = false; + view2.Enter += (s, e) => { + if (!removed) { + removed = true; + view3 = new View () { Id = "view3", Y = 1, Width = 10, Height = 5 }; + Application.Current.Add (view3); + Application.Current.BringSubviewToFront (view3); + Assert.False (view3.HasFocus); + } + }; + view2.Leave += (s, e) => { + Application.Current.Remove (view3); + view3.Dispose (); + view3 = null; + }; + top2.Add (view2); + top1.Add (view1, top2); + Application.Begin (top1); + + Assert.True (top1.HasFocus); + Assert.True (view1.HasFocus); + Assert.False (view2.HasFocus); + Assert.False (removed); + Assert.Null (view3); + + Assert.True (top1.ProcessKey (new KeyEvent (Key.Tab | Key.CtrlMask, new KeyModifiers { Ctrl = true }))); + Assert.True (top1.HasFocus); + Assert.False (view1.HasFocus); + Assert.True (view2.HasFocus); + Assert.True (removed); + Assert.NotNull (view3); + + var exception = Record.Exception (() => top1.ProcessKey (new KeyEvent (Key.Tab | Key.CtrlMask, new KeyModifiers { Ctrl = true }))); + Assert.Null (exception); + Assert.True (removed); + Assert.Null (view3); + } + } +} diff --git a/UnitTests/View/TitleTests.cs b/UnitTests/View/TitleTests.cs new file mode 100644 index 000000000..5ea688698 --- /dev/null +++ b/UnitTests/View/TitleTests.cs @@ -0,0 +1,74 @@ +using NStack; +using System; +using System.Collections.Generic; +using System.Xml.Linq; +using Xunit; +using Xunit.Abstractions; +//using GraphViewTests = Terminal.Gui.Views.GraphViewTests; + +// Alias Console to MockConsole so we don't accidentally use Console +using Console = Terminal.Gui.FakeConsole; + +namespace Terminal.Gui.ViewTests { + public class TitleTests { + readonly ITestOutputHelper output; + + public TitleTests (ITestOutputHelper output) + { + this.output = output; + } + + [Fact] + public void Set_Title_Fires_TitleChanging () + { + var r = new View (); + Assert.Equal (ustring.Empty, r.Title); + + string expectedOld = null; + string expectedDuring = null; + string expectedAfter = null; + bool cancel = false; + r.TitleChanging += (s, args) => { + Assert.Equal (expectedOld, args.OldTitle); + Assert.Equal (expectedDuring, args.NewTitle); + args.Cancel = cancel; + }; + + expectedOld = string.Empty; + r.Title = expectedDuring = expectedAfter = "title"; + Assert.Equal (expectedAfter, r.Title.ToString ()); + + expectedOld = r.Title.ToString (); + r.Title = expectedDuring = expectedAfter = "a different title"; + Assert.Equal (expectedAfter, r.Title.ToString ()); + + // Now setup cancelling the change and change it back to "title" + cancel = true; + expectedOld = r.Title.ToString (); + r.Title = expectedDuring = "title"; + Assert.Equal (expectedAfter, r.Title.ToString ()); + r.Dispose (); + + } + + [Fact] + public void Set_Title_Fires_TitleChanged () + { + var r = new View (); + Assert.Equal (ustring.Empty, r.Title); + + string expectedOld = null; + string expected = null; + r.TitleChanged += (s, args) => { + Assert.Equal (expectedOld, args.OldTitle); + Assert.Equal (r.Title, args.NewTitle); + }; + + expected = "title"; + expectedOld = r.Title.ToString (); + r.Title = expected; + Assert.Equal (expected, r.Title.ToString ()); + } + + } +} diff --git a/UnitTests/View/ViewTests.cs b/UnitTests/View/ViewTests.cs new file mode 100644 index 000000000..f9bff4018 --- /dev/null +++ b/UnitTests/View/ViewTests.cs @@ -0,0 +1,1550 @@ +using System; +using Xunit; +using Xunit.Abstractions; +using NStack; + +// Alias Console to MockConsole so we don't accidentally use Console +using Console = Terminal.Gui.FakeConsole; + +namespace Terminal.Gui.ViewTests { + public class ViewTests { + readonly ITestOutputHelper output; + + public ViewTests (ITestOutputHelper output) + { + this.output = output; + } + + [Fact] + public void New_Initializes () + { + // Parameterless + var r = new View (); + Assert.NotNull (r); + Assert.Equal (LayoutStyle.Computed, r.LayoutStyle); + Assert.Equal ("View()({X=0,Y=0,Width=0,Height=0})", r.ToString ()); + Assert.False (r.CanFocus); + Assert.False (r.HasFocus); + Assert.Equal (new Rect (0, 0, 0, 0), r.Bounds); + Assert.Equal (new Rect (0, 0, 0, 0), r.Frame); + Assert.Null (r.Focused); + Assert.Null (r.ColorScheme); + Assert.Null (r.Width); + Assert.Null (r.Height); + Assert.Null (r.X); + Assert.Null (r.Y); + Assert.False (r.IsCurrentTop); + Assert.Empty (r.Id); + Assert.Empty (r.Subviews); + Assert.False (r.WantContinuousButtonPressed); + Assert.False (r.WantMousePositionReports); + Assert.Null (r.SuperView); + Assert.Null (r.MostFocused); + Assert.Equal (TextDirection.LeftRight_TopBottom, r.TextDirection); + + // Empty Rect + r = new View (Rect.Empty); + Assert.NotNull (r); + Assert.Equal (LayoutStyle.Absolute, r.LayoutStyle); + Assert.Equal ("View()({X=0,Y=0,Width=0,Height=0})", r.ToString ()); + Assert.False (r.CanFocus); + Assert.False (r.HasFocus); + Assert.Equal (new Rect (0, 0, 0, 0), r.Bounds); + Assert.Equal (new Rect (0, 0, 0, 0), r.Frame); + Assert.Null (r.Focused); + Assert.Null (r.ColorScheme); + Assert.Null (r.Width); // All view Dim are initialized now in the IsAdded setter, + Assert.Null (r.Height); // avoiding Dim errors. + Assert.Null (r.X); // All view Pos are initialized now in the IsAdded setter, + Assert.Null (r.Y); // avoiding Pos errors. + Assert.False (r.IsCurrentTop); + Assert.Empty (r.Id); + Assert.Empty (r.Subviews); + Assert.False (r.WantContinuousButtonPressed); + Assert.False (r.WantMousePositionReports); + Assert.Null (r.SuperView); + Assert.Null (r.MostFocused); + Assert.Equal (TextDirection.LeftRight_TopBottom, r.TextDirection); + + // Rect with values + r = new View (new Rect (1, 2, 3, 4)); + Assert.NotNull (r); + Assert.Equal (LayoutStyle.Absolute, r.LayoutStyle); + Assert.Equal ("View()({X=1,Y=2,Width=3,Height=4})", r.ToString ()); + Assert.False (r.CanFocus); + Assert.False (r.HasFocus); + Assert.Equal (new Rect (0, 0, 3, 4), r.Bounds); + Assert.Equal (new Rect (1, 2, 3, 4), r.Frame); + Assert.Null (r.Focused); + Assert.Null (r.ColorScheme); + Assert.Null (r.Width); + Assert.Null (r.Height); + Assert.Null (r.X); + Assert.Null (r.Y); + Assert.False (r.IsCurrentTop); + Assert.Empty (r.Id); + Assert.Empty (r.Subviews); + Assert.False (r.WantContinuousButtonPressed); + Assert.False (r.WantMousePositionReports); + Assert.Null (r.SuperView); + Assert.Null (r.MostFocused); + Assert.Equal (TextDirection.LeftRight_TopBottom, r.TextDirection); + + // Initializes a view with a vertical direction + r = new View ("Vertical View", TextDirection.TopBottom_LeftRight); + Assert.NotNull (r); + Assert.Equal (LayoutStyle.Computed, r.LayoutStyle); + Assert.Equal ("View(Vertical View)({X=0,Y=0,Width=1,Height=13})", r.ToString ()); + Assert.False (r.CanFocus); + Assert.False (r.HasFocus); + Assert.Equal (new Rect (0, 0, 1, 13), r.Bounds); + Assert.Equal (new Rect (0, 0, 1, 13), r.Frame); + Assert.Null (r.Focused); + Assert.Null (r.ColorScheme); + Assert.Null (r.Width); // All view Dim are initialized now in the IsAdded setter, + Assert.Null (r.Height); // avoiding Dim errors. + Assert.Null (r.X); // All view Pos are initialized now in the IsAdded setter, + Assert.Null (r.Y); // avoiding Pos errors. + Assert.False (r.IsCurrentTop); + Assert.Equal ("Vertical View", r.Id); + Assert.Empty (r.Subviews); + Assert.False (r.WantContinuousButtonPressed); + Assert.False (r.WantMousePositionReports); + Assert.Null (r.SuperView); + Assert.Null (r.MostFocused); + Assert.Equal (TextDirection.TopBottom_LeftRight, r.TextDirection); + + } + + [Fact] + public void New_Methods_Return_False () + { + var r = new View (); + + Assert.False (r.ProcessKey (new KeyEvent () { Key = Key.Unknown })); + Assert.False (r.ProcessHotKey (new KeyEvent () { Key = Key.Unknown })); + Assert.False (r.ProcessColdKey (new KeyEvent () { Key = Key.Unknown })); + Assert.False (r.OnKeyDown (new KeyEvent () { Key = Key.Unknown })); + Assert.False (r.OnKeyUp (new KeyEvent () { Key = Key.Unknown })); + Assert.False (r.MouseEvent (new MouseEvent () { Flags = MouseFlags.AllEvents })); + Assert.False (r.OnMouseEnter (new MouseEvent () { Flags = MouseFlags.AllEvents })); + Assert.False (r.OnMouseLeave (new MouseEvent () { Flags = MouseFlags.AllEvents })); + Assert.False (r.OnEnter (new View ())); + Assert.False (r.OnLeave (new View ())); + + // TODO: Add more + } + + + [Fact] + public void View_With_No_Difference_Between_An_Object_Initializer_And_A_Constructor () + { + // Object Initializer + var view = new View () { + X = 1, + Y = 2, + Width = 3, + Height = 4 + }; + var super = new View (new Rect (0, 0, 10, 10)); + super.Add (view); + super.BeginInit (); + super.EndInit (); + super.LayoutSubviews (); + + Assert.Equal (1, view.X); + Assert.Equal (2, view.Y); + Assert.Equal (3, view.Width); + Assert.Equal (4, view.Height); + Assert.False (view.Frame.IsEmpty); + Assert.Equal (new Rect (1, 2, 3, 4), view.Frame); + Assert.False (view.Bounds.IsEmpty); + Assert.Equal (new Rect (0, 0, 3, 4), view.Bounds); + + view.LayoutSubviews (); + + Assert.Equal (1, view.X); + Assert.Equal (2, view.Y); + Assert.Equal (3, view.Width); + Assert.Equal (4, view.Height); + Assert.False (view.Frame.IsEmpty); + Assert.False (view.Bounds.IsEmpty); + + // Default Constructor + view = new View (); + Assert.Null (view.X); + Assert.Null (view.Y); + Assert.Null (view.Width); + Assert.Null (view.Height); + Assert.True (view.Frame.IsEmpty); + Assert.True (view.Bounds.IsEmpty); + + // Constructor + view = new View (1, 2, ""); + Assert.Null (view.X); + Assert.Null (view.Y); + Assert.Null (view.Width); + Assert.Null (view.Height); + Assert.False (view.Frame.IsEmpty); + Assert.True (view.Bounds.IsEmpty); + + // Default Constructor and post assignment equivalent to Object Initializer + view = new View (); + view.X = 1; + view.Y = 2; + view.Width = 3; + view.Height = 4; + super = new View (new Rect (0, 0, 10, 10)); + super.Add (view); + super.BeginInit (); + super.EndInit (); + super.LayoutSubviews (); + Assert.Equal (1, view.X); + Assert.Equal (2, view.Y); + Assert.Equal (3, view.Width); + Assert.Equal (4, view.Height); + Assert.False (view.Frame.IsEmpty); + Assert.Equal (new Rect (1, 2, 3, 4), view.Frame); + Assert.False (view.Bounds.IsEmpty); + Assert.Equal (new Rect (0, 0, 3, 4), view.Bounds); + } + + [Fact] + public void Added_Removed () + { + var v = new View (new Rect (0, 0, 10, 24)); + var t = new View (); + + v.Added += (s, e) => { + Assert.Same (v.SuperView, e.Parent); + Assert.Same (t, e.Parent); + Assert.Same (v, e.Child); + }; + + v.Removed += (s, e) => { + Assert.Same (t, e.Parent); + Assert.Same (v, e.Child); + Assert.True (v.SuperView == null); + }; + + t.Add (v); + Assert.True (t.Subviews.Count == 1); + + t.Remove (v); + Assert.True (t.Subviews.Count == 0); + } + + [Fact] + public void Initialized_Event_Comparing_With_Added_Event () + { + Application.Init (new FakeDriver ()); + + var t = new Toplevel () { Id = "0", }; + + var w = new Window () { Id = "t", Width = Dim.Fill (), Height = Dim.Fill () }; + var v1 = new View () { Id = "v1", Width = Dim.Fill (), Height = Dim.Fill () }; + var v2 = new View () { Id = "v2", Width = Dim.Fill (), Height = Dim.Fill () }; + var sv1 = new View () { Id = "sv1", Width = Dim.Fill (), Height = Dim.Fill () }; + + int tc = 0, wc = 0, v1c = 0, v2c = 0, sv1c = 0; + + w.Added += (s, e) => { + Assert.Equal (e.Parent.Frame.Width, w.Frame.Width); + Assert.Equal (e.Parent.Frame.Height, w.Frame.Height); + }; + v1.Added += (s, e) => { + Assert.Equal (e.Parent.Frame.Width, v1.Frame.Width); + Assert.Equal (e.Parent.Frame.Height, v1.Frame.Height); + }; + v2.Added += (s, e) => { + Assert.Equal (e.Parent.Frame.Width, v2.Frame.Width); + Assert.Equal (e.Parent.Frame.Height, v2.Frame.Height); + }; + sv1.Added += (s, e) => { + Assert.Equal (e.Parent.Frame.Width, sv1.Frame.Width); + Assert.Equal (e.Parent.Frame.Height, sv1.Frame.Height); + }; + + t.Initialized += (s, e) => { + tc++; + Assert.Equal (1, tc); + Assert.Equal (1, wc); + Assert.Equal (1, v1c); + Assert.Equal (1, v2c); + Assert.Equal (1, sv1c); + + Assert.True (t.CanFocus); + Assert.True (w.CanFocus); + Assert.False (v1.CanFocus); + Assert.False (v2.CanFocus); + Assert.False (sv1.CanFocus); + + Application.Refresh (); + }; + w.Initialized += (s, e) => { + wc++; + Assert.Equal (t.Frame.Width, w.Frame.Width); + Assert.Equal (t.Frame.Height, w.Frame.Height); + }; + v1.Initialized += (s, e) => { + v1c++; + Assert.Equal (t.Frame.Width, v1.Frame.Width); + Assert.Equal (t.Frame.Height, v1.Frame.Height); + }; + v2.Initialized += (s, e) => { + v2c++; + Assert.Equal (t.Frame.Width, v2.Frame.Width); + Assert.Equal (t.Frame.Height, v2.Frame.Height); + }; + sv1.Initialized += (s, e) => { + sv1c++; + Assert.Equal (t.Frame.Width, sv1.Frame.Width); + Assert.Equal (t.Frame.Height, sv1.Frame.Height); + Assert.False (sv1.CanFocus); + Assert.Throws (() => sv1.CanFocus = true); + Assert.False (sv1.CanFocus); + }; + + v1.Add (sv1); + w.Add (v1, v2); + t.Add (w); + + Application.Iteration = () => { + Application.Refresh (); + t.Running = false; + }; + + Application.Run (t); + Application.Shutdown (); + + Assert.Equal (1, tc); + Assert.Equal (1, wc); + Assert.Equal (1, v1c); + Assert.Equal (1, v2c); + Assert.Equal (1, sv1c); + + Assert.True (t.CanFocus); + Assert.True (w.CanFocus); + Assert.False (v1.CanFocus); + Assert.False (v2.CanFocus); + Assert.False (sv1.CanFocus); + + v1.CanFocus = true; + Assert.False (sv1.CanFocus); // False because sv1 was disposed and it isn't a subview of v1. + } + + [Fact] + public void Initialized_Event_Will_Be_Invoked_When_Added_Dynamically () + { + Application.Init (new FakeDriver ()); + + var t = new Toplevel () { Id = "0", }; + + var w = new Window () { Id = "t", Width = Dim.Fill (), Height = Dim.Fill () }; + var v1 = new View () { Id = "v1", Width = Dim.Fill (), Height = Dim.Fill () }; + var v2 = new View () { Id = "v2", Width = Dim.Fill (), Height = Dim.Fill () }; + + int tc = 0, wc = 0, v1c = 0, v2c = 0, sv1c = 0; + + t.Initialized += (s, e) => { + tc++; + Assert.Equal (1, tc); + Assert.Equal (1, wc); + Assert.Equal (1, v1c); + Assert.Equal (1, v2c); + Assert.Equal (0, sv1c); // Added after t in the Application.Iteration. + + Assert.True (t.CanFocus); + Assert.True (w.CanFocus); + Assert.False (v1.CanFocus); + Assert.False (v2.CanFocus); + + Application.Refresh (); + }; + w.Initialized += (s, e) => { + wc++; + Assert.Equal (t.Frame.Width, w.Frame.Width); + Assert.Equal (t.Frame.Height, w.Frame.Height); + }; + v1.Initialized += (s, e) => { + v1c++; + Assert.Equal (t.Frame.Width, v1.Frame.Width); + Assert.Equal (t.Frame.Height, v1.Frame.Height); + }; + v2.Initialized += (s, e) => { + v2c++; + Assert.Equal (t.Frame.Width, v2.Frame.Width); + Assert.Equal (t.Frame.Height, v2.Frame.Height); + }; + w.Add (v1, v2); + t.Add (w); + + Application.Iteration = () => { + var sv1 = new View () { Id = "sv1", Width = Dim.Fill (), Height = Dim.Fill () }; + + sv1.Initialized += (s, e) => { + sv1c++; + Assert.NotEqual (t.Frame.Width, sv1.Frame.Width); + Assert.NotEqual (t.Frame.Height, sv1.Frame.Height); + Assert.False (sv1.CanFocus); + Assert.Throws (() => sv1.CanFocus = true); + Assert.False (sv1.CanFocus); + }; + + v1.Add (sv1); + + Application.Refresh (); + t.Running = false; + }; + + Application.Run (t); + Application.Shutdown (); + + Assert.Equal (1, tc); + Assert.Equal (1, wc); + Assert.Equal (1, v1c); + Assert.Equal (1, v2c); + Assert.Equal (1, sv1c); + + Assert.True (t.CanFocus); + Assert.True (w.CanFocus); + Assert.False (v1.CanFocus); + Assert.False (v2.CanFocus); + } + + + [Fact] + public void Multi_Thread_Toplevels () + { + Application.Init (new FakeDriver ()); + + var t = Application.Top; + var w = new Window (); + t.Add (w); + + int count = 0, count1 = 0, count2 = 0; + bool log = false, log1 = false, log2 = false; + bool fromTopStillKnowFirstIsRunning = false; + bool fromTopStillKnowSecondIsRunning = false; + bool fromFirstStillKnowSecondIsRunning = false; + + Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (100), (_) => { + count++; + if (count1 == 5) { + log1 = true; + } + if (count1 == 14 && count2 == 10 && count == 15) { // count2 is already stopped + fromTopStillKnowFirstIsRunning = true; + } + if (count1 == 7 && count2 == 7 && count == 8) { + fromTopStillKnowSecondIsRunning = true; + } + if (count == 30) { + Assert.Equal (30, count); + Assert.Equal (20, count1); + Assert.Equal (10, count2); + + Assert.True (log); + Assert.True (log1); + Assert.True (log2); + + Assert.True (fromTopStillKnowFirstIsRunning); + Assert.True (fromTopStillKnowSecondIsRunning); + Assert.True (fromFirstStillKnowSecondIsRunning); + + Application.RequestStop (); + return false; + } + return true; + }); + + t.Ready += FirstDialogToplevel; + + void FirstDialogToplevel (object sender, EventArgs args) + { + var od = new OpenDialog (); + od.Ready += SecondDialogToplevel; + + Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (100), (_) => { + count1++; + if (count2 == 5) { + log2 = true; + } + if (count2 == 4 && count1 == 5 && count == 5) { + fromFirstStillKnowSecondIsRunning = true; + } + if (count1 == 20) { + Assert.Equal (20, count1); + Application.RequestStop (); + return false; + } + return true; + }); + + Application.Run (od); + } + + void SecondDialogToplevel (object sender, EventArgs args) + { + var d = new Dialog (); + + Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (100), (_) => { + count2++; + if (count < 30) { + log = true; + } + if (count2 == 10) { + Assert.Equal (10, count2); + Application.RequestStop (); + return false; + } + return true; + }); + + Application.Run (d); + } + + Application.Run (); + Application.Shutdown (); + } + + [Theory] + [InlineData (1)] + [InlineData (2)] + [InlineData (3)] + public void LabelChangeText_RendersCorrectly_Constructors (int choice) + { + var driver = new FakeDriver (); + Application.Init (driver); + + try { + // Create a label with a short text + Label lbl; + var text = "test"; + + if (choice == 1) { + // An object initializer should call the default constructor. + lbl = new Label { Text = text }; + } else if (choice == 2) { + // Calling the default constructor followed by the object initializer. + lbl = new Label () { Text = text }; + } else { + // Calling the Text constructor. + lbl = new Label (text); + } + Application.Top.Add (lbl); + Application.Top.LayoutSubviews (); + Application.Top.Redraw (Application.Top.Bounds); + + // should have the initial text + Assert.Equal ('t', driver.Contents [0, 0, 0]); + Assert.Equal ('e', driver.Contents [0, 1, 0]); + Assert.Equal ('s', driver.Contents [0, 2, 0]); + Assert.Equal ('t', driver.Contents [0, 3, 0]); + Assert.Equal (' ', driver.Contents [0, 4, 0]); + } finally { + Application.Shutdown (); + } + } + + [Fact] + [AutoInitShutdown] + public void Internal_Tests () + { + Assert.Equal (new [] { View.Direction.Forward, View.Direction.Backward }, + Enum.GetValues (typeof (View.Direction))); + + var rect = new Rect (1, 1, 10, 1); + var view = new View (rect); + var top = Application.Top; + top.Add (view); + + Assert.Equal (View.Direction.Forward, view.FocusDirection); + view.FocusDirection = View.Direction.Backward; + Assert.Equal (View.Direction.Backward, view.FocusDirection); + Assert.Empty (view.InternalSubviews); + // BUGBUG: v2 - _needsDisplay needs debugging - test disabled for now. + //Assert.Equal (new Rect (new Point (0, 0), rect.Size), view._needsDisplay); + Assert.True (view.LayoutNeeded); + Assert.False (view._childNeedsDisplay); + Assert.False (view.addingView); + view.addingView = true; + Assert.True (view.addingView); + view.ViewToScreen (0, 0, out int rcol, out int rrow); + Assert.Equal (1, rcol); + Assert.Equal (1, rrow); + Assert.Equal (rect, view.ViewToScreen (view.Bounds)); + Assert.Equal (top.Bounds, view.ScreenClip (top.Bounds)); + Assert.True (view.LayoutStyle == LayoutStyle.Absolute); + + Application.Begin (top); + + view.Width = Dim.Fill (); + view.Height = Dim.Fill (); + Assert.Equal (10, view.Bounds.Width); + Assert.Equal (1, view.Bounds.Height); + view.LayoutStyle = LayoutStyle.Computed; + view.SetRelativeLayout (top.Bounds); + Assert.Equal (1, view.Frame.X); + Assert.Equal (1, view.Frame.Y); + Assert.Equal (79, view.Frame.Width); + Assert.Equal (24, view.Frame.Height); + Assert.Equal (0, view.Bounds.X); + Assert.Equal (0, view.Bounds.Y); + Assert.Equal (79, view.Bounds.Width); + Assert.Equal (24, view.Bounds.Height); + + + view.X = 0; + view.Y = 0; + Assert.Equal ("Absolute(0)", view.X.ToString ()); + Assert.Equal ("Fill(0)", view.Width.ToString ()); + view.SetRelativeLayout (top.Bounds); + Assert.Equal (0, view.Frame.X); + Assert.Equal (0, view.Frame.Y); + Assert.Equal (80, view.Frame.Width); + Assert.Equal (25, view.Frame.Height); + Assert.Equal (0, view.Bounds.X); + Assert.Equal (0, view.Bounds.Y); + Assert.Equal (80, view.Bounds.Width); + Assert.Equal (25, view.Bounds.Height); + bool layoutStarted = false; + view.LayoutStarted += (s, e) => layoutStarted = true; + view.OnLayoutStarted (null); + Assert.True (layoutStarted); + view.LayoutComplete += (s, e) => layoutStarted = false; + view.OnLayoutComplete (null); + Assert.False (layoutStarted); + view.X = Pos.Center () - 41; + view.Y = Pos.Center () - 13; + view.SetRelativeLayout (top.Bounds); + top.LayoutSubviews (); // BUGBUG: v2 - ?? + view.ViewToScreen (0, 0, out rcol, out rrow); + Assert.Equal (-41, rcol); + Assert.Equal (-13, rrow); + } + + [Fact] + [AutoInitShutdown] + public void Visible_Sets_Also_Sets_Subviews () + { + var button = new Button ("Click Me"); + var win = new Window () { Width = Dim.Fill (), Height = Dim.Fill () }; + win.Add (button); + var top = Application.Top; + top.Add (win); + + var iterations = 0; + + Application.Iteration += () => { + iterations++; + + Assert.True (button.Visible); + Assert.True (button.CanFocus); + Assert.True (button.HasFocus); + Assert.True (win.Visible); + Assert.True (win.CanFocus); + Assert.True (win.HasFocus); + Assert.True (RunesCount () > 0); + + win.Visible = false; + Assert.True (button.Visible); + Assert.True (button.CanFocus); + Assert.False (button.HasFocus); + Assert.False (win.Visible); + Assert.True (win.CanFocus); + Assert.False (win.HasFocus); + button.SetFocus (); + Assert.False (button.HasFocus); + Assert.False (win.HasFocus); + win.SetFocus (); + Assert.False (button.HasFocus); + Assert.False (win.HasFocus); + top.Redraw (top.Bounds); + Assert.True (RunesCount () == 0); + + win.Visible = true; + win.FocusFirst (); + Assert.True (button.HasFocus); + Assert.True (win.HasFocus); + top.Redraw (top.Bounds); + Assert.True (RunesCount () > 0); + + Application.RequestStop (); + }; + + Application.Run (); + + Assert.Equal (1, iterations); + + int RunesCount () + { + var contents = ((FakeDriver)Application.Driver).Contents; + var runesCount = 0; + + for (int i = 0; i < Application.Driver.Rows; i++) { + for (int j = 0; j < Application.Driver.Cols; j++) { + if (contents [i, j, 0] != ' ') { + runesCount++; + } + } + } + return runesCount; + } + } + + [Fact] + [AutoInitShutdown] + public void GetTopSuperView_Test () + { + var v1 = new View (); + var fv1 = new FrameView (); + fv1.Add (v1); + var tf1 = new TextField (); + var w1 = new Window (); + w1.Add (fv1, tf1); + var top1 = new Toplevel (); + top1.Add (w1); + + var v2 = new View (); + var fv2 = new FrameView (); + fv2.Add (v2); + var tf2 = new TextField (); + var w2 = new Window (); + w2.Add (fv2, tf2); + var top2 = new Toplevel (); + top2.Add (w2); + + Assert.Equal (top1, v1.GetTopSuperView ()); + Assert.Equal (top2, v2.GetTopSuperView ()); + } + + + [Fact, AutoInitShutdown] + public void DrawFrame_With_Positive_Positions () + { + var view = new View (new Rect (0, 0, 8, 4)); + + view.DrawContent += (s, e) => view.DrawFrame (view.Bounds, 0, true); + + Assert.Equal (Point.Empty, new Point (view.Frame.X, view.Frame.Y)); + Assert.Equal (new Size (8, 4), new Size (view.Frame.Width, view.Frame.Height)); + + Application.Top.Add (view); + Application.Begin (Application.Top); + + var expected = @" +┌──────┐ +│ │ +│ │ +└──────┘ +"; + + var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (0, 0, 8, 4), pos); + } + + [Fact, AutoInitShutdown] + public void DrawFrame_With_Minimum_Size () + { + var view = new View (new Rect (0, 0, 2, 2)); + + view.DrawContent += (s, e) => view.DrawFrame (view.Bounds, 0, true); + + Assert.Equal (Point.Empty, new Point (view.Frame.X, view.Frame.Y)); + Assert.Equal (new Size (2, 2), new Size (view.Frame.Width, view.Frame.Height)); + + Application.Top.Add (view); + Application.Begin (Application.Top); + + var expected = @" +┌┐ +└┘ +"; + + var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (0, 0, 2, 2), pos); + } + + [Fact, AutoInitShutdown] + public void DrawFrame_With_Negative_Positions () + { + var view = new View (new Rect (-1, 0, 8, 4)); + + view.DrawContent += (s, e) => view.DrawFrame (view.Bounds, 0, true); + + Assert.Equal (new Point (-1, 0), new Point (view.Frame.X, view.Frame.Y)); + Assert.Equal (new Size (8, 4), new Size (view.Frame.Width, view.Frame.Height)); + + Application.Top.Add (view); + Application.Begin (Application.Top); + + var expected = @" +──────┐ + │ + │ +──────┘ +"; + + var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (0, 0, 7, 4), pos); + + view.Frame = new Rect (-1, -1, 8, 4); + Application.Refresh (); + + expected = @" + │ + │ +──────┘ +"; + + pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (6, 0, 7, 3), pos); + + view.Frame = new Rect (0, 0, 8, 4); + ((FakeDriver)Application.Driver).SetBufferSize (7, 4); + + expected = @" +┌────── +│ +│ +└────── +"; + + pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (0, 0, 7, 4), pos); + + view.Frame = new Rect (0, 0, 8, 4); + ((FakeDriver)Application.Driver).SetBufferSize (7, 3); + } + + + [Fact, AutoInitShutdown] + public void Clear_Can_Use_Driver_AddRune_Or_AddStr_Methods () + { + var view = new View () { + Width = Dim.Fill (), + Height = Dim.Fill () + }; + view.DrawContent += (s, e) => { + view.DrawFrame (view.Bounds); + var savedClip = Application.Driver.Clip; + Application.Driver.Clip = new Rect (1, 1, view.Bounds.Width - 2, view.Bounds.Height - 2); + for (int row = 0; row < view.Bounds.Height - 2; row++) { + Application.Driver.Move (1, row + 1); + for (int col = 0; col < view.Bounds.Width - 2; col++) { + Application.Driver.AddStr ($"{col}"); + } + } + Application.Driver.Clip = savedClip; + }; + Application.Top.Add (view); + Application.Begin (Application.Top); + ((FakeDriver)Application.Driver).SetBufferSize (20, 10); + + var expected = @" +┌──────────────────┐ +│012345678910111213│ +│012345678910111213│ +│012345678910111213│ +│012345678910111213│ +│012345678910111213│ +│012345678910111213│ +│012345678910111213│ +│012345678910111213│ +└──────────────────┘ +"; + + var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (0, 0, 20, 10), pos); + + view.Clear (); + + expected = @" +"; + + pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (Rect.Empty, pos); + } + + [Fact, AutoInitShutdown] + public void Clear_Bounds_Can_Use_Driver_AddRune_Or_AddStr_Methods () + { + var view = new View () { + Width = Dim.Fill (), + Height = Dim.Fill () + }; + view.DrawContent += (s, e) => { + view.DrawFrame (view.Bounds); + var savedClip = Application.Driver.Clip; + Application.Driver.Clip = new Rect (1, 1, view.Bounds.Width - 2, view.Bounds.Height - 2); + for (int row = 0; row < view.Bounds.Height - 2; row++) { + Application.Driver.Move (1, row + 1); + for (int col = 0; col < view.Bounds.Width - 2; col++) { + Application.Driver.AddStr ($"{col}"); + } + } + Application.Driver.Clip = savedClip; + }; + Application.Top.Add (view); + Application.Begin (Application.Top); + ((FakeDriver)Application.Driver).SetBufferSize (20, 10); + + var expected = @" +┌──────────────────┐ +│012345678910111213│ +│012345678910111213│ +│012345678910111213│ +│012345678910111213│ +│012345678910111213│ +│012345678910111213│ +│012345678910111213│ +│012345678910111213│ +└──────────────────┘ +"; + + var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (0, 0, 20, 10), pos); + + view.Clear (view.Bounds); + + expected = @" +"; + + pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (Rect.Empty, pos); + } + + [Fact, AutoInitShutdown] + public void GetTextFormatterBoundsSize_GetSizeNeededForText_HotKeySpecifier () + { + var text = "Say Hello 你"; + var horizontalView = new View () { + Text = text, + AutoSize = true, + HotKeySpecifier = '_' }; + + var verticalView = new View () { + Text = text, + AutoSize = true, + HotKeySpecifier = '_', + TextDirection = TextDirection.TopBottom_LeftRight + }; + Application.Top.Add (horizontalView, verticalView); + Application.Begin (Application.Top); + ((FakeDriver)Application.Driver).SetBufferSize (50, 50); + + Assert.True (horizontalView.AutoSize); + Assert.Equal (new Rect (0, 0, 12, 1), horizontalView.Frame); + Assert.Equal (new Size (12, 1), horizontalView.GetSizeNeededForTextWithoutHotKey ()); + Assert.Equal (new Size (12, 1), horizontalView.GetSizeNeededForTextAndHotKey ()); + Assert.Equal (horizontalView.TextFormatter.Size, horizontalView.GetSizeNeededForTextAndHotKey ()); + Assert.Equal (horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ()); + + Assert.True (verticalView.AutoSize); + // BUGBUG: v2 - Autosize is broken; disabling this test + //Assert.Equal (new Rect (0, 0, 2, 11), verticalView.Frame); + //Assert.Equal (new Size (2, 11), verticalView.GetSizeNeededForTextWithoutHotKey ()); + //Assert.Equal (new Size (2, 11), verticalView.GetSizeNeededForTextAndHotKey ()); + Assert.Equal (verticalView.TextFormatter.Size, verticalView.GetSizeNeededForTextAndHotKey ()); + Assert.Equal (verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ()); + + text = "Say He_llo 你"; + horizontalView.Text = text; + verticalView.Text = text; + + Assert.True (horizontalView.AutoSize); + Assert.Equal (new Rect (0, 0, 12, 1), horizontalView.Frame); + Assert.Equal (new Size (12, 1), horizontalView.GetSizeNeededForTextWithoutHotKey ()); + Assert.Equal (new Size (13, 1), horizontalView.GetSizeNeededForTextAndHotKey ()); + Assert.Equal (horizontalView.TextFormatter.Size, horizontalView.GetSizeNeededForTextAndHotKey ()); + Assert.Equal (horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ()); + + Assert.True (verticalView.AutoSize); + // BUGBUG: v2 - Autosize is broken; disabling this test + //Assert.Equal (new Rect (0, 0, 2, 11), verticalView.Frame); + //Assert.Equal (new Size (2, 11), verticalView.GetSizeNeededForTextWithoutHotKey ()); + //Assert.Equal (new Size (2, 12), verticalView.GetSizeNeededForTextAndHotKey ()); + //Assert.Equal (verticalView.TextFormatter.Size, verticalView.GetSizeNeededForTextAndHotKey ()); + //Assert.Equal (verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ()); + } + + [Fact] + public void IsAdded_Added_Removed () + { + var top = new Toplevel (); + var view = new View (); + Assert.False (view.IsAdded); + top.Add (view); + Assert.True (view.IsAdded); + top.Remove (view); + Assert.False (view.IsAdded); + } + + [Fact, AutoInitShutdown] + public void Visible_Clear_The_View_Output () + { + var label = new Label ("Testing visibility."); + var win = new Window (); + win.Add (label); + var top = Application.Top; + top.Add (win); + Application.Begin (top); + + Assert.True (label.Visible); + ((FakeDriver)Application.Driver).SetBufferSize (30, 5); + TestHelpers.AssertDriverContentsWithFrameAre (@" +┌────────────────────────────┐ +│Testing visibility. │ +│ │ +│ │ +└────────────────────────────┘ +", output); + + label.Visible = false; + TestHelpers.AssertDriverContentsWithFrameAre (@" +┌────────────────────────────┐ +│ │ +│ │ +│ │ +└────────────────────────────┘ +", output); + } + + [Fact, AutoInitShutdown] + public void DrawContentComplete_Event_Is_Always_Called () + { + var viewCalled = false; + var tvCalled = false; + + var view = new View ("View") { Width = 10, Height = 10 }; + view.DrawContentComplete += (s, e) => viewCalled = true; + var tv = new TextView () { Y = 11, Width = 10, Height = 10 }; + tv.DrawContentComplete += (s, e) => tvCalled = true; + + Application.Top.Add (view, tv); + Application.Begin (Application.Top); + + Assert.True (viewCalled); + Assert.True (tvCalled); + } + + [Fact, AutoInitShutdown] + public void GetNormalColor_ColorScheme () + { + var view = new View { ColorScheme = Colors.Base }; + + Assert.Equal (view.ColorScheme.Normal, view.GetNormalColor ()); + + view.Enabled = false; + Assert.Equal (view.ColorScheme.Disabled, view.GetNormalColor ()); + } + + [Fact, AutoInitShutdown] + public void GetHotNormalColor_ColorScheme () + { + var view = new View { ColorScheme = Colors.Base }; + + Assert.Equal (view.ColorScheme.HotNormal, view.GetHotNormalColor ()); + + view.Enabled = false; + Assert.Equal (view.ColorScheme.Disabled, view.GetHotNormalColor ()); + } + + [Theory, AutoInitShutdown] + [InlineData (true)] + [InlineData (false)] + public void Clear_Does_Not_Spillover_Its_Parent (bool label) + { + var root = new View () { Width = 20, Height = 10, ColorScheme = Colors.Base }; + + var v = label == true ? + new Label (new string ('c', 100)) { + Width = Dim.Fill (), + } : + (View)new TextView () { + Height = 1, + Text = new string ('c', 100), + Width = Dim.Fill () + }; + + root.Add (v); + + Application.Top.Add (root); + Application.Begin (Application.Top); + + if (label) { + Assert.True (v.AutoSize); + Assert.False (v.CanFocus); + Assert.Equal (new Rect (0, 0, 100, 1), v.Frame); + } else { + Assert.False (v.AutoSize); + Assert.True (v.CanFocus); + Assert.Equal (new Rect (0, 0, 20, 1), v.Frame); + } + + TestHelpers.AssertDriverContentsWithFrameAre (@" +cccccccccccccccccccc", output); + + var attributes = new Attribute [] { + Colors.TopLevel.Normal, + Colors.Base.Normal, + Colors.Base.Focus + }; + if (label) { + TestHelpers.AssertDriverColorsAre (@" +111111111111111111110 +111111111111111111110", attributes); + } else { + TestHelpers.AssertDriverColorsAre (@" +222222222222222222220 +111111111111111111110", attributes); + } + + if (label) { + root.CanFocus = true; + v.CanFocus = true; + Assert.False (v.HasFocus); + v.SetFocus (); + Assert.True (v.HasFocus); + Application.Refresh (); + TestHelpers.AssertDriverColorsAre (@" +222222222222222222220 +111111111111111111110", attributes); + } + } + + public class DerivedView : View { + public DerivedView () + { + CanFocus = true; + } + + public bool IsKeyDown { get; set; } + public bool IsKeyPress { get; set; } + public bool IsKeyUp { get; set; } + public override ustring Text { get; set; } + + public override bool OnKeyDown (KeyEvent keyEvent) + { + IsKeyDown = true; + return true; + } + + public override bool ProcessKey (KeyEvent keyEvent) + { + IsKeyPress = true; + return true; + } + + public override bool OnKeyUp (KeyEvent keyEvent) + { + IsKeyUp = true; + return true; + } + + public override void Redraw (Rect bounds) + { + var idx = 0; + // BUGBUG: v2 - this should use Boudns, not Frame + for (int r = 0; r < Frame.Height; r++) { + for (int c = 0; c < Frame.Width; c++) { + if (idx < Text.Length) { + var rune = Text [idx]; + if (rune != '\n') { + AddRune (c, r, Text [idx]); + } + idx++; + if (rune == '\n') { + break; + } + } + } + } + ClearLayoutNeeded (); + ClearNeedsDisplay (); + } + } + + [Fact, AutoInitShutdown] + public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Up_Left_Using_Frame () + { + var label = new Label ("At 0,0"); + var view = new DerivedView () { + X = 2, + Y = 2, + Width = 30, + Height = 2, + Text = "A text with some long width\n and also with two lines." + }; + var top = Application.Top; + top.Add (label, view); + Application.Begin (top); + + top.Redraw (top.Bounds); + TestHelpers.AssertDriverContentsWithFrameAre (@" +At 0,0 + + A text with some long width + and also with two lines. ", output); + + view.Frame = new Rect (1, 1, 10, 1); + Assert.Equal (new Rect (1, 1, 10, 1), view.Frame); + Assert.Equal (LayoutStyle.Computed, view.LayoutStyle); + view.LayoutStyle = LayoutStyle.Absolute; + Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); + Assert.Equal (new Rect (0, 0, 10, 1), view._needsDisplay); + top.Redraw (top.Bounds); + TestHelpers.AssertDriverContentsWithFrameAre (@" +At 0,0 + A text wit", output); + } + + [Fact, AutoInitShutdown] + public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Up_Left_Using_Pos_Dim () + { + var label = new Label ("At 0,0"); + var view = new DerivedView () { + X = 2, + Y = 2, + Width = 30, + Height = 2, + Text = "A text with some long width\n and also with two lines." + }; + var top = Application.Top; + top.Add (label, view); + Application.Begin (top); + + top.Redraw (top.Bounds); + TestHelpers.AssertDriverContentsWithFrameAre (@" +At 0,0 + + A text with some long width + and also with two lines. ", output); + + view.X = 1; + view.Y = 1; + view.Width = 10; + view.Height = 1; + Assert.Equal (new Rect (1, 1, 10, 1), view.Frame); + Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); + Assert.Equal (new Rect (0, 0, 30, 2), view._needsDisplay); + top.Redraw (top.Bounds); + TestHelpers.AssertDriverContentsWithFrameAre (@" +At 0,0 + A text wit", output); + } + + [Fact, AutoInitShutdown] + public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Up_Left_Using_Frame () + { + var label = new Label ("At 0,0"); + var view = new DerivedView () { + X = 2, + Y = 2, + Width = 30, + Height = 2, + Text = "A text with some long width\n and also with two lines." + }; + var top = Application.Top; + top.Add (label, view); + Application.Begin (top); + + view.Redraw (view.Bounds); + TestHelpers.AssertDriverContentsWithFrameAre (@" +At 0,0 + + A text with some long width + and also with two lines. ", output); + + view.Frame = new Rect (1, 1, 10, 1); + Assert.Equal (new Rect (1, 1, 10, 1), view.Frame); + Assert.Equal (LayoutStyle.Computed, view.LayoutStyle); + view.LayoutStyle = LayoutStyle.Absolute; + Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); + Assert.Equal (new Rect (0, 0, 10, 1), view._needsDisplay); + view.Redraw (view.Bounds); + TestHelpers.AssertDriverContentsWithFrameAre (@" +At 0,0 + A text wit + A text with some long width + and also with two lines. ", output); + } + + [Fact, AutoInitShutdown] + public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Up_Left_Using_Pos_Dim () + { + var label = new Label ("At 0,0"); + var view = new DerivedView () { + X = 2, + Y = 2, + Width = 30, + Height = 2, + Text = "A text with some long width\n and also with two lines." + }; + var top = Application.Top; + top.Add (label, view); + Application.Begin (top); + + view.Redraw (view.Bounds); + TestHelpers.AssertDriverContentsWithFrameAre (@" +At 0,0 + + A text with some long width + and also with two lines. ", output); + + view.X = 1; + view.Y = 1; + view.Width = 10; + view.Height = 1; + Assert.Equal (new Rect (1, 1, 10, 1), view.Frame); + Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); + Assert.Equal (new Rect (0, 0, 30, 2), view._needsDisplay); + view.Redraw (view.Bounds); + TestHelpers.AssertDriverContentsWithFrameAre (@" +At 0,0 + A text wit + A text with some long width + and also with two lines. ", output); + } + + [Fact, AutoInitShutdown] + public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Down_Right_Using_Frame () + { + var label = new Label ("At 0,0"); + var view = new DerivedView () { + X = 2, + Y = 2, + Width = 30, + Height = 2, + Text = "A text with some long width\n and also with two lines." + }; + var top = Application.Top; + top.Add (label, view); + Application.Begin (top); + + TestHelpers.AssertDriverContentsWithFrameAre (@" +At 0,0 + + A text with some long width + and also with two lines. ", output); + + view.Frame = new Rect (3, 3, 10, 1); + Assert.Equal (new Rect (3, 3, 10, 1), view.Frame); + Assert.Equal (LayoutStyle.Computed, view.LayoutStyle); + view.LayoutStyle = LayoutStyle.Absolute; + Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); + Assert.Equal (new Rect (0, 0, 10, 1), view._needsDisplay); + top.Redraw (top.Bounds); + TestHelpers.AssertDriverContentsWithFrameAre (@" +At 0,0 + + + A text wit", output); + } + + [Fact, AutoInitShutdown] + public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Down_Right_Using_Pos_Dim () + { + var label = new Label ("At 0,0"); + var view = new DerivedView () { + X = 2, + Y = 2, + Width = 30, + Height = 2, + Text = "A text with some long width\n and also with two lines." + }; + var top = Application.Top; + top.Add (label, view); + Application.Begin (top); + + top.Redraw (top.Bounds); + TestHelpers.AssertDriverContentsWithFrameAre (@" +At 0,0 + + A text with some long width + and also with two lines. ", output); + + view.X = 3; + view.Y = 3; + view.Width = 10; + view.Height = 1; + Assert.Equal (new Rect (3, 3, 10, 1), view.Frame); + Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); + Assert.Equal (new Rect (0, 0, 30, 2), view._needsDisplay); + top.Redraw (top.Bounds); + TestHelpers.AssertDriverContentsWithFrameAre (@" +At 0,0 + + + A text wit", output); + } + + [Fact, AutoInitShutdown] + public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Down_Right_Using_Frame () + { + var label = new Label ("At 0,0"); + var view = new DerivedView () { + X = 2, + Y = 2, + Width = 30, + Height = 2, + Text = "A text with some long width\n and also with two lines." + }; + var top = Application.Top; + top.Add (label, view); + Application.Begin (top); + + view.Redraw (view.Bounds); + TestHelpers.AssertDriverContentsWithFrameAre (@" +At 0,0 + + A text with some long width + and also with two lines. ", output); + + view.Frame = new Rect (3, 3, 10, 1); + Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); + Assert.Equal (new Rect (0, 0, 10, 1), view._needsDisplay); + view.Redraw (view.Bounds); + TestHelpers.AssertDriverContentsWithFrameAre (@" +At 0,0 + + A text with some long width + A text witith two lines. ", output); + } + + [Fact, AutoInitShutdown] + public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Down_Right_Using_Pos_Dim () + { + var label = new Label ("At 0,0"); + var view = new DerivedView () { + X = 2, + Y = 2, + Width = 30, + Height = 2, + Text = "A text with some long width\n and also with two lines." + }; + var top = Application.Top; + top.Add (label, view); + Application.Begin (top); + + view.Redraw (view.Bounds); + TestHelpers.AssertDriverContentsWithFrameAre (@" +At 0,0 + + A text with some long width + and also with two lines. ", output); + + view.X = 3; + view.Y = 3; + view.Width = 10; + view.Height = 1; + Assert.Equal (new Rect (3, 3, 10, 1), view.Frame); + Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); + Assert.Equal (new Rect (0, 0, 30, 2), view._needsDisplay); + view.Redraw (view.Bounds); + TestHelpers.AssertDriverContentsWithFrameAre (@" +At 0,0 + + A text with some long width + A text witith two lines. ", output); + } + + [Fact, AutoInitShutdown] + public void Test_Nested_Views_With_Height_Equal_To_One () + { + var v = new View () { Width = 11, Height = 3, ColorScheme = new ColorScheme () }; + + var top = new View () { Width = Dim.Fill (), Height = 1 }; + var bottom = new View () { Width = Dim.Fill (), Height = 1, Y = 2 }; + + top.Add (new Label ("111")); + v.Add (top); + v.Add (new LineView (Orientation.Horizontal) { Y = 1 }); + bottom.Add (new Label ("222")); + v.Add (bottom); + + v.LayoutSubviews (); + v.Redraw (v.Bounds); + + + string looksLike = +@" +111 +─────────── +222"; + TestHelpers.AssertDriverContentsAre (looksLike, output); + } + + [Fact] + [AutoInitShutdown] + public void Frame_Set_After_Initialize_Update_NeededDisplay () + { + var frame = new FrameView (); + + var label = new Label ("This should be the first line.") { + TextAlignment = Terminal.Gui.TextAlignment.Centered, + ColorScheme = Colors.Menu, + Width = Dim.Fill (), + X = Pos.Center (), + Y = Pos.Center () - 2 // center minus 2 minus two lines top and bottom borders equal to zero (4-2-2=0) + }; + + var button = new Button ("Press me!") { + X = Pos.Center (), + Y = Pos.Center () + }; + + frame.Add (label, button); + + frame.X = Pos.Center (); + frame.Y = Pos.Center (); + frame.Width = 40; + frame.Height = 8; + + var top = Application.Top; + + top.Add (frame); + + Application.Begin (top); + + top.LayoutComplete += (s, e) => { + Assert.Equal (new Rect (0, 0, 80, 25), top._needsDisplay); + }; + + frame.LayoutComplete += (s, e) => { + Assert.Equal (new Rect (0, 0, 40, 8), frame._needsDisplay); + }; + + label.LayoutComplete += (s, e) => { + Assert.Equal (new Rect (0, 0, 38, 1), label._needsDisplay); + }; + + button.LayoutComplete += (s, e) => { + Assert.Equal (new Rect (0, 0, 13, 1), button._needsDisplay); + }; + + Assert.True (label.AutoSize); + Assert.Equal (new Rect (0, 0, 80, 25), top.Frame); + Assert.Equal (new Rect (20, 8, 40, 8), frame.Frame); + Assert.Equal (new Rect (20, 8, 60, 16), new Rect ( + frame.Frame.Left, frame.Frame.Top, + frame.Frame.Right, frame.Frame.Bottom)); + Assert.Equal (new Rect (0, 0, 38, 1), label.Frame); + Assert.Equal (new Rect (12, 2, 13, 1), button.Frame); + var expected = @" + ┌──────────────────────────────────────┐ + │ This should be the first line. │ + │ │ + │ [ Press me! ] │ + │ │ + │ │ + │ │ + └──────────────────────────────────────┘ +"; + + TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + } + + } +} diff --git a/UnitTests/Views/AllViewsTests.cs b/UnitTests/Views/AllViewsTests.cs index b47d37dc3..4377c7df0 100644 --- a/UnitTests/Views/AllViewsTests.cs +++ b/UnitTests/Views/AllViewsTests.cs @@ -5,7 +5,7 @@ using System.Reflection; using Xunit; using System.IO; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class AllViewsTests { [Fact] public void AllViews_Tests_All_Constructors () diff --git a/UnitTests/Views/AppendAutocompleteTests.cs b/UnitTests/Views/AppendAutocompleteTests.cs index 3f3a0bb0d..89d8bbea5 100644 --- a/UnitTests/Views/AppendAutocompleteTests.cs +++ b/UnitTests/Views/AppendAutocompleteTests.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.TextTests { public class AppendAutocompleteTests { readonly ITestOutputHelper output; diff --git a/UnitTests/Views/ButtonTests.cs b/UnitTests/Views/ButtonTests.cs index b85815709..550976da3 100644 --- a/UnitTests/Views/ButtonTests.cs +++ b/UnitTests/Views/ButtonTests.cs @@ -2,7 +2,7 @@ using Xunit; using Xunit.Abstractions; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class ButtonTests { readonly ITestOutputHelper output; diff --git a/UnitTests/Views/CheckBoxTests.cs b/UnitTests/Views/CheckBoxTests.cs index ded898f62..4c1a90954 100644 --- a/UnitTests/Views/CheckBoxTests.cs +++ b/UnitTests/Views/CheckBoxTests.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class CheckboxTests { readonly ITestOutputHelper output; diff --git a/UnitTests/Views/ColorPickerTests.cs b/UnitTests/Views/ColorPickerTests.cs index 04462d736..c81502804 100644 --- a/UnitTests/Views/ColorPickerTests.cs +++ b/UnitTests/Views/ColorPickerTests.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; using Xunit; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class ColorPickerTests { [Fact] public void Constructors () diff --git a/UnitTests/Views/ComboBoxTests.cs b/UnitTests/Views/ComboBoxTests.cs index a841947ea..41f3f84db 100644 --- a/UnitTests/Views/ComboBoxTests.cs +++ b/UnitTests/Views/ComboBoxTests.cs @@ -4,7 +4,7 @@ using System.Linq; using Xunit; using Xunit.Abstractions; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class ComboBoxTests { ITestOutputHelper output; diff --git a/UnitTests/Menus/ContextMenuTests.cs b/UnitTests/Views/ContextMenuTests.cs similarity index 99% rename from UnitTests/Menus/ContextMenuTests.cs rename to UnitTests/Views/ContextMenuTests.cs index 256c776dd..008c07821 100644 --- a/UnitTests/Menus/ContextMenuTests.cs +++ b/UnitTests/Views/ContextMenuTests.cs @@ -1,10 +1,11 @@ using System.Globalization; using System.Threading; +using Terminal.Gui; using Xunit; using Xunit.Abstractions; //using GraphViewTests = Terminal.Gui.Views.GraphViewTests; -namespace Terminal.Gui.MenuTests { +namespace Terminal.Gui.ViewsTests { public class ContextMenuTests { readonly ITestOutputHelper output; diff --git a/UnitTests/Views/DateFieldTests.cs b/UnitTests/Views/DateFieldTests.cs index 6713d36c4..e32897a77 100644 --- a/UnitTests/Views/DateFieldTests.cs +++ b/UnitTests/Views/DateFieldTests.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; using Xunit; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class DateFieldTests { [Fact] public void Constructors_Defaults () diff --git a/UnitTests/Views/FrameViewTests.cs b/UnitTests/Views/FrameViewTests.cs index 514abf79f..1f2e681f1 100644 --- a/UnitTests/Views/FrameViewTests.cs +++ b/UnitTests/Views/FrameViewTests.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class FrameViewTests { readonly ITestOutputHelper output; diff --git a/UnitTests/Views/GraphViewTests.cs b/UnitTests/Views/GraphViewTests.cs index 62d82229a..6d38eb075 100644 --- a/UnitTests/Views/GraphViewTests.cs +++ b/UnitTests/Views/GraphViewTests.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using Terminal.Gui; using Xunit; -using Terminal.Gui.Graphs; using Point = Terminal.Gui.Point; using Attribute = Terminal.Gui.Attribute; using System.Text; @@ -11,8 +10,7 @@ using System.Text.RegularExpressions; using Xunit.Abstractions; using Rune = System.Rune; -namespace Terminal.Gui.ViewTests { -// BUGBUG: v2 see https://github.com/gui-cs/Terminal.Gui/issues/2463 +namespace Terminal.Gui.ViewsTests { #region Helper Classes class FakeHAxis : HorizontalAxis { diff --git a/UnitTests/Views/HexViewTests.cs b/UnitTests/Views/HexViewTests.cs index fdfca94de..92fb3f4cb 100644 --- a/UnitTests/Views/HexViewTests.cs +++ b/UnitTests/Views/HexViewTests.cs @@ -6,7 +6,7 @@ using System.Text; using System.Threading.Tasks; using Xunit; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class HexViewTests { [Fact] public void Constructors_Defaults () diff --git a/UnitTests/Views/LineViewTests.cs b/UnitTests/Views/LineViewTests.cs index 328065f9d..a568c90cd 100644 --- a/UnitTests/Views/LineViewTests.cs +++ b/UnitTests/Views/LineViewTests.cs @@ -1,7 +1,6 @@ -using Terminal.Gui.Graphs; -using Xunit; +using Xunit; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class LineViewTests { [Fact] diff --git a/UnitTests/Views/ListViewTests.cs b/UnitTests/Views/ListViewTests.cs index 733ce459f..eb0b66a9d 100644 --- a/UnitTests/Views/ListViewTests.cs +++ b/UnitTests/Views/ListViewTests.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class ListViewTests { readonly ITestOutputHelper output; diff --git a/UnitTests/TopLevels/MdiTests.cs b/UnitTests/Views/MdiTests.cs similarity index 99% rename from UnitTests/TopLevels/MdiTests.cs rename to UnitTests/Views/MdiTests.cs index 50ac5f7c8..c0ae51e01 100644 --- a/UnitTests/TopLevels/MdiTests.cs +++ b/UnitTests/Views/MdiTests.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.TopLevelTests { +namespace Terminal.Gui.ViewsTests { public class MdiTests { public MdiTests () { diff --git a/UnitTests/Menus/MenuTests.cs b/UnitTests/Views/MenuTests.cs similarity index 98% rename from UnitTests/Menus/MenuTests.cs rename to UnitTests/Views/MenuTests.cs index d1ed18b04..567f240e4 100644 --- a/UnitTests/Menus/MenuTests.cs +++ b/UnitTests/Views/MenuTests.cs @@ -1,11 +1,12 @@ using System; using System.Collections.Generic; using System.Linq; +using Terminal.Gui; using Xunit; using Xunit.Abstractions; //using static Terminal.Gui.ViewTests.MenuTests; -namespace Terminal.Gui.MenuTests { +namespace Terminal.Gui.ViewsTests { public class MenuTests { readonly ITestOutputHelper output; @@ -135,9 +136,7 @@ namespace Terminal.Gui.MenuTests { if (cancelClosing) { e.Cancel = true; isMenuClosed = false; - } else { - isMenuClosed = true; - } + } else isMenuClosed = true; }; Application.Top.Add (menu); @@ -319,21 +318,18 @@ Edit Assert.Equal ("_Paste", miCurrent.Title); for (int i = 2; i >= -1; i--) { - if (i == -1) { - Assert.False (mCurrent.MouseEvent (new MouseEvent () { + if (i == -1) Assert.False (mCurrent.MouseEvent (new MouseEvent () { X = 10, Y = i, Flags = MouseFlags.ReportMousePosition, View = menu })); - } else { - Assert.True (mCurrent.MouseEvent (new MouseEvent () { +else Assert.True (mCurrent.MouseEvent (new MouseEvent () { X = 10, Y = i, Flags = MouseFlags.ReportMousePosition, View = mCurrent })); - } Assert.True (menu.IsMenuOpen); if (i == 2) { Assert.Equal ("_Edit", miCurrent.Parent.Title); @@ -1112,17 +1108,15 @@ Edit // File Edit // New Copy public class ExpectedMenuBar : MenuBar { - FakeDriver d = ((FakeDriver)Application.Driver); + FakeDriver d = (FakeDriver)Application.Driver; // Each MenuBar title has a 1 space pad on each side // See `static int leftPadding` and `static int rightPadding` on line 1037 of Menu.cs public string MenuBarText { get { string txt = string.Empty; - foreach (var m in Menus) { - + foreach (var m in Menus) txt += " " + m.Title.ToString () + " "; - } return txt; } } @@ -1149,10 +1143,10 @@ Edit // // The width of the Frame is determined in Menu.cs line 144, where `Width` is calculated // 1 space before the Title and 2 spaces after the Title/Check/Help - public string expectedTopRow (int i) => $"{d.ULCorner}{new String (d.HLine.ToString () [0], Menus [i].Children [0].TitleLength + 3)}{d.URCorner} \n"; + public string expectedTopRow (int i) => $"{d.ULCorner}{new string (d.HLine.ToString () [0], Menus [i].Children [0].TitleLength + 3)}{d.URCorner} \n"; // The 3 spaces at end are a result of Menu.cs line 1062 where `pos` is calculated (` + spacesAfterTitle`) public string expectedMenuItemRow (int i) => $"{d.VLine} {Menus [i].Children [0].Title} {d.VLine} \n"; - public string expectedBottomRow (int i) => $"{d.LLCorner}{new String (d.HLine.ToString () [0], Menus [i].Children [0].TitleLength + 3)}{d.LRCorner} \n"; + public string expectedBottomRow (int i) => $"{d.LLCorner}{new string (d.HLine.ToString () [0], Menus [i].Children [0].TitleLength + 3)}{d.LRCorner} \n"; // The fulll expected string for an open sub menu public string expectedSubMenuOpen (int i) => ClosedMenuText + @@ -1196,12 +1190,10 @@ Edit }) }); - MenuBarItem [] items = new MenuBarItem [expectedMenu.Menus.Length]; - for (var i = 0; i < expectedMenu.Menus.Length; i++) { - items [i] = new MenuBarItem (expectedMenu.Menus [i].Title, new MenuItem [] { + var items = new MenuBarItem [expectedMenu.Menus.Length]; + for (var i = 0; i < expectedMenu.Menus.Length; i++) items [i] = new MenuBarItem (expectedMenu.Menus [i].Title, new MenuItem [] { new MenuItem (expectedMenu.Menus [i].Children [0].Title, "", null) }); - } var menu = new MenuBar (items); Application.Top.Add (menu); @@ -1481,14 +1473,12 @@ Edit }) }); - MenuBarItem [] items = new MenuBarItem [expectedMenu.Menus.Length]; - for (var i = 0; i < expectedMenu.Menus.Length; i++) { - items [i] = new MenuBarItem (expectedMenu.Menus [i].Title, expectedMenu.Menus [i].Children.Length > 0 + var items = new MenuBarItem [expectedMenu.Menus.Length]; + for (var i = 0; i < expectedMenu.Menus.Length; i++) items [i] = new MenuBarItem (expectedMenu.Menus [i].Title, expectedMenu.Menus [i].Children.Length > 0 ? new MenuItem [] { new MenuItem (expectedMenu.Menus [i].Children [0].Title, "", null), } : Array.Empty ()); - } var menu = new MenuBar (items); var tf = new TextField () { Y = 2, Width = 10 }; @@ -1740,7 +1730,7 @@ Edit [Fact, AutoInitShutdown] public void AllowNullChecked_Get_Set () { - MenuItem mi = new MenuItem ("Check this out 你", "", null) { + var mi = new MenuItem ("Check this out 你", "", null) { CheckType = MenuItemCheckStyle.Checked }; mi.Action = mi.ToggleChecked; diff --git a/UnitTests/Views/ProgressBarTests.cs b/UnitTests/Views/ProgressBarTests.cs index b546cecb9..14e058f52 100644 --- a/UnitTests/Views/ProgressBarTests.cs +++ b/UnitTests/Views/ProgressBarTests.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; using Xunit; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class ProgressBarTests { [Fact] [AutoInitShutdown] diff --git a/UnitTests/Views/RadioGroupTests.cs b/UnitTests/Views/RadioGroupTests.cs index cace675ee..110eecb44 100644 --- a/UnitTests/Views/RadioGroupTests.cs +++ b/UnitTests/Views/RadioGroupTests.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class RadioGroupTests { readonly ITestOutputHelper output; diff --git a/UnitTests/Views/ScrollBarViewTests.cs b/UnitTests/Views/ScrollBarViewTests.cs index 16ab69884..5b7ebe664 100644 --- a/UnitTests/Views/ScrollBarViewTests.cs +++ b/UnitTests/Views/ScrollBarViewTests.cs @@ -5,7 +5,7 @@ using System.Reflection; using Xunit; using Xunit.Abstractions; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class ScrollBarViewTests { readonly ITestOutputHelper output; @@ -19,9 +19,6 @@ namespace Terminal.Gui.ViewTests { { var width = 40; var height = 3; - ((FakeDriver)Application.Driver).SetBufferSize (width, height); - // BUGBUG: Application.Top only gets resized to Console size if it is set to computed?!? - Application.Top.LayoutStyle = LayoutStyle.Computed; var super = new Window () { Id = "super", Width = Dim.Fill (), Height = Dim.Fill () }; Application.Top.Add (super); @@ -35,6 +32,7 @@ namespace Terminal.Gui.ViewTests { }; super.Add (sbv); Application.Begin (Application.Top); + ((FakeDriver)Application.Driver).SetBufferSize (width, height); var expected = @" ┌──────────────────────────────────────┐ @@ -49,9 +47,6 @@ namespace Terminal.Gui.ViewTests { { var width = 3; var height = 40; - ((FakeDriver)Application.Driver).SetBufferSize (width, height); - // BUGBUG: Application.Top only gets resized to Console size if it is set to computed?!? - Application.Top.LayoutStyle = LayoutStyle.Computed; var super = new Window () { Id = "super", Width = Dim.Fill (), Height = Dim.Fill () }; Application.Top.Add (super); @@ -67,6 +62,7 @@ namespace Terminal.Gui.ViewTests { super.Add (sbv); Application.Begin (Application.Top); + ((FakeDriver)Application.Driver).SetBufferSize (width, height); var expected = @" ┌─┐ @@ -118,9 +114,6 @@ namespace Terminal.Gui.ViewTests { { var width = 3; var height = 40; - ((FakeDriver)Application.Driver).SetBufferSize (width, height); - // BUGBUG: Application.Top only gets resized to Console size if it is set to computed?!? - Application.Top.LayoutStyle = LayoutStyle.Computed; var super = new Window () { Id = "super", Width = Dim.Fill (), Height = Dim.Fill () }; Application.Top.Add (super); @@ -146,6 +139,7 @@ namespace Terminal.Gui.ViewTests { super.Add (vert); Application.Begin (Application.Top); + ((FakeDriver)Application.Driver).SetBufferSize (width, height); var expected = @" ┌─┐ @@ -569,8 +563,7 @@ namespace Terminal.Gui.ViewTests { Assert.True (_scrollBar.OtherScrollBarView.Visible); Assert.Equal ("View(Width,HostView()({X=0,Y=0,Width=80,Height=25}))", _scrollBar.OtherScrollBarView.Width.ToString ()); - // BUGBUG: v2 - Tig broke this test; not sure why. @bdisp? - //Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width); + Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width); Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height); @@ -587,8 +580,7 @@ namespace Terminal.Gui.ViewTests { Assert.False (_scrollBar.OtherScrollBarView.Visible); Assert.Equal ("View(Width,HostView()({X=0,Y=0,Width=80,Height=25}))", _scrollBar.OtherScrollBarView.Width.ToString ()); - // BUGBUG: v2 - Tig broke this test; not sure why. @bdisp? - //Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width); + Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width); Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height); @@ -600,14 +592,12 @@ namespace Terminal.Gui.ViewTests { Assert.Equal (1, _scrollBar.Bounds.Width); Assert.Equal ("View(Height,HostView()({X=0,Y=0,Width=80,Height=25}))", _scrollBar.Height.ToString ()); - // BUGBUG: v2 - Tig broke this test; not sure why. @bdisp? - //Assert.Equal (25, _scrollBar.Bounds.Height); + Assert.Equal (25, _scrollBar.Bounds.Height); Assert.False (_scrollBar.OtherScrollBarView.ShowScrollIndicator); Assert.False (_scrollBar.OtherScrollBarView.Visible); Assert.Equal ("View(Width,HostView()({X=0,Y=0,Width=80,Height=25}))", _scrollBar.OtherScrollBarView.Width.ToString ()); - // BUGBUG: v2 - Tig broke this test; not sure why. @bdisp? - //Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width); + Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width); Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height); @@ -798,7 +788,6 @@ namespace Terminal.Gui.ViewTests { Assert.False (sbv.OtherScrollBarView.CanScroll (10, out max, sbv.OtherScrollBarView.IsVertical)); Assert.Equal (0, max); - // BUGBUG: v2 - bounds etc... are not valid until after BeginInit Application.Begin (top); // They aren't visible so they aren't drawn. @@ -876,7 +865,6 @@ namespace Terminal.Gui.ViewTests { } }; - // BUGBUG: v2 - Don't mix layout and redraw! Redraw should not change layout. It's ok for Layout to cause redraw. textView.LayoutComplete += (s, e) => { scrollBar.Size = textView.Lines; scrollBar.Position = textView.TopRow; @@ -1166,5 +1154,67 @@ This is a test Assert.False (sbv.ShowScrollIndicator); Assert.False (sbv.Visible); } + + + [Fact, AutoInitShutdown] + public void ClearOnVisibleFalse_Gets_Sets () + { + + var text = "This is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test"; + var label = new Label (text); + Application.Top.Add (label); + + var sbv = new ScrollBarView (label, true, false) { + Size = 100, + ClearOnVisibleFalse = false + }; + Application.Begin (Application.Top); + + Assert.True (sbv.Visible); + TestHelpers.AssertDriverContentsWithFrameAre (@" +This is a tes▲ +This is a tes┬ +This is a tes┴ +This is a tes░ +This is a tes░ +This is a tes▼ +", output); + + sbv.Visible = false; + Assert.False (sbv.Visible); + Application.Top.Redraw (Application.Top.Bounds); + TestHelpers.AssertDriverContentsWithFrameAre (@" +This is a test +This is a test +This is a test +This is a test +This is a test +This is a test +", output); + + sbv.Visible = true; + Assert.True (sbv.Visible); + Application.Top.Redraw (Application.Top.Bounds); + TestHelpers.AssertDriverContentsWithFrameAre (@" +This is a tes▲ +This is a tes┬ +This is a tes┴ +This is a tes░ +This is a tes░ +This is a tes▼ +", output); + + sbv.ClearOnVisibleFalse = true; + sbv.Visible = false; + Assert.False (sbv.Visible); + TestHelpers.AssertDriverContentsWithFrameAre (@" +This is a tes +This is a tes +This is a tes +This is a tes +This is a tes +This is a tes +", output); + } } } diff --git a/UnitTests/Views/ScrollViewTests.cs b/UnitTests/Views/ScrollViewTests.cs index 4188b2b98..0c18671c3 100644 --- a/UnitTests/Views/ScrollViewTests.cs +++ b/UnitTests/Views/ScrollViewTests.cs @@ -1,8 +1,9 @@ -using NStack; +using Microsoft.VisualStudio.TestPlatform.Utilities; +using NStack; using Xunit; using Xunit.Abstractions; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class ScrollViewTests { readonly ITestOutputHelper output; @@ -391,37 +392,37 @@ namespace Terminal.Gui.ViewTests { // Application.Begin (Application.Top); // TestHelpers.AssertDriverContentsWithFrameAre (@" - // █████████▲ - // ██████But┬ - // █████████┴ - // ┌────────░ - // │ But░ - // └────────░ - // ┌────────░ - // │ But░ - // └────────▼ - // ◄├┤░░░░░► ", output); + // █████████▲ + // ██████But┬ + // █████████┴ + // ┌────────░ + // │ But░ + // └────────░ + // ┌────────░ + // │ But░ + // └────────▼ + // ◄├┤░░░░░► ", output); // sv.ContentOffset = new Point (5, 5); // sv.LayoutSubviews (); // Application.Refresh (); // TestHelpers.AssertDriverContentsWithFrameAre (@" - // ─────────▲ - // ─────────┬ - // Button 2│ - // ─────────┴ - // ─────────░ - // Button 3░ - // ─────────░ - // ─────────░ - // Button 4▼ - // ◄├─┤░░░░► ", output); + // ─────────▲ + // ─────────┬ + // Button 2│ + // ─────────┴ + // ─────────░ + // Button 3░ + // ─────────░ + // ─────────░ + // Button 4▼ + // ◄├─┤░░░░► ", output); //} //private class CustomButton : FrameView { // private Label labelFill; // private Label labelText; - + // public CustomButton (string fill, ustring text, int width, int height) : base () // { // Width = width; @@ -439,7 +440,7 @@ namespace Terminal.Gui.ViewTests { // } // labelFill.Text = fillText.ToString (); // }; - + // labelText = new Label (text) { X = Pos.Center (), Y = Pos.Center () }; // Add (labelFill, labelText); // CanFocus = true; @@ -600,5 +601,284 @@ namespace Terminal.Gui.ViewTests { 00000000000000000000000 00000000000000000000000", attributes); } + + + [Fact, AutoInitShutdown] + public void DrawTextFormatter_Respects_The_Clip_Bounds () + { + var view = new View (new Rect (0, 0, 20, 20)); + view.Add (new Label ("0123456789abcdefghij")); + view.Add (new Label (0, 1, "1\n2\n3\n4\n5\n6\n7\n8\n9\n0")); + view.Add (new Button (1, 1, "Press me!")); + var scrollView = new ScrollView (new Rect (1, 1, 15, 10)) { + ContentSize = new Size (40, 40), + ShowHorizontalScrollIndicator = true, + ShowVerticalScrollIndicator = true + }; + scrollView.Add (view); + var win = new Window (new Rect (1, 1, 20, 14), "Test"); + win.Add (scrollView); + Application.Top.Add (win); + Application.Begin (Application.Top); + + var expected = @" + ┌┤Test├────────────┐ + │ │ + │ 0123456789abcd▲ │ + │ 1[ Press me! ]┬ │ + │ 2 │ │ + │ 3 ┴ │ + │ 4 ░ │ + │ 5 ░ │ + │ 6 ░ │ + │ 7 ░ │ + │ 8 ▼ │ + │ ◄├───┤░░░░░░░► │ + │ │ + └──────────────────┘ +" + ; + + var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (1, 1, 21, 14), pos); + + Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); + Application.Top.Redraw (Application.Top.Bounds); + + expected = @" + ┌┤Test├────────────┐ + │ │ + │ 123456789abcde▲ │ + │ [ Press me! ] ┬ │ + │ │ │ + │ ┴ │ + │ ░ │ + │ ░ │ + │ ░ │ + │ ░ │ + │ ▼ │ + │ ◄├───┤░░░░░░░► │ + │ │ + └──────────────────┘ +" + ; + + pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (1, 1, 21, 14), pos); + + Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); + Application.Top.Redraw (Application.Top.Bounds); + + expected = @" + ┌┤Test├────────────┐ + │ │ + │ 23456789abcdef▲ │ + │ Press me! ] ┬ │ + │ │ │ + │ ┴ │ + │ ░ │ + │ ░ │ + │ ░ │ + │ ░ │ + │ ▼ │ + │ ◄├────┤░░░░░░► │ + │ │ + └──────────────────┘ +" + ; + + pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (1, 1, 21, 14), pos); + + Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); + Application.Top.Redraw (Application.Top.Bounds); + + expected = @" + ┌┤Test├────────────┐ + │ │ + │ 3456789abcdefg▲ │ + │ Press me! ] ┬ │ + │ │ │ + │ ┴ │ + │ ░ │ + │ ░ │ + │ ░ │ + │ ░ │ + │ ▼ │ + │ ◄├────┤░░░░░░► │ + │ │ + └──────────────────┘ +" + ; + + pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (1, 1, 21, 14), pos); + + Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); + Application.Top.Redraw (Application.Top.Bounds); + + expected = @" + ┌┤Test├────────────┐ + │ │ + │ 456789abcdefgh▲ │ + │ ress me! ] ┬ │ + │ │ │ + │ ┴ │ + │ ░ │ + │ ░ │ + │ ░ │ + │ ░ │ + │ ▼ │ + │ ◄░├───┤░░░░░░► │ + │ │ + └──────────────────┘ +" + ; + + pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (1, 1, 21, 14), pos); + + Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); + Application.Top.Redraw (Application.Top.Bounds); + + expected = @" + ┌┤Test├────────────┐ + │ │ + │ 56789abcdefghi▲ │ + │ ess me! ] ┬ │ + │ │ │ + │ ┴ │ + │ ░ │ + │ ░ │ + │ ░ │ + │ ░ │ + │ ▼ │ + │ ◄░├────┤░░░░░► │ + │ │ + └──────────────────┘ +" + ; + + pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (1, 1, 21, 14), pos); + + Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); + Application.Top.Redraw (Application.Top.Bounds); + + expected = @" + ┌┤Test├────────────┐ + │ │ + │ 6789abcdefghij▲ │ + │ ss me! ] ┬ │ + │ │ │ + │ ┴ │ + │ ░ │ + │ ░ │ + │ ░ │ + │ ░ │ + │ ▼ │ + │ ◄░├────┤░░░░░► │ + │ │ + └──────────────────┘ +" + ; + + pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (1, 1, 21, 14), pos); + + Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); + Application.Top.Redraw (Application.Top.Bounds); + + expected = @" + ┌┤Test├────────────┐ + │ │ + │ 789abcdefghij ▲ │ + │ s me! ] ┬ │ + │ │ │ + │ ┴ │ + │ ░ │ + │ ░ │ + │ ░ │ + │ ░ │ + │ ▼ │ + │ ◄░░├───┤░░░░░► │ + │ │ + └──────────────────┘ +"; + + pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (1, 1, 21, 14), pos); + + Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Home, new KeyModifiers ()))); + Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ()))); + Application.Top.Redraw (Application.Top.Bounds); + + expected = @" + ┌┤Test├────────────┐ + │ │ + │ 1[ Press me! ]▲ │ + │ 2 ┬ │ + │ 3 │ │ + │ 4 ┴ │ + │ 5 ░ │ + │ 6 ░ │ + │ 7 ░ │ + │ 8 ░ │ + │ 9 ▼ │ + │ ◄├───┤░░░░░░░► │ + │ │ + └──────────────────┘ +"; + + pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (1, 1, 21, 14), pos); + + Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ()))); + Application.Top.Redraw (Application.Top.Bounds); + + expected = @" + ┌┤Test├────────────┐ + │ │ + │ 2 ▲ │ + │ 3 ┬ │ + │ 4 │ │ + │ 5 ┴ │ + │ 6 ░ │ + │ 7 ░ │ + │ 8 ░ │ + │ 9 ░ │ + │ 0 ▼ │ + │ ◄├───┤░░░░░░░► │ + │ │ + └──────────────────┘ +"; + + pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (1, 1, 21, 14), pos); + + Assert.True (scrollView.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ()))); + Application.Top.Redraw (Application.Top.Bounds); + + expected = @" + ┌┤Test├────────────┐ + │ │ + │ 3 ▲ │ + │ 4 ┬ │ + │ 5 │ │ + │ 6 ┴ │ + │ 7 ░ │ + │ 8 ░ │ + │ 9 ░ │ + │ 0 ░ │ + │ ▼ │ + │ ◄├───┤░░░░░░░► │ + │ │ + └──────────────────┘ +"; + + pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new Rect (1, 1, 21, 14), pos); + } + } } diff --git a/UnitTests/Views/StatusBarTests.cs b/UnitTests/Views/StatusBarTests.cs index feb2a0f05..8cc44f3d6 100644 --- a/UnitTests/Views/StatusBarTests.cs +++ b/UnitTests/Views/StatusBarTests.cs @@ -2,7 +2,7 @@ using Xunit; using Xunit.Abstractions; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class StatusBarTests { readonly ITestOutputHelper output; diff --git a/UnitTests/Views/TabViewTests.cs b/UnitTests/Views/TabViewTests.cs index 0e3d43938..419fb646e 100644 --- a/UnitTests/Views/TabViewTests.cs +++ b/UnitTests/Views/TabViewTests.cs @@ -8,7 +8,7 @@ using Xunit; using System.Globalization; using Xunit.Abstractions; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class TabViewTests { readonly ITestOutputHelper output; diff --git a/UnitTests/Views/TableViewTests.cs b/UnitTests/Views/TableViewTests.cs index ade213d2c..8d6acde2b 100644 --- a/UnitTests/Views/TableViewTests.cs +++ b/UnitTests/Views/TableViewTests.cs @@ -8,8 +8,9 @@ using Xunit; using System.Globalization; using Xunit.Abstractions; using System.Reflection; +using Terminal.Gui.ViewTests; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class TableViewTests { readonly ITestOutputHelper output; @@ -268,6 +269,7 @@ namespace Terminal.Gui.ViewTests { Application.Top.Add (tableView); Application.Begin (Application.Top); + Application.Top.FocusFirst (); Assert.True (tableView.HasFocus); diff --git a/UnitTests/Views/TextFieldTests.cs b/UnitTests/Views/TextFieldTests.cs index f44e2b657..6de5aa557 100644 --- a/UnitTests/Views/TextFieldTests.cs +++ b/UnitTests/Views/TextFieldTests.cs @@ -6,7 +6,7 @@ using System.Reflection; using Xunit; using Xunit.Abstractions; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class TextFieldTests { readonly ITestOutputHelper output; diff --git a/UnitTests/Views/TextValidateFieldTests.cs b/UnitTests/Views/TextValidateFieldTests.cs index 94999c363..777474dc7 100644 --- a/UnitTests/Views/TextValidateFieldTests.cs +++ b/UnitTests/Views/TextValidateFieldTests.cs @@ -5,7 +5,7 @@ using Terminal.Gui.TextValidateProviders; using Xunit; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class TextValidateField_NET_Provider_Tests { diff --git a/UnitTests/Views/TextViewTests.cs b/UnitTests/Views/TextViewTests.cs index dc16e8645..204123ecf 100644 --- a/UnitTests/Views/TextViewTests.cs +++ b/UnitTests/Views/TextViewTests.cs @@ -6,7 +6,7 @@ using System.Text.RegularExpressions; using Xunit; using Xunit.Abstractions; -namespace Terminal.Gui.ViewTests { +namespace Terminal.Gui.ViewsTests { public class TextViewTests { private static TextView _textView; readonly ITestOutputHelper output; @@ -6808,7 +6808,6 @@ This is the second line. Width = 50, Height = 10, }; - // BUGBUG: v2 - views must be initialzed before doing things. tv.BeginInit (); tv.EndInit (); tv.ContentsChanged += (s, e) => { diff --git a/UnitTests/Views/TileViewTests.cs b/UnitTests/Views/TileViewTests.cs index 08ce06033..2e637f55b 100644 --- a/UnitTests/Views/TileViewTests.cs +++ b/UnitTests/Views/TileViewTests.cs @@ -1,2360 +1,2359 @@ using System; using System.ComponentModel; using System.Linq; -using Terminal.Gui.Graphs; using Xunit; using Xunit.Abstractions; -namespace Terminal.Gui.ViewTests { - public class TileViewTests { - // BUGBUG: v2 - These tests are all broken for now -#if false - readonly ITestOutputHelper output; - - public TileViewTests (ITestOutputHelper output) - { - this.output = output; - } - - - [Fact, AutoInitShutdown] - public void TestTileView_Vertical () - { - var tileView = Get11By3TileView (out var line); - tileView.Redraw (tileView.Bounds); - - string looksLike = -@" -11111│22222 -11111│22222 - │ "; - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // Keyboard movement on splitter should have no effect if it is not focused - line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); - tileView.SetNeedsDisplay (); - tileView.Redraw (tileView.Bounds); - TestHelpers.AssertDriverContentsAre (looksLike, output); - - } - [Fact, AutoInitShutdown] - public void TestTileView_Vertical_WithBorder () - { - var tileView = Get11By3TileView (out var line, true); - tileView.Redraw (tileView.Bounds); - - string looksLike = -@" -┌────┬────┐ -│1111│2222│ -└────┴────┘"; - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // Keyboard movement on splitter should have no effect if it is not focused - line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); - tileView.SetNeedsDisplay (); - tileView.Redraw (tileView.Bounds); - TestHelpers.AssertDriverContentsAre (looksLike, output); - - } - [Fact, AutoInitShutdown] - public void TestTileView_Vertical_Focused () - { - var tileView = Get11By3TileView (out var line); - tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ())); - - tileView.Redraw (tileView.Bounds); - - string looksLike = -@" -11111│22222 -11111◊22222 - │ "; - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // Now while focused move the splitter 1 unit right - line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); - tileView.Redraw (tileView.Bounds); - - looksLike = -@" -111111│2222 -111111◊2222 - │ "; - TestHelpers.AssertDriverContentsAre (looksLike, output); - - - // and 2 to the left - line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); - line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); - tileView.Redraw (tileView.Bounds); - - looksLike = -@" -1111│222222 -1111◊222222 - │ "; - TestHelpers.AssertDriverContentsAre (looksLike, output); - } - - [Fact, AutoInitShutdown] - public void TestTileView_Vertical_Focused_WithBorder () - { - var tileView = Get11By3TileView (out var line, true); - tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ())); - - tileView.Redraw (tileView.Bounds); - - string looksLike = -@" -┌────┬────┐ -│1111◊2222│ -└────┴────┘"; - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // Now while focused move the splitter 1 unit right - line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); - tileView.Redraw (tileView.Bounds); - - looksLike = -@" -┌─────┬───┐ -│11111◊222│ -└─────┴───┘"; - TestHelpers.AssertDriverContentsAre (looksLike, output); - - - // and 2 to the left - line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); - line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); - tileView.Redraw (tileView.Bounds); - - looksLike = -@" -┌───┬─────┐ -│111◊22222│ -└───┴─────┘"; - TestHelpers.AssertDriverContentsAre (looksLike, output); - } - - - [Fact, AutoInitShutdown] - public void TestTileView_Vertical_Focused_50PercentSplit () - { - var tileView = Get11By3TileView (out var line); - tileView.SetSplitterPos (0, Pos.Percent (50)); - Assert.IsType (tileView.SplitterDistances.ElementAt (0)); - tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ())); - - tileView.Redraw (tileView.Bounds); - - string looksLike = -@" -11111│22222 -11111◊22222 - │ "; - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // Now while focused move the splitter 1 unit right - line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); - tileView.Redraw (tileView.Bounds); - - looksLike = -@" -111111│2222 -111111◊2222 - │ "; - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // Even when moving the splitter location it should stay a Percentage based one - Assert.IsType (tileView.SplitterDistances.ElementAt (0)); - - - // and 2 to the left - line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); - line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); - tileView.Redraw (tileView.Bounds); - - looksLike = -@" -1111│222222 -1111◊222222 - │ "; - TestHelpers.AssertDriverContentsAre (looksLike, output); - // Even when moving the splitter location it should stay a Percentage based one - Assert.IsType (tileView.SplitterDistances.ElementAt (0)); - } - - [Fact, AutoInitShutdown] - public void TestTileView_Horizontal () - { - var tileView = Get11By3TileView (out var line); - tileView.Orientation = Terminal.Gui.Graphs.Orientation.Horizontal; - tileView.Redraw (tileView.Bounds); - - string looksLike = -@" -11111111111 -─────────── -22222222222"; - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // Keyboard movement on splitter should have no effect if it is not focused - line.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())); - tileView.SetNeedsDisplay (); - tileView.Redraw (tileView.Bounds); - TestHelpers.AssertDriverContentsAre (looksLike, output); - } - - - [Fact, AutoInitShutdown] - public void TestTileView_Vertical_View1MinSize_Absolute () - { - var tileView = Get11By3TileView (out var line); - tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ())); - tileView.Tiles.ElementAt (0).MinSize = 6; - - // distance is too small (below 6) - Assert.False (tileView.SetSplitterPos (0, 2)); - - // Should stay where it was originally at (50%) - Assert.Equal (Pos.Percent (50), tileView.SplitterDistances.ElementAt (0)); - - tileView.Redraw (tileView.Bounds); - - // so should ignore the 2 distance and stick to 6 - string looksLike = -@" -11111│22222 -11111◊22222 - │ "; - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // Keyboard movement on splitter should have no effect because it - // would take us below the minimum splitter size - line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); - tileView.SetNeedsDisplay (); - tileView.Redraw (tileView.Bounds); - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // but we can continue to move the splitter right if we want - line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); - tileView.SetNeedsDisplay (); - tileView.Redraw (tileView.Bounds); - - looksLike = -@" -111111│2222 -111111◊2222 - │ "; - - TestHelpers.AssertDriverContentsAre (looksLike, output); - } - - - [Fact, AutoInitShutdown] - public void TestTileView_Vertical_View1MinSize_Absolute_WithBorder () - { - var tileView = Get11By3TileView (out var line, true); - tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ())); - tileView.Tiles.ElementAt (0).MinSize = 5; - - // distance is too small (below 5) - Assert.False (tileView.SetSplitterPos (0, 2)); - - // Should stay where it was originally at (50%) - Assert.Equal (Pos.Percent (50), tileView.SplitterDistances.ElementAt (0)); - - tileView.Redraw (tileView.Bounds); - - // so should ignore the 2 distance and stick to 5 - string looksLike = -@" -┌────┬────┐ -│1111◊2222│ -└────┴────┘"; - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // Keyboard movement on splitter should have no effect because it - // would take us below the minimum splitter size - line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); - tileView.SetNeedsDisplay (); - tileView.Redraw (tileView.Bounds); - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // but we can continue to move the splitter right if we want - line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); - tileView.SetNeedsDisplay (); - tileView.Redraw (tileView.Bounds); - - looksLike = -@" -┌─────┬───┐ -│11111◊222│ -└─────┴───┘"; - - TestHelpers.AssertDriverContentsAre (looksLike, output); - } - - [Fact, AutoInitShutdown] - public void TestTileView_Vertical_View2MinSize_Absolute () - { - var tileView = Get11By3TileView (out var line); - tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ())); - tileView.Tiles.ElementAt (1).MinSize = 6; - - // distance leaves too little space for view2 (less than 6 would remain) - Assert.False (tileView.SetSplitterPos (0, 8)); - - // Should stay where it was originally at (50%) - Assert.Equal (Pos.Percent (50), tileView.SplitterDistances.ElementAt (0)); - - tileView.Redraw (tileView.Bounds); - - // so should ignore the 2 distance and stick to 6 - string looksLike = -@" -11111│22222 -11111◊22222 - │ "; - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // Keyboard movement on splitter should have no effect because it - // would take us below the minimum splitter size - line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); - tileView.SetNeedsDisplay (); - tileView.Redraw (tileView.Bounds); - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // but we can continue to move the splitter left if we want - line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); - tileView.SetNeedsDisplay (); - tileView.Redraw (tileView.Bounds); - - looksLike = -@" -1111│222222 -1111◊222222 - │ "; - - TestHelpers.AssertDriverContentsAre (looksLike, output); - - } - [Fact, AutoInitShutdown] - public void TestTileView_Vertical_View2MinSize_Absolute_WithBorder () - { - var tileView = Get11By3TileView (out var line, true); - tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ())); - tileView.Tiles.ElementAt (1).MinSize = 5; - - // distance leaves too little space for view2 (less than 5 would remain) - Assert.False (tileView.SetSplitterPos (0, 8)); - - // Should stay where it was originally at (50%) - Assert.Equal (Pos.Percent (50), tileView.SplitterDistances.ElementAt (0)); - - tileView.Redraw (tileView.Bounds); - - // so should ignore the 2 distance and stick to 6 - string looksLike = -@" -┌────┬────┐ -│1111◊2222│ -└────┴────┘"; - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // Keyboard movement on splitter should have no effect because it - // would take us below the minimum splitter size - line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); - tileView.SetNeedsDisplay (); - tileView.Redraw (tileView.Bounds); - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // but we can continue to move the splitter left if we want - line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); - tileView.SetNeedsDisplay (); - tileView.Redraw (tileView.Bounds); - - looksLike = -@" -┌───┬─────┐ -│111◊22222│ -└───┴─────┘"; - - TestHelpers.AssertDriverContentsAre (looksLike, output); - } - - [Fact, AutoInitShutdown] - public void TestTileView_InsertPanelAtStart () - { - var tileView = Get11By3TileView (out var line, true); - tileView.InsertTile (0); - - tileView.Redraw (tileView.Bounds); - - // so should ignore the 2 distance and stick to 6 - string looksLike = -@" -┌──┬───┬──┐ -│ │111│22│ -└──┴───┴──┘"; - TestHelpers.AssertDriverContentsAre (looksLike, output); - } - - [Fact, AutoInitShutdown] - public void TestTileView_InsertPanelMiddle () - { - var tileView = Get11By3TileView (out var line, true); - tileView.InsertTile (1); - - tileView.Redraw (tileView.Bounds); - - // so should ignore the 2 distance and stick to 6 - string looksLike = -@" -┌──┬───┬──┐ -│11│ │22│ -└──┴───┴──┘"; - TestHelpers.AssertDriverContentsAre (looksLike, output); - } - - [Fact, AutoInitShutdown] - public void TestTileView_InsertPanelAtEnd () - { - var tileView = Get11By3TileView (out var line, true); - tileView.InsertTile (2); - - tileView.Redraw (tileView.Bounds); - - // so should ignore the 2 distance and stick to 6 - string looksLike = -@" -┌──┬───┬──┐ -│11│222│ │ -└──┴───┴──┘"; - TestHelpers.AssertDriverContentsAre (looksLike, output); - } - - [Fact, AutoInitShutdown] - public void TestTileView_Horizontal_Focused () - { - var tileView = Get11By3TileView (out var line); - - tileView.Orientation = Terminal.Gui.Graphs.Orientation.Horizontal; - tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ())); - - Assert.True (line.HasFocus); - - tileView.Redraw (tileView.Bounds); - - string looksLike = -@" -11111111111 -─────◊───── -22222222222"; - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // Now move splitter line down - line.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())); - - tileView.Redraw (tileView.Bounds); - looksLike = -@" -11111111111 -11111111111 -─────◊─────"; - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // And 2 up - line.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ())); - line.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ())); - tileView.SetNeedsDisplay (); - tileView.Redraw (tileView.Bounds); - looksLike = -@" -─────◊───── -22222222222 -22222222222"; - TestHelpers.AssertDriverContentsAre (looksLike, output); - } - - - [Fact, AutoInitShutdown] - public void TestTileView_Horizontal_View1MinSize_Absolute () - { - var tileView = Get11By3TileView (out var line); - tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ())); - - tileView.Orientation = Terminal.Gui.Graphs.Orientation.Horizontal; - tileView.Tiles.ElementAt (0).MinSize = 1; - - // 0 should not be allowed because it brings us below minimum size of View1 - Assert.False (tileView.SetSplitterPos (0, 0)); - // position should remain where it was, at 50% - Assert.Equal (Pos.Percent (50f), tileView.SplitterDistances.ElementAt (0)); - - tileView.Redraw (tileView.Bounds); - - string looksLike = -@" -11111111111 -─────◊───── -22222222222"; - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // Now move splitter line down (allowed - line.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())); - tileView.Redraw (tileView.Bounds); - looksLike = -@" -11111111111 -11111111111 -─────◊─────"; - TestHelpers.AssertDriverContentsAre (looksLike, output); - - // And up 2 (only 1 is allowed because of minimum size of 1 on view1) - line.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ())); - line.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ())); - - tileView.SetNeedsDisplay (); - tileView.Redraw (tileView.Bounds); - looksLike = -@" -11111111111 -─────◊───── -22222222222"; - TestHelpers.AssertDriverContentsAre (looksLike, output); - } - - [Fact, AutoInitShutdown] - public void TestTileView_CannotSetSplitterPosToFuncEtc () - { - var tileView = Get11By3TileView (); - - var ex = Assert.Throws (() => tileView.SetSplitterPos (0, Pos.Right (tileView))); - Assert.Equal ("Only Percent and Absolute values are supported. Passed value was PosCombine", ex.Message); - - - ex = Assert.Throws (() => tileView.SetSplitterPos (0, Pos.Function (() => 1))); - Assert.Equal ("Only Percent and Absolute values are supported. Passed value was PosFunc", ex.Message); - - // Also not allowed because this results in a PosCombine - ex = Assert.Throws (() => tileView.SetSplitterPos (0, Pos.Percent (50) - 1)); - Assert.Equal ("Only Percent and Absolute values are supported. Passed value was PosCombine", ex.Message); - } - - [Fact, AutoInitShutdown] - public void TestNestedContainer2LeftAnd1Right_RendersNicely () - { - var tileView = GetNestedContainer2Left1Right (false); - - Assert.Equal (20, tileView.Frame.Width); - Assert.Equal (10, tileView.Tiles.ElementAt (0).ContentView.Frame.Width); - Assert.Equal (9, tileView.Tiles.ElementAt (1).ContentView.Frame.Width); - - Assert.IsType (tileView.Tiles.ElementAt (0).ContentView); - var left = (TileView)tileView.Tiles.ElementAt (0).ContentView; - Assert.Same (left.SuperView, tileView); - - - Assert.Equal (2, left.Tiles.ElementAt (0).ContentView.Subviews.Count); - Assert.IsType