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