1 using System;
2 using System.Drawing;
3 using System.Windows.Forms;
4 using System.Drawing.Drawing2D;
5 
6 namespace WeifenLuo.WinFormsUI.Docking
7 {
8     /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/ClassDef/*'/>
9     internal class VS2003AutoHideStrip : AutoHideStripBase
10     {
11         private class TabVS2003 : Tab
12         {
TabVS2003(IDockContent content)13             internal TabVS2003(IDockContent content)
14                 : base(content)
15             {
16             }
17 
18             private int m_tabX = 0;
19             protected internal int TabX
20             {
21                 get { return m_tabX; }
22                 set { m_tabX = value; }
23             }
24 
25             private int m_tabWidth = 0;
26             protected internal int TabWidth
27             {
28                 get { return m_tabWidth; }
29                 set { m_tabWidth = value; }
30             }
31 
32         }
33 
34         private const int _ImageHeight = 16;
35         private const int _ImageWidth = 16;
36         private const int _ImageGapTop = 2;
37         private const int _ImageGapLeft = 4;
38         private const int _ImageGapRight = 4;
39         private const int _ImageGapBottom = 2;
40         private const int _TextGapLeft = 4;
41         private const int _TextGapRight = 10;
42         private const int _TabGapTop = 3;
43         private const int _TabGapLeft = 2;
44         private const int _TabGapBetween = 10;
45 
46         private static Matrix _matrixIdentity;
47         private static DockState[] _dockStates;
48 
49         #region Customizable Properties
50         private static StringFormat _stringFormatTabHorizontal = null;
51         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Property[@name="StringFormatTabHorizontal"]/*'/>
52         protected virtual StringFormat StringFormatTabHorizontal
53         {
54             get
55             {
56                 if (_stringFormatTabHorizontal == null)
57                 {
58                     _stringFormatTabHorizontal = new StringFormat();
59                     _stringFormatTabHorizontal.Alignment = StringAlignment.Near;
60                     _stringFormatTabHorizontal.LineAlignment = StringAlignment.Center;
61                     _stringFormatTabHorizontal.FormatFlags = StringFormatFlags.NoWrap;
62                 }
63                 return _stringFormatTabHorizontal;
64             }
65         }
66 
67         private static StringFormat _stringFormatTabVertical;
68         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Property[@name="StringFormatTabVertical"]/*'/>
69         protected virtual StringFormat StringFormatTabVertical
70         {
71             get
72             {
73                 if (_stringFormatTabVertical == null)
74                 {
75                     _stringFormatTabVertical = new StringFormat();
76                     _stringFormatTabVertical.Alignment = StringAlignment.Near;
77                     _stringFormatTabVertical.LineAlignment = StringAlignment.Center;
78                     _stringFormatTabVertical.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.DirectionVertical;
79                 }
80                 return _stringFormatTabVertical;
81             }
82         }
83 
84         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Property[@name="ImageHeight"]/*'/>
85         protected virtual int ImageHeight
86         {
87             get	{	return _ImageHeight;	}
88         }
89 
90         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Property[@name="ImageWidth"]/*'/>
91         protected virtual int ImageWidth
92         {
93             get	{	return _ImageWidth;	}
94         }
95 
96         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Property[@name="ImageGapTop"]/*'/>
97         protected virtual int ImageGapTop
98         {
99             get	{	return _ImageGapTop;	}
100         }
101 
102         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Property[@name="ImageGapLeft"]/*'/>
103         protected virtual int ImageGapLeft
104         {
105             get	{	return _ImageGapLeft;	}
106         }
107 
108         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Property[@name="ImageGapRight"]/*'/>
109         protected virtual int ImageGapRight
110         {
111             get	{	return _ImageGapRight;	}
112         }
113 
114         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Property[@name="ImageGapBottom"]/*'/>
115         protected virtual int ImageGapBottom
116         {
117             get	{	return _ImageGapBottom;	}
118         }
119 
120         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Property[@name="TextGapLeft"]/*'/>
121         protected virtual int TextGapLeft
122         {
123             get	{	return _TextGapLeft;	}
124         }
125 
126         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Property[@name="TextGapRight"]/*'/>
127         protected virtual int TextGapRight
128         {
129             get	{	return _TextGapRight;	}
130         }
131 
132         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Property[@name="TabGapTop"]/*'/>
133         protected virtual int TabGapTop
134         {
135             get	{	return _TabGapTop;	}
136         }
137 
138         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Property[@name="TabGapLeft"]/*'/>
139         protected virtual int TabGapLeft
140         {
141             get	{	return _TabGapLeft;	}
142         }
143 
144         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Property[@name="TabGapBetween"]/*'/>
145         protected virtual int TabGapBetween
146         {
147             get	{	return _TabGapBetween;	}
148         }
149 
150         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Property[@name="BrushTabBackground"]/*'/>
151         protected virtual Brush BrushTabBackground
152         {
153             get	{	return SystemBrushes.Control;	}
154         }
155 
156         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Property[@name="PenTabBorder"]/*'/>
157         protected virtual Pen PenTabBorder
158         {
159             get	{	return SystemPens.GrayText;	}
160         }
161 
162         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Property[@name="BrushTabText"]/*'/>
163         protected virtual Brush BrushTabText
164         {
165             get	{	return SystemBrushes.FromSystemColor(SystemColors.ControlDarkDark);	}
166         }
167         #endregion
168 
169         private Matrix MatrixIdentity
170         {
171             get	{	return _matrixIdentity;	}
172         }
173 
174         private DockState[] DockStates
175         {
176             get	{	return _dockStates;	}
177         }
178 
VS2003AutoHideStrip()179         static VS2003AutoHideStrip()
180         {
181             _matrixIdentity = new Matrix();
182 
183             _dockStates = new DockState[4];
184             _dockStates[0] = DockState.DockLeftAutoHide;
185             _dockStates[1] = DockState.DockRightAutoHide;
186             _dockStates[2] = DockState.DockTopAutoHide;
187             _dockStates[3] = DockState.DockBottomAutoHide;
188         }
189 
VS2003AutoHideStrip(DockPanel panel)190         public VS2003AutoHideStrip(DockPanel panel) : base(panel)
191         {
192             SetStyle(ControlStyles.ResizeRedraw, true);
193             SetStyle(ControlStyles.UserPaint, true);
194             SetStyle(ControlStyles.AllPaintingInWmPaint, true);
195             BackColor = Color.WhiteSmoke;
196         }
197 
198         /// <exclude/>
OnPaint(PaintEventArgs e)199         protected override void OnPaint(PaintEventArgs e)
200         {
201             base.OnPaint(e);
202             Graphics g = e.Graphics;
203             DrawTabStrip(g);
204         }
205 
206         /// <exclude/>
OnLayout(LayoutEventArgs levent)207         protected override void OnLayout(LayoutEventArgs levent)
208         {
209             CalculateTabs();
210             base.OnLayout (levent);
211         }
212 
DrawTabStrip(Graphics g)213         private void DrawTabStrip(Graphics g)
214         {
215             DrawTabStrip(g, DockState.DockTopAutoHide);
216             DrawTabStrip(g, DockState.DockBottomAutoHide);
217             DrawTabStrip(g, DockState.DockLeftAutoHide);
218             DrawTabStrip(g, DockState.DockRightAutoHide);
219         }
220 
DrawTabStrip(Graphics g, DockState dockState)221         private void DrawTabStrip(Graphics g, DockState dockState)
222         {
223             Rectangle rectTabStrip = GetLogicalTabStripRectangle(dockState);
224 
225             if (rectTabStrip.IsEmpty)
226                 return;
227 
228             Matrix matrixIdentity = g.Transform;
229             if (dockState == DockState.DockLeftAutoHide || dockState == DockState.DockRightAutoHide)
230             {
231                 Matrix matrixRotated = new Matrix();
232                 matrixRotated.RotateAt(90, new PointF((float)rectTabStrip.X + (float)rectTabStrip.Height / 2,
233                     (float)rectTabStrip.Y + (float)rectTabStrip.Height / 2));
234                 g.Transform = matrixRotated;
235             }
236 
237             foreach (Pane pane in GetPanes(dockState))
238             {
239                 foreach (TabVS2003 tab in pane.AutoHideTabs)
240                     DrawTab(g, tab);
241             }
242             g.Transform = matrixIdentity;
243         }
244 
CalculateTabs()245         private void CalculateTabs()
246         {
247             CalculateTabs(DockState.DockTopAutoHide);
248             CalculateTabs(DockState.DockBottomAutoHide);
249             CalculateTabs(DockState.DockLeftAutoHide);
250             CalculateTabs(DockState.DockRightAutoHide);
251         }
252 
CalculateTabs(DockState dockState)253         private void CalculateTabs(DockState dockState)
254         {
255             Rectangle rectTabStrip = GetLogicalTabStripRectangle(dockState);
256 
257             int imageHeight = rectTabStrip.Height - ImageGapTop - ImageGapBottom;
258             int imageWidth = ImageWidth;
259             if (imageHeight > ImageHeight)
260                 imageWidth = ImageWidth * (imageHeight/ImageHeight);
261 
262             using (Graphics g = CreateGraphics())
263             {
264                 int x = TabGapLeft + rectTabStrip.X;
265                 foreach (Pane pane in GetPanes(dockState))
266                 {
267                     int maxWidth = 0;
268                     foreach (TabVS2003 tab in pane.AutoHideTabs)
269                     {
270                         int width = imageWidth + ImageGapLeft + ImageGapRight +
271                             (int)g.MeasureString(tab.Content.DockHandler.TabText, Font).Width + 1 +
272                             TextGapLeft + TextGapRight;
273                         if (width > maxWidth)
274                             maxWidth = width;
275                     }
276 
277                     foreach (TabVS2003 tab in pane.AutoHideTabs)
278                     {
279                         tab.TabX = x;
280                         if (tab.Content == pane.DockPane.ActiveContent)
281                             tab.TabWidth = maxWidth;
282                         else
283                             tab.TabWidth = imageWidth + ImageGapLeft + ImageGapRight;
284                         x += tab.TabWidth;
285                     }
286                     x += TabGapBetween;
287                 }
288             }
289         }
290 
DrawTab(Graphics g, TabVS2003 tab)291         private void DrawTab(Graphics g, TabVS2003 tab)
292         {
293             Rectangle rectTab = GetTabRectangle(tab);
294             if (rectTab.IsEmpty)
295                 return;
296 
297             DockState dockState = tab.Content.DockHandler.DockState;
298             IDockContent content = tab.Content;
299 
300             OnBeginDrawTab(tab);
301 
302             Brush brushTabBackGround = BrushTabBackground;
303             Pen penTabBorder = PenTabBorder;
304             Brush brushTabText = BrushTabText;
305 
306             g.FillRectangle(brushTabBackGround, rectTab);
307 
308             g.DrawLine(penTabBorder, rectTab.Left, rectTab.Top, rectTab.Left, rectTab.Bottom);
309             g.DrawLine(penTabBorder, rectTab.Right, rectTab.Top, rectTab.Right, rectTab.Bottom);
310             if (dockState == DockState.DockTopAutoHide || dockState == DockState.DockRightAutoHide)
311                 g.DrawLine(penTabBorder, rectTab.Left, rectTab.Bottom, rectTab.Right, rectTab.Bottom);
312             else
313                 g.DrawLine(penTabBorder, rectTab.Left, rectTab.Top, rectTab.Right, rectTab.Top);
314 
315             // Set no rotate for drawing icon and text
316             Matrix matrixRotate = g.Transform;
317             g.Transform = MatrixIdentity;
318 
319             // Draw the icon
320             Rectangle rectImage = rectTab;
321             rectImage.X += ImageGapLeft;
322             rectImage.Y += ImageGapTop;
323             int imageHeight = rectTab.Height - ImageGapTop - ImageGapBottom;
324             int imageWidth = ImageWidth;
325             if (imageHeight > ImageHeight)
326                 imageWidth = ImageWidth * (imageHeight/ImageHeight);
327             rectImage.Height = imageHeight;
328             rectImage.Width = imageWidth;
329             rectImage = GetTransformedRectangle(dockState, rectImage);
330             g.DrawIcon(((Form)content).Icon, rectImage);
331 
332             // Draw the text
333             if (content == content.DockHandler.Pane.ActiveContent)
334             {
335                 Rectangle rectText = rectTab;
336                 rectText.X += ImageGapLeft + imageWidth + ImageGapRight + TextGapLeft;
337                 rectText.Width -= ImageGapLeft + imageWidth + ImageGapRight + TextGapLeft;
338                 rectText = GetTransformedRectangle(dockState, rectText);
339                 if (dockState == DockState.DockLeftAutoHide || dockState == DockState.DockRightAutoHide)
340                     g.DrawString(content.DockHandler.TabText, Font, brushTabText, rectText, StringFormatTabVertical);
341                 else
342                     g.DrawString(content.DockHandler.TabText, Font, brushTabText, rectText, StringFormatTabHorizontal);
343             }
344 
345             // Set rotate back
346             g.Transform = matrixRotate;
347 
348             OnEndDrawTab(tab);
349         }
350 
GetLogicalTabStripRectangle(DockState dockState)351         private Rectangle GetLogicalTabStripRectangle(DockState dockState)
352         {
353             return GetLogicalTabStripRectangle(dockState, false);
354         }
355 
GetLogicalTabStripRectangle(DockState dockState, bool transformed)356         private Rectangle GetLogicalTabStripRectangle(DockState dockState, bool transformed)
357         {
358             if (!DockHelper.IsDockStateAutoHide(dockState))
359                 return Rectangle.Empty;
360 
361             int leftPanes = GetPanes(DockState.DockLeftAutoHide).Count;
362             int rightPanes = GetPanes(DockState.DockRightAutoHide).Count;
363             int topPanes = GetPanes(DockState.DockTopAutoHide).Count;
364             int bottomPanes = GetPanes(DockState.DockBottomAutoHide).Count;
365 
366             int x, y, width, height;
367 
368             height = MeasureHeight();
369             if (dockState == DockState.DockLeftAutoHide && leftPanes > 0)
370             {
371                 x = 0;
372                 y = (topPanes == 0) ? 0 : height;
373                 width = Height - (topPanes == 0 ? 0 : height) - (bottomPanes == 0 ? 0 :height);
374             }
375             else if (dockState == DockState.DockRightAutoHide && rightPanes > 0)
376             {
377                 x = Width - height;
378                 if (leftPanes != 0 && x < height)
379                     x = height;
380                 y = (topPanes == 0) ? 0 : height;
381                 width = Height - (topPanes == 0 ? 0 : height) - (bottomPanes == 0 ? 0 :height);
382             }
383             else if (dockState == DockState.DockTopAutoHide && topPanes > 0)
384             {
385                 x = leftPanes == 0 ? 0 : height;
386                 y = 0;
387                 width = Width - (leftPanes == 0 ? 0 : height) - (rightPanes == 0 ? 0 : height);
388             }
389             else if (dockState == DockState.DockBottomAutoHide && bottomPanes > 0)
390             {
391                 x = leftPanes == 0 ? 0 : height;
392                 y = Height - height;
393                 if (topPanes != 0 && y < height)
394                     y = height;
395                 width = Width - (leftPanes == 0 ? 0 : height) - (rightPanes == 0 ? 0 : height);
396             }
397             else
398                 return Rectangle.Empty;
399 
400             if (width == 0 || height == 0)
401             {
402                 return Rectangle.Empty;
403             }
404 
405             var rect = new Rectangle(x, y, width, height);
406             return transformed ? GetTransformedRectangle(dockState, rect) : rect;
407         }
408 
GetTabRectangle(TabVS2003 tab)409         private Rectangle GetTabRectangle(TabVS2003 tab)
410         {
411             return GetTabRectangle(tab, false);
412         }
413 
GetTabRectangle(TabVS2003 tab, bool transformed)414         private Rectangle GetTabRectangle(TabVS2003 tab, bool transformed)
415         {
416             DockState dockState = tab.Content.DockHandler.DockState;
417             Rectangle rectTabStrip = GetLogicalTabStripRectangle(dockState);
418 
419             if (rectTabStrip.IsEmpty)
420                 return Rectangle.Empty;
421 
422             int x = tab.TabX;
423             int y = rectTabStrip.Y +
424                 (dockState == DockState.DockTopAutoHide || dockState == DockState.DockRightAutoHide ?
425                 0 : TabGapTop);
426             int width = tab.TabWidth;
427             int height = rectTabStrip.Height - TabGapTop;
428 
429             if (!transformed)
430                 return new Rectangle(x, y, width, height);
431             else
432                 return GetTransformedRectangle(dockState, new Rectangle(x, y, width, height));
433         }
434 
GetTransformedRectangle(DockState dockState, Rectangle rect)435         private Rectangle GetTransformedRectangle(DockState dockState, Rectangle rect)
436         {
437             if (dockState != DockState.DockLeftAutoHide && dockState != DockState.DockRightAutoHide)
438                 return rect;
439 
440             PointF[] pts = new PointF[1];
441             // the center of the rectangle
442             pts[0].X = (float)rect.X + (float)rect.Width / 2;
443             pts[0].Y = (float)rect.Y + (float)rect.Height / 2;
444             Rectangle rectTabStrip = GetLogicalTabStripRectangle(dockState);
445             using (Matrix matrix = new Matrix())
446             {
447                 matrix.RotateAt(90, new PointF((float)rectTabStrip.X + (float)rectTabStrip.Height / 2,
448                                                (float)rectTabStrip.Y + (float)rectTabStrip.Height / 2));
449                 matrix.TransformPoints(pts);
450             }
451 
452             return new Rectangle((int)(pts[0].X - (float)rect.Height / 2 + .5F),
453                 (int)(pts[0].Y - (float)rect.Width / 2 + .5F),
454                 rect.Height, rect.Width);
455         }
456 
457         /// <exclude />
HitTest(Point point)458         protected override IDockContent HitTest(Point point)
459         {
460             foreach(DockState state in DockStates)
461             {
462                 Rectangle rectTabStrip = GetLogicalTabStripRectangle(state, true);
463                 if (!rectTabStrip.Contains(point))
464                     continue;
465 
466                 foreach(Pane pane in GetPanes(state))
467                 {
468                     foreach(TabVS2003 tab in pane.AutoHideTabs)
469                     {
470                         Rectangle rectTab = GetTabRectangle(tab, true);
471                         rectTab.Intersect(rectTabStrip);
472                         if (rectTab.Contains(point))
473                             return tab.Content;
474                     }
475                 }
476             }
477 
478             return null;
479         }
480 
GetTabBounds(Tab tab)481         protected override Rectangle GetTabBounds(Tab tab)
482         {
483             return GetTabRectangle((TabVS2003)tab, true);
484         }
485 
486         /// <exclude/>
MeasureHeight()487         protected override int MeasureHeight()
488         {
489             return Math.Max(ImageGapBottom +
490                 ImageGapTop + ImageHeight,
491                 Font.Height) + TabGapTop;
492         }
493 
494         /// <exclude/>
OnRefreshChanges()495         protected override void OnRefreshChanges()
496         {
497             CalculateTabs();
498             Invalidate();
499         }
500 
CreateTab(IDockContent content)501         protected override AutoHideStripBase.Tab CreateTab(IDockContent content)
502         {
503             return new TabVS2003(content);
504         }
505 
506         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Method[@name="OnBeginDrawTab(AutoHideTab)"]/*'/>
OnBeginDrawTab(Tab tab)507         protected virtual void OnBeginDrawTab(Tab tab)
508         {
509         }
510 
511         /// <include file='CodeDoc/AutoHideStripVS2003.xml' path='//CodeDoc/Class[@name="AutoHideStripVS2003"]/Method[@name="OnEndDrawTab(AutoHideTab)"]/*'/>
OnEndDrawTab(Tab tab)512         protected virtual void OnEndDrawTab(Tab tab)
513         {
514         }
515     }
516 }
517