using System;
using System.Windows.Forms;
using System.Drawing;
using System.Xml;
using System.ComponentModel;
namespace DevComponents.DotNetBar
{
	/// 
	/// Represents class that manages document docking UI interaction.
	/// 
	public class DocumentDockUIManager
	{
		#region Private Variables, Constructor
		private DocumentDockContainer m_DocumentDockContainer=null;
		private Cursor m_ContainerCursor=null;
		private DockSite m_Container=null;
		private Point m_MouseDownPoint=Point.Empty;
		private bool m_ResizePreview=false;
		private Form m_Splitter=null;
		private DocumentDockContainer m_ResizeDockContainer=null;
		private DocumentBaseContainer m_ResizeDocument=null;
		private int m_SplitterWidth=3;
		private bool m_LoadingLayout=false;
		public DocumentDockUIManager(DockSite container)
		{
			m_Container=container;
		}
		#endregion
		#region Properties
		/// 
		/// Gets or sets the root document dock container object.
		/// 
		public DocumentDockContainer RootDocumentDockContainer
		{
			get {return m_DocumentDockContainer;}
			set {m_DocumentDockContainer=value;}
		}
        /// 
        /// Gets or sets the splitter width used for mouse hit-testing.
        /// 
        public int SplitterWidth
        {
            get
            {
                return m_SplitterWidth;
            }
            set
            {
                m_SplitterWidth = value;
            }
        }
		/// 
		/// Gets or sets the container of the document. 
		/// 
		public DockSite Container
		{
			get {return m_Container;}
			set {m_Container=value;}
		}
		#endregion
		#region Methods
		/// 
		/// Estimates the docking position and size of a given bar for outline purposes during drag&drop
		/// 
		/// Bar to find estimated docking position and size for
		/// Docking information
		/// Preview Rectangle in screen coordinates.
		internal Rectangle GetDockPreviewRectangle(Bar bar, ref DockSiteInfo dockInfo)
		{
			DocumentBaseContainer referenceDoc=GetDocumentFromBar(dockInfo.MouseOverBar);
			Rectangle r=Rectangle .Empty;
            // Handle edge case docking first
            if (m_Container.Dock!= DockStyle.Fill && (dockInfo.DockLine == 999 || dockInfo.DockLine == -1))
            {
                return GetEdgeDockPreviewRectangle(bar, ref dockInfo);
            }
			else if(referenceDoc!=null)
			{
				if(dockInfo.MouseOverDockSide==eDockSide.Left)
				{
					r=referenceDoc.DisplayBounds;
					r.Width=r.Width/2;
				}
				else if(dockInfo.MouseOverDockSide==eDockSide.Right)
				{
					r=referenceDoc.DisplayBounds;
					r.X+=r.Width/2;
					r.Width=r.Width/2;
				}
				else if(dockInfo.MouseOverDockSide==eDockSide.Top)
				{
					r=referenceDoc.DisplayBounds;
					r.Height=r.Height/2;
				}
				else if(dockInfo.MouseOverDockSide==eDockSide.Bottom)
				{
					r=referenceDoc.DisplayBounds;
					r.Y+=r.Height/2;
					r.Height=r.Height/2;
				}
				else if(dockInfo.MouseOverDockSide==eDockSide.Document)
				{
					r=referenceDoc.DisplayBounds;
				}
				r.Location=m_Container.PointToScreen(r.Location);
			}
			else
			{
                if (m_Container.Dock == DockStyle.Fill)
                {
                    r = m_Container.ClientRectangle;
                    r.Location = m_Container.PointToScreen(r.Location);
                }
                else if (m_Container.Dock == DockStyle.Right)
                {
                    r = m_Container.ClientRectangle;
                    r.Location = m_Container.PointToScreen(r.Location);
                    if (r.Width == 0)
                    {
                        r.Width = bar.GetBarDockedSize(eOrientation.Vertical);
                        r.X -= r.Width;
                    }
                }
                else if (m_Container.Dock == DockStyle.Left)
                {
                    r = m_Container.ClientRectangle;
                    r.Location = m_Container.PointToScreen(r.Location);
                    if (r.Width == 0)
                    {
                        r.Width = bar.GetBarDockedSize(eOrientation.Vertical);
                    }
                }
                else if (m_Container.Dock == DockStyle.Top)
                {
                    r = m_Container.ClientRectangle;
                    r.Location = m_Container.PointToScreen(r.Location);
                    if (r.Height == 0)
                    {
                        r.Height = bar.GetBarDockedSize(eOrientation.Horizontal);
                    }
                }
                else if (m_Container.Dock == DockStyle.Bottom)
                {
                    r = m_Container.ClientRectangle;
                    r.Location = m_Container.PointToScreen(r.Location);
                    if (r.Height == 0)
                    {
                        r.Height = bar.GetBarDockedSize(eOrientation.Horizontal);
                        r.Y -= r.Height;
                    }
                }
			}
			return r;
		}
        private Rectangle GetEdgeDockPreviewRectangle(Bar bar, ref DockSiteInfo dockInfo)
        {
            Rectangle r = Rectangle.Empty;
            int fullSizeIndex = -1;
            int partialSizeIndex = -1;
            if (dockInfo.FullSizeDock)
                fullSizeIndex = m_Container.GetFullSizeIndex();
            else if (dockInfo.PartialSizeDock)
                partialSizeIndex = m_Container.GetPartialSizeIndex();
            // Docks the bar to the edge
            switch (m_Container.Dock)
            {
                case DockStyle.Top:
                    {
                        r.Width = m_Container.ClientRectangle.Width;
                        r.Height = bar.GetBarDockedSize(eOrientation.Horizontal);
                        if (fullSizeIndex >= 0)
                        {
                            r.Width += m_Container.GetSiteZOrderSize(m_Container.Owner.LeftDockSite, true).Width;
                            r.Width += m_Container.GetSiteZOrderSize(m_Container.Owner.RightDockSite, true).Width;
                            dockInfo.DockSiteZOrderIndex = fullSizeIndex;
                        }
                        else if (partialSizeIndex >= 0)
                        {
                            // Reduce by the size of the left and right dock site
                            r.Width -= m_Container.GetSiteZOrderSize(m_Container.Owner.LeftDockSite, false).Width;
                            r.Width -= m_Container.GetSiteZOrderSize(m_Container.Owner.RightDockSite, false).Width;
                            dockInfo.DockSiteZOrderIndex = partialSizeIndex;
                        }
                        Point p = Point.Empty;
                        if (dockInfo.DockLine == -1)
                        {
                            p = m_Container.PointToScreen(m_Container.ClientRectangle.Location);
                        }
                        else
                        {
                            p = m_Container.PointToScreen(new Point(m_Container.ClientRectangle.X, m_Container.ClientRectangle.Bottom));
                            p.Y++;
                        }
                        if (fullSizeIndex >= 0)
                            p.X -= m_Container.GetSiteZOrderSize(m_Container.Owner.LeftDockSite, true).Width;
                        else if (partialSizeIndex >= 0)
                            p.X += m_Container.GetSiteZOrderSize(m_Container.Owner.LeftDockSite, false).Width;
                        r.Location = p;
                        break;
                    }
                case DockStyle.Bottom:
                    {
                        r.Width = m_Container.ClientRectangle.Width;
                        r.Height = bar.GetBarDockedSize(eOrientation.Horizontal);
                        if (fullSizeIndex >= 0)
                        {
                            r.Width += m_Container.GetSiteZOrderSize(m_Container.Owner.LeftDockSite, true).Width;
                            r.Width += m_Container.GetSiteZOrderSize(m_Container.Owner.RightDockSite, true).Width;
                            dockInfo.DockSiteZOrderIndex = fullSizeIndex;
                        }
                        else if (partialSizeIndex >= 0)
                        {
                            // Reduce by the size of the left and right dock site
                            r.Width -= m_Container.GetSiteZOrderSize(m_Container.Owner.LeftDockSite, false).Width;
                            r.Width -= m_Container.GetSiteZOrderSize(m_Container.Owner.RightDockSite, false).Width;
                            dockInfo.DockSiteZOrderIndex = partialSizeIndex;
                        }
                        Point p = Point.Empty;
                        if (dockInfo.DockLine == -1)
                        {
                            p = m_Container.PointToScreen(new Point(m_Container.ClientRectangle.X, m_Container.ClientRectangle.Y - r.Height));
                        }
                        else
                        {
                            p = m_Container.PointToScreen(new Point(m_Container.ClientRectangle.X, m_Container.ClientRectangle.Bottom - r.Height));
                            p.Y++;
                        }
                        if (fullSizeIndex >= 0)
                            p.X -= m_Container.GetSiteZOrderSize(m_Container.Owner.LeftDockSite, true).Width;
                        else if (partialSizeIndex >= 0)
                            p.X += m_Container.GetSiteZOrderSize(m_Container.Owner.LeftDockSite, false).Width;
                        r.Location = p;
                        break;
                    }
                case DockStyle.Right:
                    {
                        r.Height = m_Container.ClientRectangle.Height;
                        if (fullSizeIndex >= 0)
                        {
                            r.Height += m_Container.GetSiteZOrderSize(m_Container.Owner.TopDockSite, true).Height;
                            r.Height += m_Container.GetSiteZOrderSize(m_Container.Owner.BottomDockSite, true).Height;
                            dockInfo.DockSiteZOrderIndex = fullSizeIndex;
                        }
                        else if (partialSizeIndex >= 0)
                        {
                            // Reduce by the size of the top and bottom dock site
                            r.Height -= m_Container.GetSiteZOrderSize(m_Container.Owner.TopDockSite, false).Height;
                            r.Height -= m_Container.GetSiteZOrderSize(m_Container.Owner.BottomDockSite, false).Height;
                            dockInfo.DockSiteZOrderIndex = partialSizeIndex;
                        }
                        r.Width = bar.GetBarDockedSize(eOrientation.Vertical);
                        Point p = Point.Empty;
                        if (dockInfo.DockLine == -1)
                        {
                            p = m_Container.PointToScreen(new Point(m_Container.ClientRectangle.X - r.Width, m_Container.ClientRectangle.Y));
                        }
                        else
                        {
                            p = m_Container.PointToScreen(new Point(m_Container.ClientRectangle.Right - r.Width, m_Container.ClientRectangle.Y));
                            p.X--;
                        }
                        if (fullSizeIndex >= 0)
                            p.Y -= m_Container.GetSiteZOrderSize(m_Container.Owner.TopDockSite, true).Height;
                        else if (partialSizeIndex >= 0)
                            p.Y += m_Container.GetSiteZOrderSize(m_Container.Owner.TopDockSite, false).Height;
                        r.Location = p;
                        break;
                    }
                default:
                    {
                        r.Height = m_Container.ClientRectangle.Height;
                        if (fullSizeIndex >= 0)
                        {
                            r.Height += m_Container.GetSiteZOrderSize(m_Container.Owner.TopDockSite, true).Height;
                            r.Height += m_Container.GetSiteZOrderSize(m_Container.Owner.BottomDockSite, true).Height;
                            dockInfo.DockSiteZOrderIndex = fullSizeIndex;
                        }
                        else if (partialSizeIndex >= 0)
                        {
                            // Reduce by the size of the top and bottom dock site
                            r.Height -= m_Container.GetSiteZOrderSize(m_Container.Owner.TopDockSite, false).Height;
                            r.Height -= m_Container.GetSiteZOrderSize(m_Container.Owner.BottomDockSite, false).Height;
                            dockInfo.DockSiteZOrderIndex = partialSizeIndex;
                        }
                        r.Width = bar.GetBarDockedSize(eOrientation.Vertical);
                        Point p = Point.Empty;
                        if (dockInfo.DockLine == -1)
                        {
                            p = m_Container.PointToScreen(new Point(m_Container.ClientRectangle.X, m_Container.ClientRectangle.Y));
                        }
                        else
                        {
                            p = m_Container.PointToScreen(new Point(m_Container.ClientRectangle.Right, m_Container.ClientRectangle.Y));
                            p.X++;
                        }
                        if (fullSizeIndex >= 0)
                            p.Y -= m_Container.GetSiteZOrderSize(m_Container.Owner.TopDockSite, true).Height;
                        else if (partialSizeIndex >= 0)
                            p.Y += m_Container.GetSiteZOrderSize(m_Container.Owner.TopDockSite, false).Height;
                        r.Location = p;
                        break;
                    }
            }
            return r;
        }
		/// 
		/// Returns DocumentBaseContainer that holds the reference bar.
		/// 
		/// Bar to return document container for.
		/// Returns null if document container cannot  be found or reference to the document container.
		public DocumentBaseContainer GetDocumentFromBar(Bar bar)
		{
			if(bar==null)
				return null;
			return GetDocumentFromBar(bar,m_DocumentDockContainer);
		}
		private DocumentBaseContainer GetDocumentFromBar(Bar bar, DocumentDockContainer dockContainer)
		{
			foreach(DocumentBaseContainer doc in dockContainer.Documents)
			{
				if(doc is DocumentBarContainer && ((DocumentBarContainer)doc).Bar==bar)
					return doc;
				else if(doc is DocumentDockContainer)
				{
					DocumentBaseContainer d=GetDocumentFromBar(bar,doc as DocumentDockContainer);
					if(d!=null)
						return d;
				}
			}
			return null;
		}
        private bool IsAddedInFront(eDockSide dockSide)
        {
            if (m_Container.Dock == DockStyle.Left && dockSide == eDockSide.Left ||
                m_Container.Dock == DockStyle.Right && dockSide == eDockSide.Left ||
                m_Container.Dock == DockStyle.Top && dockSide== eDockSide.Top || 
                m_Container.Dock == DockStyle.Bottom && dockSide == eDockSide.Top)
                return true;
            return false;
        }
		/// 
		/// Docks specified bar by appending it to the container. Bar will be added according to the container's orientation.
		/// 
		/// Bar to dock.
		public void Dock(Bar barToDock)
		{
			Dock(null,barToDock,eDockSide.None);
		}
        /// 
        /// Docks specified bar by appending it to the container. Bar will be added according to the container's orientation.
        /// 
        /// Bar to dock.
        /// Side to dock bar at.
		public void Dock(Bar referenceBar, Bar barToDock, eDockSide dockSide)
		{
			if(dockSide==eDockSide.None && barToDock.Parent==m_Container)
			{
				ApplyBarStyle(barToDock);
				return;
			}
			if(barToDock.Parent is DockSite && ((DockSite)barToDock.Parent).DocumentDockContainer!=null)
				((DockSite)barToDock.Parent).GetDocumentUIManager().UnDock(barToDock);
			else if(barToDock.Parent is DockSite && barToDock.Parent!=m_Container)
				((DockSite)barToDock.Parent).RemoveBar(barToDock);
            else if (barToDock.Parent != null && barToDock.Parent != m_Container)
            {
                if (barToDock.Parent is FloatingContainer)
                {
                    barToDock.RemoveFromFloatingContainer();
                    barToDock.SetBarState(eBarState.Docked);
                }
                else
                    barToDock.Parent.Controls.Remove(barToDock);
            }
			if(!m_LoadingLayout)
			{
				// TODO: Add Docking as Document, i.e. add DockContainerItems from barToDock...
				DocumentBarContainer doc=this.CreateDocumentBarContainer(barToDock);
                DocumentBaseContainer referenceDoc = this.GetDocumentFromBar(referenceBar);
                if (referenceBar == null || dockSide == eDockSide.None || referenceBar == barToDock || referenceDoc == null)
				{
                    if (m_Container.Dock == DockStyle.Fill)
                        m_DocumentDockContainer.Documents.Add(doc);
                    else
                    {
                        eOrientation containerOrientation = eOrientation.Horizontal; // Needed container orientation
                        if (m_Container.Dock == DockStyle.Top || m_Container.Dock == DockStyle.Bottom)
                            containerOrientation = eOrientation.Vertical;
                        // Switch orientation when adding new bar if possible
                        if (m_DocumentDockContainer.Orientation != containerOrientation)
                        {
                            if (m_DocumentDockContainer.Documents.Count <= 1)
                            {
                                m_DocumentDockContainer.Orientation = containerOrientation;
                                if (IsAddedInFront(dockSide))
                                    m_DocumentDockContainer.Documents.Insert(0, doc);
                                else
                                    m_DocumentDockContainer.Documents.Add(doc);
                            }
                            else
                            {
                                DocumentBaseContainer[] docs = new DocumentBaseContainer[m_DocumentDockContainer.Documents.Count];
                                m_DocumentDockContainer.Documents.CopyTo(docs);
                                m_DocumentDockContainer.Documents.Clear();
                                DocumentDockContainer newParent = new DocumentDockContainer(docs, m_DocumentDockContainer.Orientation);
								newParent.SetLayoutBounds(m_DocumentDockContainer.DisplayBounds);
                                m_DocumentDockContainer.Orientation = containerOrientation;
                                m_DocumentDockContainer.Documents.Add(newParent);
                                if (IsAddedInFront(dockSide))
                                    m_DocumentDockContainer.Documents.Insert(0, doc);
                                else
                                    m_DocumentDockContainer.Documents.Add(doc);
                            }
                        }
                        else
                        {
                            if (IsAddedInFront(dockSide))
                                m_DocumentDockContainer.Documents.Insert(0, doc);
                            else
                                m_DocumentDockContainer.Documents.Add(doc);
                        }
                    }
				}
				else
				{
					DocumentDockContainer parent=referenceDoc.Parent as DocumentDockContainer;
					referenceDoc.SetLayoutBounds(Rectangle.Empty);
					doc.SetLayoutBounds(Rectangle.Empty);
					if((parent.Orientation==eOrientation.Horizontal && (dockSide==eDockSide.Left || dockSide==eDockSide.Right)) ||
						(parent.Orientation==eOrientation.Vertical && (dockSide==eDockSide.Top || dockSide==eDockSide.Bottom)))
					{
						if(dockSide==eDockSide.Right || dockSide==eDockSide.Bottom)
							parent.Documents.Insert(parent.Documents.IndexOf(referenceDoc)+1,doc);
						else
							parent.Documents.Insert(parent.Documents.IndexOf(referenceDoc),doc);
					}
					else if(parent.Documents.Count==1)
					{
						// Orientation of the parent dock container can be changed
						if(parent.Orientation==eOrientation.Vertical)
							parent.Orientation=eOrientation.Horizontal;
						else
							parent.Orientation=eOrientation.Vertical;
						if(dockSide==eDockSide.Right || dockSide==eDockSide.Bottom)
							parent.Documents.Insert(parent.Documents.IndexOf(referenceDoc)+1,doc);
						else
							parent.Documents.Insert(parent.Documents.IndexOf(referenceDoc),doc);
					}
					else
					{
						// New DocumentDockContainer needs to be inserted with appropriate orientation and referenceBar needs
						// to be moved into it.
						DocumentDockContainer newParent=new DocumentDockContainer();
						if(parent.Orientation==eOrientation.Horizontal)
							newParent.Orientation=eOrientation.Vertical;
						else
							newParent.Orientation=eOrientation.Horizontal;
						parent.Documents.Insert(parent.Documents.IndexOf(referenceDoc),newParent);
						parent.Documents.Remove(referenceDoc);
	                    
						if(dockSide==eDockSide.Right || dockSide==eDockSide.Bottom)
						{
							newParent.Documents.Add(referenceDoc);
							newParent.Documents.Add(doc);
						}
						else
						{
							newParent.Documents.Add(doc);
							newParent.Documents.Add(referenceDoc);
						}
					}
				}
                AdjustContainerSize(barToDock, false);
			}
			if(m_Container!=null)
			{
				if(barToDock.Parent==null)
					m_Container.Controls.Add(barToDock);
                ApplyBarStyle(barToDock);	
				m_Container.RecalcLayout();
			}
			else
				ApplyBarStyle(barToDock);
		}
        /// 
        /// Adjusts the size of the dock container if needed after a bar has been docked to it.
        /// 
        /// Bar object that has been docked.
        /// Indicates that bar was already docked but its Visible property has changed
        internal void AdjustContainerSize(Bar barToDock, bool visibleChanged)
        {
            if (m_Container.Owner != null && m_Container.Owner.IsLoadingLayout) return;
            // Adjust the size of the container since it dictates the size of the bars docked inside
            if (m_Container.Dock != DockStyle.Fill)
            {
                DocumentBaseContainer doc = this.GetDocumentFromBar(barToDock);
                if (doc == null) return;
                if (m_Container.Dock == DockStyle.Left || m_Container.Dock == DockStyle.Right)
                {
                    if (m_Container.Width == 0 || doc.Parent == m_DocumentDockContainer &&
                        (m_DocumentDockContainer.Orientation == eOrientation.Horizontal || visibleChanged && m_DocumentDockContainer.Documents.Count == 1))
                    {
                        int width = barToDock.GetBarDockedSize(eOrientation.Vertical);
                        if (barToDock.Width > 0 && barToDock.Width clientWidth)
                                width = barToDock.MinimumDockSize(eOrientation.Vertical).Width * 2;
                            if (width > clientWidth)
                                width = barToDock.MinimumDockSize(eOrientation.Vertical).Width;
                        }
                        
						if(doc.LayoutBounds.Width == 0)
							doc.SetLayoutBounds(new Rectangle(doc.LayoutBounds.X, doc.LayoutBounds.Y, width, doc.LayoutBounds.Height));
                        width += Dpi.Width(m_DocumentDockContainer.SplitterSize);
                        if (visibleChanged)
                        {
                            if(barToDock.Visible)
                                m_Container.Width += width;
                            else if(m_Container.Width>0)
                                m_Container.Width -= Math.Min(width, m_Container.Width);
                        }
                        else
                            m_Container.Width += width;
                        m_Container.Invalidate();
                    }
                }
                else if (m_Container.Dock == DockStyle.Top || m_Container.Dock == DockStyle.Bottom)
                {
                    if (m_Container.Height == 0 || doc.Parent == m_DocumentDockContainer &&
                        (m_DocumentDockContainer.Orientation == eOrientation.Vertical || visibleChanged && m_DocumentDockContainer.Documents.Count == 1))
                    {
                        int height = barToDock.GetBarDockedSize(eOrientation.Horizontal);
                        if (barToDock.Height > 0 && barToDock.Height clientHeight)
                                height = barToDock.MinimumDockSize(eOrientation.Horizontal).Height * 2;
                            if (height > clientHeight)
                                height = barToDock.MinimumDockSize(eOrientation.Horizontal).Height;
                        }
                        
						if(doc.LayoutBounds.Height == 0)
							doc.SetLayoutBounds(new Rectangle(doc.LayoutBounds.X, doc.LayoutBounds.Y, doc.LayoutBounds.Width, height));
                        height += Dpi.Width(m_DocumentDockContainer.SplitterSize);
                        if (visibleChanged)
                        {
                            if (barToDock.Visible)
                                m_Container.Height += height;
                            else if (m_Container.Height > 0)
                                m_Container.Height -= Math.Min(height, m_Container.Height);
                        }
                        else
                            m_Container.Height += height;
                        m_Container.Invalidate();
                    }
                }
            }
        }
        private int GetClientWidth()
        {
            if (m_Container == null)
                return 0;
            return m_Container.GetClientWidth();
        }
        private int GetClientHeight()
        {
            if (m_Container == null)
                return 0;
            return m_Container.GetClientHeight();
        }
		public void UnDock(Bar barToUnDock)
		{
			UnDock(barToUnDock,true);
		}
        internal void SaveLastDockInfo(Bar bar, DocumentBarContainer doc, DockSiteInfo info)
        {
            if (bar.m_LastDockSiteInfo == null) return;
            //bar.m_LastDockSiteInfo.LastRelativeDockToBar = null;
            //bar.m_LastDockSiteInfo.LastRelativeDocumentId = -1;
            // Tries to find relative dock-to-bar so un-docked bar can be returned back
            if (!(doc.Parent is DocumentDockContainer)) return;
            DocumentDockContainer dockParent = (DocumentDockContainer)doc.Parent;
            DocumentBaseContainer nextBarDocument = GetNextDocument(dockParent, dockParent.Documents.IndexOf(doc));
            if (nextBarDocument == null)
            {
                DocumentBaseContainer prevBarDocument = GetPreviousDocument(dockParent, dockParent.Documents.IndexOf(doc));
                if (prevBarDocument != null)
                {
                    Bar prevBar = null;
                    if (prevBarDocument is DocumentBarContainer)
                    {
                        prevBar = ((DocumentBarContainer)prevBarDocument).Bar;
                        bar.m_LastDockSiteInfo.LastRelativeDockToBar = prevBar;
                        prevBar.m_LastDockSiteInfo.LastRelativeDockToBar = bar;
                        prevBar.m_LastDockSiteInfo.LastRelativeDocumentId = doc.Id;
                    }
                    bar.m_LastDockSiteInfo.LastRelativeDocumentId = prevBarDocument.Id;
                    if (dockParent.Orientation == eOrientation.Horizontal)
                    {
                        bar.LastDockSide = eDockSide.Right;
                        if (prevBar != null) prevBar.LastDockSide = eDockSide.Left;
                    }
                    else
                    {
                        bar.LastDockSide = eDockSide.Bottom;
                        if (prevBar != null) prevBar.LastDockSide = eDockSide.Top;
                    }
                }
            }
            else
            {
                Bar nextBar = null;
                if (nextBarDocument is DocumentBarContainer)
                {
                    nextBar = ((DocumentBarContainer)nextBarDocument).Bar;
                    bar.m_LastDockSiteInfo.LastRelativeDockToBar = nextBar;
                    nextBar.m_LastDockSiteInfo.LastRelativeDockToBar = bar;
                    nextBar.m_LastDockSiteInfo.LastRelativeDocumentId = doc.Id;
                }
                bar.m_LastDockSiteInfo.LastRelativeDocumentId = nextBarDocument.Id;
                if (dockParent.Orientation == eOrientation.Horizontal)
                {
                    bar.LastDockSide = eDockSide.Left;
                    if (nextBar != null) nextBar.LastDockSide = eDockSide.Right;
                }
                else
                {
                    bar.LastDockSide = eDockSide.Top;
                    if (nextBar != null) nextBar.LastDockSide = eDockSide.Bottom;
                }
            }
            if (GetDockSide(bar) != eDockSide.None)
                bar.m_LastDockSiteInfo.LastDockSiteSide = GetDockSide(bar);
        }
        private eDockSide GetDockSide(Bar bar)
        {
            if (bar.Parent == null)
                return eDockSide.None;
            else if (bar.Parent.Dock == DockStyle.Left)
                return eDockSide.Left;
            else if (bar.Parent.Dock == DockStyle.Right)
                return eDockSide.Right;
            else if (bar.Parent.Dock == DockStyle.Top)
                return eDockSide.Top;
            else if (bar.Parent.Dock == DockStyle.Bottom)
                return eDockSide.Bottom;
            else if (bar.Parent.Dock == DockStyle.Fill)
                return eDockSide.Document;
            return eDockSide.None;
        }
        [EditorBrowsable(EditorBrowsableState.Never)]
		public void UnDock(Bar barToUnDock, bool removeFromContainer)
		{
			DocumentBarContainer doc=m_DocumentDockContainer.GetBarDocumentContainer(barToUnDock);
            if (barToUnDock.DockSide != eDockSide.None) barToUnDock.LastDockSide = barToUnDock.DockSide;
            if (doc != null)
                SaveLastDockInfo(barToUnDock, doc, barToUnDock.m_LastDockSiteInfo);
            
            int containerSizeReduction = 0;
            // Calculate the size reduction of container if needed
            if (doc != null && m_Container != null && m_Container.Dock != DockStyle.Fill)
            {
                if (m_Container.Dock == DockStyle.Left || m_Container.Dock == DockStyle.Right)
                {
                    if (doc.Parent != null && doc.Parent == m_DocumentDockContainer && m_DocumentDockContainer.Orientation == eOrientation.Horizontal)
                        containerSizeReduction = barToUnDock.Width + Dpi.Width(m_DocumentDockContainer.SplitterSize);
                }
                else if (m_Container.Dock == DockStyle.Top || m_Container.Dock == DockStyle.Bottom)
                {
                    if (doc.Parent != null && doc.Parent == m_DocumentDockContainer && m_DocumentDockContainer.Orientation == eOrientation.Vertical)
                        containerSizeReduction = barToUnDock.Height + Dpi.Width(m_DocumentDockContainer.SplitterSize);
                }
            }
            if(doc==null)
            {
                if (removeFromContainer && barToUnDock.Parent == m_Container)
                    m_Container.Controls.Remove(barToUnDock);
				RestoreBarStyle(barToUnDock);
                return;
            }
			
			DocumentDockContainer parent=doc.Parent as DocumentDockContainer;
			if(parent!=null)
			{
				parent.Documents.Remove(doc);
				if(parent!=m_DocumentDockContainer)
					RemoveEmptyContainers(parent);
				else if(parent.Documents.Count==1 && parent.Documents[0] is DocumentDockContainer)
					RemoveEmptyContainers(parent.Documents[0] as DocumentDockContainer);
			}
			if(m_Container!=null)
			{
				if(removeFromContainer)
					m_Container.Controls.Remove(barToUnDock);
				RestoreBarStyle(barToUnDock);
                bool isLoadingLayout = false;
                if (m_Container.Owner != null) isLoadingLayout = m_Container.Owner.IsLoadingLayout;
                if (!isLoadingLayout && !m_Container.IsAnyControlVisible)
                {
                    if (m_Container.Dock == DockStyle.Left || m_Container.Dock == DockStyle.Right)
                        m_Container.Width = 0;
                    else if (m_Container.Dock == DockStyle.Top || m_Container.Dock == DockStyle.Bottom)
                        m_Container.Height = 0;
                }
                else if (!isLoadingLayout && containerSizeReduction != 0)
                {
                    if (m_Container.Dock == DockStyle.Left || m_Container.Dock == DockStyle.Right)
                        m_Container.Width -= containerSizeReduction;
                    else if (m_Container.Dock == DockStyle.Top || m_Container.Dock == DockStyle.Bottom)
                        m_Container.Height -= containerSizeReduction;
                }
                else
                    m_Container.RecalcLayout();
			}
			else
				RestoreBarStyle(barToUnDock);
		}
		private void RemoveEmptyContainers(DocumentDockContainer parent)
		{
			while(parent.Documents.Count==0 && parent.Parent!=null && parent.Parent is DocumentDockContainer ||
				parent.Parent!=null && parent.Parent is DocumentDockContainer && (((DocumentDockContainer)parent.Parent).Documents.Count==1 ||
                   parent.Documents.Count == 1))
			{
				if(parent.Parent!=null && parent.Parent is DocumentDockContainer && ((DocumentDockContainer)parent.Parent).Documents.Count==1)
				{
					// Removes the instances where DocumentDockContainer hosts another one and only one DocumentDockContainer object
					DocumentDockContainer p=parent.Parent as DocumentDockContainer;
                    p.Orientation = parent.Orientation;
                    p.Documents.Remove(parent);
					DocumentBaseContainer[] documents=new DocumentBaseContainer[parent.Documents.Count];
					parent.Documents.CopyTo(documents);
					p.Documents.AddRange(documents);
					parent=p;
				}
                else if (parent.Parent != null && parent.Parent is DocumentDockContainer && parent.Documents.Count == 1)
                {
                    DocumentDockContainer p = parent.Parent as DocumentDockContainer;
                    int index = p.Documents.IndexOf(parent);
                    p.Documents.Remove(parent);
                    DocumentBaseContainer document = parent.Documents[0];
                    p.Documents.Insert(index, document);
                    parent = p;
                }
				else
				{
					DocumentDockContainer p=parent.Parent as DocumentDockContainer;
					p.Documents.Remove(parent);
					parent=p;
				}
			}
		}
		private void ApplyBarStyle(Bar bar)
		{
			if(m_Container!=null && m_Container.Owner!=null && m_Container.Owner.ApplyDocumentBarStyle && m_Container.Dock == DockStyle.Fill)
			{
				BarFunctions.ApplyAutoDocumentBarStyle(bar);
			}
		}
		private void RestoreBarStyle(Bar bar)
		{
            if (m_Container != null && m_Container.Owner != null && m_Container.Owner.ApplyDocumentBarStyle && m_Container.Dock == DockStyle.Fill)
			{
				BarFunctions.RestoreAutoDocumentBarStyle(bar);
			}
		}
		private DocumentBarContainer CreateDocumentBarContainer(Bar bar)
		{
			DocumentBarContainer doc=new DocumentBarContainer(bar);
			return doc;
		}
		private DocumentDockContainer CreateDocumentDockContainer()
		{
			DocumentDockContainer dock=new DocumentDockContainer();
			return dock;
		}
		#endregion
		#region Mouse Resize Handling
        /// 
        /// Gets whether document/bar is being resized.
        /// 
        public bool IsResizingDocument
        {
            get
            {
                return (m_ResizeDocument != null);
            }
        }
		/// 
		/// Processes OnMouseMove events from DockSite. This routine assumes that mouse messages are received only when mouse is actually over
		/// the dock site and not containing bars. This is significant because it will receive messages only if mouse is over the splitter
		/// space between bars.
		/// 
		/// Mouse event arguments.
		public void OnMouseMove(MouseEventArgs e)
		{
			int x=e.X,y=e.Y;
			if(e.Button==MouseButtons.None)
			{
				Cursor c=this.GetCursor(x,y);
				if(c==null)
				{
					if(m_ContainerCursor!=null)
						this.Container.Cursor=m_ContainerCursor;
					m_ContainerCursor=null;
				}
				else
				{
					if(m_ContainerCursor==null)
						m_ContainerCursor=this.Container.Cursor;
					this.Container.Cursor=c;
				}
			}
			else if(e.Button==MouseButtons.Left)
			{
				Point p=GetResizeToPoint(x,y);
				if(p.IsEmpty)
					return;
				if(!m_ResizePreview)
					SplitterMouseMove(p.X,p.Y);
				else
				{
					ResizeTo(p.X,p.Y);
					m_MouseDownPoint=p;
				}
			}
		}
        [EditorBrowsable(EditorBrowsableState.Never)]
		public Cursor GetCursor(int x, int y)
		{
			Cursor c=null;
			DocumentDockContainer context=this.GetContainerFromRoot(x,y);
			if(context!=null)
			{
				if(context.Orientation==eOrientation.Horizontal)
					c=Cursors.VSplit;
				else if(context.Orientation==eOrientation.Vertical)
					c=Cursors.HSplit;
			}
            else if (m_Container != null && m_Container.Dock != DockStyle.Fill)
            {
                if(m_Container.Dock == DockStyle.Top || m_Container.Dock == DockStyle.Bottom)
                    c = Cursors.HSplit;
                else if (m_Container.Dock == DockStyle.Left || m_Container.Dock == DockStyle.Right)
                    c = Cursors.VSplit;
            }
			return c;
		}
		public void OnMouseDown(MouseEventArgs e)
		{
			int x=e.X, y=e.Y;
			if(e.Button==MouseButtons.Left)
			{
				m_MouseDownPoint=new Point(x,y);
				DocumentDockContainer context=this.GetContainerFromRoot(x,y);
                
                if(context!=null)
				{
					m_ResizeDocument=this.GetClosestDocument(context,x,y);
					if(m_ResizeDocument==null)
						return;
					m_ResizeDockContainer=context;
					if(!m_ResizePreview)
					{
						CreateSplitter();
						SplitterMouseMove(x,y);
					}
				}
                else if (m_Container != null && m_Container.Dock != DockStyle.Fill)
                {
                    m_ResizeDockContainer = m_DocumentDockContainer;
                    if (!m_ResizePreview)
                    {
                        CreateSplitter();
                        SplitterMouseMove(x, y);
                    }
                }
			}
		}
		public void OnMouseUp(MouseEventArgs e)
		{
			if(m_ResizeDockContainer!=null && !m_MouseDownPoint.IsEmpty)
			{
				ResizeTo(e.X,e.Y);
			}
			m_MouseDownPoint=Point.Empty;
			m_ResizeDockContainer=null;
			m_ResizeDocument=null;
			DestroySplitter();
		}
		public void OnMouseLeave()
		{
			if(m_ContainerCursor!=null)
				this.Container.Cursor=m_ContainerCursor;
			m_ContainerCursor=null;
		}
		private DocumentBaseContainer GetClosestDocument(DocumentDockContainer parent, int x, int y)
		{
			DocumentBaseContainer ret=null;
			eOrientation orientation=parent.Orientation;
			foreach(DocumentBaseContainer doc in parent.Documents)
			{
				if(orientation==eOrientation.Horizontal && doc.DisplayBounds.X>x && doc.Visible)
                    break;
                else if(orientation==eOrientation.Vertical && doc.DisplayBounds.Y>y && doc.Visible)
					break;
                if(doc.Visible)
				    ret=doc;
			}
			return ret;
		}
		/// 
		/// Returns reference to the DocumentDockContainer that contains specified coordinates. Searches through the Documents collection first.
		/// 
		/// X coordinate
		/// Y coordinate
		/// 
		private DocumentDockContainer GetContainerFromRoot(int x, int y)
		{
			return GetContainer(m_DocumentDockContainer,x,y);
		}
		private DocumentDockContainer GetContainer(DocumentDockContainer parent, int x, int y)
		{
			if(parent==null || !parent.DisplayBounds.Contains(x,y) || !parent.Visible)
				return null;
			DocumentDockContainer ret=null;
			foreach(DocumentBaseContainer doc in parent.Documents)
			{
				if(doc is DocumentDockContainer)
				{
					ret=this.GetContainer((DocumentDockContainer)doc,x,y);
					if(ret!=null)
						break;
				}
			}
            if (ret == null)
                ret = parent;
			return ret;
		}
		
		private void CreateSplitter()
		{
            if (m_ResizeDockContainer == null)
				return;
			if(m_Splitter==null)
				m_Splitter=BarFunctions.CreateOutlineForm();
		}
		private void SplitterMouseMove(int x, int y)
		{
			if(m_Splitter==null || m_ResizeDockContainer==null)
				return;
			
            Rectangle splitterBounds=Rectangle.Empty;
			// Set splitter size
		    int splitterWidth = Dpi.Width(m_SplitterWidth);
		    if (m_ResizeDockContainer.Orientation == eOrientation.Horizontal && m_ResizeDocument != null || 
                m_ResizeDocument == null && (m_Container.Dock == DockStyle.Left || m_Container.Dock == DockStyle.Right))
			{
				Point p=m_Container.PointToScreen(new Point(x-splitterWidth/2,m_ResizeDockContainer.DisplayBounds.Y));
				splitterBounds.X=p.X;
				splitterBounds.Y=p.Y;
				splitterBounds.Height=m_ResizeDockContainer.DisplayBounds.Height;
				splitterBounds.Width=splitterWidth;
			}
            else if (m_ResizeDockContainer.Orientation == eOrientation.Vertical && m_ResizeDocument != null || 
                m_ResizeDocument == null && (m_Container.Dock == DockStyle.Bottom || m_Container.Dock == DockStyle.Top))
			{
				Point p=m_Container.PointToScreen(new Point(m_ResizeDockContainer.DisplayBounds.X,y-splitterWidth/2));
				splitterBounds.X=p.X;
				splitterBounds.Y=p.Y;
				splitterBounds.Width=m_ResizeDockContainer.DisplayBounds.Width;
				splitterBounds.Height=splitterWidth;
			}
			NativeFunctions.SetWindowPos(m_Splitter.Handle,new IntPtr(NativeFunctions.HWND_TOP),splitterBounds.X,splitterBounds.Y,splitterBounds.Width,splitterBounds.Height,NativeFunctions.SWP_SHOWWINDOW | NativeFunctions.SWP_NOACTIVATE);
		}
		private void DestroySplitter()
		{
			if(m_Splitter!=null)
			{
				m_Splitter.Visible=false;
				m_Splitter.Dispose();
				m_Splitter=null;
			}
		}
        internal Size GetContainerMinimumSize(DocumentDockContainer dockContainer)
        {
            Size minimumSize = Size.Empty;
            foreach (DocumentBaseContainer d in dockContainer.Documents)
            {
                Size dm = Size.Empty;
                if (d is DocumentBarContainer)
                {
                    if (!((DocumentBarContainer)d).Visible) continue;
                    dm = d.MinimumSize;
                }
                else if (d is DocumentDockContainer)
                {
                    dm = GetContainerMinimumSize(d as DocumentDockContainer);
                }
                if (dockContainer.Orientation == eOrientation.Horizontal)
                {
                    minimumSize.Width += dm.Width + Dpi.Width(dockContainer.SplitterSize);
                    if (dm.Height < minimumSize.Height || minimumSize.Height == 0)
                        minimumSize.Height = dm.Height;
                }
                else
                {
                    minimumSize.Height += dm.Height + Dpi.Width(dockContainer.SplitterSize);
                    if (dm.Width < minimumSize.Width || minimumSize.Width == 0)
                        minimumSize.Width = dm.Width;
                }
            }
            if (minimumSize.Width > 0 && dockContainer.Orientation == eOrientation.Horizontal)
                minimumSize.Width += Dpi.Width(dockContainer.SplitterSize);
            else if (minimumSize.Height > 0 && dockContainer.Orientation == eOrientation.Vertical)
                minimumSize.Height += Dpi.Width(dockContainer.SplitterSize);
            if (minimumSize.Width == 0)
                minimumSize.Width = 32;
            if (minimumSize.Height == 0)
                minimumSize.Height = 32;
            return minimumSize;
        }
		private Point GetResizeToPoint(int x, int y)
		{
			if(m_ResizeDockContainer==null)
				return Point.Empty;
			Point resizeTo=new Point(x,y);
			int xDiff=x-m_MouseDownPoint.X;
			int yDiff=y-m_MouseDownPoint.Y;
            if (m_ResizeDocument == null)
            {
                // Resizing the dock site
                if (m_Container.Dock == DockStyle.Left || m_Container.Dock == DockStyle.Right)
                {
                    if (m_Container.Dock == DockStyle.Right) xDiff *= -1;
                    Size minimumSize = GetContainerMinimumSize(m_ResizeDockContainer);
                    if (m_ResizeDockContainer.DisplayBounds.Width + xDiff < minimumSize.Width)
                        resizeTo.X -= ((m_ResizeDockContainer.DisplayBounds.Width + xDiff) - minimumSize.Width) * ((m_Container.Dock == DockStyle.Right ? -1 : 1));
                    else
                    {
                        int clientWidth = GetClientWidth();
                        int minClientWidth = 32;
                        if (m_Container.Owner != null)
                            minClientWidth = m_Container.Owner.MinimumClientSize.Width;
                        if (clientWidth - xDiff < minClientWidth)
                            resizeTo.X -= (minClientWidth - (clientWidth - xDiff)) * ((m_Container.Dock == DockStyle.Right ? -1 : 1));
                    }
                    return resizeTo;
                }
                else if (m_Container.Dock == DockStyle.Top || m_Container.Dock == DockStyle.Bottom)
                {
                    if (m_Container.Dock == DockStyle.Bottom) yDiff *= -1;
                    Size minimumSize = GetContainerMinimumSize(m_ResizeDockContainer);
                    if (m_ResizeDockContainer.DisplayBounds.Height + yDiff < minimumSize.Height)
                        resizeTo.Y -= ((m_ResizeDockContainer.DisplayBounds.Height + yDiff) - minimumSize.Height) * ((m_Container.Dock == DockStyle.Bottom ? -1 : 1));
                    else
                    {
                        int clientHeight = GetClientHeight();
                        int minClientHeight = 32;
                        if (m_Container.Owner != null)
                            minClientHeight = m_Container.Owner.MinimumClientSize.Height;
                        
                        if (clientHeight - yDiff < minClientHeight)
                            resizeTo.Y -= (minClientHeight - (clientHeight - yDiff)) * ((m_Container.Dock == DockStyle.Bottom ? -1 : 1));
                    }
                    return resizeTo;
                }
                return Point.Empty;
            }
			else if(m_ResizeDockContainer.Orientation==eOrientation.Horizontal)
			{
				if(m_ResizeDocument.DisplayBounds.Width+xDiff>=m_ResizeDocument.MinimumSize.Width)
				{
					// Verify document next to it
					DocumentBaseContainer nextDoc=GetNextDocument(m_ResizeDockContainer,m_ResizeDockContainer.Documents.IndexOf(m_ResizeDocument));
					if(nextDoc!=null)
					{
						if(nextDoc.DisplayBounds.Width-xDiff=m_ResizeDocument.MinimumSize.Height)
				{
					DocumentBaseContainer nextDoc=GetNextDocument(m_ResizeDockContainer,m_ResizeDockContainer.Documents.IndexOf(m_ResizeDocument));
					if(nextDoc!=null)
					{
						if(nextDoc.DisplayBounds.Height-yDiff 0)
                    {
                        DocumentBaseContainer lastDoc = m_DocumentDockContainer.Documents[m_DocumentDockContainer.Documents.Count - 1];
                        int docWidth = lastDoc.DisplayBounds.Width + xDiff;
                        if (docWidth > lastDoc.MinimumSize.Width)
                            lastDoc.SetLayoutBounds(new Rectangle(lastDoc.DisplayBounds.X, lastDoc.DisplayBounds.Y, docWidth, lastDoc.DisplayBounds.Height));
						else
							ResetLayoutBounds(m_DocumentDockContainer);
                    }
                    m_Container.Width = m_Container.Width + xDiff;
					if(m_Container.Width <= this.GetContainerMinimumSize(m_DocumentDockContainer).Width)
						ResetLayoutBounds(m_DocumentDockContainer);
                }
                else if (m_Container.Dock == DockStyle.Right && xDiff != 0)
                {
                    if (m_DocumentDockContainer.Documents.Count > 0)
                    {
                        DocumentBaseContainer lastDoc = m_DocumentDockContainer.Documents[0];
                        int docWidth = lastDoc.DisplayBounds.Width - xDiff;
                        if (docWidth > lastDoc.MinimumSize.Width)
                            lastDoc.SetLayoutBounds(new Rectangle(lastDoc.DisplayBounds.X, lastDoc.DisplayBounds.Y, docWidth, lastDoc.DisplayBounds.Height));
                        else
                            ResetLayoutBounds(m_DocumentDockContainer);
                    }
                    m_Container.Width = m_Container.Width - xDiff;
					if(m_Container.Width <= this.GetContainerMinimumSize(m_DocumentDockContainer).Width)
						ResetLayoutBounds(m_DocumentDockContainer);
                }
                else if (m_Container.Dock == DockStyle.Top && yDiff != 0)
                {
                    if (m_DocumentDockContainer.Documents.Count > 0)
                    {
                        DocumentBaseContainer lastDoc = m_DocumentDockContainer.Documents[m_DocumentDockContainer.Documents.Count - 1];
                        int docHeight = lastDoc.DisplayBounds.Height + yDiff;
                        if (docHeight > lastDoc.MinimumSize.Height)
                            lastDoc.SetLayoutBounds(new Rectangle(lastDoc.DisplayBounds.X, lastDoc.DisplayBounds.Y, lastDoc.DisplayBounds.Width, docHeight));
                        else
                            ResetLayoutBounds(m_DocumentDockContainer);
                    }
                    m_Container.Height = m_Container.Height + yDiff;
					if(m_Container.Height <= this.GetContainerMinimumSize(m_DocumentDockContainer).Height)
						ResetLayoutBounds(m_DocumentDockContainer);
                }
                else if (m_Container.Dock == DockStyle.Bottom && yDiff != 0)
                {
                    if (m_DocumentDockContainer.Documents.Count > 0)
                    {
                        DocumentBaseContainer lastDoc = m_DocumentDockContainer.Documents[0];
                        int docHeight = lastDoc.DisplayBounds.Height - yDiff;
                        if (docHeight > lastDoc.MinimumSize.Height)
                            lastDoc.SetLayoutBounds(new Rectangle(lastDoc.DisplayBounds.X, lastDoc.DisplayBounds.Y, lastDoc.DisplayBounds.Width, docHeight));
                        else
                            ResetLayoutBounds(m_DocumentDockContainer);
                    }
                    m_Container.Height = m_Container.Height - yDiff;
					if(m_Container.Height <= this.GetContainerMinimumSize(m_DocumentDockContainer).Height)
						ResetLayoutBounds(m_DocumentDockContainer);
                }
                m_Container.ResumeLayout();
            }
			else if(m_ResizeDockContainer.Orientation==eOrientation.Horizontal && xDiff!=0)
			{
				m_ResizeDocument.SetWidth(m_ResizeDocument.DisplayBounds.Width+xDiff);
			}
            else if (m_ResizeDockContainer.Orientation == eOrientation.Vertical && yDiff != 0)
			{
				m_ResizeDocument.SetHeight(m_ResizeDocument.DisplayBounds.Height+yDiff);
			}
			m_Container.RecalcLayout();
            if (m_Container.Owner != null)
                ((IOwner)m_Container.Owner).InvokeUserCustomize(m_ResizeDocument, EventArgs.Empty);
		}
		private DocumentBaseContainer GetNextDocument(DocumentDockContainer parent, int refIndex)
		{
			int count=parent.Documents.Count;
			for(int i=refIndex+1;i= 0; i--)
            {
                if (parent.Documents[i].Visible)
                    return parent.Documents[i];
            }
            return null;
        }
		/// 
		/// Sets the width of the bar that is managed by this document layout. Width can be set only if parent container has
		/// Horizontal orientation. Note that bar minimum size is respected by this method and
		/// it will be enforced. If width is less than minimum width bar's width will be set to minimum width.
		/// 
		/// Reference to bar object.
		/// Desired width.
		public void SetBarWidth(Bar bar, int width)
		{
			DocumentBarContainer docBar=GetDocumentFromBar(bar) as DocumentBarContainer;
			if(docBar==null)
				return;
			if(docBar.Parent == m_DocumentDockContainer && (m_Container.Dock == DockStyle.Left || m_Container.Dock == DockStyle.Right)
				/*&& (m_DocumentDockContainer.Orientation == eOrientation.Vertical || m_DocumentDockContainer.Documents.Count == 1)*/)
			{
				m_Container.SuspendLayout();
				int diff = width;
				if(docBar.DisplayBounds.Width == 0)
					diff -= bar.GetBarDockedSize(eOrientation.Vertical);
				else
					diff -= docBar.DisplayBounds.Width;
                if (diff != 0)
                {
                    m_Container.Width += diff;
                    docBar.SetWidth(width);
                }
				//((DocumentDockContainer)docBar.Parent).SetWidth(width);
				m_Container.ResumeLayout(true);
			}
            else if (docBar.Parent is DocumentDockContainer && ((DocumentDockContainer)docBar.Parent).Orientation == eOrientation.Vertical)
            {
                ((DocumentDockContainer)docBar.Parent).SetWidth(width);
            }
            else
            {
                if (width < docBar.MinimumSize.Width)
                    width = docBar.MinimumSize.Width;
                docBar.SetWidth(width);
            }
			m_Container.RecalcLayout();
		}
		/// 
		/// Sets the height of the bar that is managed by this document layout. Height can be set only if parent container has
		/// vertical orientation. Note that bar minimum size is respected by this method and
		/// it will be enforced. If height is less than minimum height bar's height will be set to minimum height.
		/// 
		/// Reference to bar object.
		/// Desired height.
		public void SetBarHeight(Bar bar, int height)
		{
			DocumentBarContainer docBar=GetDocumentFromBar(bar) as DocumentBarContainer;
			if(docBar==null)
				return;
            if (m_Container!=null && (m_Container.Dock == DockStyle.Top || m_Container.Dock== DockStyle.Bottom) && 
                docBar.Parent == m_DocumentDockContainer
                /*&& (m_DocumentDockContainer.Orientation == eOrientation.Horizontal || m_DocumentDockContainer.Documents.Count == 1)*/)
            {
                //m_Container.Height += (height - bar.Height);
                //m_DocumentDockContainer.SetHeight(height);
                m_Container.SuspendLayout();
                int diff = height;
                if (docBar.DisplayBounds.Height == 0)
                    diff -= bar.GetBarDockedSize(eOrientation.Vertical);
                else
                    diff -= docBar.DisplayBounds.Height;
                m_Container.Height += diff;
                //((DocumentDockContainer)docBar.Parent).SetHeight(height);
                docBar.SetHeight(height);
                m_Container.ResumeLayout(true);
            }
            else if (docBar.Parent is DocumentDockContainer && ((DocumentDockContainer)docBar.Parent).Orientation == eOrientation.Horizontal)
            {
                ((DocumentDockContainer)docBar.Parent).SetHeight(height);
            }
            else
            {
                if (height < docBar.MinimumSize.Height)
                    height = docBar.MinimumSize.Height;
                docBar.SetHeight(height);
            }
			m_Container.RecalcLayout();
		}
		#endregion
		#region Serialization
		internal void SerializeDefinition(XmlElement parent)
		{
            XmlElement docs = null;
            if (m_Container.Dock == DockStyle.Fill)
                docs = parent.OwnerDocument.CreateElement(DocumentSerializationXml.Documents);
            else
            {
                docs = parent.OwnerDocument.CreateElement(DocumentSerializationXml.DockSite);
                docs.SetAttribute(DocumentSerializationXml.DockSiteSize, XmlConvert.ToString((m_Container.Dock == DockStyle.Left || m_Container.Dock == DockStyle.Right) ? m_Container.Width : m_Container.Height));
                docs.SetAttribute(DocumentSerializationXml.DockingSide, Enum.GetName(typeof(DockStyle), m_Container.Dock));
            }
			parent.AppendChild(docs);
			SerializeDocumentDockContainer(docs,m_DocumentDockContainer, true);
		}
		internal void SerializeLayout(XmlElement parent)
		{
            XmlElement docs = null;
            if (m_Container.Dock == DockStyle.Fill)
                docs = parent.OwnerDocument.CreateElement(DocumentSerializationXml.Documents);
            else
            {
                docs = parent.OwnerDocument.CreateElement(DocumentSerializationXml.DockSite);
                docs.SetAttribute(DocumentSerializationXml.DockSiteSize, XmlConvert.ToString((m_Container.Dock == DockStyle.Left || m_Container.Dock == DockStyle.Right) ? m_Container.Width : m_Container.Height));
                docs.SetAttribute(DocumentSerializationXml.DockingSide, Enum.GetName(typeof(DockStyle), m_Container.Dock));
                docs.SetAttribute(DocumentSerializationXml.OriginalDockSiteSize, XmlConvert.ToString(m_Container.OriginalSize));
            }
			parent.AppendChild(docs);
			SerializeDocumentDockContainer(docs,m_DocumentDockContainer,false);
		}
        private bool SerializeDocument(DocumentDockContainer instance)
        {
            if (instance.Documents.Count == 0) return false;
            foreach (DocumentBaseContainer doc in instance.Documents)
            {
                DocumentBarContainer bar = doc as DocumentBarContainer;
                if (bar != null)
                {
                    if (bar.Bar != null && bar.Bar.SaveLayoutChanges) return true;
                }
                else
                    return true;
            }
            return false;
        }
		private void SerializeDocumentDockContainer(XmlElement parent, DocumentDockContainer instance, bool definitionSerialization)
		{
            if (!SerializeDocument(instance))
				return;
            XmlElement document = null;
			
            document=parent.OwnerDocument.CreateElement(DocumentSerializationXml.DockContainer);
			parent.AppendChild(document);
			document.SetAttribute(DocumentSerializationXml.Orientation,XmlConvert.ToString((int)instance.Orientation));
            document.SetAttribute(DocumentSerializationXml.Width, instance.LayoutBounds.Width.ToString());
            document.SetAttribute(DocumentSerializationXml.Height, instance.LayoutBounds.Height.ToString());
			foreach(DocumentBaseContainer doc in instance.Documents)
			{
				if(doc is DocumentDockContainer)
                    SerializeDocumentDockContainer(document,(DocumentDockContainer)doc,definitionSerialization);
				else if(doc is DocumentBarContainer)
					SerializeDocumentBarContainer(document,(DocumentBarContainer)doc,definitionSerialization);
			}
		}
		private void SerializeDocumentBarContainer(XmlElement parent, DocumentBarContainer instance, bool definitionSerialization)
		{
			if(instance.Bar==null || !instance.Bar.SaveLayoutChanges)
				return;
            
			XmlElement barDocument=parent.OwnerDocument.CreateElement(DocumentSerializationXml.BarContainer);
			parent.AppendChild(barDocument);
			
			barDocument.SetAttribute(DocumentSerializationXml.Width,instance.LayoutBounds.Width.ToString());
			barDocument.SetAttribute(DocumentSerializationXml.Height,instance.LayoutBounds.Height.ToString());
			
			XmlElement barElement=parent.OwnerDocument.CreateElement(BarSerializationXml.Bar);
			barDocument.AppendChild(barElement);
			
			if(definitionSerialization)
				instance.Bar.Serialize(barElement);
			else
				instance.Bar.SerializeLayout(barElement);
		}
		internal void DeserializeLayout(XmlElement parent)
		{
            if (parent.Name != DocumentSerializationXml.Documents && parent.Name != DocumentSerializationXml.DockSite || m_LoadingLayout)
				return;
			m_LoadingLayout=true;
            ItemSerializationContext context = new ItemSerializationContext();
			try
			{
				foreach(XmlElement elem in parent.ChildNodes)
				{
					if(elem.Name==DocumentSerializationXml.DockContainer)
					{
                        context.ItemXmlElement = elem;
						DeserializeDocumentDockContainer(context,m_DocumentDockContainer,false);
						break;
					}
				}
			}
			finally
			{
				m_LoadingLayout=false;
			}
            if (parent.Name == DocumentSerializationXml.DockSite)
            {
                if (m_Container.Dock == DockStyle.Left || m_Container.Dock == DockStyle.Right)
                    m_Container.Width = XmlConvert.ToInt32(parent.GetAttribute(DocumentSerializationXml.DockSiteSize));
                else if (m_Container.Dock == DockStyle.Top || m_Container.Dock == DockStyle.Bottom)
                    m_Container.Height = XmlConvert.ToInt32(parent.GetAttribute(DocumentSerializationXml.DockSiteSize));
                if (parent.HasAttribute(DocumentSerializationXml.OriginalDockSiteSize))
                    m_Container.OriginalSize = XmlConvert.ToInt32(parent.GetAttribute(DocumentSerializationXml.OriginalDockSiteSize));
            }
			m_Container.RecalcLayout();
		}
		internal void DeserializeDefinition(ItemSerializationContext context)
		{
            XmlElement parent = context.ItemXmlElement;
            if ((parent.Name != DocumentSerializationXml.Documents && parent.Name != DocumentSerializationXml.DockSite) || m_LoadingLayout)
				return;
			m_LoadingLayout=true;
			try
			{
				foreach(XmlElement elem in parent.ChildNodes)
				{
					if(elem.Name==DocumentSerializationXml.DockContainer)
					{
                        context.ItemXmlElement = elem;
						DeserializeDocumentDockContainer(context,m_DocumentDockContainer,true);
						break;
					}
				}
                if (parent.HasAttribute(DocumentSerializationXml.DockSiteSize))
                {
                    if (m_Container.Dock == DockStyle.Left || m_Container.Dock == DockStyle.Right)
                        m_Container.Width = XmlConvert.ToInt32(parent.GetAttribute(DocumentSerializationXml.DockSiteSize));
                    else if (m_Container.Dock == DockStyle.Top || m_Container.Dock == DockStyle.Bottom)
                        m_Container.Height = XmlConvert.ToInt32(parent.GetAttribute(DocumentSerializationXml.DockSiteSize));
                }
			}
			finally
			{
				m_LoadingLayout=false;
			}
			m_Container.RecalcLayout();
		}
		private void DeserializeDocumentDockContainer(ItemSerializationContext context, DocumentDockContainer instance, bool deserializeDefinition)
		{
            XmlElement docElement = context.ItemXmlElement;
			if(docElement.Name!=DocumentSerializationXml.DockContainer)
				return;
			instance.Documents.Clear();
			instance.Orientation=(eOrientation)XmlConvert.ToInt32(docElement.GetAttribute(DocumentSerializationXml.Orientation));
            if (docElement.HasAttribute(DocumentSerializationXml.Width) && docElement.HasAttribute(DocumentSerializationXml.Height))
            {
                instance.SetLayoutBounds(new Rectangle(0,0,
                    XmlConvert.ToInt32(docElement.GetAttribute(DocumentSerializationXml.Width)),
                    XmlConvert.ToInt32(docElement.GetAttribute(DocumentSerializationXml.Height))));
            }
			foreach(XmlElement elem in docElement.ChildNodes)
			{
				bool add=true;
				DocumentBaseContainer doc=DocumentSerializationXml.CreateDocument(elem.Name);
                context.ItemXmlElement = elem;
				if(doc is DocumentDockContainer)
					DeserializeDocumentDockContainer(context,(DocumentDockContainer)doc,deserializeDefinition);
				else if(doc is DocumentBarContainer)
                    add=DeserializeDocumentBarContainer(context,(DocumentBarContainer)doc,deserializeDefinition);
				if(add)
					instance.Documents.Add(doc);
			}
		}
		private bool DeserializeDocumentBarContainer(ItemSerializationContext context, DocumentBarContainer instance, bool deserializeDefinition)
		{
            XmlElement docElement = context.ItemXmlElement;
			if(docElement.Name!=DocumentSerializationXml.BarContainer)
				return false;
			
			instance.SetLayoutBounds(new Rectangle(0,0,XmlConvert.ToInt32(docElement.GetAttribute(DocumentSerializationXml.Width)),XmlConvert.ToInt32(docElement.GetAttribute(DocumentSerializationXml.Height))));
			
			foreach(XmlElement elem in docElement.ChildNodes)
			{
				if(elem.Name==BarSerializationXml.Bar)
				{
					instance.Bar=m_Container.Owner.Bars[elem.GetAttribute(BarSerializationXml.Name)];
					if(deserializeDefinition || instance.Bar==null && elem.HasAttribute(BarSerializationXml.Custom) && XmlConvert.ToBoolean(elem.GetAttribute(BarSerializationXml.Custom)))
					{
						// New bar that user has created try to deserialize but if it does not have items ignore it
						instance.Bar=new Bar();
						m_Container.Owner.Bars.Add(instance.Bar);
						if(deserializeDefinition)
							instance.Bar.Deserialize(elem, context);
						else
							instance.Bar.DeserializeLayout(elem);
						if(instance.Bar.Items.Count==0 && !deserializeDefinition)
						{
							m_Container.Owner.Bars.Remove(instance.Bar);
							return false;
						}
						return true;
					}
                    if (instance.Bar != null)
                    {
                        instance.Bar.DeserializeLayout(elem);
                        // Restore hidden dock container size so it can be used when bar is shown
                        if (!instance.Bar.IsVisible)
                        {
                            if (instance.LayoutBounds.Height > 0 && (instance.Bar.DockSide == eDockSide.Top || instance.Bar.DockSide == eDockSide.Bottom))
                            {
                                instance.Bar.Height = instance.LayoutBounds.Height;
                            }
                            else if (instance.LayoutBounds.Width > 0 && (instance.Bar.DockSide == eDockSide.Left || instance.Bar.DockSide == eDockSide.Right))
                            {
                                instance.Bar.Width = instance.LayoutBounds.Width;
                            }
                        }
                    }
                    else
                        return false;
					break;
				}
			}
			return true;
		}
		
		#endregion
	}
}