ToplevelOverlapped.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. namespace Terminal.Gui;
  2. public partial class Toplevel
  3. {
  4. /// <summary>Gets or sets if this Toplevel is in overlapped mode within a Toplevel container.</summary>
  5. public bool IsOverlapped => Application.OverlappedTop is { } && Application.OverlappedTop != this && !Modal;
  6. /// <summary>Gets or sets if this Toplevel is a container for overlapped children.</summary>
  7. public bool IsOverlappedContainer { get; set; }
  8. }
  9. public static partial class Application
  10. {
  11. /// <summary>
  12. /// Gets the list of the Overlapped children which are not modal <see cref="Toplevel"/> from the
  13. /// <see cref="OverlappedTop"/>.
  14. /// </summary>
  15. public static List<Toplevel> OverlappedChildren
  16. {
  17. get
  18. {
  19. if (OverlappedTop is { })
  20. {
  21. List<Toplevel> _overlappedChildren = new ();
  22. foreach (Toplevel top in _topLevels)
  23. {
  24. if (top != OverlappedTop && !top.Modal)
  25. {
  26. _overlappedChildren.Add (top);
  27. }
  28. }
  29. return _overlappedChildren;
  30. }
  31. return null;
  32. }
  33. }
  34. #nullable enable
  35. /// <summary>
  36. /// The <see cref="Toplevel"/> object used for the application on startup which
  37. /// <see cref="Toplevel.IsOverlappedContainer"/> is true.
  38. /// </summary>
  39. public static Toplevel? OverlappedTop
  40. {
  41. get
  42. {
  43. if (Top is { IsOverlappedContainer: true })
  44. {
  45. return Top;
  46. }
  47. return null;
  48. }
  49. }
  50. #nullable restore
  51. /// <summary>Brings the superview of the most focused overlapped view is on front.</summary>
  52. public static void BringOverlappedTopToFront ()
  53. {
  54. if (OverlappedTop is { })
  55. {
  56. return;
  57. }
  58. View top = FindTopFromView (Top?.MostFocused);
  59. if (top is Toplevel && Top.Subviews.Count > 1 && Top.Subviews [Top.Subviews.Count - 1] != top)
  60. {
  61. Top.BringSubviewToFront (top);
  62. }
  63. }
  64. /// <summary>Gets the current visible Toplevel overlapped child that matches the arguments pattern.</summary>
  65. /// <param name="type">The type.</param>
  66. /// <param name="exclude">The strings to exclude.</param>
  67. /// <returns>The matched view.</returns>
  68. public static Toplevel GetTopOverlappedChild (Type type = null, string [] exclude = null)
  69. {
  70. if (OverlappedTop is null)
  71. {
  72. return null;
  73. }
  74. foreach (Toplevel top in OverlappedChildren)
  75. {
  76. if (type is { } && top.GetType () == type && exclude?.Contains (top.Data.ToString ()) == false)
  77. {
  78. return top;
  79. }
  80. if ((type is { } && top.GetType () != type) || exclude?.Contains (top.Data.ToString ()) == true)
  81. {
  82. continue;
  83. }
  84. return top;
  85. }
  86. return null;
  87. }
  88. /// <summary>
  89. /// Move to the next Overlapped child from the <see cref="OverlappedTop"/> and set it as the <see cref="Top"/> if
  90. /// it is not already.
  91. /// </summary>
  92. /// <param name="top"></param>
  93. /// <returns></returns>
  94. public static bool MoveToOverlappedChild (Toplevel top)
  95. {
  96. if (top.Visible && OverlappedTop is { } && Current?.Modal == false)
  97. {
  98. lock (_topLevels)
  99. {
  100. _topLevels.MoveTo (top, 0, new ToplevelEqualityComparer ());
  101. Current = top;
  102. }
  103. return true;
  104. }
  105. return false;
  106. }
  107. /// <summary>Move to the next Overlapped child from the <see cref="OverlappedTop"/>.</summary>
  108. public static void OverlappedMoveNext ()
  109. {
  110. if (OverlappedTop is { } && !Current.Modal)
  111. {
  112. lock (_topLevels)
  113. {
  114. _topLevels.MoveNext ();
  115. var isOverlapped = false;
  116. while (_topLevels.Peek () == OverlappedTop || !_topLevels.Peek ().Visible)
  117. {
  118. if (!isOverlapped && _topLevels.Peek () == OverlappedTop)
  119. {
  120. isOverlapped = true;
  121. }
  122. else if (isOverlapped && _topLevels.Peek () == OverlappedTop)
  123. {
  124. MoveCurrent (Top);
  125. break;
  126. }
  127. _topLevels.MoveNext ();
  128. }
  129. Current = _topLevels.Peek ();
  130. }
  131. }
  132. }
  133. /// <summary>Move to the previous Overlapped child from the <see cref="OverlappedTop"/>.</summary>
  134. public static void OverlappedMovePrevious ()
  135. {
  136. if (OverlappedTop is { } && !Current.Modal)
  137. {
  138. lock (_topLevels)
  139. {
  140. _topLevels.MovePrevious ();
  141. var isOverlapped = false;
  142. while (_topLevels.Peek () == OverlappedTop || !_topLevels.Peek ().Visible)
  143. {
  144. if (!isOverlapped && _topLevels.Peek () == OverlappedTop)
  145. {
  146. isOverlapped = true;
  147. }
  148. else if (isOverlapped && _topLevels.Peek () == OverlappedTop)
  149. {
  150. MoveCurrent (Top);
  151. break;
  152. }
  153. _topLevels.MovePrevious ();
  154. }
  155. Current = _topLevels.Peek ();
  156. }
  157. }
  158. }
  159. private static bool OverlappedChildNeedsDisplay ()
  160. {
  161. if (OverlappedTop is null)
  162. {
  163. return false;
  164. }
  165. foreach (Toplevel top in _topLevels)
  166. {
  167. if (top != Current && top.Visible && (top.NeedsDisplay || top.SubViewNeedsDisplay || top.LayoutNeeded))
  168. {
  169. OverlappedTop.SetSubViewNeedsDisplay ();
  170. return true;
  171. }
  172. }
  173. return false;
  174. }
  175. private static bool SetCurrentOverlappedAsTop ()
  176. {
  177. if (OverlappedTop is null && Current != Top && Current?.SuperView is null && Current?.Modal == false)
  178. {
  179. Top = Current;
  180. return true;
  181. }
  182. return false;
  183. }
  184. }