Explorar o código

Merge pull request #1001 from BDisp/UI-label-as-buttons

Fixing "LabelsAsButtons.cs" layout as "Buttons.cs" scenario.
Charlie Kindel %!s(int64=4) %!d(string=hai) anos
pai
achega
81ae970c5f

+ 2 - 7
Terminal.Gui/Core/Application.cs

@@ -432,12 +432,6 @@ namespace Terminal.Gui {
 			return p.X < 0 || p.X > r.Width - 1 || p.Y < 0 || p.Y > r.Height - 1;
 		}
 
-		/// <summary>
-		/// This event is fired once when the application is first loaded. The dimensions of the
-		/// terminal are provided.
-		/// </summary>
-		public static Action<ResizedEventArgs> Loaded;
-
 		/// <summary>
 		/// Building block API: Prepares the provided <see cref="Toplevel"/>  for execution.
 		/// </summary>
@@ -472,8 +466,8 @@ namespace Terminal.Gui {
 			if (toplevel.LayoutStyle == LayoutStyle.Computed)
 				toplevel.SetRelativeLayout (new Rect (0, 0, Driver.Cols, Driver.Rows));
 			toplevel.LayoutSubviews ();
-			Loaded?.Invoke (new ResizedEventArgs () { Rows = Driver.Rows, Cols = Driver.Cols });
 			toplevel.WillPresent ();
+			toplevel.OnLoaded ();
 			Redraw (toplevel);
 			toplevel.PositionCursor ();
 			Driver.Refresh ();
@@ -490,6 +484,7 @@ namespace Terminal.Gui {
 			if (runState == null)
 				throw new ArgumentNullException (nameof (runState));
 
+			runState.Toplevel.OnUnloaded ();
 			runState.Dispose ();
 		}
 

+ 31 - 3
Terminal.Gui/Core/Toplevel.cs

@@ -49,20 +49,48 @@ namespace Terminal.Gui {
 		public bool Running { get; set; }
 
 		/// <summary>
-		/// Fired once the Toplevel's <see cref="MainLoop"/> has started it's first iteration. 
+		/// Fired once the Toplevel's <see cref="Application.RunState"/> has begin loaded.
+		/// A Loaded event handler is a good place to finalize initialization before calling `<see cref="Application.RunLoop(Application.RunState, bool)"/>.
+		/// </summary>
+		public event Action Loaded;
+
+		/// <summary>
+		/// Fired once the Toplevel's <see cref="MainLoop"/> has started it's first iteration.
 		/// Subscribe to this event to perform tasks when the <see cref="Toplevel"/> has been laid out and focus has been set.
-		/// changes. A Ready event handler is a good place to finalize initialization after calling `<see cref="Application.Run()"/>(topLevel)`. 
+		/// changes. A Ready event handler is a good place to finalize initialization after calling `<see cref="Application.Run()"/>(topLevel)`.
 		/// </summary>
 		public event Action Ready;
 
 		/// <summary>
-		/// Called from <see cref="Application.RunLoop"/> after the <see cref="Toplevel"/> has entered it's first iteration of the loop. 
+		/// Fired once the Toplevel's <see cref="Application.RunState"/> has begin unloaded.
+		/// A Unloaded event handler is a good place to disposing after calling `<see cref="Application.End(Application.RunState)"/>.
+		/// </summary>
+		public event Action Unloaded;
+
+		/// <summary>
+		/// Called from <see cref="Application.Begin(Toplevel)"/> before the <see cref="Toplevel"/> is redraws for the first time.
+		/// </summary>
+		internal virtual void OnLoaded ()
+		{
+			Loaded?.Invoke ();
+		}
+
+		/// <summary>
+		/// Called from <see cref="Application.RunLoop"/> after the <see cref="Toplevel"/> has entered it's first iteration of the loop.
 		/// </summary>
 		internal virtual void OnReady ()
 		{
 			Ready?.Invoke ();
 		}
 
+		/// <summary>
+		/// Called from <see cref="Application.End(Application.RunState)"/> before the <see cref="Toplevel"/> is disposed.
+		/// </summary>
+		internal virtual void OnUnloaded ()
+		{
+			Unloaded?.Invoke ();
+		}
+
 		/// <summary>
 		/// Initializes a new instance of the <see cref="Toplevel"/> class with the specified absolute layout.
 		/// </summary>

+ 7 - 2
UICatalog/Scenarios/Dialogs.cs

@@ -93,8 +93,13 @@ namespace UICatalog {
 			};
 			frame.Add (numButtonsEdit);
 
-			Top.Ready += () => frame.Height = Dim.Height (widthEdit) + Dim.Height (heightEdit) + Dim.Height (titleEdit)
-				+ Dim.Height (numButtonsEdit) + 2;
+			void Top_Loaded ()
+			{
+				frame.Height = Dim.Height (widthEdit) + Dim.Height (heightEdit) + Dim.Height (titleEdit)
+					+ Dim.Height (numButtonsEdit) + 2;
+				Top.Loaded -= Top_Loaded;
+			}
+			Top.Loaded += Top_Loaded;
 
 			label = new Label ("Button Pressed:") {
 				X = Pos.Center (),

+ 4 - 2
UICatalog/Scenarios/LabelsAsButtons.cs

@@ -235,7 +235,7 @@ namespace UICatalog {
 			var moveHotKeyBtn = new Label (mhkb) {
 				X = 2,
 				Y = Pos.Bottom (radioGroup) + 1,
-				Width = mhkb.Length + 10,
+				Width = Dim.Width (computedFrame) - 2,
 				ColorScheme = Colors.TopLevel,
 				HotKeySpecifier = (System.Rune)'_',
 				CanFocus = true,
@@ -249,7 +249,7 @@ namespace UICatalog {
 			var moveUnicodeHotKeyBtn = new Label (muhkb) {
 				X = Pos.Left (absoluteFrame) + 1,
 				Y = Pos.Bottom (radioGroup) + 1,
-				Width = muhkb.Length + 30,
+				Width = Dim.Width (absoluteFrame) - 2,
 				ColorScheme = Colors.TopLevel,
 				HotKeySpecifier = (System.Rune)'_',
 				CanFocus = true,
@@ -295,6 +295,8 @@ namespace UICatalog {
 					break;
 				}
 			};
+
+			Top.Ready += () => radioGroup.Refresh ();
 		}
 	}
 }

+ 7 - 2
UICatalog/Scenarios/MessageBoxes.cs

@@ -124,8 +124,13 @@ namespace UICatalog {
 			};
 			frame.Add (styleRadioGroup);
 
-			Top.Ready += () => frame.Height = Dim.Height (widthEdit) + Dim.Height (heightEdit) + Dim.Height (titleEdit) + Dim.Height (messageEdit)
-				+ Dim.Height (numButtonsEdit) + Dim.Height (styleRadioGroup) + 2;
+			void Top_Loaded ()
+			{
+				frame.Height = Dim.Height (widthEdit) + Dim.Height (heightEdit) + Dim.Height (titleEdit) + Dim.Height (messageEdit)
+					+ Dim.Height (numButtonsEdit) + Dim.Height (styleRadioGroup) + 2;
+				Top.Loaded -= Top_Loaded;
+			}
+			Top.Loaded += Top_Loaded;
 
 			label = new Label ("Button Pressed:") {
 				X = Pos.Center (),

+ 1 - 0
UICatalog/Scenarios/Progress.cs

@@ -100,6 +100,7 @@ namespace UICatalog {
 				};
 				Add (_startedLabel);
 
+				LayoutSubviews ();
 
 				// Set height to height of controls + spacing + frame
 				Height = 2 + _verticalSpace + Dim.Height (startButton) + _verticalSpace + Dim.Height (ActivityProgressBar) + _verticalSpace + Dim.Height (PulseProgressBar) + _verticalSpace;

+ 12 - 2
UICatalog/Scenarios/Scrolling.cs

@@ -143,11 +143,13 @@ namespace UICatalog {
 			};
 			scrollView.Add (verticalRuler);
 
-			Win.LayoutComplete += (a) => {
+			void Top_Loaded()  {
 				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)];
+				Top.Loaded -= Top_Loaded;
 			};
+			Top.Loaded += Top_Loaded;
 
 			var pressMeButton = new Button ("Press me!") {
 				X = 3,
@@ -282,13 +284,21 @@ namespace UICatalog {
 			progress.X = Pos.Right (scrollView) + 1;
 			progress.Y = Pos.AnchorEnd (2);
 			progress.Width = 50;
+			bool pulsing = true;
 			bool timer (MainLoop caller)
 			{
 				progress.Pulse ();
-				return true;
+				return pulsing;
 			}
 			Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (300), timer);
 
+			void Top_Unloaded ()
+			{
+				pulsing = false;
+				Top.Unloaded -= Top_Unloaded;
+			}
+			Top.Unloaded += Top_Unloaded;
+
 			Win.Add (scrollView, scrollView2, scrollView3, mousePos, progress);
 		}
 	}

+ 4 - 4
UICatalog/UICatalog.cs

@@ -100,13 +100,13 @@ namespace UICatalog {
 				scenario.Setup ();
 				scenario.Run ();
 
-				static void ReadyHandler ()
+				static void LoadedHandler ()
 				{
 					_rightPane.SetFocus ();
-					_top.Ready -= ReadyHandler;
+					_top.Loaded -= LoadedHandler;
 				}
 
-				_top.Ready += ReadyHandler;
+				_top.Loaded += LoadedHandler;
 
 #if DEBUG_IDISPOSABLE
 				// After the scenario runs, validate all Responder-based instances
@@ -258,7 +258,7 @@ namespace UICatalog {
 			_top.Add (_leftPane);
 			_top.Add (_rightPane);
 			_top.Add (_statusBar);
-			_top.Ready += () => {
+			_top.Loaded += () => {
 				if (_runningScenario != null) {
 					_runningScenario = null;
 				}

+ 15 - 0
UnitTests/ApplicationTests.cs

@@ -212,5 +212,20 @@ namespace Terminal.Gui {
 			Assert.Null (Application.MainLoop);
 			Assert.Null (Application.Driver);
 		}
+
+		[Fact]
+		public void Loaded_Ready_Unlodaded_Events ()
+		{
+			Init ();
+			var top = Application.Top;
+			var count = 0;
+			top.Loaded += () => count++;
+			top.Ready += () => count++;
+			top.Unloaded += () => count++;
+			Application.Iteration = () => Application.RequestStop ();
+			Application.Run ();
+			Application.Shutdown ();
+			Assert.Equal (3, count);
+		}
 	}
 }