context: using System;
  using System.Drawing;
  using System.Drawing.Drawing2D;
  using System.Windows.Forms;
  using System.ComponentModel;
  using System.Runtime.InteropServices;
  using System.IO;
  using System.Text;
  using System.Diagnostics.CodeAnalysis;
  using System.Collections.Generic;
  
  // To simplify the process of finding the toolbox bitmap resource:
  // #1 Create an internal class called "resfinder" outside of the root namespace.
  // #2 Use "resfinder" in the toolbox bitmap attribute instead of the control name.
  // #3 use the "<default namespace>.<resourcename>" string to locate the resource.
  // See: http://www.bobpowell.net/toolboxbitmap.htm
  internal class resfinder
  {
  }
  
  namespace WeifenLuo.WinFormsUI.Docking
  {
      [SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters", MessageId = "0#")]
  	public delegate IDockContent DeserializeDockContent(string persistString);
  
      [LocalizedDescription("DockPanel_Description")]
      [Designer(typeof(System.Windows.Forms.Design.ControlDesigner))]
      [ToolboxBitmap(typeof(resfinder), "WeifenLuo.WinFormsUI.Docking.DockPanel.bmp")]
      [DefaultProperty("DocumentStyle")]
      [DefaultEvent("ActiveContentChanged")]
  	public partial class DockPanel : Panel
  	{
          private FocusManagerImpl m_focusManager;
          private DockPanelExtender m_extender;
          private DockPaneCollection m_panes;
          private FloatWindowCollection m_floatWindows;
          private AutoHideWindowControl m_autoHideWindow;
          private DockWindowCollection m_dockWindows;
          private DockContent m_dummyContent; 
          private Control m_dummyControl;
          
  		public DockPanel()
  		{
              m_focusManager = new FocusManagerImpl(this);
  			m_extender = new DockPanelExtender(this);
  			m_panes = new DockPaneCollection();
  			m_floatWindows = new FloatWindowCollection();
  
              SuspendLayout();
  
  			m_autoHideWindow = new AutoHideWindowControl(this);
  			m_autoHideWindow.Visible = false;
              SetAutoHideWindowParent();
  
  			m_dummyControl = new DummyControl();
  			m_dummyControl.Bounds = new Rectangle(0, 0, 1, 1);
  			Controls.Add(m_dummyControl);
  
  			m_dockWindows = new DockWindowCollection(this);
  			Controls.AddRange(new Control[]	{
  				DockWindows[DockState.Document],
  				DockWindows[DockState.DockLeft],
  				DockWindows[DockState.DockRight],
  				DockWindows[DockState.DockTop],
  				DockWindows[DockState.DockBottom]
  				});
  
  			m_dummyContent = new DockContent();
              ResumeLayout();
          }
  
  		private AutoHideStripBase m_autoHideStripControl = null;
  		internal AutoHideStripBase AutoHideStripControl
  		{
  			get
  			{	
  				if (m_autoHideStripControl == null)
  				{
  					m_autoHideStripControl = AutoHideStripFactory.CreateAutoHideStrip(this);
  					Controls.Add(m_autoHideStripControl);
  				}
  				return m_autoHideStripControl;
  			}
  		}
          internal void ResetAutoHideStripControl()
          {
              if (m_autoHideStripControl != null)
                  m_autoHideStripControl.Dispose();
  
              m_autoHideStripControl = null;
          }
  
  		private void MdiClientHandleAssigned(object sender, EventArgs e)
  		{
  			SetMdiClient();
  			PerformLayout();
  		}
  
  		private void MdiClient_Layout(object sender, LayoutEventArgs e)
  		{
  			if (DocumentStyle != DocumentStyle.DockingMdi)
  				return;
  
  			foreach (DockPane pane in Panes)
  				if (pane.DockState == DockState.Document)
  					pane.SetContentBounds();
  
  			InvalidateWindowRegion();
  		}
  
  		private bool m_disposed = false;
  		protected override void Dispose(bool disposing)
  		{
  			lock (this)
  			{
  				if (!m_disposed && disposing)
  				{
                      m_focusManager.Dispose();
  					if (m_mdiClientController != null)
  					{
  						m_mdiClientController.HandleAssigned -= new EventHandler(MdiClientHandleAssigned);
  						m_mdiClientController.MdiChildActivate -= new EventHandler(ParentFormMdiChildActivate);
  						m_mdiClientController.Layout -= new LayoutEventHandler(MdiClient_Layout);
  						m_mdiClientController.Dispose();
  					}
  					FloatWindows.Dispose();
  					Panes.Dispose();
  					DummyContent.Dispose();
  
  					m_disposed = true;
  				}
  				
  				base.Dispose(disposing);
  			}
  		}
  
  		[Browsable(false)]
  		public IDockContent ActiveAutoHideContent
  		{
  			get	{	return AutoHideWindow.ActiveContent;	}
  			set	{	AutoHideWindow.ActiveContent = value;	}
  		}
  
          private bool m_allowEndUserDocking = true;
  		[LocalizedCategory("Category_Docking")]
  		[LocalizedDescription("DockPanel_AllowEndUserDocking_Description")]
  		[DefaultValue(true)]
  		public bool AllowEndUserDocking
  		{
  			get	{	return m_allowEndUserDocking;	}
  			set	{	m_allowEndUserDocking = value;	}
  		}
  
          private bool m_allowEndUserNestedDocking = true;
          [LocalizedCategory("Category_Docking")]
          [LocalizedDescription("DockPanel_AllowEndUserNestedDocking_Description")]
          [DefaultValue(true)]
          public bool AllowEndUserNestedDocking
          {
              get { return m_allowEndUserNestedDocking; }
              set { m_allowEndUserNestedDocking = value; }
          }
  
          private DockContentCollection m_contents = new DockContentCollection();
  		[Browsable(false)]
  		public DockContentCollection Contents
  		{
  			get	{	return m_contents;	}
  		}
  
  		internal DockContent DummyContent
  		{
  			get	{	return m_dummyContent;	}
  		}
  
          private bool m_rightToLeftLayout = false;
          [DefaultValue(false)]
          [LocalizedCategory("Appearance")]
          [LocalizedDescription("DockPanel_RightToLeftLayout_Description")]
          public bool RightToLeftLayout
          {
              get { return m_rightToLeftLayout; }
              set
              {
                  if (m_rightToLeftLayout == value)
                      return;
  
                  m_rightToLeftLayout = value;
                  foreach (FloatWindow floatWindow in FloatWindows)
                      floatWindow.RightToLeftLayout = value;
              }
          }
  
          protected override void OnRightToLeftChanged(EventArgs e)
          {
              base.OnRightToLeftChanged(e);
              foreach (FloatWindow floatWindow in FloatWindows)
              {
                  if (floatWindow.RightToLeft != RightToLeft)
                      floatWindow.RightToLeft = RightToLeft;
              }
          }
  
  		private bool m_showDocumentIcon = false;
  		[DefaultValue(false)]
  		[LocalizedCategory("Category_Docking")]
  		[LocalizedDescription("DockPanel_ShowDocumentIcon_Description")]
  		public bool ShowDocumentIcon
  		{
  			get	{	return m_showDocumentIcon;	}
  			set
  			{
  				if (m_showDocumentIcon == value)
  					return;
  
  				m_showDocumentIcon = value;
  				Refresh();
  			}
  		}
  
  		[Browsable(false)]
  		public DockPanelExtender Extender
  		{
  			get	{	return m_extender;	}
  		}
  
  		public DockPanelExtender.IDockPaneFactory DockPaneFactory
  		{
  			get	{	return Extender.DockPaneFactory;	}
  		}
  
  		public DockPanelExtender.IFloatWindowFactory FloatWindowFactory
  		{
  			get	{	return Extender.FloatWindowFactory;	}
  		}
  
  		internal DockPanelExtender.IDockPaneCaptionFactory DockPaneCaptionFactory
  		{
  			get	{	return Extender.DockPaneCaptionFactory;	}
  		}
  
  		internal DockPanelExtender.IDockPaneStripFactory DockPaneStripFactory
  		{
  			get	{	return Extender.DockPaneStripFactory;	}
  		}
  
  		internal DockPanelExtender.IAutoHideStripFactory AutoHideStripFactory
  		{
  			get	{	return Extender.AutoHideStripFactory;	}
  		}
  
  		[Browsable(false)]
  		public DockPaneCollection Panes
  		{
  			get	{	return m_panes;	}
  		}
  
  		internal Rectangle DockArea
  		{
  			get
  			{
  				return new Rectangle(DockPadding.Left, DockPadding.Top,
  					ClientRectangle.Width - DockPadding.Left - DockPadding.Right,
  					ClientRectangle.Height - DockPadding.Top - DockPadding.Bottom);
  			}
  		}
  
  		private double m_dockBottomPortion = 0.25;
  		[LocalizedCategory("Category_Docking")]
  		[LocalizedDescription("DockPanel_DockBottomPortion_Description")]
  		[DefaultValue(0.25)]
  		public double DockBottomPortion
  		{
  			get	{	return m_dockBottomPortion;	}
  			set
  			{
  				if (value <= 0)
  					throw new ArgumentOutOfRangeException("value");
  
  				if (value == m_dockBottomPortion)
  					return;
  
  				m_dockBottomPortion = value;
  
                  if (m_dockBottomPortion < 1 && m_dockTopPortion < 1)
                  {
                      if (m_dockTopPortion + m_dockBottomPortion > 1)
                          m_dockTopPortion = 1 - m_dockBottomPortion;
                  }
  
  				PerformLayout();
  			}
  		}
  
  		private double m_dockLeftPortion = 0.25;
  		[LocalizedCategory("Category_Docking")]
  		[LocalizedDescription("DockPanel_DockLeftPortion_Description")]
  		[DefaultValue(0.25)]
  		public double DockLeftPortion
  		{
  			get	{	return m_dockLeftPortion;	}
  			set
  			{
  				if (value <= 0)
  					throw new ArgumentOutOfRangeException("value");
  
  				if (value == m_dockLeftPortion)
  					return;
  
  				m_dockLeftPortion = value;
  
                  if (m_dockLeftPortion < 1 && m_dockRightPortion < 1)
                  {
                      if (m_dockLeftPortion + m_dockRightPortion > 1)
                          m_dockRightPortion = 1 - m_dockLeftPortion;
                  }
  				PerformLayout();
  			}
  		}
  
  		private double m_dockRightPortion = 0.25;
  		[LocalizedCategory("Category_Docking")]
  		[LocalizedDescription("DockPanel_DockRightPortion_Description")]
  		[DefaultValue(0.25)]
  		public double DockRightPortion
  		{
  			get	{	return m_dockRightPortion;	}
  			set
  			{
  				if (value <= 0)
  					throw new ArgumentOutOfRangeException("value");
  
  				if (value == m_dockRightPortion)
  					return;
  
  				m_dockRightPortion = value;
  
                  if (m_dockLeftPortion < 1 && m_dockRightPortion < 1)
                  {
                      if (m_dockLeftPortion + m_dockRightPortion > 1)
                          m_dockLeftPortion = 1 - m_dockRightPortion;
                  }
  				PerformLayout();
  			}
  		}
  
  		private double m_dockTopPortion = 0.25;
  		[LocalizedCategory("Category_Docking")]
  		[LocalizedDescription("DockPanel_DockTopPortion_Description")]
  		[DefaultValue(0.25)]
  		public double DockTopPortion
  		{
  			get	{	return m_dockTopPortion;	}
  			set
  			{
  				if (value <= 0)
  					throw new ArgumentOutOfRangeException("value");
  
  				if (value == m_dockTopPortion)
  					return;
  
  				m_dockTopPortion = value;
  
                  if (m_dockTopPortion < 1 && m_dockBottomPortion < 1)
                  {
                      if (m_dockTopPortion + m_dockBottomPortion > 1)
                          m_dockBottomPortion = 1 - m_dockTopPortion;
                  }
  				PerformLayout();
  			}
  		}
  
  		[Browsable(false)]
  		public DockWindowCollection DockWindows
  		{
  			get	{	return m_dockWindows;	}
  		}
  
          public void UpdateDockWindowZOrder(DockStyle dockStyle, bool fullPanelEdge)
          {
              if (dockStyle == DockStyle.Left)
              {
                  if (fullPanelEdge)
                      DockWindows[DockState.DockLeft].SendToBack();
                  else
                      DockWindows[DockState.DockLeft].BringToFront();
              }
              else if (dockStyle == DockStyle.Right)
              {
                  if (fullPanelEdge)
                      DockWindows[DockState.DockRight].SendToBack();
                  else
                      DockWindows[DockState.DockRight].BringToFront();
              }
              else if (dockStyle == DockStyle.Top)
              {
                  if (fullPanelEdge)
                      DockWindows[DockState.DockTop].SendToBack();
                  else
                      DockWindows[DockState.DockTop].BringToFront();
              }
              else if (dockStyle == DockStyle.Bottom)
              {
                  if (fullPanelEdge)
                      DockWindows[DockState.DockBottom].SendToBack();
                  else
                      DockWindows[DockState.DockBottom].BringToFront();
              }
          }
  
          public int DocumentsCount
          {
              get
              {
                  int count = 0;
                  foreach (IDockContent content in Documents)
                      count++;
  
                  return count;
              }
          }
  
          public IDockContent[] DocumentsToArray()
          {
              int count = DocumentsCount;
              IDockContent[] documents = new IDockContent[count];
              int i = 0;
              foreach (IDockContent content in Documents)
              {
                  documents[i] = content;
                  i++;
              }
  
              return documents;
          }
  
  		public IEnumerable<IDockContent> Documents
  		{
              get
              {
                  foreach (IDockContent content in Contents)
                  {
                      if (content.DockHandler.DockState == DockState.Document)
                          yield return content;
                  }
              }
  		}
  
  		private Rectangle DocumentRectangle
  		{
  			get
  			{
  				Rectangle rect = DockArea;
  				if (DockWindows[DockState.DockLeft].VisibleNestedPanes.Count != 0)
  				{
  					rect.X += (int)(DockArea.Width * DockLeftPortion);
  					rect.Width -= (int)(DockArea.Width * DockLeftPortion);
  				}
  				if (DockWindows[DockState.DockRight].VisibleNestedPanes.Count != 0)
  					rect.Width -= (int)(DockArea.Width * DockRightPortion);
  				if (DockWindows[DockState.DockTop].VisibleNestedPanes.Count != 0)
  				{
  					rect.Y += (int)(DockArea.Height * DockTopPortion);
  					rect.Height -= (int)(DockArea.Height * DockTopPortion);
  				}
  				if (DockWindows[DockState.DockBottom].VisibleNestedPanes.Count != 0)
  					rect.Height -= (int)(DockArea.Height * DockBottomPortion);
  
  				return rect;
  			}
  		}
  
  		private Control DummyControl
  		{
  			get	{	return m_dummyControl;	}
  		}
  
  		[Browsable(false)]
  		public FloatWindowCollection FloatWindows
  		{
  			get	{	return m_floatWindows;	}
  		}
  
          private Size m_defaultFloatWindowSize = new Size(300, 300);
          [Category("Layout")]
          [LocalizedDescription("DockPanel_DefaultFloatWindowSize_Description")]
          public Size DefaultFloatWindowSize
          {
              get { return m_defaultFloatWindowSize; }
              set { m_defaultFloatWindowSize = value; }
          }
          private bool ShouldSerializeDefaultFloatWindowSize()
          {
              return DefaultFloatWindowSize != new Size(300, 300);
          }
  
  		private DocumentStyle m_documentStyle = DocumentStyle.DockingMdi;
  		[LocalizedCategory("Category_Docking")]
  		[LocalizedDescription("DockPanel_DocumentStyle_Description")]
  		[DefaultValue(DocumentStyle.DockingMdi)]
  		public DocumentStyle DocumentStyle
  		{
  			get	{	return m_documentStyle;	}
  			set
  			{
  				if (value == m_documentStyle)
  					return;
  
  				if (!Enum.IsDefined(typeof(DocumentStyle), value))
  					throw new InvalidEnumArgumentException();
  
  				if (value == DocumentStyle.SystemMdi && DockWindows[DockState.Document].VisibleNestedPanes.Count > 0)
  					throw new InvalidEnumArgumentException();
  
  				m_documentStyle = value;
  
  				SuspendLayout(true);
  
                  SetAutoHideWindowParent();
  				SetMdiClient();
  				InvalidateWindowRegion();
  
  				foreach (IDockContent content in Contents)
  				{
  					if (content.DockHandler.DockState == DockState.Document)
  						content.DockHandler.SetPaneAndVisible(content.DockHandler.Pane);
  				}
  
                  PerformMdiClientLayout();
  
  				ResumeLayout(true, true);
  			}
  		}
  
          private int GetDockWindowSize(DockState dockState)
          {
              if (dockState == DockState.DockLeft || dockState == DockState.DockRight)
              {
                  int width = ClientRectangle.Width - DockPadding.Left - DockPadding.Right;
                  int dockLeftSize = m_dockLeftPortion >= 1 ? (int)m_dockLeftPortion : (int)(width * m_dockLeftPortion);
                  int dockRightSize = m_dockRightPortion >= 1 ? (int)m_dockRightPortion : (int)(width * m_dockRightPortion);
  
                  if (dockLeftSize < MeasurePane.MinSize)
                      dockLeftSize = MeasurePane.MinSize;
                  if (dockRightSize < MeasurePane.MinSize)
                      dockRightSize = MeasurePane.MinSize;
  
                  if (dockLeftSize + dockRightSize > width - MeasurePane.MinSize)
                  {
                      int adjust = (dockLeftSize + dockRightSize) - (width - MeasurePane.MinSize);
                      dockLeftSize -= adjust / 2;
                      dockRightSize -= adjust / 2;
                  }
  
                  return dockState == DockState.DockLeft ? dockLeftSize : dockRightSize;
              }
              else if (dockState == DockState.DockTop || dockState == DockState.DockBottom)
              {
                  int height = ClientRectangle.Height - DockPadding.Top - DockPadding.Bottom;
                  int dockTopSize = m_dockTopPortion >= 1 ? (int)m_dockTopPortion : (int)(height * m_dockTopPortion);
                  int dockBottomSize = m_dockBottomPortion >= 1 ? (int)m_dockBottomPortion : (int)(height * m_dockBottomPortion);
  
                  if (dockTopSize < MeasurePane.MinSize)
                      dockTopSize = MeasurePane.MinSize;
                  if (dockBottomSize < MeasurePane.MinSize)
                      dockBottomSize = MeasurePane.MinSize;
  
                  if (dockTopSize + dockBottomSize > height - MeasurePane.MinSize)
                  {
                      int adjust = (dockTopSize + dockBottomSize) - (height - MeasurePane.MinSize);
                      dockTopSize -= adjust / 2;
  
gt:                     dockBottomSize -= adjust / 2;