using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Drawing; using System.Windows.Forms; namespace WeifenLuo.WinFormsUI.Docking { public sealed class VisibleNestedPaneCollection : ReadOnlyCollection<DockPane> { private NestedPaneCollection m_nestedPanes; internal VisibleNestedPaneCollection(NestedPaneCollection nestedPanes) : base(new List<DockPane>()) { m_nestedPanes = nestedPanes; } public NestedPaneCollection NestedPanes { get { return m_nestedPanes; } } public INestedPanesContainer Container { get { return NestedPanes.Container; } } public DockState DockState { get { return NestedPanes.DockState; } } public bool IsFloat { get { return NestedPanes.IsFloat; } } internal void Refresh() { Items.Clear(); for (int i=0; i<NestedPanes.Count; i++) { DockPane pane = NestedPanes[i]; NestedDockingStatus status = pane.NestedDockingStatus; status.SetDisplayingStatus(true, status.PreviousPane, status.Alignment, status.Proportion); Items.Add(pane); } foreach (DockPane pane in NestedPanes) if (pane.DockState != DockState || pane.IsHidden) { pane.Bounds = Rectangle.Empty; pane.SplitterBounds = Rectangle.Empty; Remove(pane); } CalculateBounds(); foreach (DockPane pane in this) { NestedDockingStatus status = pane.NestedDockingStatus; pane.Bounds = status.PaneBounds; pane.SplitterBounds = status.SplitterBounds; pane.SplitterAlignment = status.Alignment; } } private void Remove(DockPane pane) { if (!Contains(pane)) return; NestedDockingStatus statusPane = pane.NestedDockingStatus; DockPane lastNestedPane = null; for (int i=Count - 1; i> IndexOf(pane); i--) { if (this[i].NestedDockingStatus.PreviousPane == pane) { lastNestedPane = this[i]; break; } } if (lastNestedPane != null) { int indexLastNestedPane = IndexOf(lastNestedPane); Items.Remove(lastNestedPane); Items[IndexOf(pane)] = lastNestedPane; NestedDockingStatus lastNestedDock = lastNestedPane.NestedDockingStatus; lastNestedDock.SetDisplayingStatus(true, statusPane.DisplayingPreviousPane, statusPane.DisplayingAlignment, statusPane.DisplayingProportion); for (int i=indexLastNestedPane - 1; i>IndexOf(lastNestedPane); i--) { NestedDockingStatus status = this[i].NestedDockingStatus; if (status.PreviousPane == pane) status.SetDisplayingStatus(true, lastNestedPane, status.DisplayingAlignment, status.DisplayingProportion); } } else Items.Remove(pane); statusPane.SetDisplayingStatus(false, null, DockAlignment.Left, 0.5); } private void CalculateBounds() { if (Count == 0) return; this[0].NestedDockingStatus.SetDisplayingBounds(Container.DisplayingRectangle, Container.DisplayingRectangle, Rectangle.Empty); for (int i=1; i<Count; i++) { DockPane pane = this[i]; NestedDockingStatus status = pane.NestedDockingStatus; DockPane prevPane = status.DisplayingPreviousPane; NestedDockingStatus statusPrev = prevPane.NestedDockingStatus; Rectangle rect = statusPrev.PaneBounds; bool bVerticalSplitter = (status.DisplayingAlignment == DockAlignment.Left || status.DisplayingAlignment == DockAlignment.Right); Rectangle rectThis = rect; Rectangle rectPrev = rect; Rectangle rectSplitter = rect; if (status.DisplayingAlignment == DockAlignment.Left) { rectThis.Width = (int)((double)rect.Width * status.DisplayingProportion) - (Measures.SplitterSize / 2); rectSplitter.X = rectThis.X + rectThis.Width; rectSplitter.Width = Measures.SplitterSize; rectPrev.X = rectSplitter.X + rectSplitter.Width; rectPrev.Width = rect.Width - rectThis.Width - rectSplitter.Width; } else if (status.DisplayingAlignment == DockAlignment.Right) { rectPrev.Width = (rect.Width - (int)((double)rect.Width * status.DisplayingProportion)) - (Measures.SplitterSize / 2); rectSplitter.X = rectPrev.X + rectPrev.Width; rectSplitter.Width = Measures.SplitterSize; rectThis.X = rectSplitter.X + rectSplitter.Width; rectThis.Width = rect.Width - rectPrev.Width - rectSplitter.Width; } else if (status.DisplayingAlignment == DockAlignment.Top) { rectThis.Height = (int)((double)rect.Height * status.DisplayingProportion) - (Measures.SplitterSize / 2); rectSplitter.Y = rectThis.Y + rectThis.Height; rectSplitter.Height = Measures.SplitterSize; rectPrev.Y = rectSplitter.Y + rectSplitter.Height; rectPrev.Height = rect.Height - rectThis.Height - rectSplitter.Height; } else if (status.DisplayingAlignment == DockAlignment.Bottom) { rectPrev.Height = (rect.Height - (int)((double)rect.Height * status.DisplayingProportion)) - (Measures.SplitterSize / 2); rectSplitter.Y = rectPrev.Y + rectPrev.Height; rectSplitter.Height = Measures.SplitterSize; rectThis.Y = rectSplitter.Y + rectSplitter.Height; rectThis.Height = rect.Height - rectPrev.Height - rectSplitter.Height; } else rectThis = Rectangle.Empty; rectSplitter.Intersect(rect); rectThis.Intersect(rect); rectPrev.Intersect(rect); status.SetDisplayingBounds(rect, rectThis, rectSplitter); statusPrev.SetDisplayingBounds(statusPrev.LogicalBounds, rectPrev, statusPrev.SplitterBounds); } } } }