diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs
index 4ad5e6081..c62225228 100644
--- a/Terminal.Gui/Core/View.cs
+++ b/Terminal.Gui/Core/View.cs
@@ -13,6 +13,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using NStack;
@@ -110,7 +111,7 @@ namespace Terminal.Gui {
/// frames for the vies that use .
///
///
- public partial class View : Responder, IEnumerable {
+ public partial class View : Responder, IEnumerable, ISupportInitializeNotification {
internal enum Direction {
Forward,
@@ -665,7 +666,9 @@ namespace Terminal.Gui {
CanFocus = true;
view.tabIndex = tabIndexes.IndexOf (view);
}
-
+ if (IsInitialized) {
+ view.BeginInit ();
+ }
SetNeedsLayout ();
SetNeedsDisplay ();
}
@@ -1653,6 +1656,13 @@ namespace Terminal.Gui {
///
public Action LayoutComplete;
+ ///
+ /// Event called only once when the is being initialized for the first time.
+ /// Allows configurations and assignments to be performed before the being shown.
+ /// This derived from to allow notify all the views that are being initialized.
+ ///
+ public event EventHandler Initialized;
+
///
/// Raises the event. Called from before all sub-views have been laid out.
///
@@ -1757,6 +1767,12 @@ namespace Terminal.Gui {
}
}
+ ///
+ /// Get or sets if the was already initialized.
+ /// This derived from to allow notify all the views that are being initialized.
+ ///
+ public bool IsInitialized { get; set; }
+
///
/// Pretty prints the View
///
@@ -1848,5 +1864,37 @@ namespace Terminal.Gui {
}
base.Dispose (disposing);
}
+
+ ///
+ /// This derived from to allow notify all the views that are beginning initialized.
+ ///
+ public void BeginInit ()
+ {
+ if (!IsInitialized) {
+ Initialized?.Invoke (this, new EventArgs ());
+ }
+ if (subviews?.Count > 0) {
+ foreach (var view in subviews) {
+ if (!view.IsInitialized) {
+ view.BeginInit ();
+ }
+ }
+ }
+ }
+
+ ///
+ /// This derived from to allow notify all the views that are ending initialized.
+ ///
+ public void EndInit ()
+ {
+ IsInitialized = true;
+ if (subviews?.Count > 0) {
+ foreach (var view in subviews) {
+ if (!view.IsInitialized) {
+ view.EndInit ();
+ }
+ }
+ }
+ }
}
}
diff --git a/UnitTests/ViewTests.cs b/UnitTests/ViewTests.cs
index 3bceac0fb..fec7fd00f 100644
--- a/UnitTests/ViewTests.cs
+++ b/UnitTests/ViewTests.cs
@@ -543,5 +543,180 @@ namespace Terminal.Gui {
Assert.Equal (2, v3.TabIndex);
Assert.True (v3.TabStop);
}
+
+ [Fact]
+ public void Initialized_Event_Comparing_With_Added_Event ()
+ {
+ Application.Init (new FakeDriver (), new NetMainLoop (() => FakeConsole.ReadKey (true)));
+
+ var t = new Toplevel () { Id = "0", };
+
+ var w = new Window () {Id = "t", Width = Dim.Fill (), Height = Dim.Fill () };
+ var v1 = new View () { Id = "v1", Width = Dim.Fill (), Height = Dim.Fill () };
+ var v2 = new View () { Id = "v2", Width = Dim.Fill (), Height = Dim.Fill () };
+ var sv1 = new View () { Id = "sv1", Width = Dim.Fill (), Height = Dim.Fill () };
+
+ int tc = 0, wc = 0, v1c = 0, v2c = 0, sv1c = 0;
+
+ w.Added += (e) => {
+ Assert.Equal (e.Frame.Width, w.Frame.Width);
+ Assert.Equal (e.Frame.Height, w.Frame.Height);
+ };
+ v1.Added += (e) => {
+ Assert.Equal (e.Frame.Width, v1.Frame.Width);
+ Assert.Equal (e.Frame.Height, v1.Frame.Height);
+ };
+ v2.Added += (e) => {
+ Assert.Equal (e.Frame.Width, v2.Frame.Width);
+ Assert.Equal (e.Frame.Height, v2.Frame.Height);
+ };
+ sv1.Added += (e) => {
+ Assert.Equal (e.Frame.Width, sv1.Frame.Width);
+ Assert.Equal (e.Frame.Height, sv1.Frame.Height);
+ };
+
+ t.Initialized += (s, e) => {
+ tc++;
+ Assert.Equal (1, tc);
+ Assert.Equal (0, wc);
+ Assert.Equal (0, v1c);
+ Assert.Equal (0, v2c);
+ Assert.Equal (0, sv1c);
+
+ Assert.True (t.CanFocus);
+ Assert.True (w.CanFocus);
+ Assert.False (v1.CanFocus);
+ Assert.False (v2.CanFocus);
+ Assert.False (sv1.CanFocus);
+
+ Application.Refresh ();
+ };
+ w.Initialized += (s, e) => {
+ wc++;
+ Assert.Equal (t.Frame.Width, w.Frame.Width);
+ Assert.Equal (t.Frame.Height, w.Frame.Height);
+ };
+ v1.Initialized += (s, e) => {
+ v1c++;
+ Assert.Equal (t.Frame.Width, v1.Frame.Width);
+ Assert.Equal (t.Frame.Height, v1.Frame.Height);
+ };
+ v2.Initialized += (s, e) => {
+ v2c++;
+ Assert.Equal (t.Frame.Width, v2.Frame.Width);
+ Assert.Equal (t.Frame.Height, v2.Frame.Height);
+ };
+ sv1.Initialized += (s, e) => {
+ sv1c++;
+ Assert.Equal (t.Frame.Width, sv1.Frame.Width);
+ Assert.Equal (t.Frame.Height, sv1.Frame.Height);
+ Assert.False (sv1.CanFocus);
+ sv1.CanFocus = true;
+ Assert.True (sv1.CanFocus);
+ };
+
+ v1.Add (sv1);
+ w.Add (v1, v2);
+ t.Add (w);
+
+ Application.Iteration = () => {
+ Application.Refresh ();
+ t.Running = false;
+ };
+
+ Application.Run (t, true);
+ Application.Shutdown (true);
+
+ Assert.Equal (1, tc);
+ Assert.Equal (1, wc);
+ Assert.Equal (1, v1c);
+ Assert.Equal (1, v2c);
+ Assert.Equal (1, sv1c);
+
+ Assert.True (t.CanFocus);
+ Assert.True (w.CanFocus);
+ Assert.False (v1.CanFocus);
+ Assert.False (v2.CanFocus);
+ Assert.True (sv1.CanFocus);
+ }
+
+ [Fact]
+ public void Initialized_Event_Will_Be_Invoked_When_Added_Dynamically ()
+ {
+ Application.Init (new FakeDriver (), new NetMainLoop (() => FakeConsole.ReadKey (true)));
+
+ var t = new Toplevel () { Id = "0", };
+
+ var w = new Window () { Id = "t", Width = Dim.Fill (), Height = Dim.Fill () };
+ var v1 = new View () { Id = "v1", Width = Dim.Fill (), Height = Dim.Fill () };
+ var v2 = new View () { Id = "v2", Width = Dim.Fill (), Height = Dim.Fill () };
+
+ int tc = 0, wc = 0, v1c = 0, v2c = 0, sv1c = 0;
+
+ t.Initialized += (s, e) => {
+ tc++;
+ Assert.Equal (1, tc);
+ Assert.Equal (0, wc);
+ Assert.Equal (0, v1c);
+ Assert.Equal (0, v2c);
+ Assert.Equal (0, sv1c);
+
+ Assert.True (t.CanFocus);
+ Assert.True (w.CanFocus);
+ Assert.False (v1.CanFocus);
+ Assert.False (v2.CanFocus);
+
+ Application.Refresh ();
+ };
+ w.Initialized += (s, e) => {
+ wc++;
+ Assert.Equal (t.Frame.Width, w.Frame.Width);
+ Assert.Equal (t.Frame.Height, w.Frame.Height);
+ };
+ v1.Initialized += (s, e) => {
+ v1c++;
+ Assert.Equal (t.Frame.Width, v1.Frame.Width);
+ Assert.Equal (t.Frame.Height, v1.Frame.Height);
+ };
+ v2.Initialized += (s, e) => {
+ v2c++;
+ Assert.Equal (t.Frame.Width, v2.Frame.Width);
+ Assert.Equal (t.Frame.Height, v2.Frame.Height);
+ };
+ w.Add (v1, v2);
+ t.Add (w);
+
+ Application.Iteration = () => {
+ var sv1 = new View () { Id = "sv1", Width = Dim.Fill (), Height = Dim.Fill () };
+
+ sv1.Initialized += (s, e) => {
+ sv1c++;
+ Assert.NotEqual (t.Frame.Width, sv1.Frame.Width);
+ Assert.NotEqual (t.Frame.Height, sv1.Frame.Height);
+ Assert.False (sv1.CanFocus);
+ sv1.CanFocus = true;
+ Assert.True (sv1.CanFocus);
+ };
+
+ v1.Add (sv1);
+
+ Application.Refresh ();
+ t.Running = false;
+ };
+
+ Application.Run (t, true);
+ Application.Shutdown (true);
+
+ Assert.Equal (1, tc);
+ Assert.Equal (1, wc);
+ Assert.Equal (1, v1c);
+ Assert.Equal (1, v2c);
+ Assert.Equal (1, sv1c);
+
+ Assert.True (t.CanFocus);
+ Assert.True (w.CanFocus);
+ Assert.False (v1.CanFocus);
+ Assert.False (v2.CanFocus);
+ }
}
}