using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Data;
using System.Windows.Forms;

using BSE.Windows.Forms.Properties;

namespace BSE.Windows.Forms
{
    #region Class XPanderPanelList
	/// <summary>
	/// Manages a related set of xpanderpanels.
	/// </summary>
    /// <remarks>
    /// The XPanderPanelList contains XPanderPanels, which are represented by XPanderPanel
    /// objects that you can add through the XPanderPanels property.
    /// The order of XPanderPanel objects reflects the order the xpanderpanels appear
    /// in the XPanderPanelList control.
    /// </remarks>
	/// <copyright>Copyright © 2006-2008 Uwe Eichkorn
    /// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
    /// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
    /// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
    /// PURPOSE. IT CAN BE DISTRIBUTED FREE OF CHARGE AS LONG AS THIS HEADER 
    /// REMAINS UNCHANGED.
    /// </copyright>
    [Designer(typeof(XPanderPanelListDesigner)),
	DesignTimeVisibleAttribute(true)]
	[ToolboxBitmap(typeof(System.Windows.Forms.Panel))]
	public partial class XPanderPanelList : ScrollableControl
    {
        #region Events
        /// <summary>
        /// The PanelStyleChanged event occurs when PanelStyle flags have been changed.
        /// </summary>
        [Description("The PanelStyleChanged event occurs when PanelStyle flags have been changed.")]
        public event EventHandler<PanelStyleChangeEventArgs> PanelStyleChanged;
        /// <summary>
        /// The CaptionStyleChanged event occurs when CaptionStyle flags have been changed.
        /// </summary>
        [Description("The CaptionStyleChanged event occurs when CaptionStyle flags have been changed.")]
        public event EventHandler<EventArgs> CaptionStyleChanged;
        /// <summary>
        /// The ColorSchemeChanged event occurs when ColorScheme flags have been changed.
        /// </summary>
        [Description("The ColorSchemeChanged event occurs when ColorScheme flags have been changed.")]
        public event EventHandler<ColorSchemeChangeEventArgs> ColorSchemeChanged;
        /// <summary>
        /// Occurs when the value of the CaptionHeight property changes.
        /// </summary>
        [Description("Occurs when the value of the CaptionHeight property changes.")]
        public event EventHandler<EventArgs> CaptionHeightChanged;
        #endregion

        #region FieldsPrivate

        private bool m_bShowBorder;
        private bool m_bShowGradientBackground;
        private bool m_bShowExpandIcon;
        private bool m_bShowCloseIcon;
        private int m_iCaptionHeight;
        private LinearGradientMode m_linearGradientMode;
        private System.Drawing.Color m_colorGradientBackground;
        private CaptionStyle m_captionStyle;
		private BSE.Windows.Forms.PanelStyle m_ePanelStyle;
		private BSE.Windows.Forms.ColorScheme m_eColorScheme;
		private XPanderPanelCollection m_xpanderPanels;
        private PanelColors m_panelColors;

		#endregion

		#region Properties
		/// <summary>
		/// Gets the collection of xpanderpanels in this xpanderpanellist.
		/// </summary>
        /// <example>The following code example creates a XPanderPanel and adds it to the XPanderPanels collection,
        /// <code>
        /// private void btnAddXPanderPanel_Click(object sender, EventArgs e)
        /// {
        ///     if (xPanderPanelList3 != null)
        ///     {
        ///         // Create and initialize a XPanderPanel.
        ///         BSE.Windows.Forms.XPanderPanel xpanderPanel = new BSE.Windows.Forms.XPanderPanel();
        ///         xpanderPanel.Text = "new XPanderPanel";
        ///         // and add it to the XPanderPanels collection
        ///         xPanderPanelList3.XPanderPanels.Add(xpanderPanel);
        ///     }
        /// }
        /// </code>
        /// </example>
		[RefreshProperties(RefreshProperties.Repaint),
		Category("Collections"),
		Browsable(true),
		Description("Collection containing all the XPanderPanels for the xpanderpanellist.")]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		[Editor(typeof(XPanderPanelCollectionEditor), typeof(UITypeEditor))]
		public XPanderPanelCollection XPanderPanels
		{
			get { return this.m_xpanderPanels; }
		}
		/// <summary>
		/// Specifies the style of the panels in this xpanderpanellist.
		/// </summary>
		[Description("Specifies the style of the xpanderpanels in this xpanderpanellist."),
		DefaultValue(BSE.Windows.Forms.PanelStyle.Default),
		Category("Appearance")]
		public BSE.Windows.Forms.PanelStyle PanelStyle
		{
			get { return this.m_ePanelStyle; }
			set
			{
                if (value != this.m_ePanelStyle)
                {
                    this.m_ePanelStyle = value;
                    OnPanelStyleChanged(this, new PanelStyleChangeEventArgs(this.m_ePanelStyle));
                }
			}
		}
        /// <summary>
        /// Gets or sets the Panelcolors table.
        /// </summary>
        public PanelColors PanelColors
        {
            get { return this.m_panelColors; }
            set { this.m_panelColors = value; }
        }
		/// <summary>
		/// Specifies the colorscheme of the xpanderpanels in the xpanderpanellist
		/// </summary>
		[Description("The colorscheme of the xpanderpanels in the xpanderpanellist")]
        [DefaultValue(BSE.Windows.Forms.ColorScheme.Professional)]
        [Category("Appearance")]
		public ColorScheme ColorScheme
        {
            get { return this.m_eColorScheme; }
            set
            {
                if (value != this.m_eColorScheme)
                {
                    this.m_eColorScheme = value;
                    OnColorSchemeChanged(this, new ColorSchemeChangeEventArgs(this.m_eColorScheme));
                }
            }
        }
        /// <summary>
        /// Gets or sets the style of the captionbar.
        /// </summary>
        [Description("The style of the captionbar.")]
        [Category("Appearance")]
        public CaptionStyle CaptionStyle
        {
            get { return this.m_captionStyle; }
            set
            {
                this.m_captionStyle = value;
                OnCaptionStyleChanged(this, EventArgs.Empty);
            }
        }
		/// <summary>
		/// LinearGradientMode of the background in the xpanderpanellist 
		/// </summary>
		[Description("LinearGradientMode of the background in the xpanderpanellist"),
        DefaultValue(LinearGradientMode.Vertical),
        Category("Appearance")]
        public LinearGradientMode LinearGradientMode
        {
            get { return this.m_linearGradientMode; }
            set
            {
                if (value != this.m_linearGradientMode)
                {
                    this.m_linearGradientMode = value;
                    this.Invalidate(false);
                }
            }
        }
		/// <summary>
		/// Gets or sets a value indicating whether a xpanderpanellist's gradient background is shown. 
		/// </summary>
		[Description("Gets or sets a value indicating whether a xpanderpanellist's gradient background is shown."),
        DefaultValue(false),
        Category("Appearance")]
        public bool ShowGradientBackground
        {
            get { return this.m_bShowGradientBackground; }
            set
            {
                if (value != this.m_bShowGradientBackground)
                {
                    this.m_bShowGradientBackground = value;
                    this.Invalidate(false);
                }
            }
        }
		/// <summary>
		/// Gets or sets a value indicating whether a xpanderpanellist's border is shown
		/// </summary>
		[Description("Gets or sets a value indicating whether a xpanderpanellist's border is shown"),
        DefaultValue(true),
        Category("Appearance")]
        public bool ShowBorder
        {
            get { return this.m_bShowBorder; }
            set
            {
                if (value != this.m_bShowBorder)
                {
                    this.m_bShowBorder = value;
                    foreach (XPanderPanel xpanderPanel in this.XPanderPanels)
                    {
                        xpanderPanel.ShowBorder = this.m_bShowBorder;
                    }
                    this.Invalidate(false);
                }
            }
        }
        /// <summary>
        /// Gets or sets a value indicating whether the expand icon of the xpanderpanels in this xpanderpanellist are visible.
        /// </summary>
        [Description("Gets or sets a value indicating whether the expand icon of the xpanderpanels in this xpanderpanellist are visible."),
        DefaultValue(false),
        Category("Appearance")]
        public bool ShowExpandIcon
        {
            get { return this.m_bShowExpandIcon; }
            set
            {
                if (value != this.m_bShowExpandIcon)
                {
                    this.m_bShowExpandIcon = value;
                    foreach (XPanderPanel xpanderPanel in this.XPanderPanels)
                    {
                        xpanderPanel.ShowExpandIcon = this.m_bShowExpandIcon;
                    }
                }
            }
        }
        /// <summary>
        /// Gets or sets a value indicating whether the close icon of the xpanderpanels in this xpanderpanellist are visible.
        /// </summary>
        [Description("Gets or sets a value indicating whether the close icon of the xpanderpanels in this xpanderpanellist are visible."),
        DefaultValue(false),
        Category("Appearance")]
        public bool ShowCloseIcon
        {
            get { return this.m_bShowCloseIcon ; }
            set
            {
                if (value != this.m_bShowCloseIcon)
                {
                    this.m_bShowCloseIcon = value;
                    foreach (XPanderPanel xpanderPanel in this.XPanderPanels)
                    {
                        xpanderPanel.ShowCloseIcon = this.m_bShowCloseIcon;
                    }
                }
            }
        }
		/// <summary>
		/// Gradientcolor background in this xpanderpanellist
		/// </summary>
		[Description("Gradientcolor background in this xpanderpanellist"),
        DefaultValue(false),
        Category("Appearance")]
        public System.Drawing.Color GradientBackground
        {
            get { return this.m_colorGradientBackground; }
            set
            {
                if (value != this.m_colorGradientBackground)
                {
                    this.m_colorGradientBackground = value;
                    this.Invalidate(false);
                }
            }
        }
        /// <summary>
        /// Gets or sets the height of the XpanderPanels in this XPanderPanelList. 
        /// </summary>
        [Description("Gets or sets the height of the XpanderPanels in this XPanderPanelList. "),
        DefaultValue(25),
        Category("Appearance")]
        public int CaptionHeight
        {
            get { return m_iCaptionHeight; }
            set
            {
                if (value < Constants.CaptionMinHeight)
                {
                    throw new InvalidOperationException(
                        string.Format(
                        System.Globalization.CultureInfo.CurrentUICulture,
                        Resources.IDS_InvalidOperationExceptionInteger, value, "CaptionHeight", Constants.CaptionMinHeight));
                }
                this.m_iCaptionHeight = value;
                OnCaptionHeightChanged(this, EventArgs.Empty);
            }
        }
		#endregion

		#region MethodsPublic
		/// <summary>
		/// Initializes a new instance of the XPanderPanelList class.
		/// </summary>
		public XPanderPanelList()
		{
			// Dieser Aufruf ist für den Windows Form-Designer erforderlich.
			SetStyle(ControlStyles.DoubleBuffer, true);
			SetStyle(ControlStyles.ResizeRedraw, false);
			SetStyle(ControlStyles.UserPaint, true);
			SetStyle(ControlStyles.AllPaintingInWmPaint, true);
			SetStyle(ControlStyles.SupportsTransparentBackColor, true);
			
			InitializeComponent();

            this.m_xpanderPanels = new XPanderPanelCollection(this);
            
            this.ShowBorder = true;
            this.PanelStyle = PanelStyle.Default;
            this.LinearGradientMode = LinearGradientMode.Vertical;
            this.CaptionHeight = 25;
		}
		/// <summary>
        /// Expands the specified XPanderPanel
		/// </summary>
		/// <param name="panel">The XPanderPanel to expand</param>
        /// <example>
        /// <code>
        /// private void btnExpandXPander_Click(object sender, EventArgs e)
        /// {
        ///    // xPanderPanel10 is not null
        ///    if (xPanderPanel10 != null)
        ///    {
        ///        BSE.Windows.Forms.XPanderPanelList panelList = xPanderPanel10.Parent as BSE.Windows.Forms.XPanderPanelList;
        ///        // and it's parent panelList is not null
        ///        if (panelList != null)
        ///        {
        ///            // expands xPanderPanel10 in it's panelList.
        ///            panelList.Expand(xPanderPanel10);
        ///        }
        ///    }
        /// }
        /// </code>
        /// </example>
		public void Expand(BasePanel panel)
		{
			if (panel == null)
			{
				throw new ArgumentNullException("panel",
					string.Format(System.Globalization.CultureInfo.InvariantCulture,
					BSE.Windows.Forms.Properties.Resources.IDS_ArgumentException,
					"panel"));
			}

			XPanderPanel xpanderPanel = panel as XPanderPanel;
			if (xpanderPanel != null)
			{
				foreach (XPanderPanel tmpXPanderPanel in this.m_xpanderPanels)
				{
					if (tmpXPanderPanel.Equals(xpanderPanel) == false)
					{
						tmpXPanderPanel.Expand = false;
					}
				}
                PropertyDescriptor propertyDescriptor = TypeDescriptor.GetProperties(xpanderPanel)["Expand"];
                if (propertyDescriptor != null)
                {
                    propertyDescriptor.SetValue(xpanderPanel, true);
                }
			}
		}
		#endregion

		#region MethodsProtected
		/// <summary>
		/// Paints the background of the xpanderpanellist.
		/// </summary>
		/// <param name="pevent">A PaintEventArgs that contains information about the control to paint.</param>
		protected override void OnPaintBackground(PaintEventArgs pevent)
        {
			base.OnPaintBackground(pevent);
            if (this.m_bShowGradientBackground == true)
            {
                Rectangle rectangle = new Rectangle(0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height);
                using (LinearGradientBrush linearGradientBrush = new LinearGradientBrush(
                    rectangle,
                    this.BackColor,
                    this.GradientBackground,
                    this.LinearGradientMode))
                {
					pevent.Graphics.FillRectangle(linearGradientBrush, rectangle);
                }
            }
        }
		/// <summary>
		/// Raises the ControlAdded event.
		/// </summary>
		/// <param name="e">A ControlEventArgs that contains the event data.</param>
		protected override void OnControlAdded(System.Windows.Forms.ControlEventArgs e)
		{
			base.OnControlAdded(e);
			BSE.Windows.Forms.XPanderPanel xpanderPanel = e.Control as BSE.Windows.Forms.XPanderPanel;
			if (xpanderPanel != null)
			{
				if (xpanderPanel.Expand == true)
				{
					foreach (XPanderPanel tmpXPanderPanel in this.XPanderPanels)
					{
						if (tmpXPanderPanel != xpanderPanel)
						{
							tmpXPanderPanel.Expand = false;
							tmpXPanderPanel.Height = xpanderPanel.CaptionHeight;
						}
					}
				}
                xpanderPanel.Parent = this;
				xpanderPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
						| System.Windows.Forms.AnchorStyles.Right)));
				xpanderPanel.Left = this.Padding.Left;
				xpanderPanel.Width = this.ClientRectangle.Width
					- this.Padding.Left
					- this.Padding.Right;
                xpanderPanel.PanelStyle = this.PanelStyle;
                xpanderPanel.ColorScheme = this.ColorScheme;
                if (this.PanelColors != null)
                {
                    xpanderPanel.SetPanelProperties(this.PanelColors);
                }
                xpanderPanel.ShowBorder = this.ShowBorder;
                xpanderPanel.ShowCloseIcon = this.m_bShowCloseIcon;
                xpanderPanel.ShowExpandIcon = this.m_bShowExpandIcon;
                xpanderPanel.CaptionStyle = this.m_captionStyle;
                xpanderPanel.Top = this.GetTopPosition();
                xpanderPanel.PanelStyleChanged += new EventHandler<PanelStyleChangeEventArgs>(XpanderPanelPanelStyleChanged);
				xpanderPanel.ExpandClick += new EventHandler<EventArgs>(this.XPanderPanelExpandClick);
				xpanderPanel.CloseClick += new EventHandler<EventArgs>(this.XPanderPanelCloseClick);
			}
			else
			{
				throw new InvalidOperationException("Can only add BSE.Windows.Forms.XPanderPanel");
			}
		}
		/// <summary>
		/// Raises the ControlRemoved event.
		/// </summary>
		/// <param name="e">A ControlEventArgs that contains the event data.</param>
		protected override void OnControlRemoved(System.Windows.Forms.ControlEventArgs e)
		{
			base.OnControlRemoved(e);

			BSE.Windows.Forms.XPanderPanel xpanderPanel =
				e.Control as BSE.Windows.Forms.XPanderPanel;

			if (xpanderPanel != null)
			{
                xpanderPanel.PanelStyleChanged -= new EventHandler<PanelStyleChangeEventArgs>(XpanderPanelPanelStyleChanged);
				xpanderPanel.ExpandClick -= new EventHandler<EventArgs>(this.XPanderPanelExpandClick);
				xpanderPanel.CloseClick -= new EventHandler<EventArgs>(this.XPanderPanelCloseClick);
			}
		}
		/// <summary>
		/// Raises the Resize event.
		/// </summary>
		/// <param name="e">An EventArgs that contains the event data.</param>
		protected override void OnResize(System.EventArgs e)
		{
			base.OnResize(e);
			int iXPanderPanelCaptionHeight = 0;
			
			if (this.m_xpanderPanels != null)
			{
				foreach (XPanderPanel xpanderPanel in this.m_xpanderPanels)
				{
					xpanderPanel.Width = this.ClientRectangle.Width
						- this.Padding.Left
						- this.Padding.Right;
					if (xpanderPanel.Visible == false)
					{
						iXPanderPanelCaptionHeight -= xpanderPanel.CaptionHeight;
					}
					iXPanderPanelCaptionHeight += xpanderPanel.CaptionHeight;
				}

				foreach (XPanderPanel xpanderPanel in this.m_xpanderPanels)
				{
					if (xpanderPanel.Expand == true)
					{
						xpanderPanel.Height =
							this.Height
							- iXPanderPanelCaptionHeight
							- this.Padding.Top
							- this.Padding.Bottom
							+ xpanderPanel.CaptionHeight;
						return;
					}
				}
			}
		}
        /// <summary>
        /// Raises the PanelStyle changed event
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">A PanelStyleChangeEventArgs that contains the event data.</param>
        protected virtual void OnPanelStyleChanged(object sender, PanelStyleChangeEventArgs e)
        {
            PanelStyle panelStyle = e.PanelStyle;
            this.Padding = new System.Windows.Forms.Padding(0);

            foreach (XPanderPanel xpanderPanel in this.XPanderPanels)
            {
                PropertyDescriptorCollection propertyDescriptorCollection = TypeDescriptor.GetProperties(xpanderPanel);
                if (propertyDescriptorCollection.Count > 0)
                {
                    PropertyDescriptor propertyDescriptorPanelStyle = propertyDescriptorCollection["PanelStyle"];
                    if (propertyDescriptorPanelStyle != null)
                    {
                        propertyDescriptorPanelStyle.SetValue(xpanderPanel, panelStyle);
                    }
                    PropertyDescriptor propertyDescriptorLeft = propertyDescriptorCollection["Left"];
                    if (propertyDescriptorLeft != null)
                    {
                        propertyDescriptorLeft.SetValue(xpanderPanel, this.Padding.Left);
                    }
                    PropertyDescriptor propertyDescriptorWidth = propertyDescriptorCollection["Width"];
                    if (propertyDescriptorWidth != null)
                    {
                        propertyDescriptorWidth.SetValue(
                            xpanderPanel,
                            this.ClientRectangle.Width
                            - this.Padding.Left
                            - this.Padding.Right);
                    }

                }
            }
            if (this.PanelStyleChanged != null)
            {
                this.PanelStyleChanged(sender, e);
            }
        }
        /// <summary>
        /// Raises the ColorScheme changed event
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">A EventArgs that contains the event data.</param>
        protected virtual void OnColorSchemeChanged(object sender, ColorSchemeChangeEventArgs e)
        {
            ColorScheme eColorScheme = e.ColorSchema;
            foreach (XPanderPanel xpanderPanel in this.XPanderPanels)
            {
                PropertyDescriptor propertyDescriptor = TypeDescriptor.GetProperties(xpanderPanel)["ColorScheme"];
                if (propertyDescriptor != null)
                {
                    propertyDescriptor.SetValue(xpanderPanel, eColorScheme);
                }
            }
            if (this.ColorSchemeChanged != null)
            {
                this.ColorSchemeChanged(sender, e);
            }
        }
        /// <summary>
        /// Raises the CaptionHeight changed event
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">A EventArgs that contains the event data.</param>
        protected virtual void OnCaptionHeightChanged(object sender, EventArgs e)
        {
            foreach (XPanderPanel xpanderPanel in this.XPanderPanels)
            {
                PropertyDescriptor propertyDescriptor = TypeDescriptor.GetProperties(xpanderPanel)["CaptionHeight"];
                if (propertyDescriptor != null)
                {
                    propertyDescriptor.SetValue(xpanderPanel, this.m_iCaptionHeight);
                }
            }
            if (this.CaptionHeightChanged != null)
            {
                this.CaptionHeightChanged(sender, e);
            }
        }
        /// <summary>
        /// Raises the CaptionStyleChanged changed event
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">A EventArgs that contains the event data.</param>
        protected virtual void OnCaptionStyleChanged(object sender, EventArgs e)
        {
            foreach (XPanderPanel xpanderPanel in this.XPanderPanels)
            {
                PropertyDescriptor propertyDescriptor = TypeDescriptor.GetProperties(xpanderPanel)["CaptionStyle"];
                if (propertyDescriptor != null)
                {
                    propertyDescriptor.SetValue(xpanderPanel, this.m_captionStyle);
                }
            }
            if (this.CaptionStyleChanged != null)
            {
                this.CaptionStyleChanged(sender, e);
            }
        }
		#endregion

		#region MethodsPrivate

        private void XPanderPanelExpandClick(object sender, EventArgs e)
		{
			BSE.Windows.Forms.XPanderPanel xpanderPanel = sender as BSE.Windows.Forms.XPanderPanel;
            if (xpanderPanel != null)
			{
                this.Expand(xpanderPanel);
			}
		}

        private void XPanderPanelCloseClick(object sender, EventArgs e)
        {
            BSE.Windows.Forms.XPanderPanel xpanderPanel = sender as BSE.Windows.Forms.XPanderPanel;
            if (xpanderPanel != null)
            {
                this.Controls.Remove(xpanderPanel);
            }
        }

        private void XpanderPanelPanelStyleChanged(object sender, PanelStyleChangeEventArgs e)
        {
            PanelStyle panelStyle = e.PanelStyle;
            if (panelStyle != this.m_ePanelStyle)
            {
                this.PanelStyle = panelStyle;
            }
        }

        private int GetTopPosition()
        {
			int iTopPosition = this.Padding.Top;
			int iNextTopPosition = 0;

            //The next top position is the highest top value + that controls height, with a
            //little vertical spacing thrown in for good measure
            IEnumerator enumerator = this.XPanderPanels.GetEnumerator();
            while (enumerator.MoveNext())
            {
				XPanderPanel xpanderPanel = (XPanderPanel)enumerator.Current;

				if (xpanderPanel.Visible == true)
				{
					if (iNextTopPosition == this.Padding.Top)
					{
						iTopPosition = this.Padding.Top;
					}
					else
					{
						iTopPosition = iNextTopPosition;
					}
					iNextTopPosition = iTopPosition + xpanderPanel.Height;
				}
            }
			return iTopPosition;
        }
        #endregion
    }

    #endregion

    #region Class XPanderPanelListDesigner

    /// <summary>
    /// Extends the design mode behavior of a XPanderPanelList control that supports nested controls.
    /// </summary>
    internal class XPanderPanelListDesigner : System.Windows.Forms.Design.ParentControlDesigner
    {
        #region FieldsPrivate

        private Pen m_borderPen = new Pen(Color.FromKnownColor(KnownColor.ControlDarkDark));
        private XPanderPanelList m_xpanderPanelList;

        #endregion

        #region MethodsPublic
        /// <summary>
        /// nitializes a new instance of the XPanderPanelListDesigner class.
        /// </summary>
        public XPanderPanelListDesigner()
        {
            this.m_borderPen.DashStyle = DashStyle.Dash;
        }
		/// <summary>
		/// Initializes the designer with the specified component.
		/// </summary>
		/// <param name="component">The IComponent to associate with the designer.</param>
        public override void Initialize(System.ComponentModel.IComponent component)
        {
            base.Initialize(component);
            this.m_xpanderPanelList = (XPanderPanelList)this.Control;
            //Disable the autoscroll feature for the control during design time.  The control
            //itself sets this property to true when it initializes at run time.  Trying to position
            //controls in this control with the autoscroll property set to True is problematic.
            this.m_xpanderPanelList.AutoScroll = false;
        }
		/// <summary>
		/// This member overrides ParentControlDesigner.ActionLists
		/// </summary>
        public override DesignerActionListCollection ActionLists
        {
            get
            {
                // Create action list collection
                DesignerActionListCollection actionLists = new DesignerActionListCollection();

                // Add custom action list
                actionLists.Add(new XPanderPanelListDesignerActionList(this.Component));

                // Return to the designer action service
                return actionLists;
            }
        }

        #endregion

        #region MethodsProtected
        /// <summary>
        /// Releases the unmanaged resources used by the XPanderPanelDesigner,
        /// and optionally releases the managed resources. 
        /// </summary>
        /// <param name="disposing">true to release both managed and unmanaged resources;
        /// false to release only unmanaged resources.</param>
		protected override void Dispose(bool disposing)
		{
			try
			{
				if (disposing)
				{
					if (this.m_borderPen != null)
					{
						this.m_borderPen.Dispose();
					}
				}
			}
			finally
			{
				base.Dispose(disposing);
			}
		}
        /// <summary>
        /// Receives a call when the control that the designer is managing has painted its surface so the designer can
        /// paint any additional adornments on top of the xpanderpanel.
        /// </summary>
        /// <param name="e">A PaintEventArgs the designer can use to draw on the xpanderpanel.</param>
        protected override void OnPaintAdornments(PaintEventArgs e)
        {
            base.OnPaintAdornments(e);
            e.Graphics.DrawRectangle(this.m_borderPen, 0, 0, this.m_xpanderPanelList.Width - 2, this.m_xpanderPanelList.Height - 2);
        }

        #endregion
    }

    #endregion

    #region Class XPanderPanelListDesignerActionList

    /// <summary>
    /// Provides the class for types that define a list of items used to create a smart tag panel for the XPanderPanelList.
    /// </summary>
    public class XPanderPanelListDesignerActionList : DesignerActionList
	{
		#region Properties
		
		/// <summary>
		/// Gets a collecion of XPanderPanel objects
		/// </summary>
        [Editor(typeof(XPanderPanelCollectionEditor), typeof(UITypeEditor))]
		public XPanderPanelCollection XPanderPanels
		{
			get { return this.XPanderPanelList.XPanderPanels; }
		}
		/// <summary>
        /// Gets or sets the style of the panel.
		/// </summary>
        public PanelStyle PanelStyle
		{
			get { return this.XPanderPanelList.PanelStyle; }
			set { SetProperty("PanelStyle", value); }
		}
		/// <summary>
        /// Gets or sets the color schema which is used for the panel.
		/// </summary>
        public ColorScheme ColorScheme
        {
            get { return this.XPanderPanelList.ColorScheme; }
            set { SetProperty("ColorScheme", value); }
        }
        /// <summary>
        /// Gets or sets the style of the caption (not for PanelStyle.Aqua).
        /// </summary>
        public CaptionStyle CaptionStyle
        {
            get { return this.XPanderPanelList.CaptionStyle; }
            set { SetProperty("CaptionStyle", value); }
        }
        /// <summary>
        /// Gets or sets a value indicating whether the control shows a border.
        /// </summary>
        public bool ShowBorder
        {
            get { return this.XPanderPanelList.ShowBorder; }
            set { SetProperty("ShowBorder", value); }
        }
        /// <summary>
        /// Gets or sets a value indicating whether the expand icon is visible
        /// </summary>
        public bool ShowExpandIcon
        {
            get { return this.XPanderPanelList.ShowExpandIcon; }
            set { SetProperty("ShowExpandIcon", value); }
        }
        /// <summary>
        /// Gets or sets a value indicating whether the close icon is visible
        /// </summary>
        public bool ShowCloseIcon
        {
            get { return this.XPanderPanelList.ShowCloseIcon; }
            set { SetProperty("ShowCloseIcon", value); }
        }
		#endregion

		#region MethodsPublic
        /// <summary>
        /// Initializes a new instance of the XPanderPanelListDesignerActionList class.
        /// </summary>
        /// <param name="component">A component related to the DesignerActionList.</param>
		public XPanderPanelListDesignerActionList(System.ComponentModel.IComponent component)
            : base(component)
        {
            // Automatically display smart tag panel when
            // design-time component is dropped onto the
            // Windows Forms Designer
			base.AutoShow = true;
        }
        /// <summary>
        /// Returns the collection of DesignerActionItem objects contained in the list.
        /// </summary>
        /// <returns> A DesignerActionItem array that contains the items in this list.</returns>
        public override DesignerActionItemCollection GetSortedActionItems()
        {
            // Create list to store designer action items
            DesignerActionItemCollection actionItems = new DesignerActionItemCollection();

            actionItems.Add(
              new DesignerActionMethodItem(
                this,
                "ToggleDockStyle",
                GetDockStyleText(),
                "Design",
                "Dock or undock this control in it's parent container.",
                true));
            
            actionItems.Add(
                new DesignerActionPropertyItem(
                "ShowBorder",
                "Show Border",
                GetCategory(this.XPanderPanelList, "ShowBorder")));

            actionItems.Add(
                new DesignerActionPropertyItem(
                "ShowExpandIcon",
                "Show ExpandIcon",
                GetCategory(this.XPanderPanelList, "ShowExpandIcon")));

            actionItems.Add(
                new DesignerActionPropertyItem(
                "ShowCloseIcon",
                "Show CloseIcon",
                GetCategory(this.XPanderPanelList, "ShowCloseIcon")));
			
            actionItems.Add(
				new DesignerActionPropertyItem(
				"PanelStyle",
				"Select PanelStyle",
				GetCategory(this.XPanderPanelList, "PanelStyle")));

            actionItems.Add(
                new DesignerActionPropertyItem(
                "ColorScheme",
                "Select ColorScheme",
                GetCategory(this.XPanderPanelList, "ColorScheme")));

            actionItems.Add(
                new DesignerActionPropertyItem(
                "CaptionStyle",
                "Select CaptionStyle",
                GetCategory(this.XPanderPanelList, "CaptionStyle")));

            actionItems.Add(
			  new DesignerActionPropertyItem(
				"XPanderPanels",
				"Edit XPanderPanels",
				GetCategory(this.XPanderPanelList, "XPanderPanels")));
		
            return actionItems;
        }
        /// <summary>
        /// Dock/Undock designer action method implementation
        /// </summary>
        public void ToggleDockStyle()
        {
            // Toggle ClockControl's Dock property
            if (this.XPanderPanelList.Dock != DockStyle.Fill)
            {
                SetProperty("Dock", DockStyle.Fill);
            }
            else
            {
                SetProperty("Dock", DockStyle.None);
            }
        }

		#endregion

		#region MethodsPrivate
        /// <summary>
        /// Helper method that returns an appropriate display name for the Dock/Undock property,
		/// based on the ClockControl's current Dock property value
        /// </summary>
        /// <returns>the string to display</returns>
		private string GetDockStyleText()
        {
            if (this.XPanderPanelList.Dock == DockStyle.Fill)
            {
                return "Undock in parent container";
            }
            else
            {
                return "Dock in parent container";
            }
        }

        private XPanderPanelList XPanderPanelList
        {
            get { return (XPanderPanelList)this.Component; }
        }
		
        // Helper method to safely set a component’s property
        private void SetProperty(string propertyName, object value)
        {
            // Get property
            System.ComponentModel.PropertyDescriptor property
                = System.ComponentModel.TypeDescriptor.GetProperties(this.XPanderPanelList)[propertyName];
            // Set property value
            property.SetValue(this.XPanderPanelList, value);
        }
		// Helper method to return the Category string from a
		// CategoryAttribute assigned to a property exposed by 
		//the specified object
		private static string GetCategory(object source, string propertyName)
		{
			System.Reflection.PropertyInfo property = source.GetType().GetProperty(propertyName);
			CategoryAttribute attribute = (CategoryAttribute)property.GetCustomAttributes(typeof(CategoryAttribute), false)[0];
			if (attribute == null)
			{
				return null;
			}
			else
			{
				return attribute.Category;
			}
		}

		#endregion
	}

    #endregion

	#region Class XPanderPanelCollection

	/// <summary>
    /// Contains a collection of XPanderPanel objects.
	/// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1010:CollectionsShouldImplementGenericInterface")]
	public sealed class XPanderPanelCollection : IList,ICollection,IEnumerable
    {

        #region FieldsPrivate

        private XPanderPanelList m_xpanderPanelList;
		private Control.ControlCollection m_controlCollection;

        #endregion

        #region Constructor

		internal XPanderPanelCollection(XPanderPanelList xpanderPanelList)
        {
            this.m_xpanderPanelList = xpanderPanelList;
			this.m_controlCollection = this.m_xpanderPanelList.Controls;
        }

        #endregion

        #region Properties
		/// <summary>
		/// Gets or sets a XPanderPanel in the collection. 
		/// </summary>
        /// <param name="index">The zero-based index of the XPanderPanel to get or set.</param>
		/// <returns>The xPanderPanel at the specified index.</returns>
        public XPanderPanel this[int index]
        {
            get { return (XPanderPanel)this.m_controlCollection[index] as XPanderPanel; }
        }

        #endregion

        #region MethodsPublic
        /// <summary>
        /// Determines whether the XPanderPanelCollection contains a specific XPanderPanel
        /// </summary>
        /// <param name="xpanderPanel">The XPanderPanel to locate in the XPanderPanelCollection</param>
        /// <returns>true if the XPanderPanelCollection contains the specified value; otherwise, false.</returns>
        public bool Contains(XPanderPanel xpanderPanel)
        {
			return this.m_controlCollection.Contains(xpanderPanel);
        }
		/// <summary>
		/// Adds a XPanderPanel to the collection.  
		/// </summary>
		/// <param name="xpanderPanel">The XPanderPanel to add.</param>
        public void Add(XPanderPanel xpanderPanel)
        {
			this.m_controlCollection.Add(xpanderPanel);
			this.m_xpanderPanelList.Invalidate();

        }
        /// <summary>
        /// Removes the first occurrence of a specific XPanderPanel from the XPanderPanelCollection
        /// </summary>
        /// <param name="xpanderPanel">The XPanderPanel to remove from the XPanderPanelCollection</param>
        public void Remove(XPanderPanel xpanderPanel)
        {
			this.m_controlCollection.Remove(xpanderPanel);
        }
		/// <summary>
		/// Removes all the XPanderPanels from the collection. 
		/// </summary>
		public void Clear()
		{
			this.m_controlCollection.Clear();
		}
		/// <summary>
		/// Gets the number of XPanderPanels in the collection. 
		/// </summary>
		public int Count
		{
			get { return this.m_controlCollection.Count; }
		}
		/// <summary>
		/// Gets a value indicating whether the collection is read-only. 
		/// </summary>
		public bool IsReadOnly
		{
			get { return this.m_controlCollection.IsReadOnly; }
		}
		/// <summary>
		/// Returns an enumeration of all the XPanderPanels in the collection.  
		/// </summary>
		/// <returns></returns>
		public IEnumerator GetEnumerator()
		{
			return this.m_controlCollection.GetEnumerator();
		}
		/// <summary>
		/// Returns the index of the specified XPanderPanel in the collection. 
		/// </summary>
		/// <param name="xpanderPanel">The xpanderPanel to find the index of.</param>
		/// <returns>The index of the xpanderPanel, or -1 if the xpanderPanel is not in the <see ref="ControlCollection">ControlCollection</see> instance.</returns>
		public int IndexOf(XPanderPanel xpanderPanel)
		{
			return this.m_controlCollection.IndexOf(xpanderPanel);
		}
		/// <summary>
		/// Removes the XPanderPanel at the specified index from the collection. 
		/// </summary>
        /// <param name="index">The zero-based index of the xpanderPanel to remove from the ControlCollection instance.</param>
		public void RemoveAt(int index)
		{
			this.m_controlCollection.RemoveAt(index);
		}
		/// <summary>
		/// Inserts an XPanderPanel to the collection at the specified index. 
		/// </summary>
		/// <param name="index">The zero-based index at which value should be inserted. </param>
		/// <param name="xpanderPanel">The XPanderPanel to insert into the Collection.</param>
		public void Insert(int index, XPanderPanel xpanderPanel)
		{
			((IList)this).Insert(index, (object)xpanderPanel);
		}
		/// <summary>
		/// Copies the elements of the collection to an Array, starting at a particular Array index.
		/// </summary>
        /// <param name="xpanderPanels">The one-dimensional Array that is the destination of the elements copied from ICollection.
		/// The Array must have zero-based indexing.
		///</param>
		/// <param name="index">The zero-based index in array at which copying begins.</param>
		public void CopyTo(XPanderPanel[] xpanderPanels, int index)
		{
			this.m_controlCollection.CopyTo(xpanderPanels, index);
		}
        
		#endregion

		#region Interface ICollection
        /// <summary>
        /// Gets the number of elements contained in the ICollection.
        /// </summary>
		int ICollection.Count
		{
			get { return this.Count; }
		}
        /// <summary>
        /// Gets a value indicating whether access to the ICollection is synchronized
        /// </summary>
		bool ICollection.IsSynchronized
		{
			get { return ((ICollection)this.m_controlCollection).IsSynchronized; }
		}
        /// <summary>
        /// Gets an object that can be used to synchronize access to the ICollection.
        /// </summary>
		object ICollection.SyncRoot
		{
			get { return ((ICollection)this.m_controlCollection).SyncRoot; }
		}
        /// <summary>
        /// Copies the elements of the ICollection to an Array, starting at a particular Array index.
        /// </summary>
        /// <param name="array">The one-dimensional Array that is the destination of the elements copied from ICollection. The Array must have zero-based indexing.</param>
        /// <param name="index">The zero-based index in array at which copying begins.</param>
		void ICollection.CopyTo(Array array, int index)
		{
			((ICollection)this.m_controlCollection).CopyTo(array, index);
		}

		#endregion

		#region Interface IList
        /// <summary>
        /// Gets or sets the element at the specified index.
        /// </summary>
        /// <param name="index">The zero-based index of the element to get or set.</param>
        /// <returns> The element at the specified index.</returns>
		object IList.this[int index]
		{
			get { return this.m_controlCollection[index]; }
            set {}
		}
        /// <summary>
        /// Adds an item to the IList.
        /// </summary>
        /// <param name="value">The Object to add to the IList.</param>
        /// <returns>The position into which the new element was inserted.</returns>
		int IList.Add(object value)
		{
			XPanderPanel xpanderPanel = value as XPanderPanel;
			if (xpanderPanel == null)
			{
				throw new ArgumentException(string.Format(System.Globalization.CultureInfo.CurrentUICulture,
					Resources.IDS_ArgumentException,
					typeof(XPanderPanel).Name));
			}
			this.Add(xpanderPanel);
			return this.IndexOf(xpanderPanel);
		}
        /// <summary>
        /// Determines whether the IList contains a specific value.
        /// </summary>
        /// <param name="value">The Object to locate in the IList.</param>
        /// <returns>true if the Object is found in the IList; otherwise, false.</returns>
		bool IList.Contains(object value)
		{
			return this.Contains(value as XPanderPanel);
		}
        /// <summary>
        /// Determines the index of a specific item in the IList.
        /// </summary>
        /// <param name="value">The Object to locate in the IList.</param>
        /// <returns>The index of value if found in the list; otherwise, -1.</returns>
		int IList.IndexOf(object value)
		{
			return this.IndexOf(value as XPanderPanel);
		}
        /// <summary>
        /// Inserts an item to the IList at the specified index.
        /// </summary>
        /// <param name="index">The zero-based index of the item to insert.</param>
        /// <param name="value">The Object to insert into the IList.</param>
		void IList.Insert(int index, object value)
		{
			if ((value is XPanderPanel) == false)
			{
				throw new ArgumentException(
					string.Format(System.Globalization.CultureInfo.CurrentUICulture,
					Resources.IDS_ArgumentException,
					typeof(XPanderPanel).Name));
			}
		}
        /// <summary>
        /// Removes the first occurrence of a specific object from the IList.
        /// </summary>
        /// <param name="value">The Object to remove from the IList.</param>
		void IList.Remove(object value)
		{
			this.Remove(value as XPanderPanel);
		}
        /// <summary>
        /// Removes the IList item at the specified index.
        /// </summary>
        /// <param name="index">The zero-based index of the item to remove.</param>
		void IList.RemoveAt(int index)
		{
			this.RemoveAt(index);
		}
        /// <summary>
        /// Gets a value indicating whether the IList is read-only.
        /// </summary>
		bool IList.IsReadOnly
		{
			get { return this.IsReadOnly; }
		}
        /// <summary>
        /// Gets a value indicating whether the IList has a fixed size.
        /// </summary>
		bool IList.IsFixedSize
		{
			get { return ((IList)this.m_controlCollection).IsFixedSize; }
		}

		#endregion
	}

	#endregion

	#region Class XPanderPanelCollectionEditor
    /// <summary>
    /// Provides a user interface that can edit most types of collections at design time.
    /// </summary>
	internal class XPanderPanelCollectionEditor : CollectionEditor
	{
		#region FieldsPrivate

		private CollectionForm m_collectionForm;

		#endregion

		#region MethodsPublic
        /// <summary>
        /// Initializes a new instance of the XPanderPanelCollectionEditor class
        /// using the specified collection type.
        /// </summary>
        /// <param name="type">The type of the collection for this editor to edit.</param>
        public XPanderPanelCollectionEditor(Type type)
            : base(type)
        {
        }

		#endregion

		#region MethodsProtected
        /// <summary>
        /// Creates a new form to display and edit the current collection.
        /// </summary>
        /// <returns> A CollectionEditor.CollectionForm to provide as the user interface for editing the collection.</returns>
		protected override CollectionForm CreateCollectionForm()
		{
			this.m_collectionForm = base.CreateCollectionForm();
			return this.m_collectionForm;
		}
        /// <summary>
        /// Creates a new instance of the specified collection item type.
        /// </summary>
        /// <param name="ItemType">The type of item to create.</param>
        /// <returns> A new instance of the specified object.</returns>
        protected override Object CreateInstance(Type ItemType)
        {
            /* you can create the new instance yourself 
                 * ComplexItem ci=new ComplexItem(2,"ComplexItem",null);
                 * we know for sure that the itemType it will always be ComplexItem
                 *but this time let it to do the job... 
                 */

            BSE.Windows.Forms.XPanderPanel xpanderPanel =
                (BSE.Windows.Forms.XPanderPanel)base.CreateInstance(ItemType);

            if (this.Context.Instance != null)
            {
                xpanderPanel.Expand = true;
            }
            return xpanderPanel;
        }

		#endregion
	}

	#endregion

}
