From bbe460c18fc8ed09001ef502a36569c510871a5b Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 1 Mar 2016 18:09:01 -0600 Subject: [PATCH] Added interface and implementation for application exiting. Will automatically close all windows when called. --- src/Perspex.Application/Application.cs | 31 +++++++++++++++++-- src/Perspex.Controls/IApplicationLifecycle.cs | 24 ++++++++++++++ src/Perspex.Controls/Perspex.Controls.csproj | 1 + src/Perspex.Controls/TopLevel.cs | 17 ++++++++++ src/Perspex.Controls/Window.cs | 6 ++++ 5 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 src/Perspex.Controls/IApplicationLifecycle.cs diff --git a/src/Perspex.Application/Application.cs b/src/Perspex.Application/Application.cs index e904207b18..817253a3c9 100644 --- a/src/Perspex.Application/Application.cs +++ b/src/Perspex.Application/Application.cs @@ -32,7 +32,7 @@ namespace Perspex /// method. /// - Tracks the lifetime of the application. /// - public class Application : IGlobalDataTemplates, IGlobalStyles, IStyleRoot + public class Application : IGlobalDataTemplates, IGlobalStyles, IStyleRoot, IApplicationLifecycle { static Action _platformInitializationCallback; @@ -60,6 +60,7 @@ namespace Perspex } PerspexLocator.CurrentMutable.BindToSelf(this); + OnExit += OnExiting; } /// @@ -146,10 +147,35 @@ namespace Perspex public void Run(ICloseable closable) { var source = new CancellationTokenSource(); + closable.Closed += OnExiting; closable.Closed += (s, e) => source.Cancel(); Dispatcher.UIThread.MainLoop(source.Token); } + /// + /// Exits the application + /// + public void Exit() + { + OnExit?.Invoke(this, EventArgs.Empty); + } + + /// + /// Sent when the application is exiting. + /// + public event EventHandler OnExit; + + + /// + /// Called when the application is exiting. + /// + /// + /// + protected virtual void OnExiting(object sender, EventArgs e) + { + + } + /// /// Register's the services needed by Perspex. /// @@ -168,7 +194,8 @@ namespace Perspex .Bind().ToTransient() .Bind().ToConstant(_styler) .Bind().ToTransient() - .Bind().ToTransient(); + .Bind().ToTransient() + .Bind().ToConstant(this); } /// diff --git a/src/Perspex.Controls/IApplicationLifecycle.cs b/src/Perspex.Controls/IApplicationLifecycle.cs new file mode 100644 index 0000000000..38487bb9fc --- /dev/null +++ b/src/Perspex.Controls/IApplicationLifecycle.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Perspex.Controls +{ + /// + /// Sends events about the application lifecycle. + /// + public interface IApplicationLifecycle + { + /// + /// Sent when the application is exiting. + /// + event EventHandler OnExit; + + /// + /// Exits the application. + /// + void Exit(); + } +} diff --git a/src/Perspex.Controls/Perspex.Controls.csproj b/src/Perspex.Controls/Perspex.Controls.csproj index 58aee7f2a5..0d4a0b6c45 100644 --- a/src/Perspex.Controls/Perspex.Controls.csproj +++ b/src/Perspex.Controls/Perspex.Controls.csproj @@ -50,6 +50,7 @@ + diff --git a/src/Perspex.Controls/TopLevel.cs b/src/Perspex.Controls/TopLevel.cs index b82d3da078..cb2651c67d 100644 --- a/src/Perspex.Controls/TopLevel.cs +++ b/src/Perspex.Controls/TopLevel.cs @@ -48,6 +48,7 @@ namespace Perspex.Controls private readonly IInputManager _inputManager; private readonly IAccessKeyHandler _accessKeyHandler; private readonly IKeyboardNavigationHandler _keyboardNavigationHandler; + private readonly IApplicationLifecycle _applicationLifecycle; private Size _clientSize; private bool _isActive; @@ -92,6 +93,7 @@ namespace Perspex.Controls _inputManager = TryGetService(dependencyResolver); _keyboardNavigationHandler = TryGetService(dependencyResolver); _renderQueueManager = TryGetService(dependencyResolver); + _applicationLifecycle = TryGetService(dependencyResolver); (TryGetService(dependencyResolver) ?? new DefaultTopLevelRenderer()).Attach(this); PlatformImpl.SetInputRoot(this); @@ -112,6 +114,7 @@ namespace Perspex.Controls .Select( x => (x as InputElement)?.GetObservable(CursorProperty) ?? Observable.Empty()) .Switch().Subscribe(cursor => PlatformImpl.SetCursor(cursor?.PlatformCursor)); + _applicationLifecycle.OnExit += HandleApplicationExiting; } /// @@ -347,6 +350,20 @@ namespace Perspex.Controls private void HandleClosed() { Closed?.Invoke(this, EventArgs.Empty); + _applicationLifecycle.OnExit -= OnApplicationExiting; + } + + private void OnApplicationExiting(object sender, EventArgs args) + { + + } + + /// + /// Handles the application exiting, either from the last window closing, or a call to . + /// + protected virtual void HandleApplicationExiting() + { + } /// diff --git a/src/Perspex.Controls/Window.cs b/src/Perspex.Controls/Window.cs index 22307ab97e..ae12a4d6ed 100644 --- a/src/Perspex.Controls/Window.cs +++ b/src/Perspex.Controls/Window.cs @@ -156,6 +156,12 @@ namespace Perspex.Controls PlatformImpl.Dispose(); } + protected override void HandleApplicationExiting() + { + base.HandleApplicationExiting(); + Close(); + } + /// /// Closes a dialog window with the specified result. ///