using System;
using System.Drawing;
namespace DevComponents.DotNetBar
{
	/// 
	/// Provides layout for Explorer-Bar control.
	/// 
	[System.ComponentModel.ToolboxItem(false),System.ComponentModel.DesignTimeVisible(false)]
	public class ExplorerBarContainerItem:ImageItem,IDesignTimeProvider
	{
		#region Internal Implementation
		internal int m_ItemSpacing=15;
		/// 
		/// Creates new instance of ExplorerBarContainerItem class.
		/// 
		public ExplorerBarContainerItem()
		{
			m_IsContainer=true;
			m_SystemItem=true;
			m_SupportedOrientation=eSupportedOrientation.Horizontal;
			m_AllowOnlyOneSubItemExpanded=false;
		}
		/// 
		/// Returns copy of ExplorerBarContainerItem item
		/// 
		public override BaseItem Copy()
		{
			ExplorerBarContainerItem objCopy=new ExplorerBarContainerItem();
			this.CopyToItem(objCopy);
			return objCopy;
		}
		protected override void CopyToItem(BaseItem copy)
		{
			ExplorerBarContainerItem objCopy=copy as ExplorerBarContainerItem;
			base.CopyToItem(objCopy);
		}
		/// 
		/// Gets or sets a value indicating whether the item is expanded or not. For Popup items this would indicate whether the item is popped up or not.
		/// 
		[System.ComponentModel.Browsable(false),System.ComponentModel.DefaultValue(false),System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)]
		public override bool Expanded
		{
			get
			{
				return base.Expanded;
			}
			set
			{
				if(!value)
				{
					foreach(BaseItem item in m_SubItems)
					{
						if(item is ExplorerBarGroupItem)
						{
							foreach(BaseItem popup in item.SubItems)
							{
								if(popup is PopupItem && item.Expanded)
									popup.Expanded=false;
							}
						}
					}
				}
				base.Expanded=value;
			}
		}
		/// 
		/// Recalculates the size of the item
		/// 
		public override void RecalcSize()
		{
			// Explorer Container can have none or one or more panels expanded at a time
			// The Control itself is displaying the scroll-bars and handling the
			// case when this container is oversized. It is only possible to have
			// vertical oversize. The items are always made to fit horizontally
			int iY=m_Rect.Top;
			if(m_SubItems!=null)
			{
				foreach(BaseItem item in m_SubItems)
				{
					if(item.Visible)
					{
						// Give it our maximum size
						item.WidthInternal=this.WidthInternal;
						item.HeightInternal=0;
						// Set item position
						item.LeftInternal=m_Rect.Left;
						item.TopInternal=iY;
						item.RecalcSize();
						if(item.WidthInternal!=this.WidthInternal)
							item.WidthInternal=this.WidthInternal;
						
						iY+=(item.HeightInternal+m_ItemSpacing);
						item.Displayed=true;
					}
				}
			}
			iY-=m_ItemSpacing;
			this.HeightInternal=iY;
			base.RecalcSize();
		}
		protected override void OnTopLocationChanged(int oldValue)
		{
			int iDiff=m_Rect.Top-oldValue;
			if(m_SubItems!=null)
			{
				foreach(BaseItem item in m_SubItems)
				{
					if(item.Visible)
					{
						// Set item position
						item.TopInternal+=iDiff;
					}
				}
			}
		}
		/// 
		/// Paints this base container
		/// 
		public override void Paint(ItemPaintArgs pa)
		{
			if(this.SuspendLayout)
				return;
			System.Drawing.Graphics g=pa.Graphics;
			if(m_NeedRecalcSize)
				RecalcSize();
			if(m_SubItems==null)
				return;
			foreach(BaseItem item in m_SubItems)
			{
				if(item.Visible && item.Displayed)
				{
                    if (item is ExplorerBarGroupItem)
                    {
                        if (((ExplorerBarGroupItem)item).WordWrapSubItems)
                        {
                            pa.ButtonStringFormat = pa.ButtonStringFormat & ~(pa.ButtonStringFormat & eTextFormat.SingleLine);
                            pa.ButtonStringFormat |= eTextFormat.WordBreak;
                        }
                        else
                        {
                            pa.ButtonStringFormat |= eTextFormat.SingleLine;
                            pa.ButtonStringFormat = pa.ButtonStringFormat & ~(pa.ButtonStringFormat & eTextFormat.WordBreak);
                        }
                    }
                    else
                    {
                        pa.ButtonStringFormat = pa.ButtonStringFormat & ~(pa.ButtonStringFormat & eTextFormat.SingleLine);
                        pa.ButtonStringFormat |= eTextFormat.WordBreak;
                    }
					item.Paint(pa);
				}
			}
		}
		[System.ComponentModel.Browsable(false)]
		public override eOrientation Orientation
		{
			get
			{
				return eOrientation.Horizontal;
			}
			set
			{
				return;
			}
		}
		/// 
		/// Occurs when the mouse pointer is over the item and a mouse button is pressed. This is used by internal implementation only.
		/// 
		[System.ComponentModel.Browsable(false),System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
		public override void InternalMouseDown(System.Windows.Forms.MouseEventArgs objArg)
		{
			base.InternalMouseDown(objArg);
			if(this.DesignMode)
			{
				if(this.ItemAtLocation(objArg.X,objArg.Y)==null)
				{
					IOwner owner=this.GetOwner() as IOwner;
					if(owner!=null)
						owner.SetFocusItem(null);
				}
			}
		}
		/// 
		/// Occurs when the mouse pointer is over the item and a mouse button is released. This is used by internal implementation only.
		/// 
		[System.ComponentModel.Browsable(false),System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
		public override void InternalMouseUp(System.Windows.Forms.MouseEventArgs objArg)
		{
			if(m_HotSubItem!=null)
			{
				m_HotSubItem.InternalMouseUp(objArg);
			}
			else
				base.InternalMouseUp(objArg);
		}
		/// 
		/// Sets input focus to next visible item in Explorer Bar.
		/// 
		/// True if focus was set to next visible item otherwise false.
		public bool FocusNextItem()
		{
			bool bBaseCall=true;
			
			BaseItem focusItem=((IOwner)this.GetOwner()).GetFocusItem();
			bool bFocusNext=false;
			if(focusItem==null)
				bFocusNext=true;
			int iLoopCount=0;
			while(iLoopCount<2)
			{
				foreach(BaseItem item in this.SubItems)
				{
					if(item==focusItem)
						bFocusNext=true;
					else if(item.Visible && bFocusNext) 
					{
						((IOwner)this.GetOwner()).SetFocusItem(item);
						iLoopCount=2;
						bBaseCall=false;
						break;
					}
					if(item.Expanded && item.Visible)
					{
						foreach(BaseItem child in item.SubItems)
						{
							if(child==focusItem)
								bFocusNext=true;
							else if(item.Visible && bFocusNext) 
							{
								((IOwner)this.GetOwner()).SetFocusItem(child);
								iLoopCount=2;
								bBaseCall=false;
								break;
							}
						}
						if(iLoopCount==2)
							break;
					}
				}
				iLoopCount++;
			}				
			return bBaseCall;
		}
		/// 
		/// Sets input focus to previous visible item in Explorer Bar.
		/// 
		/// True if focus was set to previous visible item otherwise false.
		public bool FocusPreviousItem()
		{
			bool bBaseCall=true;
			
			BaseItem focusItem=((IOwner)this.GetOwner()).GetFocusItem();
			bool bFocusNext=false;
			if(focusItem==null)
				bFocusNext=true;
			int iLoopCount=0;
			while(iLoopCount<2)
			{
				for(int groupIndex=this.SubItems.Count-1;groupIndex>=0;groupIndex--)
				{
					BaseItem item=this.SubItems[groupIndex];
					
					if(item.Expanded && item.Visible)
					{
						for(int index=item.SubItems.Count-1;index>=0;index--)
						{
							BaseItem child=item.SubItems[index];
							if(child==focusItem)
								bFocusNext=true;
							else if(item.Visible && bFocusNext) 
							{
								((IOwner)this.GetOwner()).SetFocusItem(child);
								iLoopCount=2;
								bBaseCall=false;
								break;
							}
						}
						if(iLoopCount==2)
							break;
					}
					if(item==focusItem)
						bFocusNext=true;
					else if(item.Visible && bFocusNext) 
					{
						((IOwner)this.GetOwner()).SetFocusItem(item);
						iLoopCount=2;
						bBaseCall=false;
						break;
					}
				}
				iLoopCount++;
			}				
			return bBaseCall;
		}
		protected internal override void OnItemAdded(BaseItem item)
		{
			base.OnItemAdded(item);
			NeedRecalcSize=true;
			if(item is ExplorerBarGroupItem)
				((ExplorerBarGroupItem)item).VisualPropertyChanged();
			if(this.DesignMode)
			{
				//ExplorerBar bar=this.ContainerControl as ExplorerBar; 
				//this.Refresh();
				ExplorerBar bar=this.ContainerControl as ExplorerBar; 
				if(bar!=null)
					bar.RecalcLayout();
			}
		}
        protected internal override void OnAfterItemRemoved(BaseItem item, int itemIndex)
		{
			base.OnAfterItemRemoved(item, itemIndex);
			NeedRecalcSize=true;
			if(this.DesignMode)
			{
				ExplorerBar bar=this.ContainerControl as ExplorerBar; 
				if(bar!=null)
					bar.RecalcLayout();
				//this.Refresh();
			}
		}
		protected internal override void OnSubItemsClear()
		{
			base.OnSubItemsClear();
			NeedRecalcSize=true;
			if(this.DesignMode)
			{
				//this.Refresh();
				ExplorerBar bar=this.ContainerControl as ExplorerBar; 
				if(bar!=null)
					bar.RecalcLayout();
			}
		}
		internal bool _Animating=false;
		protected internal override void OnSubItemExpandChange(BaseItem objChildItem)
		{
			base.OnSubItemExpandChange(objChildItem);
			ExplorerBar exbar=this.ContainerControl as ExplorerBar;
			try
			{
				if(exbar!=null && exbar.AnimationEnabled)
				{
					TimeSpan totalAnimationTime = new TimeSpan(0, 0, 0, 0, exbar.AnimationTime);
					_Animating=true;
					int iStep=1;
					DateTime startTime=DateTime.Now;
					if(objChildItem.Expanded)
					{
						int initalHeight=objChildItem.HeightInternal;
						objChildItem.RecalcSize();
						int targetHeight=objChildItem.HeightInternal;
						for(int i=initalHeight;itargetHeight;i-=iStep)
						{
							DateTime startPerMove = DateTime.Now;
							objChildItem.HeightInternal=i;
							foreach(BaseItem item in objChildItem.SubItems)
							{
								if(!objChildItem.DisplayRectangle.Contains(item.DisplayRectangle))
									item.Displayed=false;
								else
									item.Displayed=true;
							}
							for(int pos=this.SubItems.IndexOf(objChildItem)+1;pos