Browse Source

Merge pull request #2290 from BDisp/view-clear-fix_2289

Fixes #2289. View.Clear method is clearing beyond its parent bounds.
Tig 2 years ago
parent
commit
7605e2bc11
2 changed files with 80 additions and 7 deletions
  1. 21 7
      Terminal.Gui/Core/View.cs
  2. 59 0
      UnitTests/ViewTests.cs

+ 21 - 7
Terminal.Gui/Core/View.cs

@@ -1093,8 +1093,15 @@ namespace Terminal.Gui {
 		/// </remarks>
 		public void Clear ()
 		{
-			var h = Frame.Height;
-			var w = Frame.Width;
+			Rect containerBounds = GetContainerBounds ();
+			Rect viewBounds = Bounds;
+			if (!containerBounds.IsEmpty) {
+				viewBounds.Width = Math.Min (viewBounds.Width, containerBounds.Width);
+				viewBounds.Height = Math.Min (viewBounds.Height, containerBounds.Height);
+			}
+
+			var h = viewBounds.Height;
+			var w = viewBounds.Width;
 			for (var line = 0; line < h; line++) {
 				Move (0, line);
 				for (var col = 0; col < w; col++)
@@ -1511,11 +1518,7 @@ namespace Terminal.Gui {
 				if (TextFormatter != null) {
 					TextFormatter.NeedsFormat = true;
 				}
-				var containerBounds = SuperView == null ? default : SuperView.ViewToScreen (SuperView.Bounds);
-				containerBounds.X = Math.Max (containerBounds.X, Driver.Clip.X);
-				containerBounds.Y = Math.Max (containerBounds.Y, Driver.Clip.Y);
-				containerBounds.Width = Math.Min (containerBounds.Width, Driver.Clip.Width);
-				containerBounds.Height = Math.Min (containerBounds.Height, Driver.Clip.Height);
+				Rect containerBounds = GetContainerBounds ();
 				TextFormatter?.Draw (ViewToScreen (Bounds), HasFocus ? ColorScheme.Focus : GetNormalColor (),
 				    HasFocus ? ColorScheme.HotFocus : Enabled ? ColorScheme.HotNormal : ColorScheme.Disabled,
 				    containerBounds);
@@ -1558,6 +1561,17 @@ namespace Terminal.Gui {
 			ClearNeedsDisplay ();
 		}
 
+		Rect GetContainerBounds ()
+		{
+			var containerBounds = SuperView == null ? default : SuperView.ViewToScreen (SuperView.Bounds);
+			var driverClip = Driver == null ? Rect.Empty : Driver.Clip;
+			containerBounds.X = Math.Max (containerBounds.X, driverClip.X);
+			containerBounds.Y = Math.Max (containerBounds.Y, driverClip.Y);
+			containerBounds.Width = Math.Min (containerBounds.Width, driverClip.Width);
+			containerBounds.Height = Math.Min (containerBounds.Height, driverClip.Height);
+			return containerBounds;
+		}
+
 		/// <summary>
 		/// Event invoked when the content area of the View is to be drawn.
 		/// </summary>

+ 59 - 0
UnitTests/ViewTests.cs

@@ -4117,5 +4117,64 @@ This is a tes
 			view.Enabled = false;
 			Assert.Equal (view.ColorScheme.Disabled, view.GetHotNormalColor ());
 		}
+
+		[Theory, AutoInitShutdown]
+		[InlineData (true)]
+		[InlineData (false)]
+		public void Clear_Does_Not_Spillover_Its_Parent (bool label)
+		{
+			var root = new View () { Width = 20, Height = 10 };
+
+			var v = label == true ?
+				new Label (new string ('c', 100)) {
+					Width = Dim.Fill ()
+				} :
+				(View)new TextView () {
+					Height = 1,
+					Text = new string ('c', 100),
+					Width = Dim.Fill ()
+				};
+
+			root.Add (v);
+
+			Application.Top.Add (root);
+			Application.Begin (Application.Top);
+
+			if (label) {
+				Assert.True (v.AutoSize);
+				Assert.False (v.CanFocus);
+				Assert.Equal (new Rect (0, 0, 100, 1), v.Frame);
+			} else {
+				Assert.False (v.AutoSize);
+				Assert.True (v.CanFocus);
+				Assert.Equal (new Rect (0, 0, 20, 1), v.Frame);
+			}
+
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+cccccccccccccccccccc", output);
+
+			var attributes = new Attribute [] {
+				Colors.TopLevel.Normal,
+				Colors.TopLevel.Focus,
+
+			};
+			if (label) {
+				TestHelpers.AssertDriverColorsAre (@"
+000000000000000000000", attributes);
+			} else {
+				TestHelpers.AssertDriverColorsAre (@"
+111111111111111111110", attributes);
+			}
+
+			if (label) {
+				root.CanFocus = true;
+				v.CanFocus = true;
+				Assert.False (v.HasFocus);
+				v.SetFocus ();
+				Application.Refresh ();
+				TestHelpers.AssertDriverColorsAre (@"
+111111111111111111110", attributes);
+			}
+		}
 	}
 }