فهرست منبع

Fixes #2308. Redraw passed bounds bigger than its client area.

BDisp 2 سال پیش
والد
کامیت
cd5655fc95
2فایلهای تغییر یافته به همراه193 افزوده شده و 13 حذف شده
  1. 19 12
      Terminal.Gui/Core/View.cs
  2. 174 1
      UnitTests/Views/ViewTests.cs

+ 19 - 12
Terminal.Gui/Core/View.cs

@@ -446,14 +446,11 @@ namespace Terminal.Gui {
 		public virtual Rect Frame {
 			get => frame;
 			set {
-				if (SuperView != null) {
-					SuperView.SetNeedsDisplay (frame);
-					SuperView.SetNeedsDisplay (value);
-				}
+				var rect = GetMaxNeedDisplay (frame, value);
 				frame = new Rect (value.X, value.Y, Math.Max (value.Width, 0), Math.Max (value.Height, 0));
 				TextFormatter.Size = GetBoundsTextFormatterSize ();
 				SetNeedsLayout ();
-				SetNeedsDisplay (frame);
+				SetNeedsDisplay (rect);
 			}
 		}
 
@@ -811,6 +808,7 @@ namespace Terminal.Gui {
 		{
 			var actX = x is Pos.PosAbsolute ? x.Anchor (0) : frame.X;
 			var actY = y is Pos.PosAbsolute ? y.Anchor (0) : frame.Y;
+			Rect oldFrame = frame;
 
 			if (AutoSize) {
 				var s = GetAutoSize ();
@@ -825,7 +823,21 @@ namespace Terminal.Gui {
 			}
 			TextFormatter.Size = GetBoundsTextFormatterSize ();
 			SetNeedsLayout ();
-			SetNeedsDisplay ();
+			SetNeedsDisplay (GetMaxNeedDisplay (oldFrame, frame));
+		}
+
+		Rect GetMaxNeedDisplay (Rect oldFrame, Rect newFrame)
+		{
+			var rect = new Rect () {
+				X = Math.Min (oldFrame.X, newFrame.X),
+				Y = Math.Min (oldFrame.Y, newFrame.Y),
+				Width = Math.Max (oldFrame.Width, newFrame.Width),
+				Height = Math.Max (oldFrame.Height, newFrame.Height)
+			};
+			rect.Width += Math.Max (oldFrame.X - newFrame.X, 0);
+			rect.Height += Math.Max (oldFrame.Y - newFrame.Y, 0);
+
+			return rect;
 		}
 
 		void TextFormatter_HotKeyChanged (Key obj)
@@ -1537,12 +1549,7 @@ namespace Terminal.Gui {
 							// Draw the subview
 							// Use the view's bounds (view-relative; Location will always be (0,0)
 							if (view.Visible && view.Frame.Width > 0 && view.Frame.Height > 0) {
-								var rect = new Rect () {
-									X = Math.Min (view.Bounds.X, view.NeedDisplay.X),
-									Y = Math.Min (view.Bounds.Y, view.NeedDisplay.Y),
-									Width = Math.Max (view.Bounds.Width, view.NeedDisplay.Width),
-									Height = Math.Max (view.Bounds.Height, view.NeedDisplay.Height)
-								};
+								var rect = view.Bounds;
 								view.OnDrawContent (rect);
 								view.Redraw (rect);
 								view.OnDrawContentComplete (rect);

+ 174 - 1
UnitTests/Views/ViewTests.cs

@@ -1,4 +1,5 @@
-using System;
+using NStack;
+using System;
 using Xunit;
 using Xunit.Abstractions;
 //using GraphViewTests = Terminal.Gui.Views.GraphViewTests;
@@ -3991,6 +3992,7 @@ This is a tes
 			public bool IsKeyDown { get; set; }
 			public bool IsKeyPress { get; set; }
 			public bool IsKeyUp { get; set; }
+			public override ustring Text { get; set; }
 
 			public override bool OnKeyDown (KeyEvent keyEvent)
 			{
@@ -4009,6 +4011,41 @@ This is a tes
 				IsKeyUp = true;
 				return true;
 			}
+
+			public void CorrectRedraw (Rect bounds)
+			{
+				// Clear the old and new frame area
+				Clear (NeedDisplay);
+				DrawText ();
+			}
+
+			public void IncorrectRedraw (Rect bounds)
+			{
+				// Clear only the new frame area
+				Clear ();
+				DrawText ();
+			}
+
+			private void DrawText ()
+			{
+				var idx = 0;
+				for (int r = 0; r < Frame.Height; r++) {
+					for (int c = 0; c < Frame.Width; c++) {
+						if (idx < Text.Length) {
+							var rune = Text [idx];
+							if (rune != '\n') {
+								AddRune (c, r, Text [idx]);
+							}
+							idx++;
+							if (rune == '\n') {
+								break;
+							}
+						}
+					}
+				}
+				ClearLayoutNeeded ();
+				ClearNeedsDisplay ();
+			}
 		}
 
 		[Theory, AutoInitShutdown]
@@ -4176,5 +4213,141 @@ cccccccccccccccccccc", output);
 111111111111111111110", attributes);
 			}
 		}
+
+		[Fact, AutoInitShutdown]
+		public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_Using_Frame ()
+		{
+			var label = new Label ("At 0,0");
+			var view = new DerivedView () {
+				X = 2,
+				Y = 2,
+				Width = 30,
+				Height = 2,
+				Text = "A text with some long width\n and also with two lines."
+			};
+			var top = Application.Top;
+			top.Add (label, view);
+			Application.Begin (top);
+
+			view.CorrectRedraw (view.Bounds);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+At 0,0                       
+                             
+  A text with some long width
+   and also with two lines.  ", output);
+
+			view.Frame = new Rect (1, 1, 10, 1);
+			Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds);
+			Assert.Equal (new Rect (1, 1, 31, 3), view.NeedDisplay);
+			view.CorrectRedraw (view.Bounds);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+At 0,0     
+ A text wit", output);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_Using_Pos_Dim ()
+		{
+			var label = new Label ("At 0,0");
+			var view = new DerivedView () {
+				X = 2,
+				Y = 2,
+				Width = 30,
+				Height = 2,
+				Text = "A text with some long width\n and also with two lines."
+			};
+			var top = Application.Top;
+			top.Add (label, view);
+			Application.Begin (top);
+
+			view.CorrectRedraw (view.Bounds);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+At 0,0                       
+                             
+  A text with some long width
+   and also with two lines.  ", output);
+
+			view.X = 1;
+			view.Y = 1;
+			view.Width = 10;
+			view.Height = 1;
+			Assert.Equal (new Rect (1, 1, 10, 1), view.Frame);
+			Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds);
+			Assert.Equal (new Rect (1, 1, 31, 3), view.NeedDisplay);
+			view.CorrectRedraw (view.Bounds);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+At 0,0     
+ A text wit", output);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_Using_Frame ()
+		{
+			var label = new Label ("At 0,0");
+			var view = new DerivedView () {
+				X = 2,
+				Y = 2,
+				Width = 30,
+				Height = 2,
+				Text = "A text with some long width\n and also with two lines."
+			};
+			var top = Application.Top;
+			top.Add (label, view);
+			Application.Begin (top);
+
+			view.IncorrectRedraw (view.Bounds);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+At 0,0                       
+                             
+  A text with some long width
+   and also with two lines.  ", output);
+
+			view.Frame = new Rect (1, 1, 10, 1);
+			Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds);
+			Assert.Equal (new Rect (1, 1, 31, 3), view.NeedDisplay);
+			view.IncorrectRedraw (view.Bounds);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+At 0,0                       
+ A text wit                  
+  A text with some long width
+   and also with two lines.  ", output);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_Using_Pos_Dim ()
+		{
+			var label = new Label ("At 0,0");
+			var view = new DerivedView () {
+				X = 2,
+				Y = 2,
+				Width = 30,
+				Height = 2,
+				Text = "A text with some long width\n and also with two lines."
+			};
+			var top = Application.Top;
+			top.Add (label, view);
+			Application.Begin (top);
+
+			view.IncorrectRedraw (view.Bounds);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+At 0,0                       
+                             
+  A text with some long width
+   and also with two lines.  ", output);
+
+			view.X = 1;
+			view.Y = 1;
+			view.Width = 10;
+			view.Height = 1;
+			Assert.Equal (new Rect (1, 1, 10, 1), view.Frame);
+			Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds);
+			Assert.Equal (new Rect (1, 1, 31, 3), view.NeedDisplay);
+			view.IncorrectRedraw (view.Bounds);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+At 0,0                       
+ A text wit                  
+  A text with some long width
+   and also with two lines.  ", output);
+		}
 	}
 }