context: using System;
  using System.Windows.Forms;
  using System.Drawing;
  using System.ComponentModel;
  using System.Diagnostics.CodeAnalysis;
  
  namespace WeifenLuo.WinFormsUI.Docking
  {
      public delegate string GetPersistStringCallback();
  
      public class DockContentHandler : IDisposable, IDockDragSource
      {
          public DockContentHandler(Form form)
              : this(form, null)
          {
          }
  
          public DockContentHandler(Form form, GetPersistStringCallback getPersistStringCallback)
          {
              if (!(form is IDockContent))
                  throw new ArgumentException(Strings.DockContent_Constructor_InvalidForm, "form");
  
              m_form = form;
              m_getPersistStringCallback = getPersistStringCallback;
  
              m_events = new EventHandlerList();
              Form.Disposed += new EventHandler(Form_Disposed);
              Form.TextChanged += new EventHandler(Form_TextChanged);
          }
  
          public void Dispose()
          {
              Dispose(true);
              GC.SuppressFinalize(this);
          }
  
          protected virtual void Dispose(bool disposing)
          {
              if (disposing)
              {
                  lock (this)
                  {
                      DockPanel = null;
                      if (m_autoHideTab != null)
                          m_autoHideTab.Dispose();
                      if (m_tab != null)
                          m_tab.Dispose();
  
                      Form.Disposed -= new EventHandler(Form_Disposed);
                      Form.TextChanged -= new EventHandler(Form_TextChanged);
                      m_events.Dispose();
                  }
              }
          }
  
          private Form m_form;
          public Form Form
          {
              get { return m_form; }
          }
  
          public IDockContent Content
          {
              get { return Form as IDockContent; }
          }
  
          private IDockContent m_previousActive = null;
          public IDockContent PreviousActive
          {
              get { return m_previousActive; }
              internal set { m_previousActive = value; }
          }
  
          private IDockContent m_nextActive = null;
          public IDockContent NextActive
          {
              get { return m_nextActive; }
              internal set { m_nextActive = value; }
          }
  
          private EventHandlerList m_events;
          private EventHandlerList Events
          {
              get { return m_events; }
          }
  
          private bool m_allowEndUserDocking = true;
          public bool AllowEndUserDocking
          {
              get { return m_allowEndUserDocking; }
              set { m_allowEndUserDocking = value; }
          }
  
          private double m_autoHidePortion = 0.25;
          public double AutoHidePortion
          {
              get { return m_autoHidePortion; }
              set
              {
                  if (value <= 0)
                      throw (new ArgumentOutOfRangeException(Strings.DockContentHandler_AutoHidePortion_OutOfRange));
  
                  if (m_autoHidePortion == value)
                      return;
  
                  m_autoHidePortion = value;
  
                  if (DockPanel == null)
                      return;
  
                  if (DockPanel.ActiveAutoHideContent == Content)
                      DockPanel.PerformLayout();
              }
          }
  
          private bool m_closeButton = true;
          public bool CloseButton
          {
              get { return m_closeButton; }
              set
              {
                  if (m_closeButton == value)
                      return;
  
                  m_closeButton = value;
                  if (Pane != null)
                      if (Pane.ActiveContent.DockHandler == this)
                          Pane.RefreshChanges();
              }
          }
  
          private bool m_closeButtonVisible = true;
          /// <summary>
          /// Determines whether the close button is visible on the content
          /// </summary>
          public bool CloseButtonVisible
          {
              get { return m_closeButtonVisible; }
              set { m_closeButtonVisible = value; }
          }
  
          private DockState DefaultDockState
          {
              get
              {
                  if (ShowHint != DockState.Unknown && ShowHint != DockState.Hidden)
                      return ShowHint;
  
                  if ((DockAreas & DockAreas.Document) != 0)
                      return DockState.Document;
                  if ((DockAreas & DockAreas.DockRight) != 0)
                      return DockState.DockRight;
                  if ((DockAreas & DockAreas.DockLeft) != 0)
                      return DockState.DockLeft;
                  if ((DockAreas & DockAreas.DockBottom) != 0)
                      return DockState.DockBottom;
                  if ((DockAreas & DockAreas.DockTop) != 0)
                      return DockState.DockTop;
  
                  return DockState.Unknown;
              }
          }
  
          private DockState DefaultShowState
          {
              get
              {
                  if (ShowHint != DockState.Unknown)
                      return ShowHint;
  
                  if ((DockAreas & DockAreas.Document) != 0)
                      return DockState.Document;
                  if ((DockAreas & DockAreas.DockRight) != 0)
                      return DockState.DockRight;
                  if ((DockAreas & DockAreas.DockLeft) != 0)
                      return DockState.DockLeft;
                  if ((DockAreas & DockAreas.DockBottom) != 0)
                      return DockState.DockBottom;
                  if ((DockAreas & DockAreas.DockTop) != 0)
                      return DockState.DockTop;
                  if ((DockAreas & DockAreas.Float) != 0)
                      return DockState.Float;
  
                  return DockState.Unknown;
              }
          }
  
          private DockAreas m_allowedAreas = DockAreas.DockLeft | DockAreas.DockRight | DockAreas.DockTop | DockAreas.DockBottom | DockAreas.Document | DockAreas.Float;
          public DockAreas DockAreas
          {
              get { return m_allowedAreas; }
              set
              {
                  if (m_allowedAreas == value)
                      return;
  
                  if (!DockHelper.IsDockStateValid(DockState, value))
                      throw (new InvalidOperationException(Strings.DockContentHandler_DockAreas_InvalidValue));
  
                  m_allowedAreas = value;
  
                  if (!DockHelper.IsDockStateValid(ShowHint, m_allowedAreas))
                      ShowHint = DockState.Unknown;
              }
          }
  
          private DockState m_dockState = DockState.Unknown;
          public DockState DockState
          {
              get { return m_dockState; }
              set
              {
                  if (m_dockState == value)
                      return;
  
                  DockPanel.SuspendLayout(true);
  
                  if (value == DockState.Hidden)
                      IsHidden = true;
                  else
                      SetDockState(false, value, Pane);
  
                  DockPanel.ResumeLayout(true, true);
              }
          }
  
          private DockPanel m_dockPanel = null;
          public DockPanel DockPanel
          {
              get { return m_dockPanel; }
              set
              {
                  if (m_dockPanel == value)
                      return;
  
                  Pane = null;
  
                  if (m_dockPanel != null)
                      m_dockPanel.RemoveContent(Content);
  
                  if (m_tab != null)
                  {
                      m_tab.Dispose();
                      m_tab = null;
                  }
  
                  if (m_autoHideTab != null)
                  {
                      m_autoHideTab.Dispose();
                      m_autoHideTab = null;
                  }
  
                  m_dockPanel = value;
  
                  if (m_dockPanel != null)
                  {
                      m_dockPanel.AddContent(Content);
                      Form.TopLevel = false;
                      Form.FormBorderStyle = FormBorderStyle.None;
                      Form.ShowInTaskbar = false;
                      Form.WindowState = FormWindowState.Normal;
                      NativeMethods.SetWindowPos(Form.Handle, IntPtr.Zero, 0, 0, 0, 0,
                          Win32.FlagsSetWindowPos.SWP_NOACTIVATE |
                          Win32.FlagsSetWindowPos.SWP_NOMOVE |
                          Win32.FlagsSetWindowPos.SWP_NOSIZE |
                          Win32.FlagsSetWindowPos.SWP_NOZORDER |
                          Win32.FlagsSetWindowPos.SWP_NOOWNERZORDER |
                          Win32.FlagsSetWindowPos.SWP_FRAMECHANGED);
                  }
              }
          }
  
          public Icon Icon
          {
              get { return Form.Icon; }
          }
  
          public DockPane Pane
          {
              get { return IsFloat ? FloatPane : PanelPane; }
              set
              {
                  if (Pane == value)
                      return;
  
                  DockPanel.SuspendLayout(true);
  
                  DockPane oldPane = Pane;
  
                  SuspendSetDockState();
                  FloatPane = (value == null ? null : (value.IsFloat ? value : FloatPane));
                  PanelPane = (value == null ? null : (value.IsFloat ? PanelPane : value));
                  ResumeSetDockState(IsHidden, value != null ? value.DockState : DockState.Unknown, oldPane);
  
                  DockPanel.ResumeLayout(true, true);
              }
          }
  
          private bool m_isHidden = true;
          public bool IsHidden
          {
              get { return m_isHidden; }
              set
              {
                  if (m_isHidden == value)
                      return;
  
                  SetDockState(value, VisibleState, Pane);
              }
          }
  
          private string m_tabText = null;
          public string TabText
          {
              get { return m_tabText == null || m_tabText == "" ? Form.Text : m_tabText; }
              set
              {
                  if (m_tabText == value)
                      return;
  
                  m_tabText = value;
                  if (Pane != null)
                      Pane.RefreshChanges();
              }
          }
  
          private DockState m_visibleState = DockState.Unknown;
          public DockState VisibleState
          {
              get { return m_visibleState; }
              set
              {
                  if (m_visibleState == value)
                      return;
  
                  SetDockState(IsHidden, value, Pane);
              }
          }
  
          private bool m_isFloat = false;
          public bool IsFloat
          {
              get { return m_isFloat; }
              set
              {
                  if (m_isFloat == value)
                      return;
  
                  DockState visibleState = CheckDockState(value);
  
                  if (visibleState == DockState.Unknown)
                      throw new InvalidOperationException(Strings.DockContentHandler_IsFloat_InvalidValue);
  
                  SetDockState(IsHidden, visibleState, Pane);
              }
          }
  
          [SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters")]
          public DockState CheckDockState(bool isFloat)
          {
              DockState dockState;
  
              if (isFloat)
              {
                  if (!IsDockStateValid(DockState.Float))
                      dockState = DockState.Unknown;
                  else
                      dockState = DockState.Float;
              }
              else
              {
                  dockState = (PanelPane != null) ? PanelPane.DockState : DefaultDockState;
                  if (dockState != DockState.Unknown && !IsDockStateValid(dockState))
                      dockState = DockState.Unknown;
              }
  
              return dockState;
          }
  
          private DockPane m_panelPane = null;
          public DockPane PanelPane
          {
              get { return m_panelPane; }
              set
              {
                  if (m_panelPane == value)
                      return;
  
                  if (value != null)
                  {
                      if (value.IsFloat || value.DockPanel != DockPanel)
                          throw new InvalidOperationException(Strings.DockContentHandler_DockPane_InvalidValue);
                  }
  
                  DockPane oldPane = Pane;
  
                  if (m_panelPane != null)
                      RemoveFromPane(m_panelPane);
                  m_panelPane = value;
                  if (m_panelPane != null)
                  {
                      m_panelPane.AddContent(Content);
                      SetDockState(IsHidden, IsFloat ? DockState.Float : m_panelPane.DockState, oldPane);
                  }
                  else
                      SetDockState(IsHidden, DockState.Unknown, oldPane);
              }
          }
  
          private void RemoveFromPane(DockPane pane)
          {
              pane.RemoveContent(Content);
              SetPane(null);
              if (pane.Contents.Count == 0)
                  pane.Dispose();
          }
  
          private DockPane m_floatPane = null;
          public DockPane FloatPane
          {
              get { return m_floatPane; }
              set
              {
                  if (m_floatPane == value)
                      return;
  
                  if (value != null)
                  {
                      if (!value.IsFloat || value.DockPanel != DockPanel)
                          throw new InvalidOperationException(Strings.DockContentHandler_FloatPane_InvalidValue);
                  }
  
                  DockPane oldPane = Pane;
  
                  if (m_floatPane != null)
                      RemoveFromPane(m_floatPane);
                  m_floatPane = value;
                  if (m_floatPane != null)
                  {
                      m_floatPane.AddContent(Content);
                      SetDockState(IsHidden, IsFloat ? DockState.Float : VisibleState, oldPane);
                  }
                  else
                      SetDockState(IsHidden, DockState.Unknown, oldPane);
              }
          }
  
          private int m_countSetDockState = 0;
          private void SuspendSetDockState()
          {
              m_countSetDockState++;
          }
  
          private void ResumeSetDockState()
          {
              m_countSetDockState--;
              if (m_countSetDockState < 0)
                  m_countSetDockState = 0;
          }
  
          internal bool IsSuspendSetDockState
          {
              get { return m_countSetDockState != 0; }
          }
  
          private void ResumeSetDockState(bool isHidden, DockState visibleState, DockPane oldPane)
          {
              ResumeSetDockState();
              SetDockState(isHidden, visibleState, oldPane);
          }
  
          internal void SetDockState(bool isHidden, DockState visibleState, DockPane oldPane)
          {
              if (IsSuspendSetDockState)
                  return;
  
              if (DockPanel == null && visibleState != DockState.Unknown)
                  throw new InvalidOperationException(Strings.DockContentHandler_SetDockState_NullPanel);
  
              if (visibleState == DockState.Hidden || (visibleState != DockState.Unknown && !IsDockStateValid(visibleState)))
                  throw new InvalidOperationException(Strings.DockContentHandler_SetDockState_InvalidState);
  
              DockPanel dockPanel = DockPanel;
              if (dockPanel != null)
                  dockPanel.SuspendLayout(true);
  
              SuspendSetDockState();
  
              DockState oldDockState = DockState;
  
              if (m_isHidden != isHidden || oldDockState == DockState.Unknown)
              {
                  m_isHidden = isHidden;
              }
              m_visibleState = visibleState;
              m_dockState = isHidden ? DockState.Hidden : visibleState;
  
  
gt:             if (visibleState == DockState.Unknown)