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 WeifenLuo.WinFormsUI.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 { #region IEnumerable Members IEnumerator IEnumerable.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 { 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 IEnumerable.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); } }