From d4075a1a125bbde1f7bee8fcfd96343719da782c Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Sun, 31 May 2020 22:17:18 -0600 Subject: [PATCH 1/5] added menu item to enable system console; fixed Init/Shutdown bug --- Terminal.Gui/Core/Application.cs | 1 + Terminal.Gui/Core/ConsoleDriver.cs | 2 +- UICatalog/UICatalog.cs | 129 +++++++++++++---------------- 3 files changed, 59 insertions(+), 73 deletions(-) diff --git a/Terminal.Gui/Core/Application.cs b/Terminal.Gui/Core/Application.cs index 3c41d67db..d486f817d 100644 --- a/Terminal.Gui/Core/Application.cs +++ b/Terminal.Gui/Core/Application.cs @@ -481,6 +481,7 @@ namespace Terminal.Gui { if (closeDriver) { MainLoop = null; Driver.End (); + Driver = null; } _initialized = false; diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs index 088e14ae7..fb3015893 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -5,7 +5,7 @@ // Miguel de Icaza (miguel@gnome.org) // // Define this to enable diagnostics drawing for Window Frames -#define DRAW_WINDOW_FRAME_DIAGNOSTICS +//#define DRAW_WINDOW_FRAME_DIAGNOSTICS using NStack; using System; using System.Runtime.CompilerServices; diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index c99e0aa91..62266184c 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -55,6 +55,8 @@ namespace UICatalog { private static StatusItem _scrolllock; private static Scenario _runningScenario = null; + private static bool _useSystemConsole = false; + private static MenuItem _sysConsoleMenu; static void Main (string [] args) { @@ -76,6 +78,7 @@ namespace UICatalog { Scenario scenario = GetScenarioToRun (); while (scenario != null) { + Application.UseSystemConsole = _useSystemConsole; Application.Init (); scenario.Init (Application.Top); scenario.Setup (); @@ -86,15 +89,58 @@ namespace UICatalog { Application.Shutdown (); } + /// + /// This shows the selection UI. Each time it is run, it calls Application.Init to reset everything. + /// + /// + private static Scenario GetScenarioToRun () + { + Application.UseSystemConsole = false; + Application.Init (); + + if (_menu == null) { + Setup (); + } + + _top = Application.Top; + + _top.KeyDown += KeyDownHandler; + + _top.Add (_menu); + _top.Add (_leftPane); + _top.Add (_rightPane); + _top.Add (_statusBar); + + _top.Ready += (o, a) => { + if (_runningScenario != null) { + _top.SetFocus (_rightPane); + _runningScenario = null; + } + }; + + Application.Run (_top, false); + Application.Shutdown (); + return _runningScenario; + } + + /// /// Create all controls. This gets called once and the controls remain with their state between Sceanrio runs. /// private static void Setup () { + void HandleSysConsoleMenuChange () + { + _useSystemConsole = !_useSystemConsole; + _sysConsoleMenu.Title = $"[{(_useSystemConsole ? 'x' : ' ')}] _Use System Console"; + } + _sysConsoleMenu = new MenuItem ($"[{(_useSystemConsole ? 'x' : ' ')}] _Use System Console", "", () => HandleSysConsoleMenuChange ()); + _menu = new MenuBar (new MenuBarItem [] { new MenuBarItem ("_File", new MenuItem [] { new MenuItem ("_Quit", "", () => Application.RequestStop() ) }), + new MenuBarItem ("_Settings", new MenuItem [] { _sysConsoleMenu }), new MenuBarItem ("_About...", "About this app", () => MessageBox.Query (50, 10, "About UI Catalog", "UI Catalog is a comprehensive sample library for Terminal.Gui", "Ok")), }); @@ -142,24 +188,17 @@ namespace UICatalog { CanFocus = true, }; - //_scenarioListView.OnKeyPress += (KeyEvent ke) => { - // if (_top.MostFocused == _scenarioListView && ke.Key == Key.Enter) { - // _scenarioListView_OpenSelectedItem (null, null); - // } - //}; - _scenarioListView.OpenSelectedItem += _scenarioListView_OpenSelectedItem; _rightPane.Add (_scenarioListView); _categoryListView.SelectedItem = 0; _categoryListView.OnSelectedChanged (); - _capslock = new StatusItem (Key.CharMask, "CapslockOff", null); - _numlock = new StatusItem (Key.CharMask, "NumlockOff", null); - _scrolllock = new StatusItem (Key.CharMask, "ScrolllockOff", null); + _capslock = new StatusItem (Key.CharMask, "Capslock", null); + _numlock = new StatusItem (Key.CharMask, "Numlock", null); + _scrolllock = new StatusItem (Key.CharMask, "Scrolllock", null); _statusBar = new StatusBar (new StatusItem [] { - //new StatusItem(Key.F1, "~F1~ Help", () => Help()), new StatusItem(Key.ControlQ, "~CTRL-Q~ Quit", () => { if (_runningScenario is null){ // This causes GetScenarioToRun to return null @@ -175,51 +214,6 @@ namespace UICatalog { }); } - /// - /// This shows the selection UI. Each time it is run, it calls Application.Init to reset everything. - /// - /// - private static Scenario GetScenarioToRun () - { - Application.Init (); - - if (_menu == null) { - Setup (); - } - - _top = Application.Top; - - _top.KeyDown += KeyDownHandler; - - _top.Add (_menu); - _top.Add (_leftPane); - _top.Add (_rightPane); - _top.Add (_statusBar); - - // HACK: There is no other way to SetFocus before Application.Run. See Issue #445 -#if false - if (_runningScenario != null) - Application.Iteration += Application_Iteration; -#else - _top.Ready += (o, a) => { - if (_runningScenario != null) { - _top.SetFocus (_rightPane); - _runningScenario = null; - } - }; -#endif - - Application.Run (_top, false); - return _runningScenario; - } - -#if false - private static void Application_Iteration (object sender, EventArgs e) - { - Application.Iteration -= Application_Iteration; - _top.SetFocus (_rightPane); - } -#endif private static void _scenarioListView_OpenSelectedItem (object sender, EventArgs e) { if (_runningScenario is null) { @@ -232,7 +226,7 @@ namespace UICatalog { internal class ScenarioListDataSource : IListDataSource { public List Scenarios { get; set; } - public bool IsMarked (int item) => false;// Scenarios [item].IsMarked; + public bool IsMarked (int item) => false; public int Count => Scenarios.Count; @@ -274,7 +268,6 @@ namespace UICatalog { { return Scenarios; } - } /// @@ -285,15 +278,7 @@ namespace UICatalog { /// private static void KeyDownHandler (object sender, View.KeyEventEventArgs a) { - if (_runningScenario != null) { - //switch (ke.Key) { - //case Key.Esc: - // //_runningScenario.RequestStop (); - // break; - //case Key.Enter: - // break; - //}< - } else if (a.KeyEvent.Key == Key.Tab || a.KeyEvent.Key == Key.BackTab) { + if (a.KeyEvent.Key == Key.Tab || a.KeyEvent.Key == Key.BackTab) { // BUGBUG: Work around Issue #434 by implementing our own TAB navigation if (_top.MostFocused == _categoryListView) _top.SetFocus (_rightPane); @@ -302,26 +287,26 @@ namespace UICatalog { } if (a.KeyEvent.IsCapslock) { - _capslock.Title = "CapslockOn"; + _capslock.Title = "Capslock On"; _statusBar.SetNeedsDisplay (); } else { - _capslock.Title = "CapslockOff"; + _capslock.Title = "Capslock Off"; _statusBar.SetNeedsDisplay (); } if (a.KeyEvent.IsNumlock) { - _numlock.Title = "NumlockOn"; + _numlock.Title = "Numlock On"; _statusBar.SetNeedsDisplay (); } else { - _numlock.Title = "NumlockOff"; + _numlock.Title = "Numlock Off"; _statusBar.SetNeedsDisplay (); } if (a.KeyEvent.IsScrolllock) { - _scrolllock.Title = "ScrolllockOn"; + _scrolllock.Title = "Scrolllock On"; _statusBar.SetNeedsDisplay (); } else { - _scrolllock.Title = "ScrolllockOff"; + _scrolllock.Title = "Scrolllock Off"; _statusBar.SetNeedsDisplay (); } } From 052a8cf5f6784873c00da03b157e112ce8d391a5 Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Sun, 31 May 2020 22:24:50 -0600 Subject: [PATCH 2/5] added menu item to enable system console; fixed Init/Shutdown bug --- UICatalog/Scenarios/SystemConsole.cs | 1 + UICatalog/UICatalog.cs | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/UICatalog/Scenarios/SystemConsole.cs b/UICatalog/Scenarios/SystemConsole.cs index a08bea893..a27ce5789 100644 --- a/UICatalog/Scenarios/SystemConsole.cs +++ b/UICatalog/Scenarios/SystemConsole.cs @@ -14,6 +14,7 @@ namespace UICatalog { public override void RequestStop () { base.RequestStop (); + Application.UseSystemConsole = false; } public override void Run () diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index 62266184c..e550f1259 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -141,7 +141,7 @@ namespace UICatalog { new MenuItem ("_Quit", "", () => Application.RequestStop() ) }), new MenuBarItem ("_Settings", new MenuItem [] { _sysConsoleMenu }), - new MenuBarItem ("_About...", "About this app", () => MessageBox.Query (50, 10, "About UI Catalog", "UI Catalog is a comprehensive sample library for Terminal.Gui", "Ok")), + new MenuBarItem ("_About...", "", () => MessageBox.Query (50, 10, "About UI Catalog", "UI Catalog is a comprehensive sample library for Terminal.Gui", "Ok")), }); _leftPane = new Window ("Categories") { @@ -287,26 +287,26 @@ namespace UICatalog { } if (a.KeyEvent.IsCapslock) { - _capslock.Title = "Capslock On"; + _capslock.Title = "Capslock: On"; _statusBar.SetNeedsDisplay (); } else { - _capslock.Title = "Capslock Off"; + _capslock.Title = "Capslock: Off"; _statusBar.SetNeedsDisplay (); } if (a.KeyEvent.IsNumlock) { - _numlock.Title = "Numlock On"; + _numlock.Title = "Numlock: On"; _statusBar.SetNeedsDisplay (); } else { - _numlock.Title = "Numlock Off"; + _numlock.Title = "Numlock: Off"; _statusBar.SetNeedsDisplay (); } if (a.KeyEvent.IsScrolllock) { - _scrolllock.Title = "Scrolllock On"; + _scrolllock.Title = "Scrolllock: On"; _statusBar.SetNeedsDisplay (); } else { - _scrolllock.Title = "Scrolllock Off"; + _scrolllock.Title = "Scrolllock: Off"; _statusBar.SetNeedsDisplay (); } } From f89fc03a0cc4c0f48fb886042ccaae8248a58921 Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Tue, 2 Jun 2020 10:13:50 -0600 Subject: [PATCH 3/5] merged onlayoutcomplete PR --- Example/demo.cs | 2 +- Terminal.Gui/Core/View.cs | 36 +++++++++++++++++++++++++-- Terminal.Gui/Views/ComboBox.cs | 2 +- Terminal.Gui/Views/StatusBar.cs | 4 +-- Terminal.Gui/Windows/Dialog.cs | 7 +++--- UICatalog/Scenarios/ComputedLayout.cs | 2 +- UICatalog/Scenarios/Scrolling.cs | 5 ++-- 7 files changed, 46 insertions(+), 12 deletions(-) diff --git a/Example/demo.cs b/Example/demo.cs index 0331615c1..e1ca852fe 100644 --- a/Example/demo.cs +++ b/Example/demo.cs @@ -627,7 +627,7 @@ static class Demo { var bottom2 = new Label ("This should go on the bottom of another top-level!"); top.Add (bottom2); - Application.Loaded += (sender, e) => { + top.LayoutComplete += (sender, e) => { bottom.X = win.X; bottom.Y = Pos.Bottom (win) - Pos.Top (win) - margin; bottom2.X = Pos.Left (win); diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index fa5988253..8b35f2e8b 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -1318,15 +1318,45 @@ namespace Terminal.Gui { } /// - /// Invoked when a view starts executing or - /// when the dimensions of the view have changed, for example in + /// Event arguments for the event. + /// + public class LayoutEventArgs : EventArgs { + /// + /// The view-relative bounds of the before it was laid out. + /// + public Rect OldBounds { get; set; } + } + + /// + /// Fired after the Views's method has completed. + /// + /// + /// Subscribe to this event to perform tasks when the has been resized or the layout has otherwise changed. + /// + public event EventHandler LayoutComplete; + + /// + /// Raises the event. Called from after all sub-views have been laid out. + /// + internal virtual void OnLayoutComplete (LayoutEventArgs args) + { + LayoutComplete?.Invoke (this, args); + } + + /// + /// Invoked when a view starts executing or when the dimensions of the view have changed, for example in /// response to the container view or terminal resizing. /// + /// + /// Calls (which raises the event) before it returns. + /// public virtual void LayoutSubviews () { if (!layoutNeeded) return; + Rect oldBounds = Bounds; + // Sort out the dependencies of the X, Y, Width, Height properties var nodes = new HashSet (); var edges = new HashSet<(View, View)> (); @@ -1363,6 +1393,8 @@ namespace Terminal.Gui { } layoutNeeded = false; + + OnLayoutComplete (new LayoutEventArgs () { OldBounds = oldBounds }); } /// diff --git a/Terminal.Gui/Views/ComboBox.cs b/Terminal.Gui/Views/ComboBox.cs index e5ff53dce..a89879f8d 100644 --- a/Terminal.Gui/Views/ComboBox.cs +++ b/Terminal.Gui/Views/ComboBox.cs @@ -58,7 +58,7 @@ namespace Terminal.Gui { SetValue (searchset [listview.SelectedItem]); }; - Application.Loaded += (object sender, Application.ResizedEventArgs e) => { + LayoutComplete += (sender, a) => { // Determine if this view is hosted inside a dialog for (View view = this.SuperView; view != null; view = view.SuperView) { if (view is Dialog) { diff --git a/Terminal.Gui/Views/StatusBar.cs b/Terminal.Gui/Views/StatusBar.cs index 70e4dca2b..bd200c4ff 100644 --- a/Terminal.Gui/Views/StatusBar.cs +++ b/Terminal.Gui/Views/StatusBar.cs @@ -120,7 +120,7 @@ namespace Terminal.Gui { Width = Dim.Fill (); Height = 1; - Application.Loaded += (sender, e) => { + LayoutComplete += (sender, e) => { X = 0; Height = 1; #if SNAP_TO_TOP @@ -132,7 +132,7 @@ namespace Terminal.Gui { case StatusBarStyle.SnapToBottom: #endif if (Parent == null) { - Y = e.Rows - 1; + Y = Driver.Rows - 1; } else { Y = Pos.Bottom (Parent); } diff --git a/Terminal.Gui/Windows/Dialog.cs b/Terminal.Gui/Windows/Dialog.cs index 904d73491..1455ebacd 100644 --- a/Terminal.Gui/Windows/Dialog.cs +++ b/Terminal.Gui/Windows/Dialog.cs @@ -61,6 +61,8 @@ namespace Terminal.Gui { Add (b); } } + + //LayoutComplete += (sender, a) => AdjustButtonLayout (); } /// @@ -98,14 +100,13 @@ namespace Terminal.Gui { } return buttons.Select (b => b.Bounds.Width).Sum () + buttons.Count() - 1; } - /// public override void LayoutSubviews () { int buttonsWidth = GetButtonsWidth (); - int shiftLeft = Math.Max((Bounds.Width - buttonsWidth) / 2 - 2, 0); - for (int i = buttons.Count - 1; i >= 0 ; i--) { + int shiftLeft = Math.Max ((Bounds.Width - buttonsWidth) / 2 - 2, 0); + for (int i = buttons.Count - 1; i >= 0; i--) { Button button = buttons [i]; shiftLeft += button.Frame.Width + 1; button.X = Pos.AnchorEnd (shiftLeft); diff --git a/UICatalog/Scenarios/ComputedLayout.cs b/UICatalog/Scenarios/ComputedLayout.cs index 6bbb4dbe8..0ca45c525 100644 --- a/UICatalog/Scenarios/ComputedLayout.cs +++ b/UICatalog/Scenarios/ComputedLayout.cs @@ -42,7 +42,7 @@ namespace UICatalog { ColorScheme = Colors.Error }; - Application.Resized += (sender, a) => { + Win.LayoutComplete += (sender, a) => { horizontalRuler.Text = rule.Repeat ((int)Math.Ceiling ((double)(horizontalRuler.Bounds.Width) / (double)rule.Length)) [0..(horizontalRuler.Bounds.Width)]; verticalRuler.Text = vrule.Repeat ((int)Math.Ceiling ((double)(verticalRuler.Bounds.Height*2) / (double)rule.Length)) [0..(verticalRuler.Bounds.Height*2)]; }; diff --git a/UICatalog/Scenarios/Scrolling.cs b/UICatalog/Scenarios/Scrolling.cs index 64197021d..da989d02f 100644 --- a/UICatalog/Scenarios/Scrolling.cs +++ b/UICatalog/Scenarios/Scrolling.cs @@ -121,8 +121,9 @@ namespace UICatalog { }; scrollView.Add (verticalRuler); - Application.Resized += (sender, a) => { - horizontalRuler.Text = rule.Repeat ((int)Math.Ceiling ((double)(horizontalRuler.Bounds.Width) / (double)rule.Length)) [0..(horizontalRuler.Bounds.Width)]; + Win.LayoutComplete += (sender, a) => { + horizontalRuler.Text = rule.Repeat ((int)Math.Ceiling ((double)(horizontalRuler.Bounds.Width) / (double)rule.Length)) [0..(horizontalRuler.Bounds.Width)] + + "\n" + "| ".Repeat ((int)Math.Ceiling ((double)(horizontalRuler.Bounds.Width) / (double)rule.Length)) [0..(horizontalRuler.Bounds.Width)]; verticalRuler.Text = vrule.Repeat ((int)Math.Ceiling ((double)(verticalRuler.Bounds.Height * 2) / (double)rule.Length)) [0..(verticalRuler.Bounds.Height * 2)]; }; From 2e1132f484a4b0f165baa0137902a46b3eb7284f Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Tue, 2 Jun 2020 23:50:40 -0600 Subject: [PATCH 4/5] merged upstream master --- Terminal.Gui/Views/Label.cs | 2 ++ Terminal.Gui/Windows/MessageBox.cs | 18 +++++++----------- UICatalog/UICatalog.cs | 6 ++++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Terminal.Gui/Views/Label.cs b/Terminal.Gui/Views/Label.cs index 361d66d8f..af56003c2 100644 --- a/Terminal.Gui/Views/Label.cs +++ b/Terminal.Gui/Views/Label.cs @@ -99,6 +99,8 @@ namespace Terminal.Gui { static ustring ClipAndJustify (ustring str, int width, TextAlignment talign) { + // Get rid of any '\r' added by Windows + str = str.Replace ("\r", ustring.Empty); int slen = str.RuneCount; if (slen > width){ var uints = str.ToRunes (width); diff --git a/Terminal.Gui/Windows/MessageBox.cs b/Terminal.Gui/Windows/MessageBox.cs index a95b9c3ee..3ade88f57 100644 --- a/Terminal.Gui/Windows/MessageBox.cs +++ b/Terminal.Gui/Windows/MessageBox.cs @@ -91,12 +91,11 @@ namespace Terminal.Gui { return QueryFull (true, 0, 0, title, message, buttons); } - static int QueryFull (bool useErrorColors, int width, int height, ustring title, ustring message, params ustring [] buttons) { const int defaultWidth = 30; int textWidth = Label.MaxWidth (message, width); - int textHeight = message.Count(ustring.Make('\n')) + 1; + int textHeight = message.Count (ustring.Make ('\n')) + 1; int msgboxHeight = Math.Max (1, textHeight) + 4; // textHeight + (top + top padding + buttons + bottom) // Create button array for Dialog @@ -126,15 +125,12 @@ namespace Terminal.Gui { if (message != null) { var l = new Label (textWidth > width ? 0 : (width - 4 - textWidth) / 2, 1, message); - //l.ColorScheme = Colors.Menu; - if (true) { //width == 0 & height == 0) { - l.LayoutStyle = LayoutStyle.Computed; - l.TextAlignment = TextAlignment.Centered; - l.X = Pos.Center (); - l.Y = Pos.Center (); - l.Width = Dim.Fill (2); - l.Height = Dim.Fill (2); - } + l.LayoutStyle = LayoutStyle.Computed; + l.TextAlignment = TextAlignment.Centered; + l.X = Pos.Center (); + l.Y = Pos.Center (); + l.Width = Dim.Fill (2); + l.Height = Dim.Fill (2); d.Add (l); } diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index 90fa27a34..7495c287c 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -95,9 +95,11 @@ namespace UICatalog { private static void Setup () { StringBuilder aboutMessage = new StringBuilder (); - aboutMessage.AppendLine ("UI Catalog is a comprehensive sample library for Terminal.Gui\n"); + aboutMessage.AppendLine ("UI Catalog is a comprehensive sample library for Terminal.Gui"); + aboutMessage.AppendLine (""); aboutMessage.AppendLine ($"Version: {typeof(UICatalogApp).Assembly.GetName ().Version}"); - aboutMessage.Append ($"Using Terminal.Gui Version: {typeof (Terminal.Gui.Application).Assembly.GetName ().Version}\n"); + aboutMessage.AppendLine ($"Using Terminal.Gui Version: {typeof (Terminal.Gui.Application).Assembly.GetName ().Version}"); + aboutMessage.AppendLine (""); _menu = new MenuBar (new MenuBarItem [] { new MenuBarItem ("_File", new MenuItem [] { From 95de2ca9e655b4a1cdd8be9a6a7b688f86cfd87d Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Wed, 3 Jun 2020 08:58:19 -0600 Subject: [PATCH 5/5] fixed window drag redraw --- Terminal.Gui/Core/Toplevel.cs | 2 +- Terminal.Gui/Core/View.cs | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Terminal.Gui/Core/Toplevel.cs b/Terminal.Gui/Core/Toplevel.cs index bb647bf21..4e2c6ca1d 100644 --- a/Terminal.Gui/Core/Toplevel.cs +++ b/Terminal.Gui/Core/Toplevel.cs @@ -264,7 +264,7 @@ namespace Terminal.Gui { if (IsCurrentTop || this == Application.Top) { if (NeedDisplay != null && !NeedDisplay.IsEmpty) { Driver.SetAttribute (Colors.TopLevel.Normal); - Clear (bounds); + Clear (Frame); Driver.SetAttribute (Colors.Base.Normal); } foreach (var view in Subviews) { diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index 8b35f2e8b..1d50cfe5b 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -911,9 +911,12 @@ namespace Terminal.Gui { /// /// Redraws this view and its subviews; only redraws the views that have been flagged for a re-display. /// - /// The view-relative region to redraw. + /// The bounds (view-relative region) to redraw. /// /// + /// Always use (view-relative) when calling , NOT (superview-relative). + /// + /// /// Views should set the color that they want to use on entry, as otherwise this will inherit /// the last color that was set globaly on the driver. ///