// Copyright (c) The Avalonia Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; using System.Threading; using Avalonia.Controls; using Avalonia.Controls.Templates; using Avalonia.Input; using Avalonia.Input.Platform; using Avalonia.Layout; using Avalonia.Rendering; using Avalonia.Styling; using Avalonia.Threading; using System.Reactive.Concurrency; using Avalonia.Input.DragDrop.Raw; using Avalonia.Controls.Platform; using Avalonia.Platform; using Avalonia.Input.DragDrop; namespace Avalonia { /// /// Encapsulates a Avalonia application. /// /// /// The class encapsulates Avalonia application-specific /// functionality, including: /// - A global set of . /// - A global set of . /// - A . /// - An . /// - Registers services needed by the rest of Avalonia in the /// method. /// - Tracks the lifetime of the application. /// public class Application : IApplicationLifecycle, IGlobalDataTemplates, IGlobalStyles, IStyleRoot, IResourceNode { /// /// The application-global data templates. /// private DataTemplates _dataTemplates; private readonly Lazy _clipboard = new Lazy(() => (IClipboard)AvaloniaLocator.Current.GetService(typeof(IClipboard))); private readonly Styler _styler = new Styler(); private Styles _styles; private IResourceDictionary _resources; /// /// Initializes a new instance of the class. /// public Application() { OnExit += OnExiting; } /// public event EventHandler ResourcesChanged; /// /// Gets the current instance of the class. /// /// /// The current instance of the class. /// public static Application Current { get { return AvaloniaLocator.Current.GetService(); } } /// /// Gets or sets the application's global data templates. /// /// /// The application's global data templates. /// public DataTemplates DataTemplates => _dataTemplates ?? (_dataTemplates = new DataTemplates()); /// /// Gets the application's focus manager. /// /// /// The application's focus manager. /// public IFocusManager FocusManager { get; private set; } /// /// Gets the application's input manager. /// /// /// The application's input manager. /// public InputManager InputManager { get; private set; } /// /// Gets the application clipboard. /// public IClipboard Clipboard => _clipboard.Value; /// /// Gets the application's global resource dictionary. /// public IResourceDictionary Resources { get => _resources ?? (Resources = new ResourceDictionary()); set { Contract.Requires(value != null); var hadResources = false; if (_resources != null) { hadResources = _resources.Count > 0; _resources.ResourcesChanged -= ResourcesChanged; } _resources = value; _resources.ResourcesChanged += ResourcesChanged; if (hadResources || _resources.Count > 0) { ResourcesChanged?.Invoke(this, new ResourcesChangedEventArgs()); } } } /// /// Gets the application's global styles. /// /// /// The application's global styles. /// /// /// Global styles apply to all windows in the application. /// public Styles Styles => _styles ?? (_styles = new Styles()); /// bool IDataTemplateHost.IsDataTemplatesInitialized => _dataTemplates != null; /// /// Gets the styling parent of the application, which is null. /// IStyleHost IStyleHost.StylingParent => null; /// bool IStyleHost.IsStylesInitialized => _styles != null; /// bool IResourceProvider.HasResources => _resources?.Count > 0; /// IResourceNode IResourceNode.ResourceParent => null; /// /// Initializes the application by loading XAML etc. /// public virtual void Initialize() { } /// /// Runs the application's main loop until the is closed. /// /// The closable to track public void Run(ICloseable closable) { var source = new CancellationTokenSource(); closable.Closed += OnExiting; closable.Closed += (s, e) => source.Cancel(); Dispatcher.UIThread.MainLoop(source.Token); } /// /// Runs the application's main loop until the is cancelled. /// /// The token to track public void Run(CancellationToken token) { Dispatcher.UIThread.MainLoop(token); } /// /// Exits the application /// public void Exit() { OnExit?.Invoke(this, EventArgs.Empty); } /// bool IResourceProvider.TryGetResource(string key, out object value) { value = null; return (_resources?.TryGetResource(key, out value) ?? false) || Styles.TryGetResource(key, out value); } /// /// 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 Avalonia. /// public virtual void RegisterServices() { AvaloniaSynchronizationContext.InstallIfNeeded(); FocusManager = new FocusManager(); InputManager = new InputManager(); AvaloniaLocator.CurrentMutable .Bind().ToTransient() .Bind().ToConstant(this) .Bind().ToConstant(this) .Bind().ToConstant(FocusManager) .Bind().ToConstant(InputManager) .Bind().ToTransient() .Bind().ToConstant(_styler) .Bind().ToSingleton() .Bind().ToConstant(this) .Bind().ToConstant(AvaloniaScheduler.Instance) .Bind().ToConstant(DragDropDevice.Instance) .Bind().ToTransient(); } } }