From 14f20e81dd60cf21f324053f9ca41b910ef5dbf0 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 25 Aug 2015 21:57:42 +0200 Subject: [PATCH] Implemented Window.SizeToContent. --- Perspex.Controls/TopLevel.cs | 54 +++++++------- Perspex.Controls/Window.cs | 139 ++++++++++++++++++++++++++++++++++- TestApplication/Program.cs | 1 + 3 files changed, 168 insertions(+), 26 deletions(-) diff --git a/Perspex.Controls/TopLevel.cs b/Perspex.Controls/TopLevel.cs index 04cfecdf2c..c3d87d146b 100644 --- a/Perspex.Controls/TopLevel.cs +++ b/Perspex.Controls/TopLevel.cs @@ -71,11 +71,6 @@ namespace Perspex.Controls /// private IKeyboardNavigationHandler keyboardNavigationHandler; - /// - /// Whether an auto-size operation is in progress. - /// - private bool autoSizing; - /// /// Initializes static members of the class. /// @@ -254,6 +249,15 @@ namespace Perspex.Controls set { this.SetValue(AccessText.ShowAccessKeyProperty, value); } } + /// + /// Whether an auto-size operation is in progress. + /// + protected bool AutoSizing + { + get; + private set; + } + /// /// Translates a point from window coordinates into screen coordinates. /// @@ -283,8 +287,8 @@ namespace Perspex.Controls /// protected IDisposable BeginAutoSizing() { - this.autoSizing = true; - return Disposable.Create(() => this.autoSizing = false); + this.AutoSizing = true; + return Disposable.Create(() => this.AutoSizing = false); } /// @@ -302,6 +306,24 @@ namespace Perspex.Controls return base.ArrangeOverride(this.PlatformImpl.ClientSize); } + /// + /// Handles a resize notification from . + /// + /// The new client size. + protected virtual void HandleResized(Size clientSize) + { + if (!this.AutoSizing) + { + this.Width = clientSize.Width; + this.Height = clientSize.Height; + } + + this.ClientSize = clientSize; + this.renderer.Resize((int)clientSize.Width, (int)clientSize.Height); + this.LayoutManager.ExecuteLayoutPass(); + this.PlatformImpl.Invalidate(new Rect(clientSize)); + } + /// /// Tries to get a service from an , throwing an /// exception if not found. @@ -412,23 +434,5 @@ namespace Perspex.Controls this.renderer.Render(this, handle); this.renderManager.RenderFinished(); } - - /// - /// Handles a resize notification from . - /// - /// The new client size. - private void HandleResized(Size clientSize) - { - if (!this.autoSizing) - { - this.Width = clientSize.Width; - this.Height = clientSize.Height; - } - - this.ClientSize = clientSize; - this.renderer.Resize((int)clientSize.Width, (int)clientSize.Height); - this.LayoutManager.ExecuteLayoutPass(); - this.PlatformImpl.Invalidate(new Rect(clientSize)); - } } } diff --git a/Perspex.Controls/Window.cs b/Perspex.Controls/Window.cs index 26ab6966f5..2538c6c1a4 100644 --- a/Perspex.Controls/Window.cs +++ b/Perspex.Controls/Window.cs @@ -15,50 +15,125 @@ namespace Perspex.Controls using Perspex.Styling; using Splat; + /// + /// Determines how a will size itself to fit its content. + /// + public enum SizeToContent + { + /// + /// The window will not automatically size itself to fit its content. + /// + Manual, + + /// + /// The window will size itself horizontally to fit its content. + /// + Width, + + /// + /// The window will size itself vertically to fit its content. + /// + Height, + + /// + /// The window will size itself horizontally and vertically to fit its content. + /// + WidthAndHeight, + } + + /// + /// A top-level window. + /// public class Window : TopLevel, IStyleable, IFocusScope { + /// + /// Defines the property. + /// + public static readonly PerspexProperty SizeToContentProperty = + PerspexProperty.Register(nameof(SizeToContent)); + + /// + /// Defines the property. + /// public static readonly PerspexProperty TitleProperty = - PerspexProperty.Register("Title", "Window"); + PerspexProperty.Register(nameof(Title), "Window"); private object dialogResult; + /// + /// Initializes static members of the class. + /// static Window() { BackgroundProperty.OverrideDefaultValue(typeof(Window), Brushes.White); } + /// + /// Initializes a new instance of the class. + /// public Window() : base(Locator.Current.GetService()) { } + /// + /// Gets the platform-specific window implementation. + /// public new IWindowImpl PlatformImpl { get { return (IWindowImpl)base.PlatformImpl; } } + /// + /// Gets or sets a value indicating how the window will size itself to fit its content. + /// + public SizeToContent SizeToContent + { + get { return this.GetValue(SizeToContentProperty); } + set { this.SetValue(SizeToContentProperty, value); } + } + + /// + /// Gets or sets the title of the window. + /// public string Title { get { return this.GetValue(TitleProperty); } set { this.SetValue(TitleProperty, value); } } + /// Type IStyleable.StyleKey { get { return typeof(Window); } } + /// + /// Closes the window. + /// public void Close() { this.PlatformImpl.Dispose(); } + /// + /// Closes a dialog window with the specified result. + /// + /// The dialog result. + /// + /// When the window is shown with the method, the + /// resulting task will produce the value when the window + /// is closed. + /// public void Close(object dialogResult) { this.dialogResult = dialogResult; this.Close(); } + /// + /// Hides the window but does not close it. + /// public void Hide() { using (this.BeginAutoSizing()) @@ -67,6 +142,9 @@ namespace Perspex.Controls } } + /// + /// Shows the window. + /// public void Show() { this.LayoutManager.ExecuteLayoutPass(); @@ -77,11 +155,26 @@ namespace Perspex.Controls } } + /// + /// Shows the window as a dialog. + /// + /// + /// A task that can be used to track the lifetime of the dialog. + /// public Task ShowDialog() { return this.ShowDialog(); } + /// + /// Shows the window as a dialog. + /// + /// + /// The type of the result produced by the dialog. + /// + /// . + /// A task that can be used to retrive the result of the dialog when it closes. + /// public Task ShowDialog() { this.LayoutManager.ExecuteLayoutPass(); @@ -102,5 +195,49 @@ namespace Perspex.Controls return result.Task; } } + + /// + protected override Size ArrangeOverride(Size finalSize) + { + var sizeToContent = this.SizeToContent; + + if (sizeToContent != SizeToContent.Manual) + { + Size size; + + switch (sizeToContent) + { + case SizeToContent.Width: + size = new Size(finalSize.Width, this.ClientSize.Height); + break; + case SizeToContent.Height: + size = new Size(this.ClientSize.Width, finalSize.Height); + break; + case SizeToContent.WidthAndHeight: + size = new Size(finalSize.Width, finalSize.Height); + break; + default: + throw new InvalidOperationException("Invalid value for SizeToContent."); + } + + using (this.BeginAutoSizing()) + { + this.PlatformImpl.ClientSize = size; + } + } + + return base.ArrangeOverride(this.PlatformImpl.ClientSize); + } + + /// + protected override void HandleResized(Size clientSize) + { + if (!this.AutoSizing) + { + this.SizeToContent = SizeToContent.Manual; + } + + base.HandleResized(clientSize); + } } } diff --git a/TestApplication/Program.cs b/TestApplication/Program.cs index c58618bf60..9eceafc90f 100644 --- a/TestApplication/Program.cs +++ b/TestApplication/Program.cs @@ -118,6 +118,7 @@ namespace TestApplication Window window = new Window { Title = "Perspex Test Application", + SizeToContent = SizeToContent.WidthAndHeight, Content = new Grid { ColumnDefinitions = new ColumnDefinitions