Merge pull request #771 from BDisp/Initialized-event

Added support for ISupportInitializeNotification interface.
This commit is contained in:
Charlie Kindel
2020-07-12 11:23:52 -06:00
committed by GitHub
2 changed files with 225 additions and 2 deletions

View File

@@ -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 <see cref="LayoutStyle.Computed"/>.
/// </para>
/// </remarks>
public partial class View : Responder, IEnumerable {
public partial class View : Responder, IEnumerable, ISupportInitializeNotification {
internal enum Direction {
Forward,
@@ -665,9 +666,11 @@ namespace Terminal.Gui {
CanFocus = true;
view.tabIndex = tabIndexes.IndexOf (view);
}
SetNeedsLayout ();
SetNeedsDisplay ();
if (IsInitialized) {
view.BeginInit ();
}
}
/// <summary>
@@ -1653,6 +1656,13 @@ namespace Terminal.Gui {
/// </remarks>
public Action<LayoutEventArgs> LayoutComplete;
/// <summary>
/// Event called only once when the <see cref="View"/> is being initialized for the first time.
/// Allows configurations and assignments to be performed before the <see cref="View"/> being shown.
/// This derived from <see cref="ISupportInitializeNotification"/> to allow notify all the views that are being initialized.
/// </summary>
public event EventHandler Initialized;
/// <summary>
/// Raises the <see cref="LayoutComplete"/> event. Called from <see cref="LayoutSubviews"/> before all sub-views have been laid out.
/// </summary>
@@ -1757,6 +1767,12 @@ namespace Terminal.Gui {
}
}
/// <summary>
/// Get or sets if the <see cref="View"/> was already initialized.
/// This derived from <see cref="ISupportInitializeNotification"/> to allow notify all the views that are being initialized.
/// </summary>
public bool IsInitialized { get; set; }
/// <summary>
/// Pretty prints the View
/// </summary>
@@ -1848,5 +1864,37 @@ namespace Terminal.Gui {
}
base.Dispose (disposing);
}
/// <summary>
/// This derived from <see cref="ISupportInitializeNotification"/> to allow notify all the views that are beginning initialized.
/// </summary>
public void BeginInit ()
{
if (!IsInitialized) {
Initialized?.Invoke (this, new EventArgs ());
}
if (subviews?.Count > 0) {
foreach (var view in subviews) {
if (!view.IsInitialized) {
view.BeginInit ();
}
}
}
}
/// <summary>
/// This derived from <see cref="ISupportInitializeNotification"/> to allow notify all the views that are ending initialized.
/// </summary>
public void EndInit ()
{
IsInitialized = true;
if (subviews?.Count > 0) {
foreach (var view in subviews) {
if (!view.IsInitialized) {
view.EndInit ();
}
}
}
}
}
}

View File

@@ -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);
}
}
}