OrientationHelper.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. namespace Terminal.Gui;
  2. /// <summary>
  3. /// Helper class for implementing <see cref="IOrientation"/>.
  4. /// </summary>
  5. /// <remarks>
  6. /// <para>
  7. /// Implements the standard pattern for changing/changed events.
  8. /// </para>
  9. /// </remarks>
  10. /// <example>
  11. /// <code>
  12. /// private class OrientedView : View, IOrientation
  13. /// {
  14. /// private readonly OrientationHelper _orientationHelper;
  15. ///
  16. /// public OrientedView ()
  17. /// {
  18. /// _orientationHelper = new (this);
  19. /// Orientation = Orientation.Vertical;
  20. /// _orientationHelper.OrientationChanging += (sender, e) =&gt; OrientationChanging?.Invoke (this, e);
  21. /// _orientationHelper.OrientationChanged += (sender, e) =&gt; OrientationChanged?.Invoke (this, e);
  22. /// }
  23. ///
  24. /// public Orientation Orientation
  25. /// {
  26. /// get =&gt; _orientationHelper.Orientation;
  27. /// set =&gt; _orientationHelper.Orientation = value;
  28. /// }
  29. ///
  30. /// public event EventHandler&lt;CancelEventArgs&lt;Orientation&gt;&gt; OrientationChanging;
  31. /// public event EventHandler&lt;EventArgs&lt;Orientation&gt;&gt; OrientationChanged;
  32. ///
  33. /// public bool OnOrientationChanging (Orientation currentOrientation, Orientation newOrientation)
  34. /// {
  35. /// // Custom logic before orientation changes
  36. /// return false; // Return true to cancel the change
  37. /// }
  38. ///
  39. /// public void OnOrientationChanged (Orientation newOrientation)
  40. /// {
  41. /// // Custom logic after orientation has changed
  42. /// }
  43. /// }
  44. /// </code>
  45. /// </example>
  46. public class OrientationHelper
  47. {
  48. private Orientation _orientation;
  49. private readonly IOrientation _owner;
  50. /// <summary>
  51. /// Initializes a new instance of the <see cref="OrientationHelper"/> class.
  52. /// </summary>
  53. /// <param name="owner">Specifies the object that owns this helper instance and implements <see cref="IOrientation"/>.</param>
  54. public OrientationHelper (IOrientation owner) { _owner = owner; }
  55. /// <summary>
  56. /// Gets or sets the orientation of the View.
  57. /// </summary>
  58. public Orientation Orientation
  59. {
  60. get => _orientation;
  61. set
  62. {
  63. if (_orientation == value)
  64. {
  65. return;
  66. }
  67. // Best practice is to invoke the virtual method first.
  68. // This allows derived classes to handle the event and potentially cancel it.
  69. if (_owner?.OnOrientationChanging (value, _orientation) ?? false)
  70. {
  71. return;
  72. }
  73. // If the event is not canceled by the virtual method, raise the event to notify any external subscribers.
  74. CancelEventArgs<Orientation> args = new (in _orientation, ref value);
  75. OrientationChanging?.Invoke (_owner, args);
  76. if (args.Cancel)
  77. {
  78. return;
  79. }
  80. // If the event is not canceled, update the value.
  81. Orientation old = _orientation;
  82. if (_orientation != value)
  83. {
  84. _orientation = value;
  85. if (_owner is { })
  86. {
  87. _owner.Orientation = value;
  88. }
  89. }
  90. // Best practice is to invoke the virtual method first.
  91. _owner?.OnOrientationChanged (_orientation);
  92. // Even though Changed is not cancelable, it is still a good practice to raise the event after.
  93. OrientationChanged?.Invoke (_owner, new (in _orientation));
  94. }
  95. }
  96. /// <summary>
  97. /// Raised when the orientation is changing. This is cancelable.
  98. /// </summary>
  99. /// <remarks>
  100. /// <para>
  101. /// Views that implement <see cref="IOrientation"/> should raise <see cref="IOrientation.OrientationChanging"/>
  102. /// after the orientation has changed
  103. /// (<code>_orientationHelper.OrientationChanging += (sender, e) => OrientationChanging?.Invoke (this, e);</code>).
  104. /// </para>
  105. /// <para>
  106. /// This event will be raised after the <see cref="IOrientation.OnOrientationChanging"/> method is called (assuming
  107. /// it was not canceled).
  108. /// </para>
  109. /// </remarks>
  110. public event EventHandler<CancelEventArgs<Orientation>> OrientationChanging;
  111. /// <summary>
  112. /// Raised when the orientation has changed.
  113. /// </summary>
  114. /// <remarks>
  115. /// <para>
  116. /// Views that implement <see cref="IOrientation"/> should raise <see cref="IOrientation.OrientationChanged"/>
  117. /// after the orientation has changed
  118. /// (<code>_orientationHelper.OrientationChanged += (sender, e) => OrientationChanged?.Invoke (this, e);</code>).
  119. /// </para>
  120. /// <para>
  121. /// This event will be raised after the <see cref="IOrientation.OnOrientationChanged"/> method is called.
  122. /// </para>
  123. /// </remarks>
  124. public event EventHandler<EventArgs<Orientation>> OrientationChanged;
  125. }