diff --git a/Terminal.Gui/View/View.Content.cs b/Terminal.Gui/View/View.Content.cs
index d1bfafc79..968558ca6 100644
--- a/Terminal.Gui/View/View.Content.cs
+++ b/Terminal.Gui/View/View.Content.cs
@@ -313,7 +313,7 @@ public partial class View
//SetSubViewNeedsDraw();
}
- OnViewportChanged (new (IsInitialized ? Viewport : Rectangle.Empty, oldViewport));
+ RaiseViewportChangedEvent (oldViewport);
return;
}
@@ -326,7 +326,7 @@ public partial class View
Size = newSize
};
- OnViewportChanged (new (IsInitialized ? Viewport : Rectangle.Empty, oldViewport));
+ // Note, setting the Frame will cause ViewportChanged to be raised.
return;
@@ -368,6 +368,13 @@ public partial class View
}
}
+ private void RaiseViewportChangedEvent (Rectangle oldViewport)
+ {
+ var args = new DrawEventArgs (IsInitialized ? Viewport : Rectangle.Empty, oldViewport);
+ OnViewportChanged (args);
+ ViewportChanged?.Invoke (this, args);
+ }
+
///
/// Fired when the changes. This event is fired after the has been
/// updated.
@@ -378,7 +385,7 @@ public partial class View
/// Called when the changes. Invokes the event.
///
///
- protected virtual void OnViewportChanged (DrawEventArgs e) { ViewportChanged?.Invoke (this, e); }
+ protected virtual void OnViewportChanged (DrawEventArgs e) { }
///
/// Converts a -relative location and size to a screen-relative location and size.
diff --git a/Terminal.Gui/View/View.Layout.cs b/Terminal.Gui/View/View.Layout.cs
index 67e18955e..1b37f9725 100644
--- a/Terminal.Gui/View/View.Layout.cs
+++ b/Terminal.Gui/View/View.Layout.cs
@@ -98,6 +98,11 @@ public partial class View // Layout APIs
// BUGBUG: When SetFrame is called from Frame_set, this event gets raised BEFORE OnResizeNeeded. Is that OK?
OnFrameChanged (in frame);
FrameChanged?.Invoke (this, new (in frame));
+
+ if (oldViewport != Viewport)
+ {
+ RaiseViewportChangedEvent (oldViewport);
+ }
return true;
}
diff --git a/UnitTests/View/Layout/FrameTests.cs b/UnitTests/View/Layout/FrameTests.cs
index 173409a0f..cc9ba8608 100644
--- a/UnitTests/View/Layout/FrameTests.cs
+++ b/UnitTests/View/Layout/FrameTests.cs
@@ -259,4 +259,55 @@ public class FrameTests (ITestOutputHelper output)
Assert.Equal (Dim.Absolute (40), v.Height);
v.Dispose ();
}
+
+ private class TestFrameEventsView : View
+ {
+ public int OnFrameChangedCallCount { get; private set; }
+ public int FrameChangedEventCallCount { get; private set; }
+
+ public TestFrameEventsView ()
+ {
+ FrameChanged += (sender, args) => FrameChangedEventCallCount++;
+ }
+
+ protected override void OnFrameChanged (in Rectangle frame)
+ {
+ OnFrameChangedCallCount++;
+ base.OnFrameChanged (frame);
+ }
+ }
+
+ [Fact]
+ public void OnFrameChanged_Called_When_Frame_Changes ()
+ {
+ // Arrange
+ var view = new TestFrameEventsView ();
+ var initialFrame = new Rectangle (0, 0, 10, 10);
+ var newFrame = new Rectangle (0, 0, 20, 20);
+ view.Frame = initialFrame;
+ Assert.Equal (1, view.OnFrameChangedCallCount);
+
+ // Act
+ view.Frame = newFrame;
+
+ // Assert
+ Assert.Equal (2, view.OnFrameChangedCallCount);
+ }
+
+ [Fact]
+ public void FrameChanged_Event_Raised_When_Frame_Changes ()
+ {
+ // Arrange
+ var view = new TestFrameEventsView ();
+ var initialFrame = new Rectangle (0, 0, 10, 10);
+ var newFrame = new Rectangle (0, 0, 20, 20);
+ view.Frame = initialFrame;
+ Assert.Equal (1, view.FrameChangedEventCallCount);
+
+ // Act
+ view.Frame = newFrame;
+
+ // Assert
+ Assert.Equal (2, view.FrameChangedEventCallCount);
+ }
}
diff --git a/UnitTests/View/Layout/ViewportTests.cs b/UnitTests/View/Layout/ViewportTests.cs
index c210d8215..f6ab2d394 100644
--- a/UnitTests/View/Layout/ViewportTests.cs
+++ b/UnitTests/View/Layout/ViewportTests.cs
@@ -387,6 +387,93 @@ public class ViewportTests (ITestOutputHelper output)
Assert.NotEqual (view.Viewport.Size, view.GetContentSize ());
}
+ private class TestViewportEventsView : View
+ {
+ public int OnViewportChangedCallCount { get; private set; }
+ public int ViewportChangedEventCallCount { get; private set; }
+
+ public TestViewportEventsView ()
+ {
+ ViewportChanged += (sender, args) => ViewportChangedEventCallCount++;
+ }
+
+ protected override void OnViewportChanged (DrawEventArgs e)
+ {
+ OnViewportChangedCallCount++;
+ base.OnViewportChanged (e);
+ }
+ }
+
+ [Fact]
+ public void OnViewportChanged_Called_When_Viewport_Changes ()
+ {
+ // Arrange
+ var view = new TestViewportEventsView ();
+ var initialViewport = new Rectangle (0, 0, 10, 10);
+ var newViewport = new Rectangle (0, 0, 20, 20);
+ Assert.Equal (0, view.OnViewportChangedCallCount);
+ view.Viewport = initialViewport;
+ Assert.Equal (1, view.OnViewportChangedCallCount);
+
+ // Act
+ view.Viewport = newViewport;
+
+ // Assert
+ Assert.Equal (2, view.OnViewportChangedCallCount);
+ }
+
+ [Fact]
+ public void ViewportChanged_Event_Raised_When_Viewport_Changes ()
+ {
+ // Arrange
+ var view = new TestViewportEventsView ();
+ var initialViewport = new Rectangle (0, 0, 10, 10);
+ var newViewport = new Rectangle (0, 0, 20, 20);
+ view.Viewport = initialViewport;
+ Assert.Equal (1, view.ViewportChangedEventCallCount);
+
+ // Act
+ view.Viewport = newViewport;
+
+ // Assert
+ Assert.Equal (2, view.ViewportChangedEventCallCount);
+ }
+
+ [Fact]
+ public void OnViewportChanged_Called_When_Frame_Changes ()
+ {
+ // Arrange
+ var view = new TestViewportEventsView ();
+ var initialFrame = new Rectangle (0, 0, 10, 10);
+ var newFrame = new Rectangle (0, 0, 20, 20);
+ Assert.Equal (0, view.OnViewportChangedCallCount);
+ view.Frame = initialFrame;
+ Assert.Equal (1, view.OnViewportChangedCallCount);
+
+ // Act
+ view.Frame = newFrame;
+
+ // Assert
+ Assert.Equal (2, view.OnViewportChangedCallCount);
+ }
+
+ [Fact]
+ public void ViewportChanged_Event_Raised_When_Frame_Changes ()
+ {
+ // Arrange
+ var view = new TestViewportEventsView ();
+ var initialFrame = new Rectangle (0, 0, 10, 10);
+ var newFrame = new Rectangle (0, 0, 20, 20);
+ view.Frame = initialFrame;
+ Assert.Equal (1, view.ViewportChangedEventCallCount);
+
+ // Act
+ view.Frame = newFrame;
+
+ // Assert
+ Assert.Equal (2, view.ViewportChangedEventCallCount);
+ }
+
//[Theory]
//[InlineData (0, 0, true)]
//[InlineData (-1, 0, true)]