1 using System; 2 using System.Drawing; 3 using System.Drawing.Drawing2D; 4 using System.Windows.Forms; 5 using System.ComponentModel; 6 using WeifenLuo.WinFormsUI.Docking; 7 using WeifenLuo.WinFormsUI.ThemeVS2012; 8 9 namespace WeifenLuo.WinFormsUI.ThemeVS2013 10 { 11 internal class VS2013DockPaneStrip : DockPaneStripBase 12 { 13 private class TabVS2013 : Tab 14 { TabVS2013(IDockContent content)15 public TabVS2013(IDockContent content) 16 : base(content) 17 { 18 } 19 20 private int m_tabX; 21 public int TabX 22 { 23 get { return m_tabX; } 24 set { m_tabX = value; } 25 } 26 27 private int m_tabWidth; 28 public int TabWidth 29 { 30 get { return m_tabWidth; } 31 set { m_tabWidth = value; } 32 } 33 34 private int m_maxWidth; 35 public int MaxWidth 36 { 37 get { return m_maxWidth; } 38 set { m_maxWidth = value; } 39 } 40 41 private bool m_flag; 42 protected internal bool Flag 43 { 44 get { return m_flag; } 45 set { m_flag = value; } 46 } 47 } 48 CreateTab(IDockContent content)49 protected override Tab CreateTab(IDockContent content) 50 { 51 return new TabVS2013(content); 52 } 53 54 private sealed class InertButton : InertButtonBase 55 { 56 private Bitmap _hovered, _normal, _pressed; 57 InertButton(Bitmap hovered, Bitmap normal, Bitmap pressed)58 public InertButton(Bitmap hovered, Bitmap normal, Bitmap pressed) 59 : base() 60 { 61 _hovered = hovered; 62 _normal = normal; 63 _pressed = pressed; 64 } 65 66 public override Bitmap Image 67 { 68 get { return _normal; } 69 } 70 71 public override Bitmap HoverImage 72 { 73 get { return _hovered; } 74 } 75 76 public override Bitmap PressImage 77 { 78 get { return _pressed; } 79 } 80 } 81 82 #region Constants 83 84 private const int _ToolWindowStripGapTop = 0; 85 private const int _ToolWindowStripGapBottom = 0; 86 private const int _ToolWindowStripGapLeft = 0; 87 private const int _ToolWindowStripGapRight = 0; 88 private const int _ToolWindowImageHeight = 16; 89 private const int _ToolWindowImageWidth = 0;//16; 90 private const int _ToolWindowImageGapTop = 3; 91 private const int _ToolWindowImageGapBottom = 1; 92 private const int _ToolWindowImageGapLeft = 2; 93 private const int _ToolWindowImageGapRight = 0; 94 private const int _ToolWindowTextGapRight = 3; 95 private const int _ToolWindowTabSeperatorGapTop = 3; 96 private const int _ToolWindowTabSeperatorGapBottom = 3; 97 98 private const int _DocumentStripGapTop = 0; 99 private const int _DocumentStripGapBottom = 1; 100 private const int _DocumentTabMaxWidth = 200; 101 private const int _DocumentButtonGapTop = 3; 102 private const int _DocumentButtonGapBottom = 3; 103 private const int _DocumentButtonGapBetween = 0; 104 private const int _DocumentButtonGapRight = 3; 105 private const int _DocumentTabGapTop = 0;//3; 106 private const int _DocumentTabGapLeft = 0;//3; 107 private const int _DocumentTabGapRight = 0;//3; 108 private const int _DocumentIconGapBottom = 2;//2; 109 private const int _DocumentIconGapLeft = 8; 110 private const int _DocumentIconGapRight = 0; 111 private const int _DocumentIconHeight = 16; 112 private const int _DocumentIconWidth = 16; 113 private const int _DocumentTextGapRight = 6; 114 115 #endregion 116 117 #region Members 118 119 private ContextMenuStrip m_selectMenu; 120 private InertButton m_buttonOverflow; 121 private InertButton m_buttonWindowList; 122 private IContainer m_components; 123 private ToolTip m_toolTip; 124 private Font m_font; 125 private Font m_boldFont; 126 private int m_startDisplayingTab = 0; 127 private int m_endDisplayingTab = 0; 128 private int m_firstDisplayingTab = 0; 129 private bool m_documentTabsOverflow = false; 130 private static string m_toolTipSelect; 131 private Rectangle _activeClose; 132 private int _selectMenuMargin = 5; 133 private bool m_suspendDrag = false; 134 #endregion 135 136 #region Properties 137 138 private Rectangle TabStripRectangle 139 { 140 get 141 { 142 if (Appearance == DockPane.AppearanceStyle.Document) 143 return TabStripRectangle_Document; 144 else 145 return TabStripRectangle_ToolWindow; 146 } 147 } 148 149 private Rectangle TabStripRectangle_ToolWindow 150 { 151 get 152 { 153 Rectangle rect = ClientRectangle; 154 return new Rectangle(rect.X, rect.Top + ToolWindowStripGapTop, rect.Width, rect.Height - ToolWindowStripGapTop - ToolWindowStripGapBottom); 155 } 156 } 157 158 private Rectangle TabStripRectangle_Document 159 { 160 get 161 { 162 Rectangle rect = ClientRectangle; 163 return new Rectangle(rect.X, rect.Top + DocumentStripGapTop, rect.Width, rect.Height + DocumentStripGapTop - DocumentStripGapBottom); 164 } 165 } 166 167 private Rectangle TabsRectangle 168 { 169 get 170 { 171 if (Appearance == DockPane.AppearanceStyle.ToolWindow) 172 return TabStripRectangle; 173 174 Rectangle rectWindow = TabStripRectangle; 175 int x = rectWindow.X; 176 int y = rectWindow.Y; 177 int width = rectWindow.Width; 178 int height = rectWindow.Height; 179 180 x += DocumentTabGapLeft; 181 width -= DocumentTabGapLeft + 182 DocumentTabGapRight + 183 DocumentButtonGapRight + 184 ButtonOverflow.Width + 185 ButtonWindowList.Width + 186 2 * DocumentButtonGapBetween; 187 188 return new Rectangle(x, y, width, height); 189 } 190 } 191 192 private ContextMenuStrip SelectMenu 193 { 194 get { return m_selectMenu; } 195 } 196 197 public int SelectMenuMargin 198 { 199 get { return _selectMenuMargin; } 200 set { _selectMenuMargin = value; } 201 } 202 203 private InertButton ButtonOverflow 204 { 205 get 206 { 207 if (m_buttonOverflow == null) 208 { 209 m_buttonOverflow = new InertButton( 210 DockPane.DockPanel.Theme.ImageService.DockPaneHover_OptionOverflow, 211 DockPane.DockPanel.Theme.ImageService.DockPane_OptionOverflow, 212 DockPane.DockPanel.Theme.ImageService.DockPanePress_OptionOverflow); 213 m_buttonOverflow.Click += new EventHandler(WindowList_Click); 214 Controls.Add(m_buttonOverflow); 215 } 216 217 return m_buttonOverflow; 218 } 219 } 220 221 private InertButton ButtonWindowList 222 { 223 get 224 { 225 if (m_buttonWindowList == null) 226 { 227 m_buttonWindowList = new InertButton( 228 DockPane.DockPanel.Theme.ImageService.DockPaneHover_List, 229 DockPane.DockPanel.Theme.ImageService.DockPane_List, 230 DockPane.DockPanel.Theme.ImageService.DockPanePress_List); 231 m_buttonWindowList.Click += new EventHandler(WindowList_Click); 232 Controls.Add(m_buttonWindowList); 233 } 234 235 return m_buttonWindowList; 236 } 237 } 238 239 private static GraphicsPath GraphicsPath 240 { 241 get { return VS2012AutoHideStrip.GraphicsPath; } 242 } 243 244 private IContainer Components 245 { 246 get { return m_components; } 247 } 248 249 public Font TextFont 250 { 251 get { return DockPane.DockPanel.Theme.Skin.DockPaneStripSkin.TextFont; } 252 } 253 254 private Font BoldFont 255 { 256 get 257 { 258 if (IsDisposed) 259 return null; 260 261 if (m_boldFont == null) 262 { 263 m_font = TextFont; 264 m_boldFont = new Font(TextFont, FontStyle.Bold); 265 } 266 else if (m_font != TextFont) 267 { 268 m_boldFont.Dispose(); 269 m_font = TextFont; 270 m_boldFont = new Font(TextFont, FontStyle.Bold); 271 } 272 273 return m_boldFont; 274 } 275 } 276 277 private int StartDisplayingTab 278 { 279 get { return m_startDisplayingTab; } 280 set 281 { 282 m_startDisplayingTab = value; 283 Invalidate(); 284 } 285 } 286 287 private int EndDisplayingTab 288 { 289 get { return m_endDisplayingTab; } 290 set { m_endDisplayingTab = value; } 291 } 292 293 private int FirstDisplayingTab 294 { 295 get { return m_firstDisplayingTab; } 296 set { m_firstDisplayingTab = value; } 297 } 298 299 private bool DocumentTabsOverflow 300 { 301 set 302 { 303 if (m_documentTabsOverflow == value) 304 return; 305 306 m_documentTabsOverflow = value; 307 SetInertButtons(); 308 } 309 } 310 311 #region Customizable Properties 312 313 private static int ToolWindowStripGapTop 314 { 315 get { return _ToolWindowStripGapTop; } 316 } 317 318 private static int ToolWindowStripGapBottom 319 { 320 get { return _ToolWindowStripGapBottom; } 321 } 322 323 private static int ToolWindowStripGapLeft 324 { 325 get { return _ToolWindowStripGapLeft; } 326 } 327 328 private static int ToolWindowStripGapRight 329 { 330 get { return _ToolWindowStripGapRight; } 331 } 332 333 private static int ToolWindowImageHeight 334 { 335 get { return _ToolWindowImageHeight; } 336 } 337 338 private static int ToolWindowImageWidth 339 { 340 get { return _ToolWindowImageWidth; } 341 } 342 343 private static int ToolWindowImageGapTop 344 { 345 get { return _ToolWindowImageGapTop; } 346 } 347 348 private static int ToolWindowImageGapBottom 349 { 350 get { return _ToolWindowImageGapBottom; } 351 } 352 353 private static int ToolWindowImageGapLeft 354 { 355 get { return _ToolWindowImageGapLeft; } 356 } 357 358 private static int ToolWindowImageGapRight 359 { 360 get { return _ToolWindowImageGapRight; } 361 } 362 363 private static int ToolWindowTextGapRight 364 { 365 get { return _ToolWindowTextGapRight; } 366 } 367 368 private static int ToolWindowTabSeperatorGapTop 369 { 370 get { return _ToolWindowTabSeperatorGapTop; } 371 } 372 373 private static int ToolWindowTabSeperatorGapBottom 374 { 375 get { return _ToolWindowTabSeperatorGapBottom; } 376 } 377 378 private static string ToolTipSelect 379 { 380 get 381 { 382 if (m_toolTipSelect == null) 383 m_toolTipSelect = Strings.DockPaneStrip_ToolTipWindowList; 384 return m_toolTipSelect; 385 } 386 } 387 388 private TextFormatFlags ToolWindowTextFormat 389 { 390 get 391 { 392 TextFormatFlags textFormat = TextFormatFlags.EndEllipsis | 393 TextFormatFlags.HorizontalCenter | 394 TextFormatFlags.SingleLine | 395 TextFormatFlags.VerticalCenter; 396 if (RightToLeft == RightToLeft.Yes) 397 return textFormat | TextFormatFlags.RightToLeft | TextFormatFlags.Right; 398 else 399 return textFormat; 400 } 401 } 402 403 private static int DocumentStripGapTop 404 { 405 get { return _DocumentStripGapTop; } 406 } 407 408 private static int DocumentStripGapBottom 409 { 410 get { return _DocumentStripGapBottom; } 411 } 412 413 private TextFormatFlags DocumentTextFormat 414 { 415 get 416 { 417 TextFormatFlags textFormat = TextFormatFlags.EndEllipsis | 418 TextFormatFlags.SingleLine | 419 TextFormatFlags.VerticalCenter | 420 TextFormatFlags.HorizontalCenter; 421 if (RightToLeft == RightToLeft.Yes) 422 return textFormat | TextFormatFlags.RightToLeft; 423 else 424 return textFormat; 425 } 426 } 427 428 private static int DocumentTabMaxWidth 429 { 430 get { return _DocumentTabMaxWidth; } 431 } 432 433 private static int DocumentButtonGapTop 434 { 435 get { return _DocumentButtonGapTop; } 436 } 437 438 private static int DocumentButtonGapBottom 439 { 440 get { return _DocumentButtonGapBottom; } 441 } 442 443 private static int DocumentButtonGapBetween 444 { 445 get { return _DocumentButtonGapBetween; } 446 } 447 448 private static int DocumentButtonGapRight 449 { 450 get { return _DocumentButtonGapRight; } 451 } 452 453 private static int DocumentTabGapTop 454 { 455 get { return _DocumentTabGapTop; } 456 } 457 458 private static int DocumentTabGapLeft 459 { 460 get { return _DocumentTabGapLeft; } 461 } 462 463 private static int DocumentTabGapRight 464 { 465 get { return _DocumentTabGapRight; } 466 } 467 468 private static int DocumentIconGapBottom 469 { 470 get { return _DocumentIconGapBottom; } 471 } 472 473 private static int DocumentIconGapLeft 474 { 475 get { return _DocumentIconGapLeft; } 476 } 477 478 private static int DocumentIconGapRight 479 { 480 get { return _DocumentIconGapRight; } 481 } 482 483 private static int DocumentIconWidth 484 { 485 get { return _DocumentIconWidth; } 486 } 487 488 private static int DocumentIconHeight 489 { 490 get { return _DocumentIconHeight; } 491 } 492 493 private static int DocumentTextGapRight 494 { 495 get { return _DocumentTextGapRight; } 496 } 497 498 #endregion 499 500 #endregion 501 VS2013DockPaneStrip(DockPane pane)502 public VS2013DockPaneStrip(DockPane pane) 503 : base(pane) 504 { 505 SetStyle(ControlStyles.ResizeRedraw | 506 ControlStyles.UserPaint | 507 ControlStyles.AllPaintingInWmPaint | 508 ControlStyles.OptimizedDoubleBuffer, true); 509 510 SuspendLayout(); 511 512 m_components = new Container(); 513 m_toolTip = new ToolTip(Components); 514 m_selectMenu = new ContextMenuStrip(Components); 515 pane.DockPanel.Theme.ApplyTo(m_selectMenu); 516 517 ResumeLayout(); 518 } 519 Dispose(bool disposing)520 protected override void Dispose(bool disposing) 521 { 522 if (disposing) 523 { 524 Components.Dispose(); 525 if (m_boldFont != null) 526 { 527 m_boldFont.Dispose(); 528 m_boldFont = null; 529 } 530 } 531 base.Dispose(disposing); 532 } 533 MeasureHeight()534 protected override int MeasureHeight() 535 { 536 if (Appearance == DockPane.AppearanceStyle.ToolWindow) 537 return MeasureHeight_ToolWindow(); 538 else 539 return MeasureHeight_Document(); 540 } 541 MeasureHeight_ToolWindow()542 private int MeasureHeight_ToolWindow() 543 { 544 if (DockPane.IsAutoHide || Tabs.Count <= 1) 545 return 0; 546 547 int height = Math.Max(TextFont.Height + (PatchController.EnableHighDpi == true ? DocumentIconGapBottom : 0), 548 ToolWindowImageHeight + ToolWindowImageGapTop + ToolWindowImageGapBottom) 549 + ToolWindowStripGapTop + ToolWindowStripGapBottom; 550 551 return height; 552 } 553 MeasureHeight_Document()554 private int MeasureHeight_Document() 555 { 556 int height = Math.Max(TextFont.Height + DocumentTabGapTop + (PatchController.EnableHighDpi == true ? DocumentIconGapBottom : 0), 557 ButtonOverflow.Height + DocumentButtonGapTop + DocumentButtonGapBottom) 558 + DocumentStripGapBottom + DocumentStripGapTop; 559 560 return height; 561 } 562 OnPaint(PaintEventArgs e)563 protected override void OnPaint(PaintEventArgs e) 564 { 565 base.OnPaint(e); 566 CalculateTabs(); 567 if (Appearance == DockPane.AppearanceStyle.Document && DockPane.ActiveContent != null) 568 { 569 if (EnsureDocumentTabVisible(DockPane.ActiveContent, false)) 570 CalculateTabs(); 571 } 572 573 DrawTabStrip(e.Graphics); 574 } 575 OnRefreshChanges()576 protected override void OnRefreshChanges() 577 { 578 SetInertButtons(); 579 Invalidate(); 580 } 581 GetOutline(int index)582 public override GraphicsPath GetOutline(int index) 583 { 584 if (Appearance == DockPane.AppearanceStyle.Document) 585 return GetOutline_Document(index); 586 else 587 return GetOutline_ToolWindow(index); 588 } 589 GetOutline_Document(int index)590 private GraphicsPath GetOutline_Document(int index) 591 { 592 Rectangle rectTab = Tabs[index].Rectangle.Value; 593 rectTab.X -= rectTab.Height / 2; 594 rectTab.Intersect(TabsRectangle); 595 rectTab = RectangleToScreen(DrawHelper.RtlTransform(this, rectTab)); 596 Rectangle rectPaneClient = DockPane.RectangleToScreen(DockPane.ClientRectangle); 597 598 GraphicsPath path = new GraphicsPath(); 599 GraphicsPath pathTab = GetTabOutline_Document(Tabs[index], true, true, true); 600 path.AddPath(pathTab, true); 601 602 if (DockPane.DockPanel.DocumentTabStripLocation == DocumentTabStripLocation.Bottom) 603 { 604 path.AddLine(rectTab.Right, rectTab.Top, rectPaneClient.Right, rectTab.Top); 605 path.AddLine(rectPaneClient.Right, rectTab.Top, rectPaneClient.Right, rectPaneClient.Top); 606 path.AddLine(rectPaneClient.Right, rectPaneClient.Top, rectPaneClient.Left, rectPaneClient.Top); 607 path.AddLine(rectPaneClient.Left, rectPaneClient.Top, rectPaneClient.Left, rectTab.Top); 608 path.AddLine(rectPaneClient.Left, rectTab.Top, rectTab.Right, rectTab.Top); 609 } 610 else 611 { 612 path.AddLine(rectTab.Right, rectTab.Bottom, rectPaneClient.Right, rectTab.Bottom); 613 path.AddLine(rectPaneClient.Right, rectTab.Bottom, rectPaneClient.Right, rectPaneClient.Bottom); 614 path.AddLine(rectPaneClient.Right, rectPaneClient.Bottom, rectPaneClient.Left, rectPaneClient.Bottom); 615 path.AddLine(rectPaneClient.Left, rectPaneClient.Bottom, rectPaneClient.Left, rectTab.Bottom); 616 path.AddLine(rectPaneClient.Left, rectTab.Bottom, rectTab.Right, rectTab.Bottom); 617 } 618 return path; 619 } 620 GetOutline_ToolWindow(int index)621 private GraphicsPath GetOutline_ToolWindow(int index) 622 { 623 Rectangle rectTab = Tabs[index].Rectangle.Value; 624 rectTab.Intersect(TabsRectangle); 625 rectTab = RectangleToScreen(DrawHelper.RtlTransform(this, rectTab)); 626 Rectangle rectPaneClient = DockPane.RectangleToScreen(DockPane.ClientRectangle); 627 628 GraphicsPath path = new GraphicsPath(); 629 GraphicsPath pathTab = GetTabOutline(Tabs[index], true, true); 630 path.AddPath(pathTab, true); 631 path.AddLine(rectTab.Left, rectTab.Top, rectPaneClient.Left, rectTab.Top); 632 path.AddLine(rectPaneClient.Left, rectTab.Top, rectPaneClient.Left, rectPaneClient.Top); 633 path.AddLine(rectPaneClient.Left, rectPaneClient.Top, rectPaneClient.Right, rectPaneClient.Top); 634 path.AddLine(rectPaneClient.Right, rectPaneClient.Top, rectPaneClient.Right, rectTab.Top); 635 path.AddLine(rectPaneClient.Right, rectTab.Top, rectTab.Right, rectTab.Top); 636 return path; 637 } 638 CalculateTabs()639 private void CalculateTabs() 640 { 641 if (Appearance == DockPane.AppearanceStyle.ToolWindow) 642 CalculateTabs_ToolWindow(); 643 else 644 CalculateTabs_Document(); 645 } 646 CalculateTabs_ToolWindow()647 private void CalculateTabs_ToolWindow() 648 { 649 if (Tabs.Count <= 1 || DockPane.IsAutoHide) 650 return; 651 652 Rectangle rectTabStrip = TabStripRectangle; 653 654 // Calculate tab widths 655 int countTabs = Tabs.Count; 656 foreach (TabVS2013 tab in Tabs) 657 { 658 tab.MaxWidth = GetMaxTabWidth(Tabs.IndexOf(tab)); 659 tab.Flag = false; 660 } 661 662 // Set tab whose max width less than average width 663 bool anyWidthWithinAverage = true; 664 int totalWidth = rectTabStrip.Width - ToolWindowStripGapLeft - ToolWindowStripGapRight; 665 int totalAllocatedWidth = 0; 666 int averageWidth = totalWidth / countTabs; 667 int remainedTabs = countTabs; 668 for (anyWidthWithinAverage = true; anyWidthWithinAverage && remainedTabs > 0; ) 669 { 670 anyWidthWithinAverage = false; 671 foreach (TabVS2013 tab in Tabs) 672 { 673 if (tab.Flag) 674 continue; 675 676 if (tab.MaxWidth <= averageWidth) 677 { 678 tab.Flag = true; 679 tab.TabWidth = tab.MaxWidth; 680 totalAllocatedWidth += tab.TabWidth; 681 anyWidthWithinAverage = true; 682 remainedTabs--; 683 } 684 } 685 if (remainedTabs != 0) 686 averageWidth = (totalWidth - totalAllocatedWidth) / remainedTabs; 687 } 688 689 // If any tab width not set yet, set it to the average width 690 if (remainedTabs > 0) 691 { 692 int roundUpWidth = (totalWidth - totalAllocatedWidth) - (averageWidth * remainedTabs); 693 foreach (TabVS2013 tab in Tabs) 694 { 695 if (tab.Flag) 696 continue; 697 698 tab.Flag = true; 699 if (roundUpWidth > 0) 700 { 701 tab.TabWidth = averageWidth + 1; 702 roundUpWidth--; 703 } 704 else 705 tab.TabWidth = averageWidth; 706 } 707 } 708 709 // Set the X position of the tabs 710 int x = rectTabStrip.X + ToolWindowStripGapLeft; 711 foreach (TabVS2013 tab in Tabs) 712 { 713 tab.TabX = x; 714 x += tab.TabWidth; 715 } 716 } 717 CalculateDocumentTab(Rectangle rectTabStrip, ref int x, int index)718 private bool CalculateDocumentTab(Rectangle rectTabStrip, ref int x, int index) 719 { 720 bool overflow = false; 721 722 var tab = Tabs[index] as TabVS2013; 723 tab.MaxWidth = GetMaxTabWidth(index); 724 int width = Math.Min(tab.MaxWidth, DocumentTabMaxWidth); 725 if (x + width < rectTabStrip.Right || index == StartDisplayingTab) 726 { 727 tab.TabX = x; 728 tab.TabWidth = width; 729 EndDisplayingTab = index; 730 } 731 else 732 { 733 tab.TabX = 0; 734 tab.TabWidth = 0; 735 overflow = true; 736 } 737 x += width; 738 739 return overflow; 740 } 741 742 /// <summary> 743 /// Calculate which tabs are displayed and in what order. 744 /// </summary> CalculateTabs_Document()745 private void CalculateTabs_Document() 746 { 747 if (m_startDisplayingTab >= Tabs.Count) 748 m_startDisplayingTab = 0; 749 750 Rectangle rectTabStrip = TabsRectangle; 751 752 int x = rectTabStrip.X; //+ rectTabStrip.Height / 2; 753 bool overflow = false; 754 755 // Originally all new documents that were considered overflow 756 // (not enough pane strip space to show all tabs) were added to 757 // the far left (assuming not right to left) and the tabs on the 758 // right were dropped from view. If StartDisplayingTab is not 0 759 // then we are dealing with making sure a specific tab is kept in focus. 760 if (m_startDisplayingTab > 0) 761 { 762 int tempX = x; 763 var tab = Tabs[m_startDisplayingTab] as TabVS2013; 764 tab.MaxWidth = GetMaxTabWidth(m_startDisplayingTab); 765 766 // Add the active tab and tabs to the left 767 for (int i = StartDisplayingTab; i >= 0; i--) 768 CalculateDocumentTab(rectTabStrip, ref tempX, i); 769 770 // Store which tab is the first one displayed so that it 771 // will be drawn correctly (without part of the tab cut off) 772 FirstDisplayingTab = EndDisplayingTab; 773 774 tempX = x; // Reset X location because we are starting over 775 776 // Start with the first tab displayed - name is a little misleading. 777 // Loop through each tab and set its location. If there is not enough 778 // room for all of them overflow will be returned. 779 for (int i = EndDisplayingTab; i < Tabs.Count; i++) 780 overflow = CalculateDocumentTab(rectTabStrip, ref tempX, i); 781 782 // If not all tabs are shown then we have an overflow. 783 if (FirstDisplayingTab != 0) 784 overflow = true; 785 } 786 else 787 { 788 for (int i = StartDisplayingTab; i < Tabs.Count; i++) 789 overflow = CalculateDocumentTab(rectTabStrip, ref x, i); 790 for (int i = 0; i < StartDisplayingTab; i++) 791 overflow = CalculateDocumentTab(rectTabStrip, ref x, i); 792 793 FirstDisplayingTab = StartDisplayingTab; 794 } 795 796 if (!overflow) 797 { 798 m_startDisplayingTab = 0; 799 FirstDisplayingTab = 0; 800 x = rectTabStrip.X; 801 foreach (TabVS2013 tab in Tabs) 802 { 803 tab.TabX = x; 804 x += tab.TabWidth; 805 } 806 } 807 808 DocumentTabsOverflow = overflow; 809 } 810 EnsureTabVisible(IDockContent content)811 protected override void EnsureTabVisible(IDockContent content) 812 { 813 if (Appearance != DockPane.AppearanceStyle.Document || !Tabs.Contains(content)) 814 return; 815 816 CalculateTabs(); 817 EnsureDocumentTabVisible(content, true); 818 } 819 EnsureDocumentTabVisible(IDockContent content, bool repaint)820 private bool EnsureDocumentTabVisible(IDockContent content, bool repaint) 821 { 822 int index = Tabs.IndexOf(content); 823 if (index == -1) // TODO: should prevent it from being -1; 824 return false; 825 826 var tab = Tabs[index] as TabVS2013; 827 if (tab.TabWidth != 0) 828 return false; 829 830 StartDisplayingTab = index; 831 if (repaint) 832 Invalidate(); 833 834 return true; 835 } 836 GetMaxTabWidth(int index)837 private int GetMaxTabWidth(int index) 838 { 839 if (Appearance == DockPane.AppearanceStyle.ToolWindow) 840 return GetMaxTabWidth_ToolWindow(index); 841 else 842 return GetMaxTabWidth_Document(index); 843 } 844 GetMaxTabWidth_ToolWindow(int index)845 private int GetMaxTabWidth_ToolWindow(int index) 846 { 847 IDockContent content = Tabs[index].Content; 848 Size sizeString = TextRenderer.MeasureText(content.DockHandler.TabText, TextFont); 849 return ToolWindowImageWidth + sizeString.Width + ToolWindowImageGapLeft 850 + ToolWindowImageGapRight + ToolWindowTextGapRight; 851 } 852 853 private const int TAB_CLOSE_BUTTON_WIDTH = 30; 854 GetMaxTabWidth_Document(int index)855 private int GetMaxTabWidth_Document(int index) 856 { 857 IDockContent content = Tabs[index].Content; 858 int height = GetTabRectangle_Document(index).Height; 859 Size sizeText = TextRenderer.MeasureText(content.DockHandler.TabText, BoldFont, new Size(DocumentTabMaxWidth, height), DocumentTextFormat); 860 861 int width; 862 if (DockPane.DockPanel.ShowDocumentIcon) 863 width = sizeText.Width + DocumentIconWidth + DocumentIconGapLeft + DocumentIconGapRight + DocumentTextGapRight; 864 else 865 width = sizeText.Width + DocumentIconGapLeft + DocumentTextGapRight; 866 867 width += TAB_CLOSE_BUTTON_WIDTH; 868 return width; 869 } 870 DrawTabStrip(Graphics g)871 private void DrawTabStrip(Graphics g) 872 { 873 // IMPORTANT: fill background. 874 Rectangle rectTabStrip = TabStripRectangle; 875 g.FillRectangle(DockPane.DockPanel.Theme.PaintingService.GetBrush(DockPane.DockPanel.Theme.ColorPalette.MainWindowActive.Background), rectTabStrip); 876 877 if (Appearance == DockPane.AppearanceStyle.Document) 878 DrawTabStrip_Document(g); 879 else 880 DrawTabStrip_ToolWindow(g); 881 } 882 DrawTabStrip_Document(Graphics g)883 private void DrawTabStrip_Document(Graphics g) 884 { 885 int count = Tabs.Count; 886 if (count == 0) 887 return; 888 889 Rectangle rectTabStrip = new Rectangle(TabStripRectangle.Location, TabStripRectangle.Size); 890 rectTabStrip.Height += 1; 891 892 // Draw the tabs 893 Rectangle rectTabOnly = TabsRectangle; 894 Rectangle rectTab = Rectangle.Empty; 895 TabVS2013 tabActive = null; 896 g.SetClip(DrawHelper.RtlTransform(this, rectTabOnly)); 897 for (int i = 0; i < count; i++) 898 { 899 rectTab = GetTabRectangle(i); 900 if (Tabs[i].Content == DockPane.ActiveContent) 901 { 902 tabActive = Tabs[i] as TabVS2013; 903 tabActive.Rectangle = rectTab; 904 continue; 905 } 906 907 if (rectTab.IntersectsWith(rectTabOnly)) 908 { 909 var tab = Tabs[i] as TabVS2013; 910 tab.Rectangle = rectTab; 911 DrawTab(g, tab); 912 } 913 } 914 915 g.SetClip(rectTabStrip); 916 917 if (DockPane.DockPanel.DocumentTabStripLocation == DocumentTabStripLocation.Bottom) 918 { 919 } 920 else 921 { 922 Color tabUnderLineColor; 923 if (tabActive != null && DockPane.IsActiveDocumentPane) 924 tabUnderLineColor = DockPane.DockPanel.Theme.ColorPalette.TabSelectedActive.Background; 925 else 926 tabUnderLineColor = DockPane.DockPanel.Theme.ColorPalette.TabSelectedInactive.Background; 927 928 g.DrawLine(DockPane.DockPanel.Theme.PaintingService.GetPen(tabUnderLineColor, 4), rectTabStrip.Left, rectTabStrip.Bottom, rectTabStrip.Right, rectTabStrip.Bottom); 929 } 930 931 g.SetClip(DrawHelper.RtlTransform(this, rectTabOnly)); 932 if (tabActive != null) 933 { 934 rectTab = tabActive.Rectangle.Value; 935 if (rectTab.IntersectsWith(rectTabOnly)) 936 { 937 rectTab.Intersect(rectTabOnly); 938 tabActive.Rectangle = rectTab; 939 DrawTab(g, tabActive); 940 } 941 } 942 } 943 DrawTabStrip_ToolWindow(Graphics g)944 private void DrawTabStrip_ToolWindow(Graphics g) 945 { 946 var rect = TabStripRectangle_ToolWindow; 947 Color borderColor = DockPane.DockPanel.Theme.ColorPalette.ToolWindowBorder; 948 949 g.DrawLine(DockPane.DockPanel.Theme.PaintingService.GetPen(borderColor), rect.Left, rect.Top, 950 rect.Right, rect.Top); 951 952 for (int i = 0; i < Tabs.Count; i++) 953 { 954 var tab = Tabs[i] as TabVS2013; 955 tab.Rectangle = GetTabRectangle(i); 956 DrawTab(g, tab); 957 } 958 } 959 GetTabRectangle(int index)960 private Rectangle GetTabRectangle(int index) 961 { 962 if (Appearance == DockPane.AppearanceStyle.ToolWindow) 963 return GetTabRectangle_ToolWindow(index); 964 else 965 return GetTabRectangle_Document(index); 966 } 967 GetTabRectangle_ToolWindow(int index)968 private Rectangle GetTabRectangle_ToolWindow(int index) 969 { 970 Rectangle rectTabStrip = TabStripRectangle; 971 972 TabVS2013 tab = (TabVS2013)Tabs[index]; 973 return new Rectangle(tab.TabX, rectTabStrip.Y, tab.TabWidth, rectTabStrip.Height); 974 } 975 GetTabRectangle_Document(int index)976 private Rectangle GetTabRectangle_Document(int index) 977 { 978 Rectangle rectTabStrip = TabStripRectangle; 979 var tab = (TabVS2013)Tabs[index]; 980 981 Rectangle rect = new Rectangle(); 982 rect.X = tab.TabX; 983 rect.Width = tab.TabWidth; 984 rect.Height = rectTabStrip.Height - DocumentTabGapTop; 985 986 if (DockPane.DockPanel.DocumentTabStripLocation == DocumentTabStripLocation.Bottom) 987 rect.Y = rectTabStrip.Y + DocumentStripGapBottom; 988 else 989 rect.Y = rectTabStrip.Y + DocumentTabGapTop; 990 991 return rect; 992 } 993 DrawTab(Graphics g, TabVS2013 tab)994 private void DrawTab(Graphics g, TabVS2013 tab) 995 { 996 if (Appearance == DockPane.AppearanceStyle.ToolWindow) 997 DrawTab_ToolWindow(g, tab); 998 else 999 DrawTab_Document(g, tab); 1000 } 1001 GetTabOutline(Tab tab, bool rtlTransform, bool toScreen)1002 private GraphicsPath GetTabOutline(Tab tab, bool rtlTransform, bool toScreen) 1003 { 1004 if (Appearance == DockPane.AppearanceStyle.ToolWindow) 1005 return GetTabOutline_ToolWindow(tab, rtlTransform, toScreen); 1006 else 1007 return GetTabOutline_Document(tab, rtlTransform, toScreen, false); 1008 } 1009 GetTabOutline_ToolWindow(Tab tab, bool rtlTransform, bool toScreen)1010 private GraphicsPath GetTabOutline_ToolWindow(Tab tab, bool rtlTransform, bool toScreen) 1011 { 1012 Rectangle rect = GetTabRectangle(Tabs.IndexOf(tab)); 1013 if (rtlTransform) 1014 rect = DrawHelper.RtlTransform(this, rect); 1015 if (toScreen) 1016 rect = RectangleToScreen(rect); 1017 1018 DrawHelper.GetRoundedCornerTab(GraphicsPath, rect, false); 1019 return GraphicsPath; 1020 } 1021 GetTabOutline_Document(Tab tab, bool rtlTransform, bool toScreen, bool full)1022 private GraphicsPath GetTabOutline_Document(Tab tab, bool rtlTransform, bool toScreen, bool full) 1023 { 1024 GraphicsPath.Reset(); 1025 Rectangle rect = GetTabRectangle(Tabs.IndexOf(tab)); 1026 1027 // Shorten TabOutline so it doesn't get overdrawn by icons next to it 1028 rect.Intersect(TabsRectangle); 1029 rect.Width--; 1030 1031 if (rtlTransform) 1032 rect = DrawHelper.RtlTransform(this, rect); 1033 if (toScreen) 1034 rect = RectangleToScreen(rect); 1035 1036 GraphicsPath.AddRectangle(rect); 1037 return GraphicsPath; 1038 } 1039 DrawTab_ToolWindow(Graphics g, TabVS2013 tab)1040 private void DrawTab_ToolWindow(Graphics g, TabVS2013 tab) 1041 { 1042 var rect = tab.Rectangle.Value; 1043 Rectangle rectIcon = new Rectangle( 1044 rect.X + ToolWindowImageGapLeft, 1045 rect.Y + rect.Height - ToolWindowImageGapBottom - ToolWindowImageHeight, 1046 ToolWindowImageWidth, ToolWindowImageHeight); 1047 Rectangle rectText = PatchController.EnableHighDpi == true 1048 ? new Rectangle( 1049 rect.X + ToolWindowImageGapLeft, 1050 rect.Y + rect.Height - ToolWindowImageGapBottom - TextFont.Height, 1051 ToolWindowImageWidth, TextFont.Height) 1052 : rectIcon; 1053 rectText.X += rectIcon.Width + ToolWindowImageGapRight; 1054 rectText.Width = rect.Width - rectIcon.Width - ToolWindowImageGapLeft - 1055 ToolWindowImageGapRight - ToolWindowTextGapRight; 1056 1057 Rectangle rectTab = DrawHelper.RtlTransform(this, rect); 1058 rectText = DrawHelper.RtlTransform(this, rectText); 1059 rectIcon = DrawHelper.RtlTransform(this, rectIcon); 1060 Color borderColor = DockPane.DockPanel.Theme.ColorPalette.ToolWindowBorder; 1061 1062 Color separatorColor = DockPane.DockPanel.Theme.ColorPalette.ToolWindowSeparator; 1063 if (DockPane.ActiveContent == tab.Content) 1064 { 1065 Color textColor; 1066 Color backgroundColor; 1067 if (DockPane.IsActiveDocumentPane) 1068 { 1069 textColor = DockPane.DockPanel.Theme.ColorPalette.ToolWindowTabSelectedActive.Text; 1070 backgroundColor = DockPane.DockPanel.Theme.ColorPalette.ToolWindowTabSelectedActive.Background; 1071 } 1072 else 1073 { 1074 textColor = DockPane.DockPanel.Theme.ColorPalette.ToolWindowTabSelectedInactive.Text; 1075 backgroundColor = DockPane.DockPanel.Theme.ColorPalette.ToolWindowTabSelectedInactive.Background; 1076 } 1077 1078 g.FillRectangle(DockPane.DockPanel.Theme.PaintingService.GetBrush(backgroundColor), rect); 1079 g.DrawLine(DockPane.DockPanel.Theme.PaintingService.GetPen(borderColor), rect.Left, rect.Top, 1080 rect.Left, rect.Bottom); 1081 g.DrawLine(DockPane.DockPanel.Theme.PaintingService.GetPen(borderColor), rect.Left, rect.Bottom - 1, 1082 rect.Right, rect.Bottom -1); 1083 g.DrawLine(DockPane.DockPanel.Theme.PaintingService.GetPen(borderColor), rect.Right - 1, rect.Top, 1084 rect.Right - 1, rect.Bottom); 1085 TextRenderer.DrawText(g, tab.Content.DockHandler.TabText, TextFont, rectText, textColor, ToolWindowTextFormat); 1086 } 1087 else 1088 { 1089 Color textColor; 1090 Color backgroundColor; 1091 if (tab.Content == DockPane.MouseOverTab) 1092 { 1093 textColor = DockPane.DockPanel.Theme.ColorPalette.ToolWindowTabUnselectedHovered.Text; 1094 backgroundColor = DockPane.DockPanel.Theme.ColorPalette.ToolWindowTabUnselectedHovered.Background; 1095 } 1096 else 1097 { 1098 textColor = DockPane.DockPanel.Theme.ColorPalette.ToolWindowTabUnselected.Text; 1099 backgroundColor = DockPane.DockPanel.Theme.ColorPalette.MainWindowActive.Background; 1100 } 1101 1102 g.FillRectangle(DockPane.DockPanel.Theme.PaintingService.GetBrush(backgroundColor), rect); 1103 g.DrawLine(DockPane.DockPanel.Theme.PaintingService.GetPen(borderColor), rect.Left, rect.Top, 1104 rect.Right, rect.Top); 1105 TextRenderer.DrawText(g, tab.Content.DockHandler.TabText, TextFont, rectText, textColor, ToolWindowTextFormat); 1106 } 1107 1108 if (rectTab.Contains(rectIcon)) 1109 g.DrawIcon(tab.Content.DockHandler.Icon, rectIcon); 1110 } 1111 DrawTab_Document(Graphics g, TabVS2013 tab)1112 private void DrawTab_Document(Graphics g, TabVS2013 tab) 1113 { 1114 var rect = tab.Rectangle.Value; 1115 if (tab.TabWidth == 0) 1116 return; 1117 1118 var rectCloseButton = GetCloseButtonRect(rect); 1119 Rectangle rectIcon = new Rectangle( 1120 rect.X + DocumentIconGapLeft, 1121 rect.Y + rect.Height - DocumentIconGapBottom - DocumentIconHeight, 1122 DocumentIconWidth, DocumentIconHeight); 1123 Rectangle rectText = PatchController.EnableHighDpi == true 1124 ? new Rectangle( 1125 rect.X + DocumentIconGapLeft, 1126 rect.Y + rect.Height - DocumentIconGapBottom - TextFont.Height, 1127 DocumentIconWidth, TextFont.Height) 1128 : rectIcon; 1129 if (DockPane.DockPanel.ShowDocumentIcon) 1130 { 1131 rectText.X += rectIcon.Width + DocumentIconGapRight; 1132 rectText.Y = rect.Y; 1133 rectText.Width = rect.Width - rectIcon.Width - DocumentIconGapLeft - DocumentIconGapRight - DocumentTextGapRight - rectCloseButton.Width; 1134 rectText.Height = rect.Height; 1135 } 1136 else 1137 rectText.Width = rect.Width - DocumentIconGapLeft - DocumentTextGapRight - rectCloseButton.Width; 1138 1139 Rectangle rectTab = DrawHelper.RtlTransform(this, rect); 1140 Rectangle rectBack = DrawHelper.RtlTransform(this, rect); 1141 rectBack.Width += DocumentIconGapLeft; 1142 rectBack.X -= DocumentIconGapLeft; 1143 1144 rectText = DrawHelper.RtlTransform(this, rectText); 1145 rectIcon = DrawHelper.RtlTransform(this, rectIcon); 1146 1147 Color activeColor = DockPane.DockPanel.Theme.ColorPalette.TabSelectedActive.Background; 1148 Color lostFocusColor = DockPane.DockPanel.Theme.ColorPalette.TabSelectedInactive.Background; 1149 Color inactiveColor = DockPane.DockPanel.Theme.ColorPalette.MainWindowActive.Background; 1150 Color mouseHoverColor = DockPane.DockPanel.Theme.ColorPalette.TabUnselectedHovered.Background; 1151 1152 Color activeText = DockPane.DockPanel.Theme.ColorPalette.TabSelectedActive.Text; 1153 Color lostFocusText = DockPane.DockPanel.Theme.ColorPalette.TabSelectedInactive.Text; 1154 Color inactiveText = DockPane.DockPanel.Theme.ColorPalette.TabUnselected.Text; 1155 Color mouseHoverText = DockPane.DockPanel.Theme.ColorPalette.TabUnselectedHovered.Text; 1156 1157 Color text; 1158 Image image = null; 1159 Color paint; 1160 var imageService = DockPane.DockPanel.Theme.ImageService; 1161 if (DockPane.ActiveContent == tab.Content) 1162 { 1163 if (DockPane.IsActiveDocumentPane) 1164 { 1165 paint = activeColor; 1166 text = activeText; 1167 image = IsMouseDown 1168 ? imageService.TabPressActive_Close 1169 : rectCloseButton == ActiveClose 1170 ? imageService.TabHoverActive_Close 1171 : imageService.TabActive_Close; 1172 } 1173 else 1174 { 1175 paint = lostFocusColor; 1176 text = lostFocusText; 1177 image = IsMouseDown 1178 ? imageService.TabPressLostFocus_Close 1179 : rectCloseButton == ActiveClose 1180 ? imageService.TabHoverLostFocus_Close 1181 : imageService.TabLostFocus_Close; 1182 } 1183 } 1184 else 1185 { 1186 if (tab.Content == DockPane.MouseOverTab) 1187 { 1188 paint = mouseHoverColor; 1189 text = mouseHoverText; 1190 image = IsMouseDown 1191 ? imageService.TabPressInactive_Close 1192 : rectCloseButton == ActiveClose 1193 ? imageService.TabHoverInactive_Close 1194 : imageService.TabInactive_Close; 1195 } 1196 else 1197 { 1198 paint = inactiveColor; 1199 text = inactiveText; 1200 } 1201 } 1202 1203 g.FillRectangle(DockPane.DockPanel.Theme.PaintingService.GetBrush(paint), rect); 1204 TextRenderer.DrawText(g, tab.Content.DockHandler.TabText, TextFont, rectText, text, DocumentTextFormat); 1205 if (image != null) 1206 g.DrawImage(image, rectCloseButton); 1207 1208 if (rectTab.Contains(rectIcon) && DockPane.DockPanel.ShowDocumentIcon) 1209 g.DrawIcon(tab.Content.DockHandler.Icon, rectIcon); 1210 } 1211 1212 private bool m_isMouseDown = false; 1213 protected bool IsMouseDown 1214 { 1215 get { return m_isMouseDown; } 1216 private set 1217 { 1218 if (m_isMouseDown == value) 1219 return; 1220 1221 m_isMouseDown = value; 1222 Invalidate(); 1223 } 1224 } 1225 OnMouseUp(MouseEventArgs e)1226 protected override void OnMouseUp(MouseEventArgs e) 1227 { 1228 base.OnMouseUp(e); 1229 if (IsMouseDown) 1230 IsMouseDown = false; 1231 } 1232 OnMouseDown(MouseEventArgs e)1233 protected override void OnMouseDown(MouseEventArgs e) 1234 { 1235 base.OnMouseDown(e); 1236 // suspend drag if mouse is down on active close button. 1237 this.m_suspendDrag = ActiveCloseHitTest(e.Location); 1238 if (!IsMouseDown) 1239 IsMouseDown = true; 1240 } 1241 OnMouseMove(MouseEventArgs e)1242 protected override void OnMouseMove(MouseEventArgs e) 1243 { 1244 if (!this.m_suspendDrag) 1245 base.OnMouseMove(e); 1246 1247 int index = HitTest(PointToClient(MousePosition)); 1248 string toolTip = string.Empty; 1249 1250 bool tabUpdate = false; 1251 bool buttonUpdate = false; 1252 if (index != -1) 1253 { 1254 var tab = Tabs[index] as TabVS2013; 1255 if (Appearance == DockPane.AppearanceStyle.ToolWindow || Appearance == DockPane.AppearanceStyle.Document) 1256 { 1257 tabUpdate = SetMouseOverTab(tab.Content == DockPane.ActiveContent ? null : tab.Content); 1258 } 1259 1260 if (!String.IsNullOrEmpty(tab.Content.DockHandler.ToolTipText)) 1261 toolTip = tab.Content.DockHandler.ToolTipText; 1262 else if (tab.MaxWidth > tab.TabWidth) 1263 toolTip = tab.Content.DockHandler.TabText; 1264 1265 var mousePos = PointToClient(MousePosition); 1266 var tabRect = tab.Rectangle.Value; 1267 var closeButtonRect = GetCloseButtonRect(tabRect); 1268 var mouseRect = new Rectangle(mousePos, new Size(1, 1)); 1269 buttonUpdate = SetActiveClose(closeButtonRect.IntersectsWith(mouseRect) ? closeButtonRect : Rectangle.Empty); 1270 } 1271 else 1272 { 1273 tabUpdate = SetMouseOverTab(null); 1274 buttonUpdate = SetActiveClose(Rectangle.Empty); 1275 } 1276 1277 if (tabUpdate || buttonUpdate) 1278 Invalidate(); 1279 1280 if (m_toolTip.GetToolTip(this) != toolTip) 1281 { 1282 m_toolTip.Active = false; 1283 m_toolTip.SetToolTip(this, toolTip); 1284 m_toolTip.Active = true; 1285 } 1286 } 1287 OnMouseClick(MouseEventArgs e)1288 protected override void OnMouseClick(MouseEventArgs e) 1289 { 1290 base.OnMouseClick(e); 1291 if (e.Button != MouseButtons.Left || Appearance != DockPane.AppearanceStyle.Document) 1292 return; 1293 1294 var indexHit = HitTest(); 1295 if (indexHit > -1) 1296 TabCloseButtonHit(indexHit); 1297 } 1298 TabCloseButtonHit(int index)1299 private void TabCloseButtonHit(int index) 1300 { 1301 var mousePos = PointToClient(MousePosition); 1302 var tabRect = GetTabBounds(Tabs[index]); 1303 if (tabRect.Contains(ActiveClose) && ActiveCloseHitTest(mousePos)) 1304 TryCloseTab(index); 1305 } 1306 GetCloseButtonRect(Rectangle rectTab)1307 private Rectangle GetCloseButtonRect(Rectangle rectTab) 1308 { 1309 if (Appearance != DockPane.AppearanceStyle.Document) 1310 { 1311 return Rectangle.Empty; 1312 } 1313 1314 const int gap = 3; 1315 var imageSize = PatchController.EnableHighDpi == true ? rectTab.Height - gap * 2 : 15; 1316 return new Rectangle(rectTab.X + rectTab.Width - imageSize - gap - 1, rectTab.Y + gap, imageSize, imageSize); 1317 } 1318 WindowList_Click(object sender, EventArgs e)1319 private void WindowList_Click(object sender, EventArgs e) 1320 { 1321 SelectMenu.Items.Clear(); 1322 foreach (TabVS2013 tab in Tabs) 1323 { 1324 IDockContent content = tab.Content; 1325 ToolStripItem item = SelectMenu.Items.Add(content.DockHandler.TabText, content.DockHandler.Icon.ToBitmap()); 1326 item.Tag = tab.Content; 1327 item.Click += new EventHandler(ContextMenuItem_Click); 1328 } 1329 1330 var workingArea = Screen.GetWorkingArea(ButtonWindowList.PointToScreen(new Point(ButtonWindowList.Width / 2, ButtonWindowList.Height / 2))); 1331 var menu = new Rectangle(ButtonWindowList.PointToScreen(new Point(0, ButtonWindowList.Location.Y + ButtonWindowList.Height)), SelectMenu.Size); 1332 var menuMargined = new Rectangle(menu.X - SelectMenuMargin, menu.Y - SelectMenuMargin, menu.Width + SelectMenuMargin, menu.Height + SelectMenuMargin); 1333 if (workingArea.Contains(menuMargined)) 1334 { 1335 SelectMenu.Show(menu.Location); 1336 } 1337 else 1338 { 1339 var newPoint = menu.Location; 1340 newPoint.X = DrawHelper.Balance(SelectMenu.Width, SelectMenuMargin, newPoint.X, workingArea.Left, workingArea.Right); 1341 newPoint.Y = DrawHelper.Balance(SelectMenu.Size.Height, SelectMenuMargin, newPoint.Y, workingArea.Top, workingArea.Bottom); 1342 var button = ButtonWindowList.PointToScreen(new Point(0, ButtonWindowList.Height)); 1343 if (newPoint.Y < button.Y) 1344 { 1345 // flip the menu up to be above the button. 1346 newPoint.Y = button.Y - ButtonWindowList.Height; 1347 SelectMenu.Show(newPoint, ToolStripDropDownDirection.AboveRight); 1348 } 1349 else 1350 { 1351 SelectMenu.Show(newPoint); 1352 } 1353 } 1354 } 1355 ContextMenuItem_Click(object sender, EventArgs e)1356 private void ContextMenuItem_Click(object sender, EventArgs e) 1357 { 1358 ToolStripMenuItem item = sender as ToolStripMenuItem; 1359 if (item != null) 1360 { 1361 IDockContent content = (IDockContent)item.Tag; 1362 DockPane.ActiveContent = content; 1363 } 1364 } 1365 SetInertButtons()1366 private void SetInertButtons() 1367 { 1368 if (Appearance == DockPane.AppearanceStyle.ToolWindow) 1369 { 1370 if (m_buttonOverflow != null) 1371 m_buttonOverflow.Left = -m_buttonOverflow.Width; 1372 1373 if (m_buttonWindowList != null) 1374 m_buttonWindowList.Left = -m_buttonWindowList.Width; 1375 } 1376 else 1377 { 1378 ButtonOverflow.Visible = m_documentTabsOverflow; 1379 ButtonOverflow.RefreshChanges(); 1380 1381 ButtonWindowList.Visible = !m_documentTabsOverflow; 1382 ButtonWindowList.RefreshChanges(); 1383 } 1384 } 1385 OnLayout(LayoutEventArgs levent)1386 protected override void OnLayout(LayoutEventArgs levent) 1387 { 1388 if (Appearance == DockPane.AppearanceStyle.Document) 1389 { 1390 LayoutButtons(); 1391 OnRefreshChanges(); 1392 } 1393 1394 base.OnLayout(levent); 1395 } 1396 LayoutButtons()1397 private void LayoutButtons() 1398 { 1399 Rectangle rectTabStrip = TabStripRectangle; 1400 1401 // Set position and size of the buttons 1402 int buttonWidth = ButtonOverflow.Image.Width; 1403 int buttonHeight = ButtonOverflow.Image.Height; 1404 int height = rectTabStrip.Height - DocumentButtonGapTop - DocumentButtonGapBottom; 1405 if (buttonHeight < height) 1406 { 1407 buttonWidth = buttonWidth * height / buttonHeight; 1408 buttonHeight = height; 1409 } 1410 Size buttonSize = new Size(buttonWidth, buttonHeight); 1411 1412 int x = rectTabStrip.X + rectTabStrip.Width - DocumentTabGapLeft 1413 - DocumentButtonGapRight - buttonWidth; 1414 int y = rectTabStrip.Y + DocumentButtonGapTop; 1415 Point point = new Point(x, y); 1416 ButtonOverflow.Bounds = DrawHelper.RtlTransform(this, new Rectangle(point, buttonSize)); 1417 1418 // If the close button is not visible draw the window list button overtop. 1419 // Otherwise it is drawn to the left of the close button. 1420 ButtonWindowList.Bounds = DrawHelper.RtlTransform(this, new Rectangle(point, buttonSize)); 1421 } 1422 Close_Click(object sender, EventArgs e)1423 private void Close_Click(object sender, EventArgs e) 1424 { 1425 DockPane.CloseActiveContent(); 1426 if (PatchController.EnableMemoryLeakFix == true) 1427 { 1428 ContentClosed(); 1429 } 1430 } 1431 HitTest(Point point)1432 protected override int HitTest(Point point) 1433 { 1434 if (!TabsRectangle.Contains(point)) 1435 return -1; 1436 1437 foreach (Tab tab in Tabs) 1438 { 1439 GraphicsPath path = GetTabOutline(tab, true, false); 1440 if (path.IsVisible(point)) 1441 return Tabs.IndexOf(tab); 1442 } 1443 1444 return -1; 1445 } 1446 MouseDownActivateTest(MouseEventArgs e)1447 protected override bool MouseDownActivateTest(MouseEventArgs e) 1448 { 1449 bool result = base.MouseDownActivateTest(e); 1450 if (result && (e.Button == MouseButtons.Left) && (Appearance == DockPane.AppearanceStyle.Document)) 1451 { 1452 // don't activate if mouse is down on active close button 1453 result = !ActiveCloseHitTest(e.Location); 1454 } 1455 return result; 1456 } 1457 ActiveCloseHitTest(Point ptMouse)1458 private bool ActiveCloseHitTest(Point ptMouse) 1459 { 1460 bool result = false; 1461 if (!ActiveClose.IsEmpty) 1462 { 1463 var mouseRect = new Rectangle(ptMouse, new Size(1, 1)); 1464 result = ActiveClose.IntersectsWith(mouseRect); 1465 } 1466 return result; 1467 } 1468 GetTabBounds(Tab tab)1469 protected override Rectangle GetTabBounds(Tab tab) 1470 { 1471 GraphicsPath path = GetTabOutline(tab, true, false); 1472 RectangleF rectangle = path.GetBounds(); 1473 return new Rectangle((int)rectangle.Left, (int)rectangle.Top, (int)rectangle.Width, (int)rectangle.Height); 1474 } 1475 1476 private Rectangle ActiveClose 1477 { 1478 get { return _activeClose; } 1479 } 1480 SetActiveClose(Rectangle rectangle)1481 private bool SetActiveClose(Rectangle rectangle) 1482 { 1483 if (_activeClose == rectangle) 1484 return false; 1485 1486 _activeClose = rectangle; 1487 return true; 1488 } 1489 SetMouseOverTab(IDockContent content)1490 private bool SetMouseOverTab(IDockContent content) 1491 { 1492 if (DockPane.MouseOverTab == content) 1493 return false; 1494 1495 DockPane.MouseOverTab = content; 1496 return true; 1497 } 1498 OnMouseLeave(EventArgs e)1499 protected override void OnMouseLeave(EventArgs e) 1500 { 1501 var tabUpdate = SetMouseOverTab(null); 1502 var buttonUpdate = SetActiveClose(Rectangle.Empty); 1503 if (tabUpdate || buttonUpdate) 1504 Invalidate(); 1505 1506 base.OnMouseLeave(e); 1507 } 1508 OnRightToLeftChanged(EventArgs e)1509 protected override void OnRightToLeftChanged(EventArgs e) 1510 { 1511 base.OnRightToLeftChanged(e); 1512 PerformLayout(); 1513 } 1514 } 1515 } 1516