Browse Source

Make WindowBase.IsVisible return correct value.

`WindowBase.IsVisible` now tracks the visibility of the window. Still
needs to call `Show` and `Hide` when changed.
pull/935/head
Steven Kirk 9 years ago
parent
commit
4e719262c4
  1. 32
      src/Avalonia.Controls/Primitives/PopupRoot.cs
  2. 21
      src/Avalonia.Controls/TopLevel.cs
  3. 25
      src/Avalonia.Controls/Window.cs
  4. 44
      src/Avalonia.Controls/WindowBase.cs
  5. 3
      tests/Avalonia.Controls.UnitTests/TopLevelTests.cs
  6. 64
      tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs
  7. 86
      tests/Avalonia.Controls.UnitTests/WindowTests.cs
  8. 2
      tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs
  9. 14
      tests/Avalonia.LeakTests/ControlTests.cs
  10. 2
      tests/Avalonia.UnitTests/MockWindowingPlatform.cs
  11. 3
      tests/Avalonia.UnitTests/TestServices.cs

32
src/Avalonia.Controls/Primitives/PopupRoot.cs

@ -70,32 +70,12 @@ namespace Avalonia.Controls.Primitives
this.PlatformImpl.Dispose();
}
/// <summary>
/// Hides the popup.
/// </summary>
public void Hide()
{
PlatformImpl.Hide();
IsVisible = false;
}
/// <summary>
/// Shows the popup.
/// </summary>
public void Show()
{
EnsureInitialized();
PlatformImpl.Show();
LayoutManager.Instance.ExecuteInitialLayoutPass(this);
IsVisible = true;
}
/// <inheritdoc/>
protected override void OnTemplateApplied(TemplateAppliedEventArgs e)
{
base.OnTemplateApplied(e);
if (Parent.TemplatedParent != null)
if (Parent?.TemplatedParent != null)
{
if (_presenterSubscription != null)
{
@ -109,16 +89,6 @@ namespace Avalonia.Controls.Primitives
}
}
private void EnsureInitialized()
{
if (!this.IsInitialized)
{
var init = (ISupportInitialize)this;
init.BeginInit();
init.EndInit();
}
}
private void SetTemplatedParentAndApplyChildTemplates(IControl control)
{
var templatedParent = Parent.TemplatedParent;

21
src/Avalonia.Controls/TopLevel.cs

@ -208,6 +208,16 @@ namespace Avalonia.Controls
return PlatformImpl.PointToScreen(p);
}
/// <summary>
/// Handles a closed notification from <see cref="ITopLevelImpl.Closed"/>.
/// </summary>
protected virtual void HandleClosed()
{
Closed?.Invoke(this, EventArgs.Empty);
Renderer?.Dispose();
Renderer = null;
_applicationLifecycle.OnExit -= OnApplicationExiting;
}
/// <summary>
/// Handles a resize notification from <see cref="ITopLevelImpl.Resized"/>.
@ -267,17 +277,6 @@ namespace Avalonia.Controls
return result;
}
/// <summary>
/// Handles a closed notification from <see cref="ITopLevelImpl.Closed"/>.
/// </summary>
private void HandleClosed()
{
Closed?.Invoke(this, EventArgs.Empty);
Renderer?.Dispose();
Renderer = null;
_applicationLifecycle.OnExit -= OnApplicationExiting;
}
private void OnApplicationExiting(object sender, EventArgs args)
{
HandleApplicationExiting();

25
src/Avalonia.Controls/Window.cs

@ -190,6 +190,7 @@ namespace Avalonia.Controls
{
s_windows.Remove(this);
PlatformImpl.Dispose();
IsVisible = false;
}
protected override void HandleApplicationExiting()
@ -216,22 +217,25 @@ namespace Avalonia.Controls
/// <summary>
/// Hides the window but does not close it.
/// </summary>
public void Hide()
public override void Hide()
{
using (BeginAutoSizing())
{
PlatformImpl.Hide();
}
IsVisible = false;
}
/// <summary>
/// Shows the window.
/// </summary>
public void Show()
public override void Show()
{
s_windows.Add(this);
EnsureInitialized();
IsVisible = true;
LayoutManager.Instance.ExecuteInitialLayoutPass(this);
using (BeginAutoSizing())
@ -265,6 +269,7 @@ namespace Avalonia.Controls
s_windows.Add(this);
EnsureInitialized();
IsVisible = true;
LayoutManager.Instance.ExecuteInitialLayoutPass(this);
using (BeginAutoSizing())
@ -344,6 +349,12 @@ namespace Avalonia.Controls
return size;
}
protected override void HandleClosed()
{
IsVisible = false;
base.HandleClosed();
}
/// <inheritdoc/>
protected override void HandleResized(Size clientSize)
{
@ -354,16 +365,6 @@ namespace Avalonia.Controls
base.HandleResized(clientSize);
}
private void EnsureInitialized()
{
if (!this.IsInitialized)
{
var init = (ISupportInitialize)this;
init.BeginInit();
init.EndInit();
}
}
}
}

44
src/Avalonia.Controls/WindowBase.cs

@ -30,6 +30,11 @@ namespace Avalonia.Controls
private bool _isActive;
static WindowBase()
{
IsVisibleProperty.OverrideDefaultValue<WindowBase>(false);
}
public WindowBase(IWindowBaseImpl impl) : this(impl, AvaloniaLocator.Current)
{
}
@ -59,7 +64,6 @@ namespace Avalonia.Controls
public new IWindowBaseImpl PlatformImpl => (IWindowBaseImpl) base.PlatformImpl;
/// <summary>
/// Gets a value that indicates whether the window is active.
/// </summary>
@ -95,6 +99,25 @@ namespace Avalonia.Controls
PlatformImpl.Activate();
}
/// <summary>
/// Hides the popup.
/// </summary>
public virtual void Hide()
{
PlatformImpl.Hide();
IsVisible = false;
}
/// <summary>
/// Shows the popup.
/// </summary>
public virtual void Show()
{
EnsureInitialized();
IsVisible = true;
LayoutManager.Instance.ExecuteInitialLayoutPass(this);
PlatformImpl.Show();
}
/// <summary>
/// Begins an auto-resize operation.
@ -126,6 +149,25 @@ namespace Avalonia.Controls
return base.ArrangeOverride(PlatformImpl.ClientSize);
}
/// <summary>
/// Ensures that the window is initialized.
/// </summary>
protected void EnsureInitialized()
{
if (!this.IsInitialized)
{
var init = (ISupportInitialize)this;
init.BeginInit();
init.EndInit();
}
}
protected override void HandleClosed()
{
IsVisible = false;
base.HandleClosed();
}
/// <summary>
/// Handles a resize notification from <see cref="ITopLevelImpl.Resized"/>.
/// </summary>

3
tests/Avalonia.Controls.UnitTests/TopLevelTests.cs

@ -89,6 +89,7 @@ namespace Avalonia.Controls.UnitTests
var target = new TestTopLevel(impl.Object)
{
IsVisible = true,
Template = CreateTemplate(),
Content = new TextBlock
{
@ -103,8 +104,6 @@ namespace Avalonia.Controls.UnitTests
}
}
[Fact]
public void Width_And_Height_Should_Not_Be_Set_After_Layout_Pass()
{

64
tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs

@ -34,7 +34,8 @@ namespace Avalonia.Controls.UnitTests
{
Width = 321,
Height = 432,
}
},
IsVisible = true,
};
LayoutManager.Instance.ExecuteInitialLayoutPass(target);
@ -95,6 +96,62 @@ namespace Avalonia.Controls.UnitTests
}
}
[Fact]
public void IsVisible_Should_Initially_Be_False()
{
using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
{
var target = new TestWindowBase();
Assert.False(target.IsVisible);
}
}
[Fact]
public void IsVisible_Should_Be_True_After_Show()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var target = new TestWindowBase();
target.Show();
Assert.True(target.IsVisible);
}
}
[Fact]
public void IsVisible_Should_Be_False_Atfer_Hide()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var target = new TestWindowBase();
target.Show();
target.Hide();
Assert.False(target.IsVisible);
}
}
[Fact]
public void IsVisible_Should_Be_False_Atfer_Impl_Signals_Close()
{
var windowImpl = new Mock<IPopupImpl>();
windowImpl.Setup(x => x.Scaling).Returns(1);
windowImpl.SetupProperty(x => x.Closed);
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var target = new TestWindowBase(windowImpl.Object);
target.Show();
windowImpl.Object.Closed();
Assert.False(target.IsVisible);
}
}
private FuncControlTemplate<TestWindowBase> CreateTemplate()
{
return new FuncControlTemplate<TestWindowBase>(x =>
@ -109,6 +166,11 @@ namespace Avalonia.Controls.UnitTests
{
public bool IsClosed { get; private set; }
public TestWindowBase()
: base(Mock.Of<IWindowBaseImpl>())
{
}
public TestWindowBase(IWindowBaseImpl impl)
: base(impl)
{

86
tests/Avalonia.Controls.UnitTests/WindowTests.cs

@ -28,5 +28,91 @@ namespace Avalonia.Controls.UnitTests
windowImpl.Verify(x => x.SetTitle("Hello World"));
}
}
[Fact]
public void IsVisible_Should_Initially_Be_False()
{
using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
{
var window = new Window();
Assert.False(window.IsVisible);
}
}
[Fact]
public void IsVisible_Should_Be_True_After_Show()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var window = new Window();
window.Show();
Assert.True(window.IsVisible);
}
}
[Fact]
public void IsVisible_Should_Be_True_After_ShowDialog()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var window = new Window();
var task = window.ShowDialog();
Assert.True(window.IsVisible);
}
}
[Fact]
public void IsVisible_Should_Be_False_Atfer_Hide()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var window = new Window();
window.Show();
window.Hide();
Assert.False(window.IsVisible);
}
}
[Fact]
public void IsVisible_Should_Be_False_Atfer_Close()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var window = new Window();
window.Show();
window.Close();
Assert.False(window.IsVisible);
}
}
[Fact]
public void IsVisible_Should_Be_False_Atfer_Impl_Signals_Close()
{
var windowImpl = new Mock<IWindowImpl>();
windowImpl.SetupProperty(x => x.Closed);
windowImpl.Setup(x => x.Scaling).Returns(1);
var services = TestServices.StyledWindow.With(
windowingPlatform: new MockWindowingPlatform(() => windowImpl.Object));
using (UnitTestApplication.Start(services))
{
var window = new Window();
window.Show();
windowImpl.Object.Closed();
Assert.False(window.IsVisible);
}
}
}
}

2
tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs

@ -55,6 +55,7 @@ namespace Avalonia.Layout.UnitTests
}
};
window.Show();
LayoutManager.Instance.ExecuteInitialLayoutPass(window);
Assert.Equal(new Size(400, 400), border.Bounds.Size);
@ -96,6 +97,7 @@ namespace Avalonia.Layout.UnitTests
}
};
window.Show();
LayoutManager.Instance.ExecuteInitialLayoutPass(window);
Assert.Equal(new Size(800, 600), window.Bounds.Size);

14
tests/Avalonia.LeakTests/ControlTests.cs

@ -42,6 +42,8 @@ namespace Avalonia.LeakTests
Content = new Canvas()
};
window.Show();
// Do a layout and make sure that Canvas gets added to visual tree.
LayoutManager.Instance.ExecuteInitialLayoutPass(window);
Assert.IsType<Canvas>(window.Presenter.Child);
@ -77,6 +79,8 @@ namespace Avalonia.LeakTests
}
};
window.Show();
// Do a layout and make sure that Canvas gets added to visual tree.
LayoutManager.Instance.ExecuteInitialLayoutPass(window);
Assert.IsType<Canvas>(window.Find<Canvas>("foo"));
@ -113,6 +117,8 @@ namespace Avalonia.LeakTests
}
};
window.Show();
// Do a layout and make sure that ScrollViewer gets added to visual tree and its
// template applied.
LayoutManager.Instance.ExecuteInitialLayoutPass(window);
@ -149,6 +155,8 @@ namespace Avalonia.LeakTests
Content = new TextBox()
};
window.Show();
// Do a layout and make sure that TextBox gets added to visual tree and its
// template applied.
LayoutManager.Instance.ExecuteInitialLayoutPass(window);
@ -192,6 +200,8 @@ namespace Avalonia.LeakTests
var textBox = (TextBox)window.Content;
textBox.Bind(TextBox.TextProperty, binding);
window.Show();
// Do a layout and make sure that TextBox gets added to visual tree and its
// Text property set.
LayoutManager.Instance.ExecuteInitialLayoutPass(window);
@ -229,6 +239,8 @@ namespace Avalonia.LeakTests
Content = textBox = new TextBox()
};
window.Show();
// Do a layout and make sure that TextBox gets added to visual tree and its
// template applied.
LayoutManager.Instance.ExecuteInitialLayoutPass(window);
@ -282,6 +294,8 @@ namespace Avalonia.LeakTests
}
};
window.Show();
// Do a layout and make sure that TreeViewItems get realized.
LayoutManager.Instance.ExecuteInitialLayoutPass(window);
Assert.Equal(1, target.ItemContainerGenerator.Containers.Count());

2
tests/Avalonia.UnitTests/MockWindowingPlatform.cs

@ -25,6 +25,6 @@ namespace Avalonia.UnitTests
throw new NotImplementedException();
}
public IPopupImpl CreatePopup() => _popupImpl?.Invoke() ?? Mock.Of<IPopupImpl>();
public IPopupImpl CreatePopup() => _popupImpl?.Invoke() ?? Mock.Of<IPopupImpl>(x => x.Scaling == 1);
}
}

3
tests/Avalonia.UnitTests/TestServices.cs

@ -43,6 +43,9 @@ namespace Avalonia.UnitTests
public static readonly TestServices MockThreadingInterface = new TestServices(
threadingInterface: Mock.Of<IPlatformThreadingInterface>(x => x.CurrentThreadIsLoopThread == true));
public static readonly TestServices MockWindowingPlatform = new TestServices(
windowingPlatform: new MockWindowingPlatform());
public static readonly TestServices RealFocus = new TestServices(
focusManager: new FocusManager(),
keyboardDevice: () => new KeyboardDevice(),

Loading…
Cancel
Save