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.
Steven Kirk 8 years ago
parent
commit
4e719262c4

+ 1 - 31
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;

+ 10 - 11
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();

+ 13 - 12
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();
-            }
-        }
     }
 }
 

+ 43 - 1
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>

+ 1 - 2
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()
         {

+ 63 - 1
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 - 0
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 - 0
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 - 0
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());

+ 1 - 1
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 - 0
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(),