Application.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. // Copyright (c) The Avalonia Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using System;
  4. using System.Threading;
  5. using Avalonia.Controls;
  6. using Avalonia.Controls.Templates;
  7. using Avalonia.Input;
  8. using Avalonia.Input.Platform;
  9. using Avalonia.Layout;
  10. using Avalonia.Rendering;
  11. using Avalonia.Styling;
  12. using Avalonia.Threading;
  13. using System.Reactive.Concurrency;
  14. using Avalonia.Input.DragDrop.Raw;
  15. using Avalonia.Controls.Platform;
  16. using Avalonia.Platform;
  17. using Avalonia.Input.DragDrop;
  18. namespace Avalonia
  19. {
  20. /// <summary>
  21. /// Encapsulates a Avalonia application.
  22. /// </summary>
  23. /// <remarks>
  24. /// The <see cref="Application"/> class encapsulates Avalonia application-specific
  25. /// functionality, including:
  26. /// - A global set of <see cref="DataTemplates"/>.
  27. /// - A global set of <see cref="Styles"/>.
  28. /// - A <see cref="FocusManager"/>.
  29. /// - An <see cref="InputManager"/>.
  30. /// - Registers services needed by the rest of Avalonia in the <see cref="RegisterServices"/>
  31. /// method.
  32. /// - Tracks the lifetime of the application.
  33. /// </remarks>
  34. public class Application : IApplicationLifecycle, IGlobalDataTemplates, IGlobalStyles, IStyleRoot, IResourceNode
  35. {
  36. /// <summary>
  37. /// The application-global data templates.
  38. /// </summary>
  39. private DataTemplates _dataTemplates;
  40. private readonly Lazy<IClipboard> _clipboard =
  41. new Lazy<IClipboard>(() => (IClipboard)AvaloniaLocator.Current.GetService(typeof(IClipboard)));
  42. private readonly Styler _styler = new Styler();
  43. private Styles _styles;
  44. private IResourceDictionary _resources;
  45. /// <summary>
  46. /// Initializes a new instance of the <see cref="Application"/> class.
  47. /// </summary>
  48. public Application()
  49. {
  50. OnExit += OnExiting;
  51. }
  52. /// <inheritdoc/>
  53. public event EventHandler<ResourcesChangedEventArgs> ResourcesChanged;
  54. /// <summary>
  55. /// Gets the current instance of the <see cref="Application"/> class.
  56. /// </summary>
  57. /// <value>
  58. /// The current instance of the <see cref="Application"/> class.
  59. /// </value>
  60. public static Application Current
  61. {
  62. get { return AvaloniaLocator.Current.GetService<Application>(); }
  63. }
  64. /// <summary>
  65. /// Gets or sets the application's global data templates.
  66. /// </summary>
  67. /// <value>
  68. /// The application's global data templates.
  69. /// </value>
  70. public DataTemplates DataTemplates => _dataTemplates ?? (_dataTemplates = new DataTemplates());
  71. /// <summary>
  72. /// Gets the application's focus manager.
  73. /// </summary>
  74. /// <value>
  75. /// The application's focus manager.
  76. /// </value>
  77. public IFocusManager FocusManager
  78. {
  79. get;
  80. private set;
  81. }
  82. /// <summary>
  83. /// Gets the application's input manager.
  84. /// </summary>
  85. /// <value>
  86. /// The application's input manager.
  87. /// </value>
  88. public InputManager InputManager
  89. {
  90. get;
  91. private set;
  92. }
  93. /// <summary>
  94. /// Gets the application clipboard.
  95. /// </summary>
  96. public IClipboard Clipboard => _clipboard.Value;
  97. /// <summary>
  98. /// Gets the application's global resource dictionary.
  99. /// </summary>
  100. public IResourceDictionary Resources
  101. {
  102. get => _resources ?? (Resources = new ResourceDictionary());
  103. set
  104. {
  105. Contract.Requires<ArgumentNullException>(value != null);
  106. var hadResources = false;
  107. if (_resources != null)
  108. {
  109. hadResources = _resources.Count > 0;
  110. _resources.ResourcesChanged -= ResourcesChanged;
  111. }
  112. _resources = value;
  113. _resources.ResourcesChanged += ResourcesChanged;
  114. if (hadResources || _resources.Count > 0)
  115. {
  116. ResourcesChanged?.Invoke(this, new ResourcesChangedEventArgs());
  117. }
  118. }
  119. }
  120. /// <summary>
  121. /// Gets the application's global styles.
  122. /// </summary>
  123. /// <value>
  124. /// The application's global styles.
  125. /// </value>
  126. /// <remarks>
  127. /// Global styles apply to all windows in the application.
  128. /// </remarks>
  129. public Styles Styles => _styles ?? (_styles = new Styles());
  130. /// <inheritdoc/>
  131. bool IDataTemplateHost.IsDataTemplatesInitialized => _dataTemplates != null;
  132. /// <summary>
  133. /// Gets the styling parent of the application, which is null.
  134. /// </summary>
  135. IStyleHost IStyleHost.StylingParent => null;
  136. /// <inheritdoc/>
  137. bool IStyleHost.IsStylesInitialized => _styles != null;
  138. /// <inheritdoc/>
  139. bool IResourceProvider.HasResources => _resources?.Count > 0;
  140. /// <inheritdoc/>
  141. IResourceNode IResourceNode.ResourceParent => null;
  142. /// <summary>
  143. /// Initializes the application by loading XAML etc.
  144. /// </summary>
  145. public virtual void Initialize()
  146. {
  147. }
  148. /// <summary>
  149. /// Runs the application's main loop until the <see cref="ICloseable"/> is closed.
  150. /// </summary>
  151. /// <param name="closable">The closable to track</param>
  152. public void Run(ICloseable closable)
  153. {
  154. var source = new CancellationTokenSource();
  155. closable.Closed += OnExiting;
  156. closable.Closed += (s, e) => source.Cancel();
  157. Dispatcher.UIThread.MainLoop(source.Token);
  158. }
  159. /// <summary>
  160. /// Runs the application's main loop until the <see cref="CancellationToken"/> is cancelled.
  161. /// </summary>
  162. /// <param name="token">The token to track</param>
  163. public void Run(CancellationToken token)
  164. {
  165. Dispatcher.UIThread.MainLoop(token);
  166. }
  167. /// <summary>
  168. /// Exits the application
  169. /// </summary>
  170. public void Exit()
  171. {
  172. OnExit?.Invoke(this, EventArgs.Empty);
  173. }
  174. /// <inheritdoc/>
  175. bool IResourceProvider.TryGetResource(string key, out object value)
  176. {
  177. value = null;
  178. return (_resources?.TryGetResource(key, out value) ?? false) ||
  179. Styles.TryGetResource(key, out value);
  180. }
  181. /// <summary>
  182. /// Sent when the application is exiting.
  183. /// </summary>
  184. public event EventHandler OnExit;
  185. /// <summary>
  186. /// Called when the application is exiting.
  187. /// </summary>
  188. /// <param name="sender"></param>
  189. /// <param name="e"></param>
  190. protected virtual void OnExiting(object sender, EventArgs e)
  191. {
  192. }
  193. /// <summary>
  194. /// Register's the services needed by Avalonia.
  195. /// </summary>
  196. public virtual void RegisterServices()
  197. {
  198. AvaloniaSynchronizationContext.InstallIfNeeded();
  199. FocusManager = new FocusManager();
  200. InputManager = new InputManager();
  201. AvaloniaLocator.CurrentMutable
  202. .Bind<IAccessKeyHandler>().ToTransient<AccessKeyHandler>()
  203. .Bind<IGlobalDataTemplates>().ToConstant(this)
  204. .Bind<IGlobalStyles>().ToConstant(this)
  205. .Bind<IFocusManager>().ToConstant(FocusManager)
  206. .Bind<IInputManager>().ToConstant(InputManager)
  207. .Bind<IKeyboardNavigationHandler>().ToTransient<KeyboardNavigationHandler>()
  208. .Bind<IStyler>().ToConstant(_styler)
  209. .Bind<ILayoutManager>().ToSingleton<LayoutManager>()
  210. .Bind<IApplicationLifecycle>().ToConstant(this)
  211. .Bind<IScheduler>().ToConstant(AvaloniaScheduler.Instance)
  212. .Bind<IDragDropDevice>().ToConstant(DragDropDevice.Instance)
  213. .Bind<IPlatformDragSource>().ToTransient<DragSource>();
  214. }
  215. }
  216. }