From 2fecd50a546633c12f33dc6c7fb875b09b174030 Mon Sep 17 00:00:00 2001 From: BDisp Date: Sat, 16 Nov 2019 20:57:54 +0000 Subject: [PATCH 01/22] Fixes #290 issue "Redraw issue when setting coordinates of label" --- .editorconfig | 3 +++ Designer/Program.cs | 34 ++++++++++++++++++++++++++++++++++ Terminal.Gui/Core.cs | 19 ++++++++++++++++++- Terminal.Gui/Types/PosDim.cs | 18 ++++++++++++++++-- 4 files changed, 71 insertions(+), 3 deletions(-) diff --git a/.editorconfig b/.editorconfig index 3ad2ee46d..576839082 100644 --- a/.editorconfig +++ b/.editorconfig @@ -17,3 +17,6 @@ csharp_preserve_single_line_blocks = true dotnet_style_require_accessibility_modifiers = never csharp_style_var_when_type_is_apparent = true csharp_prefer_braces = false +csharp_space_before_open_square_brackets = true +csharp_space_between_method_call_name_and_opening_parenthesis = true +csharp_space_between_method_declaration_name_and_open_parenthesis = true \ No newline at end of file diff --git a/Designer/Program.cs b/Designer/Program.cs index d3dac91a4..0d2fffe63 100644 --- a/Designer/Program.cs +++ b/Designer/Program.cs @@ -2,6 +2,7 @@ using Terminal.Gui; namespace Designer { +#if false class Surface : Window { public Surface () : base ("Designer") { @@ -42,4 +43,37 @@ namespace Designer { Application.Run (); } } +#elif true + class MainClass { + public static void Main (string [] args) + { + + string [] radioLabels = { "First", "Second" }; + Application.Init (); + + Window window = new Window ("Redraw issue when setting coordinates of label") { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; + + Label radioLabel = new Label ("Radio selection: ") { X = 1, Y = 1 }; + Label otherLabel = new Label ("Other label: ") { X = Pos.Left (radioLabel), Y = Pos.Top (radioLabel) + radioLabels.Length }; + + RadioGroup radioGroup = new RadioGroup (radioLabels) { X = Pos.Right (radioLabel), Y = Pos.Top (radioLabel) }; + RadioGroup radioGroup2 = new RadioGroup (new [] { "Option 1 of the second radio group", "Option 2 of the second radio group" }) { X = Pos.Right (radioLabel), Y = Pos.Top (otherLabel) }; + + Button replaceButton = new Button (1, 10, "Add radio labels") { + Clicked = () => { + radioGroup.RadioLabels = new [] { "First", "Second", "Third <- Third ->", "Fourth <- Fourth ->" }; + otherLabel.Y = Pos.Top (radioLabel) + radioGroup.RadioLabels.Length; + //Application.Refresh(); // Even this won't redraw the app correctly, only a terminal resize will re-render the view. + //typeof(Application).GetMethod("TerminalResized", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).Invoke(null, null); + } + }; + + window.Add (radioLabel, otherLabel, radioGroup, radioGroup2, replaceButton); + Application.Top.Add (window); + Application.Top.Add (window); + Application.Run (); + Application.Run (); + } + } +#endif } diff --git a/Terminal.Gui/Core.cs b/Terminal.Gui/Core.cs index 32bb3f630..872761afe 100644 --- a/Terminal.Gui/Core.cs +++ b/Terminal.Gui/Core.cs @@ -430,7 +430,7 @@ namespace Terminal.Gui { SetNeedsDisplay (Bounds); } - bool layoutNeeded = true; + internal bool layoutNeeded = true; internal void SetNeedsLayout () { @@ -2041,11 +2041,28 @@ namespace Terminal.Gui { DrawBounds (state.Toplevel); state.Toplevel.PositionCursor (); Driver.Refresh (); + } else if (CheckLayoutNeeded (state.Toplevel)) { + TerminalResized (); + layoutNeeded = false; } else Driver.UpdateCursor (); } } + static bool layoutNeeded; + static bool CheckLayoutNeeded (View view) + { + if (view.layoutNeeded) + return layoutNeeded = view.layoutNeeded; + + for (int i = 0; view.Subviews.Count > i; i++) { + CheckLayoutNeeded (view.Subviews [i]); + if (layoutNeeded) + return layoutNeeded; + } + return layoutNeeded; + } + internal static bool DebugDrawBounds; // Need to look into why this does not work properly. diff --git a/Terminal.Gui/Types/PosDim.cs b/Terminal.Gui/Types/PosDim.cs index bf7fdf16c..5e675644c 100644 --- a/Terminal.Gui/Types/PosDim.cs +++ b/Terminal.Gui/Types/PosDim.cs @@ -187,8 +187,16 @@ namespace Terminal.Gui { else return la - ra; } + + public override string ToString () + { + return $"{((PosView)left).Target.ToString ()},{right.ToString ()}"; + } + } + static PosCombine posCombine; + /// /// Adds a to a , yielding a new . /// @@ -197,7 +205,10 @@ namespace Terminal.Gui { /// The that is the sum of the values of left and right. public static Pos operator + (Pos left, Pos right) { - return new PosCombine (true, left, right); + PosCombine newPos = new PosCombine (true, left, right); + if (posCombine?.ToString () != newPos.ToString ()) + ((PosView)left).Target.SetNeedsLayout (); + return posCombine = newPos; } /// @@ -208,7 +219,10 @@ namespace Terminal.Gui { /// The that is the left minus right. public static Pos operator - (Pos left, Pos right) { - return new PosCombine (false, left, right); + PosCombine newPos = new PosCombine (false, left, right); + if (posCombine?.ToString () != newPos.ToString ()) + ((PosView)left).Target.SetNeedsLayout (); + return posCombine = newPos; } internal class PosView : Pos { From 746512dc4c932444e292588c5b379e956882083c Mon Sep 17 00:00:00 2001 From: Daniel Cazzulino Date: Sat, 2 Nov 2019 23:19:40 -0300 Subject: [PATCH 02/22] Add documentation on ISupportInitialize/ISupportInitializeNotification (#286) --- Terminal.Gui/Core.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Terminal.Gui/Core.cs b/Terminal.Gui/Core.cs index 872761afe..465f036e3 100644 --- a/Terminal.Gui/Core.cs +++ b/Terminal.Gui/Core.cs @@ -1283,6 +1283,19 @@ namespace Terminal.Gui { /// toplevel and then invoke with the /// new toplevel. /// + /// + /// TopLevels can also opt-in to more sophisticated initialization + /// by implementing . When they do + /// so, the and + /// methods will be called + /// before running the view. + /// If first-run-only initialization is preferred, the + /// can be implemented too, in which case the + /// methods will only be called if + /// is . This allows proper View inheritance hierarchies + /// to override base class layout code optimally by doing so only on first run, + /// instead of on every run. + /// /// public class Toplevel : View { /// From a926ff50897e721156395932d1f35130ca1091fd Mon Sep 17 00:00:00 2001 From: Marius Ungureanu Date: Sun, 3 Nov 2019 04:20:08 +0200 Subject: [PATCH 03/22] Switch netcoreapp target to netstandard2.0 (#284) Fixes #283 Instead of adding another target framework to the list, switch from netcoreapp2.0 to netstandard2.0, as ns2.0 is a subset of netcoreapp. --- Terminal.Gui/Terminal.Gui.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj index 18afec86f..108351e96 100644 --- a/Terminal.Gui/Terminal.Gui.csproj +++ b/Terminal.Gui/Terminal.Gui.csproj @@ -1,6 +1,6 @@ - net461;netcoreapp2.0 + net461;netstandard2.0 Terminal.Gui Terminal.Gui bin\Release\Terminal.Gui.xml From 55816ab1afecdaf67d7ac32a44f5c8ae1d95a7d9 Mon Sep 17 00:00:00 2001 From: Daniel Cazzulino Date: Sat, 2 Nov 2019 23:22:55 -0300 Subject: [PATCH 04/22] Added TextView.TextChanged event (#264) --- Terminal.Gui/Views/TextView.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Terminal.Gui/Views/TextView.cs b/Terminal.Gui/Views/TextView.cs index 243fd29c4..f0f42b5cc 100644 --- a/Terminal.Gui/Views/TextView.cs +++ b/Terminal.Gui/Views/TextView.cs @@ -1,4 +1,4 @@ -// +// // TextView.cs: multi-line text editing // // Authors: @@ -266,6 +266,8 @@ namespace Terminal.Gui { bool selecting; //bool used; + public event EventHandler TextChanged; + #if false /// /// Changed event, raised when the text has clicked. @@ -312,6 +314,7 @@ namespace Terminal.Gui { set { ResetPosition (); model.LoadString (value); + TextChanged?.Invoke(this, new EventArgs()); SetNeedsDisplay (); } } From 84607b90181284d00ba1d1b8e490e11bd2973de6 Mon Sep 17 00:00:00 2001 From: Adrian Alonso Date: Sun, 3 Nov 2019 15:15:22 -0300 Subject: [PATCH 05/22] Fixed key events traversal for modal dialogs (#288) The key must be propagated initially to the first chain element before evaluating if we should stop because of the handled or the Modal condition. Otherwise the modal dialog won't get any process key notification. This fixes https://github.com/migueldeicaza/gui.cs/commit/c072e29a684068af50e1b9e284213b3839dad804 --- Terminal.Gui/Core.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Terminal.Gui/Core.cs b/Terminal.Gui/Core.cs index 465f036e3..30d3cae4d 100644 --- a/Terminal.Gui/Core.cs +++ b/Terminal.Gui/Core.cs @@ -1812,25 +1812,25 @@ namespace Terminal.Gui { { var chain = toplevels.ToList(); foreach (var topLevel in chain) { - if (topLevel.Modal) - break; if (topLevel.ProcessHotKey (ke)) return; + if (topLevel.Modal) + break; } foreach (var topLevel in chain) { - if (topLevel.Modal) - break; if (topLevel.ProcessKey (ke)) return; + if (topLevel.Modal) + break; } foreach (var topLevel in chain) { - if (topLevel.Modal) - break; // Process the key normally if (topLevel.ProcessColdKey (ke)) return; + if (topLevel.Modal) + break; } } From a17d2e450629895f862cbdce066c73e6eaad9047 Mon Sep 17 00:00:00 2001 From: miguel Date: Mon, 4 Nov 2019 10:00:32 -0500 Subject: [PATCH 06/22] Prepare for 0.25 --- Terminal.Gui/Terminal.Gui.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj index 108351e96..bbf65b172 100644 --- a/Terminal.Gui/Terminal.Gui.csproj +++ b/Terminal.Gui/Terminal.Gui.csproj @@ -18,7 +18,7 @@ Miguel de Icaza Application framework for creating modern console applications using .NET Gui.cs is a framework for creating console user interfaces - 0.24: the Windows driver implements WakeUp, allowing some scenarios like bug #207 to be fixed; + 0.25: Added new TimeField from Jörg Preiß; Fixes for Backtab by Martin Björkström; ListView now supports simple selection; Bug fixes by giladlevi, Daniel Cazzulino and Marius Ungureanu; New Application.Run of T entry point by Daniel Cazzulino; Added various View methods to bring forward, backwards and move views in the hierarchy; Switch to Portable PDBs by Daniel Cazzulino; Dims can now be compared by Daniel Cazzulino; OnMenuOpen handler by giladlevi; Various memory usage optimizations by giladlevi; FileDialog.FilePath is now a full path by Yanwei Wang; ISupportInitialize/ISupportInitializeNotification is now supported thanks to the work from Daniel Cazzulino; Support for non-modal TopLevels by Daniel Cazzulino and Adrian Alonso; 0.24: the Windows driver implements WakeUp, allowing some scenarios like bug #207 to be fixed; 0.23: Better support for disabled menu items; Raises text changed event after the internals have been updated; Fix Caps-NumLock; Alt-HotKey now work on menus 0.22: Correct vertical scrollview behavior, Small curses driver fix for terminals without mouse support, TextView support for scrolling, Surface Used property on TextField, Surface Cursor on RadioGroup. From d0f3ce9e614d2691659120e43a7be7f378d0f8a0 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Tue, 5 Nov 2019 12:36:15 -0500 Subject: [PATCH 07/22] Remove travis link --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index dfbff07bf..6f46f764a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -6,7 +6,7 @@ variables: steps: - script: | - msbuild /t:Restore $TRAVIS_BUILD_DIR/Terminal.sln + msbuild /t:Restore Terminal.sln displayName: Restore dependencies - script: | From a596ea359342c06ec619edeb1e5b662e3c02f317 Mon Sep 17 00:00:00 2001 From: miguel Date: Tue, 26 Nov 2019 20:46:04 -0500 Subject: [PATCH 08/22] Revert Daniel's change 00c5997daaa40f0ee73c8b7d7eccf7b4dfd04194 as it prevents the solution from building on Mac --- .travis.yml | 2 +- Designer/Designer.csproj | 55 +++++++++++++++++++++++++++----- Example/Example.csproj | 51 +++++++++++++++++++++++++---- README.md | 12 ------- Terminal.Gui/Terminal.Gui.csproj | 10 +++++- 5 files changed, 101 insertions(+), 29 deletions(-) diff --git a/.travis.yml b/.travis.yml index 32a026fbe..37ca3f8f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,6 @@ script: - msbuild /t:Restore $TRAVIS_BUILD_DIR/Terminal.sln - cd $TRAVIS_BUILD_DIR/ - msbuild /p:Configuration=Release Terminal.sln -mono: "5.20.0" +mono: "5.20.1" dotnet: "2.1.4" os: "osx" diff --git a/Designer/Designer.csproj b/Designer/Designer.csproj index 72cddf4bc..a81a74d95 100644 --- a/Designer/Designer.csproj +++ b/Designer/Designer.csproj @@ -1,17 +1,56 @@ - + + - net472 + Debug + x86 + {1228D992-C801-49BB-839A-7BD28A3FFF0A} Exe - Terminal - Terminal + Designer + Designer + v4.6.1 + + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 true - AnyCPU;x86 - x86 + x86 + + + true + bin\Release + prompt + 4 + true + x86 - + + + ..\packages\NStack.Core.0.11.0\lib\netstandard1.5\NStack.dll + + + ..\packages\NStack.Core.0.11.0\lib\netstandard1.5\NStack.dll + - + + + + + {00F366F8-DEE4-482C-B9FD-6DB0200B79E5} + Terminal.Gui + + + + + + + \ No newline at end of file diff --git a/Example/Example.csproj b/Example/Example.csproj index f1e193d5a..3f6523667 100644 --- a/Example/Example.csproj +++ b/Example/Example.csproj @@ -1,18 +1,55 @@ - + + - net472 + Debug + x86 + {B0A602CD-E176-449D-8663-64238D54F857} Exe Terminal Terminal + v4.6.1 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 true - AnyCPU;x86 - x86 - StandaloneExample\**\*.*;Terminal.Gui\**\*.* + x86 + + + true + bin\Release + prompt + 4 + bin\Release\Terminal.xml + true + x86 - + + + ..\packages\NStack.Core.0.11.0\lib\netstandard1.5\NStack.dll + False + + + ..\packages\NStack.Core.0.11.0\lib\netstandard1.5\NStack.dll + - + + + + {00F366F8-DEE4-482C-B9FD-6DB0200B79E5} + Terminal.Gui + + + + + + diff --git a/README.md b/README.md index b9c2edba8..caa46939f 100644 --- a/README.md +++ b/README.md @@ -213,15 +213,3 @@ package version has been updated on the Terminal.Gui/Terminal.Gui.csproj, and push. Then once the package is built, VSTS will request an approval. - - -# Known Issues - -There is a [known issue](https://github.com/NuGet/Home/issues/4837) that causes the -referenced package assemblies to be missing from the output directory of your console -apps and therefore fail at run-time. In order to force the copying, you can add the -following property to your console project: - -```xml - true -``` diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj index bbf65b172..677657304 100644 --- a/Terminal.Gui/Terminal.Gui.csproj +++ b/Terminal.Gui/Terminal.Gui.csproj @@ -9,7 +9,7 @@ true Terminal.Gui - 0.25 + 0.24 Miguel de Icaza MIT https://github.com/migueldeicaza/gui.cs/ @@ -69,6 +69,14 @@ + + + ..\..\..\Users\miguel\.nuget\packages\nstack.core\0.11.0\lib\netstandard1.5\NStack.dll + + + ..\..\..\Users\miguel\.nuget\packages\nstack.core\0.11.0\lib\netstandard1.5\NStack.dll + + From 82006a81516614afe9c6aa33d1f2daa93ed56ff8 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Sat, 29 Feb 2020 10:51:36 -0500 Subject: [PATCH 09/22] Prepare for 0.26 --- Terminal.Gui/Terminal.Gui.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj index 677657304..8dee18aa1 100644 --- a/Terminal.Gui/Terminal.Gui.csproj +++ b/Terminal.Gui/Terminal.Gui.csproj @@ -9,7 +9,7 @@ true Terminal.Gui - 0.24 + 0.65 Miguel de Icaza MIT https://github.com/migueldeicaza/gui.cs/ From 4999c71218a520614f3ca4e51096fe617b07a9b3 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Sat, 29 Feb 2020 11:11:48 -0500 Subject: [PATCH 10/22] Restore some files that were deleted by Daniel's commit that I had not restored --- Designer/Designer.csproj | 3 +-- Designer/packages.config | 4 ++++ Example/packages.config | 4 ++++ Terminal.Gui/packages.config | 5 +++++ packages.config | 4 ++++ 5 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 Designer/packages.config create mode 100644 Example/packages.config create mode 100644 Terminal.Gui/packages.config create mode 100644 packages.config diff --git a/Designer/Designer.csproj b/Designer/Designer.csproj index a81a74d95..e87bd0a6b 100644 --- a/Designer/Designer.csproj +++ b/Designer/Designer.csproj @@ -40,7 +40,6 @@ - @@ -53,4 +52,4 @@ - \ No newline at end of file + diff --git a/Designer/packages.config b/Designer/packages.config new file mode 100644 index 000000000..e18eee05a --- /dev/null +++ b/Designer/packages.config @@ -0,0 +1,4 @@ + + + + diff --git a/Example/packages.config b/Example/packages.config new file mode 100644 index 000000000..e18eee05a --- /dev/null +++ b/Example/packages.config @@ -0,0 +1,4 @@ + + + + diff --git a/Terminal.Gui/packages.config b/Terminal.Gui/packages.config new file mode 100644 index 000000000..7c57b8167 --- /dev/null +++ b/Terminal.Gui/packages.config @@ -0,0 +1,5 @@ + + + + + diff --git a/packages.config b/packages.config new file mode 100644 index 000000000..e18eee05a --- /dev/null +++ b/packages.config @@ -0,0 +1,4 @@ + + + + From 5f147297dbc5ebd36712b9fbcb1f05765b1450b6 Mon Sep 17 00:00:00 2001 From: BDisp Date: Sat, 29 Feb 2020 16:44:16 +0000 Subject: [PATCH 11/22] Fixed out of range exception and text redraw when navigate backward (#320) --- Terminal.Gui/Views/TextView.cs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Terminal.Gui/Views/TextView.cs b/Terminal.Gui/Views/TextView.cs index f0f42b5cc..8d239e86c 100644 --- a/Terminal.Gui/Views/TextView.cs +++ b/Terminal.Gui/Views/TextView.cs @@ -807,7 +807,7 @@ namespace Terminal.Gui { currentRow--; if (currentRow < topRow) { topRow--; - + SetNeedsDisplay (); } currentLine = GetCurrentLine (); currentColumn = currentLine.Count; @@ -1149,18 +1149,19 @@ namespace Terminal.Gui { SuperView.SetFocus (this); - var maxCursorPositionableLine = (model.Count - 1) - topRow; - if (ev.Y > maxCursorPositionableLine) { - currentRow = maxCursorPositionableLine; - } else { - currentRow = ev.Y + topRow; + if (model.Count > 0) { + var maxCursorPositionableLine = (model.Count - 1) - topRow; + if (ev.Y > maxCursorPositionableLine) { + currentRow = maxCursorPositionableLine; + } else { + currentRow = ev.Y + topRow; + } + var r = GetCurrentLine (); + if (ev.X - leftColumn >= r.Count) + currentColumn = r.Count - leftColumn; + else + currentColumn = ev.X - leftColumn; } - var r = GetCurrentLine (); - if (ev.X - leftColumn >= r.Count) - currentColumn = r.Count - leftColumn; - else - currentColumn = ev.X - leftColumn; - PositionCursor (); return true; } From d2bf1100bb4c73423ceade77236c08dd685dae3f Mon Sep 17 00:00:00 2001 From: imaras Date: Sat, 29 Feb 2020 17:44:46 +0100 Subject: [PATCH 12/22] Typo fix (#321) --- docfx/articles/overview.md | 2 +- docs/articles/overview.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docfx/articles/overview.md b/docfx/articles/overview.md index aee9be278..bbabe2efa 100644 --- a/docfx/articles/overview.md +++ b/docfx/articles/overview.md @@ -128,7 +128,7 @@ void SetupMyView (View myView) Y = 2, Width = 30, Height = 1 - } + }; myView.Add (username); } ``` diff --git a/docs/articles/overview.html b/docs/articles/overview.html index df75bf79f..af659aba6 100644 --- a/docs/articles/overview.html +++ b/docs/articles/overview.html @@ -165,7 +165,7 @@ the Subviews. You can add a view to an existing view, by calling the Y = 2, Width = 30, Height = 1 - } + }; myView.Add (username); }

The container of a given view is called the SuperView and it is a property of every From 314cefdc2760c1d7b382c7af10750ed8fda80302 Mon Sep 17 00:00:00 2001 From: BDisp Date: Sat, 29 Feb 2020 16:45:29 +0000 Subject: [PATCH 13/22] Fixes issue #306 async/await hang (#312) * Fixed async/await hang * Fixed async/await hang with calling Wakeup * Moved Wake Up into lock statement --- Terminal.Gui/Core.cs | 2 +- Terminal.Gui/MonoCurses/mainloop.cs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Terminal.Gui/Core.cs b/Terminal.Gui/Core.cs index 30d3cae4d..440a096ba 100644 --- a/Terminal.Gui/Core.cs +++ b/Terminal.Gui/Core.cs @@ -1717,7 +1717,7 @@ namespace Terminal.Gui { public override void Post (SendOrPostCallback d, object state) { - mainLoop.AddIdle (() => { + mainLoop.AddIdle (() => { d (state); return false; }); diff --git a/Terminal.Gui/MonoCurses/mainloop.cs b/Terminal.Gui/MonoCurses/mainloop.cs index 98ba8aca1..280c4dfee 100644 --- a/Terminal.Gui/MonoCurses/mainloop.cs +++ b/Terminal.Gui/MonoCurses/mainloop.cs @@ -354,8 +354,10 @@ namespace Mono.Terminal { ///

public Func AddIdle (Func idleHandler) { - lock (idleHandlers) + lock (idleHandlers) { idleHandlers.Add (idleHandler); + driver.Wakeup (); + } return idleHandler; } From 39319faa7521965ddbbb19160faa9e7cb2e1f622 Mon Sep 17 00:00:00 2001 From: "Kasper B. Graversen" Date: Sat, 29 Feb 2020 17:46:18 +0100 Subject: [PATCH 14/22] Support menu items that are null so they can be drawn as a menu separator (#304) --- Terminal.Gui/Views/Menu.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Terminal.Gui/Views/Menu.cs b/Terminal.Gui/Views/Menu.cs index 31e28b088..ee120eb5f 100644 --- a/Terminal.Gui/Views/Menu.cs +++ b/Terminal.Gui/Views/Menu.cs @@ -124,12 +124,7 @@ namespace Terminal.Gui { static Rect MakeFrame (int x, int y, MenuItem [] items) { - int maxW = 0; - - foreach (var item in items) { - var l = item.Width; - maxW = Math.Max (l, maxW); - } + int maxW = items.Max(z=>z?.Width) ?? 0; return new Rect (x, y, maxW + 2, items.Length + 2); } From 9cf7f701fc7315d134e8633e8961387b52138a5b Mon Sep 17 00:00:00 2001 From: Fabian R Date: Sat, 29 Feb 2020 10:47:29 -0600 Subject: [PATCH 15/22] Fixed and Enabled Library reinitialization (#291) - Replaced static driver initialization with property getter for reference passing in Core.cs::View class, this allows the library to be reinitialized at any time. - Made the Shutdown method on Core.cs::Application class public, since there is no reason to keep it private. Applications can shutdown the library and revert the console to the initial stage by calling it. - Fixed a memory-leak on Drivers/WindowsDriver class by destroying the generated screen buffers at library shutdown by calling CloseHandle. - Minor change to Core.cs::Application.Init(Func) for better initialization status tracking, via backend property instead of relying on the Top field. --- Terminal.Gui/Core.cs | 11 +++++++---- Terminal.Gui/Drivers/WindowsDriver.cs | 8 ++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Terminal.Gui/Core.cs b/Terminal.Gui/Core.cs index 440a096ba..5cfa65558 100644 --- a/Terminal.Gui/Core.cs +++ b/Terminal.Gui/Core.cs @@ -243,7 +243,7 @@ namespace Terminal.Gui { /// Points to the current driver in use by the view, it is a convenience property /// for simplifying the development of new views. ///
- public static ConsoleDriver Driver = Application.Driver; + public static ConsoleDriver Driver { get { return Application.Driver; } } static IList empty = new List (0).AsReadOnly (); @@ -1741,13 +1741,15 @@ namespace Terminal.Gui { ///
public static void Init () => Init (() => Toplevel.Create ()); + static bool _initialized = false; + /// /// Initializes the Application /// static void Init (Func topLevelFactory) { - if (Top != null) - return; + if (_initialized) return; + _initialized = true; var p = Environment.OSVersion.Platform; Mono.Terminal.IMainLoopDriver mainLoopDriver; @@ -1978,9 +1980,10 @@ namespace Terminal.Gui { runState.Dispose (); } - static void Shutdown () + public static void Shutdown () { Driver.End (); + _initialized = false; } static void Redraw (View view) diff --git a/Terminal.Gui/Drivers/WindowsDriver.cs b/Terminal.Gui/Drivers/WindowsDriver.cs index 6ad870c92..0074181c7 100644 --- a/Terminal.Gui/Drivers/WindowsDriver.cs +++ b/Terminal.Gui/Drivers/WindowsDriver.cs @@ -100,6 +100,11 @@ namespace Terminal.Gui { var err = Marshal.GetLastWin32Error (); Console.WriteLine ("Error: {0}", err); } + + if (ScreenBuffer != IntPtr.Zero) + CloseHandle(ScreenBuffer); + + ScreenBuffer = IntPtr.Zero; } private bool ContinueListeningForConsoleEvents = true; @@ -352,6 +357,9 @@ namespace Terminal.Gui { [DllImport ("kernel32.dll", SetLastError = true)] static extern IntPtr GetStdHandle (int nStdHandle); + [DllImport("kernel32.dll", SetLastError = true)] + static extern bool CloseHandle(IntPtr handle); + [DllImport ("kernel32.dll", EntryPoint = "ReadConsoleInputW", CharSet = CharSet.Unicode)] public static extern bool ReadConsoleInput ( IntPtr hConsoleInput, From 6f43c59bc6530f4bfc4c3292741bf29ada029bef Mon Sep 17 00:00:00 2001 From: Timothy Date: Sun, 1 Mar 2020 00:48:46 +0800 Subject: [PATCH 16/22] Moved `ListView.ListWrapper` out of `ListView` migueldeicaza/gui.cs#313` (#315) --- Terminal.Gui/Views/ListView.cs | 124 ++++++++++++++++----------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/Terminal.Gui/Views/ListView.cs b/Terminal.Gui/Views/ListView.cs index 729a898c5..ec3450ff0 100644 --- a/Terminal.Gui/Views/ListView.cs +++ b/Terminal.Gui/Views/ListView.cs @@ -95,68 +95,6 @@ namespace Terminal.Gui { int top; int selected; - // - // This class is the built-in IListDataSource that renders arbitrary - // IList instances - // - class ListWrapper : IListDataSource { - IList src; - BitArray marks; - int count; - - public ListWrapper (IList source) - { - count = source.Count; - marks = new BitArray (count); - this.src = source; - } - - public int Count => src.Count; - - void RenderUstr (ConsoleDriver driver, ustring ustr, int col, int line, int width) - { - int byteLen = ustr.Length; - int used = 0; - for (int i = 0; i < byteLen;) { - (var rune, var size) = Utf8.DecodeRune (ustr, i, i - byteLen); - var count = Rune.ColumnWidth (rune); - if (used+count >= width) - break; - driver.AddRune (rune); - used += count; - i += size; - } - for (; used < width; used++) { - driver.AddRune (' '); - } - } - - public void Render (ListView container, ConsoleDriver driver, bool marked, int item, int col, int line, int width) - { - container.Move (col, line); - var t = src [item]; - if (t is ustring) { - RenderUstr (driver, (ustring)t, col, line, width); - } else if (t is string) { - RenderUstr (driver, (string)t, col, line, width); - } else - RenderUstr (driver, t.ToString (), col, line, width); - } - - public bool IsMarked (int item) - { - if (item >= 0 && item < count) - return marks [item]; - return false; - } - - public void SetMark (int item, bool value) - { - if (item >= 0 && item < count) - marks [item] = value; - } - } - IListDataSource source; /// /// Gets or sets the IListDataSource backing this view, use SetSource() if you want to set a new IList source. @@ -437,4 +375,66 @@ namespace Terminal.Gui { return true; } } + + /// + /// This class is the built-in IListDataSource that renders arbitrary + /// IList instances + /// + public class ListWrapper : IListDataSource { + IList src; + BitArray marks; + int count; + + public ListWrapper (IList source) + { + count = source.Count; + marks = new BitArray (count); + this.src = source; + } + + public int Count => src.Count; + + void RenderUstr (ConsoleDriver driver, ustring ustr, int col, int line, int width) + { + int byteLen = ustr.Length; + int used = 0; + for (int i = 0; i < byteLen;) { + (var rune, var size) = Utf8.DecodeRune (ustr, i, i - byteLen); + var count = Rune.ColumnWidth (rune); + if (used+count >= width) + break; + driver.AddRune (rune); + used += count; + i += size; + } + for (; used < width; used++) { + driver.AddRune (' '); + } + } + + public void Render (ListView container, ConsoleDriver driver, bool marked, int item, int col, int line, int width) + { + container.Move (col, line); + var t = src [item]; + if (t is ustring) { + RenderUstr (driver, (ustring)t, col, line, width); + } else if (t is string) { + RenderUstr (driver, (string)t, col, line, width); + } else + RenderUstr (driver, t.ToString (), col, line, width); + } + + public bool IsMarked (int item) + { + if (item >= 0 && item < count) + return marks [item]; + return false; + } + + public void SetMark (int item, bool value) + { + if (item >= 0 && item < count) + marks [item] = value; + } + } } From c4fb5315e8f391eb38603d8af3d4450cc2501d68 Mon Sep 17 00:00:00 2001 From: BDisp Date: Sat, 29 Feb 2020 16:50:37 +0000 Subject: [PATCH 17/22] Resizing the MessageBox width to accommodate all message text (#299) * Fixed key events traversal for modal dialogs The key must be propagated initially to the first chain element before evaluating if we should stop because of the handled or the Modal condition. Otherwise the modal dialog won't get any process key notification. This fixes https://github.com/migueldeicaza/gui.cs/commit/c072e29a684068af50e1b9e284213b3839dad804 * Resizing the MessageBox width to accommodate all message text Co-authored-by: Adrian Alonso --- Example/demo.cs | 2 +- Terminal.Gui/Dialogs/MessageBox.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Example/demo.cs b/Example/demo.cs index 34a78ec2e..3cdf6a6f4 100644 --- a/Example/demo.cs +++ b/Example/demo.cs @@ -223,7 +223,7 @@ static class Demo { var d = new OpenDialog ("Open", "Open a file"); Application.Run (d); - MessageBox.Query (50, 7, "Selected File", string.Join (", ", d.FilePaths), "ok"); + MessageBox.Query (50, 7, "Selected File", string.Join (", ", d.FilePaths), "Ok"); } public static void ShowHex (Toplevel top) diff --git a/Terminal.Gui/Dialogs/MessageBox.cs b/Terminal.Gui/Dialogs/MessageBox.cs index e038bf757..bbb53acf9 100644 --- a/Terminal.Gui/Dialogs/MessageBox.cs +++ b/Terminal.Gui/Dialogs/MessageBox.cs @@ -43,7 +43,7 @@ namespace Terminal.Gui { /// Width for the window. /// Height for the window. /// Title for the query. - /// Message to display, might contain multiple lines.. + /// Message to display, might contain multiple lines. /// Array of buttons to add. public static int ErrorQuery (int width, int height, string title, string message, params string [] buttons) { @@ -55,10 +55,10 @@ namespace Terminal.Gui { int textWidth = Label.MaxWidth (message, width); int clicked = -1, count = 0; - var d = new Dialog (title, width, height); + var d = new Dialog (title, Math.Max(width, textWidth) + 4, height); if (useErrorColors) d.ColorScheme = Colors.Error; - + foreach (var s in buttons) { int n = count++; var b = new Button (s); @@ -69,7 +69,7 @@ namespace Terminal.Gui { d.AddButton (b); } if (message != null) { - var l = new Label ((width - 4 - textWidth) / 2, 0, message); + var l = new Label (textWidth > width ? 0 : (width - 4 - textWidth) / 2, 0, message); d.Add (l); } From 14b744f11a471718efd96db54b23ae5c64eb7be6 Mon Sep 17 00:00:00 2001 From: BDisp Date: Sat, 29 Feb 2020 16:51:15 +0000 Subject: [PATCH 18/22] Timefield format with bounds values (#303) * Implemented lower and upper bounds to TimeField * Passing old text to the Changed event handler * Change sepChar from char to string in TimeField * Changing comparison from ':' to sepChar.ToCharArray () [0] --- Terminal.Gui/Views/TextField.cs | 7 ++-- Terminal.Gui/Views/TimeField.cs | 68 +++++++++++++++++++++++++++------ 2 files changed, 61 insertions(+), 14 deletions(-) diff --git a/Terminal.Gui/Views/TextField.cs b/Terminal.Gui/Views/TextField.cs index 215c66064..16187a339 100644 --- a/Terminal.Gui/Views/TextField.cs +++ b/Terminal.Gui/Views/TextField.cs @@ -35,7 +35,7 @@ namespace Terminal.Gui { /// Client code can hook up to this event, it is /// raised when the text in the entry changes. /// - public event EventHandler Changed; + public event EventHandler Changed; /// /// Public constructor that creates a text field, with layout controlled with X, Y, Width and Height. @@ -98,7 +98,10 @@ namespace Terminal.Gui { } set { + ustring oldText = ustring.Make(text); text = TextModel.ToRunes (value); + Changed?.Invoke(this, oldText); + if (point > text.Count) point = Math.Max (text.Count-1, 0); @@ -193,8 +196,6 @@ namespace Terminal.Gui { void SetText (List newText) { text = newText; - if (Changed != null) - Changed (this, EventArgs.Empty); } void SetText (IEnumerable newText) diff --git a/Terminal.Gui/Views/TimeField.cs b/Terminal.Gui/Views/TimeField.cs index fc9f860d7..cacfa944c 100644 --- a/Terminal.Gui/Views/TimeField.cs +++ b/Terminal.Gui/Views/TimeField.cs @@ -1,4 +1,4 @@ -// + // // TimeField.cs: text entry for time // // Author: Jörg Preiß @@ -25,9 +25,9 @@ namespace Terminal.Gui { int longFieldLen = 8; int shortFieldLen = 5; int FieldLen { get { return isShort ? shortFieldLen : longFieldLen; } } - - string longFormat = " hh:mm:ss"; - string shortFormat = " hh:mm"; + string sepChar; + string longFormat; + string shortFormat; string Format { get { return isShort ? shortFormat : longFormat; } } @@ -40,9 +40,20 @@ namespace Terminal.Gui { /// If true, the seconds are hidden. public TimeField (int x, int y, DateTime time, bool isShort = false) : base (x, y, isShort ? 7 : 10, "") { + CultureInfo cultureInfo = CultureInfo.CurrentCulture; + sepChar = cultureInfo.DateTimeFormat.TimeSeparator; + longFormat = $" HH{sepChar}mm{sepChar}ss"; + shortFormat = $" HH{sepChar}mm"; this.isShort = isShort; CursorPosition = 1; Time = time; + Changed += TimeField_Changed; + } + + private void TimeField_Changed (object sender, ustring e) + { + if (!DateTime.TryParseExact (Text.ToString (), Format, CultureInfo.CurrentCulture, DateTimeStyles.None, out DateTime result)) + Text = e; } /// @@ -72,31 +83,66 @@ namespace Terminal.Gui { bool SetText (ustring text) { - if (!DateTime.TryParseExact (text.ToString (), Format, CultureInfo.CurrentCulture, DateTimeStyles.None, out DateTime result)) + ustring [] vals = text.Split (ustring.Make (sepChar)); + bool isValidTime = true; + int hour = Int32.Parse (vals [0].ToString ()); + int minute = Int32.Parse (vals [1].ToString ()); + int second = isShort ? 0 : Int32.Parse (vals [2].ToString ()); + if (hour < 0) { + isValidTime = false; + hour = 0; + vals [0] = "0"; + } else if (hour > 23) { + isValidTime = false; + hour = 23; + vals [0] = "23"; + } + if (minute < 0) { + isValidTime = false; + minute = 0; + vals [1] = "0"; + } else if (minute > 59) { + isValidTime = false; + minute = 59; + vals [1] = "59"; + } + if (second < 0) { + isValidTime = false; + second = 0; + vals [2] = "0"; + } else if (second > 59) { + isValidTime = false; + second = 59; + vals [2] = "59"; + } + string time = isShort ? $" {hour,2:00}{sepChar}{minute,2:00}" : $" {hour,2:00}{sepChar}{minute,2:00}{sepChar}{second,2:00}"; + Text = time; + + if (!DateTime.TryParseExact (text.ToString (), Format, CultureInfo.CurrentCulture, DateTimeStyles.None, out DateTime result) || + !isValidTime) return false; - Text = text; return true; } void IncCursorPosition () { - if (CursorPosition == FieldLen) + if (CursorPosition == FieldLen) return; - if (Text [++CursorPosition] == ':') + if (Text [++CursorPosition] == sepChar.ToCharArray () [0]) CursorPosition++; } void DecCursorPosition () { - if (CursorPosition == 1) + if (CursorPosition == 1) return; - if (Text [--CursorPosition] == ':') + if (Text [--CursorPosition] == sepChar.ToCharArray () [0]) CursorPosition--; } void AdjCursorPosition () { - if (Text [CursorPosition] == ':') + if (Text [CursorPosition] == sepChar.ToCharArray () [0]) CursorPosition++; } From 8c32b3fe5e3ca69c77bea6bbb99529b19b07b846 Mon Sep 17 00:00:00 2001 From: "Kasper B. Graversen" Date: Sat, 29 Feb 2020 17:51:49 +0100 Subject: [PATCH 19/22] extract methods on ListView to make it controlable from other controls (#310) * moveup * MoveDown * MovePageDown * MovePageUp * MarkUnmarkRow --- Terminal.Gui/Views/ListView.cs | 124 ++++++++++++++++++++------------- 1 file changed, 76 insertions(+), 48 deletions(-) diff --git a/Terminal.Gui/Views/ListView.cs b/Terminal.Gui/Views/ListView.cs index ec3450ff0..bdc7f75c1 100644 --- a/Terminal.Gui/Views/ListView.cs +++ b/Terminal.Gui/Views/ListView.cs @@ -283,69 +283,97 @@ namespace Terminal.Gui { switch (kb.Key) { case Key.CursorUp: case Key.ControlP: - if (selected > 0) { - selected--; - if (selected < top) - top = selected; - if (SelectedChanged != null) - SelectedChanged (); - SetNeedsDisplay (); - } - return true; + return MoveUp(); case Key.CursorDown: case Key.ControlN: - if (selected + 1 < source.Count) { - selected++; - if (selected >= top + Frame.Height) - top++; - if (SelectedChanged != null) - SelectedChanged (); - SetNeedsDisplay (); - } - return true; + return MoveDown(); case Key.ControlV: case Key.PageDown: - var n = (selected + Frame.Height); - if (n > source.Count) - n = source.Count - 1; - if (n != selected) { - selected = n; - if (source.Count >= Frame.Height) - top = selected; - else - top = 0; - if (SelectedChanged != null) - SelectedChanged (); - SetNeedsDisplay (); - } - return true; + return MovePageDown(); case Key.PageUp: - n = (selected - Frame.Height); - if (n < 0) - n = 0; - if (n != selected) { - selected = n; - top = selected; - if (SelectedChanged != null) - SelectedChanged (); - SetNeedsDisplay (); - } - return true; + return MovePageUp(); case Key.Space: - if (allowsMarking) { - Source.SetMark (SelectedItem, !Source.IsMarked (SelectedItem)); - SetNeedsDisplay (); + if (MarkUnmarkRow()) return true; - } - break; + else + break; } return base.ProcessKey (kb); } + public virtual bool MarkUnmarkRow(){ + if (allowsMarking){ + Source.SetMark(SelectedItem, !Source.IsMarked(SelectedItem)); + SetNeedsDisplay(); + return true; + } + + return false; + } + + public virtual bool MovePageUp(){ + int n = (selected - Frame.Height); + if (n < 0) + n = 0; + if (n != selected){ + selected = n; + top = selected; + if (SelectedChanged != null) + SelectedChanged(); + SetNeedsDisplay(); + } + + return true; + } + + public virtual bool MovePageDown(){ + var n = (selected + Frame.Height); + if (n > source.Count) + n = source.Count - 1; + if (n != selected){ + selected = n; + if (source.Count >= Frame.Height) + top = selected; + else + top = 0; + if (SelectedChanged != null) + SelectedChanged(); + SetNeedsDisplay(); + } + + return true; + } + + public virtual bool MoveDown(){ + if (selected + 1 < source.Count){ + selected++; + if (selected >= top + Frame.Height) + top++; + if (SelectedChanged != null) + SelectedChanged(); + SetNeedsDisplay(); + } + + return true; + } + + public virtual bool MoveUp(){ + if (selected > 0){ + selected--; + if (selected < top) + top = selected; + if (SelectedChanged != null) + SelectedChanged(); + SetNeedsDisplay(); + } + + return true; + } + /// /// Positions the cursor in this view /// From 14d4639717269c9255c45f7720076b89f617d668 Mon Sep 17 00:00:00 2001 From: BDisp Date: Sat, 29 Feb 2020 16:54:27 +0000 Subject: [PATCH 20/22] Allowing list items selection (#302) --- Terminal.Gui/Views/ListView.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/Terminal.Gui/Views/ListView.cs b/Terminal.Gui/Views/ListView.cs index bdc7f75c1..71ea3a709 100644 --- a/Terminal.Gui/Views/ListView.cs +++ b/Terminal.Gui/Views/ListView.cs @@ -151,7 +151,7 @@ namespace Terminal.Gui { set { if (source == null) return; - + if (top < 0 || top >= source.Count) throw new ArgumentException ("value"); top = value; @@ -279,7 +279,7 @@ namespace Terminal.Gui { { if (source == null) return base.ProcessKey (kb); - + switch (kb.Key) { case Key.CursorUp: case Key.ControlP: @@ -379,7 +379,10 @@ namespace Terminal.Gui { /// public override void PositionCursor() { - Move (0, selected-top); + if (allowsMarking) + Move (1, selected - top); + else + Move (0, selected - top); } public override bool MouseEvent(MouseEvent me) @@ -387,16 +390,21 @@ namespace Terminal.Gui { if (!me.Flags.HasFlag (MouseFlags.Button1Clicked)) return false; - if (!HasFocus) + if (!HasFocus) SuperView.SetFocus (this); if (source == null) return false; - + if (me.Y + top >= source.Count) return true; selected = top + me.Y; + if (allowsMarking) { + Source.SetMark (SelectedItem, !Source.IsMarked (SelectedItem)); + SetNeedsDisplay (); + return true; + } if (SelectedChanged != null) SelectedChanged(); SetNeedsDisplay (); From 562f85029aa3c62c6cba71bd8fe929446d5ad940 Mon Sep 17 00:00:00 2001 From: BDisp Date: Sun, 8 Mar 2020 10:22:41 +0000 Subject: [PATCH 21/22] Fetch from upstream/master --- Designer/Designer.csproj | 2 +- Example/Example.csproj | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Designer/Designer.csproj b/Designer/Designer.csproj index e87bd0a6b..4374b4802 100644 --- a/Designer/Designer.csproj +++ b/Designer/Designer.csproj @@ -52,4 +52,4 @@ - + \ No newline at end of file diff --git a/Example/Example.csproj b/Example/Example.csproj index 3f6523667..95808f859 100644 --- a/Example/Example.csproj +++ b/Example/Example.csproj @@ -1,4 +1,4 @@ - + Debug @@ -52,4 +52,4 @@ - + \ No newline at end of file From 71c063b415adeb83595290b7399dcda658ae2c06 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Mon, 9 Mar 2020 14:30:15 -0400 Subject: [PATCH 22/22] Prepare for 0.70 --- Terminal.Gui/Terminal.Gui.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj index 8dee18aa1..2f42588eb 100644 --- a/Terminal.Gui/Terminal.Gui.csproj +++ b/Terminal.Gui/Terminal.Gui.csproj @@ -9,7 +9,7 @@ true Terminal.Gui - 0.65 + 0.70 Miguel de Icaza MIT https://github.com/migueldeicaza/gui.cs/ @@ -18,7 +18,7 @@ Miguel de Icaza Application framework for creating modern console applications using .NET Gui.cs is a framework for creating console user interfaces - 0.25: Added new TimeField from Jörg Preiß; Fixes for Backtab by Martin Björkström; ListView now supports simple selection; Bug fixes by giladlevi, Daniel Cazzulino and Marius Ungureanu; New Application.Run of T entry point by Daniel Cazzulino; Added various View methods to bring forward, backwards and move views in the hierarchy; Switch to Portable PDBs by Daniel Cazzulino; Dims can now be compared by Daniel Cazzulino; OnMenuOpen handler by giladlevi; Various memory usage optimizations by giladlevi; FileDialog.FilePath is now a full path by Yanwei Wang; ISupportInitialize/ISupportInitializeNotification is now supported thanks to the work from Daniel Cazzulino; Support for non-modal TopLevels by Daniel Cazzulino and Adrian Alonso; 0.24: the Windows driver implements WakeUp, allowing some scenarios like bug #207 to be fixed; + 0.70: Bug fixes (320, 321, 306, 304, 291, 299, 303); Surface ListView.ListWrapper, surface various internal methods for use in ListView; Allow list item selection; ; 0.65: Added new TimeField from Jörg Preiß; Fixes for Backtab by Martin Björkström; ListView now supports simple selection; Bug fixes by giladlevi, Daniel Cazzulino and Marius Ungureanu; New Application.Run of T entry point by Daniel Cazzulino; Added various View methods to bring forward, backwards and move views in the hierarchy; Switch to Portable PDBs by Daniel Cazzulino; Dims can now be compared by Daniel Cazzulino; OnMenuOpen handler by giladlevi; Various memory usage optimizations by giladlevi; FileDialog.FilePath is now a full path by Yanwei Wang; ISupportInitialize/ISupportInitializeNotification is now supported thanks to the work from Daniel Cazzulino; Support for non-modal TopLevels by Daniel Cazzulino and Adrian Alonso; 0.24: the Windows driver implements WakeUp, allowing some scenarios like bug #207 to be fixed; 0.23: Better support for disabled menu items; Raises text changed event after the internals have been updated; Fix Caps-NumLock; Alt-HotKey now work on menus 0.22: Correct vertical scrollview behavior, Small curses driver fix for terminals without mouse support, TextView support for scrolling, Surface Used property on TextField, Surface Cursor on RadioGroup.