using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Security.Permissions;
using System.Text;
using System.Windows.Forms;

namespace IMLibrary.Controls.Toolbox
{
    public class ToolboxEventArgs : System.EventArgs
    {
        public ToolboxEventArgs(Toolbox.Item item, Toolbox.Tab tab)
        {
            Item = item;
            Tab = tab;
        }

        public Toolbox.Item Item;
        public Toolbox.Tab Tab;
        public bool Cancel=false;
    }

    /// <summary>
    /// Represents a control, which displays a collection of items separated by categories.
    /// </summary>
    [TypeConverter(typeof(Toolbox.ToolboxConverter))]
    [Design.SRDescription("SRToolboxDescription")]
    public partial class Toolbox : Control, ITab
    {
        #region Fields
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private ItemCollection _items;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private TabCollection _tabs;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private ContextMenuStrip _tabMenu;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private ContextMenuStrip _itemMenu;

        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private BorderStyle _borderStyle = BorderStyle.None;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private int _tabHeight = 16;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private int _itemHeight = 20;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Font _tabFont = null;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private bool _showIcons = true;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private bool _showAll = false;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private bool _allowNestedTabs = true;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private bool _allowToolboxItems = false;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private ToolboxItemsTab _toolboxItemsTab;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private bool _drawTabLevel = true;

        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private bool _createGeneralCategory = true;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Tab _generalCategoryTab;

        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private bool _showPointer = false  ;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private bool _autoScroll = true;

        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Color _itemHoverColor = Color.Empty;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Color _itemSelectColor = Color.Empty;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Color _itemSelHoverColor = Color.Empty;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Color _tabSelectColor = Color.Empty;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Color _itemSelectBorderColor = Color.Empty;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Color _tabSelectBorderColor = Color.Empty;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Color _backColorGradientStart = Color.Empty;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Color _backColorGradientEnd = Color.Empty;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private ColorStyle _tabColorStyle = ColorStyle.Standard;

        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Color _defaultItemHoverColor = Color.LightBlue;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Color _defaultItemSelectColor = Color.Honeydew;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Color _defaultItemSelHoverColor = Color.PaleTurquoise;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Color _defaultTabSelectColor = Color.Lavender;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Color _defaultItemSelectBorderColor = Color.Blue;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Color _defaultTabSelectBorderColor = Color.Blue;
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Color _defaultBackColorGradientStart = Color.FromArgb(242, 240, 229);
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Color _defaultBackColorGradientEnd = Color.FromArgb(228, 225, 208);

        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Font _defaultTabFont = new Font("Arial", 9, FontStyle.Bold);

        internal const int Gap_TabTop = 1;
        internal const int Gap_TabBetween = 2;
        internal const int Gap_TabBorder = 1;
        internal const int Gap_ItemBetween = 0;
        internal const int Gap_TabFromItem = 2;
        internal const int Gap_IconFromText = 2;
        internal const int Gap_TabLevel = 7;

        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private static readonly Type _tabType = typeof(Tab);
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private static readonly Type _itemType = typeof(Item);

        private VScrollBar _verticalScroll;

        private IToolboxObject _lastSelectedTool = null;
        private Item _lastSelectedItem = null;

        private Item _lastHoveredItem = null;

        private BalloonToolTip _toolTip;
        private Point _toolTipPoint = Point.Empty;

        private IToolboxObject _draggedTool = null;
        private Rectangle _dragBoxFromMouseDown = Rectangle.Empty;

        #endregion

 
        /// <summary>
        /// Initializes a new instance of the <see cref="Toolbox"/> class.
        /// </summary>
        public Toolbox() : this(false)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Toolbox"/> class and creating a 'General' category tab if needed.
        /// </summary>
        /// <param name="createGeneral">Indicates whether to create a 'General' category tab.</param>
        public Toolbox(bool createGeneral)
        {
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.Selectable, true);
            SetStyle(ControlStyles.StandardDoubleClick, true);

            this.AllowDrop = true;
            
            _createGeneralCategory = createGeneral;

            _items = new ItemCollection(this);
            _tabs = new TabCollection(this);

            _verticalScroll = new VScrollBar();
            _verticalScroll.Visible = false;
            _verticalScroll.Dock = DockStyle.Right;
            _verticalScroll.Scroll += new ScrollEventHandler(OnVerticalScroll);
            this.Controls.Add(_verticalScroll);

            _toolTip = new BalloonToolTip();

            //TabMenu = CreateTabMenu();
            //ItemMenu = CreateItemMenu();

            if (createGeneral)
            {
                _generalCategoryTab = CreateNewTab(Properties.Resources.ToolboxTabGeneral);
                _generalCategoryTab.AllowDelete = false;
                this.Categories.Add(_generalCategoryTab);
            } 
        }

        #region Public Properties
        /// <summary>
        /// Overriden. Gets or sets the site of the control.
        /// </summary>
        public override ISite Site
        {
            set
            {
                base.Site = value;
                if (value != null && CreateGeneralCategory && GeneralCategory != null)
                {
                    this.Categories.Remove(GeneralCategory);
                }
            }
        }

        /// <summary>
        /// Gets the visible rectangle of the <see cref="Toolbox"/> including the offset of the scroll bar.
        /// </summary>
        [Browsable(false)]
        public Rectangle VisibleRectangle
        {
            get
            {
                Rectangle rect = ClientRectangle;
                if (_verticalScroll.Visible)
                {
                    rect = new Rectangle(new Point(rect.Left, rect.Top + _verticalScroll.Value), new Size(rect.Width - _verticalScroll.Width, rect.Height));
                }
                return rect;
            }
        }

        /// <summary>
        /// Gets or sets the <see cref="ContextMenuStrip">menu</see> displayed for the <see cref="Tab">tabs</see>.
        /// </summary>
        [Design.SRCategory("SRToolboxCategory")]
        [Design.SRDescription("SRToolboxTabMenuDescr")]
        public ContextMenuStrip TabMenu
        {
            [DebuggerStepThrough]
            get { return _tabMenu; }
            [DebuggerStepThrough]
            set { _tabMenu = value; }
        }

        /// <summary>
        /// Gets or sets the <see cref="ContextMenuStrip">menu</see> displayed for the <see cref="Item">items</see>.
        /// </summary>
        [Design.SRCategory("SRToolboxCategory")]
        [Design.SRDescription("SRToolboxItemMenuDescr")]
        public ContextMenuStrip ItemMenu
        {
            [DebuggerStepThrough]
            get { return _itemMenu; }
            [DebuggerStepThrough]
            set { _itemMenu = value; }
        }

        /// <summary>
        /// Gets the currently selected <see cref="Item"/> object on the <see cref="Toolbox"/>.
        /// </summary>
        [Browsable(false)]
        public Item SelectedItem
        {
            get
            {
                return _lastSelectedTool as Item;
            }
        }

        /// <summary>
        /// Gets or sets the border style for the <see cref="Toolbox"/>.
        /// </summary>
        /// <value>One of the <see cref="System.Windows.Forms.BorderStyle">BorderStyle</see> values. The default is <see cref="System.Windows.Forms.BorderStyle.None"/>.</value>
        /// <remarks>You can use this property to add a border to the <see cref="Toolbox"/>.</remarks>
        [DefaultValue(BorderStyle.None)]
        [Design.SRCategory("SRAppearanceCategory")]
        [Design.SRDescription("SRToolboxBorderStyleDescr")]
        public BorderStyle BorderStyle
        {
            get
            {
                return this._borderStyle;
            }
            set
            {
                if (this._borderStyle != value)
                {
                    int styleValue = (int)value;
                    if (styleValue < 0 || styleValue > 2)
                    {
                        throw new InvalidEnumArgumentException("value", (int)value, typeof(System.Windows.Forms.BorderStyle));
                    }
                    this._borderStyle = value;
                    base.UpdateStyles();
                }
            }
        }

        /// <summary>
        /// Gets or sets the height of the <see cref="Tab">tab</see> caption.
        /// </summary>
        [DefaultValue(16)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxTabHeightDescr")]
        public int TabHeight
        {
            [DebuggerStepThrough]
            get { return _tabHeight; }
            [DebuggerStepThrough]
            set 
            {
                if (value >= 16 && _tabHeight != value)
                {
                    _tabHeight = value;
                    OnTabHeightChanged(EventArgs.Empty);
                    Invalidate();
                }
            }
        }

        /// <summary>
        /// Gets or sets the height of the <see cref="Item">items</see>.
        /// </summary>
        [DefaultValue(20)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxItemHeightDescr")]
        public int ItemHeight
        {
            [DebuggerStepThrough]
            get { return _itemHeight; }
            [DebuggerStepThrough]
            set
            {
                if (value >= 20 && _itemHeight != value)
                {
                    _itemHeight = value;
                    OnItemHeightChanged(EventArgs.Empty);
                    Invalidate();
                }
            }
        }

        private int _selectItemHeight = 50;
        /// <summary>
        /// Gets or sets the height of the <see cref="Item">items</see>.
        /// </summary>
        [DefaultValue(40)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxItemHeightDescr")]
        public int SelectItemHeight
        {
            [DebuggerStepThrough]
            get { return _selectItemHeight; }
            [DebuggerStepThrough]
            set
            {
                if (value >= 40 && _selectItemHeight != value)
                {
                    _selectItemHeight = value;
                    Invalidate();
                }
            }
        }

        /// <summary>
        /// Gets or sets the <see cref="Font">font</see> of the <see cref="Tab">tabs</see>.
        /// </summary>
        /// <remarks>
        /// The font of the <see cref="Item">items</see> is defined by the <see cref="Font"/> property of the <see cref="Toolbox"/>.
        /// </remarks>
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxTabFontDescr")]
        public Font TabFont
        {
            [DebuggerStepThrough]
            get 
            {
                if (_tabFont == null)
                    return DefaultTabFont;
                return _tabFont; 
            }
            [DebuggerStepThrough]
            set 
            {
                if (value != null && _tabFont != value)
                {
                    _tabFont = value;
                    OnTabFontChanged(EventArgs.Empty);
                    Invalidate();
                }
            }
        }

        /// <summary>
        /// Gets or sets the design-only value indicating whether to create 'General' category tab.
        /// </summary>
        [DefaultValue(true)]
        [DesignOnly(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Design.SRCategory("SRToolboxCategory")]
        [Design.SRDescription("SRToolboxCreateGeneralDescr")]
        public bool CreateGeneralCategory
        {
            [DebuggerStepThrough]
            get { return _createGeneralCategory; }
            set
            {
                if (_createGeneralCategory != value)
                {
                    _createGeneralCategory = value;
                }
            }
        }

        /// <summary>
        /// Gets or sets the value indicating whether to show icons for <see cref="Item">items</see>.
        /// </summary>
        [DefaultValue(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxShowIconsDescr")]
        public bool ShowIcons
        {
            [DebuggerStepThrough]
            get { return _showIcons; }
            set 
            {
                if (_showIcons != value)
                {
                    _showIcons = value;
                    OnShowIconsChanged(EventArgs.Empty);
                    this.Invalidate();
                }
            }
        }

        /// <summary>
        /// Gets or sets the value indicating whether to show all <see cref="Item">items</see> and <see cref="Tab">categories</see> ignoring their <see cref="IToolboxObject.Visible">Visible</see> properties.
        /// </summary>
        [DefaultValue(false)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxShowAllDescr")]
        public bool ShowAll
        {
            [DebuggerStepThrough]
            get { return _showAll; }
            set
            {
                if (_showAll != value)
                {
                    _showAll = value;
                    OnShowAllChanged(EventArgs.Empty);
                    this.Invalidate();
                }
            }
        }

        /// <summary>
        /// Gets or sets the value indicating whether to show the pointer item for each <see cref="Tab"/>.
        /// </summary>
        [DefaultValue(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxShowPointerDescr")]
        public bool ShowPointer
        {
            [DebuggerStepThrough]
            get { return _showPointer; }
            set
            {
                if (_showPointer != value)
                {
                    _showPointer = value;
                    //OnShowPointerChanged(EventArgs.Empty);
                    this.Invalidate();
                }
            }
        }

        /// <summary>
        /// Gets or sets the value indicating whether nested <see cref="Tab">tabs</see> are allowed.
        /// </summary>
        /// <remarks>If <b>false</b>, the <see cref="Tab.Categories">nested tabs</see> are not displayed.</remarks>
        [DefaultValue(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxAllowNestedTabsDescr")]
        public bool AllowNestedTabs
        {
            get { return _allowNestedTabs; }
            set 
            {
                if (_allowNestedTabs != value)
                {
                    _allowNestedTabs = value;
                    OnAllowNestedTabsChanged(EventArgs.Empty);
                    this.Invalidate();
                }
            }
        }

        /// <summary>
        /// Gets or sets the value indicating whether to allow adding <see cref="Item">items</see> directly to <see cref="Toolbox"/>.
        /// </summary>
        /// <remarks>
        /// If <b>false</b>, items added to <see cref="Toolbox.Items"/> collection would be placed into additional <see cref="Tab">category</see>.
        /// </remarks>
        [DefaultValue(false)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxAllowToolboxItemsDescr")]
        public bool AllowToolboxItems
        {
            get { return _allowToolboxItems; }
            set 
            {
                if (_allowToolboxItems != value)
                {
                    _allowToolboxItems = value;
                    OnAllowToolboxItemsChanged(EventArgs.Empty);
                    this.Invalidate();
                }
            }
        }

        /// <summary>
        /// Gets or sets the value indicating whether to draw the <see cref="Tab"/> level mark.
        /// </summary>
        [DefaultValue(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxDrawTabLevelDescr")]
        public bool DrawTabLevel
        {
            get { return _drawTabLevel; }
            set 
            {
                if (_drawTabLevel != value)
                {
                    _drawTabLevel = value;
                    OnDrawTabLevelChanged(EventArgs.Empty);
                    this.Invalidate();
                }
            }
        }

        /// <summary>
        /// Gets or sets the value indicating whether the <see cref="Toolbox"/> enables autoscrolling.
        /// </summary>
        /// <value><b>true</b> to enable autoscrolling on the form; otherwise, <b>false</b>. The default is true.</value>
        /// <remarks>
        /// If this property is set to <b>true</b>, vertical scroll bar is displayed on the <see cref="Toolbox"/>.
        /// <para/>You can use this property if you want to synchronize the scrolling of the <see cref="Toolbox"/> with your own controls. Use the <see cref="Scroll"/> method in this case.
        /// </remarks>
        [DefaultValue(true)]
        [Design.SRCategory("SRLayoutCategory")]
        [Design.SRDescription("SRToolboxAutoScrollDescr")]
        public bool AutoScroll
        {
            [DebuggerStepThrough]
            get { return _autoScroll; }
            set
            {
                if (_autoScroll != value)
                {
                    _autoScroll = value;
                    OnAutoScrollChanged(EventArgs.Empty);
                    this.Invalidate();
                }
            }
        }

        /// <summary>
        /// Gets or sets the background color of the <see cref="Item"/> when the mouse pointer is over it.
        /// </summary>
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxItemHoverColorDescr")]
        public Color ItemHoverColor
        {
            get
            {
                if (_itemHoverColor == Color.Empty)
                    return DefaultItemHoverColor;
                return _itemHoverColor;
            }
            set
            {
                if (_itemHoverColor != value)
                {
                    _itemHoverColor = value;
                    OnItemHoverColorChanged(EventArgs.Empty);
                }
            }
        }

        /// <summary>
        /// Gets or sets the background color of the selected <see cref="Item"/>.
        /// </summary>
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxItemSelectColorDescr")]
        public Color ItemSelectColor
        {
            get
            {
                if (_itemSelectColor == Color.Empty)
                    return DefaultItemSelectColor;
                return _itemSelectColor;
            }
            set
            {
                if (_itemSelectColor != value)
                {
                    _itemSelectColor = value;
                    OnItemSelectColorChanged(EventArgs.Empty);
                    if (LastSelectedItem != null)
                        Invalidate(LastSelectedItem.Bounds);
                }
            }
        }

        /// <summary>
        /// Gets or sets the background color of the selected <see cref="Item"/> when the mouse pointer is over it.
        /// </summary>
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxItemSelHoverColorDescr")]
        public Color ItemSelectHoverColor
        {
            get
            {
                if (_itemSelHoverColor == Color.Empty)
                    return DefaultItemSelHoverColor;
                return _itemSelHoverColor;
            }
            set
            {
                if (_itemSelHoverColor != value)
                {
                    _itemSelHoverColor = value;
                    OnItemSelHoverColorChanged(EventArgs.Empty);
                }
            }
        }

        /// <summary>
        /// Gets or sets the background color of the selected <see cref="Tab"/>.
        /// </summary>
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxTabSelectColorDescr")]
        public Color TabSelectColor
        {
            get
            {
                if (_tabSelectColor == Color.Empty)
                    return DefaultTabSelectColor;
                return _tabSelectColor;
            }
            set
            {
                if (_tabSelectColor != value)
                {
                    _tabSelectColor = value;
                    OnTabSelectColorChanged(EventArgs.Empty);
                    if (LastSelectedTool is Tab)
                        Invalidate(((Tab)LastSelectedTool).GetCaptionRectangle(true));
                }
            }
        }

        /// <summary>
        /// Gets or sets the border color of the selected <see cref="Item"/>.
        /// </summary>
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxItemSelectBorderColorDescr")]
        public Color ItemSelectBorderColor
        {
            get 
            {
                if (_itemSelectBorderColor == Color.Empty)
                    return DefaultItemSelectBorderColor;
                return _itemSelectBorderColor; 
            }
            set 
            {
                if (_itemSelectBorderColor != value)
                {
                    _itemSelectBorderColor = value;
                    OnItemSelectBorderColorChanged(EventArgs.Empty);
                    if (LastSelectedItem != null)
                        Invalidate(LastSelectedItem.Bounds);
                }
            }
        }

        /// <summary>
        /// Gets or sets the border color of the selected <see cref="Tab"/>.
        /// </summary>
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxTabSelectBorderColorDescr")]
        public Color TabSelectBorderColor
        {
            get 
            {
                if (_tabSelectBorderColor == Color.Empty)
                    return DefaultTabSelectBorderColor;
                return _tabSelectBorderColor; 
            }
            set 
            {
                if (_tabSelectBorderColor != value)
                {
                    _tabSelectBorderColor = value;
                    OnTabSelectBorderColorChanged(EventArgs.Empty);
                    if (LastSelectedTool is Tab)
                        Invalidate(((Tab)LastSelectedTool).GetCaptionRectangle(true));
                }
            }
        }

        /// <summary>
        /// Gets or sets the gradient start color of the <see cref="Toolbox"/>.
        /// </summary>
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxBackColorGradientStartDescr")]
        public Color BackColorGradientStart
        {
            get
            {
                if (_backColorGradientStart == Color.Empty)
                    return DefaultBackColorGradientStart;
                return _backColorGradientStart;
            }
            set
            {
                if (_backColorGradientStart != value)
                {
                    _backColorGradientStart = value;
                    OnBackColorGradientStartChanged(EventArgs.Empty);
                    Invalidate();
                }
            }
        }

        /// <summary>
        /// Gets or sets the gradient end color of the <see cref="Toolbox"/>.
        /// </summary>
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxBackColorGradientEndDescr")]
        public Color BackColorGradientEnd
        {
            get
            {
                if (_backColorGradientEnd == Color.Empty)
                    return DefaultBackColorGradientEnd;
                return _backColorGradientEnd;
            }
            set
            {
                if (_backColorGradientEnd != value)
                {
                    _backColorGradientEnd = value;
                    OnBackColorGradientEndChanged(EventArgs.Empty);
                    Invalidate();
                }
            }
        }

        /// <summary>
        /// Gets or sets the style of drawing background of the <see cref="Tab">tabs</see>.
        /// </summary>
        [DefaultValue(Toolbox.ColorStyle.Standard)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxTabColorStyleDescr")]
        public ColorStyle TabColorStyle
        {
            get { return _tabColorStyle; }
            set
            {
                if (_tabColorStyle != value)
                {
                    int styleValue = (int)value;
                    if (styleValue < 0 || styleValue > 3)
                        throw new InvalidEnumArgumentException("value", (int)value, typeof(Toolbox.ColorStyle));
                    _tabColorStyle = value;
                    Invalidate();
                }
            }
        }

        /// <summary>
        /// Overriden.
        /// </summary>
        /// <remarks>Not used for drawing <see cref="Toolbox"/> background. Use <see cref="BackColorGradientStart"/> and <see cref="BackColorGradientEnd"/> properties instead.</remarks>
        /// <seealso cref="BackColorGradientStart"/>
        /// <seealso cref="BackColorGradientEnd"/>
        [Browsable(false)]
        public override Color BackColor
        {
            get { return base.BackColor; }
            set { base.BackColor = value; }
        }
        #endregion

        #region Protected Properties
        /// <summary>
        /// Gets or sets the 'General' category tab.
        /// </summary>
        protected Tab GeneralCategory
        {
            [DebuggerStepThrough]
            get { return _generalCategoryTab; }
            [DebuggerStepThrough]
            set { _generalCategoryTab = value; }
        }
        
        /// <summary>
        /// Gets the last selected <see cref="IToolboxObject">tool</see>.
        /// </summary>
        protected IToolboxObject LastSelectedTool
        {
            [DebuggerStepThrough]
            get { return _lastSelectedTool; }
        }

        /// <summary>
        /// Gets the last selected <see cref="Item"/>.
        /// </summary>
        protected Item LastSelectedItem
        {
            [DebuggerStepThrough]
            get { return _lastSelectedItem; }
        }

        /// <summary>
        /// Gets or sets the default <see cref="Font"/> of the <see cref="Tab"/> text.
        /// </summary>
        protected virtual Font DefaultTabFont
        {
            [DebuggerStepThrough]
            get { return _defaultTabFont; }
            [DebuggerStepThrough]
            set { _defaultTabFont = value; }
        }

        /// <summary>
        /// Gets or sets the default <see cref="Color"/> of the <see cref="Item"/> when the mouse pointer is over it.
        /// </summary>
        protected virtual Color DefaultItemHoverColor
        {
            [DebuggerStepThrough]
            get { return _defaultItemHoverColor; }
            [DebuggerStepThrough]
            set { _defaultItemHoverColor = value; }
        }

        /// <summary>
        /// Gets or sets the default <see cref="Color"/> of the selected <see cref="Item"/>.
        /// </summary>
        protected virtual Color DefaultItemSelectColor
        {
            [DebuggerStepThrough]
            get { return _defaultItemSelectColor; }
            [DebuggerStepThrough]
            set { _defaultItemSelectColor = value; }
        }

        /// <summary>
        /// Gets or sets the default <see cref="Color"/> of the selected <see cref="Item"/> when the mouse pointer is over it.
        /// </summary>
        protected virtual Color DefaultItemSelHoverColor
        {
            [DebuggerStepThrough]
            get { return _defaultItemSelHoverColor; }
            [DebuggerStepThrough]
            set { _defaultItemSelHoverColor = value; }
        }

        /// <summary>
        /// Gets or sets the default <see cref="Color"/> of the selected <see cref="Tab"/>.
        /// </summary>
        protected virtual Color DefaultTabSelectColor
        {
            [DebuggerStepThrough]
            get { return _defaultTabSelectColor; }
            [DebuggerStepThrough]
            set { _defaultTabSelectColor = value; }
        }

        /// <summary>
        /// Gets or sets the default border <see cref="Color"/> of the selected <see cref="Item"/>.
        /// </summary>
        protected virtual Color DefaultItemSelectBorderColor
        {
            [DebuggerStepThrough]
            get { return _defaultItemSelectBorderColor; }
            [DebuggerStepThrough]
            set { _defaultItemSelectBorderColor = value; }
        }

        /// <summary>
        /// Gets or sets the default border <see cref="Color"/> of the selected <see cref="Tab"/>.
        /// </summary>
        protected virtual Color DefaultTabSelectBorderColor
        {
            [DebuggerStepThrough]
            get { return _defaultTabSelectBorderColor; }
            [DebuggerStepThrough]
            set { _defaultTabSelectBorderColor = value; }
        }

        /// <summary>
        /// Gets or sets the default gradient start <see cref="Color"/> of the <see cref="Toolbox"/>.
        /// </summary>
        protected virtual Color DefaultBackColorGradientStart
        {
            [DebuggerStepThrough]
            get { return _defaultBackColorGradientStart; }
            [DebuggerStepThrough]
            set { _defaultBackColorGradientStart = value; }
        }

        /// <summary>
        /// Gets or sets the default gradient end <see cref="Color"/> of the <see cref="Toolbox"/>.
        /// </summary>
        protected virtual Color DefaultBackColorGradientEnd
        {
            [DebuggerStepThrough]
            get { return _defaultBackColorGradientEnd; }
            [DebuggerStepThrough]
            set { _defaultBackColorGradientEnd = value; }
        }

        /// <summary>
        /// Gets the required creation parameters when the control handle is created.
        /// </summary>
        protected override CreateParams CreateParams
        {
            [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
            get
            {
                System.Windows.Forms.CreateParams parameters = base.CreateParams;
                switch (this._borderStyle)
                {
                    case System.Windows.Forms.BorderStyle.FixedSingle:
                        parameters.Style |= 0x800000;
                        return parameters;

                    case System.Windows.Forms.BorderStyle.Fixed3D:
                        parameters.ExStyle |= 0x200;
                        return parameters;
                }
                return parameters;
            }
        }
        #endregion

        #region Public Methods
        public Tab AddGroup(string text)
        {
            var tab = new  Tab(text);
            tab.FactText = text;
            Categories.Add(tab);
            return tab;
        }

        public Tab InsertGroup(string text, int index)
        {
            var tab = new Tab(text);
            tab.FactText = text;
            Categories.Insert(index, tab);
            return tab;
        }

        public void IniListBox()
        {
            this.Dock = DockStyle.Fill;
            this.TabColorStyle = Toolbox.ColorStyle.None;

            this.BackColorGradientEnd = Color.FromArgb(239,237,248);// Color.Transparent;
            this.BackColorGradientStart = Color.FromArgb(239, 237, 248);  
            this.DefaultItemSelHoverColor= this.DefaultItemSelectBorderColor  = this.DefaultItemHoverColor = Color.FromArgb(253, 236, 170);
            this.DefaultItemSelectColor = this.DefaultItemSelHoverColor;
            this.DrawTabLevel = false;
            this.ItemHeight = 24;
            this.SelectItemHeight  =50;
        }

        /// <summary>
        /// Scrolls current view by the specified offset value.
        /// </summary>
        /// <param name="offset">The integer value of scrolling. Negative values mean scrolling up, positive values - scrolling down.</param>
        public void ScrollView(int offset)
        {
            int oldValue = _verticalScroll.Value;

            int newValue = _verticalScroll.Value + offset;
            if (newValue > _verticalScroll.Maximum)
                newValue = _verticalScroll.Maximum;
            if (newValue < _verticalScroll.Minimum)
                newValue = _verticalScroll.Minimum;

            _verticalScroll.Value = newValue;
            Invoke(new ScrollEventHandler(OnVerticalScroll), _verticalScroll, new ScrollEventArgs(ScrollEventType.ThumbPosition, oldValue, newValue, ScrollOrientation.VerticalScroll));
        }

        /// <summary>
        /// Returns an object with information on which portion of a toolbox control is at a location specified by a <see cref="Point"/>.
        /// </summary>
        /// <param name="location">A <see cref="Point"/> containing the <see cref="Point.X"/> and <see cref="Point.Y"/> coordinates of the point to be hit tested.</param>
        /// <returns>A <see cref="HitTestInfo"/> that contains information about the specified point on the <see cref="Toolbox"/>.</returns>
        public virtual HitTestInfo HitTest(Point location)
        {
            HitTestInfo info = new HitTestInfo(location);
            Rectangle tabsRect = ClientRectangle;
            tabsRect.Inflate(-Toolbox.Gap_TabBorder, -Toolbox.Gap_TabTop);
            if (tabsRect.Contains(location))
            {
                foreach (Tab tab in Categories)
                {
                    if ((ShowAll || tab.Visible) && tab.VisibleRectangle.Contains(location))
                    {
                        return tab.HitTest(location);
                    }
                }

                if (this.Items.Count > 0)
                {
                    if (this.AllowToolboxItems)
                    {
                        foreach (Item item in this.Items)
                        {
                            if ((item.Visible || ShowAll) && item.Bounds.Contains(location))
                            {
                                info.HitArea = HitArea.Item;
                                info.Tool = item;
                                break;
                            }
                        }
                    }
                    else
                    {
                        Tab toolboxItems = GetToolboxItemsTab(true);
                        if ((toolboxItems.Visible || ShowAll) && toolboxItems.VisibleRectangle.Contains(location))
                        {
                            info = toolboxItems.HitTest(location);
                        }
                    }
                }

                if (info.HitArea == HitArea.None)
                    info.HitArea = HitArea.Background;
            }
            return info;
        }
        #endregion

        #region Protected Methods
        /// <summary>
        /// Creates a new <see cref="Tab"/> object with the default <paramref name="text"/> value.
        /// </summary>
        /// <param name="text">The default text of the <see cref="Tab"/>.</param>
        /// <returns>A newly created <see cref="Tab"/> object.</returns>
        protected virtual Tab CreateNewTab(string text)
        {
            return new Tab(text);
        }

        /// <summary>
        /// Ensures that the <paramref name="rect"/> is visible within the <see cref="Toolbox"/>, scrolling the contents of the <see cref="Toolbox"/> if necessary.
        /// </summary>
        /// <param name="rect">The <see cref="Rectangle"/> to set visible.</param>
        protected virtual void EnsureVisible(Rectangle rect)
        {
            Rectangle visible = VisibleRectangle;
            if (!visible.Contains(rect))
            {
                int offset = 0;
                
                if (rect.Top < visible.Top)
                {
                    offset = rect.Top;
                }
                else if (rect.Height <= visible.Height)
                {
                    offset = rect.Bottom - visible.Bottom;
                }
                else
                {
                    offset = visible.Top - rect.Top;
                }

                ScrollView(offset);
            }
        }

        /// <summary>
        /// Selects a specified <paramref name="tool"/> on the <see cref="Toolbox"/>.
        /// </summary>
        /// <param name="tool">A <see cref="IToolboxObject"/> object to select.</param>
        protected virtual void SelectTool(IToolboxObject tool)
        {
            if (tool == null)
                throw new ArgumentNullException("tool");
            if (!tool.Visible)
                throw new ArgumentException(Properties.Resources.ToolboxSelectNonVisibleTool);
            if (tool is Item && !((Item)tool).Enabled)
                throw new ArgumentException(Properties.Resources.ToolboxSelectDisabledItem);

            InternalSelectTool(tool);
        }

        /// <summary>
        /// Invoked when user double clicks on an <see cref="Item"/>.
        /// </summary>
        /// <param name="picked">An <see cref="IDataObject"/> object that contains an <see cref="Item"/> in independent format.</param>
        protected virtual bool OnToolboxItemPicked(IDataObject picked)
        {
        	return false;
        }

        /// <summary>
        /// Returns <see cref="Tab"/> object which contains <see cref="Toolbox"/>-level items.
        /// </summary>
        /// <param name="createIfNull">Indicates whether to create new <see cref="Tab"/> if it is Null.</param>
        /// <remarks>Use this method only if property <see cref="AllowToolboxItems"/> is set to <b>false</b>. The collection of <see cref="Item">items</see> inside this <see cref="Tab"/> is identical to <see cref="Toolbox.Items">Toolbox Items</see>.</remarks>
        /// <returns>A <see cref="Tab"/> containing toolbox <see cref="P:IMLibrary.Components.Toolbox.Items">items</see> or a null reference.</returns>
        protected Tab GetToolboxItemsTab(bool createIfNull)
        {
            if (_toolboxItemsTab == null && createIfNull)
            {
                _toolboxItemsTab = new ToolboxItemsTab(this.Items);
            }

            return _toolboxItemsTab;
        }
        
        /// <summary>
        /// Creates a default unique category name.
        /// </summary>
        /// <returns>The unique category name for the <see cref="Toolbox"/>.</returns>
        protected string GetUnusedCategoryName()
        {
            return GetUnusedCategoryName(this, Properties.Resources.ToolboxTabDefaultName);
        }

        /// <summary>
        /// Creates a default unique category name using the <paramref name="baseName"/>.
        /// </summary>
        /// <param name="baseName">A base category name which is changed by adding a number until it becomes unique.</param>
        /// <returns>The unique category name for the <see cref="Toolbox"/>.</returns>
        protected string GetUnusedCategoryName(string baseName)
        {
            return GetUnusedCategoryName(this, baseName);
        }

        /// <summary>
        /// Creates a default unique category name.
        /// </summary>
        /// <param name="tab">The <see cref="ITab"/> for which the unique name is created.</param>
        /// <returns>The unique category name for the <see cref="ITab"/>.</returns>
        protected static string GetUnusedCategoryName(ITab tab)
        {
            return GetUnusedCategoryName(tab, Properties.Resources.ToolboxTabDefaultName);
        }

        /// <summary>
        /// Creates a default unique category name using the <paramref name="baseName"/>.
        /// </summary>
        /// <param name="tab">The <see cref="ITab"/> for which the unique name is created.</param>
        /// <param name="baseName">A base category name which is changed by adding a number until it becomes unique.</param>
        /// <returns>The unique category name for the <see cref="ITab"/>.</returns>
        protected static string GetUnusedCategoryName(ITab tab, string baseName)
        {
            string category = baseName;
            for (int i = 1; ; i++)
            {
                category = string.Format("{0}{1}", baseName, i);
                if (tab.Categories[category] == null)
                    break;
            }
            return category;
        }

        #region Overridables

        #region Paint
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.Paint"/> event.
        /// </summary>
        /// <param name="e">A <see cref="System.Windows.Forms.PaintEventArgs"/> that contains the event data.</param>
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
            e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;

            using (Brush backgroundBrush = new LinearGradientBrush(this.ClientRectangle, this.BackColorGradientStart, this.BackColorGradientEnd, LinearGradientMode.Horizontal))
            {
                e.Graphics.FillRectangle(backgroundBrush, this.ClientRectangle);
            }

            #region Drawing Background Image
            if (this.BackgroundImage != null)
            {
                using (Bitmap backgroundImage = new Bitmap(this.BackgroundImage))
                {
                    switch (this.BackgroundImageLayout)
                    {
                        case ImageLayout.None:
                            e.Graphics.DrawImageUnscaled(backgroundImage, Point.Empty);
                            break;
                        case ImageLayout.Center:
                            PointF drawImagePoint = new PointF(
                                (this.ClientSize.Width - backgroundImage.Width) / (float)2,
                                (this.ClientSize.Height - backgroundImage.Height) / (float)2);
                            e.Graphics.DrawImageUnscaled(backgroundImage, Point.Round(drawImagePoint));
                            break;
                        case ImageLayout.Stretch:
                            e.Graphics.DrawImage(backgroundImage.GetThumbnailImage(this.ClientSize.Width, this.ClientSize.Height, delegate { return false; }, IntPtr.Zero), this.ClientRectangle);
                            break;
                        case ImageLayout.Zoom:
                            float xRelation = this.ClientSize.Width / (float)backgroundImage.Width;
                            float yRelation = this.ClientSize.Height / (float)backgroundImage.Height;
                            SizeF imageSize = SizeF.Empty;
                            if (xRelation > 1 || yRelation > 1)
                            {
                                float multiplier = (xRelation < yRelation) ? xRelation : yRelation;
                                imageSize = new SizeF(backgroundImage.Width * multiplier, backgroundImage.Height * multiplier);
                                
                            }
                            else
                            {
                                float divisor = (xRelation > yRelation) ? xRelation : yRelation;
                                imageSize = new SizeF(backgroundImage.Width / divisor, backgroundImage.Height / divisor);
                            }
                            RectangleF imageRect = new RectangleF(
                                    new PointF(
                                        (this.ClientSize.Width - imageSize.Width) / 2,
                                        (this.ClientSize.Height - imageSize.Height) / 2),
                                    imageSize);
                            e.Graphics.DrawImage(backgroundImage.GetThumbnailImage((int)imageSize.Width, (int)imageSize.Height, delegate {return false;}, IntPtr.Zero), imageRect);
                            break;
                        case ImageLayout.Tile:
                            using (Brush imageBrush = new TextureBrush(backgroundImage, WrapMode.Tile))
                            {
                                e.Graphics.FillRectangle(imageBrush, this.ClientRectangle);
                            }
                            break;
                    }
                }
            }
            #endregion

            SuspendLayout();

            Point location = new Point(Toolbox.Gap_TabBorder, Toolbox.Gap_TabTop);
            
            if (!AutoScroll)
            {
                _verticalScroll.Visible = false;
            }
            else
            {
                int totalHeight = CalculateToolboxHeight(e.Graphics, false);
                if (totalHeight > this.ClientRectangle.Height)
                {
                    totalHeight = CalculateToolboxHeight(e.Graphics, true);
                    _verticalScroll.Maximum = totalHeight - this.ClientSize.Height;
                    _verticalScroll.LargeChange = Math.Min(_verticalScroll.Maximum / 3, this.ClientSize.Height);
                    _verticalScroll.SmallChange = this.ItemHeight;
                    _verticalScroll.Visible = true;
                }
                else
                {
                    _verticalScroll.Visible = false;
                }

                if (_verticalScroll.Visible)
                    location.Y -= _verticalScroll.Value;
            }

            foreach (Tab tab in Categories)
                {
                    if (tab.Visible || ShowAll)
                    {
                        tab.InternalPaint(e, ref location);
                        location.Offset(0, Toolbox.Gap_TabBetween);
                    }
                }

            if (this.Items.Count > 0)
            {
                if (this.AllowToolboxItems)
                {
                    foreach (Item item in Items)
                    {
                        if (item.Visible || this.ShowAll)
                        {
                            location.Offset(0, Toolbox.Gap_ItemBetween);
                            item.InternalPaint(e, location);
                            location.Offset(0, this.ItemHeight);
                        }
                    }
                }
                else
                {
                    Tab toolboxItems = GetToolboxItemsTab(true);
                    if (toolboxItems.Visible || this.ShowAll)
                    {
                        toolboxItems.InternalPaint(e, ref location);
                        location.Offset(0, Toolbox.Gap_TabBetween);
                    }
                }
            }

            ResumeLayout(true);
        }
        #endregion

        #region Mouse Events
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.MouseDown"/> event.
        /// </summary>
        /// <param name="e">An <see cref="System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            InternalSelectTool(HitTest(e.Location).Tool);

            if (LastSelectedTool != null)
            {
                _draggedTool = LastSelectedTool;
                Size dragSize = SystemInformation.DragSize;
                _dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2),
                                                               e.Y - (dragSize.Height / 2)), dragSize);

                Tab tab = LastSelectedTool as Tab;
                if (tab != null)
                {
                    tab.InternalMouseDown(e);
                }

                Item item = LastSelectedTool as Item;
                if (item != null)
                {
                    item.InternalMouseDown(e);
                }
            }
            else
            {
                _dragBoxFromMouseDown = Rectangle.Empty;
            }
            
            base.OnMouseDown(e);
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.MouseUp"/> event.
        /// </summary>
        /// <param name="e">An <see cref="System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
        protected override void OnMouseUp(MouseEventArgs e)
        {
            _dragBoxFromMouseDown = Rectangle.Empty;

            if (LastSelectedTool != null)
            {
                Tab tab = LastSelectedTool as Tab;
                if (tab != null)
                {
                    tab.InternalMouseUp(e);

                    goto Label_MouseUpBaseCall;
                }

                Item item = LastSelectedTool as Item;
                if (item != null)
                {
                    item.InternalMouseUp(e);

                    goto Label_MouseUpBaseCall;
                }
            }
            else if (e.Button == MouseButtons.Right)
            {
                if (this.TabMenu != null)
                {
                    this.TabMenu.Tag = null;
                    this.TabMenu.Show(this, e.Location);
                }
            }

        Label_MouseUpBaseCall:
            base.OnMouseUp(e);
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.MouseMove"/> event.
        /// </summary>
        /// <param name="e">An <see cref="System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            if ((MouseButtons == MouseButtons.Left) && 
                _dragBoxFromMouseDown != Rectangle.Empty &&
                !_dragBoxFromMouseDown.Contains(e.Location))
            {
                Item item = _draggedTool as Item;
                if (item != null && IsPointerItem(item))
                    goto Label_MouseMoveBaseCall;

                this.DoDragDrop(_draggedTool, DragDropEffects.Move | DragDropEffects.Copy);
            }
            else
            {
                IToolboxObject tool = HitTest(e.Location).Tool;
                Item item = tool as Item;
                if (item != null)
                {
                    item.Highlighted = true;

                    if (item.Tooltip != _toolTip.GetBalloonText(this) ||
                        System.Math.Abs(e.X - _toolTipPoint.X) > 5 ||
                        System.Math.Abs(e.Y - _toolTipPoint.Y) > 5)
                    {
                        _toolTip.SetBalloonText(this, item.Tooltip);
                        _toolTipPoint = e.Location;
                    }
                }
                else
                {
                    _toolTip.SetBalloonText(this, string.Empty);
                }

                if (_lastHoveredItem != item)
                {
                    if (_lastHoveredItem != null)
                        _lastHoveredItem.Highlighted = false;

                    _lastHoveredItem = item;
                }
            }

        Label_MouseMoveBaseCall:
            base.OnMouseMove(e);
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.MouseEnter"/> event.
        /// </summary>
        /// <param name="e">An <see cref="System.EventArgs"/> that contains the event data.</param>
        protected override void OnMouseEnter(EventArgs e)
        {
            this.Focus();

            base.OnMouseEnter(e);
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.MouseLeave"/> event.
        /// </summary>
        /// <param name="e">An <see cref="System.EventArgs"/> that contains the event data.</param>
        protected override void OnMouseLeave(EventArgs e)
        {
            if (_lastHoveredItem != null)
                _lastHoveredItem.Highlighted = false;

            base.OnMouseLeave(e);
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.MouseWheel"/> event.
        /// </summary>
        /// <param name="e">An <see cref="System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
        protected override void OnMouseWheel(MouseEventArgs e)
        {
            if (_verticalScroll.Visible)
            {
                int numberOfTextLinesToMove = e.Delta * SystemInformation.MouseWheelScrollLines / SystemInformation.MouseWheelScrollDelta;
                int numberOfPixelsToMove = (int)(numberOfTextLinesToMove * Font.Size);

                if (numberOfPixelsToMove != 0)
                {
                    int result = _verticalScroll.Value - numberOfPixelsToMove;
                    if (result < 0)
                    {
                        OnVerticalScroll(this, new ScrollEventArgs(ScrollEventType.First, _verticalScroll.Value, 0, ScrollOrientation.VerticalScroll));
                        _verticalScroll.Value = 0;
                    }
                    else if (result > _verticalScroll.Maximum)
                    {
                        OnVerticalScroll(this, new ScrollEventArgs(ScrollEventType.Last, _verticalScroll.Value, _verticalScroll.Maximum, ScrollOrientation.VerticalScroll));
                        _verticalScroll.Value = _verticalScroll.Maximum;
                    }
                    else
                    {
                        OnVerticalScroll(this, new ScrollEventArgs(ScrollEventType.ThumbPosition, _verticalScroll.Value, result, ScrollOrientation.VerticalScroll));
                        _verticalScroll.Value = result;
                    }
                }
            }
            base.OnMouseWheel(e);
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.Click"/> event.
        /// </summary>
        /// <param name="e">An <see cref="System.EventArgs"/> that contains the event data.</param>
        protected override void OnClick(EventArgs e)
        {
            if (_lastSelectedTool is Item)
            {
                ((Item)_lastSelectedTool).InternalClick(e);
            }
            else if (_lastSelectedTool is Tab)
            {
                ((Tab)_lastSelectedTool).InternalClick(e);
            }
            base.OnClick(e);
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.DoubleClick"/> event.
        /// </summary>
        /// <param name="e">An <see cref="System.EventArgs"/> that contains the event data.</param>
        protected override void OnDoubleClick(EventArgs e)
        {
            if (_lastSelectedTool is Item)
            {
                OnToolboxItemPicked(new DataObject(_lastSelectedTool));
                ((Item)_lastSelectedTool).InternalDoubleClick(e);
            }
            else if (_lastSelectedTool is Tab)
            {
                ((Tab)_lastSelectedTool).InternalDoubleClick(e);
            }
            base.OnDoubleClick(e);
        }
        #endregion

        #region Drag'n'Drop
        /// <summary>
        /// 事件
        /// </summary>
        /// <param name="sender">产生事件的对象</param>
        public delegate void DragItemBeforeEventHandler(object sender, ToolboxEventArgs e);
        /// <summary>
        /// 
        /// </summary>
        public event DragItemBeforeEventHandler DragItemBefore;
        /// <summary>
        /// 
        /// </summary>
        public event DragItemBeforeEventHandler DragTabBefore;

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.DragDrop"/> event.
        /// </summary>
        /// <param name="drgevent">A <see cref="System.Windows.Forms.DragEventArgs"/> that contain the event data.</param>
        protected override void OnDragDrop(DragEventArgs drgevent)
        {
            IToolboxObject dropped = GetDragDropTool(drgevent.Data);
            if (dropped != null)
            {
                Point ptDrop = PointToClient(new Point(drgevent.X, drgevent.Y));
                IToolboxObject selected = HitTest(ptDrop).Tool;

                if (dropped is Item)
                {
                    Item item = (Item)dropped;
                    Tab tab = null;

                    if (!(item.Owner as Tab).AllowDropItem)
                        return;

                    if (selected is Item)
                    {
                        Item selItem = (Item)selected;
                        tab= (Tab) selItem.Owner;

                        if (selItem.Owner == item.Owner)
                            return;
                        if (!tab.AllowDropItem)
                            return;
                    }

                    if (selected is Tab)
                    {
                        tab= (Tab)selected;
                        if (!tab.AllowDropItem) 
                            return;
                    }

                    if (tab == null) return;

                    var e=new ToolboxEventArgs(item,tab);
                    if(DragItemBefore!=null)
                        DragItemBefore(this,e);
                    if (e.Cancel) return;

                    if (item.Toolbox == this)
                        item.Owner.Items.Remove(item);
                    else
                        item = item.Clone();

                    if (selected is Item)
                    {
                        Item selItem = (Item)selected;
                        if (selItem.Owner != null)
                            if (item.IsOnline)
                                selItem.Owner.Items.Insert(0, item);
                            else
                                selItem.Owner.Items.InsertAfter(selItem, item);
                    }
                    else if (selected is Tab)
                    {
                        if (item.IsOnline)
                            ((Tab)selected).Items.Insert(0,item);
                        else
                            ((Tab)selected).Items.Add(item);
                    }
                    #region 
                    //else if (this.AllowToolboxItems)
                    //{
                    //    this.Items.Add(item);
                    //}
                    //else
                    //{
                    //    Tab t = Categories[Categories.Count - 1];
                    //    t.Items.Add(item);
                    //    if (!t.Opened)
                    //        t.Opened = true;
                    //}
                    #endregion

                }
                else if (dropped is Tab)
                {
                    Tab tab = (Tab)dropped;
                    if (!tab.AllowDrag) return;

                    if (tab.Toolbox == this)
                    {
                        TabCollection sourceCollection = tab.Owner.Categories;
                        TabCollection destCollection = this.Categories;
                        int index = sourceCollection.IndexOf(tab);
                        int destination = -1;

                        Tab over = selected as Tab;
                        if (over == null)   // Mouse is not over Tab (empty tab or header)
                        {
                            Item selItem = selected as Item;
                            if (selItem != null)
                                over = selItem.Category;
                        }

                        if (over != null)
                        {
                            if (!over.AllowDrag) return;

                            ITab parent = over.Owner;
                            while (parent != null)
                            {
                                if (parent == dropped)
                                    goto Label_Out;
                                parent = parent.Owner;
                            }

                            destCollection = over.Owner.Categories;
                            HitArea hit = over.HitTest(ptDrop).HitArea;
                            destination = destCollection.IndexOf(over);
                            if (hit != HitArea.TabHeader)
                                destination++;
                        }
                        else
                            destination = Categories.Count - 1;

                        if (sourceCollection != destCollection || index != destination)
                        {
                            if (sourceCollection == destCollection && index < destination)
                                destination--;

                            bool allowDelete = tab.AllowDelete;
                            try
                            {
                                tab.AllowDelete = true;
                                sourceCollection.Remove(tab);
                                destCollection.Insert(destination, tab);
                            }
                            finally
                            {
                                tab.AllowDelete = allowDelete;
                            }
                        }
                    }
                }
            }
            Label_Out:
            base.OnDragDrop(drgevent);
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.DragEnter"/> event.
        /// </summary>
        /// <param name="drgevent">A <see cref="System.Windows.Forms.DragEventArgs"/> that contain the event data.</param>
        protected override void OnDragEnter(DragEventArgs drgevent)
        {
            IToolboxObject tool = GetDragDropTool(drgevent.Data);
            if (tool is Tab && ((Tab)tool).Toolbox != this)
                drgevent.Effect = DragDropEffects.None;
            else
                drgevent.Effect = (tool != null) ? drgevent.AllowedEffect : DragDropEffects.None;
            base.OnDragEnter(drgevent);
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.DragOver"/> event.
        /// </summary>
        /// <param name="drgevent">A <see cref="System.Windows.Forms.DragEventArgs"/> that contain the event data.</param>
        protected override void OnDragOver(DragEventArgs drgevent)
        {
            IToolboxObject dragged = GetDragDropTool(drgevent.Data);
            if (dragged is Tab)
            {
                IToolboxObject tool = HitTest(this.PointToClient(new Point(drgevent.X, drgevent.Y))).Tool;

                if (tool is Tab)
                {
                    drgevent.Effect = drgevent.AllowedEffect;

                    ITab current = (ITab)tool;
                    while (current != null)
                    {
                        if (current == dragged)
                        {
                            drgevent.Effect = DragDropEffects.None;
                            break;
                        }
                        current = current.Owner;
                    }
                }
                else if (tool is Item && tool.Owner == dragged)
                    drgevent.Effect = DragDropEffects.None;
                else if (tool == null && Categories.IndexOf((Tab)dragged) == Categories.Count - 1)
                    drgevent.Effect = DragDropEffects.None;
                else
                    drgevent.Effect = drgevent.AllowedEffect;
            }
            else if (dragged is Item)
            {
                IToolboxObject tool = HitTest(this.PointToClient(new Point(drgevent.X, drgevent.Y))).Tool;

                if (tool is Item && dragged == tool)
                    drgevent.Effect = DragDropEffects.None;
                else
                    drgevent.Effect = drgevent.AllowedEffect;
            }
            base.OnDragOver(drgevent);
        }

        /// <summary>
        /// Retrieves an <see cref="IToolboxObject"/> object from the specified format-independent data storage.
        /// </summary>
        /// <param name="dragged">An <see cref="IDataObject"/> object that contains drag'n'drop data.</param>
        protected virtual IToolboxObject GetDragDropTool(IDataObject dragged)
        {
            if (dragged.GetDataPresent(Toolbox._itemType))
            {
                return (Item)dragged.GetData(Toolbox._itemType);
            }
            if (dragged.GetDataPresent(Toolbox._tabType))
            {
                return (Tab)dragged.GetData(Toolbox._tabType);
            }
            return null;
        }

        #endregion

        #endregion

        #endregion

        #region Private Methods
        private void OnVerticalScroll(object sender, ScrollEventArgs e)
        {
            if (e.Type == ScrollEventType.SmallIncrement)
            {
                int val = Math.Min(Math.Max(e.NewValue, e.OldValue + _verticalScroll.SmallChange), _verticalScroll.Maximum);
                if (val != e.NewValue)
                {
                    e.NewValue = val;
                }
            }

            OnScroll(e);

            if (e.Type == ScrollEventType.EndScroll)
                return;

            Invalidate();
        }

        private int CalculateToolboxHeight(Graphics g, bool scrollVisible)
        {
            int height = Toolbox.Gap_TabTop - Toolbox.Gap_TabBetween;
            Rectangle toolboxRect = (!scrollVisible) ? this.ClientRectangle : new Rectangle(ClientRectangle.Location, new Size(ClientRectangle.Width - _verticalScroll.Width, ClientRectangle.Height));
            toolboxRect.Inflate(-2 * Toolbox.Gap_TabBorder, -2 * Toolbox.Gap_TabTop);
            foreach (Tab tab in Categories)
            {
                if (tab.Visible || ShowAll)
                {
                    height += tab.CalculateTabHeight(g, toolboxRect);
                    height += Toolbox.Gap_TabBetween;
                }
            }

            if (this.Items.Count > 0)
            {
                if (this.AllowToolboxItems)
                {
                    foreach (Item item in Items)
                    {
                        if (item.Visible || ShowAll)
                        {
                            height += Toolbox.Gap_ItemBetween;
                            //height += this.ItemHeight;
                            height +=item.Height ;
                        }
                    }
                }
                else
                {
                    Tab toolboxItems = GetToolboxItemsTab(true);
                    if (toolboxItems.Visible || ShowAll)
                    {
                        height += toolboxItems.CalculateTabHeight(g, toolboxRect);
                        height += Toolbox.Gap_TabBetween;
                    }
                }
            }

            return height;
        }

        private void InternalSelectTool(IToolboxObject tool)
        {
            IToolboxObject previouslySelected = LastSelectedTool;
            if (tool is Item && !((Item)tool).Enabled)
                tool = null;
            _lastSelectedTool = tool;

            if (previouslySelected != null && previouslySelected != LastSelectedTool)
            {
                if (previouslySelected is Tab)
                    ((Tab)previouslySelected).Selected = false;
                else if (previouslySelected is Item)
                    ((Item)previouslySelected).Selected = false;
            }

            if (LastSelectedTool != null)
            {
                Tab tab = LastSelectedTool as Tab;
                if (tab != null)
                {
                    tab.Selected = true;
                    
                    return;
                }

                Item item = LastSelectedTool as Item;
                if (item != null)
                {
                    if (LastSelectedItem != item)
                    {
                        if (LastSelectedItem != null)
                        {
                            LastSelectedItem.Height = LastSelectedItem.NotSelectedHeight;

                            if (LastSelectedItem.NotSelectedImage == null)
                                LastSelectedItem.NotSelectedImage = LastSelectedItem.Image;

                            LastSelectedItem.Image = LastSelectedItem.NotSelectedImage;
                        }

                        if (LastSelectedItem != null)
                            LastSelectedItem.Selected = false;

                        _lastSelectedItem = item;
                    }

                    item.Selected = true;
                    if (item.Category != null && !item.Category.Opened)
                        item.Category.Opened = true;

                    {
                        item.Height = SelectItemHeight;
                        item.Image = item.SelectedImage;
                    }

                    OnSelectItem(new ItemSelectionEventArgs(item));

                    return;
                }
            }
        }

        private bool IsPointerItem(Item item)
        {
            Tab tab = item.Owner as Tab;
            return tab != null && tab.PointerItem == item;
        }

        private bool ShouldSerializeItemHoverColor()
        {
            return this.ItemHoverColor != this.DefaultItemHoverColor;
        }

        private bool ShouldSerializeItemSelectColor()
        {
            return this.ItemSelectColor != this.DefaultItemSelectColor;
        }

        private bool ShouldSerializeItemSelectHoverColor()
        {
            return this.ItemSelectHoverColor != this.DefaultItemSelHoverColor;
        }

        private bool ShouldSerializeTabSelectColor()
        {
            return this.TabSelectColor != this.DefaultTabSelectColor;
        }

        private bool ShouldSerializeItemSelectBorderColor()
        {
            return this.ItemSelectBorderColor != this.DefaultItemSelectBorderColor;
        }

        private bool ShouldSerializeTabSelectBorderColor()
        {
            return this.TabSelectBorderColor != this.DefaultTabSelectBorderColor;
        }

        private bool ShouldSerializeBackColorGradientStart()
        {
            return this.BackColorGradientStart != this.DefaultBackColorGradientStart;
        }

        private bool ShouldSerializeBackColorGradientEnd()
        {
            return this.BackColorGradientEnd != this.DefaultBackColorGradientEnd;
        }

        private bool ShouldSerializeTabFont()
        {
            return this.TabFont != this.DefaultTabFont;
        }
        #endregion

        #region Events
        private static readonly object EventItemHoverColorChanged = new object();
        private static readonly object EventItemSelectColorChanged = new object();
        private static readonly object EventItemSelHoverColorChanged = new object();
        private static readonly object EventTabSelectColorChanged = new object();
        private static readonly object EventItemSelectBorderColorChanged = new object();
        private static readonly object EventTabSelectBorderColorChanged = new object();
        private static readonly object EventBackColorGradientStartChanged = new object();
        private static readonly object EventBackColorGradientEndChanged = new object();
        private static readonly object EventTabColorStyleChanged = new object();
        private static readonly object EventShowAllChanged = new object();
        private static readonly object EventShowIconsChanged = new object();
        private static readonly object EventShowPointerChanged = new object();
        private static readonly object EventAllowNestedTabsChanged = new object();
        private static readonly object EventAllowToolboxItemsChanged = new object();
        private static readonly object EventDrawTabLevelChanged = new object();
        private static readonly object EventAutoScrollChanged = new object();
        private static readonly object EventItemHeightChanged = new object();
        private static readonly object EventTabHeightChanged = new object();
        private static readonly object EventTabFontChanged = new object();
        private static readonly object EventSelectItem = new object();
        private static readonly object EventScroll = new object();
 

        /// <summary>
        /// Occurs when the <see cref="ItemHoverColor"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxItemHoverColorChangedDescr")]
        public event EventHandler ItemHoverColorChanged
        {
            add { this.Events.AddHandler(EventItemHoverColorChanged, value); }
            remove { this.Events.RemoveHandler(EventItemHoverColorChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="ItemSelectColor"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxItemSelectColorChangedDescr")]
        public event EventHandler ItemSelectColorChanged
        {
            add { this.Events.AddHandler(EventItemSelectColorChanged, value); }
            remove { this.Events.RemoveHandler(EventItemSelectColorChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="ItemSelectHoverColor"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxItemSelHoverColorChanged")]
        public event EventHandler ItemSelectHoverColorChanged
        {
            add { this.Events.AddHandler(EventItemSelHoverColorChanged, value); }
            remove { this.Events.RemoveHandler(EventItemSelHoverColorChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="TabSelectColor"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxTabSelectColorChanged")]
        public event EventHandler TabSelectColorChanged
        {
            add { this.Events.AddHandler(EventTabSelectColorChanged, value); }
            remove { this.Events.RemoveHandler(EventTabSelectColorChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="ItemSelectBorderColor"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxItemSelectBorderColorChangedDescr")]
        public event EventHandler ItemSelectBorderColorChanged
        {
            add { this.Events.AddHandler(EventItemSelectBorderColorChanged, value); }
            remove { this.Events.RemoveHandler(EventItemSelectBorderColorChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="TabSelectBorderColor"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxTabSelectBorderColorChangedDescr")]
        public event EventHandler TabSelectBorderColorChanged
        {
            add { this.Events.AddHandler(EventTabSelectBorderColorChanged, value); }
            remove { this.Events.RemoveHandler(EventTabSelectBorderColorChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="BackColorGradientStart"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxBackColorGradientStartChangedDescr")]
        public event EventHandler BackColorGradientStartChanged
        {
            add { this.Events.AddHandler(EventBackColorGradientStartChanged, value); }
            remove { this.Events.RemoveHandler(EventBackColorGradientStartChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="BackColorGradientEnd"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxBackColorGradientEndChangedDescr")]
        public event EventHandler BackColorGradientEndChanged
        {
            add { this.Events.AddHandler(EventBackColorGradientEndChanged, value); }
            remove { this.Events.RemoveHandler(EventBackColorGradientEndChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="TabColorStyle"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxTabColorStyleChangedDescr")]
        public event EventHandler TabColorStyleChanged
        {
            add { this.Events.AddHandler(EventTabColorStyleChanged, value); }
            remove { this.Events.RemoveHandler(EventTabColorStyleChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="ShowAll"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxShowAllChangedDescr")]
        public event EventHandler ShowAllChanged
        {
            add { this.Events.AddHandler(EventShowAllChanged, value); }
            remove { this.Events.RemoveHandler(EventShowAllChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="ShowIcons"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxShowIconsChangedDescr")]
        public event EventHandler ShowIconsChanged
        {
            add { this.Events.AddHandler(EventShowIconsChanged, value); }
            remove { this.Events.RemoveHandler(EventShowIconsChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="ShowPointer"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxShowPointerChangedDescr")]
        public event EventHandler ShowPointerChanged
        {
            add { this.Events.AddHandler(EventShowPointerChanged, value); }
            remove { this.Events.RemoveHandler(EventShowPointerChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="AllowNestedTabs"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxAllowNestedTabsChangedDescr")]
        public event EventHandler AllowNestedTabsChanged
        {
            add { this.Events.AddHandler(EventAllowNestedTabsChanged, value); }
            remove { this.Events.RemoveHandler(EventAllowNestedTabsChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="AllowToolboxItems"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxAllowToolboxItemsChangedDescr")]
        public event EventHandler AllowToolboxItemsChanged
        {
            add { this.Events.AddHandler(EventAllowToolboxItemsChanged, value); }
            remove { this.Events.RemoveHandler(EventAllowToolboxItemsChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="DrawTabLevel"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxDrawTabLevelChangedDescr")]
        public event EventHandler DrawTabLevelChanged
        {
            add { this.Events.AddHandler(EventDrawTabLevelChanged, value); }
            remove { this.Events.RemoveHandler(EventDrawTabLevelChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="AutoScroll"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRLayoutCategory")]
        [Design.SRDescription("SRToolboxAutoScrollChangedDescr")]
        public event EventHandler AutoScrollChanged
        {
            add { this.Events.AddHandler(EventAutoScrollChanged, value); }
            remove { this.Events.RemoveHandler(EventAutoScrollChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="ItemHeight"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxItemHeightChangedDescr")]
        public event EventHandler ItemHeightChanged
        {
            add { this.Events.AddHandler(EventItemHeightChanged, value); }
            remove { this.Events.RemoveHandler(EventItemHeightChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="TabHeight"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxTabHeightChangedDescr")]
        public event EventHandler TabHeightChanged
        {
            add { this.Events.AddHandler(EventTabHeightChanged, value); }
            remove { this.Events.RemoveHandler(EventTabHeightChanged, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="TabFont"/> property value changes.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxAppearanceCategory")]
        [Design.SRDescription("SRToolboxTabFontChangedDescr")]
        public event EventHandler TabFontChanged
        {
            add { this.Events.AddHandler(EventTabFontChanged, value); }
            remove { this.Events.RemoveHandler(EventTabFontChanged, value); }
        }

        /// <summary>
        /// Occurs when the user selects an <see cref="Item"/> on the <see cref="Toolbox"/>.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxToolboxCategory")]
        [Design.SRDescription("SRToolboxSelectItemDescr")]
        public event EventHandler<ItemSelectionEventArgs> SelectItem
        {
            add { this.Events.AddHandler(EventSelectItem, value); }
            remove { this.Events.RemoveHandler(EventSelectItem, value); }
        }

        /// <summary>
        /// Occurs when the <see cref="Toolbox"/> is scrolled.
        /// </summary>
        [Browsable(true)]
        [Design.SRCategory("SRToolboxToolboxCategory")]
        [Design.SRDescription("SRToolboxScrollDescr")]
        public event ScrollEventHandler Scroll
        {
            add { this.Events.AddHandler(EventScroll, value); }
            remove { this.Events.RemoveHandler(EventScroll, value); }
        }
        #endregion

        #region Event Fires
        /// <summary>
        /// Raises the <see cref="ItemHoverColorChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnItemHoverColorChanged(EventArgs e)
        { 
            EventHandler handler = (EventHandler)this.Events[EventItemHoverColorChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="ItemSelectColorChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnItemSelectColorChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventItemSelectColorChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="ItemSelectHoverColorChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnItemSelHoverColorChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventItemSelHoverColorChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="TabSelectColorChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnTabSelectColorChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventTabSelectColorChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="ItemSelectBorderColorChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnItemSelectBorderColorChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventItemSelectBorderColorChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="TabSelectBorderColorChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnTabSelectBorderColorChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventTabSelectBorderColorChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="BackColorGradientStartChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnBackColorGradientStartChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventBackColorGradientStartChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="BackColorGradientEndChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnBackColorGradientEndChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventBackColorGradientEndChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="TabColorStyleChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnTabColorStyleChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventTabColorStyleChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="ShowAllChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnShowAllChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventShowAllChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="ShowIconsChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnShowIconsChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventShowIconsChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="ShowPointerChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnShowPointerChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventShowPointerChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="AllowNestedTabsChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnAllowNestedTabsChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventAllowNestedTabsChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="AllowToolboxItemsChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnAllowToolboxItemsChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventAllowToolboxItemsChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="DrawTabLevelChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnDrawTabLevelChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventDrawTabLevelChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="AutoScrollChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnAutoScrollChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventAutoScrollChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="ItemHeightChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnItemHeightChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventItemHeightChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="TabHeightChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnTabHeightChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventTabHeightChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="TabFontChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
        protected virtual void OnTabFontChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)this.Events[EventTabFontChanged];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="SelectItem"/> event.
        /// </summary>
        /// <param name="e">An <see cref="ItemSelectionEventArgs"/> that contains the event data.</param>
        protected virtual void OnSelectItem(ItemSelectionEventArgs e)
        {
            EventHandler<ItemSelectionEventArgs> handler = (EventHandler<ItemSelectionEventArgs>)this.Events[EventSelectItem];
            if (handler != null) handler(this, e);
        }

        /// <summary>
        /// Raises the <see cref="Scroll"/> event.
        /// </summary>
        /// <param name="e">An <see cref="ScrollEventArgs"/> that contains the scrolling event data.</param>
        protected virtual void OnScroll(ScrollEventArgs e)
        {
            ScrollEventHandler handler = (ScrollEventHandler)this.Events[EventScroll];
            if (handler != null) handler(this, e);
        }
        #endregion

        #region ITab Members

        /// <summary>
        /// Gets the <see cref="ItemCollection">collection</see> of the <see cref="Item"/> objects contained in the <see cref="Toolbox"/>.
        /// </summary>
        [MergableProperty(false)]
        [Design.SRCategory("SRToolboxCategory")]
        [Design.SRDescription("SRToolboxItemsDescr")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public Toolbox.ItemCollection Items
        {
            get { return _items; }
        }

        /// <summary>
        /// Gets the <see cref="TabCollection">collection</see> of the <see cref="Tab"/> objects contained in the <see cref="Toolbox"/>.
        /// </summary>
        [MergableProperty(false)]
        [Design.SRCategory("SRToolboxCategory")]
        [Design.SRDescription("SRToolboxCategoriesDescr")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public Toolbox.TabCollection Categories
        {
            get { return _tabs; }
        }

        ITab ITab.Owner
        {
            get { return null; }
        }

        #endregion
    }
}
