ToplevelOverlapped.cs 6.1 KB

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