ApplicationNavigation.cs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #nullable enable
  2. namespace Terminal.Gui;
  3. /// <summary>
  4. /// Helper class for <see cref="Application"/> navigation. Held by <see cref="Application.Navigation"/>
  5. /// </summary>
  6. public class ApplicationNavigation
  7. {
  8. /// <summary>
  9. /// Initializes a new instance of the <see cref="ApplicationNavigation"/> class.
  10. /// </summary>
  11. public ApplicationNavigation ()
  12. {
  13. // TODO: Move navigation key bindings here from AddApplicationKeyBindings
  14. }
  15. private View? _focused;
  16. /// <summary>
  17. /// Raised when the most focused <see cref="View"/> in the application has changed.
  18. /// </summary>
  19. public event EventHandler<EventArgs>? FocusedChanged;
  20. /// <summary>
  21. /// Gets the most focused <see cref="View"/> in the application, if there is one.
  22. /// </summary>
  23. public View? GetFocused () { return _focused; }
  24. /// <summary>
  25. /// Gets whether <paramref name="view"/> is in the Subview hierarchy of <paramref name="start"/>.
  26. /// </summary>
  27. /// <param name="start"></param>
  28. /// <param name="view"></param>
  29. /// <returns></returns>
  30. public static bool IsInHierarchy (View? start, View? view)
  31. {
  32. if (view is null)
  33. {
  34. return false;
  35. }
  36. if (view == start || start is null)
  37. {
  38. return true;
  39. }
  40. foreach (View subView in start.Subviews)
  41. {
  42. if (view == subView)
  43. {
  44. return true;
  45. }
  46. bool found = IsInHierarchy (subView, view);
  47. if (found)
  48. {
  49. return found;
  50. }
  51. }
  52. return false;
  53. }
  54. /// <summary>
  55. /// INTERNAL method to record the most focused <see cref="View"/> in the application.
  56. /// </summary>
  57. /// <remarks>
  58. /// Raises <see cref="FocusedChanged"/>.
  59. /// </remarks>
  60. internal void SetFocused (View? value)
  61. {
  62. if (_focused == value)
  63. {
  64. return;
  65. }
  66. _focused = value;
  67. FocusedChanged?.Invoke (null, EventArgs.Empty);
  68. }
  69. /// <summary>
  70. /// Advances the focus to the next or previous view in the focus chain, based on
  71. /// <paramref name="direction"/>.
  72. /// </summary>
  73. /// <remarks>
  74. /// <para>
  75. /// If there is no next/previous view, the focus remains on the current view.
  76. /// </para>
  77. /// </remarks>
  78. /// <param name="direction">The direction to advance.</param>
  79. /// <param name="behavior">The tab behavior.</param>
  80. /// <returns>
  81. /// <see langword="true"/> if focus was changed to another subview (or stayed on this one), <see langword="false"/>
  82. /// otherwise.
  83. /// </returns>
  84. public bool AdvanceFocus (NavigationDirection direction, TabBehavior? behavior)
  85. {
  86. return Application.Current is { } && Application.Current.AdvanceFocus (direction, behavior);
  87. }
  88. }