ApplicationImpl.cs 3.2 KB

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