From b185722ab6aabeb1d6e62193b427e4c186af98aa Mon Sep 17 00:00:00 2001 From: BDisp Date: Fri, 18 Feb 2022 15:23:46 +0000 Subject: [PATCH] Standalone update fix (#1596) * Updating nuget package and fixing nonworking code. * Adding some more improvements and launch for UseSystemConsole. * Fixes layout issue. * Also added a launch for UseSystemConsole for the Example project. * Fixing unit tests. * Trying fixing timeouts duplicate keys. --- Example/Properties/launchSettings.json | 11 + Example/demo.cs | 12 +- StandaloneExample/Program.cs | 427 ++++++++++-------- .../Properties/launchSettings.json | 11 + StandaloneExample/StandaloneExample.csproj | 2 +- Terminal.Gui/Core/MainLoop.cs | 2 +- Terminal.Gui/Core/View.cs | 3 + Terminal.Gui/Core/Window.cs | 9 + UnitTests/ViewTests.cs | 2 + 9 files changed, 285 insertions(+), 194 deletions(-) create mode 100644 Example/Properties/launchSettings.json create mode 100644 StandaloneExample/Properties/launchSettings.json diff --git a/Example/Properties/launchSettings.json b/Example/Properties/launchSettings.json new file mode 100644 index 000000000..495d3d1da --- /dev/null +++ b/Example/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "Example": { + "commandName": "Project" + }, + "Example:-usc": { + "commandName": "Project", + "commandLineArgs": "-usc" + } + } +} \ No newline at end of file diff --git a/Example/demo.cs b/Example/demo.cs index 766193f07..3f69b42e8 100644 --- a/Example/demo.cs +++ b/Example/demo.cs @@ -564,8 +564,13 @@ static class Demo { #endregion public static Action running = MainApp; - static void Main () + static void Main(string[] args) { + if (args.Length > 0 && args.Contains("-usc")) + { + Application.UseSystemConsole = true; + } + Console.OutputEncoding = System.Text.Encoding.Default; while (running != null) { @@ -583,8 +588,6 @@ static class Demo { if (Debugger.IsAttached) CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo ("en-US"); - Application.UseSystemConsole = true; - Application.Init(); Application.HeightAsBuffer = true; //ConsoleDriver.Diagnostics = ConsoleDriver.DiagnosticFlags.FramePadding | ConsoleDriver.DiagnosticFlags.FrameRuler; @@ -685,7 +688,8 @@ static class Demo { new StatusItem(Key.F1, "~F1~ Help", () => Help()), new StatusItem(Key.F2, "~F2~ Load", Load), new StatusItem(Key.F3, "~F3~ Save", Save), - new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => { if (Quit ()) { running = null; top.Running = false; } }) + new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => { if (Quit ()) { running = null; top.Running = false; } }), + new StatusItem(Key.Null, Application.Driver.GetType().Name, null) }); win.Add (drag, dragText); diff --git a/StandaloneExample/Program.cs b/StandaloneExample/Program.cs index 7acb39bbd..8a2103074 100644 --- a/StandaloneExample/Program.cs +++ b/StandaloneExample/Program.cs @@ -1,128 +1,137 @@ -using Terminal.Gui; -using System; -using Mono.Terminal; +namespace StandaloneExample { + using System.Linq; + using Terminal.Gui; + using System; + using NStack; + using System.Text; + using Rune = System.Rune; -class Demo { - class Box10x : View { - public Box10x (int x, int y) : base (new Rect (x, y, 10, 10)) - { - } - - public override void Redraw (Rect region) - { - Driver.SetAttribute (ColorScheme.Focus); - - for (int y = 0; y < 10; y++) { - Move (0, y); - for (int x = 0; x < 10; x++) { - - Driver.AddRune ((Rune)('0' + (x + y) % 10)); - } + static class Demo { + class Box10x : View { + public Box10x (int x, int y) : base (new Rect (x, y, 10, 10)) + { } - } - } + public override void Redraw (Rect region) + { + Driver.SetAttribute (ColorScheme.Focus); - class Filler : View { - public Filler (Rect rect) : base (rect) - { - } - - public override void Redraw (Rect region) - { - Driver.SetAttribute (ColorScheme.Focus); - var f = Frame; - - for (int y = 0; y < f.Width; y++) { - Move (0, y); - for (int x = 0; x < f.Height; x++) { - Rune r; - switch (x % 3) { - case 0: - r = '.'; - break; - case 1: - r = 'o'; - break; - default: - r = 'O'; - break; + for (int y = 0; y < 10; y++) { + Move (0, y); + for (int x = 0; x < 10; x++) { + Driver.AddRune ((Rune)('0' + ((x + y) % 10))); } - Driver.AddRune (r); } } } - } + class Filler : View { + public Filler (Rect rect) : base (rect) + { + } - static void ShowTextAlignments (View container) - { - container.Add ( - new Label (new Rect (0, 0, 40, 3), "1-Hello world, how are you doing today") { TextAlignment = TextAlignment.Left }, - new Label (new Rect (0, 4, 40, 3), "2-Hello world, how are you doing today") { TextAlignment = TextAlignment.Right }, - new Label (new Rect (0, 8, 40, 3), "3-Hello world, how are you doing today") { TextAlignment = TextAlignment.Centered }, - new Label (new Rect (0, 12, 40, 3), "4-Hello world, how are you doing today") { TextAlignment = TextAlignment.Justified }); - } + public override void Redraw (Rect region) + { + Driver.SetAttribute (ColorScheme.Focus); + var f = Frame; - static void ShowEntries (View container) - { - var scrollView = new ScrollView (new Rect (50, 10, 20, 8)) { - ContentSize = new Size (100, 100), - ContentOffset = new Point (-1, -1), - ShowVerticalScrollIndicator = true, - ShowHorizontalScrollIndicator = true - }; - - scrollView.Add (new Box10x (0, 0)); - //scrollView.Add (new Filler (new Rect (0, 0, 40, 40))); - - // This is just to debug the visuals of the scrollview when small - var scrollView2 = new ScrollView (new Rect (72, 10, 3, 3)) { - ContentSize = new Size (100, 100), - ShowVerticalScrollIndicator = true, - ShowHorizontalScrollIndicator = true - }; - scrollView2.Add (new Box10x (0, 0)); - var progress = new ProgressBar (new Rect (68, 1, 10, 1)); - bool timer (MainLoop caller) - { - progress.Pulse (); - return true; + for (int y = 0; y < f.Width; y++) { + Move (0, y); + for (int x = 0; x < f.Height; x++) { + var r = (x % 3) switch { + 0 => '.', + 1 => 'o', + _ => 'O', + }; + Driver.AddRune (r); + } + } + } } - Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (300), timer); + static void ShowTextAlignments () + { + var container = new Window ("Show Text Alignments - Press Esc to return") { + X = 0, + Y = 0, + Width = Dim.Fill (), + Height = Dim.Fill () + }; + container.KeyUp += (e) => { + if (e.KeyEvent.Key == Key.Esc) + container.Running = false; + }; - // A little convoluted, this is because I am using this to test the - // layout based on referencing elements of another view: + const int i = 0; + const string txt = "Hello world, how are you doing today?"; + container.Add ( + new Label ($"{i + 1}-{txt}") { TextAlignment = TextAlignment.Left, Y = 3, Width = Dim.Fill () }, + new Label ($"{i + 2}-{txt}") { TextAlignment = TextAlignment.Right, Y = 5, Width = Dim.Fill () }, + new Label ($"{i + 3}-{txt}") { TextAlignment = TextAlignment.Centered, Y = 7, Width = Dim.Fill () }, + new Label ($"{i + 4}-{txt}") { TextAlignment = TextAlignment.Justified, Y = 9, Width = Dim.Fill () } + ); - var login = new Label ("Login: ") { X = 3, Y = 6 }; - var password = new Label ("Password: ") { - X = Pos.Left (login), - Y = Pos.Bottom (login) + 1 - }; - var loginText = new TextField ("") { - X = Pos.Right (password), - Y = Pos.Top (login), - Width = 40 - }; - var passText = new TextField ("") { - Secret = true, - X = Pos.Left (loginText), - Y = Pos.Top (password), - Width = Dim.Width (loginText) - }; + Application.Run (container); + } - // Add some content - container.Add ( - login, - loginText, - password, - passText, - new FrameView (new Rect (3, 10, 25, 6), "Options"){ + static void ShowEntries (View container) + { + scrollView = new ScrollView (new Rect (50, 10, 20, 8)) { + ContentSize = new Size (100, 100), + ContentOffset = new Point (-1, -1), + ShowVerticalScrollIndicator = true, + ShowHorizontalScrollIndicator = true + }; + + AddScrollViewChild (); + + // This is just to debug the visuals of the scrollview when small + var scrollView2 = new ScrollView (new Rect (72, 10, 3, 3)) { + ContentSize = new Size (100, 100), + ShowVerticalScrollIndicator = true, + ShowHorizontalScrollIndicator = true + }; + scrollView2.Add (new Box10x (0, 0)); + var progress = new ProgressBar (new Rect (68, 1, 10, 1)); + bool timer (MainLoop _) + { + progress.Pulse (); + return true; + } + + Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (300), timer); + + // A little convoluted, this is because I am using this to test the + // layout based on referencing elements of another view: + + var login = new Label ("Login: ") { X = 3, Y = 6 }; + var password = new Label ("Password: ") { + X = Pos.Left (login), + Y = Pos.Bottom (login) + 1 + }; + var loginText = new TextField ("") { + X = Pos.Right (password), + Y = Pos.Top (login), + Width = 40 + }; + var passText = new TextField ("") { + Secret = true, + X = Pos.Left (loginText), + Y = Pos.Top (password), + Width = Dim.Width (loginText) + }; + + // Add some content + container.Add ( + login, + loginText, + password, + passText, + new FrameView (new Rect (3, 10, 25, 6), "Options", new View [] { new CheckBox (1, 0, "Remember me"), - new RadioGroup (1, 2, new [] { "_Personal", "_Company" }), - }, - new ListView (new Rect (60, 6, 16, 4), new string [] { + new RadioGroup (1, 2, new ustring [] { "_Personal", "_Company" }) } + ), + new ListView (new Rect (60, 6, 16, 4), new string [] { "First row", "<>", "This is a very long row that should overflow what is shown", @@ -130,85 +139,127 @@ class Demo { "There is an empty slot on the second row", "Whoa", "This is so cool" - }), - scrollView, - //scrollView2, - new Button ("Ok") { X = 3, Y = 19 }, - new Button ("Cancel") { X = 10, Y = 19 }, - progress, - new Label ("Press F9 (on Unix ESC+9 is an alias) to activate the menubar") { X = 3, Y = 22 } - ); + }), + scrollView, + scrollView2, + new Button ("Ok") { X = 3, Y = 19 }, + new Button ("Cancel") { X = 10, Y = 19 }, + progress, + new Label ("Press F9 (on Unix ESC+9 is an alias) to activate the menubar") { X = 3, Y = 22 } + ); + } + private static void AddScrollViewChild () + { + if (isBox10x) { + scrollView.Add (new Box10x (0, 0)); + } else { + scrollView.Add (new Filler (new Rect (0, 0, 40, 40))); + } + scrollView.ContentOffset = Point.Empty; + } + + static void NewFile () + { + var okButton = new Button ("Ok", is_default: true); + okButton.Clicked += () => Application.RequestStop (); + var cancelButton = new Button ("Cancel"); + cancelButton.Clicked += () => Application.RequestStop (); + + var d = new Dialog ( + "New File", 50, 20, + okButton, + cancelButton); + + var ml2 = new Label (1, 1, "Mouse Debug Line"); + d.Add (ml2); + Application.Run (d); + } + + static bool Quit () + { + var n = MessageBox.Query (50, 7, "Quit Demo", "Are you sure you want to quit this demo?", "Yes", "No"); + return n == 0; + } + + static void Close () + { + MessageBox.ErrorQuery (50, 7, "Error", "There is nothing to close", "Ok"); + } + + private static void ScrollViewCheck () + { + isBox10x = miScrollViewCheck.Children [0].Checked = !miScrollViewCheck.Children [0].Checked; + miScrollViewCheck.Children [1].Checked = !miScrollViewCheck.Children [1].Checked; + + scrollView.RemoveAll (); + AddScrollViewChild (); + } + + public static Label ml; + private static MenuBarItem miScrollViewCheck; + private static bool isBox10x = true; + private static Window win; + private static ScrollView scrollView; + + static void Main (string [] args) + { + if (args.Length > 0 && args.Contains ("-usc")) { + Application.UseSystemConsole = true; + } + + Console.OutputEncoding = Encoding.Default; + + Application.Init (); + + var top = Application.Top; + + win = new Window ("Hello") { + X = 0, + Y = 1, + Width = Dim.Fill (), + Height = Dim.Fill () - 1 + }; + var menu = new MenuBar (new MenuBarItem [] { + new MenuBarItem ("_File", new MenuItem [] { + new MenuItem ("_New", "Creates new file", NewFile), + new MenuItem ("_Open", "", null), + new MenuItem ("_Close", "", () => Close ()), + new MenuItem ("_Quit", "", () => { if (Quit ()) top.Running = false; }) + }), + new MenuBarItem ("_Edit", new MenuItem [] { + new MenuItem ("_Copy", "", null), + new MenuItem ("C_ut", "", null), + new MenuItem ("_Paste", "", null) + }), + new MenuBarItem ("A_ssorted", new MenuItem [] { + new MenuItem ("_Show text alignments", "", () => ShowTextAlignments (), null, null, Key.AltMask | Key.CtrlMask | Key.G) + }), + miScrollViewCheck = new MenuBarItem ("ScrollView", new MenuItem [] { + new MenuItem ("Box10x", "", () => ScrollViewCheck()) {CheckType = MenuItemCheckStyle.Radio, Checked = true }, + new MenuItem ("Filler", "", () => ScrollViewCheck()) {CheckType = MenuItemCheckStyle.Radio } + }) + }); + + ShowEntries (win); + int count = 0; + ml = new Label (new Rect (3, 17, 47, 1), "Mouse: "); + Application.RootMouseEvent += (me) => ml.Text = $"Mouse: ({me.X},{me.Y}) - {me.Flags} {count++}"; + + win.Add (ml); + + var statusBar = new StatusBar (new StatusItem [] { + new StatusItem(Key.F1, "~F1~ Help", () => MessageBox.Query (50, 7, "Help", "Helping", "Ok")), + new StatusItem(Key.F2, "~F2~ Load", () => MessageBox.Query (50, 7, "Load", "Loading", "Ok")), + new StatusItem(Key.F3, "~F3~ Save", () => MessageBox.Query (50, 7, "Save", "Saving", "Ok")), + new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => { if (Quit ()) top.Running = false; }), + new StatusItem(Key.Null, Application.Driver.GetType().Name, null) + }); + + top.Add (win, menu, statusBar); + Application.Run (); + + Application.Shutdown (); + } } - - static void NewFile () - { - var okButton = new Button ("Ok", is_default: true); - okButton.Clicked += () => { Application.RequestStop (); }; - var cancelButton = new Button ("Cancel"); - cancelButton.Clicked += () => { Application.RequestStop (); }; - - var d = new Dialog ( - "New File", 50, 20, - okButton, - cancelButton); - - var ml2 = new Label (1, 1, "Mouse Debug Line"); - d.Add (ml2); - Application.Run (d); - } - - static bool Quit () - { - var n = MessageBox.Query (50, 7, "Quit Demo", "Are you sure you want to quit this demo?", "Yes", "No"); - return n == 0; - } - - static void Close () - { - MessageBox.ErrorQuery (50, 7, "Error", "There is nothing to close", "Ok"); - } - - public static Label ml; - static void Main () - { - //Application.UseSystemConsole = true; - Application.Init (); - - var top = Application.Top; - var tframe = top.Frame; - - var win = new Window ("Hello"){ - X = 0, - Y = 1, - Width = Dim.Fill (), - Height = Dim.Fill () - 1 - }; - var menu = new MenuBar (new MenuBarItem [] { - new MenuBarItem ("_File", new MenuItem [] { - new MenuItem ("_New", "Creates new file", NewFile), - new MenuItem ("_Open", "", null), - new MenuItem ("_Close", "", () => Close ()), - new MenuItem ("_Quit", "", () => { if (Quit ()) top.Running = false; }) - }), - new MenuBarItem ("_Edit", new MenuItem [] { - new MenuItem ("_Copy", "", null), - new MenuItem ("C_ut", "", null), - new MenuItem ("_Paste", "", null) - }) - }); - - ShowEntries (win); - int count = 0; - ml = new Label (new Rect (3, 17, 47, 1), "Mouse: "); - Application.RootMouseEvent += delegate (MouseEvent me) { - ml.Text = $"Mouse: ({me.X},{me.Y}) - {me.Flags} {count++}"; - }; - - win.Add (ml); - - top.Add (win, menu); - top.Add (menu); - Application.Run (); - } -} +} \ No newline at end of file diff --git a/StandaloneExample/Properties/launchSettings.json b/StandaloneExample/Properties/launchSettings.json new file mode 100644 index 000000000..7fc5e118e --- /dev/null +++ b/StandaloneExample/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "StandaloneExample": { + "commandName": "Project" + }, + "StandaloneExample-usc": { + "commandName": "Project", + "commandLineArgs": "-usc" + } + } +} \ No newline at end of file diff --git a/StandaloneExample/StandaloneExample.csproj b/StandaloneExample/StandaloneExample.csproj index b70be9f1a..3ba15da2c 100644 --- a/StandaloneExample/StandaloneExample.csproj +++ b/StandaloneExample/StandaloneExample.csproj @@ -7,6 +7,6 @@ - + diff --git a/Terminal.Gui/Core/MainLoop.cs b/Terminal.Gui/Core/MainLoop.cs index e53e43a03..cd0473293 100644 --- a/Terminal.Gui/Core/MainLoop.cs +++ b/Terminal.Gui/Core/MainLoop.cs @@ -117,8 +117,8 @@ namespace Terminal.Gui { void AddTimeout (TimeSpan time, Timeout timeout) { - var k = (DateTime.UtcNow + time).Ticks; lock (timeouts) { + var k = (DateTime.UtcNow + time).Ticks; while (timeouts.ContainsKey (k)) { k = (DateTime.UtcNow + time).Ticks; } diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index 2aef4ef49..0c1e09f2d 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -771,6 +771,9 @@ namespace Terminal.Gui { if (SuperView == null) return; SuperView.SetNeedsLayout (); + foreach (var view in Subviews) { + view.SetNeedsLayout (); + } textFormatter.NeedsFormat = true; } diff --git a/Terminal.Gui/Core/Window.cs b/Terminal.Gui/Core/Window.cs index f030d8f1e..d08d950ec 100644 --- a/Terminal.Gui/Core/Window.cs +++ b/Terminal.Gui/Core/Window.cs @@ -88,6 +88,15 @@ namespace Terminal.Gui { this.instance = instance; } + public override void OnCanFocusChanged () + { + if (MostFocused == null && CanFocus && Visible) { + EnsureFocus (); + } + + base.OnCanFocusChanged (); + } + public override bool MouseEvent (MouseEvent mouseEvent) { return instance.MouseEvent (mouseEvent); diff --git a/UnitTests/ViewTests.cs b/UnitTests/ViewTests.cs index 4dfc3da95..b8a66688a 100644 --- a/UnitTests/ViewTests.cs +++ b/UnitTests/ViewTests.cs @@ -747,6 +747,7 @@ namespace Terminal.Gui.Views { } [Fact] + [AutoInitShutdown] public void CanFocus_Faced_With_Container () { var t = new Toplevel (); @@ -1576,6 +1577,7 @@ namespace Terminal.Gui.Views { } [Fact] + [AutoInitShutdown] public void GetTopSuperView_Test () { var v1 = new View ();