using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using DevComponents.Charts.TextMarkup;
using DevComponents.DotNetBar.Charts.Style;
namespace DevComponents.DotNetBar.Charts
{
    /// 
    /// Represents the collection of ChartTitles.
    /// 
    [Editor("DevComponents.Charts.Design.ChartTitleCollectionEditor, DevComponents.Charts.Design, " +
            "Version=14.1.0.37, Culture=neutral,  PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
    public class ChartTitleCollection : CustomNamedCollection
    {
        public ChartTitleCollection()
        {
        }
        #region GetUniqueName
        public string GetUniqueName()
        {
            return (GetUniqueName("Title"));
        }
        #endregion
    }
    /// 
    /// ChartTitle
    /// 
    public class ChartTitle : ChartNote
    {
        #region Private variables
        private States _States;
        private XyAlignment _XyAlignment = XyAlignment.NotSet;
        private RotateDegrees _RotateDegrees = RotateDegrees.NotSet;
        private ChartTitleVisualStyle _ChartTitleVisualStyle;
        private EffectiveStyle _EffectiveTitleStyle;
        private Rectangle _FrameBounds;
        private Rectangle _ContentBounds;
        private int _TextHeight;
        #endregion
        #region Constructors
        /// 
        /// Creates a new ChartTitle
        /// 
        public ChartTitle()
            : this(null, null)
        {
        }
        /// 
        /// Creates a new ChartTitle
        /// 
        /// Title name
        public ChartTitle(string name)
            : this(name, null)
        {
        }
        /// 
        /// Creates a new ChartTitle
        /// 
        /// Title Name
        /// Title Text
        public ChartTitle(string name, string text)
        {
            InitDefaultStates();
            Name = name;
            Text = text;
            _EffectiveTitleStyle = new EffectiveStyle(this);
        }
        #endregion
        #region InitDefaultStates
        private void InitDefaultStates()
        {
        }
        #endregion
        #region Public properties
        #region ChartTitleVisualStyle
        /// 
        /// Gets or sets the visual style for the Title.
        /// 
        [Category("Style")]
        [Description("Indicates the visual style for the Title.")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public ChartTitleVisualStyle ChartTitleVisualStyle
        {
            get
            {
                if (_ChartTitleVisualStyle == null)
                {
                    _ChartTitleVisualStyle = new ChartTitleVisualStyle();
                    StyleVisualChangeHandler(null, _ChartTitleVisualStyle);
                }
                return (_ChartTitleVisualStyle);
            }
            set
            {
                if (_ChartTitleVisualStyle != value)
                {
                    ChartTitleVisualStyle oldValue = _ChartTitleVisualStyle;
                    _ChartTitleVisualStyle = value;
                    OnStyleChanged("ChartTitleVisualStyle", oldValue, value);
                    if (oldValue != null)
                        oldValue.Dispose();
                }
            }
        }
        #endregion
        #region EffectiveTitleStyle
        /// 
        /// Gets a reference to the title's effective (cached, composite) style.
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public ChartTitleVisualStyle EffectiveTitleStyle
        {
            get { return (_EffectiveTitleStyle.Style); }
        }
        #endregion
        #region RotateDegrees
        /// 
        /// Gets or sets the title's display rotation.
        /// 
        [DefaultValue(RotateDegrees.NotSet), Category("Layout")]
        [Description("Indicates the title's display rotation.")]
        public RotateDegrees RotateDegrees
        {
            get { return (_RotateDegrees); }
            set
            {
                if (value != _RotateDegrees)
                {
                    _RotateDegrees = value;
                    OnPropertyChangedEx("RotateDegrees", VisualChangeType.Layout);
                }
            }
        }
        #endregion
        #region XyAlignment
        /// 
        /// Gets or sets the X/Y Alignment for the title.
        /// 
        [DefaultValue(XyAlignment.NotSet), Category("Layout")]
        [Description("Indicates the X/Y Alignment for the title.")]
        public XyAlignment XyAlignment
        {
            get { return (_XyAlignment); }
            set
            {
                if (value != _XyAlignment)
                {
                    _XyAlignment = value;
                    OnPropertyChangedEx("XyAlignment", VisualChangeType.Layout);
                }
            }
        }
        #endregion
        #endregion
        #region MeasureOverride
        protected override void MeasureOverride(ChartLayoutInfo layoutInfo)
        {
            Graphics g = layoutInfo.Graphics;
            ChartTitleVisualStyle style = EffectiveTitleStyle;
            Size size = Size.Empty;
            Rectangle layoutBounds = layoutInfo.LayoutBounds;
            RotateDegrees rotDegrees = GetRotateDegrees(style);
            if (rotDegrees == RotateDegrees.Rotate90 || rotDegrees == RotateDegrees.Rotate270)
                layoutBounds.Size = new Size(layoutBounds.Height, layoutBounds.Width);
            Thickness brdThickness = style.BorderThickness;
            Size ncSize = GetNonContentSize(style, brdThickness);
            layoutBounds.Width -= ncSize.Width;
            layoutBounds.Height -= ncSize.Height;
            Alignment imageAlignment = style.ImageAlignment;
            Size imageSize = style.GetFigureSize(g);
            if (layoutBounds.Width > 0 && layoutBounds.Height > 0)
            {
                if (imageSize.IsEmpty == false)
                {
                    if (style.IsOverlayImage == true)
                        imageAlignment = Alignment.MiddleCenter;
                    else if (imageAlignment == Alignment.NotSet)
                        imageAlignment = Alignment.MiddleLeft;
                    switch (imageAlignment)
                    {
                        case Alignment.TopLeft:
                        case Alignment.TopRight:
                        case Alignment.BottomLeft:
                        case Alignment.BottomRight:
                        case Alignment.MiddleLeft:
                        case Alignment.MiddleRight:
                            if (rotDegrees == RotateDegrees.Rotate90 || rotDegrees == RotateDegrees.Rotate270)
                                layoutBounds.Height -= imageSize.Width;
                            else
                                layoutBounds.Width -= imageSize.Width;
                            break;
                        case Alignment.TopCenter:
                        case Alignment.BottomCenter:
                            layoutBounds.Height -= imageSize.Height;
                            break;
                    }
                    if (layoutBounds.Size.Width > 0 && layoutBounds.Size.Height > 0)
                        size = MeasureText(g, style, layoutBounds.Size);
                    switch (imageAlignment)
                    {
                        case Alignment.TopLeft:
                        case Alignment.TopRight:
                        case Alignment.MiddleLeft:
                        case Alignment.MiddleRight:
                        case Alignment.BottomLeft:
                        case Alignment.BottomRight:
                            size.Width += imageSize.Width;
                            size.Height = Math.Max(imageSize.Height, size.Height);
                            break;
                        case Alignment.TopCenter:
                        case Alignment.BottomCenter:
                            size.Height += imageSize.Height;
                            size.Width = Math.Max(imageSize.Width, size.Width);
                            break;
                        case Alignment.MiddleCenter:
                            size.Height = Math.Max(imageSize.Height, size.Height);
                            size.Width = Math.Max(imageSize.Width, size.Width);
                            break;
                    }
                }
                else
                {
                    size = MeasureText(g, style, layoutBounds.Size);
                }
                size.Width += ncSize.Width;
                size.Height += ncSize.Height;
            }
            if (FixedHeight > 0)
                size.Height = Dpi.Height(FixedHeight);
            Rectangle bounds = layoutBounds;
            if (style.Stretch == Tbool.True)
            {
                switch (XyAlignment)
                {
                    case XyAlignment.Left:
                    case XyAlignment.Right:
                        if (rotDegrees == RotateDegrees.Rotate90 || rotDegrees == RotateDegrees.Rotate270)
                            size.Width = layoutInfo.LayoutBounds.Height;
                        break;
                    default:
                        if (rotDegrees != RotateDegrees.Rotate90 && rotDegrees != RotateDegrees.Rotate270)
                            size.Width = layoutInfo.LayoutBounds.Width;
                        break;
                }
            }
            Rectangle rb = bounds;
            if (rotDegrees == RotateDegrees.Rotate90 || rotDegrees == RotateDegrees.Rotate270)
                bounds.Size = new Size(size.Height, size.Width);
            else
                bounds.Size = size;
            if (bounds.Width > layoutInfo.LayoutBounds.Width)
                bounds.Width = layoutInfo.LayoutBounds.Width;
            if (bounds.Height > layoutInfo.LayoutBounds.Height)
                bounds.Height = layoutInfo.LayoutBounds.Height;
            Size = bounds.Size;
            bounds = AlignTitle(layoutInfo, bounds, style);
            _FrameBounds = GetAdjustedBoundsRot(bounds, style.Margin);
            if (style.DropShadow.Enabled == Tbool.True)
            {
                _FrameBounds.Width -= 3;
                _FrameBounds.Height -= 3;
            }
            _ContentBounds = _FrameBounds;
            if (brdThickness.IsEmpty == false)
            {
                _ContentBounds.X += brdThickness.Left;
                _ContentBounds.Width -= brdThickness.Horizontal;
                _ContentBounds.Y += brdThickness.Top;
                _ContentBounds.Height -= brdThickness.Vertical;
            }
            if (rotDegrees == RotateDegrees.Rotate90 || rotDegrees == RotateDegrees.Rotate270)
                _ContentBounds = GetAdjustedBoundsRot(_ContentBounds, style.Padding);
            else
                _ContentBounds = GetAdjustedBounds(_ContentBounds, style.Padding);
            if (imageSize.IsEmpty == false)
            {
                if (rotDegrees == RotateDegrees.Rotate90 || rotDegrees == RotateDegrees.Rotate270)
                    AdjustVerticalContent(rotDegrees, imageAlignment, imageSize);
                else
                    AdjustHorizontalContent(imageAlignment, imageSize);
            }
            BoundsRelative = bounds;
        }
        #region GetAdjustedBoundsRot
        internal Rectangle GetAdjustedBoundsRot(Rectangle bounds, Thickness thickness)
        {
            if (thickness.IsEmpty == false)
            {
                if (bounds.Width > Dpi.Height(thickness.Vertical))
                {
                    bounds.X += Dpi.Height(thickness.Top);
                    bounds.Width -= Dpi.Height(thickness.Vertical);
                }
                if (bounds.Height > Dpi.Width(thickness.Horizontal))
                {
                    bounds.Y += Dpi.Width(thickness.Left);
                    bounds.Height -= Dpi.Width(thickness.Horizontal);
                }
            }
            return (bounds);
        }
        #endregion
        #region GetNonContentSize
        private Size GetNonContentSize(ChartTitleVisualStyle style, Thickness brdThickness)
        {
            Size size = Size.Empty;
            size.Width = Dpi.Width(style.Margin.Horizontal + brdThickness.Horizontal + style.Padding.Horizontal);
            size.Height = Dpi.Height(style.Margin.Vertical + brdThickness.Vertical + style.Padding.Vertical);
            if (style.DropShadow.Enabled == Tbool.True)
            {
                size.Width += 3;
                size.Height += 3;
            }
            return (size);
        }
        #endregion
        #region AdjustVerticalContent
        private void AdjustVerticalContent(
            RotateDegrees rotDegrees, Alignment imageAlignment, Size imageSize)
        {
            switch (imageAlignment)
            {
                case Alignment.TopLeft:
                case Alignment.MiddleLeft:
                case Alignment.BottomLeft:
                    if (rotDegrees == RotateDegrees.Rotate90)
                        _ContentBounds.Y += imageSize.Width;
                    else if (rotDegrees == RotateDegrees.Rotate270)
                        _ContentBounds.Y += imageSize.Width;
                    else
                        _ContentBounds.X += imageSize.Height;
                    _ContentBounds.Height -= imageSize.Width;
                    break;
                case Alignment.TopCenter:
                    if (rotDegrees == RotateDegrees.Rotate90)
                        _ContentBounds.X += imageSize.Height;
                    else if (rotDegrees == RotateDegrees.Rotate270)
                        _ContentBounds.X += imageSize.Height;
                    else
                        _ContentBounds.Y += imageSize.Width;
                    _ContentBounds.Width -= imageSize.Height;
                    break;
                case Alignment.BottomCenter:
                    _ContentBounds.Width -= imageSize.Height;
                    break;
                case Alignment.TopRight:
                case Alignment.MiddleRight:
                case Alignment.BottomRight:
                    _ContentBounds.Height -= imageSize.Width;
                    break;
            }
        }
        #endregion
        #region AdjustHorizontalContent
        private void AdjustHorizontalContent(
            Alignment imageAlignment, Size imageSize)
        {
            switch (imageAlignment)
            {
                case Alignment.TopLeft:
                case Alignment.MiddleLeft:
                case Alignment.BottomLeft:
                    _ContentBounds.X += imageSize.Width;
                    _ContentBounds.Width -= imageSize.Width;
                    break;
                case Alignment.TopCenter:
                    _ContentBounds.Y += imageSize.Height;
                    _ContentBounds.Height -= imageSize.Height;
                    break;
                case Alignment.BottomCenter:
                    _ContentBounds.Height -= imageSize.Height;
                    break;
                case Alignment.TopRight:
                case Alignment.MiddleRight:
                case Alignment.BottomRight:
                    _ContentBounds.Width -= imageSize.Width;
                    break;
            }
        }
        #endregion
        #region MeasureText
        private Size MeasureText(Graphics g, ChartTitleVisualStyle style, Size vsize)
        {
            Size size = Size.Empty;
            string s = Text;
            if (string.IsNullOrEmpty(s) == false)
            {
                if (TextMarkup != null)
                {
                    size = GetMarkupTextSize(g,
                        TextMarkup, style, (vsize.Width > 0 ? vsize.Width : 10000));
                }
                else
                {
                    using (StringFormat sf = new StringFormat())
                    {
                        style.GetStringFormatFlags(sf);
                        if (style.MaxLineCount <= 1)
                            sf.FormatFlags |= StringFormatFlags.NoWrap;
                        size = g.MeasureString(Text, style.Font, vsize, sf).ToSize();
                    }
                }
                size.Width++;
                size.Height++;
                if (style.MaxLineCount > 1)
                {
                    int lineHeight = (int)(Math.Ceiling(style.Font.GetHeight())) * style.MaxLineCount;
                    if (size.Height > lineHeight)
                        size.Height = lineHeight;
                }
            }
            _TextHeight = size.Height;
            return (size);
        }
        #region GetMarkupTextSize
        private Size GetMarkupTextSize(Graphics g,
            BodyElement textMarkup, ChartTitleVisualStyle style, int width)
        {
            MarkupDrawContext d =
                new MarkupDrawContext(g, style.Font, style.TextColor, false);
            textMarkup.InvalidateElementsSize();
            textMarkup.Measure(new Size(width, 0), d);
            return (textMarkup.Bounds.Size);
        }
        #endregion
        #endregion
        #region AlignTitle
        private Rectangle AlignTitle(
            ChartLayoutInfo layoutInfo, Rectangle bounds, ChartTitleVisualStyle style)
        {
            Rectangle layoutBounds = layoutInfo.LayoutBounds;
            switch (XyAlignment)
            {
                case XyAlignment.Left:
                    layoutInfo.LayoutBounds.X += Size.Width;
                    layoutInfo.LayoutBounds.Width -= Size.Width;
                    break;
                case XyAlignment.Bottom:
                    bounds.Y = layoutBounds.Bottom - Size.Height;
                    layoutInfo.LayoutBounds.Height -= Size.Height;
                    break;
                case XyAlignment.Right:
                    bounds.X = layoutBounds.Right - Size.Width;
                    layoutInfo.LayoutBounds.Width -= Size.Width;
                    break;
                default:
                    layoutInfo.LayoutBounds.Y += Size.Height;
                    layoutInfo.LayoutBounds.Height -= Size.Height;
                    break;
            }
            if (XyAlignment == XyAlignment.Left || XyAlignment == XyAlignment.Right)
            {
                if (bounds.Height < layoutBounds.Height)
                {
                    switch (style.Alignment)
                    {
                        case Alignment.TopCenter:
                        case Alignment.MiddleCenter:
                        case Alignment.BottomCenter:
                            bounds.Y += (layoutBounds.Height - bounds.Height) / 2;
                            break;
                        case Alignment.TopLeft:
                        case Alignment.MiddleLeft:
                        case Alignment.BottomLeft:
                            bounds.Y = layoutBounds.Bottom - bounds.Height;
                            break;
                    }
                }
            }
            else
            {
                if (bounds.Width < layoutBounds.Width)
                {
                    switch (style.Alignment)
                    {
                        case Alignment.TopCenter:
                        case Alignment.MiddleCenter:
                        case Alignment.BottomCenter:
                            bounds.X += (layoutBounds.Width - bounds.Width) / 2;
                            break;
                        case Alignment.TopRight:
                        case Alignment.MiddleRight:
                        case Alignment.BottomRight:
                            bounds.X = layoutBounds.Right - bounds.Width;
                            break;
                    }
                }
            }
            return (bounds);
        }
        #endregion
        #endregion
        #region ArrangeOverride
        protected override void ArrangeOverride(ChartLayoutInfo layoutInfo)
        {
        }
        #endregion
        #region RenderOverride
        protected override void RenderOverride(ChartRenderInfo renderInfo)
        {
            Graphics g = renderInfo.Graphics;
            Rectangle scFrameBounds = GetScrollBounds(_FrameBounds);
            Rectangle scContentBounds = GetScrollBounds(_ContentBounds);
            if (scFrameBounds.Height > 0 && scFrameBounds.Width > 0)
            {
                ChartTitleVisualStyle tstyle = EffectiveTitleStyle;
                Rectangle rfb = scFrameBounds;
                Rectangle rcb = scContentBounds;
                RotateDegrees rotDegrees = GetRotateDegrees(tstyle);
                if (rotDegrees != RotateDegrees.None)
                {
                    TransformBounds(g, scFrameBounds, rotDegrees);
                    rfb = TranslateFrameBounds(scFrameBounds, rotDegrees);
                    rcb = TranslateContentBounds(scFrameBounds, scContentBounds, rotDegrees);
                }
                RenderBackground(g, rfb, tstyle);
                RenderTextAndFigure(g, rfb, rcb, rotDegrees, tstyle);
                if (rotDegrees != RotateDegrees.None)
                    g.ResetTransform();
                tstyle.RenderBorder(g, scFrameBounds);
                if (tstyle.DropShadow.Enabled == Tbool.True)
                    tstyle.DropShadow.RenderDropShadow(g, scFrameBounds, true, true);
            }
        }
        #region TransformBounds
        private void TransformBounds(Graphics g, Rectangle rfb, RotateDegrees rotDegrees)
        {
            switch (rotDegrees)
            {
                case RotateDegrees.Rotate90:
                    g.TranslateTransform(rfb.Right, rfb.Y);
                    g.RotateTransform(90);
                    break;
                case RotateDegrees.Rotate180:
                    g.TranslateTransform(rfb.Right, rfb.Bottom);
                    g.RotateTransform(-180);
                    break;
                case RotateDegrees.Rotate270:
                    g.TranslateTransform(rfb.X, rfb.Bottom);
                    g.RotateTransform(-90);
                    break;
            }
        }
        #endregion
        #region TranslateFrameBounds
        private Rectangle TranslateFrameBounds(Rectangle rfb, RotateDegrees rotDegrees)
        {
            Rectangle tfb = new Rectangle(0, 0, rfb.Width, rfb.Height);
            switch (rotDegrees)
            {
                case RotateDegrees.Rotate90:
                case RotateDegrees.Rotate270:
                    tfb.Width = rfb.Height;
                    tfb.Height = rfb.Width;
                    break;
            }
            return (tfb);
        }
        #endregion
        #region TranslateContentBounds
        private Rectangle TranslateContentBounds(Rectangle rfb, Rectangle rcb, RotateDegrees rotDegrees)
        {
            Rectangle tcb = new Rectangle(rcb.X - rfb.X, rcb.Y - rfb.Y, rcb.Width, rcb.Height);
            switch (rotDegrees)
            {
                case RotateDegrees.Rotate90:
                    int X = tcb.X;
                    tcb.X = tcb.Y;
                    tcb.Y = X;
                    tcb.Width = rcb.Height;
                    tcb.Height = rcb.Width;
                    break;
                case RotateDegrees.Rotate270:
                    int X1 = tcb.X;
                    tcb.X = tcb.Y;
                    tcb.Y = X1;
                    tcb.Width = rcb.Height;
                    tcb.Height = rcb.Width;
                    break;
            }
            return (tcb);
        }
        #endregion
        #region CalcImageBounds
        private Rectangle CalcImageBounds(
            Rectangle rfb, RotateDegrees rotDegrees, ChartTitleVisualStyle style)
        {
            if (style.BorderThickness.IsEmpty == false)
            {
                switch (rotDegrees)
                {
                    case RotateDegrees.Rotate90:
                        rfb.X += Dpi.Height(style.BorderThickness.Top);
                        rfb.Width -= Dpi.Height(style.BorderThickness.Vertical);
                        rfb.Y += Dpi.Width(style.BorderThickness.Right);
                        rfb.Height -= Dpi.Width(style.BorderThickness.Horizontal);
                        break;
                    case RotateDegrees.Rotate270:
                        rfb.X += Dpi.Height(style.BorderThickness.Bottom);
                        rfb.Width -= Dpi.Height(style.BorderThickness.Vertical);
                        rfb.Y += Dpi.Width(style.BorderThickness.Left);
                        rfb.Height -= Dpi.Width(style.BorderThickness.Horizontal);
                        break;
                    case RotateDegrees.Rotate180:
                        rfb.X += Dpi.Width(style.BorderThickness.Right);
                        rfb.Width -= Dpi.Width(style.BorderThickness.Horizontal);
                        rfb.Y += Dpi.Height(style.BorderThickness.Bottom);
                        rfb.Height -= Dpi.Height(style.BorderThickness.Vertical);
                        break;
                    default:
                        rfb.X += Dpi.Width(style.BorderThickness.Left);
                        rfb.Width -= Dpi.Width(style.BorderThickness.Horizontal);
                        rfb.Y += Dpi.Height(style.BorderThickness.Top);
                        rfb.Height -= Dpi.Height(style.BorderThickness.Vertical);
                        break;
                }
            }
            return (rfb);
        }
        #endregion
        #region RenderBackground
        private void RenderBackground(
            Graphics g, Rectangle r, ChartTitleVisualStyle style)
        {
            if (r.Width > 2 && r.Height > 2)
            {
                using (Brush br = style.Background.GetBrush(r))
                    g.FillRectangle(br, r);
            }
        }
        #endregion
        #region RenderTextAndFigure
        private void RenderTextAndFigure(Graphics g, Rectangle rfb,
            Rectangle rcb, RotateDegrees rotDegrees, ChartTitleVisualStyle tstyle)
        {
            Rectangle rib = Rectangle.Empty;
            object figure = tstyle.GetFigure();
            if (figure != null)
            {
                rib = CalcImageBounds(rfb, rotDegrees, tstyle);
                if (tstyle.ImageOverlay != ImageOverlay.Top)
                    RenderFigure(g, figure, rib, tstyle);
            }
            RenderText(g, rcb, tstyle);
            if (figure != null)
            {
                if (tstyle.ImageOverlay == ImageOverlay.Top)
                    RenderFigure(g, figure, rib, tstyle);
            }
        }
        #region RenderFigure
        private void RenderFigure(Graphics g,
            object figure, Rectangle r, ChartTitleVisualStyle tstyle)
        {
            Rectangle t = tstyle.GetFigureBounds(g, r);
            t.Intersect(r);
            if (t.Width > 0 && t.Height > 0)
            {
                SymbolDef sd = figure as SymbolDef;
                if (sd != null && sd.IsValidSymbol == true)
                {
                    using (Brush br = new SolidBrush(sd.SymbolColor))
                        g.DrawString(sd.SymbolRealized, sd.SymbolFont, br, t);
                }
                else
                {
                    Image image = figure as Image;
                    if (image != null)
                        g.DrawImage(image, t);
                }
            }
        }
        #endregion
        #region RenderText
        private void RenderText(
            Graphics g, Rectangle r, ChartTitleVisualStyle style)
        {
            if (r.Width > 0 && r.Height > 0)
            {
                string s = Text;
                if (string.IsNullOrEmpty(s) == false)
                {
                    if (TextMarkup != null)
                    {
                        RenderTextMarkup(g, r, style);
                    }
                    else
                    {
                        using (SolidBrush br = new SolidBrush(style.TextColor))
                        {
                            using (StringFormat sf = new StringFormat())
                            {
                                style.GetStringFormatFlags(sf);
                                if (style.MaxLineCount <= 1)
                                    sf.FormatFlags |= StringFormatFlags.NoWrap;
                                if (r.Height > _TextHeight)
                                {
                                    if (sf.LineAlignment == StringAlignment.Center)
                                    {
                                        r.Y += (r.Height - _TextHeight) / 2;
                                        r.Height = _TextHeight;
                                    }
                                }
                                g.DrawString(Text, style.Font, br, r, sf);
                            }
                        }
                    }
                }
            }
        }
        #region RenderTextMarkup
        private void RenderTextMarkup(
            Graphics g, Rectangle r, ChartTitleVisualStyle style)
        {
            MarkupDrawContext d =
                new MarkupDrawContext(g, style.Font, style.TextColor, false);
            TextMarkup.Arrange(r, d);
            Size size = TextMarkup.Bounds.Size;
            switch (style.Alignment)
            {
                case Alignment.MiddleLeft:
                case Alignment.MiddleCenter:
                case Alignment.MiddleRight:
                    if (r.Height > size.Height)
                        r.Y += (r.Height - size.Height) / 2;
                    break;
                default:
                    if (r.Height > size.Height)
                        r.Y = r.Bottom - size.Height;
                    break;
            }
            TextMarkup.Bounds = new Rectangle(r.Location, size);
            Region oldClip = g.Clip;
            try
            {
                g.SetClip(r, CombineMode.Intersect);
                TextMarkup.Render(d);
            }
            finally
            {
                g.Clip = oldClip;
            }
        }
        #endregion
        #endregion
        #endregion
        #endregion
        #region GetRotateDegrees
        private RotateDegrees GetRotateDegrees(ChartTitleVisualStyle style)
        {
            switch (RotateDegrees)
            {
                case RotateDegrees.Auto:
                case RotateDegrees.NotSet:
                switch (XyAlignment)
                {
                    case XyAlignment.Left:
                        return (RotateDegrees.Rotate270);
                    case XyAlignment.Right:
                        return (RotateDegrees.Rotate90);
                    default:
                        return (RotateDegrees.None);
                }
            }
            return (RotateDegrees);
        }
        #endregion
        #region Style Support
        #region ApplyStyles
        public override void ApplyStyles(BaseVisualStyle style)
        {
            ChartTitleVisualStyle tstyle = style as ChartTitleVisualStyle;
            if (tstyle != null)
            {
                ApplyParentStyles(tstyle, Parent as ChartContainer);
                tstyle.ApplyStyle(ChartTitleVisualStyle);
                tstyle.ApplyDefaults();
            }
        }
        #endregion
        #region ApplyParentStyles
        private void ApplyParentStyles(ChartTitleVisualStyle tstyle, ChartContainer item)
        {
            if (item != null)
            {
                ApplyParentStyles(tstyle, item.Parent as ChartContainer);
                if (item is ChartPanel)
                    tstyle.ApplyStyle(((ChartPanel)item).DefaultVisualStyles.ChartTitleVisualStyle);
            }
            else
            {
                tstyle.ApplyStyle(ChartControl.BaseVisualStyles.ChartTitleVisualStyle);
                tstyle.ApplyStyle(ChartControl.DefaultVisualStyles.ChartTitleVisualStyle);
            }
        }
        #endregion
        #region InvalidateStyle
        ///
        ///Invalidate the cached Styles
        ///
        public void InvalidateStyle()
        {
            ClearEffectiveStyles();
        }
        #endregion
        #region ClearEffectiveStyles
        protected override void ClearEffectiveStyles()
        {
            base.ClearEffectiveStyles();
            _EffectiveTitleStyle.InvalidateStyle();
        }
        #endregion
        #endregion
        #region Copy/CopyTo
        public override ChartVisualElement Copy()
        {
            ChartTitle copy = new ChartTitle();
            CopyTo(copy);
            return (copy);
        }
        public override void CopyTo(ChartVisualElement copy)
        {
            ChartTitle c = copy as ChartTitle;
            if (c != null)
            {
                base.CopyTo(c);
                c.ChartTitleVisualStyle = 
                    (_ChartTitleVisualStyle != null) ? ChartTitleVisualStyle.Copy() : null;
                c.RotateDegrees = RotateDegrees;
                c.XyAlignment = XyAlignment;
            }
        }
        #endregion
        #region GetSerialData
        internal override SerialElementCollection GetSerialData(string serialName)
        {
            SerialElementCollection sec = new SerialElementCollection();
            if (serialName != null)
            {
                if (serialName.Equals("") == true)
                    serialName = "ChartTitle";
                sec.AddStartElement(serialName);
            }
            if (_ChartTitleVisualStyle != null && _ChartTitleVisualStyle.IsEmpty == false)
                sec.AddElement(_ChartTitleVisualStyle.GetSerialData("ChartTitleVisualStyle"));
            sec.AddValue("RotateDegrees", RotateDegrees, RotateDegrees.NotSet);
            sec.AddValue("XyAlignment", XyAlignment, XyAlignment.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 "RotateDegrees":
                    RotateDegrees = (RotateDegrees)se.GetValueEnum(typeof(RotateDegrees));
                    break;
                case "XyAlignment":
                    XyAlignment = (XyAlignment)se.GetValueEnum(typeof(XyAlignment));
                    break;
                default:
                    base.ProcessValue(se);
                    break;
            }
        }
        #endregion
        #region ProcessCollection
        internal override void ProcessCollection(SerialElement se)
        {
            SerialElementCollection sec = se.Sec;
            switch (se.Name)
            {
                case "ChartTitleVisualStyle":
                    sec.PutSerialData(ChartTitleVisualStyle);
                    break;
                default:
                    base.ProcessCollection(se);
                    break;
            }
        }
        #endregion
        #endregion
        #region States
        [Flags]
        private enum States : uint
        {
        }
        #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()
        {
            ChartTitleVisualStyle = null;
            base.Dispose();
        }
        #endregion
    }
}