浏览代码

Added IsLoaded property to allow control if a change was done before or after the toplevel was loaded.

BDisp 2 年之前
父节点
当前提交
5840ad25e8
共有 4 个文件被更改,包括 95 次插入0 次删除
  1. 8 0
      Terminal.Gui/Core/Toplevel.cs
  2. 5 0
      Terminal.Gui/Core/View.cs
  3. 34 0
      UnitTests/Core/ViewTests.cs
  4. 48 0
      UnitTests/TopLevels/ToplevelTests.cs

+ 8 - 0
Terminal.Gui/Core/Toplevel.cs

@@ -167,6 +167,7 @@ namespace Terminal.Gui {
 		/// </summary>
 		/// </summary>
 		virtual public void OnLoaded ()
 		virtual public void OnLoaded ()
 		{
 		{
+			IsLoaded = true;
 			foreach (Toplevel tl in Subviews.Where (v => v is Toplevel)) {
 			foreach (Toplevel tl in Subviews.Where (v => v is Toplevel)) {
 				tl.OnLoaded ();
 				tl.OnLoaded ();
 			}
 			}
@@ -367,6 +368,13 @@ namespace Terminal.Gui {
 			}
 			}
 		}
 		}
 
 
+		/// <summary>
+		/// <see langword="true"/> if was already loaded by the <see cref="Application.Begin(Toplevel)"/>
+		/// <see langword="false"/>, otherwise. This is used to avoid the <see cref="View.NeedDisplay"/>
+		/// having wrong values while this was not yet loaded.
+		/// </summary>
+		public bool IsLoaded { get; private set; }
+
 		///<inheritdoc/>
 		///<inheritdoc/>
 		public override bool OnKeyDown (KeyEvent keyEvent)
 		public override bool OnKeyDown (KeyEvent keyEvent)
 		{
 		{

+ 5 - 0
Terminal.Gui/Core/View.cs

@@ -829,6 +829,11 @@ namespace Terminal.Gui {
 
 
 		Rect GetMaxNeedDisplay (Rect oldFrame, Rect newFrame)
 		Rect GetMaxNeedDisplay (Rect oldFrame, Rect newFrame)
 		{
 		{
+			var topSuperView = GetTopSuperView ();
+			if (topSuperView == null || topSuperView is not Toplevel || ((Toplevel)topSuperView)?.IsLoaded == false) {
+				return newFrame;
+			}
+
 			var rect = new Rect () {
 			var rect = new Rect () {
 				X = Math.Min (oldFrame.X, newFrame.X),
 				X = Math.Min (oldFrame.X, newFrame.X),
 				Y = Math.Min (oldFrame.Y, newFrame.Y),
 				Y = Math.Min (oldFrame.Y, newFrame.Y),

+ 34 - 0
UnitTests/Core/ViewTests.cs

@@ -2885,6 +2885,7 @@ At 0,0
 			frame.Height = 8;
 			frame.Height = 8;
 
 
 			var top = Application.Top;
 			var top = Application.Top;
+
 			top.Add (frame);
 			top.Add (frame);
 
 
 			Assert.Equal (new Rect (0, 0, 80, 25), top.Frame);
 			Assert.Equal (new Rect (0, 0, 80, 25), top.Frame);
@@ -2897,6 +2898,39 @@ At 0,0
 			Assert.Equal (new Rect (0, 0, 30, 1), label.Frame);
 			Assert.Equal (new Rect (0, 0, 30, 1), label.Frame);
 			Assert.Equal (new Rect (0, 0, 13, 1), button.Frame);
 			Assert.Equal (new Rect (0, 0, 13, 1), button.Frame);
 
 
+			Assert.Equal (new Rect (0, 0, 80, 25), top.NeedDisplay);
+			Assert.Equal (new Rect (0, 0, 40, 8), frame.NeedDisplay);
+			Assert.Equal (Rect.Empty, frame.Subviews [0].NeedDisplay);
+			Assert.Equal (new Rect (0, 0, 40, 8), new Rect (
+				frame.NeedDisplay.Left, frame.NeedDisplay.Top,
+				frame.NeedDisplay.Right, frame.NeedDisplay.Bottom));
+			Assert.Equal (new Rect (0, 0, 30, 1), label.NeedDisplay);
+			Assert.Equal (new Rect (0, 0, 13, 1), button.NeedDisplay);
+
+			top.LayoutComplete += e => {
+				Assert.Equal (new Rect (0, 0, 80, 25), top.NeedDisplay);
+			};
+
+			frame.LayoutComplete += e => {
+				Assert.Equal (new Rect (0, 0, 40, 8), frame.NeedDisplay);
+			};
+
+			frame.Subviews [0].LayoutComplete += e => {
+				if (top.IsLoaded) {
+					Assert.Equal (new Rect (0, 0, 38, 6), frame.Subviews [0].NeedDisplay);
+				} else {
+					Assert.Equal (new Rect (1, 1, 38, 6), frame.Subviews [0].NeedDisplay);
+				}
+			};
+
+			label.LayoutComplete += e => {
+				Assert.Equal (new Rect (0, 0, 38, 1), label.NeedDisplay);
+			};
+
+			button.LayoutComplete += e => {
+				Assert.Equal (new Rect (0, 0, 13, 1), button.NeedDisplay);
+			};
+
 			Application.Begin (top);
 			Application.Begin (top);
 
 
 			Assert.True (label.AutoSize);
 			Assert.True (label.AutoSize);

+ 48 - 0
UnitTests/TopLevels/ToplevelTests.cs

@@ -1031,5 +1031,53 @@ namespace Terminal.Gui.TopLevelTests {
 			Application.Driver.GetCursorVisibility (out cursor);
 			Application.Driver.GetCursorVisibility (out cursor);
 			Assert.Equal (CursorVisibility.Invisible, cursor);
 			Assert.Equal (CursorVisibility.Invisible, cursor);
 		}
 		}
+
+		[Fact, AutoInitShutdown]
+		public void IsLoaded_Application_Begin ()
+		{
+			var top = Application.Top;
+			Assert.False (top.IsLoaded);
+
+			Application.Begin (top);
+			Assert.True (top.IsLoaded);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void IsLoaded_With_Sub_Toplevel_Application_Begin_NeedDisplay ()
+		{
+			var top = Application.Top;
+			var subTop = new Toplevel ();
+			var view = new View (new Rect (0, 0, 20, 10));
+			subTop.Add (view);
+			top.Add (subTop);
+
+			Assert.False (top.IsLoaded);
+			Assert.False (subTop.IsLoaded);
+			Assert.Equal (new Rect (0, 0, 20, 10), view.Frame);
+			Assert.Equal (new Rect (0, 0, 20, 10), view.NeedDisplay);
+
+			view.LayoutStarted += view_LayoutStarted;
+
+			void view_LayoutStarted (View.LayoutEventArgs e)
+			{
+				Assert.Equal (new Rect (0, 0, 20, 10), view.NeedDisplay);
+				view.LayoutStarted -= view_LayoutStarted;
+			}
+
+			Application.Begin (top);
+
+			Assert.True (top.IsLoaded);
+			Assert.True (subTop.IsLoaded);
+			Assert.Equal (new Rect (0, 0, 20, 10), view.Frame);
+
+			view.Frame = new Rect (1, 3, 10, 5);
+			Assert.Equal (new Rect (1, 3, 10, 5), view.Frame);
+			Assert.Equal (new Rect (0, 0, 20, 10), view.NeedDisplay);
+
+			view.Redraw (view.Bounds);
+			view.Frame = new Rect (1, 3, 10, 5);
+			Assert.Equal (new Rect (1, 3, 10, 5), view.Frame);
+			Assert.Equal (new Rect (1, 3, 10, 5), view.NeedDisplay);
+		}
 	}
 	}
 }
 }