diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index c7104fcdb..8734261c0 100644 --- a/Terminal.Gui/Core/View.cs +++ b/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); diff --git a/UnitTests/Views/ViewTests.cs b/UnitTests/Views/ViewTests.cs index b1a22046c..404a4290c 100644 --- a/UnitTests/Views/ViewTests.cs +++ b/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); + } } }