1 using System;
2 using System.Collections.Generic;
3 using System.Collections.ObjectModel;
4 using System.Drawing;
5 using System.Windows.Forms;
6 
7 namespace WeifenLuo.WinFormsUI.Docking
8 {
9     public sealed class VisibleNestedPaneCollection : ReadOnlyCollection<DockPane>
10     {
11         private NestedPaneCollection m_nestedPanes;
12 
VisibleNestedPaneCollection(NestedPaneCollection nestedPanes)13         internal VisibleNestedPaneCollection(NestedPaneCollection nestedPanes)
14             : base(new List<DockPane>())
15         {
16             m_nestedPanes = nestedPanes;
17         }
18 
19         public NestedPaneCollection NestedPanes
20         {
21             get	{	return m_nestedPanes;	}
22         }
23 
24         public INestedPanesContainer Container
25         {
26             get	{	return NestedPanes.Container;	}
27         }
28 
29         public DockState DockState
30         {
31             get	{	return NestedPanes.DockState;	}
32         }
33 
34         public bool IsFloat
35         {
36             get	{	return NestedPanes.IsFloat;	}
37         }
38 
Refresh()39         internal void Refresh()
40         {
41             Items.Clear();
42             for (int i=0; i<NestedPanes.Count; i++)
43             {
44                 DockPane pane = NestedPanes[i];
45                 NestedDockingStatus status = pane.NestedDockingStatus;
46                 status.SetDisplayingStatus(true, status.PreviousPane, status.Alignment, status.Proportion);
47                 Items.Add(pane);
48             }
49 
50             foreach (DockPane pane in NestedPanes)
51                 if (pane.DockState != DockState || pane.IsHidden)
52                 {
53                     pane.Bounds = Rectangle.Empty;
54                     pane.SplitterBounds = Rectangle.Empty;
55                     Remove(pane);
56                 }
57 
58             CalculateBounds();
59 
60             foreach (DockPane pane in this)
61             {
62                 NestedDockingStatus status = pane.NestedDockingStatus;
63                 pane.Bounds = status.PaneBounds;
64                 pane.SplitterBounds = status.SplitterBounds;
65                 pane.SplitterAlignment = status.Alignment;
66             }
67         }
68 
Remove(DockPane pane)69         private void Remove(DockPane pane)
70         {
71             if (!Contains(pane))
72                 return;
73 
74             NestedDockingStatus statusPane = pane.NestedDockingStatus;
75             DockPane lastNestedPane = null;
76             for (int i=Count - 1; i> IndexOf(pane); i--)
77             {
78                 if (PatchController.EnableDisplayingPaneFix == true)
79                 {
80                     if (this[i].NestedDockingStatus.DisplayingPreviousPane == pane)
81                     {
82                         lastNestedPane = this[i];
83                         break;
84                     }
85                 }
86                 else
87                 {
88                     if (this[i].NestedDockingStatus.PreviousPane == pane)
89                     {
90                         lastNestedPane = this[i];
91                         break;
92                     }
93                 }
94             }
95 
96             if (lastNestedPane != null)
97             {
98                 int indexLastNestedPane = IndexOf(lastNestedPane);
99                 Items.Remove(lastNestedPane);
100                 Items[IndexOf(pane)] = lastNestedPane;
101                 NestedDockingStatus lastNestedDock = lastNestedPane.NestedDockingStatus;
102                 lastNestedDock.SetDisplayingStatus(true, statusPane.DisplayingPreviousPane, statusPane.DisplayingAlignment, statusPane.DisplayingProportion);
103                 for (int i=indexLastNestedPane - 1; i>IndexOf(lastNestedPane); i--)
104                 {
105                     NestedDockingStatus status = this[i].NestedDockingStatus;
106                     if (PatchController.EnableDisplayingPaneFix == true)
107                     {
108                         if (status.DisplayingPreviousPane == pane)
109                             status.SetDisplayingStatus(true, lastNestedPane, status.DisplayingAlignment, status.DisplayingProportion);
110                     }
111                     else
112                     {
113                         if (status.PreviousPane == pane)
114                             status.SetDisplayingStatus(true, lastNestedPane, status.DisplayingAlignment, status.DisplayingProportion);
115                     }
116                 }
117             }
118             else
119                 Items.Remove(pane);
120 
121             statusPane.SetDisplayingStatus(false, null, DockAlignment.Left, 0.5);
122         }
123 
CalculateBounds()124         private void CalculateBounds()
125         {
126             if (Count == 0)
127                 return;
128 
129             this[0].NestedDockingStatus.SetDisplayingBounds(Container.DisplayingRectangle, Container.DisplayingRectangle, Rectangle.Empty);
130 
131             for (int i=1; i<Count; i++)
132             {
133                 DockPane pane = this[i];
134                 NestedDockingStatus status = pane.NestedDockingStatus;
135                 DockPane prevPane = status.DisplayingPreviousPane;
136                 NestedDockingStatus statusPrev = prevPane.NestedDockingStatus;
137 
138                 Rectangle rect = statusPrev.PaneBounds;
139                 bool bVerticalSplitter = (status.DisplayingAlignment == DockAlignment.Left || status.DisplayingAlignment == DockAlignment.Right);
140 
141                 Rectangle rectThis = rect;
142                 Rectangle rectPrev = rect;
143                 Rectangle rectSplitter = rect;
144                 if (status.DisplayingAlignment == DockAlignment.Left)
145                 {
146                     rectThis.Width = (int)((double)rect.Width * status.DisplayingProportion) - (pane.DockPanel.Theme.Measures.SplitterSize / 2);
147                     rectSplitter.X = rectThis.X + rectThis.Width;
148                     rectSplitter.Width = pane.DockPanel.Theme.Measures.SplitterSize;
149                     rectPrev.X = rectSplitter.X + rectSplitter.Width;
150                     rectPrev.Width = rect.Width - rectThis.Width - rectSplitter.Width;
151                 }
152                 else if (status.DisplayingAlignment == DockAlignment.Right)
153                 {
154                     rectPrev.Width = (rect.Width - (int)((double)rect.Width * status.DisplayingProportion)) - (pane.DockPanel.Theme.Measures.SplitterSize / 2);
155                     rectSplitter.X = rectPrev.X + rectPrev.Width;
156                     rectSplitter.Width = pane.DockPanel.Theme.Measures.SplitterSize;
157                     rectThis.X = rectSplitter.X + rectSplitter.Width;
158                     rectThis.Width = rect.Width - rectPrev.Width - rectSplitter.Width;
159                 }
160                 else if (status.DisplayingAlignment == DockAlignment.Top)
161                 {
162                     rectThis.Height = (int)((double)rect.Height * status.DisplayingProportion) - (pane.DockPanel.Theme.Measures.SplitterSize / 2);
163                     rectSplitter.Y = rectThis.Y + rectThis.Height;
164                     rectSplitter.Height = pane.DockPanel.Theme.Measures.SplitterSize;
165                     rectPrev.Y = rectSplitter.Y + rectSplitter.Height;
166                     rectPrev.Height = rect.Height - rectThis.Height - rectSplitter.Height;
167                 }
168                 else if (status.DisplayingAlignment == DockAlignment.Bottom)
169                 {
170                     rectPrev.Height = (rect.Height - (int)((double)rect.Height * status.DisplayingProportion)) - (pane.DockPanel.Theme.Measures.SplitterSize / 2);
171                     rectSplitter.Y = rectPrev.Y + rectPrev.Height;
172                     rectSplitter.Height = pane.DockPanel.Theme.Measures.SplitterSize;
173                     rectThis.Y = rectSplitter.Y + rectSplitter.Height;
174                     rectThis.Height = rect.Height - rectPrev.Height - rectSplitter.Height;
175                 }
176                 else
177                     rectThis = Rectangle.Empty;
178 
179                 rectSplitter.Intersect(rect);
180                 rectThis.Intersect(rect);
181                 rectPrev.Intersect(rect);
182                 status.SetDisplayingBounds(rect, rectThis, rectSplitter);
183                 statusPrev.SetDisplayingBounds(statusPrev.LogicalBounds, rectPrev, statusPrev.SplitterBounds);
184             }
185         }
186     }
187 }
188