//
// ___ _____ ___ ___ __ __
// / __|_ _/ _ \| _ \ \/ |
// \__ \ | || (_) | / |\/| |
// |___/ |_| \___/|_|_\_| |_|
//
// Storm.TabControl.dll
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Storm.TabControl.dll was created under the LGPL license.
// It was based on another .dll and evolved from that one.
// The original .dll was created by Hadi Eskandari.
//
// What is Storm?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Storm is a set of dynamic link libraries used in Theodor
// "Vestras" Storm Kristensen's application "Moonlite".
//
//
// Thanks:
// ¯¯¯¯¯¯¯
// - Hadi Eskandari for creating and publishing the library.
//
//
// Copyright (c) Theodor "Vestras" Storm Kristensen 2009
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//
namespace Storm.TabControl
{
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Threading;
using System.Windows.Forms;
using Storm.TabControl.Base;
using Storm.TabControl.Design;
[Designer(typeof(TabStripDesigner))]
[DefaultEvent("TabStripItemSelectionChanged")]
[DefaultProperty("Items")]
[ToolboxItem(true)]
[ToolboxBitmap("TabStrip.bmp")]
public class TabStrip : BaseStyledPanel, ISupportInitialize, IDisposable
{
#region Static Members
internal static int PreferredWidth = 350;
internal static int PreferredHeight = 200;
#endregion
#region Constants
private const int DEF_HEADER_HEIGHT = 19;
private const int DEF_GLYPH_WIDTH = 40;
private int DEF_START_POS = 10;
#endregion
#region Members
private TabStripMenuGlyph menuGlyph = null;
private TabStripCloseButton closeButton = null;
private TabStripItemCollection items;
private TabStripItem selectedItem = null;
private Rectangle stripButtonRect = Rectangle.Empty;
private Point cursorLoc = new Point(0, 0);
private ContextMenuStrip menu = null;
private ToolStripDropDownMenu rightClickMenu = null;
private StringFormat sf = null;
private static Font defaultFont = new Font("Tahoma", 8.25f, FontStyle.Regular);
private bool alwaysShowClose = true;
private bool isIniting = false;
private bool alwaysShowMenuGlyph = true;
private bool menuOpen = false;
#region Hover & Color Members
private Color selectedColor1;
private Color selectedColor2;
private Color selectedForeColor;
private Color normalColor1;
private Color normalColor2;
private Color normalForeColor;
private Color selectedBorderColor;
private Color normalBorderColor;
private TabStripItem currentHotItem = null;
private TabStripItem hoverItem = null;
#endregion
#endregion
#region Events
public event TabStripItemMouseEnterHandler TabStripItemMouseEnter;
public event TabStripItemMouseLeaveHandler TabStripItemMouseLeave;
public event TabStripItemClosingHandler TabStripItemClosing;
public event TabStripItemChangedHandler TabStripItemSelectionChanged;
public event SelectedItemChangedHandler SelectedItemChanged;
public event HandledEventHandler MenuItemsLoading;
public event EventHandler MenuItemsLoaded;
public event EventHandler TabStripItemClosed;
#endregion
#region Properties
[DefaultValue(null)]
[RefreshProperties(RefreshProperties.All)]
public TabStripItem SelectedItem
{
get { return selectedItem; }
set
{
if (selectedItem == value)
return;
if (value == null && Items.Count > 0)
{
TabStripItem itm = Items[0];
if (itm.Visible)
{
selectedItem = itm;
selectedItem.Selected = true;
selectedItem.Dock = DockStyle.Fill;
}
}
else
selectedItem = value;
foreach (TabStripItem itm in Items)
{
if (itm == selectedItem)
{
SelectItem(itm);
itm.Dock = DockStyle.Fill;
itm.Show();
}
else
{
UnSelectItem(itm);
itm.Hide();
}
}
SelectItem(selectedItem);
Invalidate();
if (!selectedItem.IsDrawn)
{
Items.MoveTo(0, selectedItem);
Invalidate();
}
OnTabStripItemChanged(
new TabStripItemChangedEventArgs(selectedItem, TabStripItemChangeTypes.SelectionChanged));
}
}
[DefaultValue(true)]
public bool AlwaysShowMenuGlyph
{
get { return alwaysShowMenuGlyph; }
set
{
if (alwaysShowMenuGlyph == value)
return;
alwaysShowMenuGlyph = value;
Invalidate();
}
}
[DefaultValue(true)]
public bool AlwaysShowClose
{
get { return alwaysShowClose; }
set
{
if (alwaysShowClose == value)
return;
alwaysShowClose = value;
Invalidate();
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public TabStripItemCollection Items
{ get { return items; } }
[DefaultValue(typeof(Size), "350,200")]
public new Size Size
{
get { return base.Size; }
set
{
if (base.Size == value)
return;
base.Size = value;
UpdateLayout();
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new ControlCollection Controls
{ get { return base.Controls; } }
public ToolStripDropDownMenu RightClickMenu
{
get { return rightClickMenu; }
set { rightClickMenu = value; }
}
public Color SelectedColorStart
{
get { return selectedColor1; }
set
{
selectedColor1 = value;
this.Invalidate();
}
}
public Color SelectedColorEnd
{
get { return selectedColor2; }
set
{
selectedColor2 = value;
this.Invalidate();
}
}
public Color SelectedBorderColor
{
get { return selectedBorderColor; }
set
{
selectedBorderColor = value;
this.Invalidate();
}
}
public Color NormalColorStart
{
get { return normalColor1; }
set
{
normalColor1 = value;
this.Invalidate();
}
}
public Color NormalColorEnd
{
get { return normalColor2; }
set
{
normalColor2 = value;
this.Invalidate();
}
}
public Color NormalBorderColor
{
get { return normalBorderColor; }
set
{
normalBorderColor = value;
this.Invalidate();
}
}
public Color NormalForeColor
{
get { return normalForeColor; }
set
{
normalForeColor = value;
this.Invalidate();
}
}
public Color SelectedForeColor
{
get { return selectedForeColor; }
set
{
selectedForeColor = value;
this.Invalidate();
}
}
#endregion
#region Methods
#region Public
public HitTestResult HitTest(Point pt)
{
if (closeButton.Bounds.Contains(pt))
return HitTestResult.CloseButton;
if (menuGlyph.Bounds.Contains(pt))
return HitTestResult.MenuGlyph;
if (GetTabItemByPoint(pt) != null)
return HitTestResult.TabItem;
return HitTestResult.None;
}
public void AddTab(TabStripItem tabItem)
{
AddTab(tabItem, false);
if (SelectedItemChanged != null)
SelectedItemChanged(new TabStripItemMouseEventArgs(SelectedItem));
// Update the currently shown controls.
foreach (Control control in SelectedItem.Controls)
control.Show();
}
public void AddTab(TabStripItem tabItem, bool autoSelect)
{
tabItem.Dock = DockStyle.Fill;
tabItem.TabStripParent = this;
Items.Add(tabItem);
TabStripItemMouseEnter += new TabStripItemMouseEnterHandler(OnTabMouseEnter);
TabStripItemMouseLeave += new TabStripItemMouseLeaveHandler(OnTabMouseLeave);
if ((autoSelect && tabItem.Visible) || (tabItem.Visible && Items.DrawnCount < 1))
{
SelectedItem = tabItem;
SelectItem(tabItem);
if (SelectedItemChanged != null)
SelectedItemChanged(new TabStripItemMouseEventArgs(tabItem));
// Update the currently shown controls.
foreach (Control control in tabItem.Controls)
control.Show();
}
}
public void RemoveTab(TabStripItem tabItem)
{
int tabIndex = Items.IndexOf(tabItem);
TabStripItemMouseEnter -= new TabStripItemMouseEnterHandler(OnTabMouseEnter);
TabStripItemMouseLeave -= new TabStripItemMouseLeaveHandler(OnTabMouseLeave);
if (tabIndex >= 0)
{
UnSelectItem(tabItem);
Items.Remove(tabItem);
}
if (Items.Count > 0)
{
if (RightToLeft == RightToLeft.No)
{
if (Items[tabIndex - 1] != null)
SelectedItem = Items[tabIndex - 1];
else
SelectedItem = Items.FirstVisible;
if (SelectedItemChanged != null)
SelectedItemChanged(new TabStripItemMouseEventArgs(SelectedItem));
// Update the currently shown controls.
foreach (Control control in SelectedItem.Controls)
control.Show();
}
else
{
if (Items[tabIndex + 1] != null)
SelectedItem = Items[tabIndex + 1];
else
SelectedItem = Items.LastVisible;
if (SelectedItemChanged != null)
SelectedItemChanged(new TabStripItemMouseEventArgs(SelectedItem));
// Update the currently shown controls.
foreach (Control control in SelectedItem.Controls)
control.Show();
}
}
}
public TabStripItem GetTabItemByPoint(Point pt)
{
TabStripItem item = null;
bool found = false;
for (int i = 0; i < Items.Count; i++)
{
TabStripItem current = Items[i];
if (current.StripRect.Contains(pt) && current.Visible
&& current.IsDrawn)
{
item = current;
found = true;
}
if (found)
break;
}
return item;
}
public virtual void ShowMenu()
{
if (menu.Visible == false && menu.Items.Count > 0)
{
if (RightToLeft == RightToLeft.No)
menu.Show(this, new Point(menuGlyph.Bounds.Left,
menuGlyph.Bounds.Bottom));
else
menu.Show(this, new Point(menuGlyph.Bounds.Right,
menuGlyph.Bounds.Bottom));
menuOpen = true;
}
}
public void CheckHot()
{
foreach (TabStripItem item in Items)
{
if (item.IsHot == false &&
currentHotItem == item)
{
currentHotItem = null;
item.IsHot = false;
if (TabStripItemMouseLeave != null)
{
TabStripItemMouseEventArgs args =
new TabStripItemMouseEventArgs(item);
TabStripItemMouseLeave(args);
}
}
if (item.IsHot == true &&
(item.StripRect.Contains(PointToClient(Cursor.Position)) == false ||
item.Bounds.Contains(PointToClient(Cursor.Position)) == true))
{
currentHotItem = null;
item.IsHot = false;
if (TabStripItemMouseLeave != null)
{
TabStripItemMouseEventArgs args =
new TabStripItemMouseEventArgs(item);
TabStripItemMouseLeave(args);
}
}
if (item.StripRect.Contains(PointToClient(Cursor.Position)) == true)
{
currentHotItem = item;
item.IsHot = true;
if (TabStripItemMouseEnter != null)
{
TabStripItemMouseEventArgs args =
new TabStripItemMouseEventArgs(item);
TabStripItemMouseEnter(args);
}
}
}
}
#endregion
#region Internal
internal void UnDrawAll()
{
for (int i = 0; i < Items.Count; i++)
{
Items[i].IsDrawn = false;
}
}
internal void SelectItem(TabStripItem tabItem)
{
tabItem.Dock = DockStyle.Fill;
tabItem.Visible = true;
tabItem.Selected = true;
}
internal void UnSelectItem(TabStripItem tabItem)
{
tabItem.Selected = false;
}
#endregion
#region Protected
protected internal virtual void OnTabStripItemClosing(TabStripItemClosingEventArgs e)
{
if (TabStripItemClosing != null)
TabStripItemClosing(e);
}
protected internal virtual void OnTabStripItemClosed(EventArgs e)
{
if (TabStripItemClosed != null)
TabStripItemClosed(this, e);
}
protected virtual void OnMenuItemsLoading(HandledEventArgs e)
{
if (MenuItemsLoading != null)
MenuItemsLoading(this, e);
}
protected virtual void OnMenuItemsLoaded(EventArgs e)
{
if (MenuItemsLoaded != null)
MenuItemsLoaded(this, e);
}
protected virtual void OnTabStripItemChanged(TabStripItemChangedEventArgs e)
{
if (TabStripItemSelectionChanged != null)
TabStripItemSelectionChanged(e);
}
protected virtual void OnMenuItemsLoad(EventArgs e)
{
menu.RightToLeft = RightToLeft;
menu.Items.Clear();
for (int i = 0; i < Items.Count; i++)
{
TabStripItem item = Items[i];
if (!item.Visible)
continue;
ToolStripMenuItem tItem = new ToolStripMenuItem(item.Title);
tItem.Tag = item;
tItem.Image = item.Image;
menu.Items.Add(tItem);
}
OnMenuItemsLoaded(EventArgs.Empty);
}
#endregion
#region Overrides
protected override void OnRightToLeftChanged(EventArgs e)
{
base.OnRightToLeftChanged(e);
UpdateLayout();
Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
SetDefaultSelected();
Rectangle borderRc = ClientRectangle;
borderRc.Width--;
borderRc.Height--;
if (RightToLeft == RightToLeft.No)
DEF_START_POS = 10;
else
DEF_START_POS = stripButtonRect.Right;
e.Graphics.DrawRectangle(SystemPens.ControlDark, borderRc);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
#region Draw Pages
for (int i = 0; i < Items.Count; i++)
{
TabStripItem currentItem = Items[i];
if (!currentItem.Visible && !DesignMode)
continue;
OnCalcTabPage(e.Graphics, currentItem);
currentItem.IsDrawn = false;
if (!AllowDraw(currentItem))
continue;
OnDrawTabPage(e.Graphics, currentItem);
}
#endregion
#region Draw UnderPage Line
if (RightToLeft == RightToLeft.No)
{
if (Items.DrawnCount == 0 || Items.VisibleCount == 0)
{
e.Graphics.DrawLine(SystemPens.ControlDark, new Point(0, DEF_HEADER_HEIGHT),
new Point(ClientRectangle.Width, DEF_HEADER_HEIGHT));
}
else if (SelectedItem != null && SelectedItem.IsDrawn)
{
Point end = new Point((int)SelectedItem.StripRect.Left - 9, DEF_HEADER_HEIGHT);
e.Graphics.DrawLine(SystemPens.ControlDark, new Point(0, DEF_HEADER_HEIGHT), end);
end.X += (int)SelectedItem.StripRect.Width + 10;
e.Graphics.DrawLine(SystemPens.ControlDark, end, new Point(ClientRectangle.Width, DEF_HEADER_HEIGHT));
}
}
else
{
if (Items.DrawnCount == 0 || Items.VisibleCount == 0)
{
e.Graphics.DrawLine(SystemPens.ControlDark, new Point(0, DEF_HEADER_HEIGHT),
new Point(ClientRectangle.Width, DEF_HEADER_HEIGHT));
}
else if (SelectedItem != null && SelectedItem.IsDrawn)
{
Point end = new Point((int)SelectedItem.StripRect.Left, DEF_HEADER_HEIGHT);
e.Graphics.DrawLine(SystemPens.ControlDark, new Point(0, DEF_HEADER_HEIGHT), end);
end.X += (int)SelectedItem.StripRect.Width + 20;
e.Graphics.DrawLine(SystemPens.ControlDark, end, new Point(ClientRectangle.Width, DEF_HEADER_HEIGHT));
}
}
#endregion
#region Draw Menu and Close Glyphs
if (AlwaysShowMenuGlyph || Items.DrawnCount > Items.VisibleCount)
menuGlyph.DrawGlyph(e.Graphics);
if (AlwaysShowClose || (SelectedItem != null && SelectedItem.CanClose))
closeButton.DrawCross(e.Graphics);
#endregion
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
HitTestResult result = HitTest(e.Location);
if (result == HitTestResult.MenuGlyph)
{
HandledEventArgs args = new HandledEventArgs(false);
OnMenuItemsLoading(args);
if (!args.Handled)
OnMenuItemsLoad(EventArgs.Empty);
ShowMenu();
}
else if (result == HitTestResult.CloseButton)
{
if (SelectedItem != null)
{
TabStripItemClosingEventArgs args = new TabStripItemClosingEventArgs(SelectedItem);
OnTabStripItemClosing(args);
if (!args.Cancel && SelectedItem.CanClose)
{
RemoveTab(SelectedItem);
OnTabStripItemClosed(EventArgs.Empty);
}
}
}
else if (result == HitTestResult.TabItem)
{
TabStripItem item = GetTabItemByPoint(e.Location);
if (item != null)
{
SelectedItem = item;
if (SelectedItemChanged != null)
SelectedItemChanged(new TabStripItemMouseEventArgs(item));
// Update the currently shown controls.
foreach (Control control in item.Controls)
control.Show();
// Somehow the right click doesn't work
// if we don't pass the thread to another
// function.
RightClick(e);
}
}
Invalidate();
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
CheckHot();
if (menuGlyph.Bounds.Contains(e.Location) == true)
{
menuGlyph.IsMouseOver = true;
Invalidate(menuGlyph.Bounds);
}
else
{
if (menuGlyph.IsMouseOver == true &&
menuOpen == false)
{
menuGlyph.IsMouseOver = false;
Invalidate(menuGlyph.Bounds);
}
}
if (closeButton.Bounds.Contains(e.Location) == true)
{
closeButton.IsMouseOver = true;
Invalidate(closeButton.Bounds);
}
else
{
if (closeButton.IsMouseOver == true)
{
closeButton.IsMouseOver = false;
Invalidate(closeButton.Bounds);
}
}
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
menuGlyph.IsMouseOver = false;
Invalidate(menuGlyph.Bounds);
closeButton.IsMouseOver = false;
Invalidate(closeButton.Bounds);
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
if (isIniting)
return;
UpdateLayout();
}
#endregion
#region Private
#region Non-drawing Methods
private void RightClick(MouseEventArgs e)
{
switch (e.Button)
{
case MouseButtons.Right:
if (rightClickMenu == null) { return; }
Point point = new Point(e.X, e.Y);
rightClickMenu.Show(this, point);
break;
case MouseButtons.Left:
break;
}
}
private bool AllowDraw(TabStripItem item)
{
bool result = true;
if (RightToLeft == RightToLeft.No)
{
if (item.StripRect.Right >= stripButtonRect.Width)
result = false;
}
else
{
if (item.StripRect.Left <= stripButtonRect.Left)
return false;
}
return result;
}
private void SetDefaultSelected()
{
if (selectedItem == null && Items.Count > 0)
SelectedItem = Items[0];
for (int i = 0; i < Items.Count; i++)
{
TabStripItem itm = Items[i];
itm.Dock = DockStyle.Fill;
}
}
private void OnMenuItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
TabStripItem clickedItem = (TabStripItem)e.ClickedItem.Tag;
SelectedItem = clickedItem;
if (SelectedItemChanged != null)
SelectedItemChanged(new TabStripItemMouseEventArgs(clickedItem));
// Update the currently shown controls.
foreach (Control control in clickedItem.Controls)
control.Show();
}
private void OnMenuVisibleChanged(object sender, EventArgs e)
{
if (menu.Visible == false)
{
menuOpen = false;
}
}
private void OnCollectionChanged(object sender, CollectionChangeEventArgs e)
{
TabStripItem itm = (TabStripItem)e.Element;
if (e.Action == CollectionChangeAction.Add)
{
Controls.Add(itm);
OnTabStripItemChanged(new TabStripItemChangedEventArgs(itm, TabStripItemChangeTypes.Added));
}
else if (e.Action == CollectionChangeAction.Remove)
{
Controls.Remove(itm);
OnTabStripItemChanged(new TabStripItemChangedEventArgs(itm, TabStripItemChangeTypes.Removed));
}
else
{
OnTabStripItemChanged(new TabStripItemChangedEventArgs(itm, TabStripItemChangeTypes.Changed));
}
UpdateLayout();
Invalidate();
}
#endregion
private void OnCalcTabPage(Graphics g, TabStripItem currentItem)
{
Font currentFont = Font;
if (currentItem == SelectedItem)
currentFont = new Font(Font, FontStyle.Bold);
SizeF textSize = g.MeasureString(currentItem.Title, currentFont, new SizeF(200, 10), sf);
textSize.Width += 20;
if (RightToLeft == RightToLeft.No)
{
RectangleF buttonRect = new RectangleF(DEF_START_POS, 3, textSize.Width, 17);
currentItem.StripRect = buttonRect;
DEF_START_POS += (int)textSize.Width;
}
else
{
RectangleF buttonRect = new RectangleF(DEF_START_POS - textSize.Width + 1, 3, textSize.Width - 1, 17);
currentItem.StripRect = buttonRect;
DEF_START_POS -= (int)textSize.Width;
}
}
private void OnDrawTabPage(Graphics g, TabStripItem currentItem)
{
bool isFirstTab = Items.IndexOf(currentItem) == 0;
Font currentFont = Font;
if (currentItem == SelectedItem)
currentFont = new Font(Font, FontStyle.Bold);
SizeF textSize = g.MeasureString(currentItem.Title, currentFont, new SizeF(200, 10), sf);
textSize.Width += 20;
RectangleF buttonRect = currentItem.StripRect;
GraphicsPath path = new GraphicsPath();
LinearGradientBrush brush;
int mtop = 3;
#region Draw Not Right-To-Left Tab
if (RightToLeft == RightToLeft.No)
{
if (currentItem == SelectedItem || isFirstTab)
{
path.AddLine(buttonRect.Left - 10, buttonRect.Bottom - 1,
buttonRect.Left + (buttonRect.Height / 2) - 3, mtop + 2);
}
else
{
path.AddLine(buttonRect.Left, buttonRect.Bottom - 1, buttonRect.Left,
buttonRect.Bottom - (buttonRect.Height / 2) - 3);
path.AddLine(buttonRect.Left, buttonRect.Bottom - (buttonRect.Height / 2) - 1,
buttonRect.Left + (buttonRect.Height / 2) - 3, mtop + 2);
}
path.AddLine(buttonRect.Left +
(buttonRect.Height / 2) + 2, mtop,
buttonRect.Right - 3, mtop);
path.AddLine(buttonRect.Right, mtop + 2,
buttonRect.Right, buttonRect.Bottom - 1);
path.AddLine(buttonRect.Right - 4,
buttonRect.Bottom - 1, buttonRect.Left,
buttonRect.Bottom - 1);
path.CloseFigure();
if (currentItem == currentHotItem &&
currentHotItem.IsHot == true)
{
brush = new LinearGradientBrush(buttonRect,
selectedColor1, selectedColor2,
LinearGradientMode.Vertical);
g.FillPath(brush, path);
g.DrawPath(new Pen(selectedBorderColor), path);
g.DrawLine(new Pen(brush), buttonRect.Left - 9, buttonRect.Height + 2,
buttonRect.Left + buttonRect.Width - 1, buttonRect.Height + 2);
PointF textLoc = new PointF(buttonRect.Left + buttonRect.Height - 4,
buttonRect.Top + (buttonRect.Height / 2) - (textSize.Height / 2)
- 3);
RectangleF textRect = buttonRect;
textRect.Location = textLoc;
textRect.Width = buttonRect.Width - (textRect.Left - buttonRect.Left) - 4;
textRect.Height = textSize.Height + currentFont.Size / 2;
g.DrawString(currentHotItem.Title, currentFont,
new SolidBrush(selectedForeColor), textRect, sf);
}
else
{
if (currentItem == SelectedItem)
{
brush = new LinearGradientBrush(buttonRect,
selectedColor1, selectedColor2,
LinearGradientMode.Vertical);
}
else
{
brush = new LinearGradientBrush(buttonRect,
normalColor1, normalColor2,
LinearGradientMode.Vertical);
}
g.FillPath(brush, path);
if (currentItem == SelectedItem)
g.DrawPath(new Pen(selectedBorderColor), path);
else
g.DrawPath(new Pen(normalBorderColor), path);
if (currentItem == SelectedItem)
{
g.DrawLine(new Pen(brush), buttonRect.Left - 9, buttonRect.
Height + 2, buttonRect.Left + buttonRect.Width - 1,
buttonRect.Height + 2);
}
PointF textLoc = new PointF(buttonRect.Left + buttonRect.Height - 4,
buttonRect.Top + (buttonRect.Height / 2) - (textSize.Height / 2)
- 3);
RectangleF textRect = buttonRect;
textRect.Location = textLoc;
textRect.Height = textSize.Height + currentFont.Size / 2;
textRect.Width = buttonRect.Width - (textRect.Left -
buttonRect.Left) - 4;
if (currentItem == SelectedItem)
{
g.DrawString(currentItem.Title, currentFont, new SolidBrush
(selectedForeColor), textRect, sf);
}
else
{
g.DrawString(currentItem.Title, currentFont, new SolidBrush
(normalForeColor), textRect, sf);
}
}
}
#endregion
#region Draw Right-To-Left Tab
if (RightToLeft == RightToLeft.Yes)
{
if (currentItem == SelectedItem || isFirstTab)
{
path.AddLine(buttonRect.Left - 10, buttonRect.Bottom - 1,
buttonRect.Left + (buttonRect.Height / 2) - 3, mtop + 2);
}
else
{
path.AddLine(buttonRect.Left, buttonRect.Bottom - 1, buttonRect.Left,
buttonRect.Bottom - (buttonRect.Height / 2) - 3);
path.AddLine(buttonRect.Left, buttonRect.Bottom - (buttonRect.Height / 2) - 1,
buttonRect.Left + (buttonRect.Height / 2) - 3, mtop + 2);
}
path.AddLine(buttonRect.Left +
(buttonRect.Height / 2) + 2, mtop,
buttonRect.Right - 3, mtop);
path.AddLine(buttonRect.Right, mtop + 2,
buttonRect.Right, buttonRect.Bottom - 1);
path.AddLine(buttonRect.Right - 4,
buttonRect.Bottom - 1, buttonRect.Left,
buttonRect.Bottom - 1);
path.CloseFigure();
if (currentItem == currentHotItem &&
currentHotItem.IsHot == true)
{
brush = new LinearGradientBrush(buttonRect,
selectedColor1, selectedColor2,
LinearGradientMode.Vertical);
g.FillPath(brush, path);
g.DrawPath(new Pen(selectedBorderColor), path);
g.DrawLine(new Pen(brush), buttonRect.Left - 9, buttonRect.Height + 2,
buttonRect.Left + buttonRect.Width - 1, buttonRect.Height + 2);
PointF textLoc = new PointF(buttonRect.Left + 2, buttonRect.Top + (buttonRect.Height / 2) - (textSize.Height / 2) - 2);
RectangleF textRect = buttonRect;
textRect.Location = textLoc;
textRect.Width = buttonRect.Width - (textRect.Left - buttonRect.Left) - 10;
textRect.Height = textSize.Height + currentFont.Size / 2;
if (hoverItem == SelectedItem)
textRect.Y -= 1;
g.DrawString(currentHotItem.Title, currentFont,
new SolidBrush(ForeColor), textRect, sf);
}
else
{
if (currentItem == SelectedItem)
brush = new LinearGradientBrush(buttonRect,
selectedColor1, selectedColor2,
LinearGradientMode.Vertical);
else
brush = new LinearGradientBrush(buttonRect,
normalColor1, normalColor2,
LinearGradientMode.Vertical);
g.FillPath(brush, path);
if (currentItem == SelectedItem)
g.DrawPath(new Pen(selectedBorderColor), path);
else
g.DrawPath(new Pen(normalBorderColor), path);
if (currentItem == SelectedItem)
{
g.DrawLine(new Pen(brush), buttonRect.Right + 9, buttonRect.Height + 2,
buttonRect.Right - buttonRect.Width + 1, buttonRect.Height + 2);
}
PointF textLoc = new PointF(buttonRect.Left + 2, buttonRect.Top + (buttonRect.Height / 2) - (textSize.Height / 2) - 2);
RectangleF textRect = buttonRect;
textRect.Location = textLoc;
textRect.Width = buttonRect.Width - (textRect.Left - buttonRect.Left) - 10;
textRect.Height = textSize.Height + currentFont.Size / 2;
if (currentItem == SelectedItem)
{
textRect.Y -= 1;
g.DrawString(currentItem.Title, currentFont, new SolidBrush(ForeColor), textRect, sf);
}
else
{
g.DrawString(currentItem.Title, currentFont, new SolidBrush(ForeColor), textRect, sf);
}
}
}
#endregion
currentItem.IsDrawn = true;
}
private void UpdateLayout()
{
if (RightToLeft == RightToLeft.No)
{
sf.Trimming = StringTrimming.EllipsisCharacter;
sf.FormatFlags |= StringFormatFlags.NoWrap;
sf.FormatFlags &= StringFormatFlags.DirectionRightToLeft;
stripButtonRect = new Rectangle(0, 0, ClientSize.Width - DEF_GLYPH_WIDTH - 2, 10);
menuGlyph.Bounds = new Rectangle(ClientSize.Width - DEF_GLYPH_WIDTH, 2, 16, 16);
closeButton.Bounds = new Rectangle(ClientSize.Width - 20, 2, 16, 16);
}
else
{
sf.Trimming = StringTrimming.EllipsisCharacter;
sf.FormatFlags |= StringFormatFlags.NoWrap;
sf.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
stripButtonRect = new Rectangle(DEF_GLYPH_WIDTH + 2, 0, ClientSize.Width - DEF_GLYPH_WIDTH - 15, 10);
closeButton.Bounds = new Rectangle(4, 2, 16, 16);
menuGlyph.Bounds = new Rectangle(20 + 4, 2, 16, 16);
}
DockPadding.Top = DEF_HEADER_HEIGHT + 1;
DockPadding.Bottom = 1;
DockPadding.Right = 1;
DockPadding.Left = 1;
}
#region Tab EventHandlers
private void OnTabMouseEnter(TabStripItemMouseEventArgs e)
{ Invalidate(); }
private void OnTabMouseLeave(TabStripItemMouseEventArgs e)
{ Invalidate(); }
#endregion
#endregion
#endregion
#region ShouldSerialize
public bool ShouldSerializeFont()
{
return Font != null && !Font.Equals(defaultFont);
}
public bool ShouldSerializeSelectedItem()
{
return true;
}
public bool ShouldSerializeItems()
{
return items.Count > 0;
}
public new void ResetFont()
{
Font = defaultFont;
}
#endregion
#region ISupportInitialize Members
public void BeginInit()
{
isIniting = true;
}
public void EndInit()
{
isIniting = false;
}
#endregion
#region IDisposable
protected override void Dispose(bool disposing)
{
if (disposing)
{
items.CollectionChanged -= new CollectionChangeEventHandler(OnCollectionChanged);
menu.ItemClicked -= new ToolStripItemClickedEventHandler(OnMenuItemClicked);
menu.VisibleChanged -= new EventHandler(OnMenuVisibleChanged);
foreach (TabStripItem item in items)
{
if (item != null && !item.IsDisposed)
item.Dispose();
}
if (menu != null && !menu.IsDisposed)
menu.Dispose();
if (sf != null)
sf.Dispose();
}
base.Dispose(disposing);
}
#endregion
/// <summary>
/// Initializes the TabStrip.
/// </summary>
public TabStrip()
{
BeginInit();
SetStyle(ControlStyles.ContainerControl, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.Selectable, true);
items = new TabStripItemCollection();
items.CollectionChanged += new CollectionChangeEventHandler(OnCollectionChanged);
base.Size = new Size(350, 200);
menu = new ContextMenuStrip();
menu.Renderer = ToolStripRenderer;
menu.ItemClicked += new ToolStripItemClickedEventHandler(OnMenuItemClicked);
menu.VisibleChanged += new EventHandler(OnMenuVisibleChanged);
menuGlyph = new TabStripMenuGlyph(ToolStripRenderer);
closeButton = new TabStripCloseButton(ToolStripRenderer);
Font = defaultFont;
sf = new StringFormat();
normalColor1 = Color.FromArgb(227, 239, 255);
normalColor2 = Color.FromArgb(152, 186, 230);
normalBorderColor = normalColor2;
selectedColor1 = Color.FromArgb(255, 255, 255);
selectedColor2 = Color.FromArgb(111, 157, 217);
selectedBorderColor = normalColor2;
selectedForeColor = Color.Black;
normalForeColor = Color.Black;
EndInit();
UpdateLayout();
}
}
}