📄 dockpane.cs
字号:
#region Fireball License
// Copyright (C) 2005 Sebastian Faltoni sebastian{at}dotnetfireball{dot}net
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#endregion
#region Original License
// *****************************************************************************
//
// Copyright 2004, Weifen Luo
// All rights reserved. The software and associated documentation
// supplied hereunder are the proprietary information of Weifen Luo
// and are supplied subject to licence terms.
//
// WinFormsUI Library Version 1.0
// *****************************************************************************
#endregion
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Fireball.Docking
{
/// <include file='CodeDoc\DockPane.xml' path='//CodeDoc/Class[@name="DockPane"]/ClassDef/*'/>
[ToolboxItem(false)]
public class DockPane : UserControl
{
/// <include file='CodeDoc\DockPane.xml' path='//CodeDoc/Class[@name="DockPane"]/Enum[@name="AppearanceStyle"]/EnumDef/*'/>
public enum AppearanceStyle
{
/// <include file='CodeDoc\DockPane.xml' path='//CodeDoc/Class[@name="DockPane"]/Enum[@name="AppearanceStyle"]/Member[@name="ToolWindow"]/*'/>
ToolWindow,
/// <include file='CodeDoc\DockPane.xml' path='//CodeDoc/Class[@name="DockPane"]/Enum[@name="AppearanceStyle"]/Member[@name="Document"]/*'/>
Document
}
private enum HitTestArea
{
Caption,
TabStrip,
Content,
None
}
private struct HitTestResult
{
public HitTestArea HitArea;
public int Index;
public HitTestResult(HitTestArea hitTestArea)
{
HitArea = hitTestArea;
Index = -1;
}
public HitTestResult(HitTestArea hitTestArea, int index)
{
HitArea = hitTestArea;
Index = index;
}
}
private DockPaneCaptionBase m_captionControl;
private DockPaneCaptionBase CaptionControl
{
get { return m_captionControl; }
}
private DockPaneStripBase m_tabStripControl;
internal DockPaneStripBase TabStripControl
{
get { return m_tabStripControl; }
}
/// <include file='CodeDoc\DockPane.xml' path='//CodeDoc/Class[@name="DockPane"]/Constructor[@name="Overloads"]/*'/>
/// <include file='CodeDoc\DockPane.xml' path='//CodeDoc/Class[@name="DockPane"]/Constructor[@name="(IDockContent, DockState, bool)"]/*'/>
public DockPane(IDockableWindow content, DockState visibleState, bool show)
{
InternalConstruct(content, visibleState, false, Rectangle.Empty, null, DockAlignment.Right, 0.5, show);
}
/// <include file='CodeDoc\DockPane.xml' path='//CodeDoc/Class[@name="DockPane"]/Constructor[@name="(IDockContent, FloatWindow, bool)"]/*'/>
public DockPane(IDockableWindow content, FloatWindow floatWindow, bool show)
{
InternalConstruct(content, DockState.Float, false, Rectangle.Empty, floatWindow.DockList.GetDefaultPrevPane(this), DockAlignment.Right, 0.5, show);
}
/// <include file='CodeDoc\DockPane.xml' path='//CodeDoc/Class[@name="DockPane"]/Constructor[@name="(IDockContent, DockPane, DockAlignment, double, bool)"]/*'/>
public DockPane(IDockableWindow content, DockPane prevPane, DockAlignment alignment, double proportion, bool show)
{
if (prevPane == null)
throw(new ArgumentNullException());
InternalConstruct(content, prevPane.DockState, false, Rectangle.Empty, prevPane, alignment, proportion, show);
}
/// <include file='CodeDoc\DockPane.xml' path='//CodeDoc/Class[@name="DockPane"]/Constructor[@name="(IDockContent, Rectangle, bool)"]/*'/>
public DockPane(IDockableWindow content, Rectangle floatWindowBounds, bool show)
{
InternalConstruct(content, DockState.Float, true, floatWindowBounds, null, DockAlignment.Right, 0.5, show);
}
private void InternalConstruct(IDockableWindow content, DockState dockState, bool flagBounds, Rectangle floatWindowBounds, DockPane prevPane, DockAlignment alignment, double proportion, bool show)
{
if (dockState == DockState.Hidden || dockState == DockState.Unknown)
throw new ArgumentException(ResourceHelper.GetString("DockPane.DockState.InvalidState"));
if (content == null)
throw new ArgumentNullException(ResourceHelper.GetString("DockPane.Constructor.NullContent"));
if (content.DockHandler.DockPanel == null)
throw new ArgumentException(ResourceHelper.GetString("DockPane.Constructor.NullDockPanel"));
SuspendLayout();
SetStyle(ControlStyles.Selectable, false);
m_isFloat = (dockState == DockState.Float);
m_contents = new DockContentCollection();
m_displayingContents = new DockContentCollection(this);
m_tabs = new DockPaneTabCollection(this);
m_dockPanel = content.DockHandler.DockPanel;
m_dockPanel.AddPane(this);
m_splitter = new DockPaneSplitter(this);
m_nestedDockingStatus = new NestedDockingStatus(this);
m_autoHidePane = DockPanel.AutoHidePaneFactory.CreateAutoHidePane(this);
m_captionControl = DockPanel.DockPaneCaptionFactory.CreateDockPaneCaption(this);
m_tabStripControl = DockPanel.DockPaneStripFactory.CreateDockPaneStrip(this);
Controls.AddRange(new Control[] { m_captionControl, m_tabStripControl });
DockPanel.SuspendLayout(true);
if (flagBounds)
FloatWindow = DockPanel.FloatWindowFactory.CreateFloatWindow(DockPanel, this, floatWindowBounds);
else if (prevPane != null)
AddToDockList(prevPane.DockListContainer, prevPane, alignment, proportion);
SetDockState(dockState);
if (show)
content.DockHandler.Pane = this;
else if (this.IsFloat)
content.DockHandler.FloatPane = this;
else
content.DockHandler.PanelPane = this;
ResumeLayout();
DockPanel.ResumeLayout(true, true);
}
private void Close_Click(object sender, EventArgs e)
{
CloseActiveContent();
if (!DockHelper.IsDockStateAutoHide(DockState) && ActiveContent != null)
ActiveContent.DockHandler.Activate();
}
/// <exclude/>
protected override void Dispose(bool disposing)
{
if (disposing)
{
m_dockState = DockState.Unknown;
if (DockListContainer != null)
DockListContainer.DockList.Remove(this);
if (DockPanel != null)
{
DockPanel.RemovePane(this);
m_dockPanel = null;
}
Splitter.Dispose();
AutoHidePane.Dispose();
}
base.Dispose(disposing);
}
private IDockableWindow m_activeContent = null;
/// <include file='CodeDoc\DockPane.xml' path='//CodeDoc/Class[@name="DockPane"]/Property[@name="ActiveContent"]/*'/>
public virtual IDockableWindow ActiveContent
{
get { return m_activeContent; }
set
{
if (ActiveContent == value)
return;
if (value != null)
{
if (!DisplayingContents.Contains(value))
throw(new InvalidOperationException(ResourceHelper.GetString("DockPane.ActiveContent.InvalidValue")));
}
else
{
if (DisplayingContents.Count != 0)
throw(new InvalidOperationException(ResourceHelper.GetString("DockPane.ActiveContent.InvalidValue")));
}
IDockableWindow oldValue = m_activeContent;
if (DockPanel.ActiveAutoHideContent == oldValue)
DockPanel.ActiveAutoHideContent = null;
m_activeContent = value;
if (DockPanel.DocumentStyle == DocumentStyles.DockingMdi && DockState == DockState.Document)
{
if (m_activeContent != null)
m_activeContent.DockHandler.Form.BringToFront();
}
else
{
if (m_activeContent != null)
m_activeContent.DockHandler.SetVisible();
if (oldValue != null && DisplayingContents.Contains(oldValue))
oldValue.DockHandler.SetVisible();
}
if (FloatWindow != null)
FloatWindow.SetText();
RefreshChanges(false);
if (m_activeContent != null)
TabStripControl.EnsureTabVisible(m_activeContent);
}
}
private bool m_allowRedocking = true;
/// <include file='CodeDoc\DockPane.xml' path='//CodeDoc/Class[@name="DockPane"]/Property[@name="AllowRedocking"]/*'/>
public virtual bool AllowRedocking
{
get { return m_allowRedocking; }
set { m_allowRedocking = value; }
}
private DockPaneTabCollection m_tabs;
internal DockPaneTabCollection Tabs
{
get { return m_tabs; }
}
private Rectangle CaptionRectangle
{
get
{
if (!HasCaption)
return Rectangle.Empty;
Rectangle rectWindow = DisplayingRectangle;
int x, y, width;
x = rectWindow.X;
y = rectWindow.Y;
width = rectWindow.Width;
int height = CaptionControl.MeasureHeight();
return new Rectangle(x, y, width, height);
}
}
internal Rectangle ContentRectangle
{
get
{
Rectangle rectWindow = DisplayingRectangle;
Rectangle rectCaption = CaptionRectangle;
Rectangle rectTabStrip = TabStripRectangle;
int x = rectWindow.X;
int y = rectWindow.Y + (rectCaption.IsEmpty ? 0 : rectCaption.Height) +
(DockState == DockState.Document ? rectTabStrip.Height : 0);
int width = rectWindow.Width;
int height = rectWindow.Height - rectCaption.Height - rectTabStrip.Height;
return new Rectangle(x, y, width, height);
}
}
internal Rectangle TabStripRectangle
{
get
{
if (Appearance == AppearanceStyle.ToolWindow)
return TabStripRectangle_ToolWindow;
else
return TabStripRectangle_Document;
}
}
private Rectangle TabStripRectangle_ToolWindow
{
get
{
if (DisplayingContents.Count <= 1 || IsAutoHide)
return Rectangle.Empty;
Rectangle rectWindow = DisplayingRectangle;
int width = rectWindow.Width;
int height = TabStripControl.MeasureHeight();
int x = rectWindow.X;
int y = rectWindow.Bottom - height;
Rectangle rectCaption = CaptionRectangle;
if (rectCaption.Contains(x, y))
y = rectCaption.Y + rectCaption.Height;
return new Rectangle(x, y, width, height);
}
}
private Rectangle TabStripRectangle_Document
{
get
{
if (DisplayingContents.Count == 0)
return Rectangle.Empty;
if (DisplayingContents.Count == 1 && DockPanel.DocumentStyle == DocumentStyles.DockingSdi)
return Rectangle.Empty;
Rectangle rectWindow = DisplayingRectangle;
int x = rectWindow.X;
int y = rectWindow.Y;
int width = rectWindow.Width;
int height = TabStripControl.MeasureHeight();
return new Rectangle(x, y, width, height);
}
}
/// <include file='CodeDoc\DockPane.xml' path='//CodeDoc/Class[@name="DockPane"]/Property[@name="CaptionText"]/*'/>
public virtual string CaptionText
{
get { return ActiveContent == null ? string.Empty : ActiveContent.DockHandler.TabText; }
}
private DockContentCollection m_contents;
/// <include file='CodeDoc\DockPane.xml' path='//CodeDoc/Class[@name="DockPane"]/Property[@name="Contents"]/*'/>
public DockContentCollection Contents
{
get { return m_contents; }
}
private DockContentCollection m_displayingContents;
/// <include file='CodeDoc\DockPane.xml' path='//CodeDoc/Class[@name="DockPane"]/Property[@name="DisplayingContents"]/*'/>
public DockContentCollection DisplayingContents
{
get { return m_displayingContents; }
}
private DockContainer m_dockPanel;
/// <include file='CodeDoc\DockPane.xml' path='//CodeDoc/Class[@name="DockPane"]/Property[@name="DockPanel"]/*'/>
public DockContainer DockPanel
{
get { return m_dockPanel; }
}
private bool HasCaption
{
get
{
if (DockState == DockState.Document ||
DockState == DockState.Hidden ||
DockState == DockState.Unknown ||
(DockState == DockState.Float && FloatWindow.DisplayingList.Count <= 1))
return false;
else
return true;
}
}
private bool m_isActivated = false;
/// <include file='CodeDoc\DockPane.xml' path='//CodeDoc/Class[@name="DockPane"]/Property[@name="IsActivated"]/*'/>
public bool IsActivated
{
get { return m_isActivated; }
}
internal void SetIsActivated(bool value)
{
if (m_isActivated == value)
return;
m_isActivated = value;
if (DockState != DockState.Document)
RefreshChanges(false);
OnIsActivatedChanged(EventArgs.Empty);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -