using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using DevComponents.DotNetBar.Charts.Style;
namespace DevComponents.DotNetBar.Charts
{
    /// 
    /// Represents an item in the chart Legend.
    /// 
    public class ChartLegendItem : ChartVisualElement
    {
        #region Private variables
        private States _States;
        private List _ChartItems;
        private ChartLegendItem _LikeItem;
        private Tbool _ShowCheckBox = Tbool.NotSet;
        private Tbool _ShowItemText = Tbool.NotSet;
        private Tbool _ShowMarker = Tbool.NotSet;
        private Tbool _ShowInParentLegend = Tbool.NotSet;
        private ChartLegendItemVisualStyles _ChartLegendItemVisualStyles;
        private EffectiveStyles _EffectiveStyles;
        private Size _MarkerSize;
        private Size _TextSize;
        private Rectangle _MarkerBounds;
        private string _ItemText;
        private string _FormattedText;
        private LegendItemArea _HitArea;
        private LegendItemArea _MouseDownHitArea;
        private CheckState _CheckState = CheckState.Unchecked;
        private bool _InCheckStateUpdate;
        #endregion
        public ChartLegendItem()
        {
            InitDefaultStates();
            _EffectiveStyles = new EffectiveStyles(this);
        }
        #region InitDefaultStates
        private void InitDefaultStates()
        {
            SetState(States.IsEnabled, true);
        }
        #endregion
        #region Public properties
        #region ChartItems
        /// 
        /// Gets or sets the referenced Chart items.
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public List ChartItems
        {
            get
            {
                if (_ChartItems == null)
                    _ChartItems = new List();
                return (_ChartItems);
            }
            set
            {
                if (value != ChartItems)
                {
                    _ChartItems = value;
                    OnPropertyChangedEx("ChartItems", VisualChangeType.Layout);
                }
            }
        }
        #endregion
        #region ChartLegendItemVisualStyles
        /// 
        /// Gets or sets the visual styles for the Legend item.
        /// 
        [Category("Style")]
        [Description("Indicates the visual styles for the Legend item.")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public ChartLegendItemVisualStyles ChartLegendItemVisualStyles
        {
            get
            {
                if (_ChartLegendItemVisualStyles == null)
                {
                    _ChartLegendItemVisualStyles = new ChartLegendItemVisualStyles();
                    StyleVisualChangeHandler(null, _ChartLegendItemVisualStyles);
                }
                return (_ChartLegendItemVisualStyles);
            }
            set
            {
                if (_ChartLegendItemVisualStyles != value)
                {
                    ChartLegendItemVisualStyles oldValue = _ChartLegendItemVisualStyles;
                    _ChartLegendItemVisualStyles = value;
                    OnStyleChanged("ChartLegendItemVisualStyles", oldValue, value);
                    if (oldValue != null)
                        oldValue.Dispose();
                }
            }
        }
        #endregion
        #region CheckState
        /// 
        /// Gets or sets whether the item's checkbox is checked.
        /// 
        [DefaultValue(CheckState.Unchecked), Category("Appearance")]
        [Description("Indicates whether the item's checkbox is checked.")]
        public CheckState CheckState
        {
            get { return (_CheckState); }
            set
            {
                if (value != _CheckState)
                {
                    _CheckState = value;
                    UpdateChartItemsCheckState();
                    OnPropertyChangedEx("CheckState", VisualChangeType.Render);
                }
            }
        }
        #endregion
        #region EffectiveStyles
        /// 
        /// Gets a reference to the item's Effective (cached, composite) styles.
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public EffectiveStyles EffectiveStyles
        {
            get { return (_EffectiveStyles); }
        }
        #endregion
        #region ItemText
        /// 
        /// Gets or sets the item Text.
        /// 
        [DefaultValue(null), Category("Appearance")]
        [Description("Indicates the item Text.")]
        public string ItemText
        {
            get { return (_ItemText); }
            set
            {
                if (value != _ItemText)
                {
                    _ItemText = value;
                    OnPropertyChangedEx("ItemText", VisualChangeType.Layout);
                }
            }
        }
        #endregion
        #region ItemTextBounds
        /// 
        /// Gets the Item's Text bounds
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Rectangle ItemTextBounds
        {
            get
            {
                Rectangle bounds = Bounds;
                int n = _MarkerSize.Width + Dpi.Width(Legend.ItemTextOffset);
                bounds.X += n;
                bounds.Width -= n;
                return (bounds);
            }
        }
        #endregion
        #region Legend
        /// 
        /// Gets the associated ChartLegend
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public ChartLegend Legend
        {
            get { return (Parent as ChartLegend); }
        }
        #endregion
        #region MarkerBounds
        /// 
        /// Gets the Marker bounds
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Rectangle MarkerBounds
        {
            get { return (_MarkerBounds); }
        }
        #endregion
        #region ShowCheckBox
        /// 
        /// Gets or sets whether the item CheckBox is shown in the Legend.
        /// 
        [DefaultValue(Tbool.NotSet), Category("Appearance")]
        [Description("Indicates whether the item CheckBox is shown in the Legend.")]
        public Tbool ShowCheckBox
        {
            get { return (_ShowCheckBox); }
            set
            {
                if (value != _ShowCheckBox)
                {
                    _ShowCheckBox = value;
                    OnPropertyChangedEx("ShowCheckBox", VisualChangeType.Layout);
                }
            }
        }
        #endregion
        #region ShowInParentLegend
        /// 
        /// Gets or sets whether the item is shown in parent Legend(s).
        /// 
        [DefaultValue(Tbool.NotSet), Category("Layout")]
        [Description("Indicates whether the item is shown in parent Legend(s).")]
        public Tbool ShowInParentLegend
        {
            get { return (_ShowInParentLegend); }
            set
            {
                if (value != _ShowInParentLegend)
                {
                    _ShowInParentLegend = value;
                    OnPropertyChangedEx("ShowInParentLegend", VisualChangeType.Layout);
                }
            }
        }
        #endregion
        #region ShowItemText
        /// 
        /// Gets or sets whether the item text is shown in the Legend.
        /// 
        [DefaultValue(Tbool.NotSet), Category("Appearance")]
        [Description("Indicates whether the item text is shown in the Legend.")]
        public Tbool ShowItemText
        {
            get { return (_ShowItemText); }
            set
            {
                if (value != _ShowItemText)
                {
                    _ShowItemText = value;
                    OnPropertyChangedEx("ShowItemText", VisualChangeType.Layout);
                }
            }
        }
        #endregion
        #region ShowMarker
        /// 
        /// Gets or sets whether the item Marker is shown in the Legend.
        /// 
        [DefaultValue(Tbool.NotSet), Category("Appearance")]
        [Description("Indicates whether the item Marker is shown in the Legend.")]
        public Tbool ShowMarker
        {
            get { return (_ShowMarker); }
            set
            {
                if (value != _ShowMarker)
                {
                    _ShowMarker = value;
                    OnPropertyChangedEx("ShowMarker", VisualChangeType.Layout);
                }
            }
        }
        #endregion
        #endregion
        #region Internal properties
        #region FormattedText
        internal string FormattedText
        {
            get { return (_FormattedText); }
            set { _FormattedText = value; }
        }
        #endregion
        #region IsEnabled
        internal bool IsEnabled
        {
            get { return (TestState(States.IsEnabled)); }
            set { SetState(States.IsEnabled, value); }
        }
        #endregion
        #region IsHitItem
        internal bool IsHitItem
        {
            get { return (TestState(States.IsHitItem)); }
            set { SetState(States.IsHitItem, value); }
        }
        #endregion
        #region IsLegendHitItem
        internal bool IsLegendHitItem
        {
            get { return (TestState(States.IsLegendHitItem)); }
            set { SetState(States.IsLegendHitItem, value); }
        }
        #endregion
        #region LikeItem
        internal ChartLegendItem LikeItem
        {
            get { return (_LikeItem ?? this); }
            set { _LikeItem = value; }
        }
        #endregion
        #region TextWrapped
        internal bool TextWrapped
        {
            get { return (TestState(States.TextWrapped)); }
            set { SetState(States.TextWrapped, value); }
        }
        #endregion
        #endregion
        #region MeasureOverride
        protected override void MeasureOverride(ChartLayoutInfo layoutInfo)
        {
            BoundsRelative = layoutInfo.LayoutBounds;
            ChartLegend cl = Parent as ChartLegend;
            if (cl != null)
            {
                Size sizeNeeded = Size.Empty;
                Rectangle layoutBounds = layoutInfo.LayoutBounds;
                ChartLegendItemVisualStyle style = EffectiveStyles[StyleType.Default];
                if (cl.ShowMarkers == true || cl.ShowCheckBoxes == true)
                {
                    Size size = MeasureMarker(layoutInfo, cl);
                    sizeNeeded.Width += (size.Width + Dpi.Width2);
                    if (cl.ShowItemText == true)
                        sizeNeeded.Width += Dpi.Width(cl.ItemTextOffset);
                    sizeNeeded.Height = size.Height;
                    layoutInfo.LayoutBounds.Width -= sizeNeeded.Width;
                }
                _TextSize = Size.Empty;
                if (cl.ShowItemText == true)
                {
                    Size size = MeasureItemText(layoutInfo, cl, style);
                    sizeNeeded.Width += size.Width;
                    if (size.Height > sizeNeeded.Height)
                        sizeNeeded.Height = size.Height;
                }
                layoutInfo.LayoutBounds = layoutBounds;
                Size = sizeNeeded;
            }
        }
        #region MeasureMarker
        private Size MeasureMarker(ChartLayoutInfo layoutInfo, ChartLegend legend)
        {
            _MarkerSize = Size.Empty;
            if (legend.ShowCheckBoxes == true)
                _MarkerSize = Dpi.Size(legend.CheckBoxSize);
            if (legend.ShowMarkers == true)
            {
                Size msize = Dpi.Size(legend.MarkerSize);
                _MarkerSize.Width = Math.Max(_MarkerSize.Width, msize.Width);
                _MarkerSize.Height = Math.Max(_MarkerSize.Height, msize.Height);
            }
            return (_MarkerSize);
        }
        #endregion
        #region MeasureItemText
        private Size MeasureItemText(
            ChartLayoutInfo layoutInfo, ChartLegend legend, ChartLegendItemVisualStyle style)
        {
            if (legend.ShowItemText == true && (ShowItemText != Tbool.False))
            {
                Graphics g = layoutInfo.Graphics;
                string text = GetItemText();
                if (string.IsNullOrEmpty(text) == false)
                {
                    using (StringFormat sf = new StringFormat())
                    {
                        style.GetStringFormatFlags(sf);
                        Size size = layoutInfo.LayoutBounds.Size;
                        _TextSize = g.MeasureString(text, style.Font, size, sf).ToSize();
                    }
                }
                _TextSize.Width++;
                _TextSize.Height++;
                TextWrapped = false;
                if (style.MaxLineCount > 1)
                {
                    if (_TextSize.Height > style.Font.Height + 2)
                    {
                        if (text.Contains("\n") == false)
                            TextWrapped = true;
                    }
                    int lineHeight = style.Font.Height * style.MaxLineCount;
                    if (_TextSize.Height > lineHeight)
                        _TextSize.Height = lineHeight;
                }
            }
            return (_TextSize);
        }
        #endregion
        #endregion
        #region ArrangeOverride
        protected override void ArrangeOverride(ChartLayoutInfo layoutInfo)
        {
            BoundsRelative = layoutInfo.LayoutBounds;
            Rectangle bounds = Bounds;
            _MarkerBounds = bounds;
            _MarkerBounds.X += Dpi.Width2;
            if (_MarkerSize.IsEmpty == false)
            {
                _MarkerBounds.Size = _MarkerSize;
                ChartLegend legend = Legend;
                if (legend != null)
                {
                    if (bounds.Height > _MarkerBounds.Height)
                        _MarkerBounds.Y += (bounds.Height - _MarkerBounds.Height) / 2;
                }
            }
            else
            {
                _MarkerBounds.Size = Size.Empty;
            }
        }
        #endregion
        #region RenderOverride
        protected override void RenderOverride(ChartRenderInfo renderInfo)
        {
            ChartLegend legend = Parent as ChartLegend;
            if (legend != null)
            {
                Graphics g = renderInfo.Graphics;
                Rectangle bounds = Bounds;
                bool showCheckBoxes = (CanShowCheckBox(legend) == true);
                StyleState state = (IsMouseOver == true || IsHitItem == true)
                    ? StyleState.MouseOver : StyleState.Default;
                if (showCheckBoxes == true)
                {
                    if (CheckState != CheckState.Unchecked)
                        state |= StyleState.Selected;
                }
                ChartLegendItemVisualStyle istyle = EffectiveStyles[state];
                Color dcolor = GetLegendItemColor(legend, istyle);
                if (istyle.Background.IsEmpty == false)
                {
                    using (Brush br = istyle.Background.GetBrush(bounds))
                        g.FillRectangle(br, bounds);
                }
                if (_MarkerSize.IsEmpty == false)
                {
                    if (CanShowCheckBox(legend) == true)
                        RenderCheckBox(g, istyle, dcolor);
                    else if (CanShowMarker(legend) == true)
                        RenderMarker(g, istyle);
                    int n = _MarkerSize.Width;
                    if (_TextSize.IsEmpty == false)
                        n += Dpi.Width(legend.ItemTextOffset);
                    bounds.X += n;
                    bounds.Width -= n;
                }
                if (_TextSize.IsEmpty == false)
                    RenderItemText(g, bounds, istyle, dcolor);
            }
        }
        #region RenderCheckBox
        private void RenderCheckBox(Graphics g,
            ChartLegendItemVisualStyle istyle, Color dcolor)
        {
            if (_HitArea != LegendItemArea.CheckBox)
                istyle = EffectiveStyles[StyleState.Default];
            Rectangle r = _MarkerBounds;
            r.Inflate(-1, -1);
            Background background = istyle.CheckBoxBackground;
            if (background.IsEmpty == false)
            {
                using (Brush br = background.GetBrush(r))
                    g.FillRectangle(br, r);
            }
            Color color = GetCheckBoxBorderColor(istyle, dcolor);
            
            using (Pen pen = new Pen(color, Dpi.Width1))
                g.DrawRectangle(pen, r);
            color = GetCheckBoxCheckColor(istyle, dcolor);
            Rectangle t = r;
            t.Inflate(-Dpi.Width2, -Dpi.Width2);
            float fx = (float)t.Width / Dpi.Width9;
            float fy = (float)t.Height / Dpi.Width9;
            switch (_CheckState)
            {
                case CheckState.Checked:
                    SmoothingMode sm = g.SmoothingMode;
                    g.SmoothingMode = SmoothingMode.AntiAlias;
                    Point pt1 = new Point(t.X + (int)(fx), t.Y + (int)(fy * Dpi.Width4));
                    Point pt2 = new Point(t.X + (int)(fx * Dpi.Width3), t.Bottom - Dpi.Width2);
                    Point pt3 = new Point(t.Right - Dpi.Width1, t.Y + (int)fy);
                    using (Pen pen = new Pen(color, Dpi.Width2))
                        g.DrawLines(pen, new Point[] { pt1, pt2, pt3 });
                    g.SmoothingMode = sm;
                    break;
                case CheckState.Indeterminate:
                    Rectangle z = t;
                    z.Inflate(-(int)fx, -(int)fy);
                    z.Width += Dpi.Width1;
                    z.Height += Dpi.Width1;
                    using (Brush br = new SolidBrush(color))
                        g.FillRectangle(br, z);
                    break;
            }
        }
        #region GetCheckBoxCheckColor
        private Color GetCheckBoxCheckColor(
            ChartLegendItemVisualStyle istyle, Color dcolor)
        {
            Color color = istyle.CheckBoxCheckColor;
            if (color.IsEmpty == true)
                color = dcolor;
            return (color);
        }
        #endregion
        #region GetCheckBoxBorderColor
        private Color GetCheckBoxBorderColor(
            ChartLegendItemVisualStyle istyle, Color dcolor)
        {
            Color color = istyle.CheckBoxBorderColor;
            if (color.IsEmpty == true)
                color = dcolor;
            
            return (color);
        }
        #endregion
        #endregion
        #region RenderMarker
        private void RenderMarker(Graphics g, ChartLegendItemVisualStyle istyle)
        {
            if (istyle.MarkerVisualStyle.IsEmpty == false)
            {
                Color color = GetLegendItemColor(Legend, istyle);
                istyle.MarkerVisualStyle.RenderMarker(g, Legend.PointMarker, MarkerBounds, color);
            }
            else
            {
                if (ChartItems.Count > 0)
                {
                    ILegendItem item = ChartItems[0];
                    item.RenderLegendItemMarker(g, this, istyle);
                }
            }
        }
        #endregion
        #region RenderItemText
        private void RenderItemText(Graphics g,
            Rectangle bounds, ChartLegendItemVisualStyle istyle, Color dcolor)
        {
            bounds.Y++;
            string text = GetItemText();
            using (StringFormat sf = new StringFormat())
            {
                istyle.GetStringFormatFlags(sf);
                Color color = istyle.TextColor;
                if (color.IsEmpty == true)
                    color = dcolor;
                using (Brush br = new SolidBrush(color))
                    g.DrawString(text, istyle.Font, br, bounds, sf);
            }
        }
        #endregion
        #region GetLegendItemColor
        private Color GetLegendItemColor(ChartLegend legend, ChartLegendItemVisualStyle istyle)
        {
            if (IsEnabled == true)
            {
                Color color = istyle.TextColor;
                if (color.IsEmpty == false)
                    return (color);
                if (ChartItems.Count > 0)
                {
                    color = ChartItems[0].LegendItem.EffectiveStyles[StyleType.Default].TextColor;
                    if (color.IsEmpty == true)
                        color = ChartItems[0].GetLegendItemColor();
                }
                if (color.IsEmpty == true)
                    color = Color.DimGray;
                else
                    color = Color.FromArgb(255, color);
                return (color);
            }
            else
            {
                Color color = istyle.DisabledTextColor;
                if (color.IsEmpty == true)
                    color = Color.Silver;
                return (color);
            }
        }
        #endregion
        #endregion
        #region Mouse handling
        #region OnMouseEnter
        protected override bool OnMouseEnter(EventArgs e)
        {
            base.OnMouseEnter(e);
            InvalidateRender();
            InvalidateChartItems(true);
            return (true);
        }
        #endregion
        #region OnMouseLeave
        protected override bool OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            InvalidateRender();
            InvalidateChartItems(false);
            return (true);
        }
        #endregion
        #region InvalidateChartItems
        private void InvalidateChartItems(bool isHitItem)
        {
            IsLegendHitItem = isHitItem;
            foreach (ILegendItem item in ChartItems)
            {
                ILegendItemEx itemEx = item as ILegendItemEx;
                if (itemEx != null)
                {
                    if (itemEx.TrackLegendItem == true)
                    {
                        if (item is PieRing)
                        {
                            PieRing pieRing = (PieRing)item;
                            foreach (PieSeriesPoint psp in pieRing.Psps)
                            {
                                psp.LegendItem.IsLegendHitItem = isHitItem;
                                psp.InvalidateRender();
                            }
                        }
                        else
                        {
                            item.LegendItem.IsLegendHitItem = isHitItem;
                            itemEx.InvalidateRender();
                        }
                    }
                }
            }
        }
        #endregion
        #region OnMouseMove
        protected override bool OnMouseMove(MouseEventArgs e)
        {
            LegendItemArea area = GetItemAreaAt(e.Location);
            if (_HitArea != area)
                InvalidateRender();
            _HitArea = area;
            if (_HitArea == LegendItemArea.CheckBox)
            {
                ChartCursor = Cursors.Hand;
                
                return (true);
            }
            return (false);
        }
        #endregion
        #region OnMouseDown
        protected override bool OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            _MouseDownHitArea = _HitArea;
            if (_HitArea == LegendItemArea.CheckBox)
            {
                ChartControl.CapturedItem = this;
                return (true);
            }
            return (false);
        }
        #endregion
        #region OnMouseUp
        protected override bool OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            if (_HitArea == LegendItemArea.CheckBox && 
                _MouseDownHitArea == LegendItemArea.CheckBox)
            {
                switch (CheckState)
                {
                    case CheckState.Checked:
                        CheckState = CheckState.Unchecked;
                        break;
                    default:
                        CheckState = CheckState.Checked;
                        break;
                }
                ChartControl.CapturedItem = null;
                InvalidateDisplay();
            }
            return (true);
        }
        #region UpdateChartItemsCheckState
        private void UpdateChartItemsCheckState()
        {
            if (_InCheckStateUpdate == false)
            {
                _InCheckStateUpdate = true;
                if (CheckState != CheckState.Indeterminate)
                {
                    foreach (ILegendItem item in ChartItems)
                        item.CheckedInLegend = (CheckState == CheckState.Checked);
                }
                if (ChartControl != null)
                    ChartControl.DoLegendItemCheckedChangedEvent(Legend, this);
                _InCheckStateUpdate = false;
            }
        }
        #endregion
        #endregion
        #endregion
        #region GetItemText
        private string GetItemText()
        {
            string text = GetItemTextEx();
            if (string.IsNullOrEmpty(text) == false)
            {
                if (ChartItems.Count > 0)
                {
                    if (ChartItems[0] is ILegendItemEx)
                    {
                        ILegendItemEx itemEx = (ILegendItemEx)ChartItems[0];
                        text = itemEx.FormatItemText(text);
                    }
                }
            }
            return (text);
        }
        #region GetItemTextEx
        private string GetItemTextEx()
        {
            if (String.IsNullOrEmpty(_ItemText) == false)
                return (_ItemText);
            foreach (ILegendItem item in _ChartItems)
            {
                if (String.IsNullOrEmpty(item.LegendText) == false)
                    return (item.LegendText);
            }
            if (_ChartItems.Count > 0)
            {
                if (String.IsNullOrEmpty(_ChartItems[0].Name) == false)
                    return (_ChartItems[0].Name);
            }
            if (String.IsNullOrEmpty(Name) == false)
                return (Name);
            return ("");
        }
        #endregion
        #endregion
        #region GetItemAreaAt
        private LegendItemArea GetItemAreaAt(Point pt)
        {
            if (Bounds.Contains(pt) == true)
            {
                if (_MarkerBounds.Contains(pt))
                {
                    ChartLegend legend = Parent as ChartLegend;
                    if (CanShowCheckBox(legend) == true)
                        return (LegendItemArea.CheckBox);
                    return (LegendItemArea.Marker);
                }
                if (pt.X > _MarkerBounds.Right)
                    return (LegendItemArea.ItemText);
            }
            return (LegendItemArea.None);
        }
        #endregion
        #region Style Support
        #region ApplyStyles
        public override void ApplyStyles(BaseVisualStyle style, StyleType cs)
        {
            ChartLegendItemVisualStyle lstyle = style as ChartLegendItemVisualStyle;
            if (lstyle != null)
            {
                ApplyParentStyles(lstyle, cs, Parent as ChartVisualElement);
                lstyle.ApplyStyle(ChartLegendItemVisualStyles[cs]);
                if (ChartItems.Count > 0 && ChartItems[0] != null)
                    lstyle.ApplyStyle(ChartItems[0].ChartLegendItemVisualStyles[cs]);
            }
        }
        #region ApplyParentStyles
        private void ApplyParentStyles(
            ChartLegendItemVisualStyle lstyle, StyleType cs, ChartVisualElement item)
        {
            if (item != null)
            {
                ApplyParentStyles(lstyle, cs, item.Parent as ChartVisualElement);
                if (item is ChartLegend)
                    lstyle.ApplyStyle(((ChartLegend)item).ChartLegendItemVisualStyles[cs]);
                else if (item is ChartPanel)
                    lstyle.ApplyStyle(((ChartPanel)item).DefaultVisualStyles.ChartLegendItemVisualStyles[cs]);
            }
            else
            {
                lstyle.ApplyStyle(ChartControl.BaseVisualStyles.ChartLegendItemVisualStyles[cs]);
                lstyle.ApplyStyle(ChartControl.DefaultVisualStyles.ChartLegendItemVisualStyles[cs]);
            }
        }
        #endregion
        #endregion
        #region ApplyDefaults
        public override void ApplyDefaults(BaseVisualStyle style, StyleType cs)
        {
            ChartLegendItemVisualStyle lstyle = style as ChartLegendItemVisualStyle;
            if (lstyle != null)
            {
                if (lstyle.MaxLineCount <= 0)
                    lstyle.MaxLineCount = 2;
                if (lstyle.Font == null)
                    lstyle.Font = SystemFonts.DefaultFont;
            }
            base.ApplyDefaults(style, cs);
        }
        #endregion
        #region InvalidateStyle
        ///
        ///Invalidate the cached Styles
        ///
        public void InvalidateStyle()
        {
            ClearEffectiveStyles();
        }
        #endregion
        #region ClearEffectiveStyles
        protected override void ClearEffectiveStyles()
        {
            base.ClearEffectiveStyles();
            EffectiveStyles.InvalidateStyles();
        }
        #endregion
        #endregion
        #region InvalidateDisplay
        private void InvalidateDisplay()
        {
            ChartContainer cc = ParentChartContainer;
            if (cc != null)
            {
                cc.InvalidateRender(GetScrollBounds(cc.ContentBounds));
                cc.InvalidateLayoutBounds(null);
            }
            while (cc != null)
            {
                ILegendData ld = cc as ILegendData;
                if (ld != null)
                {
                    ChartLegend legend = ld.Legend;
                    if (legend != null)
                    {
                        if (CanShowInParentLegend(legend) == true)
                            legend.InvalidateItem(this);
                    }
                }
                cc = cc.ParentChartContainer;
            }
        }
        #endregion
        #region UpdateCheckState
        internal void UpdateCheckState()
        {
            if (_InCheckStateUpdate == false)
            {
                _InCheckStateUpdate = true;
                if (ChartItems.Count > 0)
                {
                    CheckState checkState = CheckState.Unchecked;
                    for (int i = 0; i < ChartItems.Count; i++)
                    {
                        ILegendItem chartItem = ChartItems[i];
                        CheckState ics = chartItem.CheckedInLegend ? CheckState.Checked : CheckState.Unchecked;
                        if (i == 0)
                        {
                            checkState = ics;
                        }
                        else
                        {
                            if (checkState != ics)
                            {
                                checkState = CheckState.Indeterminate;
                                break;
                            }
                        }
                    }
                    if (CheckState != checkState)
                    {
                        CheckState = checkState;
                        InvalidateDisplay();
                    }
                }
                _InCheckStateUpdate = false;
            }
        }
        #endregion
        #region CanShowCheckBox
        private bool CanShowCheckBox(ChartLegend legend)
        {
            if (legend.ShowCheckBoxes == true)
            {
                if (ShowCheckBox != Tbool.NotSet)
                {
                    bool show = (ShowCheckBox == Tbool.False ? false : true);
                    if (ChartItems.Count > 0)
                        ChartItems[0].ShowCheckBoxInLegend = show;
                    return (show);
                }
                if (ChartItems.Count > 0)
                    return (ChartItems[0].ShowCheckBoxInLegend);
                return (true);
            }
            return (false);
        }
        #endregion
        #region CanShowMarker
        private bool CanShowMarker(ChartLegend legend)
        {
            if (legend.ShowMarkers == true)
            {
                if (ShowMarker == Tbool.NotSet)
                {
                    if (ChartItems.Count > 0)
                        return (ChartItems[0].ShowMarkerInLegend);
                }
                return (ShowMarker == Tbool.False ? false : true);
            }
            return (false);
        }
        #endregion
        #region CanShowInParentLegend
        private bool CanShowInParentLegend(ChartLegend legend)
        {
            if (ChartItems.Count > 0)
            {
                if (ShowInParentLegend == Tbool.NotSet)
                    return (ChartItems[0].ShowInParentLegend);
                return (ShowInParentLegend == Tbool.False ? false : true);
            }
            return (false);
        }
        #endregion
        #region Copy/CopyTo
        public override ChartVisualElement Copy()
        {
            ChartLegendItem copy = new ChartLegendItem();
            CopyTo(copy);
            return (copy);
        }
        public override void CopyTo(ChartVisualElement copy)
        {
            ChartLegendItem c = copy as ChartLegendItem;
            if (c != null)
            {
                base.CopyTo(c);
                c.ChartLegendItemVisualStyles =
                    (_ChartLegendItemVisualStyles != null) ? ChartLegendItemVisualStyles.Copy() : null;
                c.CheckState = CheckState;
                c.ItemText = ItemText;
                c.ShowCheckBox = ShowCheckBox;
                c.ShowInParentLegend = ShowInParentLegend;
                c.ShowItemText = ShowItemText;
                c.ShowMarker = ShowMarker;
            }
        }
        #endregion
        #region GetSerialData
        internal override SerialElementCollection GetSerialData(string serialName)
        {
            SerialElementCollection sec = new SerialElementCollection();
            if (serialName != null)
            {
                if (serialName.Equals("") == true)
                    serialName = "BaseChart";
                sec.AddStartElement(serialName);
            }
            if (_ChartLegendItemVisualStyles != null)
                sec.AddElement(_ChartLegendItemVisualStyles.GetSerialData("ChartLegendItemVisualStyles"));
            sec.AddValue("CheckState", CheckState, CheckState.Unchecked);
            sec.AddValue("ItemText", ItemText, null);
            sec.AddValue("ShowCheckBox", ShowCheckBox, Tbool.NotSet);
            sec.AddValue("ShowInParentLegend", ShowInParentLegend, Tbool.NotSet);
            sec.AddValue("ShowItemText", ShowItemText, Tbool.NotSet);
            sec.AddValue("ShowMarker", ShowMarker, Tbool.NotSet);
            sec.AddElement(base.GetSerialData(null));
            if (serialName != null)
                sec.AddEndElement(serialName);
            return (sec);
        }
        #endregion
        #region PutSerialData
        #region ProcessValue
        internal override void ProcessValue(SerialElement se)
        {
            switch (se.Name)
            {
                case "CheckState":
                    CheckState = (CheckState)se.GetValueEnum(typeof(CheckState));
                    break;
                case "ItemText":
                    ItemText = se.StringValue;
                    break;
                case "ShowCheckBox":
                    ShowCheckBox = (Tbool)se.GetValueEnum(typeof(Tbool));
                    break;
                case "ShowInParentLegend":
                    ShowInParentLegend = (Tbool)se.GetValueEnum(typeof(Tbool));
                    break;
                case "ShowItemText":
                    ShowItemText = (Tbool)se.GetValueEnum(typeof(Tbool));
                    break;
                case "ShowMarker":
                    ShowMarker = (Tbool)se.GetValueEnum(typeof(Tbool));
                    break;
                default:
                    base.ProcessValue(se);
                    break;
            }
        }
        #endregion
        #region ProcessCollection
        internal override void ProcessCollection(SerialElement se)
        {
            SerialElementCollection sec = se.Sec;
            switch (se.Name)
            {
                case "ChartLegendItemVisualStyles":
                    sec.PutSerialData(ChartLegendItemVisualStyles);
                    break;
                default:
                    base.ProcessCollection(se);
                    break;
            }
        }
        #endregion
        #endregion
        #region States
        [Flags]
        private enum States : uint
        {
            IsEnabled = (1U << 0),
            IsHitItem = (1 << 1),
            IsLegendHitItem = (1 << 2),
            TextWrapped = (1U << 3),
        }
        #region TestState
        private bool TestState(States state)
        {
            return ((_States & state) == state);
        }
        #endregion
        #region SetState
        private void SetState(States state, bool value)
        {
            if (value == true)
                _States |= state;
            else
                _States &= ~state;
        }
        #endregion
        #endregion
        #region IDisposable
        public override void Dispose()
        {
            ChartLegendItemVisualStyles = null;
            base.Dispose();
        }
        #endregion
    }
    #region enums
    #region LegendItemArea
    public enum LegendItemArea
    {
        None = 0,
        CheckBox,
        ItemText,
        Marker,
    }
    #endregion
    #endregion
    #region Interfaces
    #region ILegendItem
    public interface ILegendItem
    {
        string Name { get; set; }
        string LegendText { get; set; }
        ChartLegendItem LegendItem { get; }
        ChartLegendItem GetLegendItem();
        List GetLegendItems();
        Color GetLegendItemColor();
        bool ShowInLegend { get; set; }
        bool ShowInParentLegend { get; set; }
        bool ShowCheckBoxInLegend { get; set; }
        bool ShowMarkerInLegend { get; set; }
        bool CheckedInLegend { get; set; }
        void RenderLegendItemMarker(Graphics g, ChartLegendItem item, ChartLegendItemVisualStyle style);
        ChartLegendItemVisualStyles ChartLegendItemVisualStyles { get; set; }
    }
    #endregion
    #region ILegendItem
    internal interface ILegendItemEx
    {
        bool TrackLegendItem { get; }
        void InvalidateRender();
        string FormatItemText(string text);
    }
    #endregion
    #endregion
}