ApplicationImpl.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. using System.Collections.Concurrent;
  2. namespace Terminal.Gui.App;
  3. /// <summary>
  4. /// Implementation of core <see cref="Application"/> methods using the modern
  5. /// main loop architecture with component factories for different platforms.
  6. /// </summary>
  7. public partial class ApplicationImpl : IApplication
  8. {
  9. /// <summary>
  10. /// Creates a new instance of the Application backend.
  11. /// </summary>
  12. public ApplicationImpl () { }
  13. /// <summary>
  14. /// INTERNAL: Creates a new instance of the Application backend.
  15. /// </summary>
  16. /// <param name="componentFactory"></param>
  17. internal ApplicationImpl (IComponentFactory componentFactory) { _componentFactory = componentFactory; }
  18. #region Singleton
  19. // Private static readonly Lazy instance of Application
  20. private static Lazy<IApplication> _lazyInstance = new (() => new ApplicationImpl ());
  21. /// <summary>
  22. /// Change the singleton implementation, should not be called except before application
  23. /// startup. This method lets you provide alternative implementations of core static gateway
  24. /// methods of <see cref="Application"/>.
  25. /// </summary>
  26. /// <param name="newApplication"></param>
  27. public static void ChangeInstance (IApplication? newApplication) { _lazyInstance = new (newApplication!); }
  28. /// <summary>
  29. /// Gets the currently configured backend implementation of <see cref="Application"/> gateway methods.
  30. /// Change to your own implementation by using <see cref="ChangeInstance"/> (before init).
  31. /// </summary>
  32. public static IApplication Instance => _lazyInstance.Value;
  33. #endregion Singleton
  34. private string? _driverName;
  35. #region Input
  36. private IMouse? _mouse;
  37. /// <summary>
  38. /// Handles mouse event state and processing.
  39. /// </summary>
  40. public IMouse Mouse
  41. {
  42. get
  43. {
  44. if (_mouse is null)
  45. {
  46. _mouse = new MouseImpl { Application = this };
  47. }
  48. return _mouse;
  49. }
  50. set => _mouse = value ?? throw new ArgumentNullException (nameof (value));
  51. }
  52. private IKeyboard? _keyboard;
  53. /// <summary>
  54. /// Handles keyboard input and key bindings at the Application level
  55. /// </summary>
  56. public IKeyboard Keyboard
  57. {
  58. get
  59. {
  60. if (_keyboard is null)
  61. {
  62. _keyboard = new KeyboardImpl { App = this };
  63. }
  64. return _keyboard;
  65. }
  66. set => _keyboard = value ?? throw new ArgumentNullException (nameof (value));
  67. }
  68. #endregion Input
  69. #region View Management
  70. /// <inheritdoc/>
  71. public ApplicationPopover? Popover { get; set; }
  72. private ApplicationNavigation? _navigation;
  73. /// <inheritdoc/>
  74. public ApplicationNavigation? Navigation
  75. {
  76. get
  77. {
  78. if (_navigation is null)
  79. {
  80. _navigation = new () { App = this };
  81. }
  82. return _navigation;
  83. }
  84. set => _navigation = value ?? throw new ArgumentNullException (nameof (value));
  85. }
  86. /// <inheritdoc/>
  87. public Toplevel? Current { get; set; }
  88. // BUGBUG: Technically, this is not the full lst of sessions. There be dragons here, e.g. see how Toplevel.Id is used. What
  89. /// <inheritdoc/>
  90. public ConcurrentStack<Toplevel> SessionStack { get; } = new ();
  91. /// <inheritdoc/>
  92. public Toplevel? CachedSessionTokenToplevel { get; set; }
  93. #endregion View Management
  94. }