/*************************************************************************************

   Extended WPF Toolkit

   Copyright (C) 2007-2013 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license 

   For more features, controls, and fast professional support,
   pick up the Plus Edition at http://xceed.com/wpf_toolkit

   Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids

  ***********************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Markup;
using System.ComponentModel;
using System.Windows.Interop;
using System.Diagnostics;

using Xceed.Wpf.AvalonDock.Layout;
using Xceed.Wpf.AvalonDock.Controls;
using System.Windows.Input;
using System.Collections;
using System.Collections.Specialized;
using System.Windows.Data;
using System.Windows.Threading;
using Xceed.Wpf.AvalonDock.Commands;
using Xceed.Wpf.AvalonDock.Themes;

namespace Xceed.Wpf.AvalonDock
{
    [ContentProperty("Layout")]
    [TemplatePart(Name="PART_AutoHideArea")]
    public class DockingManager : Control, IOverlayWindowHost//, ILogicalChildrenContainer
    {
        private ResourceDictionary currentThemeResourceDictionary; // = null

        static DockingManager()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(DockingManager), new FrameworkPropertyMetadata(typeof(DockingManager)));
            FocusableProperty.OverrideMetadata(typeof(DockingManager), new FrameworkPropertyMetadata(false));
            HwndSource.DefaultAcquireHwndFocusInMenuMode = false;
        }


        public DockingManager()
        {
#if !VS2008
          Layout = new LayoutRoot() { RootPanel = new LayoutPanel(new LayoutDocumentPaneGroup(new LayoutDocumentPane())) };
#else
          this.SetCurrentValue( DockingManager.LayoutProperty, new LayoutRoot() { RootPanel = new LayoutPanel(new LayoutDocumentPaneGroup(new LayoutDocumentPane())) } );
#endif
          this.Loaded += new RoutedEventHandler(DockingManager_Loaded);
          this.Unloaded += new RoutedEventHandler(DockingManager_Unloaded);
        }

        #region Layout

        /// <summary>
        /// Layout Dependency Property
        /// </summary>
        public static readonly DependencyProperty LayoutProperty =
            DependencyProperty.Register("Layout", typeof(LayoutRoot), typeof(DockingManager),
                new FrameworkPropertyMetadata(null,
                    new PropertyChangedCallback(OnLayoutChanged),
                    new CoerceValueCallback(CoerceLayoutValue)));

        /// <summary>
        /// Gets or sets the Layout property.  This dependency property 
        /// indicates layout tree.
        /// </summary>
        public LayoutRoot Layout
        {
            get { return (LayoutRoot)GetValue(LayoutProperty); }
            set { SetValue(LayoutProperty, value); }
        }

        /// <summary>
        /// Handles changes to the Layout property.
        /// </summary>
        private static void OnLayoutChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnLayoutChanged(e.OldValue as LayoutRoot, e.NewValue as LayoutRoot);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the <see cref="DockingManager.Layout"/> property.
        /// </summary>
        protected virtual void OnLayoutChanged(LayoutRoot oldLayout, LayoutRoot newLayout)
        {
            if (oldLayout != null)
            {
                oldLayout.PropertyChanged -= new PropertyChangedEventHandler(OnLayoutRootPropertyChanged);
                oldLayout.Updated -= new EventHandler(OnLayoutRootUpdated);
            }

            foreach (var fwc in _fwList.ToArray())
            {
                fwc.KeepContentVisibleOnClose = true;
                fwc.InternalClose();
            }

            _fwList.Clear();

            DetachDocumentsSource(oldLayout, DocumentsSource);
            DetachAnchorablesSource(oldLayout, AnchorablesSource);

            if (oldLayout != null &&
                oldLayout.Manager == this)
                oldLayout.Manager = null;

            ClearLogicalChildrenList();
            DetachLayoutItems();

            Layout.Manager = this;

            AttachLayoutItems();
            AttachDocumentsSource(newLayout, DocumentsSource);
            AttachAnchorablesSource(newLayout, AnchorablesSource);

            if (IsLoaded)
            {
                LayoutRootPanel = CreateUIElementForModel(Layout.RootPanel) as LayoutPanelControl;
                LeftSidePanel = CreateUIElementForModel(Layout.LeftSide) as LayoutAnchorSideControl;
                TopSidePanel = CreateUIElementForModel(Layout.TopSide) as LayoutAnchorSideControl;
                RightSidePanel = CreateUIElementForModel(Layout.RightSide) as LayoutAnchorSideControl;
                BottomSidePanel = CreateUIElementForModel(Layout.BottomSide) as LayoutAnchorSideControl;

                foreach (var fw in Layout.FloatingWindows.ToArray())
                {
                    if (fw.IsValid)
                       _fwList.Add(CreateUIElementForModel(fw) as LayoutFloatingWindowControl);
                }

                foreach (var fw in _fwList)
                {
                    //fw.Owner = Window.GetWindow(this);
                    //fw.SetParentToMainWindowOf(this);
                }
            }


            if (newLayout != null)
            {
                newLayout.PropertyChanged += new PropertyChangedEventHandler(OnLayoutRootPropertyChanged);
                newLayout.Updated += new EventHandler(OnLayoutRootUpdated);
            }

            if (LayoutChanged != null)
                LayoutChanged(this, EventArgs.Empty);

            //if (Layout != null)
            //    Layout.CollectGarbage();

            CommandManager.InvalidateRequerySuggested();
        }

      //  DispatcherOperation _setFocusAsyncOperation = null;

        void OnLayoutRootPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "RootPanel")
            {
                if (IsInitialized)
                {
                    var layoutRootPanel = CreateUIElementForModel(Layout.RootPanel) as LayoutPanelControl;
                    LayoutRootPanel = layoutRootPanel;
                }
            }
            else if (e.PropertyName == "ActiveContent")
            {
                if (Layout.ActiveContent != null)
                {
                    //Debug.WriteLine(new StackTrace().ToString());

                    //set focus on active element only after a layout pass is completed
                    //it's possible that it is not yet visible in the visual tree
                    //if (_setFocusAsyncOperation == null)
                    //{
                    //    _setFocusAsyncOperation = Dispatcher.BeginInvoke(new Action(() =>
                           // {
                                if (Layout.ActiveContent != null)
                                    FocusElementManager.SetFocusOnLastElement(Layout.ActiveContent);
                                //_setFocusAsyncOperation = null;
                          //  } ), DispatcherPriority.Input );
                    //}
                }

            //if (!_insideInternalSetActiveContent)
            //    ActiveContent = Layout.ActiveContent != null ?
            //        Layout.ActiveContent.Content : null;
            if( !_insideInternalSetActiveContent && (Layout.ActiveContent != null) )
            {
              this.ActiveContent = Layout.ActiveContent.Content;
            }
          }
        }

        void OnLayoutRootUpdated(object sender, EventArgs e)
        {
            CommandManager.InvalidateRequerySuggested();
        }


        /// <summary>
        /// Event fired when <see cref="DockingManager.Layout"/> property changes
        /// </summary>
        public event EventHandler LayoutChanged;

        /// <summary>
        /// Coerces the <see cref="DockingManager.Layout"/> value.
        /// </summary>
        private static object CoerceLayoutValue(DependencyObject d, object value)
        {
            if (value == null)
                return new LayoutRoot() { RootPanel = new LayoutPanel(new LayoutDocumentPaneGroup(new LayoutDocumentPane())) };

            ((DockingManager)d).OnLayoutChanging(value as LayoutRoot);

            return value;
        }

        /// <summary>
        /// Event fired when <see cref="DockingManager.Layout"/> property is about to be changed
        /// </summary>
        public event EventHandler LayoutChanging;

        void OnLayoutChanging(LayoutRoot newLayout)
        {
            if (LayoutChanging != null)
                LayoutChanging(this, EventArgs.Empty);
        }


        #region LayoutUpdateStrategy

        /// <summary>
        /// LayoutUpdateStrategy Dependency Property
        /// </summary>
        public static readonly DependencyProperty LayoutUpdateStrategyProperty =
            DependencyProperty.Register("LayoutUpdateStrategy", typeof(ILayoutUpdateStrategy), typeof(DockingManager),
                new FrameworkPropertyMetadata((ILayoutUpdateStrategy)null));

        /// <summary>
        /// Gets or sets the LayoutUpdateStrategy property.  This dependency property 
        /// indicates the strategy class to call when AvalonDock needs to positionate a LayoutAnchorable inside an existing layout.
        /// </summary>
        /// <remarks>Sometimes it's impossible to automatically insert an anchorable in the layout without specifing the target parent pane.
        /// Set this property to an object that will be asked to insert the anchorable to the desidered position.</remarks>
        public ILayoutUpdateStrategy LayoutUpdateStrategy
        {
            get { return (ILayoutUpdateStrategy)GetValue(LayoutUpdateStrategyProperty); }
            set { SetValue(LayoutUpdateStrategyProperty, value); }
        }

        #endregion



        #endregion

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

          //  SetupAutoHideWindow();
        }

        protected override void OnInitialized( EventArgs e )
        {
            base.OnInitialized(e);
        }

        void DockingManager_Loaded(object sender, RoutedEventArgs e)
        {
            if (!DesignerProperties.GetIsInDesignMode(this))
            {
                if( Layout.Manager == this )
                {
                  LayoutRootPanel = CreateUIElementForModel( Layout.RootPanel ) as LayoutPanelControl;
                  LeftSidePanel = CreateUIElementForModel( Layout.LeftSide ) as LayoutAnchorSideControl;
                  TopSidePanel = CreateUIElementForModel( Layout.TopSide ) as LayoutAnchorSideControl;
                  RightSidePanel = CreateUIElementForModel( Layout.RightSide ) as LayoutAnchorSideControl;
                  BottomSidePanel = CreateUIElementForModel( Layout.BottomSide ) as LayoutAnchorSideControl;
                }

                SetupAutoHideWindow();

                //load windows not already loaded!
                foreach (var fw in Layout.FloatingWindows.Where(fw => !_fwList.Any(fwc => fwc.Model == fw)))
                    _fwList.Add(CreateUIElementForModel(fw) as LayoutFloatingWindowControl);

                //create the overlaywindow if it's possible
                if (IsVisible)
                    CreateOverlayWindow();
                FocusElementManager.SetupFocusManagement(this);
            }
        }

        void DockingManager_Unloaded(object sender, RoutedEventArgs e)
        {

            if (!DesignerProperties.GetIsInDesignMode(this))
            {
              if( _autoHideWindowManager != null )
              {
                _autoHideWindowManager.HideAutoWindow();
              }

              if( AutoHideWindow != null )
                AutoHideWindow.Dispose();

              foreach (var fw in _fwList.ToArray())
              {
                  //fw.Owner = null;
                  fw.SetParentWindowToNull();
                  fw.KeepContentVisibleOnClose = true;
                  fw.Close();
              }

              DestroyOverlayWindow();
              FocusElementManager.FinalizeFocusManagement(this);
            }
        }

        internal UIElement CreateUIElementForModel(ILayoutElement model)
        {
            if (model is LayoutPanel)
                return new LayoutPanelControl(model as LayoutPanel);
            if (model is LayoutAnchorablePaneGroup)
                return new LayoutAnchorablePaneGroupControl(model as LayoutAnchorablePaneGroup);
            if (model is LayoutDocumentPaneGroup)
                return new LayoutDocumentPaneGroupControl(model as LayoutDocumentPaneGroup);

            if (model is LayoutAnchorSide)
            {
                var templateModelView = new LayoutAnchorSideControl(model as LayoutAnchorSide);
                templateModelView.SetBinding(LayoutAnchorSideControl.TemplateProperty, new Binding("AnchorSideTemplate") { Source = this });
                return templateModelView;
            }
            if (model is LayoutAnchorGroup)
            {
                var templateModelView = new LayoutAnchorGroupControl(model as LayoutAnchorGroup);
                templateModelView.SetBinding(LayoutAnchorGroupControl.TemplateProperty, new Binding("AnchorGroupTemplate") { Source = this });
                return templateModelView;
            }

            if (model is LayoutDocumentPane)
            {
                var templateModelView = new LayoutDocumentPaneControl(model as LayoutDocumentPane);
                templateModelView.SetBinding(LayoutDocumentPaneControl.StyleProperty, new Binding("DocumentPaneControlStyle") { Source = this });
                return templateModelView;
            }
            if (model is LayoutAnchorablePane)
            {
                var templateModelView = new LayoutAnchorablePaneControl(model as LayoutAnchorablePane);
                templateModelView.SetBinding(LayoutAnchorablePaneControl.StyleProperty, new Binding("AnchorablePaneControlStyle") { Source = this });
                return templateModelView;
            }

            if (model is LayoutAnchorableFloatingWindow)
            {
                if (DesignerProperties.GetIsInDesignMode(this))
                    return null;
                var modelFW = model as LayoutAnchorableFloatingWindow;
                var newFW = new LayoutAnchorableFloatingWindowControl(modelFW)
                {
                    //Owner = Window.GetWindow(this) 
                };
                newFW.SetParentToMainWindowOf(this);

                var paneForExtensions = modelFW.RootPanel.Children.OfType<LayoutAnchorablePane>().FirstOrDefault();
                if (paneForExtensions != null)
                {
                    //ensure that floating window position is inside current (or nearest) monitor
                    paneForExtensions.KeepInsideNearestMonitor();

                    newFW.Left = paneForExtensions.FloatingLeft;
                    newFW.Top = paneForExtensions.FloatingTop;
                    newFW.Width = paneForExtensions.FloatingWidth;
                    newFW.Height = paneForExtensions.FloatingHeight;
                }

                newFW.ShowInTaskbar = false;
                newFW.Show();
                // Do not set the WindowState before showing or it will be lost
                if( paneForExtensions != null && paneForExtensions.IsMaximized )
                {
                  newFW.WindowState = WindowState.Maximized;
                }
                return newFW;
            }

            if (model is LayoutDocumentFloatingWindow)
            {
                if (DesignerProperties.GetIsInDesignMode(this))
                    return null;
                var modelFW = model as LayoutDocumentFloatingWindow;
                var newFW = new LayoutDocumentFloatingWindowControl(modelFW)
                {
                    //Owner = Window.GetWindow(this) 
                };
                newFW.SetParentToMainWindowOf(this);

                var paneForExtensions = modelFW.RootDocument;
                if (paneForExtensions != null)
                {
                    //ensure that floating window position is inside current (or nearest) monitor
                    paneForExtensions.KeepInsideNearestMonitor();

                    newFW.Left = paneForExtensions.FloatingLeft;
                    newFW.Top = paneForExtensions.FloatingTop;
                    newFW.Width = paneForExtensions.FloatingWidth;
                    newFW.Height = paneForExtensions.FloatingHeight;
                }

                newFW.ShowInTaskbar = false;
                newFW.Show();
                // Do not set the WindowState before showing or it will be lost
                if( paneForExtensions != null && paneForExtensions.IsMaximized )
                {
                  newFW.WindowState = WindowState.Maximized;
                }
                return newFW;
            }

            if (model is LayoutDocument)
            {
                var templateModelView = new LayoutDocumentControl() { Model = model as LayoutDocument };
                return templateModelView;
            }

            return null;
        }



        #region DocumentPaneTemplate

        /// <summary>
        /// DocumentPaneTemplate Dependency Property
        /// </summary>
        public static readonly DependencyProperty DocumentPaneTemplateProperty =
            DependencyProperty.Register("DocumentPaneTemplate", typeof(ControlTemplate), typeof(DockingManager),
                new FrameworkPropertyMetadata((ControlTemplate)null,
                    new PropertyChangedCallback(OnDocumentPaneTemplateChanged)));

        /// <summary>
        /// Gets or sets the DocumentPaneDataTemplate property.  This dependency property 
        /// indicates .
        /// </summary>
        public ControlTemplate DocumentPaneTemplate
        {
            get { return (ControlTemplate)GetValue(DocumentPaneTemplateProperty); }
            set { SetValue(DocumentPaneTemplateProperty, value); }
        }

        /// <summary>
        /// Handles changes to the DocumentPaneTemplate property.
        /// </summary>
        private static void OnDocumentPaneTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnDocumentPaneTemplateChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the DocumentPaneTemplate property.
        /// </summary>
        protected virtual void OnDocumentPaneTemplateChanged(DependencyPropertyChangedEventArgs e)
        {
        }

        #endregion

        #region AnchorablePaneTemplate

        /// <summary>
        /// AnchorablePaneTemplate Dependency Property
        /// </summary>
        public static readonly DependencyProperty AnchorablePaneTemplateProperty =
            DependencyProperty.Register("AnchorablePaneTemplate", typeof(ControlTemplate), typeof(DockingManager),
                new FrameworkPropertyMetadata((ControlTemplate)null,
                    new PropertyChangedCallback(OnAnchorablePaneTemplateChanged)));

        /// <summary>
        /// Gets or sets the AnchorablePaneTemplate property.  This dependency property 
        /// indicates ....
        /// </summary>
        public ControlTemplate AnchorablePaneTemplate
        {
            get { return (ControlTemplate)GetValue(AnchorablePaneTemplateProperty); }
            set { SetValue(AnchorablePaneTemplateProperty, value); }
        }

        /// <summary>
        /// Handles changes to the AnchorablePaneDataTemplate property.
        /// </summary>
        private static void OnAnchorablePaneTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnAnchorablePaneTemplateChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the AnchorablePaneDataTemplate property.
        /// </summary>
        protected virtual void OnAnchorablePaneTemplateChanged(DependencyPropertyChangedEventArgs e)
        {
        }

        #endregion

        #region AnchorSideTemplate

        /// <summary>
        /// AnchorSideTemplate Dependency Property
        /// </summary>
        public static readonly DependencyProperty AnchorSideTemplateProperty =
            DependencyProperty.Register("AnchorSideTemplate", typeof(ControlTemplate), typeof(DockingManager),
                new FrameworkPropertyMetadata((ControlTemplate)null));

        /// <summary>
        /// Gets or sets the AnchorSideTemplate property.  This dependency property 
        /// indicates ....
        /// </summary>
        public ControlTemplate AnchorSideTemplate
        {
            get { return (ControlTemplate)GetValue(AnchorSideTemplateProperty); }
            set { SetValue(AnchorSideTemplateProperty, value); }
        }

        #endregion

        #region AnchorGroupTemplate

        /// <summary>
        /// AnchorGroupTemplate Dependency Property
        /// </summary>
        public static readonly DependencyProperty AnchorGroupTemplateProperty =
            DependencyProperty.Register("AnchorGroupTemplate", typeof(ControlTemplate), typeof(DockingManager),
                new FrameworkPropertyMetadata((ControlTemplate)null));

        /// <summary>
        /// Gets or sets the AnchorGroupTemplate property.  This dependency property 
        /// indicates the template used to render the AnchorGroup control.
        /// </summary>
        public ControlTemplate AnchorGroupTemplate
        {
            get { return (ControlTemplate)GetValue(AnchorGroupTemplateProperty); }
            set { SetValue(AnchorGroupTemplateProperty, value); }
        }

        #endregion

        #region AnchorTemplate

        /// <summary>
        /// AnchorTemplate Dependency Property
        /// </summary>
        public static readonly DependencyProperty AnchorTemplateProperty =
            DependencyProperty.Register("AnchorTemplate", typeof(ControlTemplate), typeof(DockingManager),
                new FrameworkPropertyMetadata((ControlTemplate)null));

        /// <summary>
        /// Gets or sets the AnchorTemplate property.  This dependency property 
        /// indicates ....
        /// </summary>
        public ControlTemplate AnchorTemplate
        {
            get { return (ControlTemplate)GetValue(AnchorTemplateProperty); }
            set { SetValue(AnchorTemplateProperty, value); }
        }

        #endregion

        #region DocumentPaneControlStyle

        /// <summary>
        /// DocumentPaneControlStyle Dependency Property
        /// </summary>
        public static readonly DependencyProperty DocumentPaneControlStyleProperty =
            DependencyProperty.Register("DocumentPaneControlStyle", typeof(Style), typeof(DockingManager),
                new FrameworkPropertyMetadata((Style)null,
                    new PropertyChangedCallback(OnDocumentPaneControlStyleChanged)));

        /// <summary>
        /// Gets or sets the DocumentPaneControlStyle property.  This dependency property 
        /// indicates ....
        /// </summary>
        public Style DocumentPaneControlStyle
        {
            get { return (Style)GetValue(DocumentPaneControlStyleProperty); }
            set { SetValue(DocumentPaneControlStyleProperty, value); }
        }

        /// <summary>
        /// Handles changes to the DocumentPaneControlStyle property.
        /// </summary>
        private static void OnDocumentPaneControlStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnDocumentPaneControlStyleChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the DocumentPaneControlStyle property.
        /// </summary>
        protected virtual void OnDocumentPaneControlStyleChanged(DependencyPropertyChangedEventArgs e)
        {
        }

        #endregion

        #region AnchorablePaneControlStyle

        /// <summary>
        /// AnchorablePaneControlStyle Dependency Property
        /// </summary>
        public static readonly DependencyProperty AnchorablePaneControlStyleProperty =
            DependencyProperty.Register("AnchorablePaneControlStyle", typeof(Style), typeof(DockingManager),
                new FrameworkPropertyMetadata((Style)null,
                    new PropertyChangedCallback(OnAnchorablePaneControlStyleChanged)));

        /// <summary>
        /// Gets or sets the AnchorablePaneControlStyle property.  This dependency property 
        /// indicates the style to apply to AnchorablePaneControl.
        /// </summary>
        public Style AnchorablePaneControlStyle
        {
            get { return (Style)GetValue(AnchorablePaneControlStyleProperty); }
            set { SetValue(AnchorablePaneControlStyleProperty, value); }
        }

        /// <summary>
        /// Handles changes to the AnchorablePaneControlStyle property.
        /// </summary>
        private static void OnAnchorablePaneControlStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnAnchorablePaneControlStyleChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the AnchorablePaneControlStyle property.
        /// </summary>
        protected virtual void OnAnchorablePaneControlStyleChanged(DependencyPropertyChangedEventArgs e)
        {
        }

        #endregion

        #region DocumentHeaderTemplate

        /// <summary>
        /// DocumentHeaderTemplate Dependency Property
        /// </summary>
        public static readonly DependencyProperty DocumentHeaderTemplateProperty =
            DependencyProperty.Register("DocumentHeaderTemplate", typeof(DataTemplate), typeof(DockingManager),
                new FrameworkPropertyMetadata((DataTemplate)null,
                    new PropertyChangedCallback(OnDocumentHeaderTemplateChanged),
                    new CoerceValueCallback(CoerceDocumentHeaderTemplateValue)));

        /// <summary>
        /// Gets or sets the DocumentHeaderTemplate property.  This dependency property 
        /// indicates data template to use for document header.
        /// </summary>
        public DataTemplate DocumentHeaderTemplate
        {
            get { return (DataTemplate)GetValue(DocumentHeaderTemplateProperty); }
            set { SetValue(DocumentHeaderTemplateProperty, value); }
        }

        /// <summary>
        /// Handles changes to the DocumentHeaderTemplate property.
        /// </summary>
        private static void OnDocumentHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnDocumentHeaderTemplateChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the DocumentHeaderTemplate property.
        /// </summary>
        protected virtual void OnDocumentHeaderTemplateChanged(DependencyPropertyChangedEventArgs e)
        {
        }

        /// <summary>
        /// Coerces the DocumentHeaderTemplate value.
        /// </summary>
        private static object CoerceDocumentHeaderTemplateValue(DependencyObject d, object value)
        {
            if (value != null &&
                d.GetValue(DocumentHeaderTemplateSelectorProperty) != null)
                return null;
            return value;
        }

        #endregion

        #region DocumentHeaderTemplateSelector

        /// <summary>
        /// DocumentHeaderTemplateSelector Dependency Property
        /// </summary>
        public static readonly DependencyProperty DocumentHeaderTemplateSelectorProperty =
            DependencyProperty.Register("DocumentHeaderTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager),
                new FrameworkPropertyMetadata((DataTemplateSelector)null,
                    new PropertyChangedCallback(OnDocumentHeaderTemplateSelectorChanged),
                    new CoerceValueCallback(CoerceDocumentHeaderTemplateSelectorValue)));

        /// <summary>
        /// Gets or sets the DocumentHeaderTemplateSelector property.  This dependency property 
        /// indicates the template selector that is used when selcting the data template for the header.
        /// </summary>
        public DataTemplateSelector DocumentHeaderTemplateSelector
        {
            get { return (DataTemplateSelector)GetValue(DocumentHeaderTemplateSelectorProperty); }
            set { SetValue(DocumentHeaderTemplateSelectorProperty, value); }
        }

        /// <summary>
        /// Handles changes to the DocumentHeaderTemplateSelector property.
        /// </summary>
        private static void OnDocumentHeaderTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnDocumentHeaderTemplateSelectorChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the DocumentHeaderTemplateSelector property.
        /// </summary>
        protected virtual void OnDocumentHeaderTemplateSelectorChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue != null &&
                DocumentHeaderTemplate != null)
                DocumentHeaderTemplate = null;

            if (DocumentPaneMenuItemHeaderTemplateSelector == null)
                DocumentPaneMenuItemHeaderTemplateSelector = DocumentHeaderTemplateSelector;

        }

        /// <summary>
        /// Coerces the DocumentHeaderTemplateSelector value.
        /// </summary>
        private static object CoerceDocumentHeaderTemplateSelectorValue(DependencyObject d, object value)
        {
            return value;
        }

        #endregion

        #region DocumentTitleTemplate

        /// <summary>
        /// DocumentTitleTemplate Dependency Property
        /// </summary>
        public static readonly DependencyProperty DocumentTitleTemplateProperty =
            DependencyProperty.Register("DocumentTitleTemplate", typeof(DataTemplate), typeof(DockingManager),
                new FrameworkPropertyMetadata((DataTemplate)null,
                    new PropertyChangedCallback(OnDocumentTitleTemplateChanged),
                    new CoerceValueCallback(CoerceDocumentTitleTemplateValue)));

        /// <summary>
        /// Gets or sets the DocumentTitleTemplate property.  This dependency property 
        /// indicates the datatemplate to use when creating the title for a document.
        /// </summary>
        public DataTemplate DocumentTitleTemplate
        {
            get { return (DataTemplate)GetValue(DocumentTitleTemplateProperty); }
            set { SetValue(DocumentTitleTemplateProperty, value); }
        }

        /// <summary>
        /// Handles changes to the DocumentTitleTemplate property.
        /// </summary>
        private static void OnDocumentTitleTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnDocumentTitleTemplateChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the DocumentTitleTemplate property.
        /// </summary>
        protected virtual void OnDocumentTitleTemplateChanged(DependencyPropertyChangedEventArgs e)
        {
        }

        /// <summary>
        /// Coerces the DocumentTitleTemplate value.
        /// </summary>
        private static object CoerceDocumentTitleTemplateValue(DependencyObject d, object value)
        {
            if (value != null &&
                d.GetValue(DocumentTitleTemplateSelectorProperty) != null)
                return null;

            return value;
        }

        #endregion

        #region DocumentTitleTemplateSelector

        /// <summary>
        /// DocumentTitleTemplateSelector Dependency Property
        /// </summary>
        public static readonly DependencyProperty DocumentTitleTemplateSelectorProperty =
            DependencyProperty.Register("DocumentTitleTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager),
                new FrameworkPropertyMetadata((DataTemplateSelector)null,
                    new PropertyChangedCallback(OnDocumentTitleTemplateSelectorChanged),
                    new CoerceValueCallback(CoerceDocumentTitleTemplateSelectorValue)));

        /// <summary>
        /// Gets or sets the DocumentTitleTemplateSelector property.  This dependency property 
        /// indicates the data template selector to use when creating the data template for the title.
        /// </summary>
        public DataTemplateSelector DocumentTitleTemplateSelector
        {
            get { return (DataTemplateSelector)GetValue(DocumentTitleTemplateSelectorProperty); }
            set { SetValue(DocumentTitleTemplateSelectorProperty, value); }
        }

        /// <summary>
        /// Handles changes to the DocumentTitleTemplateSelector property.
        /// </summary>
        private static void OnDocumentTitleTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnDocumentTitleTemplateSelectorChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the DocumentTitleTemplateSelector property.
        /// </summary>
        protected virtual void OnDocumentTitleTemplateSelectorChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue != null)
                DocumentTitleTemplate = null;                
        }

        /// <summary>
        /// Coerces the DocumentTitleTemplateSelector value.
        /// </summary>
        private static object CoerceDocumentTitleTemplateSelectorValue(DependencyObject d, object value)
        {
            return value;
        }

        #endregion

        #region AnchorableTitleTemplate

        /// <summary>
        /// AnchorableTitleTemplate Dependency Property
        /// </summary>
        public static readonly DependencyProperty AnchorableTitleTemplateProperty =
            DependencyProperty.Register("AnchorableTitleTemplate", typeof(DataTemplate), typeof(DockingManager),
                new FrameworkPropertyMetadata((DataTemplate)null,
                    new PropertyChangedCallback(OnAnchorableTitleTemplateChanged),
                    new CoerceValueCallback(CoerceAnchorableTitleTemplateValue)));

        /// <summary>
        /// Gets or sets the AnchorableTitleTemplate property.  This dependency property 
        /// indicates the data template to use for anchorables title.
        /// </summary>
        public DataTemplate AnchorableTitleTemplate
        {
            get { return (DataTemplate)GetValue(AnchorableTitleTemplateProperty); }
            set { SetValue(AnchorableTitleTemplateProperty, value); }
        }

        /// <summary>
        /// Handles changes to the AnchorableTitleTemplate property.
        /// </summary>
        private static void OnAnchorableTitleTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnAnchorableTitleTemplateChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the AnchorableTitleTemplate property.
        /// </summary>
        protected virtual void OnAnchorableTitleTemplateChanged(DependencyPropertyChangedEventArgs e)
        {
        }

        /// <summary>
        /// Coerces the AnchorableTitleTemplate value.
        /// </summary>
        private static object CoerceAnchorableTitleTemplateValue(DependencyObject d, object value)
        {
            if (value != null &&
                d.GetValue(AnchorableTitleTemplateSelectorProperty) != null)
                return null;
            return value;
        }

        #endregion

        #region AnchorableTitleTemplateSelector

        /// <summary>
        /// AnchorableTitleTemplateSelector Dependency Property
        /// </summary>
        public static readonly DependencyProperty AnchorableTitleTemplateSelectorProperty =
            DependencyProperty.Register("AnchorableTitleTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager),
                new FrameworkPropertyMetadata((DataTemplateSelector)null,
                    new PropertyChangedCallback(OnAnchorableTitleTemplateSelectorChanged)));

        /// <summary>
        /// Gets or sets the AnchorableTitleTemplateSelector property.  This dependency property 
        /// indicates selctor to use when selecting data template for the title of anchorables.
        /// </summary>
        public DataTemplateSelector AnchorableTitleTemplateSelector
        {
            get { return (DataTemplateSelector)GetValue(AnchorableTitleTemplateSelectorProperty); }
            set { SetValue(AnchorableTitleTemplateSelectorProperty, value); }
        }

        /// <summary>
        /// Handles changes to the AnchorableTitleTemplateSelector property.
        /// </summary>
        private static void OnAnchorableTitleTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnAnchorableTitleTemplateSelectorChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the AnchorableTitleTemplateSelector property.
        /// </summary>
        protected virtual void OnAnchorableTitleTemplateSelectorChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue != null &&
                AnchorableTitleTemplate != null)
                AnchorableTitleTemplate = null;
        }

        #endregion

        #region AnchorableHeaderTemplate

        /// <summary>
        /// AnchorableHeaderTemplate Dependency Property
        /// </summary>
        public static readonly DependencyProperty AnchorableHeaderTemplateProperty =
            DependencyProperty.Register("AnchorableHeaderTemplate", typeof(DataTemplate), typeof(DockingManager),
                new FrameworkPropertyMetadata((DataTemplate)null,
                    new PropertyChangedCallback(OnAnchorableHeaderTemplateChanged),
                    new CoerceValueCallback(CoerceAnchorableHeaderTemplateValue)));

        /// <summary>
        /// Gets or sets the AnchorableHeaderTemplate property.  This dependency property 
        /// indicates the data template to use for anchorable templates.
        /// </summary>
        public DataTemplate AnchorableHeaderTemplate
        {
            get { return (DataTemplate)GetValue(AnchorableHeaderTemplateProperty); }
            set { SetValue(AnchorableHeaderTemplateProperty, value); }
        }

        /// <summary>
        /// Handles changes to the AnchorableHeaderTemplate property.
        /// </summary>
        private static void OnAnchorableHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnAnchorableHeaderTemplateChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the AnchorableHeaderTemplate property.
        /// </summary>
        protected virtual void OnAnchorableHeaderTemplateChanged(DependencyPropertyChangedEventArgs e)
        {
        }

        /// <summary>
        /// Coerces the AnchorableHeaderTemplate value.
        /// </summary>
        private static object CoerceAnchorableHeaderTemplateValue(DependencyObject d, object value)
        {
            if (value != null &&
                d.GetValue(AnchorableHeaderTemplateSelectorProperty) != null)
                return null;

            return value;
        }

        #endregion

        #region AnchorableHeaderTemplateSelector

        /// <summary>
        /// AnchorableHeaderTemplateSelector Dependency Property
        /// </summary>
        public static readonly DependencyProperty AnchorableHeaderTemplateSelectorProperty =
            DependencyProperty.Register("AnchorableHeaderTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager),
                new FrameworkPropertyMetadata((DataTemplateSelector)null,
                    new PropertyChangedCallback(OnAnchorableHeaderTemplateSelectorChanged)));

        /// <summary>
        /// Gets or sets the AnchorableHeaderTemplateSelector property.  This dependency property 
        /// indicates the selector to use when selecting the data template for anchorable headers.
        /// </summary>
        public DataTemplateSelector AnchorableHeaderTemplateSelector
        {
            get { return (DataTemplateSelector)GetValue(AnchorableHeaderTemplateSelectorProperty); }
            set { SetValue(AnchorableHeaderTemplateSelectorProperty, value); }
        }

        /// <summary>
        /// Handles changes to the AnchorableHeaderTemplateSelector property.
        /// </summary>
        private static void OnAnchorableHeaderTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnAnchorableHeaderTemplateSelectorChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the AnchorableHeaderTemplateSelector property.
        /// </summary>
        protected virtual void OnAnchorableHeaderTemplateSelectorChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue != null)
                AnchorableHeaderTemplate = null;
        }

        #endregion

        #region LayoutRootPanel

        /// <summary>
        /// LayoutRootPanel Dependency Property
        /// </summary>
        public static readonly DependencyProperty LayoutRootPanelProperty =
            DependencyProperty.Register("LayoutRootPanel", typeof(LayoutPanelControl), typeof(DockingManager),
                new FrameworkPropertyMetadata((LayoutPanelControl)null,
                    new PropertyChangedCallback(OnLayoutRootPanelChanged)));

        /// <summary>
        /// Gets or sets the LayoutRootPanel property.  This dependency property 
        /// indicates the layout panel control which is attached to the Layout.Root property.
        /// </summary>
        public LayoutPanelControl LayoutRootPanel
        {
            get { return (LayoutPanelControl)GetValue(LayoutRootPanelProperty); }
            set { SetValue(LayoutRootPanelProperty, value); }
        }

        /// <summary>
        /// Handles changes to the LayoutRootPanel property.
        /// </summary>
        private static void OnLayoutRootPanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnLayoutRootPanelChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the LayoutRootPanel property.
        /// </summary>
        protected virtual void OnLayoutRootPanelChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.OldValue != null)
                InternalRemoveLogicalChild(e.OldValue);
            if (e.NewValue != null)
                InternalAddLogicalChild(e.NewValue);
        }

        #endregion

        #region RightSidePanel

        /// <summary>
        /// RightSidePanel Dependency Property
        /// </summary>
        public static readonly DependencyProperty RightSidePanelProperty =
            DependencyProperty.Register("RightSidePanel", typeof(LayoutAnchorSideControl), typeof(DockingManager),
                new FrameworkPropertyMetadata((LayoutAnchorSideControl)null,
                    new PropertyChangedCallback(OnRightSidePanelChanged)));

        /// <summary>
        /// Gets or sets the RightSidePanel property.  This dependency property 
        /// indicates right side anchor panel.
        /// </summary>
        public LayoutAnchorSideControl RightSidePanel
        {
            get { return (LayoutAnchorSideControl)GetValue(RightSidePanelProperty); }
            set { SetValue(RightSidePanelProperty, value); }
        }

        /// <summary>
        /// Handles changes to the RightSidePanel property.
        /// </summary>
        private static void OnRightSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnRightSidePanelChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the RightSidePanel property.
        /// </summary>
        protected virtual void OnRightSidePanelChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.OldValue != null)
                InternalRemoveLogicalChild(e.OldValue);
            if (e.NewValue != null)
                InternalAddLogicalChild(e.NewValue);
        }

        #endregion

        #region LeftSidePanel

        /// <summary>
        /// LeftSidePanel Dependency Property
        /// </summary>
        public static readonly DependencyProperty LeftSidePanelProperty =
            DependencyProperty.Register("LeftSidePanel", typeof(LayoutAnchorSideControl), typeof(DockingManager),
                new FrameworkPropertyMetadata((LayoutAnchorSideControl)null,
                    new PropertyChangedCallback(OnLeftSidePanelChanged)));

        /// <summary>
        /// Gets or sets the LeftSidePanel property.  This dependency property 
        /// indicates the left side panel control.
        /// </summary>
        public LayoutAnchorSideControl LeftSidePanel
        {
            get { return (LayoutAnchorSideControl)GetValue(LeftSidePanelProperty); }
            set { SetValue(LeftSidePanelProperty, value); }
        }

        /// <summary>
        /// Handles changes to the LeftSidePanel property.
        /// </summary>
        private static void OnLeftSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnLeftSidePanelChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the LeftSidePanel property.
        /// </summary>
        protected virtual void OnLeftSidePanelChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.OldValue != null)
                InternalRemoveLogicalChild(e.OldValue);
            if (e.NewValue != null)
                InternalAddLogicalChild(e.NewValue);
        }

        #endregion

        #region TopSidePanel

        /// <summary>
        /// TopSidePanel Dependency Property
        /// </summary>
        public static readonly DependencyProperty TopSidePanelProperty =
            DependencyProperty.Register("TopSidePanel", typeof(LayoutAnchorSideControl), typeof(DockingManager),
                new FrameworkPropertyMetadata((LayoutAnchorSideControl)null,
                    new PropertyChangedCallback(OnTopSidePanelChanged)));

        /// <summary>
        /// Gets or sets the TopSidePanel property.  This dependency property 
        /// indicates top side control panel.
        /// </summary>
        public LayoutAnchorSideControl TopSidePanel
        {
            get { return (LayoutAnchorSideControl)GetValue(TopSidePanelProperty); }
            set { SetValue(TopSidePanelProperty, value); }
        }

        /// <summary>
        /// Handles changes to the TopSidePanel property.
        /// </summary>
        private static void OnTopSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnTopSidePanelChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the TopSidePanel property.
        /// </summary>
        protected virtual void OnTopSidePanelChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.OldValue != null)
                InternalRemoveLogicalChild(e.OldValue);
            if (e.NewValue != null)
                InternalAddLogicalChild(e.NewValue);
        }

        #endregion

        #region BottomSidePanel

        /// <summary>
        /// BottomSidePanel Dependency Property
        /// </summary>
        public static readonly DependencyProperty BottomSidePanelProperty =
            DependencyProperty.Register("BottomSidePanel", typeof(LayoutAnchorSideControl), typeof(DockingManager),
                new FrameworkPropertyMetadata((LayoutAnchorSideControl)null,
                    new PropertyChangedCallback(OnBottomSidePanelChanged)));

        /// <summary>
        /// Gets or sets the BottomSidePanel property.  This dependency property 
        /// indicates bottom side panel control.
        /// </summary>
        public LayoutAnchorSideControl BottomSidePanel
        {
            get { return (LayoutAnchorSideControl)GetValue(BottomSidePanelProperty); }
            set { SetValue(BottomSidePanelProperty, value); }
        }

        /// <summary>
        /// Handles changes to the BottomSidePanel property.
        /// </summary>
        private static void OnBottomSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnBottomSidePanelChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the BottomSidePanel property.
        /// </summary>
        protected virtual void OnBottomSidePanelChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.OldValue != null)
                InternalRemoveLogicalChild(e.OldValue);
            if (e.NewValue != null)
                InternalAddLogicalChild(e.NewValue);
        }

        #endregion

        #region LogicalChildren

        List<WeakReference> _logicalChildren = new List<WeakReference>();

        protected override System.Collections.IEnumerator LogicalChildren
        {
            get
            {
                return _logicalChildren.Select(ch => ch.GetValueOrDefault<object>()).GetEnumerator();
            }
        }

    public System.Collections.IEnumerator LogicalChildrenPublic
    {
      get
      {
        return this.LogicalChildren;
      }
    }


        internal void InternalAddLogicalChild(object element)
        {
#if DEBUG
            if (_logicalChildren.Select(ch => ch.GetValueOrDefault<object>()).Contains(element))
                new InvalidOperationException();
#endif
            if (_logicalChildren.Select(ch => ch.GetValueOrDefault<object>()).Contains(element))
                return;

            _logicalChildren.Add(new WeakReference(element));
            AddLogicalChild(element);
        }

        internal void InternalRemoveLogicalChild(object element)
        {
            var wrToRemove = _logicalChildren.FirstOrDefault(ch => ch.GetValueOrDefault<object>() == element);
            if (wrToRemove != null)
                _logicalChildren.Remove(wrToRemove);
            RemoveLogicalChild(element);
        }

        void ClearLogicalChildrenList()
        {
            foreach (var child in _logicalChildren.Select(ch => ch.GetValueOrDefault<object>()).ToArray())
                RemoveLogicalChild(child);
            _logicalChildren.Clear();
        }

        #endregion  

        #region AutoHide window
        internal void ShowAutoHideWindow(LayoutAnchorControl anchor)
        {
            _autoHideWindowManager.ShowAutoHideWindow(anchor);
            //if (_autohideArea == null)
            //    return;

            //if (AutoHideWindow != null && AutoHideWindow.Model == anchor.Model)
            //    return;

          //Trace.WriteLine("ShowAutoHideWindow()");

            //_currentAutohiddenAnchor = new WeakReference(anchor);

            //HideAutoHideWindow(anchor);

            //SetAutoHideWindow(new LayoutAutoHideWindowControl(anchor));
            //AutoHideWindow.Show();
        }

        internal void HideAutoHideWindow(LayoutAnchorControl anchor)
        {
            _autoHideWindowManager.HideAutoWindow(anchor);
        }


        void SetupAutoHideWindow()
        {
            _autohideArea = GetTemplateChild("PART_AutoHideArea") as FrameworkElement;

            if (_autoHideWindowManager != null)
                _autoHideWindowManager.HideAutoWindow();
            else
                _autoHideWindowManager = new AutoHideWindowManager(this);

            if (AutoHideWindow != null)
                AutoHideWindow.Dispose();

            SetAutoHideWindow(new LayoutAutoHideWindowControl());
        }

        AutoHideWindowManager _autoHideWindowManager;

        FrameworkElement _autohideArea;
        internal FrameworkElement GetAutoHideAreaElement()
        {
            return _autohideArea;
        }

        #region AutoHideWindow

        /// <summary>
        /// AutoHideWindow Read-Only Dependency Property
        /// </summary>
        private static readonly DependencyPropertyKey AutoHideWindowPropertyKey
            = DependencyProperty.RegisterReadOnly("AutoHideWindow", typeof(LayoutAutoHideWindowControl), typeof(DockingManager),
                new FrameworkPropertyMetadata((LayoutAutoHideWindowControl)null,
                    new PropertyChangedCallback(OnAutoHideWindowChanged)));

        public static readonly DependencyProperty AutoHideWindowProperty
            = AutoHideWindowPropertyKey.DependencyProperty;

        /// <summary>
        /// Gets the AutoHideWindow property.  This dependency property 
        /// indicates the currently shown autohide window.
        /// </summary>
        public LayoutAutoHideWindowControl AutoHideWindow
        {
            get { return (LayoutAutoHideWindowControl)GetValue(AutoHideWindowProperty); }
        }

        /// <summary>
        /// Provides a secure method for setting the AutoHideWindow property.  
        /// This dependency property indicates the currently shown autohide window.
        /// </summary>
        /// <param name="value">The new value for the property.</param>
        protected void SetAutoHideWindow(LayoutAutoHideWindowControl value)
        {
            SetValue(AutoHideWindowPropertyKey, value);
        }

        /// <summary>
        /// Handles changes to the AutoHideWindow property.
        /// </summary>
        private static void OnAutoHideWindowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnAutoHideWindowChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the AutoHideWindow property.
        /// </summary>
        protected virtual void OnAutoHideWindowChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.OldValue != null)
                InternalRemoveLogicalChild(e.OldValue);
            if (e.NewValue != null)
                InternalAddLogicalChild(e.NewValue);

        }

        #endregion



        #endregion
        // #region AutoHide window
        //WeakReference _currentAutohiddenAnchor = null;
        //internal void ShowAutoHideWindow(LayoutAnchorControl anchor)
        //{
        //    if (_autohideArea == null)
        //        return;

        //    if (AutoHideWindow != null && AutoHideWindow.Model == anchor.Model)
        //        return;

        //    Trace.WriteLine("ShowAutoHideWindow()");

        //    _currentAutohiddenAnchor = new WeakReference(anchor);

        //    HideAutoHideWindow(anchor);

        //    SetAutoHideWindow(new LayoutAutoHideWindowControl(anchor));
        //}

        //internal void HideAutoHideWindow(LayoutAnchorControl anchor)
        //{
        //    if (AutoHideWindow != null)
        //    {
        //        if (anchor == _currentAutohiddenAnchor.GetValueOrDefault<LayoutAnchorControl>())
        //        {
        //            Trace.WriteLine("AutoHideWindow()");
        //            AutoHideWindow.Dispose();
        //            SetAutoHideWindow(null);
        //        }
        //    }
        //}

        //FrameworkElement _autohideArea;
        //internal FrameworkElement GetAutoHideAreaElement()
        //{
        //    return _autohideArea;
        //}

        //void SetupAutoHideArea()
        //{
        //    _autohideArea = GetTemplateChild("PART_AutoHideArea") as FrameworkElement;
        //}

        // #region AutoHideWindow

        ///// <summary>
        ///// AutoHideWindow Read-Only Dependency Property
        ///// </summary>
        //private static readonly DependencyPropertyKey AutoHideWindowPropertyKey
        //    = DependencyProperty.RegisterReadOnly("AutoHideWindow", typeof(LayoutAutoHideWindowControl), typeof(DockingManager),
        //        new FrameworkPropertyMetadata((LayoutAutoHideWindowControl)null,
        //            new PropertyChangedCallback(OnAutoHideWindowChanged)));

        //public static readonly DependencyProperty AutoHideWindowProperty
        //    = AutoHideWindowPropertyKey.DependencyProperty;

        ///// <summary>
        ///// Gets the AutoHideWindow property.  This dependency property 
        ///// indicates the currently shown autohide window.
        ///// </summary>
        //public LayoutAutoHideWindowControl AutoHideWindow
        //{
        //    get { return (LayoutAutoHideWindowControl)GetValue(AutoHideWindowProperty); }
        //}

        ///// <summary>
        ///// Provides a secure method for setting the AutoHideWindow property.  
        ///// This dependency property indicates the currently shown autohide window.
        ///// </summary>
        ///// <param name="value">The new value for the property.</param>
        //protected void SetAutoHideWindow(LayoutAutoHideWindowControl value)
        //{
        //    SetValue(AutoHideWindowPropertyKey, value);
        //}

        ///// <summary>
        ///// Handles changes to the AutoHideWindow property.
        ///// </summary>
        //private static void OnAutoHideWindowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        //{
        //    ((DockingManager)d).OnAutoHideWindowChanged(e);
        //}

        ///// <summary>
        ///// Provides derived classes an opportunity to handle changes to the AutoHideWindow property.
        ///// </summary>
        //protected virtual void OnAutoHideWindowChanged(DependencyPropertyChangedEventArgs e)
        //{
        //    if (e.OldValue != null)
        //        ((ILogicalChildrenContainer)this).InternalRemoveLogicalChild(e.OldValue);
        //    if (e.NewValue != null)
        //        ((ILogicalChildrenContainer)this).InternalAddLogicalChild(e.NewValue);
        //}

        // #endregion



        // #endregion

        #region Floating Windows
        List<LayoutFloatingWindowControl> _fwList = new List<LayoutFloatingWindowControl>();

        internal void StartDraggingFloatingWindowForContent(LayoutContent contentModel, bool startDrag = true)
        {
            if (!contentModel.CanFloat)
                return;
            var contentModelAsAnchorable = contentModel as LayoutAnchorable;
            if (contentModelAsAnchorable != null &&
                contentModelAsAnchorable.IsAutoHidden)
                contentModelAsAnchorable.ToggleAutoHide();

            var parentPane = contentModel.Parent as ILayoutPane;
            var parentPaneAsPositionableElement = contentModel.Parent as ILayoutPositionableElement;
            var parentPaneAsWithActualSize = contentModel.Parent as ILayoutPositionableElementWithActualSize;
            var contentModelParentChildrenIndex = parentPane.Children.ToList().IndexOf(contentModel);

            if (contentModel.FindParent<LayoutFloatingWindow>() == null)
            {
                ((ILayoutPreviousContainer)contentModel).PreviousContainer = parentPane;
                contentModel.PreviousContainerIndex = contentModelParentChildrenIndex;
            }

            parentPane.RemoveChildAt(contentModelParentChildrenIndex);

            double fwWidth = contentModel.FloatingWidth; 
            double fwHeight = contentModel.FloatingHeight; 

            if (fwWidth == 0.0)
                fwWidth = parentPaneAsPositionableElement.FloatingWidth;
            if (fwHeight == 0.0)
                fwHeight = parentPaneAsPositionableElement.FloatingHeight;

            if (fwWidth == 0.0)
                fwWidth = parentPaneAsWithActualSize.ActualWidth;
            if (fwHeight == 0.0)
                fwHeight = parentPaneAsWithActualSize.ActualHeight;

            LayoutFloatingWindow fw;
            LayoutFloatingWindowControl fwc;
            if (contentModel is LayoutAnchorable)
            {
                var anchorableContent = contentModel as LayoutAnchorable;
                fw = new LayoutAnchorableFloatingWindow()
                {
                    RootPanel = new LayoutAnchorablePaneGroup(
                        new LayoutAnchorablePane(anchorableContent)
                        {
                            DockWidth = parentPaneAsPositionableElement.DockWidth,
                            DockHeight = parentPaneAsPositionableElement.DockHeight,
                            DockMinHeight = parentPaneAsPositionableElement.DockMinHeight,
                            DockMinWidth = parentPaneAsPositionableElement.DockMinWidth,
                            FloatingLeft = parentPaneAsPositionableElement.FloatingLeft,
                            FloatingTop = parentPaneAsPositionableElement.FloatingTop,
                            FloatingWidth = parentPaneAsPositionableElement.FloatingWidth,
                            FloatingHeight = parentPaneAsPositionableElement.FloatingHeight,
                        })
                };

                Layout.FloatingWindows.Add(fw);

                fwc = new LayoutAnchorableFloatingWindowControl(
                    fw as LayoutAnchorableFloatingWindow)
                    {
                        Width = fwWidth,
                        Height = fwHeight,
                        Left = contentModel.FloatingLeft,
                        Top = contentModel.FloatingTop
                    };
            }
            else
            {
                var anchorableDocument = contentModel as LayoutDocument;
                fw = new LayoutDocumentFloatingWindow()
                {
                    RootDocument = anchorableDocument
                };

                Layout.FloatingWindows.Add(fw);

                fwc = new LayoutDocumentFloatingWindowControl(
                    fw as LayoutDocumentFloatingWindow)
                {
                    Width = fwWidth,
                    Height = fwHeight,
                    Left = contentModel.FloatingLeft,
                    Top = contentModel.FloatingTop
                };
            }


            //fwc.Owner = Window.GetWindow(this);
            //fwc.SetParentToMainWindowOf(this);


            _fwList.Add(fwc);

            Layout.CollectGarbage();

            UpdateLayout();

            Dispatcher.BeginInvoke(new Action(() =>
            {
                if (startDrag)
                    fwc.AttachDrag();
                fwc.Show();
            }), DispatcherPriority.Send);
        }

        internal void StartDraggingFloatingWindowForPane(LayoutAnchorablePane paneModel)
        {
            if (paneModel.Children.Any(c => !c.CanFloat))
                return;
            var paneAsPositionableElement = paneModel as ILayoutPositionableElement;
            var paneAsWithActualSize = paneModel as ILayoutPositionableElementWithActualSize;

            double fwWidth = paneAsPositionableElement.FloatingWidth;
            double fwHeight = paneAsPositionableElement.FloatingHeight;
            double fwLeft = paneAsPositionableElement.FloatingLeft;
            double fwTop = paneAsPositionableElement.FloatingTop;



            if (fwWidth == 0.0)
                fwWidth = paneAsWithActualSize.ActualWidth;
            if (fwHeight == 0.0)
                fwHeight = paneAsWithActualSize.ActualHeight;

            var destPane = new LayoutAnchorablePane()
            {
                DockWidth = paneAsPositionableElement.DockWidth,
                DockHeight = paneAsPositionableElement.DockHeight,
                DockMinHeight = paneAsPositionableElement.DockMinHeight,
                DockMinWidth = paneAsPositionableElement.DockMinWidth,
                FloatingLeft = paneAsPositionableElement.FloatingLeft,
                FloatingTop = paneAsPositionableElement.FloatingTop,
                FloatingWidth = paneAsPositionableElement.FloatingWidth,
                FloatingHeight = paneAsPositionableElement.FloatingHeight,
            };

            bool savePreviousContainer = paneModel.FindParent<LayoutFloatingWindow>() == null;
            int currentSelectedContentIndex = paneModel.SelectedContentIndex;
            while (paneModel.Children.Count > 0)
            {
                var contentModel = paneModel.Children[paneModel.Children.Count - 1] as LayoutAnchorable;

                if (savePreviousContainer)
                {
                    var contentModelAsPreviousContainer = contentModel as ILayoutPreviousContainer;
                    contentModelAsPreviousContainer.PreviousContainer = paneModel;
                    contentModel.PreviousContainerIndex = paneModel.Children.Count - 1;
                }

                paneModel.RemoveChildAt(paneModel.Children.Count - 1);
                destPane.Children.Insert(0, contentModel);
            }

            if (destPane.Children.Count > 0)
            {
                destPane.SelectedContentIndex = currentSelectedContentIndex;
            }


            LayoutFloatingWindow fw;
            LayoutFloatingWindowControl fwc;
            fw = new LayoutAnchorableFloatingWindow()
            {
                RootPanel = new LayoutAnchorablePaneGroup(
                    destPane) 
                    {
                        DockHeight = destPane.DockHeight,
                        DockWidth = destPane.DockWidth,
                        DockMinHeight = destPane.DockMinHeight,
                        DockMinWidth = destPane.DockMinWidth,
                    }
            };

            Layout.FloatingWindows.Add(fw);

            fwc = new LayoutAnchorableFloatingWindowControl(
                fw as LayoutAnchorableFloatingWindow)
            {
                Width = fwWidth,
                Height = fwHeight
            };



            //fwc.Owner = Window.GetWindow(this);
            //fwc.SetParentToMainWindowOf(this);


            _fwList.Add(fwc);

            Layout.CollectGarbage();

            InvalidateArrange();

            fwc.AttachDrag();
            fwc.Show(); 

        }

        internal IEnumerable<LayoutFloatingWindowControl> GetFloatingWindowsByZOrder()
        {
            var parentWindow = Window.GetWindow(this);

            if (parentWindow == null)
                yield break;

            IntPtr windowParentHanlde = new WindowInteropHelper(parentWindow).Handle;

            IntPtr currentHandle = Win32Helper.GetWindow(windowParentHanlde, (uint)Win32Helper.GetWindow_Cmd.GW_HWNDFIRST);
            while (currentHandle != IntPtr.Zero)
            {
                LayoutFloatingWindowControl ctrl = _fwList.FirstOrDefault(fw => new WindowInteropHelper(fw).Handle == currentHandle);
                if (ctrl != null && ctrl.Model.Root.Manager == this)
                    yield return ctrl;

                currentHandle = Win32Helper.GetWindow(currentHandle, (uint)Win32Helper.GetWindow_Cmd.GW_HWNDNEXT);
            }
        }

        internal void RemoveFloatingWindow(LayoutFloatingWindowControl floatingWindow)
        {
            _fwList.Remove(floatingWindow);
        }

        public IEnumerable<LayoutFloatingWindowControl> FloatingWindows
        {
            get { return _fwList; }
        }
        #endregion

        #region OverlayWindow

        bool IOverlayWindowHost.HitTest(Point dragPoint)
        {
            Rect detectionRect = new Rect(this.PointToScreenDPIWithoutFlowDirection(new Point()), this.TransformActualSizeToAncestor());
            return detectionRect.Contains(dragPoint);
        }

        DockingManager IOverlayWindowHost.Manager
        {
            get { return this; }
        }

        OverlayWindow _overlayWindow = null;
        void CreateOverlayWindow()
        {
            if (_overlayWindow == null)
            {
                _overlayWindow = new OverlayWindow(this);
            }
            Rect rectWindow = new Rect(this.PointToScreenDPIWithoutFlowDirection(new Point()), this.TransformActualSizeToAncestor());
            _overlayWindow.Left = rectWindow.Left;
            _overlayWindow.Top = rectWindow.Top;
            _overlayWindow.Width = rectWindow.Width;
            _overlayWindow.Height = rectWindow.Height;
        }

        void DestroyOverlayWindow()
        {
            if (_overlayWindow != null)
            {
                _overlayWindow.Close();
                _overlayWindow = null;
            }
        }

        IOverlayWindow IOverlayWindowHost.ShowOverlayWindow(LayoutFloatingWindowControl draggingWindow)
        {
            CreateOverlayWindow();
            _overlayWindow.Owner = draggingWindow;
            _overlayWindow.EnableDropTargets();
            _overlayWindow.Show();
            return _overlayWindow;
        }

        void IOverlayWindowHost.HideOverlayWindow()
        {
            _areas = null;
            _overlayWindow.Owner = null;
            _overlayWindow.HideDropTargets();
        }

        List<IDropArea> _areas = null;

        IEnumerable<IDropArea> IOverlayWindowHost.GetDropAreas(LayoutFloatingWindowControl draggingWindow)
        {
            if (_areas != null)
                return _areas;

            bool isDraggingDocuments = draggingWindow.Model is LayoutDocumentFloatingWindow;

            _areas = new List<IDropArea>();

            if (!isDraggingDocuments)
            {
                _areas.Add(new DropArea<DockingManager>(
                    this,
                    DropAreaType.DockingManager));

                foreach (var areaHost in this.FindVisualChildren<LayoutAnchorablePaneControl>())
                {
                    if (areaHost.Model.Descendents().Any())
                    {
                        _areas.Add(new DropArea<LayoutAnchorablePaneControl>(
                            areaHost,
                            DropAreaType.AnchorablePane));
                    }
                }
            }

            foreach (var areaHost in this.FindVisualChildren<LayoutDocumentPaneControl>())
            {
                _areas.Add(new DropArea<LayoutDocumentPaneControl>(
                    areaHost,
                    DropAreaType.DocumentPane));
            }

            foreach (var areaHost in this.FindVisualChildren<LayoutDocumentPaneGroupControl>())
            {
                var documentGroupModel = areaHost.Model as LayoutDocumentPaneGroup;
                if (documentGroupModel.Children.Where(c => c.IsVisible).Count() == 0)
                {
                    _areas.Add(new DropArea<LayoutDocumentPaneGroupControl>(
                        areaHost,
                        DropAreaType.DocumentPaneGroup));
                }
            }

            return _areas;
        }

        protected override Size ArrangeOverride(Size arrangeBounds)
        {
            _areas = null;
            return base.ArrangeOverride(arrangeBounds);
        }

        #endregion

        #region LayoutDocument & LayoutAnchorable Templates

        #region LayoutItemTemplate

        /// <summary>
        /// LayoutItemTemplate Dependency Property
        /// </summary>
        public static readonly DependencyProperty LayoutItemTemplateProperty =
            DependencyProperty.Register("LayoutItemTemplate", typeof(DataTemplate), typeof(DockingManager),
                new FrameworkPropertyMetadata((DataTemplate)null,
                    new PropertyChangedCallback(OnLayoutItemTemplateChanged)));

        /// <summary>
        /// Gets or sets the AnchorableTemplate property.  This dependency property 
        /// indicates the template to use to render anchorable and document contents.
        /// </summary>
        public DataTemplate LayoutItemTemplate
        {
            get { return (DataTemplate)GetValue(LayoutItemTemplateProperty); }
            set { SetValue(LayoutItemTemplateProperty, value); }
        }

        /// <summary>
        /// Handles changes to the AnchorableTemplate property.
        /// </summary>
        private static void OnLayoutItemTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnLayoutItemTemplateChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the AnchorableTemplate property.
        /// </summary>
        protected virtual void OnLayoutItemTemplateChanged(DependencyPropertyChangedEventArgs e)
        {
        }

        #endregion

        #region LayoutItemTemplateSelector

        /// <summary>
        /// LayoutItemTemplateSelector Dependency Property
        /// </summary>
        public static readonly DependencyProperty LayoutItemTemplateSelectorProperty =
            DependencyProperty.Register("LayoutItemTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager),
                new FrameworkPropertyMetadata((DataTemplateSelector)null,
                    new PropertyChangedCallback(OnLayoutItemTemplateSelectorChanged)));

        /// <summary>
        /// Gets or sets the LayoutItemTemplateSelector property.  This dependency property 
        /// indicates selector object to use for anchorable templates.
        /// </summary>
        public DataTemplateSelector LayoutItemTemplateSelector
        {
            get { return (DataTemplateSelector)GetValue(LayoutItemTemplateSelectorProperty); }
            set { SetValue(LayoutItemTemplateSelectorProperty, value); }
        }

        /// <summary>
        /// Handles changes to the LayoutItemTemplateSelector property.
        /// </summary>
        private static void OnLayoutItemTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnLayoutItemTemplateSelectorChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the LayoutItemTemplateSelector property.
        /// </summary>
        protected virtual void OnLayoutItemTemplateSelectorChanged(DependencyPropertyChangedEventArgs e)
        {
        }

        #endregion


        #endregion

        #region DocumentsSource

        /// <summary>
        /// DocumentsSource Dependency Property
        /// </summary>
        public static readonly DependencyProperty DocumentsSourceProperty =
            DependencyProperty.Register("DocumentsSource", typeof(IEnumerable), typeof(DockingManager),
                new FrameworkPropertyMetadata((IEnumerable)null,
                    new PropertyChangedCallback(OnDocumentsSourceChanged)));

        /// <summary>
        /// Gets or sets the DocumentsSource property.  This dependency property 
        /// indicates the source collection of documents.
        /// </summary>
        public IEnumerable DocumentsSource
        {
            get 
            { 
              return (IEnumerable)GetValue(DocumentsSourceProperty); 
            }
            set 
            { 
              SetValue(DocumentsSourceProperty, value); 
            }
        }

        /// <summary>
        /// Handles changes to the DocumentsSource property.
        /// </summary>
        private static void OnDocumentsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnDocumentsSourceChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the DocumentsSource property.
        /// </summary>
        protected virtual void OnDocumentsSourceChanged(DependencyPropertyChangedEventArgs e)
        {
            DetachDocumentsSource(Layout, e.OldValue as IEnumerable);
            AttachDocumentsSource(Layout, e.NewValue as IEnumerable);
        }


        void AttachDocumentsSource(LayoutRoot layout, IEnumerable documentsSource)
        {
            if (documentsSource == null)
                return;

            if (layout == null)
                return;

            //if (layout.Descendents().OfType<LayoutDocument>().Any())
            //    throw new InvalidOperationException("Unable to set the DocumentsSource property if LayoutDocument objects are already present in the model");
            var documentsImported = layout.Descendents().OfType<LayoutDocument>().Select(d => d.Content).ToArray();
            var documents = documentsSource as IEnumerable;
            var listOfDocumentsToImport = new List<object>(documents.OfType<object>());

            foreach (var document in listOfDocumentsToImport.ToArray())
            {
                if (documentsImported.Contains(document))
                    listOfDocumentsToImport.Remove(document);
            }


            LayoutDocumentPane documentPane = null;
            if (layout.LastFocusedDocument != null)
            {
                documentPane = layout.LastFocusedDocument.Parent as LayoutDocumentPane;
            }

            if (documentPane == null)
            {
                documentPane = layout.Descendents().OfType<LayoutDocumentPane>().FirstOrDefault();
            }

            //if (documentPane == null)
            //    throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents");

            _suspendLayoutItemCreation = true;
            foreach (var documentContentToImport in listOfDocumentsToImport)
            {

                //documentPane.Children.Add(new LayoutDocument() { Content = documentToImport });

                var documentToImport = new LayoutDocument()
                {
                    Content = documentContentToImport
                };

                bool added = false;
                if (LayoutUpdateStrategy != null)
                {
                    added = LayoutUpdateStrategy.BeforeInsertDocument(layout, documentToImport, documentPane);
                }

                if (!added)
                {
                    if (documentPane == null)
                        throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents");

                    documentPane.Children.Add(documentToImport);
                    added = true;
                }

                if (LayoutUpdateStrategy != null)
                    LayoutUpdateStrategy.AfterInsertDocument(layout, documentToImport);


                CreateDocumentLayoutItem(documentToImport);

            }
            _suspendLayoutItemCreation = false;


            var documentsSourceAsNotifier = documentsSource as INotifyCollectionChanged;
            if (documentsSourceAsNotifier != null)
                documentsSourceAsNotifier.CollectionChanged += new NotifyCollectionChangedEventHandler(documentsSourceElementsChanged);
        }

        internal bool SuspendDocumentsSourceBinding = false;

        void documentsSourceElementsChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (Layout == null)
                return;

            //When deserializing documents are created automatically by the deserializer
            if (SuspendDocumentsSourceBinding)
                return;

            //handle remove
            if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove ||
                e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace)
            {
                if (e.OldItems != null)
                {
                    var documentsToRemove = Layout.Descendents().OfType<LayoutDocument>().Where(d => e.OldItems.Contains(d.Content)).ToArray();
                    foreach (var documentToRemove in documentsToRemove)
                    {
                        (documentToRemove.Parent as ILayoutContainer).RemoveChild(
                            documentToRemove);
                        this.RemoveViewFromLogicalChild( documentToRemove );
                    }
                }
            }

            //handle add
            if (e.NewItems != null &&
                (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add ||
                e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace))
            {
                if (e.NewItems != null)
                {
                    LayoutDocumentPane documentPane = null;
                    if (Layout.LastFocusedDocument != null)
                    {
                        documentPane = Layout.LastFocusedDocument.Parent as LayoutDocumentPane;
                    }

                    if (documentPane == null)
                    {
                        documentPane = Layout.Descendents().OfType<LayoutDocumentPane>().FirstOrDefault();
                    }

                    //if (documentPane == null)
                    //    throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents");

                    _suspendLayoutItemCreation = true;

                    foreach (var documentContentToImport in e.NewItems)
                    {
                        var documentToImport = new LayoutDocument()
                        {
                            Content = documentContentToImport
                        };

                        bool added = false;
                        if (LayoutUpdateStrategy != null)
                        {
                            added = LayoutUpdateStrategy.BeforeInsertDocument(Layout, documentToImport, documentPane);
                        }

                        if (!added)
                        {
                            if (documentPane == null)
                                throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents");

                            documentPane.Children.Add(documentToImport);
                            added = true;
                        }

                        if (LayoutUpdateStrategy != null)
                        {
                            LayoutUpdateStrategy.AfterInsertDocument(Layout, documentToImport);
                        }


                        var root = documentToImport.Root;

                        if (root != null && root.Manager == this)
                        {
                            CreateDocumentLayoutItem(documentToImport);
                        }
                    }
                    _suspendLayoutItemCreation = false;
                }
            }

            if (e.Action == NotifyCollectionChangedAction.Reset)
            {
                //NOTE: I'm going to clear every document present in layout but
                //some documents may have been added directly to the layout, for now I clear them too
                var documentsToRemove = Layout.Descendents().OfType<LayoutDocument>().ToArray();
                foreach (var documentToRemove in documentsToRemove)
                {
                    (documentToRemove.Parent as ILayoutContainer).RemoveChild(
                        documentToRemove);
                    this.RemoveViewFromLogicalChild( documentToRemove );
                }
            }

            if (Layout != null)
            {
                Layout.CollectGarbage();
            }
        }

        void DetachDocumentsSource(LayoutRoot layout, IEnumerable documentsSource)
        {
            if (documentsSource == null)
                return;

            if (layout == null)
                return;

            var documentsToRemove = layout.Descendents().OfType<LayoutDocument>()
                .Where(d => documentsSource.Contains(d.Content)).ToArray();

            foreach (var documentToRemove in documentsToRemove)
            {
                (documentToRemove.Parent as ILayoutContainer).RemoveChild(
                    documentToRemove);
                this.RemoveViewFromLogicalChild( documentToRemove );
            }

            var documentsSourceAsNotifier = documentsSource as INotifyCollectionChanged;
            if (documentsSourceAsNotifier != null)
                documentsSourceAsNotifier.CollectionChanged -= new NotifyCollectionChangedEventHandler(documentsSourceElementsChanged);
        }


        #endregion

        #region DocumentCloseCommand

        internal void _ExecuteCloseCommand(LayoutDocument document)
        {
            if (DocumentClosing != null)
            {
                var evargs = new DocumentClosingEventArgs(document);
                DocumentClosing(this, evargs);
                if (evargs.Cancel)
                    return;
            }

            if( document.CloseDocument() )
            {
              this.RemoveViewFromLogicalChild( document );

              if( DocumentClosed != null )
              {
                var evargs = new DocumentClosedEventArgs( document );
                DocumentClosed( this, evargs );
              }
            }
        }

        /// <summary>
        /// Event fired when a document is about to be closed
        /// </summary>
        /// <remarks>Subscribers have the opportuniy to cancel the operation.</remarks>
        public event EventHandler<DocumentClosingEventArgs> DocumentClosing;

        /// <summary>
        /// Event fired after a document is closed
        /// </summary>
        public event EventHandler<DocumentClosedEventArgs> DocumentClosed;



        #endregion

        internal void _ExecuteCloseAllButThisCommand(LayoutContent contentSelected)
        {
            foreach (var contentToClose in Layout.Descendents().OfType<LayoutContent>().Where(d => d != contentSelected && (d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow)).ToArray())
            {
              this.Close( contentToClose );              
            }
        }

        internal void _ExecuteCloseAllCommand( LayoutContent contentSelected )
        {
          foreach( var contentToClose in Layout.Descendents().OfType<LayoutContent>().Where( d => ( d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow ) ).ToArray() )
          {
            this.Close( contentToClose );
          }
        }

        private void Close( LayoutContent contentToClose )
        {
          if( !contentToClose.CanClose )
            return;

          var layoutItem = GetLayoutItemFromModel( contentToClose );
          if( layoutItem.CloseCommand != null )
          {
            if( layoutItem.CloseCommand.CanExecute( null ) )
              layoutItem.CloseCommand.Execute( null );
          }
          else
          {
            if( contentToClose is LayoutDocument )
              _ExecuteCloseCommand( contentToClose as LayoutDocument );
            else if( contentToClose is LayoutAnchorable )
              _ExecuteCloseCommand( contentToClose as LayoutAnchorable );
          }
        }

        #region DocumentContextMenu

        /// <summary>
        /// DocumentContextMenu Dependency Property
        /// </summary>
        public static readonly DependencyProperty DocumentContextMenuProperty =
            DependencyProperty.Register("DocumentContextMenu", typeof(ContextMenu), typeof(DockingManager),
                new FrameworkPropertyMetadata((ContextMenu)null));

        /// <summary>
        /// Gets or sets the DocumentContextMenu property.  This dependency property 
        /// indicates context menu to show for documents.
        /// </summary>
        public ContextMenu DocumentContextMenu
        {
            get { return (ContextMenu)GetValue(DocumentContextMenuProperty); }
            set { SetValue(DocumentContextMenuProperty, value); }
        }

        #endregion

        #region AnchorablesSource

        /// <summary>
        /// AnchorablesSource Dependency Property
        /// </summary>
        public static readonly DependencyProperty AnchorablesSourceProperty =
            DependencyProperty.Register("AnchorablesSource", typeof(IEnumerable), typeof(DockingManager),
                new FrameworkPropertyMetadata((IEnumerable)null,
                    new PropertyChangedCallback(OnAnchorablesSourceChanged)));

        /// <summary>
        /// Gets or sets the AnchorablesSource property.  This dependency property 
        /// indicates source collection of anchorables.
        /// </summary>
        public IEnumerable AnchorablesSource
        {
            get 
            { 
              return (IEnumerable)GetValue(AnchorablesSourceProperty); 
            }
            set 
            { 
              SetValue(AnchorablesSourceProperty, value); 
            }
        }

        /// <summary>
        /// Handles changes to the AnchorablesSource property.
        /// </summary>
        private static void OnAnchorablesSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnAnchorablesSourceChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the AnchorablesSource property.
        /// </summary>
        protected virtual void OnAnchorablesSourceChanged(DependencyPropertyChangedEventArgs e)
        {
            DetachAnchorablesSource(Layout, e.OldValue as IEnumerable);
            AttachAnchorablesSource(Layout, e.NewValue as IEnumerable);
        }

        void AttachAnchorablesSource(LayoutRoot layout, IEnumerable anchorablesSource)
        {
            if (anchorablesSource == null)
                return;

            if (layout == null)
                return;

            //if (layout.Descendents().OfType<LayoutAnchorable>().Any())
            //    throw new InvalidOperationException("Unable to set the AnchorablesSource property if LayoutAnchorable objects are already present in the model");
            var anchorablesImported = layout.Descendents().OfType<LayoutAnchorable>().Select(d => d.Content).ToArray();
            var anchorables = anchorablesSource as IEnumerable;
            var listOfAnchorablesToImport = new List<object>(anchorables.OfType<object>());

            foreach (var document in listOfAnchorablesToImport.ToArray())
            {
                if (anchorablesImported.Contains(document))
                    listOfAnchorablesToImport.Remove(document);
            }

            LayoutAnchorablePane anchorablePane = null;
            if (layout.ActiveContent != null)
            {
                //look for active content parent pane
                anchorablePane = layout.ActiveContent.Parent as LayoutAnchorablePane;
            }

            if (anchorablePane == null)
            {
                //look for a pane on the right side
                anchorablePane = layout.Descendents().OfType<LayoutAnchorablePane>().Where(pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right).FirstOrDefault();
            }

            if (anchorablePane == null)
            {
                //look for an available pane
                anchorablePane = layout.Descendents().OfType<LayoutAnchorablePane>().FirstOrDefault();
            }

            _suspendLayoutItemCreation = true;
            foreach (var anchorableContentToImport in listOfAnchorablesToImport)
            {
                var anchorableToImport = new LayoutAnchorable()
                {
                    Content = anchorableContentToImport
                };

                bool added = false;
                if (LayoutUpdateStrategy != null)
                {
                    added = LayoutUpdateStrategy.BeforeInsertAnchorable(layout, anchorableToImport, anchorablePane);
                }

                if (!added)
                {
                    if (anchorablePane == null)
                    {
                        var mainLayoutPanel = new LayoutPanel() { Orientation = Orientation.Horizontal };
                        if (layout.RootPanel != null)
                        {
                            mainLayoutPanel.Children.Add(layout.RootPanel);
                        }

                        layout.RootPanel = mainLayoutPanel;
                        anchorablePane = new LayoutAnchorablePane() { DockWidth = new GridLength(200.0, GridUnitType.Pixel) };
                        mainLayoutPanel.Children.Add(anchorablePane);
                    }

                    anchorablePane.Children.Add(anchorableToImport);
                    added = true;
                }

                if (LayoutUpdateStrategy != null)
                    LayoutUpdateStrategy.AfterInsertAnchorable(layout, anchorableToImport);


                CreateAnchorableLayoutItem(anchorableToImport);

            }

            _suspendLayoutItemCreation = false;

            var anchorablesSourceAsNotifier = anchorablesSource as INotifyCollectionChanged;
            if (anchorablesSourceAsNotifier != null)
                anchorablesSourceAsNotifier.CollectionChanged += new NotifyCollectionChangedEventHandler(anchorablesSourceElementsChanged);
        }

        internal bool SuspendAnchorablesSourceBinding = false;

        void anchorablesSourceElementsChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (Layout == null)
                return;

            //When deserializing documents are created automatically by the deserializer
            if (SuspendAnchorablesSourceBinding)
                return;

            //handle remove
            if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove ||
                e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace)
            {
                if (e.OldItems != null)
                {
                    var anchorablesToRemove = Layout.Descendents().OfType<LayoutAnchorable>().Where(d => e.OldItems.Contains(d.Content)).ToArray();
                    foreach (var anchorableToRemove in anchorablesToRemove)
                    {
                        anchorableToRemove.Content = null;
                        (anchorableToRemove.Parent as ILayoutContainer).RemoveChild(
                            anchorableToRemove);
                        this.RemoveViewFromLogicalChild( anchorableToRemove );
                    }
                }
            }

            //handle add
            if (e.NewItems != null &&
                (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add ||
                e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace))
            {
                if (e.NewItems != null)
                {
                    LayoutAnchorablePane anchorablePane = null;

                    if (Layout.ActiveContent != null)
                    {
                        //look for active content parent pane
                        anchorablePane = Layout.ActiveContent.Parent as LayoutAnchorablePane;
                    }

                    if (anchorablePane == null)
                    {
                        //look for a pane on the right side
                        anchorablePane = Layout.Descendents().OfType<LayoutAnchorablePane>().Where(pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right).FirstOrDefault();
                    }

                    if (anchorablePane == null)
                    {
                        //look for an available pane
                        anchorablePane = Layout.Descendents().OfType<LayoutAnchorablePane>().FirstOrDefault();
                    }

                    _suspendLayoutItemCreation = true;
                    foreach (var anchorableContentToImport in e.NewItems)
                    {
                        var anchorableToImport = new LayoutAnchorable()
                        {
                            Content = anchorableContentToImport
                        };

                        bool added = false;
                        if (LayoutUpdateStrategy != null)
                        {
                            added = LayoutUpdateStrategy.BeforeInsertAnchorable(Layout, anchorableToImport, anchorablePane);
                        }

                        if (!added)
                        {
                            if (anchorablePane == null)
                            {
                                var mainLayoutPanel = new LayoutPanel() { Orientation = Orientation.Horizontal };
                                if (Layout.RootPanel != null)
                                {
                                    mainLayoutPanel.Children.Add(Layout.RootPanel);
                                }

                                Layout.RootPanel = mainLayoutPanel;
                                anchorablePane = new LayoutAnchorablePane() { DockWidth = new GridLength(200.0, GridUnitType.Pixel) };
                                mainLayoutPanel.Children.Add(anchorablePane);
                            }

                            anchorablePane.Children.Add(anchorableToImport);
                            added = true;
                        }

                        if (LayoutUpdateStrategy != null)
                        {
                            LayoutUpdateStrategy.AfterInsertAnchorable(Layout, anchorableToImport);
                        }

                        var root = anchorableToImport.Root;

                        if (root != null && root.Manager == this)
                        {
                            CreateAnchorableLayoutItem(anchorableToImport);
                        }

                    }
                    _suspendLayoutItemCreation = false;
                }
            }

            if (e.Action == NotifyCollectionChangedAction.Reset)
            {
                //NOTE: I'm going to clear every anchorable present in layout but
                //some anchorable may have been added directly to the layout, for now I clear them too
                var anchorablesToRemove = Layout.Descendents().OfType<LayoutAnchorable>().ToArray();
                foreach (var anchorableToRemove in anchorablesToRemove)
                {
                    (anchorableToRemove.Parent as ILayoutContainer).RemoveChild(
                        anchorableToRemove);
                    this.RemoveViewFromLogicalChild( anchorableToRemove );
                }
            }

            if (Layout != null)
                Layout.CollectGarbage();
        }

        void DetachAnchorablesSource(LayoutRoot layout, IEnumerable anchorablesSource)
        {
            if (anchorablesSource == null)
                return;

            if (layout == null)
                return;

            var anchorablesToRemove = layout.Descendents().OfType<LayoutAnchorable>()
                .Where(d => anchorablesSource.Contains(d.Content)).ToArray();

            foreach (var anchorableToRemove in anchorablesToRemove)
            {
                (anchorableToRemove.Parent as ILayoutContainer).RemoveChild(
                    anchorableToRemove);
                this.RemoveViewFromLogicalChild( anchorableToRemove );
            }

            var anchorablesSourceAsNotifier = anchorablesSource as INotifyCollectionChanged;
            if (anchorablesSourceAsNotifier != null)
                anchorablesSourceAsNotifier.CollectionChanged -= new NotifyCollectionChangedEventHandler(anchorablesSourceElementsChanged);
        }

        #endregion

        internal void _ExecuteCloseCommand(LayoutAnchorable anchorable)
        {
            var model = anchorable as LayoutAnchorable;
            if (model != null )
            {
              model.CloseAnchorable();
              this.RemoveViewFromLogicalChild( anchorable );
            }
        }

        internal void _ExecuteHideCommand(LayoutAnchorable anchorable)
        {
            var model = anchorable as LayoutAnchorable;
            if (model != null)
            {
                //by default hide the anchorable
                model.Hide();
            }
        }

        internal void _ExecuteAutoHideCommand(LayoutAnchorable _anchorable)
        {
            _anchorable.ToggleAutoHide();
        }

        internal void _ExecuteFloatCommand(LayoutContent contentToFloat)
        {
            contentToFloat.Float();
        }

        internal void _ExecuteDockCommand(LayoutAnchorable anchorable)
        {
            anchorable.Dock();
        }

        internal void _ExecuteDockAsDocumentCommand(LayoutContent content)
        {
            content.DockAsDocument();
        }

        private void RemoveViewFromLogicalChild( LayoutContent layoutContent )
        {
          if( layoutContent == null )
            return;

          var layoutItem = this.GetLayoutItemFromModel( layoutContent );
          if( layoutItem != null )
          {
            if( layoutItem.IsViewExists() )
            {
              this.InternalRemoveLogicalChild( layoutItem.View );
            }
          }
        }

        #region ActiveContent

        /// <summary>
        /// ActiveContent Dependency Property
        /// </summary>
        public static readonly DependencyProperty ActiveContentProperty =
            DependencyProperty.Register("ActiveContent", typeof(object), typeof(DockingManager),
                new FrameworkPropertyMetadata((object)null,
                    new PropertyChangedCallback(OnActiveContentChanged)));

        /// <summary>
        /// Gets or sets the ActiveContent property.  This dependency property 
        /// indicates the content currently active.
        /// </summary>
        public object ActiveContent
        {
            get { return (object)GetValue(ActiveContentProperty); }
            set { SetValue(ActiveContentProperty, value); }
        }

        /// <summary>
        /// Handles changes to the ActiveContent property.
        /// </summary>
        private static void OnActiveContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).InternalSetActiveContent(e.NewValue);
            ((DockingManager)d).OnActiveContentChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the ActiveContent property.
        /// </summary>
        protected virtual void OnActiveContentChanged(DependencyPropertyChangedEventArgs e)
        {
            if (ActiveContentChanged != null)
                ActiveContentChanged(this, EventArgs.Empty);
        }


        bool _insideInternalSetActiveContent = false;
        void InternalSetActiveContent(object contentObject)
        {
            var layoutContent = Layout.Descendents().OfType<LayoutContent>().FirstOrDefault(lc => lc == contentObject || lc.Content == contentObject);
            _insideInternalSetActiveContent = true;
            Layout.ActiveContent = layoutContent;
            _insideInternalSetActiveContent = false;
        }

        public event EventHandler ActiveContentChanged;

        #endregion

        #region AnchorableContextMenu

        /// <summary>
        /// AnchorableContextMenu Dependency Property
        /// </summary>
        public static readonly DependencyProperty AnchorableContextMenuProperty =
            DependencyProperty.Register("AnchorableContextMenu", typeof(ContextMenu), typeof(DockingManager),
                new FrameworkPropertyMetadata((ContextMenu)null));

        /// <summary>
        /// Gets or sets the AnchorableContextMenu property.  This dependency property 
        /// indicates the context menu to show up for anchorables.
        /// </summary>
        public ContextMenu AnchorableContextMenu
        {
            get { return (ContextMenu)GetValue(AnchorableContextMenuProperty); }
            set { SetValue(AnchorableContextMenuProperty, value); }
        }

        #endregion

        #region Theme

        /// <summary>
        /// Theme Dependency Property
        /// </summary>
        public static readonly DependencyProperty ThemeProperty =
            DependencyProperty.Register("Theme", typeof(Theme), typeof(DockingManager),
                new FrameworkPropertyMetadata(null,
                    new PropertyChangedCallback(OnThemeChanged)));

        /// <summary>
        /// Gets or sets the Theme property.  This dependency property 
        /// indicates the theme to use for AvalonDock controls.
        /// </summary>
        public Theme Theme
        {
            get { return (Theme)GetValue(ThemeProperty); }
            set { SetValue(ThemeProperty, value); }
        }

        /// <summary>
        /// Handles changes to the Theme property.
        /// </summary>
        private static void OnThemeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnThemeChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the Theme property.
        /// </summary>
        protected virtual void OnThemeChanged(DependencyPropertyChangedEventArgs e)
        {
            var oldTheme = e.OldValue as Theme;
            var newTheme = e.NewValue as Theme;
            var resources = this.Resources;
            if (oldTheme != null)
            {
              if( oldTheme is DictionaryTheme )
              {
                if( currentThemeResourceDictionary != null )
                {
                  resources.MergedDictionaries.Remove( currentThemeResourceDictionary );
                  currentThemeResourceDictionary = null;
                }
              }
              else
              {
                var resourceDictionaryToRemove =
                   resources.MergedDictionaries.FirstOrDefault( r => r.Source == oldTheme.GetResourceUri() );
                if( resourceDictionaryToRemove != null )
                  resources.MergedDictionaries.Remove(
                      resourceDictionaryToRemove );
              }
            }

            if (newTheme != null)
            {
              if( newTheme is DictionaryTheme )
              {
                currentThemeResourceDictionary = ( ( DictionaryTheme )newTheme ).ThemeResourceDictionary;
                resources.MergedDictionaries.Add( currentThemeResourceDictionary );
              }
              else
              {
                resources.MergedDictionaries.Add(new ResourceDictionary() { Source = newTheme.GetResourceUri() });
              }
            }

            foreach (var fwc in _fwList)
                fwc.UpdateThemeResources(oldTheme);

            if (_navigatorWindow != null)
                _navigatorWindow.UpdateThemeResources();

            if (_overlayWindow != null)
                _overlayWindow.UpdateThemeResources();
        }

        #endregion

        #region GridSplitterWidth

        /// <summary>
        /// GridSplitterWidth Dependency Property
        /// </summary>
        public static readonly DependencyProperty GridSplitterWidthProperty =
            DependencyProperty.Register("GridSplitterWidth", typeof(double), typeof(DockingManager),
                new FrameworkPropertyMetadata((double)6.0));

        /// <summary>
        /// Gets or sets the GridSplitterWidth property.  This dependency property 
        /// indicates width of grid splitters.
        /// </summary>
        public double GridSplitterWidth
        {
            get { return (double)GetValue(GridSplitterWidthProperty); }
            set { SetValue(GridSplitterWidthProperty, value); }
        }

        #endregion

        #region GridSplitterHeight

        /// <summary>
        /// GridSplitterHeight Dependency Property
        /// </summary>
        public static readonly DependencyProperty GridSplitterHeightProperty =
            DependencyProperty.Register("GridSplitterHeight", typeof(double), typeof(DockingManager),
                new FrameworkPropertyMetadata((double)6.0));

        /// <summary>
        /// Gets or sets the GridSplitterHeight property.  This dependency property 
        /// indicates height of grid splitters.
        /// </summary>
        public double GridSplitterHeight
        {
            get { return (double)GetValue(GridSplitterHeightProperty); }
            set { SetValue(GridSplitterHeightProperty, value); }
        }

        #endregion

        internal void _ExecuteContentActivateCommand(LayoutContent content)
        {
            content.IsActive = true;
        }

        #region DocumentPaneMenuItemHeaderTemplate

        /// <summary>
        /// DocumentPaneMenuItemHeaderTemplate Dependency Property
        /// </summary>
        public static readonly DependencyProperty DocumentPaneMenuItemHeaderTemplateProperty =
            DependencyProperty.Register("DocumentPaneMenuItemHeaderTemplate", typeof(DataTemplate), typeof(DockingManager),
                new FrameworkPropertyMetadata((DataTemplate)null,
                    new PropertyChangedCallback(OnDocumentPaneMenuItemHeaderTemplateChanged),
                    new CoerceValueCallback(CoerceDocumentPaneMenuItemHeaderTemplateValue)));

        /// <summary>
        /// Gets or sets the DocumentPaneMenuItemHeaderTemplate property.  This dependency property 
        /// indicates the header template to use while creating menu items for the document panes.
        /// </summary>
        public DataTemplate DocumentPaneMenuItemHeaderTemplate
        {
            get { return (DataTemplate)GetValue(DocumentPaneMenuItemHeaderTemplateProperty); }
            set { SetValue(DocumentPaneMenuItemHeaderTemplateProperty, value); }
        }

        /// <summary>
        /// Handles changes to the DocumentPaneMenuItemHeaderTemplate property.
        /// </summary>
        private static void OnDocumentPaneMenuItemHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnDocumentPaneMenuItemHeaderTemplateChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the DocumentPaneMenuItemHeaderTemplate property.
        /// </summary>
        protected virtual void OnDocumentPaneMenuItemHeaderTemplateChanged(DependencyPropertyChangedEventArgs e)
        { 
        }

        /// <summary>
        /// Coerces the DocumentPaneMenuItemHeaderTemplate value.
        /// </summary>
        private static object CoerceDocumentPaneMenuItemHeaderTemplateValue(DependencyObject d, object value)
        {
            if (value != null &&
                d.GetValue(DocumentPaneMenuItemHeaderTemplateSelectorProperty) != null)
                return null;
            if (value == null)
                return d.GetValue(DocumentHeaderTemplateProperty);

            return value;
        }

        #endregion

        #region DocumentPaneMenuItemHeaderTemplateSelector

        /// <summary>
        /// DocumentPaneMenuItemHeaderTemplateSelector Dependency Property
        /// </summary>
        public static readonly DependencyProperty DocumentPaneMenuItemHeaderTemplateSelectorProperty =
            DependencyProperty.Register("DocumentPaneMenuItemHeaderTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager),
                new FrameworkPropertyMetadata((DataTemplateSelector)null,
                    new PropertyChangedCallback(OnDocumentPaneMenuItemHeaderTemplateSelectorChanged),
                    new CoerceValueCallback(CoerceDocumentPaneMenuItemHeaderTemplateSelectorValue)));

        /// <summary>
        /// Gets or sets the DocumentPaneMenuItemHeaderTemplateSelector property.  This dependency property 
        /// indicates the data template selector to use for the menu items show when user select the DocumentPane document switch context menu.
        /// </summary>
        public DataTemplateSelector DocumentPaneMenuItemHeaderTemplateSelector
        {
            get { return (DataTemplateSelector)GetValue(DocumentPaneMenuItemHeaderTemplateSelectorProperty); }
            set { SetValue(DocumentPaneMenuItemHeaderTemplateSelectorProperty, value); }
        }

        /// <summary>
        /// Handles changes to the DocumentPaneMenuItemHeaderTemplateSelector property.
        /// </summary>
        private static void OnDocumentPaneMenuItemHeaderTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnDocumentPaneMenuItemHeaderTemplateSelectorChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the DocumentPaneMenuItemHeaderTemplateSelector property.
        /// </summary>
        protected virtual void OnDocumentPaneMenuItemHeaderTemplateSelectorChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue != null &&
                DocumentPaneMenuItemHeaderTemplate != null)
                DocumentPaneMenuItemHeaderTemplate = null;

        }

        /// <summary>
        /// Coerces the DocumentPaneMenuItemHeaderTemplateSelector value.
        /// </summary>
        private static object CoerceDocumentPaneMenuItemHeaderTemplateSelectorValue(DependencyObject d, object value)
        {
            return value;
        }

        #endregion

        #region IconContentTemplate

        /// <summary>
        /// IconContentTemplate Dependency Property
        /// </summary>
        public static readonly DependencyProperty IconContentTemplateProperty =
            DependencyProperty.Register("IconContentTemplate", typeof(DataTemplate), typeof(DockingManager),
                new FrameworkPropertyMetadata((DataTemplate)null));

        /// <summary>
        /// Gets or sets the IconContentTemplate property.  This dependency property 
        /// indicates the data template to use while extracting the icon from model.
        /// </summary>
        public DataTemplate IconContentTemplate
        {
            get { return (DataTemplate)GetValue(IconContentTemplateProperty); }
            set { SetValue(IconContentTemplateProperty, value); }
        }

        #endregion

        #region IconContentTemplateSelector

        /// <summary>
        /// IconContentTemplateSelector Dependency Property
        /// </summary>
        public static readonly DependencyProperty IconContentTemplateSelectorProperty =
            DependencyProperty.Register("IconContentTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager),
                new FrameworkPropertyMetadata((DataTemplateSelector)null));

        /// <summary>
        /// Gets or sets the IconContentTemplateSelector property.  This dependency property 
        /// indicates data template selector to use while selecting the datatamplate for content icons.
        /// </summary>
        public DataTemplateSelector IconContentTemplateSelector
        {
            get { return (DataTemplateSelector)GetValue(IconContentTemplateSelectorProperty); }
            set { SetValue(IconContentTemplateSelectorProperty, value); }
        }

        #endregion

        #region LayoutItems

        List<LayoutItem> _layoutItems = new List<LayoutItem>();

        bool _suspendLayoutItemCreation = false;

        void DetachLayoutItems()
        {
            if (Layout != null)
            {
                _layoutItems.ForEach<LayoutItem>(i => i.Detach());
                _layoutItems.Clear();
                Layout.ElementAdded -= new EventHandler<LayoutElementEventArgs>(Layout_ElementAdded);
                Layout.ElementRemoved -= new EventHandler<LayoutElementEventArgs>(Layout_ElementRemoved);
            }
        }

        void Layout_ElementRemoved(object sender, LayoutElementEventArgs e)
        {
            if (_suspendLayoutItemCreation)
                return;

            CollectLayoutItemsDeleted();
        }

        void Layout_ElementAdded(object sender, LayoutElementEventArgs e)
        {
            if (_suspendLayoutItemCreation)
                return;

            foreach (var content in Layout.Descendents().OfType<LayoutContent>())
            {
                if (content is LayoutDocument)
                    CreateDocumentLayoutItem(content as LayoutDocument);
                else //if (content is LayoutAnchorable)
                    CreateAnchorableLayoutItem(content as LayoutAnchorable);
            }

            CollectLayoutItemsDeleted();
        }


        DispatcherOperation _collectLayoutItemsOperations = null;
        void CollectLayoutItemsDeleted()
        {
            if (_collectLayoutItemsOperations != null)
                return;
            _collectLayoutItemsOperations = Dispatcher.BeginInvoke(new Action(() =>
                {
                    _collectLayoutItemsOperations = null;
                    foreach (var itemToRemove in _layoutItems.Where(item => item.LayoutElement.Root != Layout).ToArray())
                    {

                        if (itemToRemove != null &&
                            itemToRemove.Model != null &&
                            itemToRemove.Model is UIElement)
                        {
                            //((ILogicalChildrenContainer)this).InternalRemoveLogicalChild(itemToRemove.Model as UIElement);
                        }

                        itemToRemove.Detach();
                        _layoutItems.Remove(itemToRemove);

                    }
                }));
        }


        void AttachLayoutItems()
        {
            if (Layout != null)
            {
                foreach (var document in Layout.Descendents().OfType<LayoutDocument>().ToArray())
                {
                    CreateDocumentLayoutItem(document);
                    //var documentItem = new LayoutDocumentItem();
                    //documentItem.Attach(document);
                    //ApplyStyleToLayoutItem(documentItem);
                    //_layoutItems.Add(documentItem);
                }
                foreach (var anchorable in Layout.Descendents().OfType<LayoutAnchorable>().ToArray())
                {
                    CreateAnchorableLayoutItem(anchorable);
                    //var anchorableItem = new LayoutAnchorableItem();
                    //anchorableItem.Attach(anchorable);
                    //ApplyStyleToLayoutItem(anchorableItem);
                    //_layoutItems.Add(anchorableItem);
                }

                Layout.ElementAdded += new EventHandler<LayoutElementEventArgs>(Layout_ElementAdded);
                Layout.ElementRemoved += new EventHandler<LayoutElementEventArgs>(Layout_ElementRemoved);
            }
        }

        void ApplyStyleToLayoutItem(LayoutItem layoutItem)
        {
            layoutItem._ClearDefaultBindings();
            if (LayoutItemContainerStyle != null)
                layoutItem.Style = LayoutItemContainerStyle;
            else if (LayoutItemContainerStyleSelector != null)
                layoutItem.Style = LayoutItemContainerStyleSelector.SelectStyle(layoutItem.Model, layoutItem);
            layoutItem._SetDefaultBindings();
        }

        void CreateAnchorableLayoutItem(LayoutAnchorable contentToAttach)
        {
            if (_layoutItems.Any(item => item.LayoutElement == contentToAttach))
                return;

            var layoutItem = new LayoutAnchorableItem();
            layoutItem.Attach(contentToAttach);
            ApplyStyleToLayoutItem(layoutItem);
            _layoutItems.Add(layoutItem);

            if (contentToAttach != null &&
                contentToAttach.Content != null &&
                contentToAttach.Content is UIElement)
            {
                InternalAddLogicalChild(contentToAttach.Content);
            }

        }

        void CreateDocumentLayoutItem(LayoutDocument contentToAttach)
        {
            if (_layoutItems.Any(item => item.LayoutElement == contentToAttach))
                return;

            var layoutItem = new LayoutDocumentItem();
            layoutItem.Attach(contentToAttach);
            ApplyStyleToLayoutItem(layoutItem);
            _layoutItems.Add(layoutItem);

            if (contentToAttach != null &&
                contentToAttach.Content != null &&
                contentToAttach.Content is UIElement)
            {
                InternalAddLogicalChild(contentToAttach.Content);
            }

        }

        #region LayoutItemContainerStyle

        /// <summary>
        /// LayoutItemContainerStyle Dependency Property
        /// </summary>
        public static readonly DependencyProperty LayoutItemContainerStyleProperty =
            DependencyProperty.Register("LayoutItemContainerStyle", typeof(Style), typeof(DockingManager),
                new FrameworkPropertyMetadata((Style)null,
                    new PropertyChangedCallback(OnLayoutItemContainerStyleChanged)));

        /// <summary>
        /// Gets or sets the LayoutItemContainerStyle property.  This dependency property 
        /// indicates the style to apply to LayoutDocumentItem objects. A LayoutDocumentItem object is created when a new LayoutDocument is created inside the current Layout.
        /// </summary>
        public Style LayoutItemContainerStyle
        {
            get { return (Style)GetValue(LayoutItemContainerStyleProperty); }
            set { SetValue(LayoutItemContainerStyleProperty, value); }
        }

        /// <summary>
        /// Handles changes to the LayoutItemContainerStyle property.
        /// </summary>
        private static void OnLayoutItemContainerStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnLayoutItemContainerStyleChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the LayoutItemContainerStyle property.
        /// </summary>
        protected virtual void OnLayoutItemContainerStyleChanged(DependencyPropertyChangedEventArgs e)
        {
            AttachLayoutItems();
        }

        #endregion

        #region LayoutItemContainerStyleSelector

        /// <summary>
        /// LayoutItemContainerStyleSelector Dependency Property
        /// </summary>
        public static readonly DependencyProperty LayoutItemContainerStyleSelectorProperty =
            DependencyProperty.Register("LayoutItemContainerStyleSelector", typeof(StyleSelector), typeof(DockingManager),
                new FrameworkPropertyMetadata((StyleSelector)null,
                    new PropertyChangedCallback(OnLayoutItemContainerStyleSelectorChanged)));

        /// <summary>
        /// Gets or sets the LayoutItemContainerStyleSelector property.  This dependency property 
        /// indicates style selector of the LayoutDocumentItemStyle.
        /// </summary>
        public StyleSelector LayoutItemContainerStyleSelector
        {
            get { return (StyleSelector)GetValue(LayoutItemContainerStyleSelectorProperty); }
            set { SetValue(LayoutItemContainerStyleSelectorProperty, value); }
        }

        /// <summary>
        /// Handles changes to the LayoutItemContainerStyleSelector property.
        /// </summary>
        private static void OnLayoutItemContainerStyleSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockingManager)d).OnLayoutItemContainerStyleSelectorChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the LayoutItemContainerStyleSelector property.
        /// </summary>
        protected virtual void OnLayoutItemContainerStyleSelectorChanged(DependencyPropertyChangedEventArgs e)
        {
            AttachLayoutItems();
        }

        #endregion

        /// <summary>
        /// Return the LayoutItem wrapper for the content passed as argument
        /// </summary>
        /// <param name="content">LayoutContent to search</param>
        /// <returns>Either a LayoutAnchorableItem or LayoutDocumentItem which contains the LayoutContent passed as argument</returns>
        public LayoutItem GetLayoutItemFromModel(LayoutContent content)
        {
            return _layoutItems.FirstOrDefault(item => item.LayoutElement == content);
        }
        #endregion

        #region NavigatorWindow
        NavigatorWindow _navigatorWindow = null;

        void ShowNavigatorWindow()
        {
            if (_navigatorWindow == null)
            {
                _navigatorWindow = new NavigatorWindow(this)
                { 
                    Owner = Window.GetWindow(this),
                    WindowStartupLocation = WindowStartupLocation.CenterOwner
                };
            }

            _navigatorWindow.ShowDialog();
            _navigatorWindow = null;
        }

        bool IsNavigatorWindowActive
        {
            get { return _navigatorWindow != null; }
        }


        protected override void OnPreviewKeyDown(KeyEventArgs e)
        {
            if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
            {
                if (e.IsDown && e.Key == Key.Tab)
                {
                    if (!IsNavigatorWindowActive)
                    {
                        ShowNavigatorWindow();
                        e.Handled = true;
                    }
                }
            }

            base.OnPreviewKeyDown(e);
        }

        #endregion

        #region ShowSystemMenu

        /// <summary>
        /// ShowSystemMenu Dependency Property
        /// </summary>
        public static readonly DependencyProperty ShowSystemMenuProperty =
            DependencyProperty.Register("ShowSystemMenu", typeof(bool), typeof(DockingManager),
                new FrameworkPropertyMetadata((bool)true));

        /// <summary>
        /// Gets or sets the ShowSystemMenu property.  This dependency property 
        /// indicates if floating windows should show the system menu when a custom context menu is not defined.
        /// </summary>
        public bool ShowSystemMenu
        {
            get { return (bool)GetValue(ShowSystemMenuProperty); }
            set { SetValue(ShowSystemMenuProperty, value); }
        }

        #endregion

        #region AllowMixedOrientation

        /// <summary>
        /// AllowMixedOrientation Dependency Property
        /// </summary>
        public static readonly DependencyProperty AllowMixedOrientationProperty =
            DependencyProperty.Register("AllowMixedOrientation", typeof(bool), typeof(DockingManager),
                new FrameworkPropertyMetadata((bool)false));

        /// <summary>
        /// Gets or sets the AllowMixedOrientation property.  This dependency property 
        /// indicates if the manager should allow mixed orientation for document panes.
        /// </summary>
        public bool AllowMixedOrientation
        {
            get { return (bool)GetValue(AllowMixedOrientationProperty); }
            set { SetValue(AllowMixedOrientationProperty, value); }
        }

        #endregion


    }
}
