1 using System.Windows.Forms;
2 using System.Drawing;
3 using System.ComponentModel;
4 
5 namespace WeifenLuo.WinFormsUI.Docking
6 {
7     /// <summary>
8     /// Dock window base class.
9     /// </summary>
10     [ToolboxItem(false)]
11     public partial class DockWindow : Panel, INestedPanesContainer, ISplitterHost
12     {
13         private DockPanel m_dockPanel;
14         private DockState m_dockState;
15         private SplitterBase m_splitter;
16         private NestedPaneCollection m_nestedPanes;
17 
DockWindow(DockPanel dockPanel, DockState dockState)18         protected internal DockWindow(DockPanel dockPanel, DockState dockState)
19         {
20             m_nestedPanes = new NestedPaneCollection(this);
21             m_dockPanel = dockPanel;
22             m_dockState = dockState;
23             Visible = false;
24 
25             SuspendLayout();
26 
27             if (DockState == DockState.DockLeft || DockState == DockState.DockRight ||
28                 DockState == DockState.DockTop || DockState == DockState.DockBottom)
29             {
30                 m_splitter = DockPanel.Theme.Extender.WindowSplitterControlFactory.CreateSplitterControl(this);
31                 Controls.Add(m_splitter);
32             }
33 
34             if (DockState == DockState.DockLeft)
35             {
36                 Dock = DockStyle.Left;
37                 m_splitter.Dock = DockStyle.Right;
38             }
39             else if (DockState == DockState.DockRight)
40             {
41                 Dock = DockStyle.Right;
42                 m_splitter.Dock = DockStyle.Left;
43             }
44             else if (DockState == DockState.DockTop)
45             {
46                 Dock = DockStyle.Top;
47                 m_splitter.Dock = DockStyle.Bottom;
48             }
49             else if (DockState == DockState.DockBottom)
50             {
51                 Dock = DockStyle.Bottom;
52                 m_splitter.Dock = DockStyle.Top;
53             }
54             else if (DockState == DockState.Document)
55             {
56                 Dock = DockStyle.Fill;
57             }
58 
59             ResumeLayout();
60         }
61 
62         public bool IsDockWindow
63         {
64             get { return true; }
65         }
66 
67         public VisibleNestedPaneCollection VisibleNestedPanes
68         {
69             get	{	return NestedPanes.VisibleNestedPanes;	}
70         }
71 
72         public NestedPaneCollection NestedPanes
73         {
74             get	{	return m_nestedPanes;	}
75         }
76 
77         public DockPanel DockPanel
78         {
79             get	{	return m_dockPanel;	}
80         }
81 
82         public DockState DockState
83         {
84             get	{	return m_dockState;	}
85         }
86 
87         public bool IsFloat
88         {
89             get	{	return DockState == DockState.Float;	}
90         }
91 
92         internal DockPane DefaultPane
93         {
94             get	{	return VisibleNestedPanes.Count == 0 ? null : VisibleNestedPanes[0];	}
95         }
96 
97         public virtual Rectangle DisplayingRectangle
98         {
99             get
100             {
101                 Rectangle rect = ClientRectangle;
102                 // if DockWindow is document, exclude the border
103                 if (DockState == DockState.Document)
104                 {
105                     rect.X += 1;
106                     rect.Y += 1;
107                     rect.Width -= 2;
108                     rect.Height -= 2;
109                 }
110                 // exclude the splitter
111                 else if (DockState == DockState.DockLeft)
112                     rect.Width -= DockPanel.Theme.Measures.SplitterSize;
113                 else if (DockState == DockState.DockRight)
114                 {
115                     rect.X += DockPanel.Theme.Measures.SplitterSize;
116                     rect.Width -= DockPanel.Theme.Measures.SplitterSize;
117                 }
118                 else if (DockState == DockState.DockTop)
119                     rect.Height -= DockPanel.Theme.Measures.SplitterSize;
120                 else if (DockState == DockState.DockBottom)
121                 {
122                     rect.Y += DockPanel.Theme.Measures.SplitterSize;
123                     rect.Height -= DockPanel.Theme.Measures.SplitterSize;
124                 }
125 
126                 return rect;
127             }
128         }
129 
OnLayout(LayoutEventArgs levent)130         protected override void OnLayout(LayoutEventArgs levent)
131         {
132             VisibleNestedPanes.Refresh();
133             if (VisibleNestedPanes.Count == 0)
134             {
135                 if (Visible)
136                     Visible = false;
137             }
138             else if (!Visible)
139             {
140                 Visible = true;
141                 VisibleNestedPanes.Refresh();
142             }
143 
144             base.OnLayout (levent);
145         }
146 
147         #region ISplitterDragSource Members
148 
ISplitterDragSource.BeginDrag(Rectangle rectSplitter)149         void ISplitterDragSource.BeginDrag(Rectangle rectSplitter)
150         {
151         }
152 
ISplitterDragSource.EndDrag()153         void ISplitterDragSource.EndDrag()
154         {
155         }
156 
157         bool ISplitterDragSource.IsVertical
158         {
159             get { return (DockState == DockState.DockLeft || DockState == DockState.DockRight); }
160         }
161 
162         Rectangle ISplitterDragSource.DragLimitBounds
163         {
164             get
165             {
166                 Rectangle rectLimit = DockPanel.DockArea;
167                 Point location;
168                 if ((Control.ModifierKeys & Keys.Shift) == 0)
169                     location = Location;
170                 else
171                     location = DockPanel.DockArea.Location;
172 
173                 if (((ISplitterDragSource)this).IsVertical)
174                 {
175                     rectLimit.X += MeasurePane.MinSize;
176                     rectLimit.Width -= 2 * MeasurePane.MinSize;
177                     rectLimit.Y = location.Y;
178                     if ((Control.ModifierKeys & Keys.Shift) == 0)
179                         rectLimit.Height = Height;
180                 }
181                 else
182                 {
183                     rectLimit.Y += MeasurePane.MinSize;
184                     rectLimit.Height -= 2 * MeasurePane.MinSize;
185                     rectLimit.X = location.X;
186                     if ((Control.ModifierKeys & Keys.Shift) == 0)
187                         rectLimit.Width = Width;
188                 }
189 
190                 return DockPanel.RectangleToScreen(rectLimit);
191             }
192         }
193 
ISplitterDragSource.MoveSplitter(int offset)194         void ISplitterDragSource.MoveSplitter(int offset)
195         {
196             if ((Control.ModifierKeys & Keys.Shift) != 0)
197                 SendToBack();
198 
199             Rectangle rectDockArea = DockPanel.DockArea;
200             if (DockState == DockState.DockLeft && rectDockArea.Width > 0)
201             {
202                 if (DockPanel.DockLeftPortion > 1)
203                     DockPanel.DockLeftPortion = Width + offset;
204                 else
205                     DockPanel.DockLeftPortion += ((double)offset) / (double)rectDockArea.Width;
206             }
207             else if (DockState == DockState.DockRight && rectDockArea.Width > 0)
208             {
209                 if (DockPanel.DockRightPortion > 1)
210                     DockPanel.DockRightPortion = Width - offset;
211                 else
212                     DockPanel.DockRightPortion -= ((double)offset) / (double)rectDockArea.Width;
213             }
214             else if (DockState == DockState.DockBottom && rectDockArea.Height > 0)
215             {
216                 if (DockPanel.DockBottomPortion > 1)
217                     DockPanel.DockBottomPortion = Height - offset;
218                 else
219                     DockPanel.DockBottomPortion -= ((double)offset) / (double)rectDockArea.Height;
220             }
221             else if (DockState == DockState.DockTop && rectDockArea.Height > 0)
222             {
223                 if (DockPanel.DockTopPortion > 1)
224                     DockPanel.DockTopPortion = Height + offset;
225                 else
226                     DockPanel.DockTopPortion += ((double)offset) / (double)rectDockArea.Height;
227             }
228         }
229 
230         #region IDragSource Members
231 
232         Control IDragSource.DragControl
233         {
234             get { return this; }
235         }
236 
237         #endregion
238         #endregion
239     }
240 
241     /// <summary>
242     /// Dock window of Visual Studio 2003/2005 theme.
243     /// </summary>
244     [ToolboxItem(false)]
245     internal class DefaultDockWindow : DockWindow
246     {
DefaultDockWindow(DockPanel dockPanel, DockState dockState)247         internal DefaultDockWindow(DockPanel dockPanel, DockState dockState) : base(dockPanel, dockState)
248         {
249         }
250 
OnPaint(PaintEventArgs e)251         protected override void OnPaint(PaintEventArgs e)
252         {
253             // if DockWindow is document, draw the border
254             if (DockState == DockState.Document)
255                 e.Graphics.DrawRectangle(SystemPens.ControlDark, ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width - 1, ClientRectangle.Height - 1);
256 
257             base.OnPaint(e);
258         }
259     }
260 }
261