using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; namespace Terminal.Gui { public partial class Toplevel { /// /// Gets or sets if this Toplevel is a container for overlapped children. /// public bool IsOverlappedContainer { get; set; } /// /// Gets or sets if this Toplevel is in overlapped mode within a Toplevel container. /// public bool IsOverlapped { get { return Application.OverlappedTop != null && Application.OverlappedTop != this && !Modal; } } } public static partial class Application { /// /// Gets the list of the Overlapped children which are not modal from the . /// public static List OverlappedChildren { get { if (OverlappedTop != null) { List _overlappedChildren = new List (); foreach (var top in _toplevels) { if (top != OverlappedTop && !top.Modal) { _overlappedChildren.Add (top); } } return _overlappedChildren; } return null; } } /// /// The object used for the application on startup which is true. /// public static Toplevel OverlappedTop { get { if (Top.IsOverlappedContainer) { return Top; } return null; } } static View FindDeepestOverlappedView (View start, int x, int y, out int resx, out int resy) { if (start.GetType ().BaseType != typeof (Toplevel) && !((Toplevel)start).IsOverlappedContainer) { resx = 0; resy = 0; return null; } var startFrame = start.Frame; if (!startFrame.Contains (x, y)) { resx = 0; resy = 0; return null; } int count = _toplevels.Count; for (int i = count - 1; i >= 0; i--) { foreach (var top in _toplevels) { var rx = x - startFrame.X; var ry = y - startFrame.Y; if (top.Visible && top.Frame.Contains (rx, ry)) { var deep = View.FindDeepestView (top, rx, ry, out resx, out resy); if (deep == null) return FindDeepestOverlappedView (top, rx, ry, out resx, out resy); if (deep != OverlappedTop) return deep; } } } resx = x - startFrame.X; resy = y - startFrame.Y; return start; } static bool OverlappedChildNeedsDisplay () { if (OverlappedTop == null) { return false; } foreach (var top in _toplevels) { if (top != Current && top.Visible && (top.NeedsDisplay || top.SubViewNeedsDisplay || top.LayoutNeeded)) { OverlappedTop.SetSubViewNeedsDisplay (); return true; } } return false; } static bool SetCurrentOverlappedAsTop () { if (OverlappedTop == null && Current != Top && Current?.SuperView == null && Current?.Modal == false) { if (Current.Frame != new Rect (0, 0, Driver.Cols, Driver.Rows)) { Current.Frame = new Rect (0, 0, Driver.Cols, Driver.Rows); } Top = Current; return true; } return false; } /// /// Move to the next Overlapped child from the . /// public static void OverlappedMoveNext () { if (OverlappedTop != null && !Current.Modal) { lock (_toplevels) { _toplevels.MoveNext (); var isOverlapped = false; while (_toplevels.Peek () == OverlappedTop || !_toplevels.Peek ().Visible) { if (!isOverlapped && _toplevels.Peek () == OverlappedTop) { isOverlapped = true; } else if (isOverlapped && _toplevels.Peek () == OverlappedTop) { MoveCurrent (Top); break; } _toplevels.MoveNext (); } Current = _toplevels.Peek (); } } } /// /// Move to the previous Overlapped child from the . /// public static void OverlappedMovePrevious () { if (OverlappedTop != null && !Current.Modal) { lock (_toplevels) { _toplevels.MovePrevious (); var isOverlapped = false; while (_toplevels.Peek () == OverlappedTop || !_toplevels.Peek ().Visible) { if (!isOverlapped && _toplevels.Peek () == OverlappedTop) { isOverlapped = true; } else if (isOverlapped && _toplevels.Peek () == OverlappedTop) { MoveCurrent (Top); break; } _toplevels.MovePrevious (); } Current = _toplevels.Peek (); } } } /// /// Move to the next Overlapped child from the and set it as the if it is not already. /// /// /// public static bool MoveToOverlappedChild (Toplevel top) { if (top.Visible && OverlappedTop != null && Current?.Modal == false) { lock (_toplevels) { _toplevels.MoveTo (top, 0, new ToplevelEqualityComparer ()); Current = top; } return true; } return false; } /// /// Brings the superview of the most focused overlapped view is on front. /// public static void BringOverlappedTopToFront () { if (OverlappedTop != null) { return; } var top = FindTopFromView (Top?.MostFocused); if (top != null && Top.Subviews.Count > 1 && Top.Subviews [Top.Subviews.Count - 1] != top) { Top.BringSubviewToFront (top); } } /// /// Gets the current visible Toplevel overlapped child that matches the arguments pattern. /// /// The type. /// The strings to exclude. /// The matched view. public static Toplevel GetTopOverlappedChild (Type type = null, string [] exclude = null) { if (Application.OverlappedTop == null) { return null; } foreach (var top in Application.OverlappedChildren) { if (type != null && top.GetType () == type && exclude?.Contains (top.Data.ToString ()) == false) { return top; } else if ((type != null && top.GetType () != type) || (exclude?.Contains (top.Data.ToString ()) == true)) { continue; } return top; } return null; } } }