You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

531 lines
15 KiB
C#

using System;
using System.Collections;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
namespace Mesnac.Docking
{
public abstract partial class AutoHideStripBase : Control
{
[SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
protected class Tab : IDisposable
{
private IDockContent m_content;
protected internal Tab(IDockContent content)
{
m_content = content;
}
~Tab()
{
Dispose(false);
}
public IDockContent Content
{
get { return m_content; }
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
}
}
[SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
protected sealed class TabCollection : IEnumerable<Tab>
{
#region IEnumerable Members
IEnumerator<Tab> IEnumerable<Tab>.GetEnumerator()
{
for (int i = 0; i < Count; i++)
yield return this[i];
}
IEnumerator IEnumerable.GetEnumerator()
{
for (int i = 0; i < Count; i++)
yield return this[i];
}
#endregion
internal TabCollection(DockPane pane)
{
m_dockPane = pane;
}
private DockPane m_dockPane = null;
public DockPane DockPane
{
get { return m_dockPane; }
}
public DockPanel DockPanel
{
get { return DockPane.DockPanel; }
}
public int Count
{
get { return DockPane.DisplayingContents.Count; }
}
public Tab this[int index]
{
get
{
IDockContent content = DockPane.DisplayingContents[index];
if (content == null)
throw (new ArgumentOutOfRangeException("index"));
if (content.DockHandler.AutoHideTab == null)
content.DockHandler.AutoHideTab = (DockPanel.AutoHideStripControl.CreateTab(content));
return content.DockHandler.AutoHideTab as Tab;
}
}
public bool Contains(Tab tab)
{
return (IndexOf(tab) != -1);
}
public bool Contains(IDockContent content)
{
return (IndexOf(content) != -1);
}
public int IndexOf(Tab tab)
{
if (tab == null)
return -1;
return IndexOf(tab.Content);
}
public int IndexOf(IDockContent content)
{
return DockPane.DisplayingContents.IndexOf(content);
}
}
[SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
protected class Pane : IDisposable
{
private DockPane m_dockPane;
protected internal Pane(DockPane dockPane)
{
m_dockPane = dockPane;
}
~Pane()
{
Dispose(false);
}
public DockPane DockPane
{
get { return m_dockPane; }
}
public TabCollection AutoHideTabs
{
get
{
if (DockPane.AutoHideTabs == null)
DockPane.AutoHideTabs = new TabCollection(DockPane);
return DockPane.AutoHideTabs as TabCollection;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
}
}
[SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
protected sealed class PaneCollection : IEnumerable<Pane>
{
private class AutoHideState
{
public DockState m_dockState;
public bool m_selected = false;
public AutoHideState(DockState dockState)
{
m_dockState = dockState;
}
public DockState DockState
{
get { return m_dockState; }
}
public bool Selected
{
get { return m_selected; }
set { m_selected = value; }
}
}
private class AutoHideStateCollection
{
private AutoHideState[] m_states;
public AutoHideStateCollection()
{
m_states = new AutoHideState[] {
new AutoHideState(DockState.DockTopAutoHide),
new AutoHideState(DockState.DockBottomAutoHide),
new AutoHideState(DockState.DockLeftAutoHide),
new AutoHideState(DockState.DockRightAutoHide)
};
}
public AutoHideState this[DockState dockState]
{
get
{
for (int i = 0; i < m_states.Length; i++)
{
if (m_states[i].DockState == dockState)
return m_states[i];
}
throw new ArgumentOutOfRangeException("dockState");
}
}
public bool ContainsPane(DockPane pane)
{
if (pane.IsHidden)
return false;
for (int i = 0; i < m_states.Length; i++)
{
if (m_states[i].DockState == pane.DockState && m_states[i].Selected)
return true;
}
return false;
}
}
internal PaneCollection(DockPanel panel, DockState dockState)
{
m_dockPanel = panel;
m_states = new AutoHideStateCollection();
States[DockState.DockTopAutoHide].Selected = (dockState == DockState.DockTopAutoHide);
States[DockState.DockBottomAutoHide].Selected = (dockState == DockState.DockBottomAutoHide);
States[DockState.DockLeftAutoHide].Selected = (dockState == DockState.DockLeftAutoHide);
States[DockState.DockRightAutoHide].Selected = (dockState == DockState.DockRightAutoHide);
}
private DockPanel m_dockPanel;
public DockPanel DockPanel
{
get { return m_dockPanel; }
}
private AutoHideStateCollection m_states;
private AutoHideStateCollection States
{
get { return m_states; }
}
public int Count
{
get
{
int count = 0;
foreach (DockPane pane in DockPanel.Panes)
{
if (States.ContainsPane(pane))
count++;
}
return count;
}
}
public Pane this[int index]
{
get
{
int count = 0;
foreach (DockPane pane in DockPanel.Panes)
{
if (!States.ContainsPane(pane))
continue;
if (count == index)
{
if (pane.AutoHidePane == null)
pane.AutoHidePane = DockPanel.AutoHideStripControl.CreatePane(pane);
return pane.AutoHidePane as Pane;
}
count++;
}
throw new ArgumentOutOfRangeException("index");
}
}
public bool Contains(Pane pane)
{
return (IndexOf(pane) != -1);
}
public int IndexOf(Pane pane)
{
if (pane == null)
return -1;
int index = 0;
foreach (DockPane dockPane in DockPanel.Panes)
{
if (!States.ContainsPane(pane.DockPane))
continue;
if (pane == dockPane.AutoHidePane)
return index;
index++;
}
return -1;
}
#region IEnumerable Members
IEnumerator<Pane> IEnumerable<Pane>.GetEnumerator()
{
for (int i = 0; i < Count; i++)
yield return this[i];
}
IEnumerator IEnumerable.GetEnumerator()
{
for (int i = 0; i < Count; i++)
yield return this[i];
}
#endregion
}
protected AutoHideStripBase(DockPanel panel)
{
m_dockPanel = panel;
m_panesTop = new PaneCollection(panel, DockState.DockTopAutoHide);
m_panesBottom = new PaneCollection(panel, DockState.DockBottomAutoHide);
m_panesLeft = new PaneCollection(panel, DockState.DockLeftAutoHide);
m_panesRight = new PaneCollection(panel, DockState.DockRightAutoHide);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.Selectable, false);
}
private DockPanel m_dockPanel;
protected DockPanel DockPanel
{
get { return m_dockPanel; }
}
private PaneCollection m_panesTop;
protected PaneCollection PanesTop
{
get { return m_panesTop; }
}
private PaneCollection m_panesBottom;
protected PaneCollection PanesBottom
{
get { return m_panesBottom; }
}
private PaneCollection m_panesLeft;
protected PaneCollection PanesLeft
{
get { return m_panesLeft; }
}
private PaneCollection m_panesRight;
protected PaneCollection PanesRight
{
get { return m_panesRight; }
}
protected PaneCollection GetPanes(DockState dockState)
{
if (dockState == DockState.DockTopAutoHide)
return PanesTop;
else if (dockState == DockState.DockBottomAutoHide)
return PanesBottom;
else if (dockState == DockState.DockLeftAutoHide)
return PanesLeft;
else if (dockState == DockState.DockRightAutoHide)
return PanesRight;
else
throw new ArgumentOutOfRangeException("dockState");
}
internal int GetNumberOfPanes(DockState dockState)
{
return GetPanes(dockState).Count;
}
protected Rectangle RectangleTopLeft
{
get
{
int height = MeasureHeight();
return PanesTop.Count > 0 && PanesLeft.Count > 0 ? new Rectangle(0, 0, height, height) : Rectangle.Empty;
}
}
protected Rectangle RectangleTopRight
{
get
{
int height = MeasureHeight();
return PanesTop.Count > 0 && PanesRight.Count > 0 ? new Rectangle(Width - height, 0, height, height) : Rectangle.Empty;
}
}
protected Rectangle RectangleBottomLeft
{
get
{
int height = MeasureHeight();
return PanesBottom.Count > 0 && PanesLeft.Count > 0 ? new Rectangle(0, Height - height, height, height) : Rectangle.Empty;
}
}
protected Rectangle RectangleBottomRight
{
get
{
int height = MeasureHeight();
return PanesBottom.Count > 0 && PanesRight.Count > 0 ? new Rectangle(Width - height, Height - height, height, height) : Rectangle.Empty;
}
}
protected internal Rectangle GetTabStripRectangle(DockState dockState)
{
int height = MeasureHeight();
if (dockState == DockState.DockTopAutoHide && PanesTop.Count > 0)
return new Rectangle(RectangleTopLeft.Width, 0, Width - RectangleTopLeft.Width - RectangleTopRight.Width, height);
else if (dockState == DockState.DockBottomAutoHide && PanesBottom.Count > 0)
return new Rectangle(RectangleBottomLeft.Width, Height - height, Width - RectangleBottomLeft.Width - RectangleBottomRight.Width, height);
else if (dockState == DockState.DockLeftAutoHide && PanesLeft.Count > 0)
return new Rectangle(0, RectangleTopLeft.Width, height, Height - RectangleTopLeft.Height - RectangleBottomLeft.Height);
else if (dockState == DockState.DockRightAutoHide && PanesRight.Count > 0)
return new Rectangle(Width - height, RectangleTopRight.Width, height, Height - RectangleTopRight.Height - RectangleBottomRight.Height);
else
return Rectangle.Empty;
}
private GraphicsPath m_displayingArea = null;
private GraphicsPath DisplayingArea
{
get
{
if (m_displayingArea == null)
m_displayingArea = new GraphicsPath();
return m_displayingArea;
}
}
private void SetRegion()
{
DisplayingArea.Reset();
DisplayingArea.AddRectangle(RectangleTopLeft);
DisplayingArea.AddRectangle(RectangleTopRight);
DisplayingArea.AddRectangle(RectangleBottomLeft);
DisplayingArea.AddRectangle(RectangleBottomRight);
DisplayingArea.AddRectangle(GetTabStripRectangle(DockState.DockTopAutoHide));
DisplayingArea.AddRectangle(GetTabStripRectangle(DockState.DockBottomAutoHide));
DisplayingArea.AddRectangle(GetTabStripRectangle(DockState.DockLeftAutoHide));
DisplayingArea.AddRectangle(GetTabStripRectangle(DockState.DockRightAutoHide));
Region = new Region(DisplayingArea);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button != MouseButtons.Left)
return;
IDockContent content = HitTest();
if (content == null)
return;
content.DockHandler.Activate();
}
protected override void OnMouseHover(EventArgs e)
{
base.OnMouseHover(e);
IDockContent content = HitTest();
if (content != null && DockPanel.ActiveAutoHideContent != content)
DockPanel.ActiveAutoHideContent = content;
// requires further tracking of mouse hover behavior,
ResetMouseEventArgs();
}
protected override void OnLayout(LayoutEventArgs levent)
{
RefreshChanges();
base.OnLayout (levent);
}
internal void RefreshChanges()
{
if (IsDisposed)
return;
SetRegion();
OnRefreshChanges();
}
protected virtual void OnRefreshChanges()
{
}
protected internal abstract int MeasureHeight();
private IDockContent HitTest()
{
Point ptMouse = PointToClient(Control.MousePosition);
return HitTest(ptMouse);
}
protected virtual Tab CreateTab(IDockContent content)
{
return new Tab(content);
}
protected virtual Pane CreatePane(DockPane dockPane)
{
return new Pane(dockPane);
}
protected abstract IDockContent HitTest(Point point);
}
}