RaUI/Source/ryControls/Gdu.WinFormUI/Forms/MdiBarController.cs

1384 lines
45 KiB
C#
Raw Normal View History

/*
*
* 使
* 使ping3108@163.com,
*/
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using MGdu.WinFormUI.MyGraphics;
//忽略没有注释警告
#pragma warning disable 1591
namespace MGdu.WinFormUI
{
/// <summary>
/// 该类处理mdi-bar的绘制及鼠标事件管理
/// </summary>
internal class MdiBarController
{
#region private var
GMForm _owner;
public List<MdiGMTabItem> _listTabItems { get; private set; }
// 有时候可能有很多tab,不能全部显示,那么就用两个变量来标识
// 是第几个到第几个tab被显示出来了。
int _beginShowIndex;
int _endShowIndex;
int _activeTabIndex;
// 有多少tab被隐藏了
int _hiddenTabsCount;
Point _lastMouseUpLocation;
WLButton _newTabBtn;
WLButton _listAllBtn;
EventHandler _newTabBtnClick;
EventHandler _tabCloseBtnClick;
ContextMenuStrip _menuPopup;
private Rectangle _hitTestBounds;
#endregion
#region event & event handler
public event EventHandler NewTabButtonClick
{
add { _newTabBtnClick = value; }
remove { _newTabBtnClick = null; }
}
public event EventHandler TabCloseButtonClick
{
add { _tabCloseBtnClick = value; }
remove { _tabCloseBtnClick = null; }
}
private void OnNewTabBtnClick(object sender, EventArgs e)
{
_newTabBtnClick?.Invoke(this, EventArgs.Empty);
}
private void OnTabCloseBtnClick(object sender, EventArgs e)
{
if (sender is Form f)
{
_tabCloseBtnClick?.Invoke(f, EventArgs.Empty);
}
}
private void OnListAllBtnClick(object sender, EventArgs e)
{
if (_listTabItems.Count < 1)
return;
foreach (MdiGMTabItem tab in _listTabItems)
{
if (tab.IsFormActive)
{
tab.MenuItemPop.Checked = true;
tab.MenuItemPop.Image = null;
}
else
{
tab.MenuItemPop.Checked = false;
tab.MenuItemPop.Image = tab.Form.Icon.ToBitmap();
}
tab.MenuItemPop.Text = tab.Form.Text;
if (!tab.IsHidden)
tab.MenuItemPop.Font = new Font(tab.MenuItemPop.Font, FontStyle.Bold);
else
tab.MenuItemPop.Font = new Font(tab.MenuItemPop.Font, FontStyle.Regular);
}
_menuPopup.Show(_owner, ListAllBtnBounds.Left, ListAllBtnBounds.Bottom);
}
private void OnActivateChild(Form child)
{
if (child != _owner.ActiveMdiChild)
{
_owner.OnBeforeActivate();
if (_owner.XTheme.Mdi_UseMsgToActivateChild)
_owner.ActivateMdiChildForm(child);
else
child.Activate();
_owner.OnEndActivate();
}
}
private void OnPopMenuItemClick(object sender, EventArgs e)
{
if (sender is ToolStripMenuItem ctl)
{
if (ctl.Tag is Form f)
{
OnActivateChild(f);
}
}
}
#endregion
#region Constructor & initial
public MdiBarController(GMForm owner)
{
_owner = owner;
_listTabItems = new List<MdiGMTabItem>();
_newTabBtn = new WLButton(owner);
_listAllBtn = new WLButton(owner);
// ini _newtabbtn
_newTabBtn.ColorTable = NewTabBtnColor;
_newTabBtn.Click += new EventHandler(OnNewTabBtnClick);
_newTabBtn.ForePathGetter = new ButtonForePathGetter(
MGdu.WinFormUI.MyGraphics.GraphicsPathHelper.CreatePlusFlag);
_listAllBtn.ColorTable = ListAllBtnColor;
_listAllBtn.Click +=new EventHandler(OnListAllBtnClick);
_listAllBtn.ForePathGetter = new ButtonForePathGetter(
MGdu.WinFormUI.MyGraphics.GraphicsPathHelper.CreateDownTriangleFlag);
_listAllBtn.ForePathSize = new Size(10, 9);
_listAllBtn.ForeFont = new Font("微软雅黑", 8);
_menuPopup = new ContextMenuStrip();
}
#endregion
#region editable properties from thmem info
/// <summary>
/// use left,top,right to location the bar in owner form,
/// the margin is from Form.ClientRectangle
/// </summary>
public Padding Margin
{
get { return _owner.XTheme.Mdi_BarMargin; }
}
/// <summary>
/// 整个标签栏高度,包含标签栏底部区域、标签、标签顶部空隙
/// </summary>
public int BarHeight
{
get { return BarBottomRegionHeight + Math.Max(TabHeight, TabHeightActive) + TabTopSpace; }
}
/// <summary>
/// 标签栏底部区域的高度
/// </summary>
public int BarBottomRegionHeight
{
get { return _owner.XTheme.Mdi_BarBottomRegionHeight; }
}
/// <summary>
/// 是否显示标签栏边框
/// </summary>
public bool DrawBarBorder
{
get { return _owner.XTheme.Mdi_DrawBarBorder; }
}
/// <summary>
/// 是否显示标签栏背景
/// </summary>
public bool DrawBarBackgound
{
get { return _owner.XTheme.Mdi_DrawBarBackground; }
}
/// <summary>
///标签栏左内边距
/// </summary>
public int BarLeftPadding
{
get { return _owner.XTheme.Mdi_BarLeftPadding; }
}
/// <summary>
/// 标签栏右内边距
/// </summary>
public int BarRightPadding
{
get { return _owner.XTheme.Mdi_BarRightPadding; }
}
/// <summary>
/// 标签高度
/// </summary>
public int TabHeight
{
get { return _owner.XTheme.Mdi_TabHeight; }
}
/// <summary>
/// 激活的标签高度
/// </summary>
public int TabHeightActive
{
get { return _owner.XTheme.Mdi_TabHeightActive; }
}
/// <summary>
/// tab顶部与bar顶部的空间,这个值用来计算 BarHeight
/// </summary>
public int TabTopSpace
{
get { return _owner.XTheme.Mdi_TabTopSpace; }
}
/// <summary>
/// 每个标签的左右边界可以不是垂直的,而是都有一个斜度
/// </summary>
public int TabSlopeWidth
{
get { return _owner.XTheme.Mdi_TabSlopeWidth; }
}
/// <summary>
/// tab与tab之间的距离用负值可以使tab有重叠的效果
/// </summary>
public int TabAndTabSpace
{
get { return _owner.XTheme.Mdi_TabAndTabSpace; }
}
/// <summary>
/// 标签是否显示图标
/// </summary>
public bool ShowTabIcon
{
get { return _owner.XTheme.Mdi_ShowTabIcon; }
}
/// <summary>
/// 是否显示标签关闭按钮
/// </summary>
public bool ShowTabCloseIcon
{
get { return _owner.XTheme.Mdi_ShowTabCloseIcon; }
}
/// <summary>
/// 标签图标大小
/// </summary>
public Size IconSize
{
get { return ShowTabIcon ? new Size(16, 16) : Size.Empty; }
}
/// <summary>
/// 标签图标距离左边的距离
/// </summary>
public int IconLeftSpace
{
get { return TabSlopeWidth + (ShowTabIcon ? 2 : 0); }
}
/// <summary>
/// 标签文字距离左边的距离
/// </summary>
public int TextLeftSpace
{
get { return 2; }
}
/// <summary>
/// 标签关闭按钮的大小
/// </summary>
public Size TabCloseBtnSize
{
get { return new Size(16, 16); }
}
/// <summary>
/// 标签关闭按钮距离右边的距离
/// </summary>
public int TabCloseBtnRightSpace
{
get { return TabSlopeWidth + 2; }
}
/// <summary>
/// 是否显示新建标签按钮
/// </summary>
public bool ShowNewTabBtn
{
get { return _owner.XTheme.Mdi_ShowNewTabBtn; }
}
/// <summary>
/// 新建标签按钮的大小
/// </summary>
public Size NewTabBtnSize
{
get { return _owner.XTheme.Mdi_NewTabBtnSize; }
}
public Rectangle NewTabBtnBounds
{
get;
set;
}
/// <summary>
/// 新建标签距离左边的距离
/// </summary>
public int NewTabBtnLeftSpace
{
get { return _owner.XTheme.Mdi_NewTabBtnLeftSpace; }
}
/// <summary>
/// 按钮与Bar底部的距离
/// </summary>
public int NewTabBtnBottomSpace
{
get { return _owner.XTheme.Mdi_NewTabBtnBottomSpace; }
}
public Rectangle ListAllBtnBounds { get; set; }
public Size ListAllBtnSize
{
get { return _owner.XTheme.Mdi_ListAllBtnSize; }
}
public int ListAllBtnLeftSpace
{
get { return _owner.XTheme.Mdi_ListAllBtnLeftSpace; }
}
public int ListAllBtnBottomSpace
{
get { return _owner.XTheme.Mdi_ListAllBtnBottomSpace; }
}
public BarButtonAlignmentType ListAllBtnAlign
{
get { return _owner.XTheme.Mdi_ListAllBtnAlign; }
}
public bool AlwaysShowListAllBtn
{ get { return _owner.XTheme.Mdi_AlwaysShowListAllBtn; } }
/// <summary>
/// 一个tab允许的最小宽度
/// </summary>
public int TabMinWidth
{
get
{
return Math.Max(TabSlopeWidth * 2 + IconLeftSpace + IconSize.Width
+ TabCloseBtnRightSpace + TabCloseBtnSize.Width + 36,
_owner.XTheme.Mdi_TabMinWidth);
}
}
/// <summary>
/// 一个tab允许的最大显示宽度
/// </summary>
public int TabMaxWidth
{
get { return _owner.XTheme.Mdi_TabMaxWidth; }
}
/// <summary>
/// 标签正常宽度
/// </summary>
public int TabNormalWidth
{
get { return _owner.XTheme.Mdi_TabNormalWidth; }
}
#region bar & tab color
public Color BarBorderColor
{
get { return _owner.XTheme.Mdi_BarBorderColor; }
}
public Color BarBackColor
{
get { return _owner.XTheme.Mdi_BarBackColor; }
}
public Color TabOutterBorderColor
{
get { return _owner.XTheme.Mdi_TabOutterBorderColor; }
}
public Color TabInnerBorderColor
{
get { return _owner.XTheme.Mdi_TabInnerBorderColor; }
}
public bool TabShowBorder
{
get { return _owner.XTheme.Mdi_TabShowBorder; }
}
public Color TabActiveBackColorTop
{
get { return _owner.XTheme.Mdi_TabActiveBackColorTop; }
}
public Color TabActiveBackColorBottom
{
get { return _owner.XTheme.Mdi_TabActiveBackColorBottom; }
}
public Color TabDeactiveBackColorTop
{
get { return _owner.XTheme.Mdi_TabDeactiveBackColorTop; }
}
public Color TabDeactiveBackColorBottom
{
get { return _owner.XTheme.Mdi_TabDeactiveBackColorBottom; }
}
public Color BarBottomRegionBackColor
{
get { return _owner.XTheme.Mdi_BarBottomRegionBackColor; }
}
public Color TabActiveForeColor
{
get { return _owner.XTheme.Mdi_TabActiveForeColor; }
}
public Color TabDeactiveForeColor
{
get { return _owner.XTheme.Mdi_TabDeactiveForeColor; }
}
#endregion
#region tab btn color
public ButtonColorTable NewTabBtnColor
{
get { return _owner.XTheme.Mdi_NewTabBtnColor; }
}
public ButtonColorTable ListAllBtnColor
{
get { return _owner.XTheme.Mdi_ListAllBtnColor; }
}
public ButtonColorTable TabCloseBtnColor
{
get { return ButtonColorTable.GetDefaultCloseBtnColor(); }
}
#endregion
#endregion
#region Calculated Properties
public int BarWidth
{
get { return _owner.ClientSize.Width - Margin.Left - Margin.Right; }
}
public Rectangle Bounds
{
get
{
return new Rectangle(
_owner.ClientRectangle.Left + Margin.Left,
_owner.ClientRectangle.Top + Margin.Top,
BarWidth,
BarHeight);
}
}
public Rectangle BarBottomRegionBounds
{
get
{
return new Rectangle(
Bounds.Left,
Bounds.Top + (Bounds.Height - BarBottomRegionHeight),
BarWidth,
BarBottomRegionHeight);
}
}
public Rectangle HitTestBounds
{
get { return _hitTestBounds; }
}
#endregion
#region private method
private MdiGMTabItem CreateNewTab(Form f)
{
MdiGMTabItem tab = new MdiGMTabItem(this);
tab.Form = f;
tab.CloseBtn = new WLButton(_owner)
{
ColorTable = TabCloseBtnColor,
BorderType = ButtonBorderType.Ellipse,
DrawForePathTwice = true,
//tab.CloseBtn.DrawLightGlass = true;
ClickSendBackOject = f,
ForePathGetter = new
ButtonForePathGetter(MGdu.WinFormUI.MyGraphics.GraphicsPathHelper.CreateSingleLineCloseFlag)
};
tab.CloseBtn.Click += new EventHandler(OnTabCloseBtnClick);
// menu item
tab.MenuItemPop = new ToolStripMenuItem();
tab.MenuItemPop.Tag = f;
tab.MenuItemPop.Click += new EventHandler(OnPopMenuItemClick);
_menuPopup.Items.Add(tab.MenuItemPop);
return tab;
}
/// <summary>
/// 同步_listTabItems与mdi主窗体实际存在的子form
/// </summary>
private void CheckTabItemsWithOwnerMdiForm()
{
List<Form> listCurrent = _owner.GetCurrentMdiChildren();
List<Form> newForm = new List<Form>();
foreach (MdiGMTabItem tab in _listTabItems)
tab.IsStillValid = false;
foreach (Form f in listCurrent)
{
MdiGMTabItem tab;
if (IsTabItemsContaining(f, out tab))
tab.IsStillValid = true;
else
newForm.Add(f);
}
// remove the closed form tab
for (int i = _listTabItems.Count - 1; i >= 0; i--)
if (!_listTabItems[i].IsStillValid)
{
_menuPopup.Items.Remove(_listTabItems[i].MenuItemPop);
_listTabItems[i].MenuItemPop.Dispose();
_listTabItems.RemoveAt(i);
}
// create tabs for newly added forms
foreach (Form f in newForm)
{
_listTabItems.Add(CreateNewTab(f));
}
// find the active tab
int j = 0;
foreach (MdiGMTabItem tab in _listTabItems)
{
if (tab.Form == _owner.ActiveMdiChild)
{
_activeTabIndex = j;
tab.IsFormActive = true;
}
else
tab.IsFormActive = false;
j++;
}
}
private bool IsTabItemsContaining(Form f, out MdiGMTabItem theTab)
{
theTab = null;
foreach (MdiGMTabItem tab in _listTabItems)
{
if (f == tab.Form)
{
theTab = tab;
return true;
}
}
return false;
}
/// <summary>
/// 为每个tab分配空间如果tab数目太多则有些会被隐藏
/// </summary>
private void CalculateSpaceForEachTab()
{
int beginOld = _beginShowIndex;
int endOld = _endShowIndex;
_beginShowIndex = 0;
_endShowIndex = _listTabItems.Count - 1;
_hiddenTabsCount = 0;
int availableWidth = BarWidth - BarLeftPadding - BarRightPadding;
if (ShowNewTabBtn)
availableWidth -= (NewTabBtnSize.Width + NewTabBtnLeftSpace);
if (AlwaysShowListAllBtn)
availableWidth -= (ListAllBtnSize.Width + ListAllBtnLeftSpace * 2);
//int tabCount = _listTabItems.Count;
int widthAll = 0;
int tabShorterThanNormalCount = 0;
int tabLongerThanMinWidthCount = 0;
int index = 0;
foreach (MdiGMTabItem tab in _listTabItems)
{
tab.FinalWidth = tab.GetFullShowTabWidth();
widthAll += (tab.FinalWidth + (index > 0 ? TabAndTabSpace : 0));
if (tab.FinalWidth < TabNormalWidth)
tabShorterThanNormalCount++;
if (tab.FinalWidth > TabMinWidth && index != _activeTabIndex)
tabLongerThanMinWidthCount++;
index++;
}
if (widthAll <= availableWidth)
{
#region 1.
int extraWidth = availableWidth - widthAll;
//把剩余的空间分配给那些还没有达到normal宽度的tab
index=0;
while (extraWidth > 0 && tabShorterThanNormalCount > 0)
{
if (_listTabItems[index].FinalWidth < TabNormalWidth)
{
if (extraWidth > 2)
{
_listTabItems[index].FinalWidth += 2;
extraWidth -= 2;
}
else
{
_listTabItems[index].FinalWidth += extraWidth;
extraWidth = 0;
}
if (_listTabItems[index].FinalWidth >= TabNormalWidth)
tabShorterThanNormalCount--;
}
index++;
if (index >= _listTabItems.Count)
index = 0;
}
return;
#endregion
}
// 空间有限不能以全文本方式显示所有tab则统一缩小非active的tab
int neededWidth = widthAll - availableWidth;
#region active tab,tabminwidth
// 统一缩小非active-tab看是否能在所有tab达到min宽度前腾出空间
index = 0;
while (neededWidth > 0 && tabLongerThanMinWidthCount > 0)
{
if (_listTabItems[index].FinalWidth > TabMinWidth && index != _activeTabIndex)
{
int diff = _listTabItems[index].FinalWidth - TabMinWidth;
if (diff > 2)
{
_listTabItems[index].FinalWidth -= 2;
neededWidth -= 2;
}
else
{
_listTabItems[index].FinalWidth = TabMinWidth;
neededWidth -= diff;
}
if (_listTabItems[index].FinalWidth <= TabMinWidth)
tabLongerThanMinWidthCount--;
}
index++;
if (index >= _listTabItems.Count)
index = 0;
}
#endregion
if (neededWidth <= 0)
{
// 2. 缩小非actvie-tab后可以全部显示
return;
}
if ((_listTabItems[_activeTabIndex].FinalWidth > TabNormalWidth))
{
// 若active-tab的宽度大于normal则逐渐减小到normal
int width = _listTabItems[_activeTabIndex].FinalWidth;
while (width > TabNormalWidth && neededWidth > 0)
{
width--;
neededWidth--;
}
_listTabItems[_activeTabIndex].FinalWidth = width;
if (neededWidth <= 0)
{
// 3. 缩小active-tab达到normal宽度后可以显示全部标签
return;
}
}
#region 4. tab
if (!AlwaysShowListAllBtn)
{
availableWidth -= (ListAllBtnSize.Width + ListAllBtnLeftSpace * 2);
neededWidth += (ListAllBtnSize.Width + ListAllBtnLeftSpace * 2);
}
if (availableWidth < _listTabItems[_activeTabIndex].FinalWidth)
{
_listTabItems[_activeTabIndex].FinalWidth = availableWidth;
if (availableWidth < (TabCloseBtnSize.Width + TabSlopeWidth * 2))
_listTabItems[_activeTabIndex].FinalWidth = TabCloseBtnSize.Width + TabSlopeWidth * 2;
}
_hiddenTabsCount = neededWidth / (TabMinWidth + TabAndTabSpace);
if ((neededWidth % (TabMinWidth + TabAndTabSpace)) != 0)
_hiddenTabsCount++;
if (_hiddenTabsCount >= _listTabItems.Count)
_hiddenTabsCount = _listTabItems.Count - 1;
//先看一下之前所隐藏的tab数是否与将要隐藏的tab数一致如果一致
//且不影响active的显示则不需要改变之前所隐藏的tab
//若不行,则简单点,先隐藏右边,不够的再隐藏左边
#region tabs被隐藏
int showTabCount = endOld - beginOld + 1;
if ((_listTabItems.Count - _hiddenTabsCount) == showTabCount)
{
if (endOld > _listTabItems.Count - 1)
{
endOld = _listTabItems.Count - 1;
beginOld = endOld - showTabCount + 1;
}
if (beginOld <= _activeTabIndex && endOld >= _activeTabIndex)
{
_beginShowIndex = beginOld;
_endShowIndex = endOld;
}
else
{
//平移一下使_actvieTabIndex包含其中
if (_activeTabIndex < beginOld)
{
_beginShowIndex = _activeTabIndex;
_endShowIndex = _activeTabIndex + showTabCount - 1;
}
else
{
_endShowIndex = _activeTabIndex;
_beginShowIndex = _activeTabIndex - showTabCount + 1;
}
}
}
else
{
//先隐藏右边,不够的再隐藏左边
int tabCntAfterActive = _listTabItems.Count - (_activeTabIndex + 1);
if (tabCntAfterActive >= _hiddenTabsCount)
{
_beginShowIndex = 0;
_endShowIndex = _listTabItems.Count - 1 - _hiddenTabsCount;
}
else
{
_beginShowIndex = _hiddenTabsCount - tabCntAfterActive;
_endShowIndex = _activeTabIndex;
}
}
#endregion
// 再次把多出的空间重新分配给能显示的tab
int remainWidth = _hiddenTabsCount * (TabMinWidth + TabAndTabSpace) - neededWidth;
if (remainWidth > (_endShowIndex - _beginShowIndex + 1) * 3)
{
int average = remainWidth / (_endShowIndex - _beginShowIndex + 1);
for (int i = _beginShowIndex; i <= _endShowIndex; i++)
_listTabItems[i].FinalWidth += average;
}
#endregion
}
private void SetTabsVisibility()
{
for (int i = 0; i < _listTabItems.Count; i++)
{
if (i >= _beginShowIndex && i <= _endShowIndex)
_listTabItems[i].IsHidden = false;
else
_listTabItems[i].IsHidden = true;
}
}
private void SetTabsAndBarButtonBounds()
{
if (ListAllBtnAlign == BarButtonAlignmentType.Left)
{
SetListAllBtnBounds();
SetEachTabBounds();
SetNewTabBtnBounds();
}
else
{
SetEachTabBounds();
SetNewTabBtnBounds();
SetListAllBtnBounds();
}
SetHitTestBounds();
}
private void SetHitTestBounds()
{
int right = Bounds.Right - BarRightPadding;
if(ListAllBtnAlign != BarButtonAlignmentType.Left &&
(AlwaysShowListAllBtn || _hiddenTabsCount>0))
{
right = ListAllBtnBounds.Right;
}
else if (ShowNewTabBtn)
{
right = NewTabBtnBounds.Right;
}
else if (_listTabItems.Count > 0 && _endShowIndex < _listTabItems.Count)
{
right = _listTabItems[_endShowIndex].Bounds.Right;
}
int left = Bounds.Left + BarLeftPadding;
int width = right - left;
_hitTestBounds = new Rectangle(left, Bounds.Top, width, Bounds.Height);
}
private void SetEachTabBounds()
{
int x = Bounds.X + BarLeftPadding;
if (ListAllBtnAlign == BarButtonAlignmentType.Left)
{
if (AlwaysShowListAllBtn || _hiddenTabsCount > 0)
{
x = ListAllBtnBounds.Right + ListAllBtnLeftSpace;
}
}
if (_listTabItems.Count > 0)
{
for (int i = _beginShowIndex; i <= _endShowIndex; i++)
{
int height = _listTabItems[i].IsFormActive ? TabHeightActive : TabHeight;
int y = Bounds.Bottom - BarBottomRegionHeight - height;
int w = _listTabItems[i].FinalWidth;
_listTabItems[i].Bounds = new Rectangle(x, y, w, height);
x += (w + TabAndTabSpace);
}
}
}
private void SetNewTabBtnBounds()
{
int tabsCount = _listTabItems.Count;
int x;
if (tabsCount > 0 && _endShowIndex < tabsCount)
{
x = _listTabItems[_endShowIndex].Bounds.Right + NewTabBtnLeftSpace;
if (x > (Bounds.Right - BarRightPadding - NewTabBtnSize.Width))
x = Bounds.Right - BarRightPadding - NewTabBtnSize.Width;
if (x < Bounds.Left + BarLeftPadding)
x = Bounds.Left + BarLeftPadding;
}
else
{
x = Bounds.Left + BarLeftPadding;
if (ListAllBtnAlign == BarButtonAlignmentType.Left)
x = ListAllBtnBounds.Right + ListAllBtnLeftSpace;
}
int y = Bounds.Bottom - NewTabBtnBottomSpace - NewTabBtnSize.Height;
var size = ShowNewTabBtn ? NewTabBtnSize : Size.Empty;
if (size.Width > Bounds.Width)
size.Width = Bounds.Width;
NewTabBtnBounds = new Rectangle(new Point(x, y), size);
}
private void SetListAllBtnBounds()
{
int x;
if (ListAllBtnAlign == BarButtonAlignmentType.Left)
{
x = Bounds.X + BarLeftPadding;
}
else
{
x = NewTabBtnBounds.Right;
if (ShowNewTabBtn || _listTabItems.Count > 0)
x += ListAllBtnLeftSpace;
if (x > (Bounds.Right - BarRightPadding - ListAllBtnSize.Width))
x = Bounds.Right - BarRightPadding - ListAllBtnSize.Width;
}
int y = Bounds.Bottom - ListAllBtnBottomSpace - ListAllBtnSize.Height;
var size = ((_hiddenTabsCount>0 || AlwaysShowListAllBtn) ? ListAllBtnSize : Size.Empty);
if (size.Width > Bounds.Width)
size.Width = Bounds.Width;
ListAllBtnBounds = new Rectangle(new Point(x, y), size);
}
private void RenderEachBarItem(Graphics g)
{
Region oldClip = g.Clip;
Region newClip = new Region(Bounds);
g.Clip = newClip;
SmoothingMode oldMode = g.SmoothingMode;
g.SmoothingMode = SmoothingMode.AntiAlias;
DrawBarBorderAndBackground(g);
DrawEachTabItem(g);
DrawOtherBarButtons(g);
DrawBarBottomRegion(g);
g.SmoothingMode = oldMode;
g.Clip = oldClip;
newClip.Dispose();
}
private void DrawBarBorderAndBackground(Graphics g)
{
Rectangle rect = Bounds;
if (DrawBarBackgound)
{
using (SolidBrush sb = new SolidBrush(BarBackColor))
{
g.FillRectangle(sb, rect);
}
}
if (DrawBarBorder)
{
rect.Width--;
rect.Height--;
using (Pen p = new Pen(BarBorderColor))
{
g.DrawRectangle(p, rect);
}
}
}
private void DrawBarBottomRegion(Graphics g)
{
// bottom region
using (SolidBrush sb = new SolidBrush(BarBottomRegionBackColor))
{
using (NewSmoothModeGraphics newGP = new NewSmoothModeGraphics(g, SmoothingMode.HighSpeed))
{
g.FillRectangle(sb, BarBottomRegionBounds);
}
}
}
private void DrawOtherBarButtons(Graphics g)
{
// new-tab-btn
if (ShowNewTabBtn)
{
_newTabBtn.Bounds = NewTabBtnBounds;
_newTabBtn.DrawButton(g);
}
// list-all-btn
if (_hiddenTabsCount > 0 || AlwaysShowListAllBtn)
{
_listAllBtn.Bounds = ListAllBtnBounds;
if (_hiddenTabsCount == 0)
_listAllBtn.Text = string.Empty;
else
_listAllBtn.Text = _hiddenTabsCount.ToString();
_listAllBtn.DrawButton(g);
}
}
private void DrawEachTabItem(Graphics g)
{
foreach (MdiGMTabItem tab in _listTabItems)
{
if (!tab.IsHidden && !tab.IsFormActive)
RenderTabItem(g, tab);
}
// active-tab last
if (_listTabItems.Count > 0)
RenderTabItem(g, _listTabItems[_activeTabIndex]);
}
private void RenderTabItem(Graphics g, MdiGMTabItem tab)
{
Rectangle rect = tab.Bounds;
Region oldRegion = g.Clip;
Region newRegion = new Region(rect);
g.Clip = newRegion;
// fill backgroung
Color backTop,backBottom;
if (tab.IsFormActive)
{
backTop = TabActiveBackColorTop;
backBottom = TabActiveBackColorBottom;
}
else
{
backTop = TabDeactiveBackColorTop;
backBottom = TabDeactiveBackColorBottom;
}
// background
using (LinearGradientBrush lb = new LinearGradientBrush(
rect, backTop, backBottom, LinearGradientMode.Vertical))
{
using (GraphicsPath path = PathGetter.GetTabBorderPath(rect, TabSlopeWidth))
{
g.FillPath(lb, path);
}
}
// icon
if (ShowTabIcon && tab.Form.Icon != null)
{
if (tab.IconRect.Right < tab.Bounds.Right)
g.DrawIcon(tab.Form.Icon, tab.IconRect);
}
if (tab.IsFormActive)
{
// text
TextRenderer.DrawText(g, tab.Form.Text, tab.Form.Font, tab.TextRect,TabActiveForeColor,
TextFormatFlags.Left | TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis);
}
else
{
TextRenderer.DrawText(g, tab.Form.Text, tab.Form.Font, tab.TextRect, TabDeactiveForeColor,
TextFormatFlags.Left | TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis);
}
// outter border
rect.Width--;
rect.Height--;
if (TabShowBorder)
{
using (Pen p = new Pen(TabOutterBorderColor))
{
if (tab.IsFormActive)
{
Rectangle rectTab = tab.Bounds;
Rectangle rectBottom = BarBottomRegionBounds;
Point p1 = new Point(rectBottom.X, rectBottom.Y - 1);
Point p2 = new Point(rectTab.X, rectTab.Bottom - 1);
Point p3 = new Point(rectTab.X + TabSlopeWidth, rectTab.Y);
Point p4 = new Point(rectTab.Right - 1 - TabSlopeWidth, rectTab.Y);
Point p5 = new Point(rectTab.Right - 1, rectTab.Bottom - 1);
Point p6 = new Point(rectBottom.Right - 1, rectBottom.Y - 1);
g.Clip = oldRegion;
//g.DrawLines(p, new Point[] { p1, p2, p3, p4, p5, p6 });
g.Clip = newRegion;
}
else
{
using (GraphicsPath path = PathGetter.GetTabBorderPath(rect, TabSlopeWidth))
{
//g.DrawPath(p, path);
}
}
}
}
// inner border
rect.Inflate(-1, -1);
rect.Height++; // 为了使bar-bottom-region 与 active-tab 的连线能覆盖非 active-tab 的底部的线
if (TabShowBorder)
{
using (Pen p = new Pen(TabInnerBorderColor))
{
using (GraphicsPath path = PathGetter.GetTabBorderPath(rect, TabSlopeWidth))
{
g.DrawPath(p, path);
}
}
}
// do not let the active-tab to have bottom-line
if (tab.IsFormActive)
{
Rectangle rtmp = tab.Bounds;
Point p1 = new Point(rtmp.Left + 1, rtmp.Bottom - 1);
Point p2 = new Point(rtmp.Right - 2, rtmp.Bottom - 1);
using (Pen pen = new Pen(backBottom))
{
g.DrawLine(pen, p1, p2);
}
}
if (ShowTabCloseIcon)
{
//close btn
tab.CloseBtn.Bounds = tab.CloseBtnRect;
tab.CloseBtn.DrawButton(g);
}
g.Clip = oldRegion;
newRegion.Dispose();
}
#region mouse operation
private void MouseOperationDown(Point location)
{
try
{
for (int i = 0; i < _listTabItems.Count; i++)
{
MdiGMTabItem tab = _listTabItems[i];
if (!tab.IsHidden)
{
if (tab.Bounds.Contains(location) && !tab.CloseBtnRect.Contains(location))
{
tab.Capture = true;
break;
}
}
}
}
catch {}
}
private void MouseOperationUp(Point location)
{
try
{
for (int i = 0; i < _listTabItems.Count; i++)
{
MdiGMTabItem tab = _listTabItems[i];
if (!tab.IsHidden)
{
if (tab.Capture && tab.Bounds.Contains(location))
{
tab.Capture = false;
OnActivateChild(tab.Form);
//break;
}
}
tab.Capture = false;
}
}
catch{}
}
#endregion
#endregion
#region public method
/// <summary>
/// 重绘整个标签栏
/// </summary>
/// <param name="g"></param>
public void RenderTheBar(Graphics g)
{
// 先把已关闭的form对应的tab删除对新加的form则为其创建相应tab
CheckTabItemsWithOwnerMdiForm();
if (_listTabItems.Count > 0)
{
// 按照指定方式为每个tab分配空间
CalculateSpaceForEachTab();
SetTabsVisibility();
}
SetTabsAndBarButtonBounds();
RenderEachBarItem(g);
if (ShowNewTabBtn)
{
if (_lastMouseUpLocation != Point.Empty)
{
//gdu debug: currently we need this to set the btn back to normal
if (!NewTabBtnBounds.Contains(_lastMouseUpLocation)
&& _newTabBtn.State == GMButtonState.Hover)
_newTabBtn.MouseOperation(_lastMouseUpLocation, MouseOperationType.Move);
}
}
}
/// <summary>
/// 处理鼠标事件。该方法会触发一些click事件重刷一些按钮等
/// </summary>
/// <param name="location"></param>
/// <param name="type"></param>
public void MouseOperation(Point location, MouseOperationType type)
{
//if (type == MouseOperationType.Up)
_lastMouseUpLocation = location;
//else
// _lastMouseUpLocation = Point.Empty;
if (ShowNewTabBtn)
_newTabBtn.MouseOperation(location, type);
if (_hiddenTabsCount > 0 || AlwaysShowListAllBtn)
_listAllBtn.MouseOperation(location, type);
try
{
for (int i = 0; i < _listTabItems.Count; i++)
{
MdiGMTabItem tab = _listTabItems[i];
if (!tab.IsHidden)
{
if (ShowTabCloseIcon)
{ tab.CloseBtn.MouseOperation(location, type); }
}
}
}
catch { }
switch (type)
{
case MouseOperationType.Down:
MouseOperationDown(location);
break;
case MouseOperationType.Up:
MouseOperationUp(location);
break;
}
}
#endregion
}
/// <summary>
/// 该类表示一个单独的标签项
/// </summary>
internal class MdiGMTabItem
{
#region
#endregion
// mdi bar which this tab item is belong to
MdiBarController _barContainer;
public MdiGMTabItem(MdiBarController barContainer)
{
_barContainer = barContainer;
IsStillValid = true;
}
/// <summary>
/// 该标签所对应的窗体
/// </summary>
public Form Form { get; set; }
public bool IsFormActive { get; set; }
/// <summary>
/// 最终分配到的整个tab的宽度
/// </summary>
public int FinalWidth { get; set; }
/// <summary>
/// 表示所对应的form是否仍未被关闭
/// </summary>
public bool IsStillValid { get; set; }
public Rectangle Bounds { get; set; }
public WLButton CloseBtn { get; set; }
public bool Capture { get; set; }
/// <summary>
/// 是否因空间不足而被隐藏
/// </summary>
public bool IsHidden { get; set; }
public ToolStripMenuItem MenuItemPop { get; set; }
public Rectangle IconRect
{
get
{
return new Rectangle(
Bounds.Left + _barContainer.IconLeftSpace,
Bounds.Top + (Bounds.Height - _barContainer.IconSize.Height) / 2,
_barContainer.IconSize.Width,
_barContainer.IconSize.Height);
}
}
public Rectangle TextRect
{
get
{
int x = IconRect.Right + _barContainer.TextLeftSpace;
int w = CloseBtnRect.Left - x;
if (w < 0)
w = 0;
return new Rectangle(x, Bounds.Top, w, Bounds.Height);
}
}
public Rectangle CloseBtnRect
{
get
{
return new Rectangle(
Bounds.Right - _barContainer.TabCloseBtnRightSpace - _barContainer.TabCloseBtnSize.Width,
Bounds.Top + (Bounds.Height - _barContainer.TabCloseBtnSize.Height) / 2,
_barContainer.TabCloseBtnSize.Width,
_barContainer.TabCloseBtnSize.Height);
}
}
/// <summary>
/// 返回全部显示该标签文本所需的长度
/// </summary>
/// <returns></returns>
private int GetFullTextLength()
{
if (string.IsNullOrEmpty(Form.Text))
return 0;
return TextRenderer.MeasureText(Form.Text, Form.Font).Width;
}
/// <summary>
/// 返回显示全部文本时该tab所需的宽度,该宽度不超过bar-container
/// 规定的tabmaxwidth
/// </summary>
/// <returns></returns>
public int GetFullShowTabWidth()
{
int w = _barContainer.TabSlopeWidth * 2 + _barContainer.IconSize.Width
+ _barContainer.IconLeftSpace + _barContainer.TabCloseBtnSize.Width
+ _barContainer.TabCloseBtnRightSpace + GetFullTextLength();
if (w > _barContainer.TabMaxWidth)
w = _barContainer.TabMaxWidth;
return w;
}
}
public enum BarButtonAlignmentType
{
/// <summary>
/// 居左
/// </summary>
Left,
/// <summary>
/// 显示在最后一个标签后面
/// </summary>
AfterLastTab,
}
internal static class PathGetter
{
public static GraphicsPath GetTabBorderPath(Rectangle rect, int slopeWidth)
{
GraphicsPath path = new GraphicsPath();
Point p1 = new Point(rect.X + slopeWidth, rect.Y);
Point p2 = new Point(rect.Right - slopeWidth, rect.Y);
Point p3 = new Point(rect.Right, rect.Bottom);
Point p4 = new Point(rect.X, rect.Bottom);
path.AddLine(p1, p2);
path.AddLine(p3, p4);
path.CloseFigure();
return path;
}
}
}