From ee7fc3022db80aa705b338df3b557103f1a69f52 Mon Sep 17 00:00:00 2001 From: BDisp Date: Wed, 15 Apr 2020 02:50:17 +0100 Subject: [PATCH] Fixes #355 stack overflow with Pos based on the size of windows at startup. Added a OnResized action to set the Pos after the terminal are resized. (#367) --- Example/demo.cs | 16 +++++---- Terminal.Gui/Core.cs | 84 ++++++++++++++++++++++++-------------------- 2 files changed, 55 insertions(+), 45 deletions(-) diff --git a/Example/demo.cs b/Example/demo.cs index 9bacd6574..3cc63d77c 100644 --- a/Example/demo.cs +++ b/Example/demo.cs @@ -88,7 +88,7 @@ static class Demo { "Text Alignments", 50, 20, new Button ("Ok", is_default: true) { Clicked = () => { Application.RequestStop (); } }, new Button ("Cancel") { Clicked = () => { Application.RequestStop (); } }); - + int i = 0; string txt = "Hello world, how are you doing today"; @@ -418,6 +418,8 @@ static class Demo { CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo ("en-US"); //Application.UseSystemConsole = true; + Console.WindowHeight = 35; + Application.Init (); var top = Application.Top; @@ -521,14 +523,16 @@ static class Demo { }); win.Add (drag, dragText); -#if false +#if true // This currently causes a stack overflow, because it is referencing a window that has not had its size allocated yet - var bottom = new Label ("This should go on the bottom!") { - X = Pos.Left (win), - Y = Pos.Bottom (win) - }; + var bottom = new Label ("This should go on the bottom!"); win.Add (bottom); + + Application.OnResized = () => { + bottom.X = Pos.Left (win); + bottom.Y = Pos.Bottom (win); + }; #endif top.Add (win); diff --git a/Terminal.Gui/Core.cs b/Terminal.Gui/Core.cs index d0477ef86..b37d76d4a 100644 --- a/Terminal.Gui/Core.cs +++ b/Terminal.Gui/Core.cs @@ -68,7 +68,7 @@ namespace Terminal.Gui { /// /// If the view is focused, gives the view a - /// chance to process the keystroke. + /// chance to process the keystroke. /// /// /// @@ -83,7 +83,7 @@ namespace Terminal.Gui { /// /// /// The View implementation does nothing but return false, - /// so it is not necessary to call base.ProcessKey if you + /// so it is not necessary to call base.ProcessKey if you /// derive directly from View, but you should if you derive /// other View subclasses. /// @@ -161,27 +161,27 @@ namespace Terminal.Gui { /// /// Views can either be created with an absolute position, by calling the constructor that takes a /// Rect parameter to specify the absolute position and size (the Frame of the View) or by setting the - /// X, Y, Width and Height properties on the view. Both approaches use coordinates that are relative + /// X, Y, Width and Height properties on the view. Both approaches use coordinates that are relative /// to the container they are being added to. /// /// - /// When you do not specify a Rect frame you can use the more flexible - /// Dim and Pos objects that can dynamically update the position of a view. + /// When you do not specify a Rect frame you can use the more flexible + /// Dim and Pos objects that can dynamically update the position of a view. /// The X and Y properties are of type /// and you can use either absolute positions, percentages or anchor - /// points. The Width and Height properties are of type - /// and can use absolute position, + /// points. The Width and Height properties are of type + /// and can use absolute position, /// percentages and anchors. These are useful as they will take /// care of repositioning your views if your view's frames are resized /// or if the terminal size changes. /// /// - /// When you specify the Rect parameter to a view, you are setting the LayoutStyle to Absolute, and the - /// view will always stay in the position that you placed it. To change the position change the + /// When you specify the Rect parameter to a view, you are setting the LayoutStyle to Absolute, and the + /// view will always stay in the position that you placed it. To change the position change the /// Frame property to the new position. /// /// - /// Subviews can be added to a View by calling the Add method. The container of a view is the + /// Subviews can be added to a View by calling the Add method. The container of a view is the /// Superview. /// /// @@ -192,7 +192,7 @@ namespace Terminal.Gui { /// Views have a ColorScheme property that defines the default colors that subviews /// should use for rendering. This ensures that the views fit in the context where /// they are being used, and allows for themes to be plugged in. For example, the - /// default colors for windows and toplevels uses a blue background, while it uses + /// default colors for windows and toplevels uses a blue background, while it uses /// a white background for dialog boxes and a red background for errors. /// /// @@ -208,7 +208,7 @@ namespace Terminal.Gui { /// /// Views that are focusable should implement the PositionCursor to make sure that /// the cursor is placed in a location that makes sense. Unix terminals do not have - /// a way of hiding the cursor, so it can be distracting to have the cursor left at + /// a way of hiding the cursor, so it can be distracting to have the cursor left at /// the last focused view. So views should make sure that they place the cursor /// in a visually sensible place. /// @@ -257,7 +257,7 @@ namespace Terminal.Gui { static IList empty = new List (0).AsReadOnly (); - // This is null, and allocated on demand. + // This is null, and allocated on demand. List subviews; /// @@ -292,7 +292,7 @@ namespace Terminal.Gui { /// /// The frame. /// - /// Altering the Frame of a view will trigger the redrawing of the + /// Altering the Frame of a view will trigger the redrawing of the /// view as well as the redrawing of the affected regions in the superview. /// public virtual Rect Frame { @@ -422,7 +422,7 @@ namespace Terminal.Gui { /// /// Initializes a new instance of the class and sets the - /// view up for Computed layout, which will use the values in X, Y, Width and Height to + /// view up for Computed layout, which will use the values in X, Y, Width and Height to /// compute the View's Frame. /// public View () @@ -1233,8 +1233,8 @@ namespace Terminal.Gui { } /// - /// This virtual method is invoked when a view starts executing or - /// when the dimensions of the view have changed, for example in + /// This virtual method is 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. /// public virtual void LayoutSubviews () @@ -1269,8 +1269,8 @@ namespace Terminal.Gui { if (v.LayoutStyle == LayoutStyle.Computed) v.RelativeLayout (Frame); - - v.LayoutSubviews (); + if (this?.SuperView != v) + v.LayoutSubviews (); v.layoutNeeded = false; } @@ -1304,23 +1304,23 @@ namespace Terminal.Gui { /// new toplevel. /// /// - /// TopLevels can also opt-in to more sophisticated initialization - /// by implementing . When they do - /// so, the and - /// methods will be called + /// 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, + /// 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 { /// /// This flag is checked on each iteration of the mainloop and it continues - /// running until this flag is set to false. + /// running until this flag is set to false. /// public bool Running; @@ -1362,8 +1362,8 @@ namespace Terminal.Gui { } /// - /// Determines whether the is modal or not. - /// Causes to propagate keys upwards + /// Determines whether the is modal or not. + /// Causes to propagate keys upwards /// by default unless set to . /// public bool Modal { get; set; } @@ -1592,7 +1592,7 @@ namespace Terminal.Gui { int padding; /// /// Initializes a new instance of the with - /// the specified frame for its location, with the specified border + /// the specified frame for its location, with the specified border /// an optional title. /// /// Frame. @@ -1610,7 +1610,7 @@ namespace Terminal.Gui { /// /// Initializes a new instance of the with - /// the specified frame for its location, with the specified border + /// the specified frame for its location, with the specified border /// an optional title. /// /// Number of characters to use for padding of the drawn frame. @@ -1771,7 +1771,7 @@ namespace Terminal.Gui { /// /// /// - /// You can hook up to the Iteration event to have your method + /// You can hook up to the Iteration event to have your method /// invoked on each iteration of the mainloop. /// /// @@ -1811,7 +1811,7 @@ namespace Terminal.Gui { /// /// This event is raised on each iteration of the - /// main loop. + /// main loop. /// /// /// See also @@ -2069,7 +2069,7 @@ namespace Terminal.Gui { /// Toplevel to prepare execution for. /// /// This method prepares the provided toplevel for running with the focus, - /// it adds this to the list of toplevels, sets up the mainloop to process the + /// it adds this to the list of toplevels, sets up the mainloop to process the /// event, lays out the subviews, focuses the first element, and draws the /// toplevel in the screen. This is usually followed by executing /// the method, and then the method upon termination which will @@ -2082,7 +2082,7 @@ namespace Terminal.Gui { var rs = new RunState (toplevel); Init (); - if (toplevel is ISupportInitializeNotification initializableNotification && + if (toplevel is ISupportInitializeNotification initializableNotification && !initializableNotification.IsInitialized) { initializableNotification.BeginInit(); initializableNotification.EndInit(); @@ -2172,7 +2172,7 @@ namespace Terminal.Gui { /// /// /// Use the wait parameter to control whether this is a - /// blocking or non-blocking call. + /// blocking or non-blocking call. /// /// The state returned by the Begin method. /// By default this is true which will execute the runloop waiting for events, if you pass false, you can use this method to run a single iteration of the events. @@ -2246,7 +2246,7 @@ namespace Terminal.Gui { /// returned value, and then calling end on the return value. /// /// - /// Alternatively, if your program needs to control the main loop and needs to + /// Alternatively, if your program needs to control the main loop and needs to /// process events manually, you can invoke Begin to set things up manually and then /// repeatedly call RunLoop with the wait parameter set to false. By doing this /// the RunLoop method will only process any pending events, timers, idle handlers and @@ -2268,8 +2268,14 @@ namespace Terminal.Gui { Current.Running = false; } + /// + /// Invoked when the terminal was resized. + /// + static public Action OnResized; + static void TerminalResized () { + OnResized?.Invoke (); var full = new Rect (0, 0, Driver.Cols, Driver.Rows); Driver.Clip = full; foreach (var t in toplevels) {