ToplevelOverlapped.cs 4.8 KB

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