MouseGrabHandler.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #nullable enable
  2. namespace Terminal.Gui.App;
  3. /// <summary>
  4. /// INTERNAL: Implements <see cref="IMouseGrabHandler"/> to manage which <see cref="View"/> (if any) has 'grabbed' the mouse,
  5. /// giving it exclusive priority for mouse events such as movement, button presses, and release.
  6. /// <para>
  7. /// Used for scenarios like dragging, scrolling, or any interaction where a view needs to receive all mouse events
  8. /// until the operation completes (e.g., a scrollbar thumb being dragged).
  9. /// </para>
  10. /// <para>
  11. /// See <see cref="IMouseGrabHandler"/> for usage details.
  12. /// </para>
  13. /// </summary>
  14. internal class MouseGrabHandler : IMouseGrabHandler
  15. {
  16. /// <inheritdoc/>
  17. public View? MouseGrabView { get; private set; }
  18. /// <inheritdoc/>
  19. public event EventHandler<GrabMouseEventArgs>? GrabbingMouse;
  20. /// <inheritdoc/>
  21. public event EventHandler<GrabMouseEventArgs>? UnGrabbingMouse;
  22. /// <inheritdoc/>
  23. public event EventHandler<ViewEventArgs>? GrabbedMouse;
  24. /// <inheritdoc/>
  25. public event EventHandler<ViewEventArgs>? UnGrabbedMouse;
  26. /// <inheritdoc/>
  27. public void GrabMouse (View? view)
  28. {
  29. if (view is null || RaiseGrabbingMouseEvent (view))
  30. {
  31. return;
  32. }
  33. RaiseGrabbedMouseEvent (view);
  34. // MouseGrabView is a static; only set if the application is initialized.
  35. MouseGrabView = view;
  36. }
  37. /// <inheritdoc/>
  38. public void UngrabMouse ()
  39. {
  40. if (MouseGrabView is null)
  41. {
  42. return;
  43. }
  44. #if DEBUG_IDISPOSABLE
  45. if (View.EnableDebugIDisposableAsserts)
  46. {
  47. ObjectDisposedException.ThrowIf (MouseGrabView.WasDisposed, MouseGrabView);
  48. }
  49. #endif
  50. if (!RaiseUnGrabbingMouseEvent (MouseGrabView))
  51. {
  52. View view = MouseGrabView;
  53. MouseGrabView = null;
  54. RaiseUnGrabbedMouseEvent (view);
  55. }
  56. }
  57. /// <exception cref="Exception">A delegate callback throws an exception.</exception>
  58. private bool RaiseGrabbingMouseEvent (View? view)
  59. {
  60. if (view is null)
  61. {
  62. return false;
  63. }
  64. var evArgs = new GrabMouseEventArgs (view);
  65. GrabbingMouse?.Invoke (view, evArgs);
  66. return evArgs.Cancel;
  67. }
  68. /// <exception cref="Exception">A delegate callback throws an exception.</exception>
  69. private bool RaiseUnGrabbingMouseEvent (View? view)
  70. {
  71. if (view is null)
  72. {
  73. return false;
  74. }
  75. var evArgs = new GrabMouseEventArgs (view);
  76. UnGrabbingMouse?.Invoke (view, evArgs);
  77. return evArgs.Cancel;
  78. }
  79. /// <exception cref="Exception">A delegate callback throws an exception.</exception>
  80. private void RaiseGrabbedMouseEvent (View? view)
  81. {
  82. if (view is null)
  83. {
  84. return;
  85. }
  86. GrabbedMouse?.Invoke (view, new (view));
  87. }
  88. /// <exception cref="Exception">A delegate callback throws an exception.</exception>
  89. private void RaiseUnGrabbedMouseEvent (View? view)
  90. {
  91. if (view is null)
  92. {
  93. return;
  94. }
  95. UnGrabbedMouse?.Invoke (view, new (view));
  96. }
  97. }