6324 lines
		
	
	
		
			195 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			6324 lines
		
	
	
		
			195 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System;
 | 
						|
using System.Collections;
 | 
						|
using System.Collections.Generic;
 | 
						|
using System.ComponentModel;
 | 
						|
using System.Drawing;
 | 
						|
using System.Drawing.Design;
 | 
						|
using System.Drawing.Drawing2D;
 | 
						|
using System.Drawing.Text;
 | 
						|
using System.Windows.Forms;
 | 
						|
using DevComponents.DotNetBar.Charts.Style;
 | 
						|
 | 
						|
namespace DevComponents.DotNetBar.Charts
 | 
						|
{
 | 
						|
    /// <summary>
 | 
						|
    /// Represents the collection of PieSeries.
 | 
						|
    /// </summary>
 | 
						|
    [Editor("DevComponents.Charts.Design.ChartSeriesCollectionEditor, DevComponents.Charts.Design, " +
 | 
						|
            "Version=14.1.0.37, Culture=neutral,  PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
 | 
						|
    public class ChartPieSeriesCollection : CustomNamedCollection<PieSeries>
 | 
						|
    {
 | 
						|
        #region GetUniqueName
 | 
						|
 | 
						|
        public string GetUniqueName()
 | 
						|
        {
 | 
						|
            return (GetUniqueName("Series"));
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
    }
 | 
						|
 | 
						|
    [TypeConverter(typeof(PieSeriesConverter))]
 | 
						|
    public class PieSeries : BaseSeries, ISeriesPointContainer, ILegendItemEx
 | 
						|
    {
 | 
						|
        #region Private variables
 | 
						|
 | 
						|
        private States _States;
 | 
						|
 | 
						|
        private PieSeriesPointCollection _SeriesPoints;
 | 
						|
 | 
						|
        private double _ExplodedMargin = double.NaN;
 | 
						|
 | 
						|
        private Point _PieCenter;
 | 
						|
        private List<PieRing> _PieRings;
 | 
						|
 | 
						|
        private int _RingWeightTotal;
 | 
						|
 | 
						|
        private Tbool _CenterFirstSlice = Tbool.NotSet;
 | 
						|
 | 
						|
        private Tbool _ShowAllRings = Tbool.NotSet;
 | 
						|
        private Tbool _ShowOtherSlice = Tbool.NotSet;
 | 
						|
 | 
						|
        private PieSeriesPointCollection _ActiveSeriesPointSet;
 | 
						|
 | 
						|
        private MouseClickSliceAction _MouseClickSliceAction = MouseClickSliceAction.NotSet;
 | 
						|
        private MouseDoubleClickSliceAction _MouseDoubleClickSliceAction = MouseDoubleClickSliceAction.NotSet;
 | 
						|
 | 
						|
        private PieSelectionMode _PieSelectionMode = PieSelectionMode.NotSet;
 | 
						|
 | 
						|
        private PieSeriesPoint _MouseDownPsp;
 | 
						|
        private int _MouseDownRadius;
 | 
						|
        private int _MouseDownOffset;
 | 
						|
 | 
						|
        private Tbool _EnableDragDetach = Tbool.NotSet;
 | 
						|
 | 
						|
        private SymbolDef _ScaleSymDef = new SymbolDef();
 | 
						|
        private float _SymFontScale = -1;
 | 
						|
 | 
						|
        private SliceVisualLayout _SliceVisualLayout;
 | 
						|
 | 
						|
        private int _RingWeight = 100;
 | 
						|
        private int _RingWeightEx;
 | 
						|
 | 
						|
        private PaletteGroup _PaletteGroup = PaletteGroup.NotSet;
 | 
						|
        private Color[] _CustomPalette;
 | 
						|
 | 
						|
        private double _PieOuterExtent;
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Constructors
 | 
						|
 | 
						|
        public PieSeries()
 | 
						|
            : this(null)
 | 
						|
        {
 | 
						|
        }
 | 
						|
 | 
						|
        public PieSeries(string name)
 | 
						|
        {
 | 
						|
            Name = name;
 | 
						|
            SeriesType = SeriesType.Pie;
 | 
						|
 | 
						|
            InitDefaultStates();
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region InitDefaultStates
 | 
						|
 | 
						|
        private void InitDefaultStates()
 | 
						|
        {
 | 
						|
            SetState(States.ShowInnerRingsEx, true);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Public properties
 | 
						|
 | 
						|
        #region CenterFirstSlice
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets or sets whether the first pie slice is centered
 | 
						|
        /// on the starting angle or starts on the starting angle. Default is false.
 | 
						|
        /// </summary>
 | 
						|
        [DefaultValue(Tbool.NotSet), Category("Display")]
 | 
						|
        [Description("Indicates whether the first pie slice is centered on the starting angle or starts on the starting angle. Default is false.")]
 | 
						|
        public Tbool CenterFirstSlice
 | 
						|
        {
 | 
						|
            get { return (_CenterFirstSlice); }
 | 
						|
 | 
						|
            set
 | 
						|
            {
 | 
						|
                if (value != _CenterFirstSlice)
 | 
						|
                {
 | 
						|
                    _CenterFirstSlice = value;
 | 
						|
 | 
						|
                    OnPropertyChangedEx("CenterFirstSlice", VisualChangeType.Layout);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region CustomPalette
 | 
						|
 | 
						|
        ///<summary>
 | 
						|
        /// Gets or sets the custom palette for the series.
 | 
						|
        ///</summary>
 | 
						|
        [DefaultValue(null), Category("Appearance")]
 | 
						|
        [Description("Indicates the custom palette for the series.")]
 | 
						|
        public Color[] CustomPalette
 | 
						|
        {
 | 
						|
            get { return (_CustomPalette); }
 | 
						|
 | 
						|
            set
 | 
						|
            {
 | 
						|
                _CustomPalette = value;
 | 
						|
 | 
						|
                OnPropertyChangedEx("CustomPalette", VisualChangeType.Layout);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region EnableDragDetach
 | 
						|
 | 
						|
        ///<summary>
 | 
						|
        /// Gets or sets whether the user can detach associated series elements by Click and drag.
 | 
						|
        /// Note that MouseClickSelect must not be set to None or NotSet.
 | 
						|
        ///</summary>
 | 
						|
        [DefaultValue(Tbool.NotSet), Category("Behavior")]
 | 
						|
        [Description("Indicates whether the user can detach associated series elements by Click and drag. Note that MouseClickSelect must not be set to None or NotSet.")]
 | 
						|
        public Tbool EnableDragDetach
 | 
						|
        {
 | 
						|
            get { return (_EnableDragDetach); }
 | 
						|
 | 
						|
            set
 | 
						|
            {
 | 
						|
                if (value != _EnableDragDetach)
 | 
						|
                {
 | 
						|
                    _EnableDragDetach = value;
 | 
						|
 | 
						|
                    OnPropertyChangedEx("EnableDragDetach", VisualChangeType.Layout);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetEnableDragDetach
 | 
						|
 | 
						|
        internal bool GetEnableDragDetach(PieChart pieChart)
 | 
						|
        {
 | 
						|
            Tbool enable = EnableDragDetach;
 | 
						|
 | 
						|
            if (enable == Tbool.NotSet)
 | 
						|
                enable = pieChart.EnableDragDetach;
 | 
						|
 | 
						|
            return (enable == Tbool.True);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region ExplodedMargin
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets or sets the exploded Margin for the series when the pie
 | 
						|
        /// is Exploded. The Margin is is measured as a percentage of the pie
 | 
						|
        /// radius (if less than 1) or the absolute pixel amount (if greater than 1).
 | 
						|
        /// </summary>
 | 
						|
        [DefaultValue(double.NaN), Category("Layout")]
 | 
						|
        [Description("Indicates the exploded Margin for the series when the pie is Exploded. The Margin is is measured as a percentage of the pie radius (if <= 1) or the absolute pixel amount (if > 1).")]
 | 
						|
        public double ExplodedMargin
 | 
						|
        {
 | 
						|
            get { return (_ExplodedMargin); }
 | 
						|
 | 
						|
            set
 | 
						|
            {
 | 
						|
                if (value != _ExplodedMargin)
 | 
						|
                {
 | 
						|
                    _ExplodedMargin = value;
 | 
						|
 | 
						|
                    OnPropertyChangedEx("ExplodedMargin", VisualChangeType.Layout);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region MouseClickSliceAction
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets or sets the action used when the user clicks on a pie slice.
 | 
						|
        /// </summary>
 | 
						|
        [DefaultValue(MouseClickSliceAction.NotSet), Category("Behavior")]
 | 
						|
        [Description("Indicates the action used when the user clicks on a pie slice.")]
 | 
						|
        public MouseClickSliceAction MouseClickSliceAction
 | 
						|
        {
 | 
						|
            get { return (_MouseClickSliceAction); }
 | 
						|
 | 
						|
            set
 | 
						|
            {
 | 
						|
                if (value != _MouseClickSliceAction)
 | 
						|
                {
 | 
						|
                    _MouseClickSliceAction = value;
 | 
						|
 | 
						|
                    OnPropertyChanged("MouseClickSliceAction");
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetMouseClickSliceAction
 | 
						|
 | 
						|
        private MouseClickSliceAction GetMouseClickSliceAction(PieChart pieChart)
 | 
						|
        {
 | 
						|
            MouseClickSliceAction mca =
 | 
						|
                (MouseClickSliceAction != MouseClickSliceAction.NotSet)
 | 
						|
                ? MouseClickSliceAction : pieChart.MouseClickSliceAction;
 | 
						|
 | 
						|
            return ((mca != MouseClickSliceAction.NotSet) ? mca : MouseClickSliceAction.None);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region MouseDoubleClickSliceAction
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets or sets the action used when the user double-clicks on a pie slice.
 | 
						|
        /// </summary>
 | 
						|
        [DefaultValue(MouseDoubleClickSliceAction.NotSet), Category("Behavior")]
 | 
						|
        [Description("Indicates the action used when the user clicks on a pie slice.")]
 | 
						|
        public MouseDoubleClickSliceAction MouseDoubleClickSliceAction
 | 
						|
        {
 | 
						|
            get { return (_MouseDoubleClickSliceAction); }
 | 
						|
 | 
						|
            set
 | 
						|
            {
 | 
						|
                if (value != _MouseDoubleClickSliceAction)
 | 
						|
                {
 | 
						|
                    _MouseDoubleClickSliceAction = value;
 | 
						|
 | 
						|
                    OnPropertyChanged("MouseDoubleClickSliceAction");
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetMouseDoubleClickSliceAction
 | 
						|
 | 
						|
        private MouseDoubleClickSliceAction GetMouseDoubleClickSliceAction(PieChart pieChart)
 | 
						|
        {
 | 
						|
            MouseDoubleClickSliceAction mca =
 | 
						|
                (MouseDoubleClickSliceAction != MouseDoubleClickSliceAction.NotSet)
 | 
						|
                ? MouseDoubleClickSliceAction : pieChart.MouseDoubleClickSliceAction;
 | 
						|
 | 
						|
            return ((mca != MouseDoubleClickSliceAction.NotSet) ? mca : MouseDoubleClickSliceAction.None);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region PaletteGroup
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets or sets the palette color group to use (Light/Medium/Dark/Color1/MonoBlue/etc).
 | 
						|
        /// </summary>
 | 
						|
        [DefaultValue(PaletteGroup.NotSet), Category("Appearance")]
 | 
						|
        [Description("Indicates the palette color group to use (Light/Medium/Dark/Color1/MonoBlue/etc.).")]
 | 
						|
        public PaletteGroup PaletteGroup
 | 
						|
        {
 | 
						|
            get { return (_PaletteGroup); }
 | 
						|
 | 
						|
            set
 | 
						|
            {
 | 
						|
                if (value != _PaletteGroup)
 | 
						|
                {
 | 
						|
                    _PaletteGroup = value;
 | 
						|
 | 
						|
                    OnPropertyChangedEx("PaletteGroup", VisualChangeType.Recalc);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region PieSelectionMode
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets or sets the mode used to perfoem pie selections.
 | 
						|
        /// </summary>
 | 
						|
        [DefaultValue(PieSelectionMode.NotSet), Category("Behavior")]
 | 
						|
        [Description("Indicates the mode used to perform pie selections.")]
 | 
						|
        public PieSelectionMode PieSelectionMode
 | 
						|
        {
 | 
						|
            get { return (_PieSelectionMode); }
 | 
						|
 | 
						|
            set
 | 
						|
            {
 | 
						|
                if (value != _PieSelectionMode)
 | 
						|
                {
 | 
						|
                    _PieSelectionMode = value;
 | 
						|
 | 
						|
                    OnPropertyChanged("PieSelectionMode");
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetPieSelectionMode
 | 
						|
 | 
						|
        internal PieSelectionMode GetPieSelectionMode(PieChart pieChart)
 | 
						|
        {
 | 
						|
            PieSelectionMode psm = PieSelectionMode;
 | 
						|
 | 
						|
            if (psm == PieSelectionMode.NotSet)
 | 
						|
                psm = pieChart.PieSelectionMode;
 | 
						|
 | 
						|
            return ((psm != PieSelectionMode.NotSet) ? psm : PieSelectionMode.Slice);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region ReversePaletteColors
 | 
						|
 | 
						|
        ///<summary>
 | 
						|
        /// Gets or sets whether default palette colors are utilized in reverse order.
 | 
						|
        ///</summary>
 | 
						|
        [DefaultValue(false), Category("Behavior")]
 | 
						|
        [Description("Indicates whether default palette colors are utilized in reverse order.")]
 | 
						|
        public virtual bool ReversePaletteColors
 | 
						|
        {
 | 
						|
            get { return (TestState(States.ReversePaletteColors)); }
 | 
						|
 | 
						|
            set
 | 
						|
            {
 | 
						|
                if (value != ReversePaletteColors)
 | 
						|
                {
 | 
						|
                    SetState(States.ReversePaletteColors, value);
 | 
						|
 | 
						|
                    OnPropertyChangedEx("ReversePaletteColors", VisualChangeType.Layout);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RingWeight
 | 
						|
 | 
						|
        ///<summary>
 | 
						|
        /// Gets or sets the 'relative' total combined thickness of all series rings, as
 | 
						|
        /// compared to the relative thickness of other series combined rings.
 | 
						|
        /// rings.
 | 
						|
        ///</summary>
 | 
						|
        [DefaultValue(100), Category("Layout")]
 | 
						|
        [Description("Indicates the 'relative' total combined thickness of all series rings, as compared to the relative thickness of other series combined rings.. Default is 100.")]
 | 
						|
        public int RingWeight
 | 
						|
        {
 | 
						|
            get { return (_RingWeight); }
 | 
						|
 | 
						|
            set
 | 
						|
            {
 | 
						|
                if (value != _RingWeight)
 | 
						|
                {
 | 
						|
                    _RingWeight = value;
 | 
						|
 | 
						|
                    OnPropertyChangedEx("RingWeight", Style.VisualChangeType.Recalc);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region SeriesPoints
 | 
						|
 | 
						|
        ///<summary>
 | 
						|
        /// Gets or sets the series point data collection.
 | 
						|
        ///</summary>
 | 
						|
        [Category("Data")]
 | 
						|
        [Description("Indicates the series point data collection.")]
 | 
						|
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
 | 
						|
        public PieSeriesPointCollection SeriesPoints
 | 
						|
        {
 | 
						|
            get
 | 
						|
            {
 | 
						|
                if (_SeriesPoints == null)
 | 
						|
                {
 | 
						|
                    _SeriesPoints = new PieSeriesPointCollection();
 | 
						|
 | 
						|
                    _SeriesPoints.Parent = this;
 | 
						|
 | 
						|
                    _SeriesPoints.CollectionChanged += SeriesPoints_CollectionChanged;
 | 
						|
                }
 | 
						|
 | 
						|
                return (_SeriesPoints);
 | 
						|
            }
 | 
						|
 | 
						|
            set
 | 
						|
            {
 | 
						|
                if (value != _SeriesPoints)
 | 
						|
                {
 | 
						|
                    if (_SeriesPoints != null)
 | 
						|
                    {
 | 
						|
                        _SeriesPoints.Parent = null;
 | 
						|
 | 
						|
                        _SeriesPoints.CollectionChanged -= SeriesPoints_CollectionChanged;
 | 
						|
                    }
 | 
						|
 | 
						|
                    _SeriesPoints = value;
 | 
						|
 | 
						|
                    if (_SeriesPoints != null)
 | 
						|
                    {
 | 
						|
                        _SeriesPoints.Parent = this;
 | 
						|
 | 
						|
                        _SeriesPoints.CollectionChanged += SeriesPoints_CollectionChanged;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region SeriesPoints_CollectionChanged
 | 
						|
 | 
						|
        void SeriesPoints_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
 | 
						|
        {
 | 
						|
            SeriesRangeChanged = true;
 | 
						|
 | 
						|
            SetPointNotify(e.OldItems, false);
 | 
						|
            SetPointNotify(e.NewItems, true);
 | 
						|
 | 
						|
            InvalidateLayout();
 | 
						|
        }
 | 
						|
 | 
						|
        #region SetPointNotify
 | 
						|
 | 
						|
        private void SetPointNotify(IList list, bool notify)
 | 
						|
        {
 | 
						|
            if (list != null)
 | 
						|
            {
 | 
						|
                for (int i = 0; i < list.Count; i++)
 | 
						|
                {
 | 
						|
                    PieSeriesPoint psp = list[i] as PieSeriesPoint;
 | 
						|
 | 
						|
                    if (psp != null)
 | 
						|
                    {
 | 
						|
                        if (notify == true)
 | 
						|
                        {
 | 
						|
                            psp.Parent = SeriesPoints;
 | 
						|
                            psp.PropertyChanged += Sp_PropertyChanged;
 | 
						|
                        }
 | 
						|
                        else
 | 
						|
                        {
 | 
						|
                            psp.Parent = null;
 | 
						|
                            psp.PropertyChanged -= Sp_PropertyChanged;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Sp_PropertyChanged
 | 
						|
 | 
						|
        void Sp_PropertyChanged(object sender, PropertyChangedEventArgs e)
 | 
						|
        {
 | 
						|
            VisualPropertyChangedEventArgs vce = e as VisualPropertyChangedEventArgs;
 | 
						|
 | 
						|
            if (vce != null)
 | 
						|
            {
 | 
						|
                if (vce.ChangeType == VisualChangeType.Recalc)
 | 
						|
                {
 | 
						|
                    InvalidateRecalc();
 | 
						|
                }
 | 
						|
                else if (vce.ChangeType == VisualChangeType.Layout)
 | 
						|
                {
 | 
						|
                    InvalidateLayout();
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    PieSeriesPoint psp = sender as PieSeriesPoint;
 | 
						|
 | 
						|
                    if (psp != null)
 | 
						|
                    {
 | 
						|
                        InvalidateRender(psp.Bounds);
 | 
						|
                        InvalidateRender(psp.PathBounds);
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        InvalidateRender();
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                if (ChartControl != null)
 | 
						|
                    ChartControl.GlobalUpdateCount++;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region ShowAllRings
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets or sets whether all series rings are shown when rendering the chart.
 | 
						|
        /// If false, only one ring at a time is shown, with the ability to 'drill' up
 | 
						|
        /// or down, to display adjacent rings.        
 | 
						|
        /// </summary>
 | 
						|
        [DefaultValue(Tbool.NotSet), Category("Appearance")]
 | 
						|
        [Description("Indicates  whether all series Rings are shown when rendering the chart. If false, only one ring at a time is shown, with the ability to 'drill' up or down, to display adjacent rings.")]
 | 
						|
        public Tbool ShowAllRings
 | 
						|
        {
 | 
						|
            get { return (_ShowAllRings); }
 | 
						|
 | 
						|
            set
 | 
						|
            {
 | 
						|
                if (value != _ShowAllRings)
 | 
						|
                {
 | 
						|
                    _ShowAllRings = value;
 | 
						|
 | 
						|
                    OnPropertyChangedEx("ShowAllRings", VisualChangeType.Layout);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region ShowAllRingsEx
 | 
						|
 | 
						|
        internal bool ShowAllRingsEx(PieChart pieChart)
 | 
						|
        {
 | 
						|
            if (ShowAllRings != Tbool.NotSet)
 | 
						|
                return (ShowAllRings != Tbool.False);
 | 
						|
 | 
						|
            return (pieChart.ShowAllRings != Tbool.False);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region ShowOtherSlice
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets or sets whether to consolidate smaller pie slices into a single slice that
 | 
						|
        /// represents 'other' data values, or whether to display those smaller slices
 | 
						|
        /// as separate pie slices.
 | 
						|
        /// </summary>
 | 
						|
        [DefaultValue(Tbool.NotSet), Category("Appearance")]
 | 
						|
        [Description("Indicates whether to consolidate smaller pie slices into a single slice that represents 'other' data values, or whether to display those smaller slices as separate pie slices.")]
 | 
						|
        public Tbool ShowOtherSlice
 | 
						|
        {
 | 
						|
            get { return (_ShowOtherSlice); }
 | 
						|
 | 
						|
            set
 | 
						|
            {
 | 
						|
                if (value != _ShowOtherSlice)
 | 
						|
                {
 | 
						|
                    _ShowOtherSlice = value;
 | 
						|
 | 
						|
                    OnPropertyChangedEx("ShowOtherSlice", VisualChangeType.Layout);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region ShowOtherSliceEx
 | 
						|
 | 
						|
        internal bool ShowOtherSliceEx(PieChart pieChart)
 | 
						|
        {
 | 
						|
            if (ShowOtherSlice != Tbool.NotSet)
 | 
						|
                return (ShowOtherSlice == Tbool.True);
 | 
						|
 | 
						|
            return (pieChart.ShowOtherSlice == Tbool.True);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region SubSliceVisualLayout
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets or sets the default layout of the subordinate or nested series slices.
 | 
						|
        /// </summary>
 | 
						|
        [Category("Layout")]
 | 
						|
        [Description("Indicates the default layout of the subordinate or nested series slices.")]
 | 
						|
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
 | 
						|
        public SliceVisualLayout SubSliceVisualLayout
 | 
						|
        {
 | 
						|
            get
 | 
						|
            {
 | 
						|
                if (_SliceVisualLayout == null)
 | 
						|
                    SubSliceVisualLayout = new SliceVisualLayout(this);
 | 
						|
 | 
						|
                return (_SliceVisualLayout);
 | 
						|
            }
 | 
						|
 | 
						|
            set
 | 
						|
            {
 | 
						|
                if (value != _SliceVisualLayout)
 | 
						|
                {
 | 
						|
                    if (_SliceVisualLayout != null)
 | 
						|
                        _SliceVisualLayout.PropertyChanged -= SliceVisualLayout_PropertyChanged;
 | 
						|
 | 
						|
                    _SliceVisualLayout = value;
 | 
						|
 | 
						|
                    if (_SliceVisualLayout != null)
 | 
						|
                        _SliceVisualLayout.PropertyChanged += SliceVisualLayout_PropertyChanged;
 | 
						|
 | 
						|
                    OnPropertyChangedEx("SliceVisualLayout", VisualChangeType.Recalc);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region SliceVisualLayout_PropertyChanged
 | 
						|
 | 
						|
        void SliceVisualLayout_PropertyChanged(object sender, PropertyChangedEventArgs e)
 | 
						|
        {
 | 
						|
            VisualPropertyChangedEventArgs vce = e as VisualPropertyChangedEventArgs;
 | 
						|
 | 
						|
            if (vce != null)
 | 
						|
            {
 | 
						|
                OnPropertyChangedEx(vce.PropertyName, vce.ChangeType);
 | 
						|
 | 
						|
                if (ChartControl != null)
 | 
						|
                    ChartControl.GlobalUpdateCount++;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Visible
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets or sets whether the series is visible or not.
 | 
						|
        /// </summary>
 | 
						|
        [DefaultValue(true), Category("Appearance")]
 | 
						|
        [Description("Indicates whether the series is visible or not.")]
 | 
						|
        public override bool Visible
 | 
						|
        {
 | 
						|
            get { return (base.Visible); }
 | 
						|
 | 
						|
            set
 | 
						|
            {
 | 
						|
                if (Visible != value)
 | 
						|
                {
 | 
						|
                    base.Visible = value;
 | 
						|
 | 
						|
                    SeriesRangeChanged = true;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Internal properties
 | 
						|
 | 
						|
        #region ActiveSeriesPointCollection
 | 
						|
 | 
						|
        internal PieSeriesPointCollection ActiveSeriesPointCollection
 | 
						|
        {
 | 
						|
            get { return (_ActiveSeriesPointSet); }
 | 
						|
            set { _ActiveSeriesPointSet = value; }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region IsInnerRingSeries
 | 
						|
 | 
						|
        internal bool IsInnerRingSeries
 | 
						|
        {
 | 
						|
            get { return (TestState(States.IsInnerRingSeries)); }
 | 
						|
            set { SetState(States.IsInnerRingSeries, value); }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region IsOffset
 | 
						|
 | 
						|
        internal bool IsOffset
 | 
						|
        {
 | 
						|
            get { return (TestState(States.IsOffset)); }
 | 
						|
            set { SetState(States.IsOffset, value); }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region IsOuterRingSeries
 | 
						|
 | 
						|
        internal bool IsOuterRingSeries
 | 
						|
        {
 | 
						|
            get { return (TestState(States.IsOuterRingSeries)); }
 | 
						|
            set { SetState(States.IsOuterRingSeries, value); }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region PieCenter
 | 
						|
 | 
						|
        internal Point PieCenter
 | 
						|
        {
 | 
						|
            get { return (_PieCenter); }
 | 
						|
            set { _PieCenter = value; }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region PieOuterExtent
 | 
						|
 | 
						|
        internal double PieOuterExtent
 | 
						|
        {
 | 
						|
            get { return (_PieOuterExtent); }
 | 
						|
            set { _PieOuterExtent = value; }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region PieRings
 | 
						|
 | 
						|
        internal List<PieRing> PieRings
 | 
						|
        {
 | 
						|
            get
 | 
						|
            {
 | 
						|
                if (_PieRings == null)
 | 
						|
                    _PieRings = new List<PieRing>();
 | 
						|
 | 
						|
                return (_PieRings);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RingWeightTotal
 | 
						|
 | 
						|
        internal int RingWeightTotal
 | 
						|
        {
 | 
						|
            get { return (_RingWeightTotal); }
 | 
						|
            set { _RingWeightTotal = value; }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RingWeightEx
 | 
						|
 | 
						|
        internal int RingWeightEx
 | 
						|
        {
 | 
						|
            get { return (_RingWeightEx); }
 | 
						|
            set { _RingWeightEx = value; }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region SymFontScale
 | 
						|
 | 
						|
        internal float SymFontScale
 | 
						|
        {
 | 
						|
            get { return (_SymFontScale); }
 | 
						|
            set { _SymFontScale = value; }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RenderOverride
 | 
						|
 | 
						|
        protected override void RenderOverride(ChartRenderInfo renderInfo)
 | 
						|
        {
 | 
						|
            if (SeriesPoints.Count > 0)
 | 
						|
            {
 | 
						|
                PieChart pieChart = Parent as PieChart;
 | 
						|
 | 
						|
                Point pt = pieChart.GetGlobalAdjustedPoint(pieChart.ContentBounds.Location);
 | 
						|
                RenderBounds = new Rectangle(pt, pieChart.ContentBounds.Size);
 | 
						|
 | 
						|
                if (RenderBounds.Width > 0 && RenderBounds.Height > 0)
 | 
						|
                    RenderPieSeries(renderInfo);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region RenderPieSeries
 | 
						|
 | 
						|
        private void RenderPieSeries(ChartRenderInfo renderInfo)
 | 
						|
        {
 | 
						|
            Graphics g = renderInfo.Graphics;
 | 
						|
            PieChart pieChart = Parent as PieChart;
 | 
						|
 | 
						|
            PieSeriesPointCollection spc = GetActiveSeriesPointCollection();
 | 
						|
 | 
						|
            RenderPieSeriesEx(g, renderInfo.ClipRectangle, pieChart, spc);
 | 
						|
        }
 | 
						|
 | 
						|
        #region RenderPieSeriesEx
 | 
						|
 | 
						|
        private void RenderPieSeriesEx(Graphics g,
 | 
						|
            Rectangle clip, PieChart pieChart, PieSeriesPointCollection spc)
 | 
						|
        {
 | 
						|
            if (spc != null)
 | 
						|
                spc = spc.PieSlices;
 | 
						|
 | 
						|
            if (spc != null)
 | 
						|
            {
 | 
						|
                foreach (PieSeriesPoint psp in spc)
 | 
						|
                {
 | 
						|
                    if (psp.PieRing != null)
 | 
						|
                    {
 | 
						|
                        if (psp.PieRing.IsDisplayed == true)
 | 
						|
                            RenderSlice(g, clip, pieChart, spc, psp);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region RenderSlice
 | 
						|
 | 
						|
        private void RenderSlice(Graphics g, Rectangle clip,
 | 
						|
            PieChart pieChart, PieSeriesPointCollection spc, PieSeriesPoint psp)
 | 
						|
        {
 | 
						|
            if (PspNeedsDisplayed(pieChart, psp, clip) == true)
 | 
						|
            {
 | 
						|
                Region rgn = null;
 | 
						|
 | 
						|
                int outerRadius = (int)psp.OuterRadius;
 | 
						|
                int innerRadius = (int)psp.InnerRadius;
 | 
						|
 | 
						|
                ChartSliceVisualStyle sstyle = psp.GetEffectiveSliceStyle(pieChart, this);
 | 
						|
 | 
						|
                if (psp.IsEmpty == false)
 | 
						|
                    RenderReferenceLines(g, pieChart, spc, psp, false);
 | 
						|
 | 
						|
                RenderSliceEx(g, ref rgn, pieChart, 
 | 
						|
                    spc, psp, outerRadius, innerRadius, sstyle);
 | 
						|
 | 
						|
                if (psp.IsEmpty == false)
 | 
						|
                {
 | 
						|
                    if (psp.IsOther == true)
 | 
						|
                    {
 | 
						|
                        if (ShowAllRingsEx(pieChart) == true)
 | 
						|
                        {
 | 
						|
                            List<PieRing> pieRings = psp.PieRing.ChartSeries.PieRings;
 | 
						|
 | 
						|
                            outerRadius = innerRadius;
 | 
						|
                            innerRadius = pieRings[pieRings.Count - 1].InnerRadius;
 | 
						|
 | 
						|
                            RenderSliceOtherSpace(g, ref rgn,
 | 
						|
                                pieChart, psp, outerRadius, innerRadius, sstyle);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                psp.PathBounds = (rgn != null)
 | 
						|
                    ? Rectangle.Ceiling(rgn.GetBounds(g)) : Rectangle.Empty;
 | 
						|
 | 
						|
                if (psp.IsEmpty == false)
 | 
						|
                {
 | 
						|
                    if (sstyle.ImageOverlay == ImageOverlay.Bottom)
 | 
						|
                        RenderSliceFigure(g, rgn, pieChart, psp, sstyle);
 | 
						|
 | 
						|
                    if ((sstyle.ImageOverlay == ImageOverlay.Middle) ||
 | 
						|
                        (sstyle.ImageOverlay == ImageOverlay.NotSet))
 | 
						|
                    {
 | 
						|
                        RenderSliceFigure(g, rgn, pieChart, psp, sstyle);
 | 
						|
                    }
 | 
						|
 | 
						|
                    RenderSliceLabel(g, pieChart, psp, sstyle);
 | 
						|
 | 
						|
                    if (sstyle.ImageOverlay == ImageOverlay.Top)
 | 
						|
                        RenderSliceFigure(g, rgn, pieChart, psp, sstyle);
 | 
						|
 | 
						|
                    RenderReferenceLines(g, pieChart, spc, psp, true);
 | 
						|
                }
 | 
						|
 | 
						|
                //using (StringFormat sf = new StringFormat())
 | 
						|
                //{
 | 
						|
                //    sf.Alignment = StringAlignment.Center;
 | 
						|
                //    sf.LineAlignment = StringAlignment.Center;
 | 
						|
 | 
						|
                //    g.DrawString(psp.RenderCount.ToString(),
 | 
						|
                //        SystemFonts.DefaultFont, Brushes.Black, psp.PathBounds, sf);
 | 
						|
                //}
 | 
						|
 | 
						|
                //psp.RenderCount++;
 | 
						|
            }
 | 
						|
 | 
						|
            if (ShowAllRingsEx(pieChart) == true)
 | 
						|
            {
 | 
						|
                if (psp.SeriesPoints != null)
 | 
						|
                    RenderPieSeriesEx(g, clip, pieChart, psp.SeriesPoints);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region PspNeedsDisplayed
 | 
						|
 | 
						|
        private bool PspNeedsDisplayed(PieChart pieChart, PieSeriesPoint psp, Rectangle clip)
 | 
						|
        {
 | 
						|
            if (psp.IsDisplayedEx == true)
 | 
						|
            {
 | 
						|
                if (psp.SweepAngleEx != 0)
 | 
						|
                {
 | 
						|
                    Rectangle r = psp.Bounds;
 | 
						|
 | 
						|
                    if (r.Width > 0 && r.Height > 0)
 | 
						|
                    {
 | 
						|
                        if (psp.InnerRadius < psp.OuterRadius)
 | 
						|
                        {
 | 
						|
                            if (psp.PathBounds.IsEmpty == true || clip.IntersectsWith(psp.PathBounds) == true)
 | 
						|
                                return (true);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (false);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RenderSliceEx
 | 
						|
 | 
						|
        private void RenderSliceEx(Graphics g, ref Region rgn,
 | 
						|
            PieChart pieChart, PieSeriesPointCollection spc, PieSeriesPoint psp,
 | 
						|
            int outerRadius, int innerRadius, ChartSliceVisualStyle sstyle)
 | 
						|
        {
 | 
						|
            int width = outerRadius - innerRadius;
 | 
						|
            int extentWidth = (int)(psp.SliceExtent * width);
 | 
						|
 | 
						|
            bool renderShading = (sstyle.EnableShading == Tbool.True);
 | 
						|
 | 
						|
            SliceRenderType renderType = SliceRenderType.FullSlice;
 | 
						|
 | 
						|
            if (psp.HasExtent == true)
 | 
						|
            {
 | 
						|
                int extentRadius = innerRadius + extentWidth;
 | 
						|
 | 
						|
                if (extentWidth < width)
 | 
						|
                {
 | 
						|
                    renderType = SliceRenderType.ExtentSlice;
 | 
						|
 | 
						|
                    if (psp.ShowSliceWhiteSpaceEx == true)
 | 
						|
                    {
 | 
						|
                        RenderSliceWhiteSpace(g, ref rgn, pieChart,
 | 
						|
                            psp, outerRadius, extentRadius, renderShading, sstyle);
 | 
						|
 | 
						|
                        renderShading = false;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                outerRadius = extentRadius;
 | 
						|
            }
 | 
						|
 | 
						|
            RenderSliceExtent(g, ref rgn, pieChart,
 | 
						|
                psp, outerRadius, innerRadius, renderShading, renderType, sstyle);
 | 
						|
        }
 | 
						|
 | 
						|
        #region RenderSliceWhiteSpace
 | 
						|
 | 
						|
        private void RenderSliceWhiteSpace(Graphics g, ref Region rgn,
 | 
						|
            PieChart pieChart, PieSeriesPoint psp, int outerRadius,
 | 
						|
            int innerRadius, bool renderShading, ChartSliceVisualStyle sstyle)
 | 
						|
        {
 | 
						|
            Background background = sstyle.WhiteSpaceBackground;
 | 
						|
            ChartLineVisualStyle border = sstyle.WhiteSpaceBorder;
 | 
						|
 | 
						|
            GraphicsState gs = g.Save();
 | 
						|
 | 
						|
            g.TranslateTransform((float)psp.SliceCenter.X, (float)psp.SliceCenter.Y);
 | 
						|
            g.RotateTransform((float)(psp.CenterAngle) % 360);
 | 
						|
 | 
						|
            Rectangle r = new Rectangle();
 | 
						|
 | 
						|
            r.X = r.Y = -outerRadius;
 | 
						|
            r.Width = r.Height = (outerRadius * 2);
 | 
						|
 | 
						|
            float angle = (float)GetSweepAngle(psp);
 | 
						|
 | 
						|
            // Try to blend the edges of the slice better.
 | 
						|
 | 
						|
            //if (background.IsDisplayable == true && border.IsDisplayable == false)
 | 
						|
            //    angle += .1f;
 | 
						|
 | 
						|
            ChartControl chartControl = ChartControl;
 | 
						|
 | 
						|
            using (GraphicsPath path = new GraphicsPath())
 | 
						|
            {
 | 
						|
                path.AddArc(r, -angle / 2, angle);
 | 
						|
 | 
						|
                if (psp.SliceExtent == 0)
 | 
						|
                {
 | 
						|
                    path.AddLine(Point.Empty, Point.Empty);
 | 
						|
                    path.CloseFigure();
 | 
						|
 | 
						|
                    if (chartControl.DoPreRenderSliceEvent(
 | 
						|
                        g, path, pieChart, this, psp, SliceRenderType.ExtentWhitespace) == false)
 | 
						|
                    {
 | 
						|
                        Rectangle pb = Rectangle.Truncate(path.GetBounds());
 | 
						|
 | 
						|
                        if (psp.IsEmpty == false)
 | 
						|
                        {
 | 
						|
                            if (background.IsDisplayable == true)
 | 
						|
                            {
 | 
						|
                                using (Brush br = background.GetBrush(pb))
 | 
						|
                                    g.FillPath(br, path);
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
 | 
						|
                        if (border.IsDisplayable == true)
 | 
						|
                        {
 | 
						|
                            using (Pen pen = new Pen(border.LineColor, Dpi.Width(border.LineWidth)))
 | 
						|
                            {
 | 
						|
                                if (border.LinePattern != LinePattern.NotSet)
 | 
						|
                                    pen.DashStyle = (DashStyle)border.LinePattern;
 | 
						|
 | 
						|
                                g.DrawPath(pen, path);
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
 | 
						|
                        chartControl.DoPostRenderSliceEvent(
 | 
						|
                            g, path, pieChart, this, psp, SliceRenderType.ExtentWhitespace);
 | 
						|
                    }
 | 
						|
 | 
						|
                    if (psp.IsEmpty == false)
 | 
						|
                    {
 | 
						|
                        if (renderShading == true)
 | 
						|
                            RenderShading(g, psp, path);
 | 
						|
                    }
 | 
						|
 | 
						|
                    path.Transform(g.Transform);
 | 
						|
 | 
						|
                    if (rgn == null)
 | 
						|
                        rgn = new Region(path);
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    int pcount = path.PointCount;
 | 
						|
 | 
						|
                    Rectangle t = new Rectangle();
 | 
						|
                    t.X = t.Y = (-innerRadius);
 | 
						|
                    t.Width = t.Height = (innerRadius * 2);
 | 
						|
 | 
						|
                    path.AddArc(t, angle / 2, -angle);
 | 
						|
 | 
						|
                    PointF ppt1 = path.PathPoints[pcount];
 | 
						|
                    PointF ppt2 = path.GetLastPoint();
 | 
						|
 | 
						|
                    path.CloseFigure();
 | 
						|
 | 
						|
                    if (chartControl.DoPreRenderSliceEvent(
 | 
						|
                        g, path, pieChart, this, psp, SliceRenderType.ExtentWhitespace) == false)
 | 
						|
                    {
 | 
						|
                        if (psp.IsEmpty == false)
 | 
						|
                        {
 | 
						|
                            if (background.IsDisplayable == true)
 | 
						|
                            {
 | 
						|
                                t = Rectangle.Ceiling(path.GetBounds());
 | 
						|
 | 
						|
                                Rectangle t2 = t;
 | 
						|
                                t2.Width = outerRadius - (int)psp.InnerRadius;
 | 
						|
                                t2.X = -t2.Width;
 | 
						|
 | 
						|
                                using (Brush br = background.GetBrush(t2))
 | 
						|
                                    g.FillPath(br, path);
 | 
						|
                            }
 | 
						|
 | 
						|
                            if (renderShading == true)
 | 
						|
                                RenderShading(g, psp, path);
 | 
						|
                        }
 | 
						|
 | 
						|
                        path.Transform(g.Transform);
 | 
						|
 | 
						|
                        if (rgn == null)
 | 
						|
                            rgn = new Region(path);
 | 
						|
 | 
						|
                        if (border.IsDisplayable == true)
 | 
						|
                        {
 | 
						|
                            path.Reset();
 | 
						|
 | 
						|
                            using (Pen pen = new Pen(border.LineColor, Dpi.Width(border.LineWidth)))
 | 
						|
                            {
 | 
						|
                                if (border.LinePattern != LinePattern.NotSet)
 | 
						|
                                    pen.DashStyle = (DashStyle)border.LinePattern;
 | 
						|
 | 
						|
                                path.AddLine(ppt2, ppt2);
 | 
						|
                                path.AddArc(r, -angle / 2, angle);
 | 
						|
                                path.AddLine(ppt1, ppt1);
 | 
						|
 | 
						|
                                g.DrawPath(pen, path);
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
 | 
						|
                        chartControl.DoPostRenderSliceEvent(
 | 
						|
                            g, path, pieChart, this, psp, SliceRenderType.ExtentWhitespace);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            g.Restore(gs);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RenderSliceExtent
 | 
						|
 | 
						|
        private void RenderSliceExtent(Graphics g, ref Region rgn,
 | 
						|
            PieChart pieChart, PieSeriesPoint psp, int outerRadius, int innerRadius, 
 | 
						|
            bool renderShading, SliceRenderType renderType, ChartSliceVisualStyle sstyle)
 | 
						|
        {
 | 
						|
            if (outerRadius - innerRadius > 0)
 | 
						|
            {
 | 
						|
                GraphicsState gs = g.Save();
 | 
						|
 | 
						|
                g.TranslateTransform((float)psp.SliceCenter.X, (float)psp.SliceCenter.Y);
 | 
						|
                g.RotateTransform((float)(psp.CenterAngle) % 360);
 | 
						|
 | 
						|
                Rectangle r = new Rectangle();
 | 
						|
 | 
						|
                r.X = r.Y = -outerRadius;
 | 
						|
                r.Width = r.Height = (outerRadius * 2);
 | 
						|
 | 
						|
                float angle = (float)GetSweepAngle(psp);
 | 
						|
 | 
						|
                using (GraphicsPath path = new GraphicsPath())
 | 
						|
                {
 | 
						|
                    path.AddArc(r, -angle / 2, angle);
 | 
						|
 | 
						|
                    if (psp.InnerRadius == 0)
 | 
						|
                    {
 | 
						|
                        path.AddLine(Point.Empty, Point.Empty);
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        Rectangle t = new Rectangle();
 | 
						|
                        t.X = t.Y = -innerRadius;
 | 
						|
                        t.Width = t.Height = innerRadius * 2;
 | 
						|
 | 
						|
                        path.AddArc(t, angle / 2, -angle);
 | 
						|
                    }
 | 
						|
 | 
						|
                    path.CloseFigure();
 | 
						|
 | 
						|
                    ChartControl chartControl = ChartControl;
 | 
						|
 | 
						|
                    if (chartControl.DoPreRenderSliceEvent(g, path, pieChart, this, psp, renderType) == false)
 | 
						|
                    {
 | 
						|
                        if (psp.IsEmpty == false)
 | 
						|
                        {
 | 
						|
                            if (sstyle.Background.IsDisplayable == true)
 | 
						|
                            {
 | 
						|
                                r = Rectangle.Ceiling(path.GetBounds());
 | 
						|
 | 
						|
                                if (psp.HasExtent == true)
 | 
						|
                                {
 | 
						|
                                    switch (sstyle.ExtentFillRange)
 | 
						|
                                    {
 | 
						|
                                        case ExtentFillRange.ByRing:
 | 
						|
                                            r.Width = psp.PieRing.ExtentRadius - innerRadius;
 | 
						|
                                            break;
 | 
						|
 | 
						|
                                        case ExtentFillRange.BySlice:
 | 
						|
                                            PieSeriesPointCollection spc = psp.Parent as PieSeriesPointCollection;
 | 
						|
 | 
						|
                                            if (spc != null)
 | 
						|
                                            {
 | 
						|
                                                double sliceExtent = spc.PieMaxExtent / spc.PieOuterExtent;
 | 
						|
 | 
						|
                                                int width = (int)(psp.OuterRadius - psp.InnerRadius);
 | 
						|
                                                int extentWidth = (int)(sliceExtent * width);
 | 
						|
 | 
						|
                                                r.Width = extentWidth;
 | 
						|
                                            }
 | 
						|
                                            break;
 | 
						|
                                    }
 | 
						|
                                }
 | 
						|
 | 
						|
                                using (Brush br = sstyle.Background.GetBrush(r))
 | 
						|
                                    g.FillPath(br, path);
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
 | 
						|
                        if (sstyle.Border.IsDisplayable == true)
 | 
						|
                        {
 | 
						|
                            using (Pen pen = new Pen(
 | 
						|
                                sstyle.Border.LineColor, Dpi.Width(sstyle.Border.LineWidth)))
 | 
						|
                            {
 | 
						|
                                if (sstyle.Border.LinePattern != LinePattern.NotSet)
 | 
						|
                                    pen.DashStyle = (DashStyle)sstyle.Border.LinePattern;
 | 
						|
 | 
						|
                                g.DrawPath(pen, path);
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
 | 
						|
                        chartControl.DoPostRenderSliceEvent(g, path, pieChart, this, psp, renderType);
 | 
						|
                    }
 | 
						|
 | 
						|
                    if (psp.IsEmpty == false)
 | 
						|
                    {
 | 
						|
                        if (renderShading == true)
 | 
						|
                            RenderShading(g, psp, path);
 | 
						|
                    }
 | 
						|
 | 
						|
                    path.Transform(g.Transform);
 | 
						|
 | 
						|
                    if (rgn == null)
 | 
						|
                        rgn = new Region(path);
 | 
						|
                    else
 | 
						|
                        rgn.Union(path);
 | 
						|
 | 
						|
                    g.Restore(gs);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetSweepAngle
 | 
						|
 | 
						|
        private double GetSweepAngle(PieSeriesPoint psp)
 | 
						|
        {
 | 
						|
            double sweepAngle = psp.SweepAngleEx;
 | 
						|
 | 
						|
            if (sweepAngle > 360)
 | 
						|
                sweepAngle %= 360;
 | 
						|
 | 
						|
            return (sweepAngle);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RenderSliceOtherSpace
 | 
						|
 | 
						|
        private void RenderSliceOtherSpace(Graphics g,
 | 
						|
            ref Region rgn, PieChart pieChart, PieSeriesPoint psp,
 | 
						|
            int outerRadius, int innerRadius, ChartSliceVisualStyle sstyle)
 | 
						|
        {
 | 
						|
            if (outerRadius - innerRadius > 0)
 | 
						|
            {
 | 
						|
                GraphicsState gs = g.Save();
 | 
						|
 | 
						|
                g.TranslateTransform((float)psp.SliceCenter.X, (float)psp.SliceCenter.Y);
 | 
						|
                g.RotateTransform((float)(psp.CenterAngle) % 360);
 | 
						|
 | 
						|
                Rectangle r = new Rectangle();
 | 
						|
 | 
						|
                r.X = r.Y = -outerRadius;
 | 
						|
                r.Width = r.Height = (outerRadius * 2);
 | 
						|
 | 
						|
                float angle = (float)GetSweepAngle(psp);
 | 
						|
 | 
						|
                Background background = sstyle.WhiteSpaceBackground;
 | 
						|
                ChartLineVisualStyle border = sstyle.WhiteSpaceBorder;
 | 
						|
 | 
						|
                ChartControl chartControl = ChartControl;
 | 
						|
 | 
						|
                using (GraphicsPath path = new GraphicsPath())
 | 
						|
                {
 | 
						|
                    path.AddArc(r, -angle / 2, angle);
 | 
						|
 | 
						|
                    if (innerRadius == 0)
 | 
						|
                    {
 | 
						|
                        path.AddLine(Point.Empty, Point.Empty);
 | 
						|
                        path.CloseFigure();
 | 
						|
 | 
						|
                        if (chartControl.DoPreRenderSliceEvent(
 | 
						|
                            g, path, pieChart, this, psp, SliceRenderType.OtherWhitespace) == false)
 | 
						|
                        {
 | 
						|
                            Rectangle pb = Rectangle.Truncate(path.GetBounds());
 | 
						|
 | 
						|
                            if (background.IsEmpty == false)
 | 
						|
                            {
 | 
						|
                                using (Brush br = background.GetBrush(pb))
 | 
						|
                                    g.FillPath(br, path);
 | 
						|
                            }
 | 
						|
 | 
						|
                            if (border.IsDisplayable == true)
 | 
						|
                            {
 | 
						|
                                using (Pen pen = new Pen(border.LineColor, Dpi.Width(border.LineWidth)))
 | 
						|
                                {
 | 
						|
                                    if (border.LinePattern != LinePattern.NotSet)
 | 
						|
                                        pen.DashStyle = (DashStyle)border.LinePattern;
 | 
						|
 | 
						|
                                    g.DrawPath(pen, path);
 | 
						|
                                }
 | 
						|
                            }
 | 
						|
 | 
						|
                            chartControl.DoPostRenderSliceEvent(
 | 
						|
                                g, path, pieChart, this, psp, SliceRenderType.OtherWhitespace);
 | 
						|
                        }
 | 
						|
 | 
						|
                        path.Transform(g.Transform);
 | 
						|
 | 
						|
                        if (rgn == null)
 | 
						|
                            rgn = new Region(path);
 | 
						|
                        else
 | 
						|
                            rgn.Union(path);
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        int pcount = path.PointCount;
 | 
						|
 | 
						|
                        Rectangle t = new Rectangle();
 | 
						|
 | 
						|
                        t.X = t.Y = -innerRadius;
 | 
						|
                        t.Width = t.Height = (innerRadius * 2);
 | 
						|
 | 
						|
                        PointF ppt1 = path.PathPoints[0];
 | 
						|
                        PointF ppt2 = path.GetLastPoint();
 | 
						|
 | 
						|
                        path.AddArc(t, angle / 2, -angle);
 | 
						|
                        path.CloseFigure();
 | 
						|
 | 
						|
                        if (chartControl.DoPreRenderSliceEvent(
 | 
						|
                            g, path, pieChart, this, psp, SliceRenderType.OtherWhitespace) == false)
 | 
						|
                        {
 | 
						|
                            Rectangle pb = Rectangle.Ceiling(path.GetBounds());
 | 
						|
 | 
						|
                            if (background.IsEmpty == false)
 | 
						|
                            {
 | 
						|
                                using (Brush br = background.GetBrush(pb))
 | 
						|
                                    g.FillPath(br, path);
 | 
						|
                            }
 | 
						|
 | 
						|
                            path.Transform(g.Transform);
 | 
						|
 | 
						|
                            if (rgn == null)
 | 
						|
                                rgn = new Region(path);
 | 
						|
                            else
 | 
						|
                                rgn.Union(path);
 | 
						|
 | 
						|
                            if (border.IsDisplayable == true)
 | 
						|
                            {
 | 
						|
                                using (Pen pen = new Pen(border.LineColor, Dpi.Width(border.LineWidth)))
 | 
						|
                                {
 | 
						|
                                    if (border.LinePattern != LinePattern.NotSet)
 | 
						|
                                        pen.DashStyle = (DashStyle)border.LinePattern;
 | 
						|
 | 
						|
                                    path.Reset();
 | 
						|
 | 
						|
                                    path.AddLine(ppt1, ppt1);
 | 
						|
                                    path.AddArc(t, -angle / 2, angle);
 | 
						|
                                    path.AddLine(ppt2, ppt2);
 | 
						|
 | 
						|
                                    g.DrawPath(pen, path);
 | 
						|
                                }
 | 
						|
                            }
 | 
						|
 | 
						|
                            chartControl.DoPostRenderSliceEvent(
 | 
						|
                                g, path, pieChart, this, psp, SliceRenderType.OtherWhitespace);
 | 
						|
                        }
 | 
						|
                        else
 | 
						|
                        {
 | 
						|
                            path.Transform(g.Transform);
 | 
						|
 | 
						|
                            if (rgn == null)
 | 
						|
                                rgn = new Region(path);
 | 
						|
                            else
 | 
						|
                                rgn.Union(path);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                g.Restore(gs);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RenderShading
 | 
						|
 | 
						|
        private void RenderShading(Graphics g, PieSeriesPoint psp, GraphicsPath path)
 | 
						|
        {
 | 
						|
            PieChart pieChart = Parent as PieChart;
 | 
						|
 | 
						|
            int radius = (int)((psp.HasExtent == true) ? psp.ExtentRadius : psp.OuterRadius);
 | 
						|
 | 
						|
            Rectangle r = new Rectangle();
 | 
						|
            r.Inflate(radius, radius);
 | 
						|
 | 
						|
            Region clip = g.Clip;
 | 
						|
            g.SetClip(path, CombineMode.Intersect);
 | 
						|
 | 
						|
            using (GraphicsPath path2 = new GraphicsPath())
 | 
						|
            {
 | 
						|
                path2.AddEllipse(r);
 | 
						|
 | 
						|
                PathGradientBrush pbr = new PathGradientBrush(path2);
 | 
						|
 | 
						|
                ColorBlend cb = new ColorBlend(3);
 | 
						|
 | 
						|
                Color[] colors = new Color[3];
 | 
						|
 | 
						|
                colors[0] = Color.FromArgb(100, Color.Black);
 | 
						|
                colors[1] = Color.Transparent;
 | 
						|
                colors[2] = Color.Transparent;
 | 
						|
 | 
						|
                cb.Colors = colors;
 | 
						|
 | 
						|
                float[] cp = new float[3];
 | 
						|
 | 
						|
                cp[0] = 0f;
 | 
						|
                cp[1] = .07f;
 | 
						|
                cp[2] = 1f;
 | 
						|
 | 
						|
                cb.Positions = cp;
 | 
						|
 | 
						|
                pbr.InterpolationColors = cb;
 | 
						|
 | 
						|
                g.FillEllipse(pbr, r);
 | 
						|
            }
 | 
						|
 | 
						|
            g.Clip = clip;
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RenderReferenceLines
 | 
						|
 | 
						|
        private void RenderReferenceLines(Graphics g, PieChart pieChart,
 | 
						|
            PieSeriesPointCollection spc, PieSeriesPoint psp, bool onTop)
 | 
						|
        {
 | 
						|
            if (spc.PieOuterExtent > 0)
 | 
						|
            {
 | 
						|
                ISeriesPointContainer ispc = spc.Parent;
 | 
						|
 | 
						|
                if (ispc != null)
 | 
						|
                {
 | 
						|
                    if (psp.ReferenceLineDisplayOnTopEx == onTop)
 | 
						|
                    {
 | 
						|
                        PieRefLineDisplayMode mode = psp.ReferenceLineDisplayModeEx;
 | 
						|
 | 
						|
                        if ((mode != PieRefLineDisplayMode.NotSet) &&
 | 
						|
                            ((mode & PieRefLineDisplayMode.None) != PieRefLineDisplayMode.None))
 | 
						|
                        {
 | 
						|
                            ChartSliceVisualStyle sstyle = psp.GetEffectiveSliceStyle(pieChart, this);
 | 
						|
 | 
						|
                            int width = psp.OuterRadius - psp.InnerRadius;
 | 
						|
 | 
						|
                            float start = (float)psp.StartAngleEx;
 | 
						|
                            float sweep = (float)psp.SweepAngleEx;
 | 
						|
 | 
						|
                            if ((mode & PieRefLineDisplayMode.ExtentAverage) == PieRefLineDisplayMode.ExtentAverage)
 | 
						|
                            {
 | 
						|
                                int avg = (int)((spc.PieAverageExtent / spc.PieOuterExtent) * width);
 | 
						|
 | 
						|
                                RenderReferenceLine(g, psp, start, sweep,
 | 
						|
                                    avg + psp.InnerRadius, sstyle.ExtentAverageRefLineStyle);
 | 
						|
                            }
 | 
						|
 | 
						|
                            if ((mode & PieRefLineDisplayMode.ExtentMinimum) == PieRefLineDisplayMode.ExtentMinimum)
 | 
						|
                            {
 | 
						|
                                int min = (int)((spc.PieMinExtent / spc.PieOuterExtent) * width);
 | 
						|
 | 
						|
                                RenderReferenceLine(g, psp, start, sweep,
 | 
						|
                                    min + psp.InnerRadius, sstyle.ExtentMinRefLineStyle);
 | 
						|
                            }
 | 
						|
 | 
						|
                            if ((mode & PieRefLineDisplayMode.ExtentMaximum) == PieRefLineDisplayMode.ExtentMaximum)
 | 
						|
                            {
 | 
						|
                                int max = (int)((spc.PieMaxExtent / spc.PieOuterExtent) * width);
 | 
						|
 | 
						|
                                RenderReferenceLine(g, psp, start, sweep,
 | 
						|
                                    max + psp.InnerRadius, sstyle.ExtentMaxRefLineStyle);
 | 
						|
                            }
 | 
						|
 | 
						|
                            if ((mode & PieRefLineDisplayMode.ExtentOuterRadius) == PieRefLineDisplayMode.ExtentOuterRadius)
 | 
						|
                            {
 | 
						|
                                RenderReferenceLine(g, psp, start, sweep,
 | 
						|
                                    psp.OuterRadius, sstyle.ExtentOuterRefLineStyle);
 | 
						|
                            }
 | 
						|
 | 
						|
                            if ((mode & PieRefLineDisplayMode.UserDefined) == PieRefLineDisplayMode.UserDefined)
 | 
						|
                            {
 | 
						|
                                List<PieReferenceLine> lines = psp.ReferenceLinesEx;
 | 
						|
 | 
						|
                                if (lines.Count > 0)
 | 
						|
                                {
 | 
						|
                                    foreach (PieReferenceLine line in lines)
 | 
						|
                                    {
 | 
						|
                                        if (line.Visible == true)
 | 
						|
                                        {
 | 
						|
                                            double radius = (line.Value / spc.PieOuterExtent) * width;
 | 
						|
 | 
						|
                                            RenderReferenceLine(g, psp, start, sweep,
 | 
						|
                                                radius + psp.InnerRadius, line.EffectiveStyle);
 | 
						|
                                        }
 | 
						|
                                    }
 | 
						|
                                }
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region RenderReferenceLine
 | 
						|
 | 
						|
        private void RenderReferenceLine(Graphics g, PieSeriesPoint psp,
 | 
						|
            float start, float sweep, double radius, PieReferenceLineVisualStyle rstyle)
 | 
						|
        {
 | 
						|
            if (radius > 0)
 | 
						|
            {
 | 
						|
                if (rstyle.IsDisplayable == true)
 | 
						|
                {
 | 
						|
                    Rectangle r = new Rectangle();
 | 
						|
                    r.Location = psp.SliceCenter;
 | 
						|
 | 
						|
                    r.Inflate((int)radius, (int)radius);
 | 
						|
 | 
						|
                    using (Pen pen = new Pen(rstyle.LineColor, rstyle.LineWidth))
 | 
						|
                    {
 | 
						|
                        if (rstyle.LinePattern != LinePattern.NotSet)
 | 
						|
                            pen.DashStyle = (DashStyle)rstyle.LinePattern;
 | 
						|
 | 
						|
                        g.DrawArc(pen, r, start, sweep);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RenderSliceFigure
 | 
						|
 | 
						|
        private void RenderSliceFigure(Graphics g, Region rgn,
 | 
						|
            PieChart pieChart, PieSeriesPoint psp, ChartSliceVisualStyle sstyle)
 | 
						|
        {
 | 
						|
            object figure = sstyle.GetFigure();
 | 
						|
 | 
						|
            if (figure != null)
 | 
						|
            {
 | 
						|
                double radius = GetFigureRadius(psp, sstyle);
 | 
						|
                double centerAngle = psp.CenterAngle;
 | 
						|
 | 
						|
                double angle = GetImageAngle(psp, centerAngle, sstyle);
 | 
						|
 | 
						|
                Point pt = psp.GetRayEndPoint(angle, radius);
 | 
						|
                Size srcSize = sstyle.GetFigureSizeEx(g);
 | 
						|
 | 
						|
                srcSize.Height = Dpi.DescaleHeight(srcSize.Height);
 | 
						|
                srcSize.Width = Dpi.DescaleWidth(srcSize.Width);
 | 
						|
 | 
						|
                Rectangle srcRect = new Rectangle(pt, Size.Empty);
 | 
						|
                Rectangle destRect = srcRect;
 | 
						|
 | 
						|
                double scaleFactor = GetImageSideFactor(psp, radius, srcSize);
 | 
						|
 | 
						|
                Size destSize = srcRect.Size;
 | 
						|
 | 
						|
                if (scaleFactor != 1)
 | 
						|
                {
 | 
						|
                    double dh = (double)srcSize.Width / srcSize.Height;
 | 
						|
                    destSize = new Size((int)(dh * scaleFactor * 2), (int)scaleFactor * 2);
 | 
						|
                }
 | 
						|
 | 
						|
                srcRect.Inflate(srcSize.Width / 2, srcSize.Height / 2);
 | 
						|
                destRect.Inflate(destSize.Width / 2, destSize.Height / 2);
 | 
						|
 | 
						|
                bool scaleImage = (double.IsNaN(sstyle.ImageScale) == false);
 | 
						|
 | 
						|
                Region clip = null;
 | 
						|
 | 
						|
                if (scaleImage == false)
 | 
						|
                {
 | 
						|
                    if (sstyle.ImageCropMode == SliceImageCropMode.ClipImage)
 | 
						|
                    {
 | 
						|
                        clip = g.Clip;
 | 
						|
 | 
						|
                        g.SetClip(rgn, CombineMode.Intersect);
 | 
						|
                    }
 | 
						|
                    else if (sstyle.ImageCropMode == SliceImageCropMode.HideImage)
 | 
						|
                    {
 | 
						|
                        if (destRect.Contains(srcRect) == false)
 | 
						|
                            return;
 | 
						|
                    }
 | 
						|
 | 
						|
                    destRect = srcRect;
 | 
						|
                }
 | 
						|
 | 
						|
                psp.PathBounds = Rectangle.Union(psp.PathBounds, destRect);
 | 
						|
 | 
						|
                GraphicsState gState = null;
 | 
						|
 | 
						|
                if (sstyle.ImageAutoRotate == Tbool.True || sstyle.ImageRotation != 0)
 | 
						|
                {
 | 
						|
                    gState = g.Save();
 | 
						|
 | 
						|
                    destRect.X = -(destRect.Width / 2);
 | 
						|
                    destRect.Y = -(destRect.Height / 2);
 | 
						|
 | 
						|
                    g.TranslateTransform(pt.X, pt.Y);
 | 
						|
 | 
						|
                    if (sstyle.ImageAutoRotate == Tbool.True)
 | 
						|
                        g.RotateTransform((float)angle);
 | 
						|
 | 
						|
                    if (sstyle.ImageRotation != 0)
 | 
						|
                        g.RotateTransform((float)sstyle.ImageRotation);
 | 
						|
                }
 | 
						|
 | 
						|
                if (scaleImage == true)
 | 
						|
                {
 | 
						|
                    if (sstyle.ImageScale != 1)
 | 
						|
                    {
 | 
						|
                        int width = (int)(destRect.Width * sstyle.ImageScale);
 | 
						|
                        int height = (int)(destRect.Height * sstyle.ImageScale);
 | 
						|
 | 
						|
                        destRect.X += (destRect.Width / 2);
 | 
						|
                        destRect.Y += (destRect.Height / 2);
 | 
						|
                        destRect.Size = Size.Empty;
 | 
						|
 | 
						|
                        destRect.Inflate(width / 2, height / 2);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                if (sstyle.IsSymbolFigure == true)
 | 
						|
                    RenderSliceSymbol(g, pieChart, (SymbolDef)figure, destRect, sstyle);
 | 
						|
                else
 | 
						|
                    RenderSliceImage(g, (Image)figure, srcRect, destRect);
 | 
						|
 | 
						|
                if (sstyle.ImageAutoRotate == Tbool.True || sstyle.ImageRotation != 0)
 | 
						|
                    g.Restore(gState);
 | 
						|
 | 
						|
                if (clip != null)
 | 
						|
                    g.Clip = clip;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetImageAngle
 | 
						|
 | 
						|
        private double GetImageAngle(
 | 
						|
            PieSeriesPoint psp, double centerAngle, ChartSliceVisualStyle sstyle)
 | 
						|
        {
 | 
						|
            double offset = sstyle.ImageAngleOffset;
 | 
						|
 | 
						|
            if (offset == 0)
 | 
						|
                return (centerAngle);
 | 
						|
 | 
						|
            if ((uint)offset < 1)
 | 
						|
                return (centerAngle + offset * psp.SweepAngleEx);
 | 
						|
 | 
						|
            return (centerAngle + offset);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetImageSideFactor
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Calculates the max 'a' side of the image.
 | 
						|
        /// </summary>
 | 
						|
        /// <param name="psp"></param>
 | 
						|
        /// <param name="radius"></param>
 | 
						|
        /// <param name="size"></param>
 | 
						|
        /// <returns></returns>
 | 
						|
        private double GetImageSideFactor(
 | 
						|
            PieSeriesPoint psp, double radius, Size size)
 | 
						|
        {
 | 
						|
            double maxRadius = GetMaxImageRadius(psp, radius);
 | 
						|
 | 
						|
            double scaleFactor = (double)(size.Width * size.Width) / (size.Height * size.Height);
 | 
						|
            double side = Math.Sqrt((maxRadius * maxRadius) / (scaleFactor + 1));
 | 
						|
 | 
						|
            return (side);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetMaxImageRadius
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets the max radius of a circle image at the given ray radius.
 | 
						|
        /// </summary>
 | 
						|
        /// <param name="psp"></param>
 | 
						|
        /// <param name="radius"></param>
 | 
						|
        /// <returns></returns>
 | 
						|
        private double GetMaxImageRadius(PieSeriesPoint psp, double radius)
 | 
						|
        {
 | 
						|
            double angle = psp.SweepAngleEx / 2;
 | 
						|
 | 
						|
            if (angle >= 90)
 | 
						|
                return (radius);
 | 
						|
 | 
						|
            double radians = MathHelper.ToRadians(angle);
 | 
						|
 | 
						|
            double maxRad = radius * Math.Sin(radians);
 | 
						|
 | 
						|
            //double dr = (int)(radius * radius);
 | 
						|
 | 
						|
            //double maxRad = 2 * dr - 2 * (dr * Math.Cos(radians));
 | 
						|
            //maxRad = Math.Sqrt(maxRad);
 | 
						|
 | 
						|
            return (maxRad);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetFigureRadius
 | 
						|
 | 
						|
        private double GetFigureRadius(PieSeriesPoint psp, ChartSliceVisualStyle sstyle)
 | 
						|
        {
 | 
						|
            double radius = psp.OuterRadius - psp.InnerRadius;
 | 
						|
            double extentRadius = psp.InnerRadius + radius * psp.SliceExtent;
 | 
						|
 | 
						|
            double innerRadius = GetAnchorRadius(psp, extentRadius, sstyle.ImageInnerRadiusAnchor);
 | 
						|
            double outerRadius = GetAnchorRadius(psp, extentRadius, sstyle.ImageOuterRadiusAnchor);
 | 
						|
 | 
						|
            double delta = outerRadius - innerRadius;
 | 
						|
 | 
						|
            if (delta == 0)
 | 
						|
                delta = radius;
 | 
						|
 | 
						|
            if (Math.Abs(sstyle.ImageRadiusOffset) <= 1)
 | 
						|
                return (innerRadius + delta * sstyle.ImageRadiusOffset);
 | 
						|
            else
 | 
						|
                return (innerRadius + sstyle.ImageRadiusOffset * (delta > 0 ? 1 : -1));
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetAnchorRadius
 | 
						|
 | 
						|
        private double GetAnchorRadius(
 | 
						|
            PieSeriesPoint psp, double extentRadius, SliceImageRadiusAnchor anchor)
 | 
						|
        {
 | 
						|
            switch (anchor)
 | 
						|
            {
 | 
						|
                case SliceImageRadiusAnchor.ExtentRadius:
 | 
						|
                    return (extentRadius);
 | 
						|
 | 
						|
                case SliceImageRadiusAnchor.InnerRadius:
 | 
						|
                    return (psp.InnerRadius);
 | 
						|
 | 
						|
                case SliceImageRadiusAnchor.OuterRadius:
 | 
						|
                    return (psp.OuterRadius);
 | 
						|
            }
 | 
						|
 | 
						|
            return (psp.InnerRadius);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RenderSliceSymbol
 | 
						|
 | 
						|
        private void RenderSliceSymbol(Graphics g,
 | 
						|
            PieChart pieChart, SymbolDef symDef, Rectangle destRect, ChartSliceVisualStyle sstyle)
 | 
						|
        {
 | 
						|
            TextRenderingHint hint = g.TextRenderingHint;
 | 
						|
            g.TextRenderingHint = TextRenderingHint.AntiAlias;
 | 
						|
 | 
						|
            if (double.IsNaN(sstyle.ImageScale) == true)
 | 
						|
            {
 | 
						|
                using (StringFormat sf = new StringFormat())
 | 
						|
                {
 | 
						|
                    sf.LineAlignment = StringAlignment.Center;
 | 
						|
                    sf.Alignment = StringAlignment.Center;
 | 
						|
 | 
						|
                    using (Brush br = new SolidBrush(symDef.SymbolColor))
 | 
						|
                        g.DrawString(symDef.SymbolRealized, symDef.SymbolFont, br, destRect, sf);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                float n = Math.Max(destRect.Width, destRect.Height);
 | 
						|
 | 
						|
                destRect.Y += Dpi.Width4;
 | 
						|
 | 
						|
                if (_SymFontScale <= 0)
 | 
						|
                {
 | 
						|
                    _ScaleSymDef.SymbolSize = n;
 | 
						|
                    _ScaleSymDef.SymbolSet = symDef.SymbolSet;
 | 
						|
 | 
						|
                    _SymFontScale = n / _ScaleSymDef.SymbolFont.Height * .8f;
 | 
						|
                }
 | 
						|
 | 
						|
                float fn = _SymFontScale * n;
 | 
						|
 | 
						|
                _ScaleSymDef.SymbolSize = fn;
 | 
						|
                _ScaleSymDef.SymbolSet = symDef.SymbolSet;
 | 
						|
 | 
						|
                using (StringFormat sf = new StringFormat())
 | 
						|
                {
 | 
						|
                    sf.LineAlignment = StringAlignment.Center;
 | 
						|
                    sf.Alignment = StringAlignment.Center;
 | 
						|
 | 
						|
                    using (Brush br = new SolidBrush(symDef.SymbolColor))
 | 
						|
                        g.DrawString(symDef.SymbolRealized, _ScaleSymDef.SymbolFont, br, destRect, sf);
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            g.TextRenderingHint = hint;
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RenderSliceImage
 | 
						|
 | 
						|
        private void RenderSliceImage(Graphics g, Image image, Rectangle srcRect, Rectangle destRect)
 | 
						|
        {
 | 
						|
            g.DrawImage(image, destRect,
 | 
						|
                new Rectangle(Point.Empty, srcRect.Size), GraphicsUnit.Pixel);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RenderSliceLabel
 | 
						|
 | 
						|
        internal void RenderSliceLabel(Graphics g,
 | 
						|
            PieChart pieChart, PieSeriesPoint psp, ChartSliceVisualStyle sstyle)
 | 
						|
        {
 | 
						|
            if (IsInnerSliceLabelVisible(pieChart, psp) == true)
 | 
						|
            {
 | 
						|
                SliceInnerLabelVisualStyle lstyle = sstyle.SliceInnerLabelStyle;
 | 
						|
 | 
						|
                psp.InnerLabelDisplayed = false;
 | 
						|
 | 
						|
                string text = GetSliceLabel(pieChart, psp, true, psp.InnerSliceLabelEx);
 | 
						|
 | 
						|
                ChartControl chartControl = ChartControl;
 | 
						|
 | 
						|
                bool displayed = true;
 | 
						|
 | 
						|
                if (chartControl.DoRenderSliceInnerLabelEvent(g, pieChart, psp, text, ref displayed) == false)
 | 
						|
                {
 | 
						|
                    if (string.IsNullOrEmpty(text) == false)
 | 
						|
                    {
 | 
						|
                        double maxRadius = psp.OuterRadius;
 | 
						|
 | 
						|
                        if (lstyle.OuterRadiusOffsetBase == OuterRadiusOffsetBase.ExtentRadius)
 | 
						|
                            maxRadius = psp.InnerRadius + (psp.OuterRadius - psp.InnerRadius) * psp.SliceExtent;
 | 
						|
 | 
						|
                        SliceLabelOrientation orientation = psp.InnerLabelOrientationEx;
 | 
						|
 | 
						|
                        switch (orientation)
 | 
						|
                        {
 | 
						|
                            case SliceLabelOrientation.Adaptive:
 | 
						|
                                psp.InnerLabelDisplayed =
 | 
						|
                                    RenderAdaptiveLabel(g, pieChart, psp, maxRadius, text, lstyle);
 | 
						|
                                break;
 | 
						|
 | 
						|
                            case SliceLabelOrientation.Custom:
 | 
						|
                                psp.InnerLabelDisplayed =
 | 
						|
                                    RenderCustomLabel(g, pieChart, psp, maxRadius, text, lstyle);
 | 
						|
                                break;
 | 
						|
 | 
						|
                            case SliceLabelOrientation.Parallel:
 | 
						|
                                psp.InnerLabelDisplayed =
 | 
						|
                                    RenderParallelLabel(g, pieChart, psp, maxRadius, text, lstyle);
 | 
						|
                                break;
 | 
						|
 | 
						|
                            case SliceLabelOrientation.Perpendicular:
 | 
						|
                                psp.InnerLabelDisplayed =
 | 
						|
                                    RenderPerpendicularLabel(g, pieChart, psp, maxRadius, text, lstyle);
 | 
						|
                                break;
 | 
						|
 | 
						|
                            default:
 | 
						|
                                psp.InnerLabelDisplayed =
 | 
						|
                                    RenderHorizontalLabel(g, pieChart, psp, maxRadius, text, lstyle);
 | 
						|
                                break;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                psp.LastPathBounds = Rectangle.Empty;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region IsInnerSliceLabelVisible
 | 
						|
 | 
						|
        private bool IsInnerSliceLabelVisible(PieChart pieChart, PieSeriesPoint psp)
 | 
						|
        {
 | 
						|
            switch (psp.SliceLabelDisplayModeEx)
 | 
						|
            {
 | 
						|
                case SliceLabelDisplayMode.NotSet:
 | 
						|
 | 
						|
                case SliceLabelDisplayMode.Inner:
 | 
						|
                case SliceLabelDisplayMode.InnerAndOuter:
 | 
						|
                case SliceLabelDisplayMode.InnerXorOuter:
 | 
						|
                    return (IsLabelDisplayed(pieChart, psp));
 | 
						|
            }
 | 
						|
 | 
						|
            return (false);
 | 
						|
        }
 | 
						|
 | 
						|
        #region IsLabelDisplayed
 | 
						|
 | 
						|
        internal bool IsLabelDisplayed(PieChart pieChart, PieSeriesPoint psp)
 | 
						|
        {
 | 
						|
            SliceLabelVisibility labVis = psp.SliceLabelVisibilityEx;
 | 
						|
 | 
						|
            if ((labVis == SliceLabelVisibility.NotSet) ||
 | 
						|
                (labVis & SliceLabelVisibility.Always) == SliceLabelVisibility.Always)
 | 
						|
                return (true);
 | 
						|
 | 
						|
            if ((labVis & SliceLabelVisibility.Never) == SliceLabelVisibility.Never)
 | 
						|
                return (false);
 | 
						|
 | 
						|
            if (pieChart.ShowSliceLabelsOnEntry == true && pieChart.IsMouseOver == true)
 | 
						|
                return (true);
 | 
						|
 | 
						|
            if ((labVis & SliceLabelVisibility.SliceMouseOver) == SliceLabelVisibility.SliceMouseOver)
 | 
						|
            {
 | 
						|
                if (psp == pieChart.HitPsp)
 | 
						|
                    return (true);
 | 
						|
            }
 | 
						|
 | 
						|
            if (((labVis & SliceLabelVisibility.SelectionModeMouseOver) == SliceLabelVisibility.SelectionModeMouseOver) ||
 | 
						|
                ((labVis & SliceLabelVisibility.SliceMouseOver) == SliceLabelVisibility.SliceMouseOver))
 | 
						|
            {
 | 
						|
                if (IsHighLightedPsp(pieChart, psp) == true)
 | 
						|
                    return (true);
 | 
						|
            }
 | 
						|
 | 
						|
            if ((labVis & SliceLabelVisibility.SliceSelect) == SliceLabelVisibility.SliceSelect)
 | 
						|
            {
 | 
						|
                if (psp.IsSelected == true)
 | 
						|
                    return (true);
 | 
						|
            }
 | 
						|
 | 
						|
            if ((labVis & SliceLabelVisibility.SliceDetach) == SliceLabelVisibility.SliceDetach)
 | 
						|
            {
 | 
						|
                if (psp.IsDetached == true)
 | 
						|
                    return (true);
 | 
						|
            }
 | 
						|
 | 
						|
            return (false);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RenderAdaptiveLabel
 | 
						|
 | 
						|
        internal bool RenderAdaptiveLabel(Graphics g, PieChart pieChart,
 | 
						|
            PieSeriesPoint psp, double maxRadius, string text, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            double innerOffset = GetLableInnerOffset(psp, maxRadius, lstyle);
 | 
						|
            double outerOffset = GetLableOuterOffset(psp, maxRadius, lstyle);
 | 
						|
 | 
						|
            if (outerOffset - innerOffset > 0)
 | 
						|
            {
 | 
						|
                double centerAngle = psp.CenterAngle % 360;
 | 
						|
 | 
						|
                float fontAngle = 0;
 | 
						|
 | 
						|
                if (lstyle.AutoOrientLabel != Tbool.False)
 | 
						|
                {
 | 
						|
                    if (centerAngle < 180)
 | 
						|
                        fontAngle += 180;
 | 
						|
                }
 | 
						|
 | 
						|
                float c = (float)(Math.PI * outerOffset * 2);
 | 
						|
 | 
						|
                if (c > 0)
 | 
						|
                {
 | 
						|
                    RectangleF[] cBounds = GetAdaptiveCharBounds(g, psp, text, lstyle);
 | 
						|
 | 
						|
                    if (centerAngle < 180)
 | 
						|
                    {
 | 
						|
                        return (PaintAdaptiveFlipText(g, pieChart, psp,
 | 
						|
                            outerOffset, innerOffset, fontAngle, text, cBounds, lstyle));
 | 
						|
                    }
 | 
						|
 | 
						|
                    return (PaintAdaptiveText(g, pieChart, psp,
 | 
						|
                        outerOffset, innerOffset, fontAngle, text, cBounds, lstyle));
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (false);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetAdaptiveCharBounds
 | 
						|
 | 
						|
        private RectangleF[] GetAdaptiveCharBounds(Graphics g,
 | 
						|
            PieSeriesPoint psp, string text, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            RectangleF[] charBounds = psp.CharBounds;
 | 
						|
 | 
						|
            if (charBounds == null || charBounds.Length < text.Length)
 | 
						|
            {
 | 
						|
                charBounds = new RectangleF[text.Length];
 | 
						|
 | 
						|
                int n = (int)Math.Ceiling((double)text.Length / 32);
 | 
						|
 | 
						|
                using (StringFormat sf = new StringFormat())
 | 
						|
                {
 | 
						|
                    sf.FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.MeasureTrailingSpaces;
 | 
						|
 | 
						|
                    for (int i = 0; i < text.Length; i += 32)
 | 
						|
                    {
 | 
						|
                        int len = 32;
 | 
						|
 | 
						|
                        if (i + len > text.Length)
 | 
						|
                            len = text.Length - i;
 | 
						|
 | 
						|
                        MeasureAdaptiveText(g, sf, text, i, len, charBounds, lstyle);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                psp.CharBounds = charBounds;
 | 
						|
            }
 | 
						|
 | 
						|
            return (charBounds); 
 | 
						|
        }
 | 
						|
 | 
						|
        #region MeasureAdaptiveText
 | 
						|
 | 
						|
        private void MeasureAdaptiveText(Graphics g, StringFormat sf,
 | 
						|
            string text, int index, int len, RectangleF[] charBounds, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            CharacterRange[] crs = new CharacterRange[len];
 | 
						|
 | 
						|
            string s = text.Substring(index, len);
 | 
						|
 | 
						|
            for (int j = 0; j < len; j++)
 | 
						|
                crs[j] = new CharacterRange(j, 1);
 | 
						|
 | 
						|
            sf.SetMeasurableCharacterRanges(crs);
 | 
						|
 | 
						|
            Rectangle r = new Rectangle(0, 0, 5000, 5000);
 | 
						|
            Region[] rgns = g.MeasureCharacterRanges(s, lstyle.Font, r, sf);
 | 
						|
 | 
						|
            for (int i = 0; i < len; i++)
 | 
						|
                charBounds[index + i] = rgns[i].GetBounds(g);
 | 
						|
 | 
						|
            if (index > 0)
 | 
						|
            {
 | 
						|
                float dx = charBounds[index - 1].X + charBounds[index - 1].Width - charBounds[index].X;
 | 
						|
 | 
						|
                for (int i = 0; i < len; i++)
 | 
						|
                    charBounds[index + i].X += dx;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region PaintAdaptiveText
 | 
						|
 | 
						|
        private bool PaintAdaptiveText(Graphics g, PieChart pieChart,
 | 
						|
            PieSeriesPoint psp, double outerOffset, double innerOffset,
 | 
						|
            float fontAngle, string text, RectangleF[] cBounds, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            bool clipped;
 | 
						|
            List<WordPosLine> wpsLines =
 | 
						|
                GetAdaptiveLines(psp, outerOffset, innerOffset, text, cBounds, out clipped, lstyle);
 | 
						|
 | 
						|
            if (wpsLines != null && wpsLines.Count > 0)
 | 
						|
            {
 | 
						|
                psp.InnerLabelClipped = clipped;
 | 
						|
 | 
						|
                if (clipped == true)
 | 
						|
                {
 | 
						|
                    if (psp.SliceLabelCropModeEx == SliceLabelCropMode.Hide)
 | 
						|
                        return (false);
 | 
						|
                }
 | 
						|
 | 
						|
                double startAngle;
 | 
						|
                double endAngle;
 | 
						|
                NormalizeSliceAngles(psp, out startAngle, out endAngle);
 | 
						|
 | 
						|
                double startRadians = MathHelper.ToRadians((float)(startAngle + lstyle.AngleMargin));
 | 
						|
                double endRadians = MathHelper.ToRadians((float)(endAngle - lstyle.AngleMargin));
 | 
						|
 | 
						|
                if (startRadians < endRadians)
 | 
						|
                {
 | 
						|
                    TextRenderingHint renderingHint = g.TextRenderingHint;
 | 
						|
                    g.TextRenderingHint = TextRenderingHint.AntiAlias;
 | 
						|
 | 
						|
                    float height = cBounds[0].Height;
 | 
						|
                    float halfHeight = height / 2;
 | 
						|
 | 
						|
                    using (Brush br = new SolidBrush(lstyle.TextColor))
 | 
						|
                    {
 | 
						|
                        foreach (WordPosLine wpsLine in wpsLines)
 | 
						|
                        {
 | 
						|
                            double offset = wpsLine.Offset;
 | 
						|
 | 
						|
                            if (wpsLine.Wps.Count > 0)
 | 
						|
                            {
 | 
						|
                                double dx = GetAlignmentOffset(wpsLine, cBounds, lstyle);
 | 
						|
                                double xRadians = startRadians + (dx / offset);
 | 
						|
 | 
						|
                                foreach (WordPos wp in wpsLine.Wps)
 | 
						|
                                {
 | 
						|
                                    for (int j = 0; j < wp.Text.Length; j++)
 | 
						|
                                    {
 | 
						|
                                        RectangleF tf = cBounds[wp.Index + j];
 | 
						|
 | 
						|
                                        float cRadians = (float)(tf.Width / offset);
 | 
						|
 | 
						|
                                        if (xRadians + cRadians > (float)endRadians + .5)
 | 
						|
                                            break;
 | 
						|
 | 
						|
                                        xRadians += (cRadians / 2);
 | 
						|
 | 
						|
                                        float z = (float)(offset - halfHeight);
 | 
						|
                                        float y = (float)(psp.SliceCenter.Y + z * Math.Sin(xRadians));
 | 
						|
                                        float x = (float)(psp.SliceCenter.X + z * Math.Cos(xRadians));
 | 
						|
 | 
						|
                                        int n = (int)Math.Max(tf.Width, tf.Height);
 | 
						|
 | 
						|
                                        GraphicsState gState = g.Save();
 | 
						|
 | 
						|
                                        g.TranslateTransform(x, y);
 | 
						|
                                        g.RotateTransform(90 + (float)MathHelper.ToDegrees((float)xRadians));
 | 
						|
 | 
						|
                                        g.DrawString(wp.Text[j].ToString(), lstyle.Font, br, -tf.Width/2, -tf.Height / 2);
 | 
						|
 | 
						|
                                        g.Restore(gState);
 | 
						|
 | 
						|
                                        xRadians += (cRadians / 2);
 | 
						|
                                    }
 | 
						|
 | 
						|
                                    if (wp.Index + wp.Length < cBounds.Length)
 | 
						|
                                        xRadians += cBounds[wp.Index + wp.Length].Width / offset;
 | 
						|
                                }
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    if ((outerOffset > psp.OuterRadius) || 
 | 
						|
                        (wpsLines[wpsLines.Count - 1].Offset < psp.InnerRadius))
 | 
						|
                    {
 | 
						|
                        Rectangle t = GetBoundingArcRect(
 | 
						|
                            psp, startAngle, endAngle, outerOffset + height);
 | 
						|
 | 
						|
                        psp.PathBounds = Rectangle.Union(psp.PathBounds, t);
 | 
						|
 | 
						|
                        if (psp.PathBounds.Equals(psp.LastPathBounds) == false)
 | 
						|
                        {
 | 
						|
                            psp.LastPathBounds = psp.PathBounds;
 | 
						|
 | 
						|
                            InvalidateRender(psp.PathBounds);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    g.TextRenderingHint = renderingHint;
 | 
						|
 | 
						|
                    return (true);
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (false);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetBoundingArcRect
 | 
						|
 | 
						|
        private Rectangle GetBoundingArcRect(
 | 
						|
            PieSeriesPoint psp, double startAngle, double endAngle, double outerOffset)
 | 
						|
        {
 | 
						|
            Rectangle r = new Rectangle(psp.SliceCenter, Size.Empty);
 | 
						|
 | 
						|
            double n = startAngle;
 | 
						|
 | 
						|
            n += 89;
 | 
						|
            n = (int)(n / 90) * 90;
 | 
						|
 | 
						|
            while (n <= endAngle)
 | 
						|
            {
 | 
						|
                UpdateAngleBounds(psp, n, outerOffset, ref r);
 | 
						|
 | 
						|
                n += 90;
 | 
						|
            }
 | 
						|
 | 
						|
            if (startAngle % 90 != 0)
 | 
						|
                UpdateAngleBounds(psp, startAngle, outerOffset, ref r);
 | 
						|
 | 
						|
            if (endAngle % 90 != 0)
 | 
						|
                UpdateAngleBounds(psp, endAngle, outerOffset, ref r);
 | 
						|
 | 
						|
            return (r);
 | 
						|
        }
 | 
						|
 | 
						|
        #region UpdateAngleBounds
 | 
						|
 | 
						|
        private void UpdateAngleBounds(PieSeriesPoint psp,
 | 
						|
            double angle, double outerOffset, ref Rectangle r)
 | 
						|
        {
 | 
						|
            Point pts = psp.GetRayEndPoint(angle, outerOffset);
 | 
						|
 | 
						|
            if (pts.X < r.X)
 | 
						|
            {
 | 
						|
                r.Width += (r.X - pts.X);
 | 
						|
                r.X = pts.X;
 | 
						|
            }
 | 
						|
            else if (pts.X > r.Right)
 | 
						|
            {
 | 
						|
                r.Width += (pts.X - r.Right);
 | 
						|
            }
 | 
						|
 | 
						|
            if (pts.Y < r.Y)
 | 
						|
            {
 | 
						|
                r.Height += (r.Y - pts.Y);
 | 
						|
                r.Y = pts.Y;
 | 
						|
            }
 | 
						|
            else if (pts.Y > r.Bottom)
 | 
						|
            {
 | 
						|
                r.Height += (pts.Y - r.Bottom);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetAdaptiveLines
 | 
						|
 | 
						|
        private List<WordPosLine> GetAdaptiveLines(
 | 
						|
            PieSeriesPoint psp, double outerOffset, double innerOffset,
 | 
						|
            string text, RectangleF[] cBounds, out bool clipped, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            if (psp.WordPosLines == null)
 | 
						|
            {
 | 
						|
                psp.WordPosLines =
 | 
						|
                    GetAdaptiveLinesEx(psp, outerOffset, innerOffset, text, cBounds, out clipped, lstyle);
 | 
						|
 | 
						|
                psp.InnerLabelClipped = clipped;
 | 
						|
            }
 | 
						|
 | 
						|
            clipped = psp.InnerLabelClipped;
 | 
						|
 | 
						|
            return (psp.WordPosLines);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetAdaptiveLinesEx
 | 
						|
 | 
						|
        private List<WordPosLine> GetAdaptiveLinesEx(
 | 
						|
            PieSeriesPoint psp, double outerOffset, double innerOffset, string text,
 | 
						|
            RectangleF[] cBounds, out bool clipped, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            float height = cBounds[0].Height;
 | 
						|
            int maxLineCount = (int)((outerOffset - innerOffset) / height);
 | 
						|
 | 
						|
            SliceLabelCropMode cropMode = psp.SliceLabelCropModeEx;
 | 
						|
 | 
						|
            if (cropMode != SliceLabelCropMode.Hide)
 | 
						|
                maxLineCount = 1000;
 | 
						|
 | 
						|
            if (lstyle.MaxLineCount >= 0)
 | 
						|
            {
 | 
						|
                if (maxLineCount > lstyle.MaxLineCount)
 | 
						|
                    maxLineCount = lstyle.MaxLineCount;
 | 
						|
            }
 | 
						|
 | 
						|
            List<WordPosLine> wpsLines = null;
 | 
						|
 | 
						|
            if (maxLineCount > 0)
 | 
						|
            {
 | 
						|
                List<WordPos> wps = GetWordWidths(text, cBounds);
 | 
						|
 | 
						|
                double offset = outerOffset;
 | 
						|
 | 
						|
                bool middle = false;
 | 
						|
 | 
						|
                switch (lstyle.Alignment)
 | 
						|
                {
 | 
						|
                    case SliceLabelAlignment.MiddleLeft:
 | 
						|
                    case SliceLabelAlignment.MiddleRight:
 | 
						|
                    case SliceLabelAlignment.MiddleCenter:
 | 
						|
                        offset = (outerOffset + innerOffset) / 2;
 | 
						|
                        middle = true;
 | 
						|
                        break;
 | 
						|
 | 
						|
                    case SliceLabelAlignment.InnerLeft:
 | 
						|
                    case SliceLabelAlignment.InnerRight:
 | 
						|
                    case SliceLabelAlignment.InnerCenter:
 | 
						|
 | 
						|
                        clipped = false;
 | 
						|
 | 
						|
                        while (offset > innerOffset)
 | 
						|
                        {
 | 
						|
                            List<WordPosLine> ilines = FitAdaptiveLines(psp,
 | 
						|
                                offset, -height, cBounds, maxLineCount, wps, out clipped, lstyle);
 | 
						|
 | 
						|
                            if (ilines != null)
 | 
						|
                            {
 | 
						|
                                if (wpsLines == null || clipped == false)
 | 
						|
                                    wpsLines = ilines;
 | 
						|
 | 
						|
                                if (clipped == true)
 | 
						|
                                    break;
 | 
						|
 | 
						|
                                wps = GetWordWidths(text, cBounds);
 | 
						|
 | 
						|
                                offset -= height;
 | 
						|
                            }
 | 
						|
                            else
 | 
						|
                            {
 | 
						|
                                break;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
 | 
						|
                        return (wpsLines);
 | 
						|
 | 
						|
                    default:
 | 
						|
                        List<WordPosLine> lines = FitAdaptiveLines(psp,
 | 
						|
                            offset, -height, cBounds, maxLineCount, wps, out clipped, lstyle);
 | 
						|
 | 
						|
                        return (lines);
 | 
						|
                }
 | 
						|
 | 
						|
                for (int i = 0; i < maxLineCount; i++)
 | 
						|
                {
 | 
						|
                    List<WordPosLine> lines = FitAdaptiveLines(psp,
 | 
						|
                        offset, -height, cBounds, (i + 1), wps, out clipped, lstyle);
 | 
						|
 | 
						|
                    if (lines != null)
 | 
						|
                    {
 | 
						|
                        if (clipped == false)
 | 
						|
                            return (lines);
 | 
						|
 | 
						|
                        wpsLines = lines;
 | 
						|
 | 
						|
                        wps = GetWordWidths(text, cBounds);
 | 
						|
 | 
						|
                        if ((middle == false) || (i % 2 == 0))
 | 
						|
                            offset += height;
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        break;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            clipped = false;
 | 
						|
 | 
						|
            return (wpsLines);
 | 
						|
        }
 | 
						|
 | 
						|
        #region FitAdaptiveLines
 | 
						|
 | 
						|
        private List<WordPosLine> FitAdaptiveLines(
 | 
						|
            PieSeriesPoint psp, double offset, float height, RectangleF[] cBounds,
 | 
						|
            int count, List<WordPos> wps, out bool clipped, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            List<WordPosLine> wpsLines = new List<WordPosLine>();
 | 
						|
 | 
						|
            int wordIndex = 0;
 | 
						|
 | 
						|
            while (wpsLines.Count < count)
 | 
						|
            {
 | 
						|
                int lineWordCount = 0;
 | 
						|
 | 
						|
                double arcWidth = GetArcWidth(psp, offset - cBounds[0].Height / 4, lstyle);
 | 
						|
 | 
						|
                if (arcWidth <= 0)
 | 
						|
                    break;
 | 
						|
 | 
						|
                WordPosLine wpsLine = new WordPosLine();
 | 
						|
 | 
						|
                wpsLine.Offset = offset;
 | 
						|
                wpsLine.ArcWidth = arcWidth;
 | 
						|
 | 
						|
                while (wordIndex < wps.Count)
 | 
						|
                {
 | 
						|
                    WordPos wp = wps[wordIndex];
 | 
						|
 | 
						|
                    double wordLength = GetWordLength(wp, cBounds, lineWordCount);
 | 
						|
 | 
						|
                    if (wp.Text.Equals("\n") == true)
 | 
						|
                    {
 | 
						|
                        if (wpsLine.Wps.Count == 0)
 | 
						|
                            wpsLine.Wps.Add(wp);
 | 
						|
 | 
						|
                        wordIndex++;
 | 
						|
                        break;
 | 
						|
                    }
 | 
						|
 | 
						|
                    if (wpsLine.ArcWidth - (wpsLine.LineWidth + wordLength) < 0)
 | 
						|
                    {
 | 
						|
                        if (lineWordCount == 0 || wpsLines.Count + 1 == count)
 | 
						|
                        {
 | 
						|
                            wpsLine = FitNonBrokenLine(psp, offset,
 | 
						|
                                count - wpsLines.Count, wpsLines, wpsLine, wp, cBounds, height, out clipped, lstyle);
 | 
						|
 | 
						|
                            if (clipped == true || wpsLine == null)
 | 
						|
                            {
 | 
						|
                                if (wpsLine != null && wpsLine.Wps.Count > 0)
 | 
						|
                                    wpsLines.Add(wpsLine);
 | 
						|
 | 
						|
                                return (wpsLines);
 | 
						|
                            }
 | 
						|
 | 
						|
                            offset = wpsLine.Offset;
 | 
						|
                        }
 | 
						|
                        else
 | 
						|
                        {
 | 
						|
                            break;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        wpsLine.LineWidth += wordLength;
 | 
						|
 | 
						|
                        wpsLine.Wps.Add(wp);
 | 
						|
                    }
 | 
						|
 | 
						|
                    wordIndex++;
 | 
						|
                    lineWordCount++;
 | 
						|
                }
 | 
						|
 | 
						|
                if (wpsLine.Wps.Count > 0)
 | 
						|
                {
 | 
						|
                    offset = wpsLine.Offset;
 | 
						|
 | 
						|
                    wpsLines.Add(wpsLine);
 | 
						|
                }
 | 
						|
 | 
						|
                if (wordIndex >= wps.Count)
 | 
						|
                    break;
 | 
						|
 | 
						|
                offset += height;
 | 
						|
            }
 | 
						|
 | 
						|
            clipped = (wordIndex < wps.Count);
 | 
						|
 | 
						|
            return (wpsLines);
 | 
						|
        }
 | 
						|
 | 
						|
        #region FitNonBrokenLine
 | 
						|
 | 
						|
        private WordPosLine FitNonBrokenLine(PieSeriesPoint psp,
 | 
						|
            double offset, int maxCount, List<WordPosLine> wpsLines, WordPosLine wpsLine,
 | 
						|
            WordPos wp, RectangleF[] cBounds, float height, out bool clipped, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            double length;
 | 
						|
            int count = GetNonBrokenCount(wpsLine, wp, cBounds, out length);
 | 
						|
 | 
						|
            clipped = true;
 | 
						|
 | 
						|
            if (length == 0)
 | 
						|
                return (wpsLine);
 | 
						|
 | 
						|
            int rindex = wp.Index;
 | 
						|
 | 
						|
            while (count > 0)
 | 
						|
            {
 | 
						|
                WordPos wp2 = new WordPos();
 | 
						|
 | 
						|
                wp2.Index = wp.Index;
 | 
						|
                wp2.Length = count;
 | 
						|
                wp2.Text = wp.Text.Substring((wp.Index - rindex), count);
 | 
						|
 | 
						|
                wpsLine.Wps.Add(wp2);
 | 
						|
 | 
						|
                wp.Index += count;
 | 
						|
                wp.Length -= count;
 | 
						|
 | 
						|
                if (--maxCount <= 0)
 | 
						|
                    break;
 | 
						|
 | 
						|
                if (wp.Length <= 0)
 | 
						|
                    break;
 | 
						|
 | 
						|
                wpsLines.Add(wpsLine);
 | 
						|
 | 
						|
                offset += height;
 | 
						|
 | 
						|
                wpsLine = new WordPosLine();
 | 
						|
                wpsLine.Offset = offset;
 | 
						|
 | 
						|
                wpsLine.ArcWidth = GetArcWidth(psp, offset - cBounds[0].Height / 4, lstyle);
 | 
						|
 | 
						|
                count = GetNonBrokenCount(wpsLine, wp, cBounds, out length);
 | 
						|
            }
 | 
						|
 | 
						|
            clipped = (wp.Length > 0);
 | 
						|
 | 
						|
            return (wpsLine);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetNonBrokenCount
 | 
						|
 | 
						|
        private int GetNonBrokenCount(
 | 
						|
            WordPosLine wpsLine, WordPos wp, RectangleF[] cBounds, out double length)
 | 
						|
        {
 | 
						|
            length = 0;
 | 
						|
 | 
						|
            if (wpsLine.Wps.Count > 0 && wp.Index > 0)
 | 
						|
            {
 | 
						|
                double width = cBounds[wp.Index - 1].Width;
 | 
						|
 | 
						|
                if (wpsLine.ArcWidth - (wpsLine.LineWidth + width) < 0)
 | 
						|
                    return (0);
 | 
						|
 | 
						|
                wpsLine.LineWidth += width;
 | 
						|
                length += width;
 | 
						|
            }
 | 
						|
 | 
						|
            for (int i = 0; i < wp.Length; i++)
 | 
						|
            {
 | 
						|
                double width = cBounds[wp.Index + i].Width;
 | 
						|
 | 
						|
                if (wpsLine.ArcWidth - (wpsLine.LineWidth + width) < 0)
 | 
						|
                    return (i);
 | 
						|
 | 
						|
                wpsLine.LineWidth += width;
 | 
						|
                length += width;
 | 
						|
            }
 | 
						|
 | 
						|
            return (wp.Length);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region PaintAdaptiveFlipText
 | 
						|
 | 
						|
        private bool PaintAdaptiveFlipText(Graphics g, PieChart pieChart,
 | 
						|
            PieSeriesPoint psp, double outerOffset, double innerOffset, float fontAngle,
 | 
						|
            string text, RectangleF[] cBounds, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            bool clipped;
 | 
						|
            List<WordPosLine> wpsLines =
 | 
						|
                GetAdaptiveFlipLines(psp, outerOffset, innerOffset, text, cBounds, out clipped, lstyle);
 | 
						|
 | 
						|
            if (wpsLines != null && wpsLines.Count > 0)
 | 
						|
            {
 | 
						|
                if (clipped == true)
 | 
						|
                {
 | 
						|
                    if (psp.SliceLabelCropModeEx == SliceLabelCropMode.Hide)
 | 
						|
                        return (false);
 | 
						|
                }
 | 
						|
 | 
						|
                double startAngle;
 | 
						|
                double endAngle;
 | 
						|
                NormalizeSliceAngles(psp, out startAngle, out endAngle);
 | 
						|
 | 
						|
                double endRadians = MathHelper.ToRadians(startAngle + lstyle.AngleMargin);
 | 
						|
                double startRadians = MathHelper.ToRadians(endAngle - lstyle.AngleMargin);
 | 
						|
 | 
						|
                float height = cBounds[0].Height;
 | 
						|
                float halfHeight = height / 2;
 | 
						|
 | 
						|
                TextRenderingHint renderingHint = g.TextRenderingHint;
 | 
						|
                g.TextRenderingHint = TextRenderingHint.AntiAlias;
 | 
						|
 | 
						|
                using (Brush br = new SolidBrush(lstyle.TextColor))
 | 
						|
                {
 | 
						|
                    foreach (WordPosLine wpsLine in wpsLines)
 | 
						|
                    {
 | 
						|
                        double offset = wpsLine.Offset;
 | 
						|
 | 
						|
                        if (wpsLine.Wps.Count > 0)
 | 
						|
                        {
 | 
						|
                            double dx = GetAlignmentOffset(wpsLine, cBounds, lstyle);
 | 
						|
                            double xRadians = startRadians - dx / offset;
 | 
						|
 | 
						|
                            foreach (WordPos wp in wpsLine.Wps)
 | 
						|
                            {
 | 
						|
                                for (int j = 0; j < wp.Text.Length; j++)
 | 
						|
                                {
 | 
						|
                                    if (xRadians < (float)endRadians)
 | 
						|
                                        break;
 | 
						|
 | 
						|
                                    RectangleF tf = cBounds[wp.Index + j];
 | 
						|
 | 
						|
                                    float cRadians = (float)(tf.Width / offset);
 | 
						|
 | 
						|
                                    xRadians -= (cRadians / 2);
 | 
						|
 | 
						|
                                    float z = (float)(offset - halfHeight);
 | 
						|
                                    float y = (float)((float)psp.SliceCenter.Y + z * Math.Sin(xRadians));
 | 
						|
                                    float x = (float)((float)psp.SliceCenter.X + z * Math.Cos(xRadians));
 | 
						|
 | 
						|
                                    GraphicsState gState = g.Save();
 | 
						|
 | 
						|
                                    g.TranslateTransform(x, y);
 | 
						|
                                    g.RotateTransform(-90 + (float)MathHelper.ToDegrees(xRadians));
 | 
						|
 | 
						|
                                    g.DrawString(wp.Text[j].ToString(), lstyle.Font, br, -tf.Width / 2, -tf.Height / 2);
 | 
						|
 | 
						|
                                    g.Restore(gState);
 | 
						|
 | 
						|
                                    xRadians -= (cRadians / 2);
 | 
						|
                                }
 | 
						|
 | 
						|
                                if (wp.Index + wp.Length < cBounds.Length)
 | 
						|
                                    xRadians -= cBounds[wp.Index + wp.Length].Width / offset;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                if ((outerOffset > psp.OuterRadius) ||
 | 
						|
                    (wpsLines.Count > 0 && wpsLines[0].Offset < psp.InnerRadius))
 | 
						|
                {
 | 
						|
                    Rectangle t = GetBoundingArcRect(
 | 
						|
                        psp, startAngle, endAngle, outerOffset + height);
 | 
						|
 | 
						|
                    psp.PathBounds = Rectangle.Union(psp.PathBounds, t);
 | 
						|
 | 
						|
                    if (psp.PathBounds.Equals(psp.LastPathBounds) == false)
 | 
						|
                    {
 | 
						|
                        psp.LastPathBounds = psp.PathBounds;
 | 
						|
 | 
						|
                        InvalidateRender(psp.PathBounds);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                g.TextRenderingHint = renderingHint;
 | 
						|
 | 
						|
                return (true);
 | 
						|
            }
 | 
						|
 | 
						|
            return (false);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetAdaptiveFlipLines
 | 
						|
 | 
						|
        private List<WordPosLine> GetAdaptiveFlipLines(
 | 
						|
            PieSeriesPoint psp, double outerOffset, double innerOffset,
 | 
						|
            string text, RectangleF[] cBounds, out bool clipped, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            if (psp.WordPosLines == null)
 | 
						|
            {
 | 
						|
                psp.WordPosLines =
 | 
						|
                    GetAdaptiveFlipLinesEx(psp, outerOffset, innerOffset, text, cBounds, out clipped, lstyle);
 | 
						|
 | 
						|
                psp.InnerLabelClipped = clipped;
 | 
						|
            }
 | 
						|
 | 
						|
            clipped = psp.InnerLabelClipped;
 | 
						|
 | 
						|
            return (psp.WordPosLines);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetAdaptiveFlipLinesEx
 | 
						|
 | 
						|
        private List<WordPosLine> GetAdaptiveFlipLinesEx(
 | 
						|
            PieSeriesPoint psp, double outerOffset, double innerOffset,
 | 
						|
            string text, RectangleF[] cBounds, out bool clipped, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            float height = cBounds[0].Height;
 | 
						|
            int maxLineCount = (int)Math.Abs((outerOffset - innerOffset) / height);
 | 
						|
 | 
						|
            SliceLabelCropMode cropMode = psp.SliceLabelCropModeEx;
 | 
						|
 | 
						|
            if (cropMode == SliceLabelCropMode.NoAction)
 | 
						|
                maxLineCount = 1000;
 | 
						|
 | 
						|
            if (lstyle.MaxLineCount >= 0)
 | 
						|
            {
 | 
						|
                if (maxLineCount > lstyle.MaxLineCount)
 | 
						|
                    maxLineCount = lstyle.MaxLineCount;
 | 
						|
            }
 | 
						|
 | 
						|
            List<WordPosLine> wpsLines = null;
 | 
						|
 | 
						|
            clipped = false;
 | 
						|
 | 
						|
            if (maxLineCount > 0)
 | 
						|
            {
 | 
						|
                List<WordPos> wps = GetWordWidths(text, cBounds);
 | 
						|
 | 
						|
                double offset = outerOffset;
 | 
						|
 | 
						|
                bool middle = false;
 | 
						|
 | 
						|
                switch (lstyle.Alignment)
 | 
						|
                {
 | 
						|
                    case SliceLabelAlignment.MiddleLeft:
 | 
						|
                    case SliceLabelAlignment.MiddleRight:
 | 
						|
                    case SliceLabelAlignment.MiddleCenter:
 | 
						|
                        offset = (outerOffset + innerOffset) / 2;
 | 
						|
                        height = -height;
 | 
						|
                        middle = true;
 | 
						|
                        break;
 | 
						|
 | 
						|
                    case SliceLabelAlignment.InnerLeft:
 | 
						|
                    case SliceLabelAlignment.InnerRight:
 | 
						|
                    case SliceLabelAlignment.InnerCenter:
 | 
						|
 | 
						|
                        clipped = false;
 | 
						|
 | 
						|
                        offset = innerOffset;
 | 
						|
 | 
						|
                        while (offset < outerOffset)
 | 
						|
                        {
 | 
						|
                            List<WordPosLine> ilines = FitAdaptiveLines(psp,
 | 
						|
                                offset, height, cBounds, maxLineCount, wps, out clipped, lstyle);
 | 
						|
 | 
						|
                            if (ilines != null && ilines.Count > 0)
 | 
						|
                                return (ilines);
 | 
						|
 | 
						|
                            wps = GetWordWidths(text, cBounds);
 | 
						|
 | 
						|
                            offset += height;
 | 
						|
                        }
 | 
						|
 | 
						|
                        return (wpsLines);
 | 
						|
 | 
						|
                    default:
 | 
						|
                        height = -height;
 | 
						|
                        break;
 | 
						|
                }
 | 
						|
 | 
						|
                for (int i = 0; i < maxLineCount; i++)
 | 
						|
                {
 | 
						|
                    List<WordPosLine> lines = FitAdaptiveLines(psp,
 | 
						|
                        offset, Math.Abs(height), cBounds, i + 1, wps, out clipped, lstyle);
 | 
						|
 | 
						|
                    if (lines != null)
 | 
						|
                    {
 | 
						|
                        if (clipped == false)
 | 
						|
                            return (lines);
 | 
						|
 | 
						|
                        wpsLines = lines;
 | 
						|
 | 
						|
                        wps = GetWordWidths(text, cBounds);
 | 
						|
 | 
						|
                        if ((middle == false) || (i % 2 == 0))
 | 
						|
                            offset += height;
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        break;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (wpsLines);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region NormalizeSliceAngles
 | 
						|
 | 
						|
        private void NormalizeSliceAngles(
 | 
						|
            PieSeriesPoint psp, out double startAngle, out double endAngle)
 | 
						|
        {
 | 
						|
            startAngle = psp.StartAngleEx;
 | 
						|
            endAngle = psp.StartAngleEx + psp.SweepAngleEx;
 | 
						|
 | 
						|
            if (startAngle > endAngle)
 | 
						|
            {
 | 
						|
                double temp = startAngle;
 | 
						|
                startAngle = endAngle;
 | 
						|
                endAngle = temp;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetArcWidth
 | 
						|
 | 
						|
        private double GetArcWidth(
 | 
						|
            PieSeriesPoint psp, double offset, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            double margin = lstyle.AngleMargin * 2;
 | 
						|
            double sweep = Math.Abs(psp.SweepAngleEx);
 | 
						|
 | 
						|
            double width = offset * MathHelper.ToRadians(sweep - margin);
 | 
						|
 | 
						|
            return (width);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetWordLength
 | 
						|
 | 
						|
        private double GetWordLength(
 | 
						|
            WordPos wp, RectangleF[] cBounds, int lineWordCount)
 | 
						|
        {
 | 
						|
            double length = 0;
 | 
						|
 | 
						|
            if (lineWordCount > 0)
 | 
						|
                length += cBounds[wp.Index - 1].Width;
 | 
						|
 | 
						|
            for (int i = 0; i < wp.Length; i++)
 | 
						|
                length += cBounds[wp.Index + i].Width;
 | 
						|
 | 
						|
            return (length);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetWordWidths
 | 
						|
 | 
						|
        private List<WordPos> GetWordWidths(string text, RectangleF[] cBounds)
 | 
						|
        {
 | 
						|
            List<WordPos> wps = new List<WordPos>();
 | 
						|
 | 
						|
            int index = 0;
 | 
						|
 | 
						|
            while (index < text.Length)
 | 
						|
            {
 | 
						|
                int length = GetNextWord(text, ref index);
 | 
						|
 | 
						|
                if (length > 0)
 | 
						|
                {
 | 
						|
                    WordPos wp = new WordPos();
 | 
						|
 | 
						|
                    wp.Index = index;
 | 
						|
                    wp.Length = length;
 | 
						|
                    wp.Text = text.Substring(index, length);
 | 
						|
 | 
						|
                    wps.Add(wp);
 | 
						|
 | 
						|
                    index += length;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (wps);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetNextWord
 | 
						|
 | 
						|
        private int GetNextWord(string text, ref int index)
 | 
						|
        {
 | 
						|
            while (index < text.Length)
 | 
						|
            {
 | 
						|
                if (text[index] == '\n')
 | 
						|
                    return (1);
 | 
						|
 | 
						|
                if (Char.IsWhiteSpace(text[index]) == false)
 | 
						|
                    break;
 | 
						|
 | 
						|
                index++;
 | 
						|
            }
 | 
						|
 | 
						|
            int eindex = index;
 | 
						|
 | 
						|
            while (eindex < text.Length)
 | 
						|
            {
 | 
						|
                if (Char.IsWhiteSpace(text[eindex]) == true)
 | 
						|
                    break;
 | 
						|
 | 
						|
                eindex++;
 | 
						|
            }
 | 
						|
 | 
						|
            return (eindex - index);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetAlignmentOffset
 | 
						|
 | 
						|
        private double GetAlignmentOffset(
 | 
						|
            WordPosLine wpsLine, RectangleF[] tbounds, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            switch (lstyle.Alignment)
 | 
						|
            {
 | 
						|
                case SliceLabelAlignment.OuterRight:
 | 
						|
                case SliceLabelAlignment.MiddleRight:
 | 
						|
                case SliceLabelAlignment.InnerRight:
 | 
						|
                    return (wpsLine.ArcWidth - wpsLine.LineWidth);
 | 
						|
 | 
						|
                case SliceLabelAlignment.OuterCenter:
 | 
						|
                case SliceLabelAlignment.MiddleCenter:
 | 
						|
                case SliceLabelAlignment.InnerCenter:
 | 
						|
                    return ((wpsLine.ArcWidth - wpsLine.LineWidth) / 2);
 | 
						|
 | 
						|
                default:
 | 
						|
                    return (0);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RenderCustomLabel
 | 
						|
 | 
						|
        internal bool RenderCustomLabel(Graphics g, PieChart pieChart,
 | 
						|
            PieSeriesPoint psp, double maxRadius, string text,SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            double angle = GetCustomLabelAngle(psp, lstyle);
 | 
						|
            double offset = GetCustomLableOffset(psp, maxRadius, lstyle);
 | 
						|
 | 
						|
            Rectangle r = GetCustomLabelRect(psp, maxRadius, angle, offset, lstyle);
 | 
						|
 | 
						|
            angle += lstyle.CustomFontAngle;
 | 
						|
 | 
						|
            if (lstyle.AutoRotate != Tbool.True)
 | 
						|
                angle -= (psp.CenterAngle - 90);
 | 
						|
 | 
						|
            angle = (angle + 360000) % 360;
 | 
						|
 | 
						|
            double fontAngle = 0;
 | 
						|
 | 
						|
            if (lstyle.AutoOrientLabel != Tbool.False)
 | 
						|
            {
 | 
						|
                if (angle < 180)
 | 
						|
                    fontAngle += 180;
 | 
						|
            }
 | 
						|
 | 
						|
            r = GetSliceLabelBounds(g, pieChart, psp, text, r, lstyle);
 | 
						|
 | 
						|
            if (r.Width > 0 && r.Height > 0)
 | 
						|
            {
 | 
						|
                GraphicsState gState = g.Save();
 | 
						|
 | 
						|
                TextRenderingHint renderingHint = g.TextRenderingHint;
 | 
						|
                g.TextRenderingHint = TextRenderingHint.AntiAlias;
 | 
						|
 | 
						|
                using (StringFormat sf = new StringFormat())
 | 
						|
                {
 | 
						|
                    lstyle.GetStringFormatFlags(sf, angle < 180);
 | 
						|
 | 
						|
                    g.TranslateTransform(r.X, r.Y);
 | 
						|
                    g.RotateTransform((float)(angle + fontAngle + 90));
 | 
						|
 | 
						|
                    r.X = -(int)(r.Width / 2);
 | 
						|
                    r.Y = -(int)(r.Height / 2);
 | 
						|
 | 
						|
                    if (lstyle.Background.IsEmpty == false)
 | 
						|
                    {
 | 
						|
                        using (Brush br = lstyle.Background.GetBrush(r))
 | 
						|
                            g.FillRectangle(br, r);
 | 
						|
                    }
 | 
						|
 | 
						|
                    using (Brush br = new SolidBrush(lstyle.TextColor))
 | 
						|
                        g.DrawString(text, lstyle.Font, br, r, sf);
 | 
						|
 | 
						|
                    if (ChartControl.DesignerHosted == true)
 | 
						|
                    {
 | 
						|
                        using (Pen pen = new Pen(Color.Plum))
 | 
						|
                        {
 | 
						|
                            pen.DashStyle = DashStyle.Dash;
 | 
						|
 | 
						|
                            g.DrawRectangle(pen, r);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                g.Restore(gState);
 | 
						|
 | 
						|
                return (true);
 | 
						|
            }
 | 
						|
 | 
						|
            return (false);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetCustomLabelRect
 | 
						|
 | 
						|
        private Rectangle GetCustomLabelRect(PieSeriesPoint psp,
 | 
						|
            double maxRadius, double angle, double offset, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            Rectangle r = new Rectangle();
 | 
						|
 | 
						|
            r.Location = psp.GetRayEndPoint(angle, offset);
 | 
						|
 | 
						|
            r.Width = (int)GetCustomLabelWidth(psp, offset, lstyle);
 | 
						|
            r.Height = (int)GetCustomLabelHeight(psp, maxRadius, offset, lstyle);
 | 
						|
 | 
						|
            return (r);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetCustomLabelHeight
 | 
						|
 | 
						|
        private double GetCustomLabelHeight(PieSeriesPoint psp,
 | 
						|
            double maxRadius, double offset, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            double height = maxRadius - psp.InnerRadius;
 | 
						|
 | 
						|
            if (double.IsNaN(lstyle.CustomHeight) == false)
 | 
						|
            {
 | 
						|
                if (Math.Abs(lstyle.CustomHeight) < 1)
 | 
						|
                    return (lstyle.CustomHeight * height);
 | 
						|
 | 
						|
                return (lstyle.CustomHeight);
 | 
						|
            }
 | 
						|
 | 
						|
            return (height * .5);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetCustomLabelWidth
 | 
						|
 | 
						|
        private double GetCustomLabelWidth(
 | 
						|
            PieSeriesPoint psp, double offset, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            double width = GetArcWidth(psp, offset, lstyle);
 | 
						|
 | 
						|
            if (double.IsNaN(lstyle.CustomWidth) == false)
 | 
						|
            {
 | 
						|
                if (Math.Abs(lstyle.CustomWidth) < 1)
 | 
						|
                    return (lstyle.CustomWidth * width);
 | 
						|
 | 
						|
                return (lstyle.CustomWidth);
 | 
						|
            }
 | 
						|
 | 
						|
            return (width * .8);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetCustomLableOffset
 | 
						|
 | 
						|
        private double GetCustomLableOffset(
 | 
						|
            PieSeriesPoint psp, double maxRadius, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            double offset = lstyle.CustomRadiusOffset;
 | 
						|
 | 
						|
            if (double.IsNaN(offset) == false)
 | 
						|
            {
 | 
						|
                if (Math.Abs(offset) < 1)
 | 
						|
                    offset = (maxRadius - psp.InnerRadius) * offset;
 | 
						|
 | 
						|
                return (psp.InnerRadius + offset);
 | 
						|
            }
 | 
						|
 | 
						|
            return (psp.InnerRadius + (maxRadius - psp.InnerRadius) * .7);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetCustomLabelAngle
 | 
						|
 | 
						|
        private double GetCustomLabelAngle(PieSeriesPoint psp, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            double angle = (psp.StartAngleEx + psp.SweepAngleEx / 2) % 360;
 | 
						|
 | 
						|
            if (double.IsNaN(lstyle.CustomAngleOffset) == false)
 | 
						|
            {
 | 
						|
                double offset = lstyle.CustomAngleOffset;
 | 
						|
 | 
						|
                if (Math.Abs(offset) < 1)
 | 
						|
                    angle += (psp.SweepAngleEx * offset);
 | 
						|
                else
 | 
						|
                    angle += offset;
 | 
						|
            }
 | 
						|
 | 
						|
            return (angle);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RenderParallelLabel
 | 
						|
 | 
						|
        internal bool RenderParallelLabel(Graphics g, PieChart pieChart,
 | 
						|
            PieSeriesPoint psp, double maxRadius, string text, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            double centerAngle = psp.CenterAngle % 360;
 | 
						|
 | 
						|
            double innerOffset = GetLableInnerOffset(psp, maxRadius, lstyle);
 | 
						|
            double outerOffset = GetLableOuterOffset(psp, maxRadius, lstyle);
 | 
						|
 | 
						|
            float fontAngle = 0;
 | 
						|
 | 
						|
            if (lstyle.AutoOrientLabel != Tbool.False)
 | 
						|
            {
 | 
						|
                if (centerAngle >= 90 && centerAngle < 270)
 | 
						|
                    fontAngle += 180;
 | 
						|
            }
 | 
						|
 | 
						|
            Point lpt = psp.GetRayEndPoint(
 | 
						|
                centerAngle, (innerOffset + outerOffset) / 2);
 | 
						|
 | 
						|
            Rectangle r = new Rectangle();
 | 
						|
 | 
						|
            r.Location = lpt;
 | 
						|
            r.Width = (int)(outerOffset - innerOffset);
 | 
						|
            r.Height = (int)GetArcWidth(psp, innerOffset, lstyle);
 | 
						|
 | 
						|
            r = GetSliceLabelBounds(g, pieChart, psp, text, r, lstyle);
 | 
						|
 | 
						|
            if (r.Width > 0 && r.Height > 0)
 | 
						|
            {
 | 
						|
                GraphicsState gState = g.Save();
 | 
						|
 | 
						|
                TextRenderingHint renderingHint = g.TextRenderingHint;
 | 
						|
                g.TextRenderingHint = TextRenderingHint.AntiAlias;
 | 
						|
 | 
						|
                using (StringFormat sf = new StringFormat())
 | 
						|
                {
 | 
						|
                    GetStringFormatFlags(lstyle, sf, fontAngle != 0);
 | 
						|
 | 
						|
                    r.X = -(int)(r.Width / 2);
 | 
						|
                    r.Y = -(int)(r.Height / 2);
 | 
						|
 | 
						|
                    g.TranslateTransform(lpt.X, lpt.Y);
 | 
						|
                    g.RotateTransform((float)centerAngle + fontAngle);
 | 
						|
 | 
						|
                    if (lstyle.Background.IsEmpty == false)
 | 
						|
                    {
 | 
						|
                        using (Brush br = lstyle.Background.GetBrush(r))
 | 
						|
                            g.FillRectangle(br, r);
 | 
						|
                    }
 | 
						|
 | 
						|
                    using (Brush br = new SolidBrush(lstyle.TextColor))
 | 
						|
                        g.DrawString(text, lstyle.Font, br, r, sf);
 | 
						|
                }
 | 
						|
 | 
						|
                g.Restore(gState);
 | 
						|
 | 
						|
                return (true);
 | 
						|
            }
 | 
						|
 | 
						|
            return (false);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetStringFormatFlags
 | 
						|
 | 
						|
        private void GetStringFormatFlags(
 | 
						|
            SliceInnerLabelVisualStyle lstyle, StringFormat sf, bool flip)
 | 
						|
        {
 | 
						|
            if (lstyle.AllowWrap == Tbool.False || lstyle.MaxLineCount == 1)
 | 
						|
                sf.FormatFlags |= StringFormatFlags.NoWrap;
 | 
						|
 | 
						|
            sf.Trimming = StringTrimming.EllipsisCharacter;
 | 
						|
 | 
						|
            switch (lstyle.Alignment)
 | 
						|
            {
 | 
						|
                case SliceLabelAlignment.OuterLeft:
 | 
						|
                    sf.Alignment = (flip ? StringAlignment.Near : StringAlignment.Far);     // Outer/inner
 | 
						|
                    sf.LineAlignment = (flip ? StringAlignment.Far : StringAlignment.Near); // Left/right
 | 
						|
                    break;
 | 
						|
 | 
						|
                case SliceLabelAlignment.InnerLeft:
 | 
						|
                    sf.Alignment = (flip ? StringAlignment.Far : StringAlignment.Near);
 | 
						|
                    sf.LineAlignment = (flip ? StringAlignment.Far : StringAlignment.Near);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case SliceLabelAlignment.MiddleLeft:
 | 
						|
                    sf.Alignment = StringAlignment.Center;
 | 
						|
                    sf.LineAlignment = (flip ? StringAlignment.Far : StringAlignment.Near);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case SliceLabelAlignment.OuterRight:
 | 
						|
                    sf.Alignment = (flip ? StringAlignment.Near : StringAlignment.Far);
 | 
						|
                    sf.LineAlignment = (flip ? StringAlignment.Near : StringAlignment.Far);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case SliceLabelAlignment.InnerRight:
 | 
						|
                    sf.Alignment = (flip ? StringAlignment.Far : StringAlignment.Near);
 | 
						|
                    sf.LineAlignment = (flip ? StringAlignment.Near : StringAlignment.Far);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case SliceLabelAlignment.MiddleRight:
 | 
						|
                    sf.Alignment = StringAlignment.Center;
 | 
						|
                    sf.LineAlignment = (flip ? StringAlignment.Near : StringAlignment.Far);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case SliceLabelAlignment.OuterCenter:
 | 
						|
                    sf.Alignment = (flip ? StringAlignment.Near : StringAlignment.Far);
 | 
						|
                    sf.LineAlignment = StringAlignment.Center;
 | 
						|
                    break;
 | 
						|
 | 
						|
                case SliceLabelAlignment.InnerCenter:
 | 
						|
                    sf.Alignment = (flip ? StringAlignment.Far : StringAlignment.Near);
 | 
						|
                    sf.LineAlignment = StringAlignment.Center;
 | 
						|
                    break;
 | 
						|
 | 
						|
                case SliceLabelAlignment.NotSet:
 | 
						|
                case SliceLabelAlignment.MiddleCenter:
 | 
						|
                    sf.Alignment = StringAlignment.Center;
 | 
						|
                    sf.LineAlignment = StringAlignment.Center;
 | 
						|
                    break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RenderPerpendicularLabel
 | 
						|
 | 
						|
        internal bool RenderPerpendicularLabel(Graphics g, PieChart pieChart,
 | 
						|
            PieSeriesPoint psp, double maxRadius, string text, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            double innerOffset = GetLableInnerOffset(psp, maxRadius, lstyle);
 | 
						|
            double outerOffset = GetLableOuterOffset(psp, maxRadius, lstyle);
 | 
						|
 | 
						|
            if (outerOffset - innerOffset > 0)
 | 
						|
            {
 | 
						|
                double centerAngle = psp.CenterAngle % 360;
 | 
						|
 | 
						|
                Point lpt = psp.GetRayEndPoint(centerAngle, outerOffset);
 | 
						|
 | 
						|
                float fontAngle = 0;
 | 
						|
 | 
						|
                if (lstyle.AutoOrientLabel != Tbool.False)
 | 
						|
                {
 | 
						|
                    if (centerAngle < 180)
 | 
						|
                        fontAngle += 180;
 | 
						|
                }
 | 
						|
 | 
						|
                Rectangle r = GetInscribedRectP(psp, maxRadius,
 | 
						|
                    centerAngle, outerOffset, innerOffset, lpt, lstyle);
 | 
						|
 | 
						|
                r = GetSliceLabelBounds(g, pieChart, psp, text, r, lstyle);
 | 
						|
 | 
						|
                if (r.Width > 0 && r.Height > 0)
 | 
						|
                {
 | 
						|
                    GraphicsState gState = g.Save();
 | 
						|
 | 
						|
                    TextRenderingHint renderingHint = g.TextRenderingHint;
 | 
						|
                    g.TextRenderingHint = TextRenderingHint.AntiAlias;
 | 
						|
 | 
						|
                    g.TranslateTransform(lpt.X, lpt.Y);
 | 
						|
                    g.RotateTransform((float)((centerAngle + fontAngle + 90) % 360));
 | 
						|
 | 
						|
                    if (lstyle.Background.IsEmpty == false)
 | 
						|
                    {
 | 
						|
                        using (Brush br = lstyle.Background.GetBrush(r))
 | 
						|
                            g.FillRectangle(br, r);
 | 
						|
                    }
 | 
						|
 | 
						|
                    using (StringFormat sf = new StringFormat())
 | 
						|
                    {
 | 
						|
                        lstyle.GetStringFormatFlags(sf, (centerAngle < 180));
 | 
						|
 | 
						|
                        using (Brush br = new SolidBrush(lstyle.TextColor))
 | 
						|
                            g.DrawString(text, lstyle.Font, br, r, sf);
 | 
						|
                    }
 | 
						|
 | 
						|
                    g.Restore(gState);
 | 
						|
 | 
						|
                    return (true);
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (false);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetInscribedRectP
 | 
						|
 | 
						|
        private Rectangle GetInscribedRectP(PieSeriesPoint psp, double maxRadius,
 | 
						|
            double centerAngle, double outerOffset, double innerOffset, Point lpt, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            if (psp.InscribedRectValid == false)
 | 
						|
            {
 | 
						|
                double sweepAngle = psp.SweepAngleEx / 2 - lstyle.AngleMargin;
 | 
						|
 | 
						|
                double b = (innerOffset * Math.Tan(MathHelper.ToRadians(sweepAngle)));
 | 
						|
                double h = (outerOffset - innerOffset);
 | 
						|
 | 
						|
                double maxb = Math.Sqrt(maxRadius * maxRadius - outerOffset * outerOffset);
 | 
						|
 | 
						|
                if (b > maxb)
 | 
						|
                    b = maxb;
 | 
						|
 | 
						|
                h = (h / lstyle.Font.Height) * lstyle.Font.Height;
 | 
						|
 | 
						|
                Rectangle r = new Rectangle();
 | 
						|
 | 
						|
                r.Location = new Point((int)-b, (centerAngle < 180) ? (int)-h : 0);
 | 
						|
 | 
						|
                r.Width = (int)(b * 2);
 | 
						|
                r.Height = (int)h;
 | 
						|
 | 
						|
                psp.InscribedRect = r;
 | 
						|
            }
 | 
						|
 | 
						|
            return (psp.InscribedRect);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RenderHorizontalLabel
 | 
						|
 | 
						|
        internal bool RenderHorizontalLabel(Graphics g, PieChart pieChart,
 | 
						|
            PieSeriesPoint psp, double maxRadius, string text, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            double innerOffset = GetLableInnerOffset(psp, maxRadius, lstyle);
 | 
						|
 | 
						|
            Rectangle r = GetInscribedRectH(g,
 | 
						|
                psp, psp.CenterAngle % 360, maxRadius, innerOffset, lstyle);
 | 
						|
 | 
						|
            r = GetSliceLabelBounds(g, pieChart, psp, text, r, lstyle);
 | 
						|
 | 
						|
            if (r.Width > 0 && r.Height > 0)
 | 
						|
            {
 | 
						|
                if (lstyle.Background.IsDisplayable == true)
 | 
						|
                {
 | 
						|
                    using (Brush br = lstyle.Background.GetBrush(r))
 | 
						|
                        g.FillRectangle(br, r);
 | 
						|
                }
 | 
						|
 | 
						|
                using (StringFormat sf = new StringFormat())
 | 
						|
                {
 | 
						|
                    lstyle.GetStringFormatFlags(sf, false);
 | 
						|
 | 
						|
                    using (Brush br = new SolidBrush(lstyle.TextColor))
 | 
						|
                        g.DrawString(text, lstyle.Font, br, r, sf);
 | 
						|
                }
 | 
						|
 | 
						|
                if (ChartControl.DesignerHosted == true)
 | 
						|
                {
 | 
						|
                    using (Pen pen = new Pen(Color.Plum))
 | 
						|
                    {
 | 
						|
                        pen.DashStyle = DashStyle.Dash;
 | 
						|
 | 
						|
                        g.DrawRectangle(pen, r);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                return (true);
 | 
						|
            }
 | 
						|
 | 
						|
            return (false);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetInscribedRectH
 | 
						|
 | 
						|
        private Rectangle GetInscribedRectH(Graphics g, PieSeriesPoint psp,
 | 
						|
            double centerAngle, double outerOffset, double innerOffset, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            if (psp.InscribedRectValid == false)
 | 
						|
            {
 | 
						|
                double startAngle = psp.StartAngleEx % 360;
 | 
						|
                double endAngle = startAngle + psp.SweepAngleEx;
 | 
						|
 | 
						|
                if (psp.SweepAngleEx > 180)
 | 
						|
                {
 | 
						|
                    startAngle = centerAngle - 88;
 | 
						|
                    endAngle = centerAngle + 88;
 | 
						|
                }
 | 
						|
 | 
						|
                Rectangle r;
 | 
						|
 | 
						|
                if (centerAngle > 270)
 | 
						|
                {
 | 
						|
                    r = GetInscribedRectQuad4(g, psp,
 | 
						|
                        startAngle, endAngle, centerAngle, outerOffset, innerOffset, lstyle);
 | 
						|
                }
 | 
						|
                else if (centerAngle > 180)
 | 
						|
                {
 | 
						|
                    r = GetInscribedRectQuad3(g, psp,
 | 
						|
                        startAngle, endAngle, centerAngle, outerOffset, innerOffset, lstyle);
 | 
						|
                }
 | 
						|
                else if (centerAngle > 90)
 | 
						|
                {
 | 
						|
                    r = GetInscribedRectQuad2(g, psp,
 | 
						|
                        startAngle, endAngle, centerAngle, outerOffset, innerOffset, lstyle);
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    r = GetInscribedRectQuad1(g, psp,
 | 
						|
                        startAngle, endAngle, centerAngle, outerOffset, innerOffset, lstyle);
 | 
						|
                }
 | 
						|
 | 
						|
                r.Inflate(-2, -2);
 | 
						|
 | 
						|
                psp.InscribedRect = r;
 | 
						|
            }
 | 
						|
 | 
						|
            return (psp.InscribedRect);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetInscribedRectQuad1
 | 
						|
 | 
						|
        private Rectangle GetInscribedRectQuad1(Graphics g,
 | 
						|
            PieSeriesPoint psp, double startAngle, double endAngle,
 | 
						|
            double centerAngle, double outerOffset, double innerOffset, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            Point ptCenter = psp.SliceCenter;
 | 
						|
 | 
						|
            centerAngle = NormalizeCenterAngleQuad1(centerAngle, startAngle, endAngle);
 | 
						|
 | 
						|
            Point ptcInner = psp.GetRayEndPoint(centerAngle, innerOffset);
 | 
						|
            Point ptcOuter = psp.GetRayEndPoint(centerAngle, outerOffset);
 | 
						|
 | 
						|
            Point ptLeftRay = psp.GetRayEndPoint(startAngle, outerOffset);
 | 
						|
            Point ptRightRay = psp.GetRayEndPoint(endAngle, outerOffset);
 | 
						|
 | 
						|
            Point ptPie1, ptPie2;
 | 
						|
            int count = FindCircleIntersect(ptCenter, outerOffset, ptcOuter,
 | 
						|
                new Point(ptcOuter.X + 1, ptcOuter.Y), out ptPie1, out ptPie2, true);
 | 
						|
 | 
						|
            if (count != 2)
 | 
						|
                return (Rectangle.Empty);
 | 
						|
 | 
						|
            Point ptLeftLower = new Point(ptPie1.X, ptcOuter.Y);
 | 
						|
 | 
						|
            Point pt1;
 | 
						|
            if (FindLineIntersect(ptcOuter, ptLeftLower, ptCenter, ptRightRay, out pt1) == true)
 | 
						|
            {
 | 
						|
                if ((uint)(ptcOuter.X - pt1.X) < ptcOuter.X - ptLeftLower.X)
 | 
						|
                    ptLeftLower.X = pt1.X;
 | 
						|
            }
 | 
						|
 | 
						|
            Point ptPie3, ptPie4;
 | 
						|
            count = FindCircleIntersect(ptCenter, outerOffset, ptcOuter,
 | 
						|
                new Point(ptcOuter.X, ptcOuter.Y + 10), out ptPie3, out ptPie4, false);
 | 
						|
 | 
						|
            if (count != 2)
 | 
						|
                return (Rectangle.Empty);
 | 
						|
 | 
						|
            Point ptRightUpper = new Point(ptcOuter.X, ptPie3.Y);
 | 
						|
 | 
						|
            if (FindLineIntersect(ptcOuter, new Point(ptcOuter.X, ptcOuter.Y + 10),
 | 
						|
                ptCenter, ptLeftRay, out pt1) == true)
 | 
						|
            {
 | 
						|
                if ((uint)(ptcOuter.Y - pt1.Y) < (ptcOuter.Y - ptRightUpper.Y))
 | 
						|
                    ptRightUpper.Y = pt1.Y;
 | 
						|
            }
 | 
						|
 | 
						|
            if (centerAngle < 40)
 | 
						|
            {
 | 
						|
                Point ray = psp.GetRayEndPoint(0, innerOffset);
 | 
						|
 | 
						|
                if (Math.Abs(ray.X - ptcOuter.X) < Math.Abs(ptLeftLower.X - ptcOuter.X))
 | 
						|
                    ptLeftLower.X = ray.X;
 | 
						|
            }
 | 
						|
            else if (centerAngle > 50)
 | 
						|
            {
 | 
						|
                Point ray = psp.GetRayEndPoint(90, innerOffset);
 | 
						|
 | 
						|
                if (Math.Abs(ray.Y - ptcOuter.Y) < Math.Abs(ptRightUpper.Y - ptcOuter.Y))
 | 
						|
                    ptRightUpper.Y = ray.Y;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                if (ptLeftLower.X < ptcInner.X)
 | 
						|
                {
 | 
						|
                    if (FindLineIntersect(ptCenter, ptLeftRay, ptcInner,
 | 
						|
                        new Point(ptcInner.X, ptcInner.Y + 10), out pt1) == true)
 | 
						|
                    {
 | 
						|
                        if (Math.Abs(pt1.X - ptcOuter.X) < Math.Abs(ptLeftLower.X - ptcOuter.X))
 | 
						|
                            ptLeftLower.X = pt1.X;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                if (ptRightUpper.Y <= ptcInner.Y)
 | 
						|
                {
 | 
						|
                    if (FindLineIntersect(ptCenter, ptRightRay,
 | 
						|
                        ptcInner, new Point(ptcInner.X + 10, ptcInner.Y), out pt1) == true)
 | 
						|
                    {
 | 
						|
                        if (Math.Abs(pt1.Y - ptcOuter.Y) < Math.Abs(ptRightUpper.Y - ptcOuter.Y))
 | 
						|
                            ptRightUpper.Y = pt1.Y;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            if (psp.SweepAngleEx < 180)
 | 
						|
            {
 | 
						|
                if (FindLineIntersect(ptCenter, ptRightRay, ptRightUpper,
 | 
						|
                    new Point(ptRightUpper.X + 10, ptRightUpper.Y), out pt1) == true)
 | 
						|
                {
 | 
						|
                    if (Math.Abs(pt1.X - ptcOuter.X) < Math.Abs(ptLeftLower.X - ptcOuter.X))
 | 
						|
                        ptLeftLower.X = pt1.X;
 | 
						|
                }
 | 
						|
 | 
						|
                if (FindLineIntersect(ptCenter, ptLeftRay, ptLeftLower,
 | 
						|
                    new Point(ptLeftLower.X, ptLeftLower.Y + 10), out pt1) == true)
 | 
						|
                {
 | 
						|
                    if (Math.Abs(pt1.Y - ptcOuter.Y) < Math.Abs(ptRightUpper.Y - ptcOuter.Y))
 | 
						|
                        ptRightUpper.Y = pt1.Y;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            Rectangle r = new Rectangle();
 | 
						|
 | 
						|
            r.Location = new Point(ptLeftLower.X, ptRightUpper.Y);
 | 
						|
            r.Width = ptcOuter.X - ptLeftLower.X;
 | 
						|
            r.Height = ptcOuter.Y - ptRightUpper.Y;
 | 
						|
 | 
						|
            return (r);
 | 
						|
        }
 | 
						|
 | 
						|
        #region NormalizeCenterAngleQuad1
 | 
						|
 | 
						|
        private double NormalizeCenterAngleQuad1(
 | 
						|
            double centerAngle, double startAngle, double endAngle)
 | 
						|
        {
 | 
						|
            if (centerAngle > 70)
 | 
						|
            {
 | 
						|
                centerAngle -= (centerAngle - 70) / 2;
 | 
						|
 | 
						|
                if (centerAngle - 2 < 0)
 | 
						|
                    centerAngle += 360;
 | 
						|
 | 
						|
                if (centerAngle - 2 <= startAngle)
 | 
						|
                    centerAngle = (startAngle + 2) % 360;
 | 
						|
            }
 | 
						|
            else if (centerAngle < 20)
 | 
						|
            {
 | 
						|
                centerAngle += (20 - centerAngle) / 2;
 | 
						|
 | 
						|
                if (centerAngle + 2 >= endAngle)
 | 
						|
                    centerAngle = endAngle - 2;
 | 
						|
            }
 | 
						|
 | 
						|
            return (centerAngle);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetInscribedRectQuad2
 | 
						|
 | 
						|
        private Rectangle GetInscribedRectQuad2(Graphics g,
 | 
						|
            PieSeriesPoint psp, double startAngle, double endAngle,
 | 
						|
            double centerAngle, double outerOffset, double innerOffset, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            Point ptCenter = psp.SliceCenter;
 | 
						|
 | 
						|
            centerAngle = NormalizeCenterAngleQuad2(centerAngle, startAngle, endAngle);
 | 
						|
 | 
						|
            Point ptcInner = psp.GetRayEndPoint(centerAngle, innerOffset);
 | 
						|
            Point ptcOuter = psp.GetRayEndPoint(centerAngle, outerOffset);
 | 
						|
 | 
						|
            Point ptLeftRay = psp.GetRayEndPoint(startAngle, outerOffset);
 | 
						|
            Point ptRightRay = psp.GetRayEndPoint(endAngle, outerOffset);
 | 
						|
 | 
						|
            Point ptPie1, ptPie2;
 | 
						|
            int count = FindCircleIntersect(ptCenter, outerOffset, ptcOuter,
 | 
						|
                new Point(ptcOuter.X + 1, ptcOuter.Y), out ptPie1, out ptPie2, true);
 | 
						|
 | 
						|
            if (count != 2)
 | 
						|
                return (Rectangle.Empty);
 | 
						|
 | 
						|
            Point ptRightLower = new Point(ptPie2.X, ptcOuter.Y);
 | 
						|
 | 
						|
            Point pt1;
 | 
						|
            if (FindLineIntersect(ptcOuter, ptRightLower, ptCenter, ptLeftRay, out pt1) == true)
 | 
						|
            {
 | 
						|
                if ((uint)(pt1.X - ptcOuter.X) < (ptRightLower.X - ptcOuter.X))
 | 
						|
                    ptRightLower.X = pt1.X;
 | 
						|
            }
 | 
						|
 | 
						|
            Point ptPie3, ptPie4;
 | 
						|
            count = FindCircleIntersect(ptCenter, outerOffset, ptcOuter,
 | 
						|
                new Point(ptcOuter.X, ptcOuter.Y + 10), out ptPie3, out ptPie4, false);
 | 
						|
 | 
						|
            if (count != 2)
 | 
						|
                return (Rectangle.Empty);
 | 
						|
 | 
						|
            Point ptLeftUpper = new Point(ptcOuter.X, ptPie3.Y);
 | 
						|
 | 
						|
            if (FindLineIntersect(ptcOuter, new Point(ptcOuter.X, ptcOuter.Y + 10),
 | 
						|
                ptCenter, ptRightRay, out pt1) == true)
 | 
						|
            {
 | 
						|
                if ((uint)(ptcOuter.Y - pt1.Y) < (ptcOuter.Y - ptLeftUpper.Y))
 | 
						|
                    ptLeftUpper.Y = pt1.Y;
 | 
						|
            }
 | 
						|
 | 
						|
            if (centerAngle < 130)
 | 
						|
            {
 | 
						|
                Point ray = psp.GetRayEndPoint(90, innerOffset);
 | 
						|
 | 
						|
                if (Math.Abs(ray.Y - ptcOuter.Y) < Math.Abs(ptLeftUpper.Y - ptcOuter.Y))
 | 
						|
                    ptLeftUpper.Y = ray.Y;
 | 
						|
            }
 | 
						|
            else if (centerAngle > 140)
 | 
						|
            {
 | 
						|
                Point ray = psp.GetRayEndPoint(180, innerOffset);
 | 
						|
 | 
						|
                if (Math.Abs(ray.X - ptcOuter.X) < Math.Abs(ptRightLower.X - ptcOuter.X))
 | 
						|
                    ptRightLower.X = ray.X;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                if (ptRightLower.X > ptcInner.X)
 | 
						|
                {
 | 
						|
                    if (FindLineIntersect(ptCenter, ptLeftRay, ptcInner,
 | 
						|
                        new Point(ptcInner.X, ptcInner.Y + 10), out pt1) == true)
 | 
						|
                    {
 | 
						|
                        if (Math.Abs(pt1.X - ptcOuter.X) < Math.Abs(ptRightLower.X - ptcOuter.X))
 | 
						|
                            ptRightLower.X = pt1.X;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                if (ptLeftUpper.Y <= ptcInner.Y)
 | 
						|
                {
 | 
						|
                    if (FindLineIntersect(ptCenter, ptRightRay,
 | 
						|
                        ptcInner, new Point(ptcInner.X + 10, ptcInner.Y), out pt1) == true)
 | 
						|
                    {
 | 
						|
                        if (Math.Abs(pt1.Y - ptcOuter.Y) < Math.Abs(ptLeftUpper.Y - ptcOuter.Y))
 | 
						|
                            ptLeftUpper.Y = pt1.Y;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            if (psp.SweepAngleEx < 180)
 | 
						|
            {
 | 
						|
                if (FindLineIntersect(ptCenter, ptRightRay, ptRightLower,
 | 
						|
                    new Point(ptRightLower.X, ptRightLower.Y + 10), out pt1) == true)
 | 
						|
                {
 | 
						|
                    if (Math.Abs(pt1.Y - ptcOuter.Y) < Math.Abs(ptLeftUpper.Y - ptcOuter.Y))
 | 
						|
                        ptLeftUpper.Y = pt1.Y;
 | 
						|
                }
 | 
						|
 | 
						|
                if (FindLineIntersect(ptCenter, ptLeftRay, ptLeftUpper,
 | 
						|
                    new Point(ptLeftUpper.X + 10, ptLeftUpper.Y), out pt1) == true)
 | 
						|
                {
 | 
						|
                    if (Math.Abs(pt1.X - ptcOuter.X) < Math.Abs(ptRightLower.X - ptcOuter.X))
 | 
						|
                        ptRightLower.X = pt1.X;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            Rectangle r = new Rectangle();
 | 
						|
 | 
						|
            r.Location = ptLeftUpper;
 | 
						|
            r.Width = ptRightLower.X - ptcOuter.X;
 | 
						|
            r.Height = ptcOuter.Y - ptLeftUpper.Y;
 | 
						|
 | 
						|
            return (r);
 | 
						|
        }
 | 
						|
 | 
						|
        #region NormalizeCenterAngleQuad2
 | 
						|
 | 
						|
        private double NormalizeCenterAngleQuad2(
 | 
						|
            double centerAngle, double startAngle, double endAngle)
 | 
						|
        {
 | 
						|
            if (centerAngle > 160)
 | 
						|
            {
 | 
						|
                centerAngle -= (centerAngle - 160) / 2;
 | 
						|
 | 
						|
                if (centerAngle - 2 <= startAngle)
 | 
						|
                    centerAngle = startAngle + 2;
 | 
						|
            }
 | 
						|
            else if (centerAngle < 110)
 | 
						|
            {
 | 
						|
                centerAngle += (110 - centerAngle) / 2;
 | 
						|
 | 
						|
                if (centerAngle + 2 >= endAngle)
 | 
						|
                    centerAngle = endAngle - 2;
 | 
						|
            }
 | 
						|
 | 
						|
            return (centerAngle);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetInscribedRectQuad3
 | 
						|
 | 
						|
        private Rectangle GetInscribedRectQuad3(Graphics g,
 | 
						|
            PieSeriesPoint psp, double startAngle, double endAngle,
 | 
						|
            double centerAngle, double outerOffset, double innerOffset, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            Point ptCenter = psp.SliceCenter;
 | 
						|
 | 
						|
            centerAngle = NormalizeCenterAngleQuad3(centerAngle, startAngle, endAngle);
 | 
						|
 | 
						|
            Point ptcInner = psp.GetRayEndPoint(centerAngle, innerOffset);
 | 
						|
            Point ptcOuter = psp.GetRayEndPoint(centerAngle, outerOffset);
 | 
						|
 | 
						|
            Point ptLeftRay = psp.GetRayEndPoint(startAngle, outerOffset);
 | 
						|
            Point ptRightRay = psp.GetRayEndPoint(endAngle, outerOffset);
 | 
						|
 | 
						|
            Point ptPie1, ptPie2;
 | 
						|
 | 
						|
            int count = FindCircleIntersect(ptCenter, outerOffset, ptcOuter,
 | 
						|
                new Point(ptcOuter.X + 1, ptcOuter.Y), out ptPie1, out ptPie2, true);
 | 
						|
 | 
						|
            if (count != 2)
 | 
						|
                return (Rectangle.Empty);
 | 
						|
 | 
						|
            Point ptRightUpper = new Point(ptPie2.X, ptcOuter.Y);
 | 
						|
 | 
						|
            Point pt1;
 | 
						|
            if (FindLineIntersect(ptcOuter, ptRightUpper, ptCenter, ptRightRay, out pt1) == true)
 | 
						|
            {
 | 
						|
                if (pt1.X - ptcOuter.X > 0)
 | 
						|
                {
 | 
						|
                    if ((uint)(pt1.X - ptcOuter.X) < (ptRightUpper.X - ptcOuter.X))
 | 
						|
                        ptRightUpper.X = pt1.X;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            Point ptPie3, ptPie4;
 | 
						|
 | 
						|
            count = FindCircleIntersect(ptCenter, outerOffset, ptcOuter,
 | 
						|
                new Point(ptcOuter.X, ptcOuter.Y + 10), out ptPie3, out ptPie4, false);
 | 
						|
 | 
						|
            if (count != 2)
 | 
						|
                return (Rectangle.Empty);
 | 
						|
 | 
						|
            Point ptLeftLower = new Point(ptcOuter.X, ptPie4.Y);
 | 
						|
 | 
						|
            if (FindLineIntersect(ptcOuter, new Point(ptcOuter.X, ptcOuter.Y + 10),
 | 
						|
                ptCenter, ptLeftRay, out pt1) == true)
 | 
						|
            {
 | 
						|
                if (pt1.Y - ptcOuter.Y > 0)
 | 
						|
                {
 | 
						|
                    if ((uint)(pt1.Y - ptcOuter.Y) < (ptLeftLower.Y - ptcOuter.Y))
 | 
						|
                        ptLeftLower.Y = pt1.Y;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            if (centerAngle < 220)
 | 
						|
            {
 | 
						|
                Point ray = psp.GetRayEndPoint(180, innerOffset);
 | 
						|
 | 
						|
                if (Math.Abs(ray.X - ptcOuter.X) < Math.Abs(ptRightUpper.X - ptcOuter.X))
 | 
						|
                    ptRightUpper.X = ray.X;
 | 
						|
            }
 | 
						|
            else if (centerAngle > 230)
 | 
						|
            {
 | 
						|
                Point ray = psp.GetRayEndPoint(270, innerOffset);
 | 
						|
 | 
						|
                if (Math.Abs(ray.Y - ptcOuter.Y) < Math.Abs(ptLeftLower.Y - ptcOuter.Y))
 | 
						|
                    ptLeftLower.Y = ray.Y;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                if (ptLeftLower.Y >= ptcInner.Y)
 | 
						|
                {
 | 
						|
                    if (FindLineIntersect(ptCenter, ptLeftRay, ptcInner,
 | 
						|
                        new Point(ptcInner.X + 10, ptcInner.Y), out pt1) == true)
 | 
						|
                    {
 | 
						|
                        if (Math.Abs(pt1.Y - ptcOuter.Y) < Math.Abs(ptLeftLower.Y - ptcOuter.Y))
 | 
						|
                            ptLeftLower.Y = pt1.Y;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                if (ptRightUpper.X > ptcInner.X)
 | 
						|
                {
 | 
						|
                    if (FindLineIntersect(ptCenter, ptRightRay,
 | 
						|
                        ptcInner, new Point(ptcInner.X, ptcInner.Y + 10), out pt1) == true)
 | 
						|
                    {
 | 
						|
                        if (Math.Abs(pt1.X - ptcOuter.X) < Math.Abs(ptRightUpper.X - ptcOuter.X))
 | 
						|
                            ptRightUpper.X = pt1.X;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            if (psp.SweepAngleEx < 180)
 | 
						|
            {
 | 
						|
                if (FindLineIntersect(ptCenter, ptRightRay, ptLeftLower,
 | 
						|
                    new Point(ptLeftLower.X + 10, ptLeftLower.Y), out pt1) == true)
 | 
						|
                {
 | 
						|
                    if (Math.Abs(pt1.X - ptcOuter.X) < Math.Abs(ptRightUpper.X - ptcOuter.X))
 | 
						|
                        ptRightUpper.X = pt1.X;
 | 
						|
                }
 | 
						|
 | 
						|
                if (FindLineIntersect(ptCenter, ptLeftRay,
 | 
						|
                    ptRightUpper, new Point(ptRightUpper.X, ptRightUpper.Y + 10), out pt1) == true)
 | 
						|
                {
 | 
						|
                    if (Math.Abs(pt1.Y - ptcOuter.Y) < Math.Abs(ptLeftLower.Y - ptcOuter.Y))
 | 
						|
                        ptLeftLower.Y = pt1.Y;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            Rectangle r = new Rectangle();
 | 
						|
 | 
						|
            r.Location = ptcOuter;
 | 
						|
            r.Width = ptRightUpper.X - ptcOuter.X;
 | 
						|
            r.Height = ptLeftLower.Y - ptcOuter.Y;
 | 
						|
 | 
						|
            return (r);
 | 
						|
        }
 | 
						|
 | 
						|
        #region NormalizeCenterAngleQuad3
 | 
						|
 | 
						|
        private double NormalizeCenterAngleQuad3(
 | 
						|
            double centerAngle, double startAngle, double endAngle)
 | 
						|
        {
 | 
						|
            if (centerAngle > 250)
 | 
						|
            {
 | 
						|
                centerAngle -= (centerAngle - 250) / 2;
 | 
						|
 | 
						|
                if (centerAngle - startAngle < 2)
 | 
						|
                    centerAngle = startAngle + 2;
 | 
						|
            }
 | 
						|
            else if (centerAngle < 200)
 | 
						|
            {
 | 
						|
                centerAngle += (200 - centerAngle) / 2;
 | 
						|
 | 
						|
                if (centerAngle + 2 >= endAngle)
 | 
						|
                    centerAngle = endAngle - 2;
 | 
						|
            }
 | 
						|
 | 
						|
            return (centerAngle);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetInscribedRectQuad4
 | 
						|
 | 
						|
        private Rectangle GetInscribedRectQuad4(Graphics g,
 | 
						|
            PieSeriesPoint psp, double startAngle, double endAngle,
 | 
						|
            double centerAngle, double outerOffset, double innerOffset, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            Point ptCenter = psp.SliceCenter;
 | 
						|
 | 
						|
            centerAngle = NormalizeCenterAngleQuad4(centerAngle, startAngle, endAngle);
 | 
						|
 | 
						|
            Point ptcInner = psp.GetRayEndPoint(centerAngle, innerOffset);
 | 
						|
            Point ptcOuter = psp.GetRayEndPoint(centerAngle, outerOffset);
 | 
						|
 | 
						|
            Point ptLeftRay = psp.GetRayEndPoint(startAngle, outerOffset);
 | 
						|
            Point ptRightRay = psp.GetRayEndPoint(endAngle, outerOffset);
 | 
						|
 | 
						|
            Point ptPie1, ptPie2;
 | 
						|
            int count = FindCircleIntersect(ptCenter, outerOffset, ptcOuter,
 | 
						|
                new Point(ptcOuter.X + 1, ptcOuter.Y), out ptPie1, out ptPie2, true);
 | 
						|
 | 
						|
            if (count != 2)
 | 
						|
                return (Rectangle.Empty);
 | 
						|
 | 
						|
            Point ptLeftUpper = new
 | 
						|
                Point((ptcOuter.Y < ptCenter.Y) ? ptPie1.X : ptPie2.X, ptcOuter.Y);
 | 
						|
 | 
						|
            Point pt1;
 | 
						|
            if (FindLineIntersect(ptcOuter, ptLeftUpper, ptCenter, ptLeftRay, out pt1) == true)
 | 
						|
            {
 | 
						|
                if (ptcOuter.X - pt1.X > 0)
 | 
						|
                {
 | 
						|
                    if ((uint)(ptcOuter.X - pt1.X) < ptcOuter.X - ptLeftUpper.X)
 | 
						|
                        ptLeftUpper.X = pt1.X;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            Point ptPie3, ptPie4;
 | 
						|
            count = FindCircleIntersect(ptCenter, outerOffset, ptcOuter,
 | 
						|
                new Point(ptcOuter.X, ptcOuter.Y + 10), out ptPie3, out ptPie4, false);
 | 
						|
 | 
						|
            if (count != 2)
 | 
						|
                return (Rectangle.Empty);
 | 
						|
 | 
						|
            Point ptRightLower = new Point(ptcOuter.X,
 | 
						|
                (ptcOuter.X < ptCenter.X) ? ptPie3.Y : ptPie4.Y);
 | 
						|
 | 
						|
            if (FindLineIntersect(ptcOuter, new Point(ptcOuter.X, ptcOuter.Y + 10),
 | 
						|
                ptCenter, ptRightRay, out pt1) == true)
 | 
						|
            {
 | 
						|
                if (pt1.Y - ptcOuter.Y > 0)
 | 
						|
                {
 | 
						|
                    if ((uint)(pt1.Y - ptcOuter.Y) < (ptRightLower.Y - ptcOuter.Y))
 | 
						|
                        ptRightLower.Y = pt1.Y;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            if (centerAngle < 310)
 | 
						|
            {
 | 
						|
                Point ray = psp.GetRayEndPoint(270, innerOffset);
 | 
						|
 | 
						|
                if (Math.Abs(ray.Y - ptcOuter.Y) < Math.Abs(ptRightLower.Y - ptcOuter.Y))
 | 
						|
                    ptRightLower.Y = ray.Y;
 | 
						|
            }
 | 
						|
            else if (centerAngle > 320)
 | 
						|
            {
 | 
						|
                Point ray = psp.GetRayEndPoint(0, innerOffset);
 | 
						|
 | 
						|
                if (Math.Abs(ray.X - ptcOuter.X) < Math.Abs(ptLeftUpper.X - ptcOuter.X))
 | 
						|
                    ptLeftUpper.X = ray.X;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                if (ptLeftUpper.X <= ptcInner.X)
 | 
						|
                {
 | 
						|
                    if (FindLineIntersect(ptCenter, ptLeftRay, ptcInner,
 | 
						|
                        new Point(ptcInner.X, ptcInner.Y + 10), out pt1) == true)
 | 
						|
                    {
 | 
						|
                        if (Math.Abs(pt1.X - ptcOuter.X) < Math.Abs(ptLeftUpper.X - ptcOuter.X))
 | 
						|
                            ptLeftUpper.X = pt1.X;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                if (ptRightLower.Y >= ptcInner.Y)
 | 
						|
                {
 | 
						|
                    if (FindLineIntersect(ptCenter, ptRightRay,
 | 
						|
                        ptcInner, new Point(ptcInner.X + 10, ptcInner.Y), out pt1) == true)
 | 
						|
                    {
 | 
						|
                        if (Math.Abs(pt1.Y - ptcOuter.Y) < Math.Abs(ptRightLower.Y - ptcOuter.Y))
 | 
						|
                            ptRightLower.Y = pt1.Y;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            if (psp.SweepAngleEx < 180)
 | 
						|
            {
 | 
						|
                if (FindLineIntersect(ptCenter, ptRightRay, ptLeftUpper,
 | 
						|
                    new Point(ptLeftUpper.X, ptLeftUpper.Y + 10), out pt1) == true)
 | 
						|
                {
 | 
						|
                    if (Math.Abs(pt1.Y - ptcOuter.Y) < Math.Abs(ptRightLower.Y - ptcOuter.Y))
 | 
						|
                        ptRightLower.Y = pt1.Y;
 | 
						|
                }
 | 
						|
 | 
						|
                if (FindLineIntersect(ptCenter, ptLeftRay,
 | 
						|
                    ptRightLower, new Point(ptRightLower.X + 10, ptRightLower.Y), out pt1) == true)
 | 
						|
                {
 | 
						|
                    if (Math.Abs(pt1.X - ptcOuter.X) < Math.Abs(ptLeftUpper.X - ptcOuter.X))
 | 
						|
                        ptLeftUpper.X = pt1.X;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            Rectangle r = new Rectangle();
 | 
						|
 | 
						|
            r.Location = ptLeftUpper;
 | 
						|
            r.Width = ptRightLower.X - ptLeftUpper.X;
 | 
						|
            r.Height = ptRightLower.Y - ptLeftUpper.Y;
 | 
						|
 | 
						|
            return (r);
 | 
						|
        }
 | 
						|
 | 
						|
        #region NormalizeCenterAngleQuad4
 | 
						|
 | 
						|
        private double NormalizeCenterAngleQuad4(
 | 
						|
            double centerAngle, double startAngle, double endAngle)
 | 
						|
        {
 | 
						|
            if (centerAngle > 340)
 | 
						|
            {
 | 
						|
                centerAngle -= (centerAngle - 340) / 2;
 | 
						|
 | 
						|
                if (centerAngle - 2 <= startAngle)
 | 
						|
                    centerAngle = startAngle + 2;
 | 
						|
            }
 | 
						|
            else if (centerAngle < 290)
 | 
						|
            {
 | 
						|
                centerAngle += (290 - centerAngle) / 2;
 | 
						|
 | 
						|
                if (centerAngle + 2 >= endAngle)
 | 
						|
                    centerAngle = endAngle - 2;
 | 
						|
            }
 | 
						|
 | 
						|
            return (centerAngle);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region FindLineIntersect
 | 
						|
 | 
						|
        private bool FindLineIntersect(
 | 
						|
            Point ps1, Point pe1, Point ps2, Point pe2, out Point ptOut)
 | 
						|
        {
 | 
						|
            float A1 = pe1.Y - ps1.Y;
 | 
						|
            float B1 = ps1.X - pe1.X;
 | 
						|
            float C1 = A1 * ps1.X + B1 * ps1.Y;
 | 
						|
 | 
						|
            float A2 = pe2.Y - ps2.Y;
 | 
						|
            float B2 = ps2.X - pe2.X;
 | 
						|
            float C2 = A2 * ps2.X + B2 * ps2.Y;
 | 
						|
 | 
						|
            float delta = A1 * B2 - A2 * B1;
 | 
						|
 | 
						|
            if (delta == 0)
 | 
						|
            {
 | 
						|
                ptOut = Point.Empty;
 | 
						|
 | 
						|
                return (false);
 | 
						|
            }
 | 
						|
 | 
						|
            ptOut = new Point(
 | 
						|
                (int)((B2 * C1 - B1 * C2) / delta),
 | 
						|
                (int)((A1 * C2 - A2 * C1) / delta));
 | 
						|
 | 
						|
            return (true);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region FindCircleIntersect
 | 
						|
 | 
						|
        private int FindCircleIntersect(Point ptc, double radius,
 | 
						|
            Point pt1, Point pt2, out Point ptOut1, out Point ptOut2, bool normx)
 | 
						|
        {
 | 
						|
            int dx = pt2.X - pt1.X;
 | 
						|
            int dy = pt2.Y - pt1.Y;
 | 
						|
 | 
						|
            int a = dx * dx + dy * dy;
 | 
						|
            int b = 2 * (dx * (pt1.X - ptc.X) + dy * (pt1.Y - ptc.Y));
 | 
						|
 | 
						|
            double c = (pt1.X - ptc.X) * (pt1.X - ptc.X) +
 | 
						|
                (pt1.Y - ptc.Y) * (pt1.Y - ptc.Y) - radius * radius;
 | 
						|
 | 
						|
            double det = b * b - 4 * a * c;
 | 
						|
 | 
						|
            if ((a <= 0.0000001) || (det < 0))
 | 
						|
            {
 | 
						|
                ptOut1 = Point.Empty;
 | 
						|
                ptOut2 = Point.Empty;
 | 
						|
 | 
						|
                return (0);
 | 
						|
            }
 | 
						|
            else if (det == 0)
 | 
						|
            {
 | 
						|
                double t1 = -b / (2 * a);
 | 
						|
 | 
						|
                ptOut1 = new Point((int)(pt1.X + t1 * dx), (int)(pt1.Y + t1 * dy));
 | 
						|
                ptOut2 = Point.Empty;
 | 
						|
 | 
						|
                return (1);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                double t2 = (float)((-b + Math.Sqrt(det)) / (2 * a));
 | 
						|
                double t3 = (float)((-b - Math.Sqrt(det)) / (2 * a));
 | 
						|
 | 
						|
                ptOut1 = new Point((int)(pt1.X + t2 * dx), (int)(pt1.Y + t2 * dy));
 | 
						|
                ptOut2 = new Point((int)(pt1.X + t3 * dx), (int)(pt1.Y + t3 * dy));
 | 
						|
 | 
						|
                if ((normx == true && ptOut1.X > ptOut2.X) ||
 | 
						|
                    (normx == false && ptOut1.Y > ptOut2.Y))
 | 
						|
                {
 | 
						|
                    Point ptTemp = ptOut1;
 | 
						|
 | 
						|
                    ptOut1 = ptOut2;
 | 
						|
                    ptOut2 = ptTemp;
 | 
						|
                }
 | 
						|
 | 
						|
                return (2);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetLableInnerOffset
 | 
						|
 | 
						|
        internal double GetLableInnerOffset
 | 
						|
            (PieSeriesPoint psp, double maxRadius, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            double offset;
 | 
						|
 | 
						|
            if (Math.Abs(lstyle.InnerRadiusOffset) >= 1)
 | 
						|
                offset = lstyle.InnerRadiusOffset;
 | 
						|
            else
 | 
						|
                offset = (maxRadius - psp.InnerRadius) * lstyle.InnerRadiusOffset;
 | 
						|
 | 
						|
            offset += psp.InnerRadius;
 | 
						|
 | 
						|
            if (lstyle.MaxLineCount >= 0)
 | 
						|
            {
 | 
						|
                double outerOffset = psp.InnerRadius;
 | 
						|
                
 | 
						|
                if (lstyle.OuterRadiusOffset > -1 && lstyle.OuterRadiusOffset < 1)
 | 
						|
                    outerOffset += (lstyle.OuterRadiusOffset * maxRadius);
 | 
						|
                else
 | 
						|
                    outerOffset += lstyle.OuterRadiusOffset;
 | 
						|
 | 
						|
                double fh = lstyle.Font.GetHeight() * lstyle.MaxLineCount;
 | 
						|
 | 
						|
                fh = outerOffset - fh;
 | 
						|
 | 
						|
                if (fh > offset)
 | 
						|
                    offset = fh;
 | 
						|
            }
 | 
						|
 | 
						|
            return (offset);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetLableOuterOffset
 | 
						|
 | 
						|
        internal double GetLableOuterOffset(
 | 
						|
            PieSeriesPoint psp, double maxRadius, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            double offset;
 | 
						|
 | 
						|
            if (Math.Abs(lstyle.OuterRadiusOffset) >= 1)
 | 
						|
                offset = lstyle.OuterRadiusOffset;
 | 
						|
            else
 | 
						|
                offset = (maxRadius * lstyle.OuterRadiusOffset);
 | 
						|
 | 
						|
            return (maxRadius + offset);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetSliceLabel
 | 
						|
 | 
						|
        internal string GetSliceLabel(
 | 
						|
            PieChart pieChart, PieSeriesPoint psp, bool inner, string label)
 | 
						|
        {
 | 
						|
            if (string.IsNullOrEmpty(label) == false)
 | 
						|
            {
 | 
						|
                string text = (string)label.Clone();
 | 
						|
 | 
						|
                if (ChartControl.DoGetSliceLabelEvent(pieChart, this, psp, inner, ref text) == false)
 | 
						|
                    text = psp.GetLabelText(text);
 | 
						|
 | 
						|
                return (text);
 | 
						|
            }
 | 
						|
 | 
						|
            return (null);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetSliceLabelBounds
 | 
						|
 | 
						|
        private Rectangle GetSliceLabelBounds(Graphics g, PieChart pieChart,
 | 
						|
            PieSeriesPoint psp, string text, Rectangle r, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            if (r.Width > 0 && r.Height > 0)
 | 
						|
            {
 | 
						|
                SizeF sz = g.MeasureString(text, lstyle.Font, r.Width);
 | 
						|
                Size size = sz.ToSize();
 | 
						|
 | 
						|
                psp.InnerLabelClipped = (size.Width > r.Width || size.Height > r.Height);
 | 
						|
 | 
						|
                if (psp.InnerLabelClipped == true)
 | 
						|
                {
 | 
						|
                    SliceLabelCropMode cropMode = psp.SliceLabelCropModeEx;
 | 
						|
 | 
						|
                    if (cropMode == SliceLabelCropMode.Hide)
 | 
						|
                        return (Rectangle.Empty);
 | 
						|
 | 
						|
                    else if (cropMode == SliceLabelCropMode.Clip)
 | 
						|
                    {
 | 
						|
                        int height = GetTruncatedHeight(r.Height, lstyle);
 | 
						|
 | 
						|
                        if (height > 0)
 | 
						|
                            r.Height = height;
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        r.Height = size.Height;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (r);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetTruncatedHeight
 | 
						|
 | 
						|
        private int GetTruncatedHeight(int height, SliceInnerLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            int n = (int)(height / lstyle.Font.Height);
 | 
						|
 | 
						|
            if (lstyle.MaxLineCount > 0)
 | 
						|
            {
 | 
						|
                if (n > lstyle.MaxLineCount)
 | 
						|
                    n = lstyle.MaxLineCount;
 | 
						|
            }
 | 
						|
 | 
						|
            return (lstyle.Font.Height * n);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region IsHighLightedPsp
 | 
						|
 | 
						|
        internal bool IsHighLightedPsp(PieChart pieChart, PieSeriesPoint psp)
 | 
						|
        {
 | 
						|
            if (pieChart.Legend.TrackingMode == LegendTrackingMode.ChartAndLegend)
 | 
						|
            {
 | 
						|
                if (LegendItem != null && LegendItem.IsLegendHitItem == true)
 | 
						|
                    return (true);
 | 
						|
 | 
						|
                if (psp.LegendItem != null && psp.LegendItem.IsLegendHitItem == true)
 | 
						|
                    return (true);
 | 
						|
            }
 | 
						|
 | 
						|
            PieSeriesPoint hitPsp = pieChart.HitPsp;
 | 
						|
 | 
						|
            if (hitPsp != null)
 | 
						|
            {
 | 
						|
                PieSelectionMode psm = GetPieSelectionMode(pieChart);
 | 
						|
 | 
						|
                switch (psm)
 | 
						|
                {
 | 
						|
                    case PieSelectionMode.Pie:
 | 
						|
                        return (true);
 | 
						|
 | 
						|
                    case PieSelectionMode.Ring:
 | 
						|
                        return (psp.PieRing == hitPsp.PieRing);
 | 
						|
 | 
						|
                    case PieSelectionMode.Series:
 | 
						|
                        return (psp.ChartSeries == hitPsp.ChartSeries);
 | 
						|
 | 
						|
                    case PieSelectionMode.Slice:
 | 
						|
                        if (ShowAllRingsEx(pieChart) == true)
 | 
						|
                            return (psp.RootPsp == hitPsp.RootPsp);
 | 
						|
                        else
 | 
						|
                            return (psp == hitPsp);
 | 
						|
 | 
						|
                    case PieSelectionMode.Point:
 | 
						|
                        return (psp == hitPsp);
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (false);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Render
 | 
						|
 | 
						|
        internal override void Render(ChartRenderInfo renderInfo)
 | 
						|
        {
 | 
						|
            if (Displayed == true)
 | 
						|
            {
 | 
						|
                Rectangle bounds = BoundsRelative;
 | 
						|
 | 
						|
                if (renderInfo.ClipRectangle.IntersectsWith(bounds))
 | 
						|
                    RenderOverride(renderInfo);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region UpdatePalette
 | 
						|
 | 
						|
        internal bool UpdatePalette(PieChart pieChart)
 | 
						|
        {
 | 
						|
            if (PaletteGroup == PaletteGroup.NotSet)
 | 
						|
                return (false);
 | 
						|
 | 
						|
            Color[] palette = (PaletteGroup == PaletteGroup.Custom)
 | 
						|
                ? (CustomPalette.Length > 0 ? CustomPalette : pieChart.CustomPalette) 
 | 
						|
                : BaseChart.PaletteGroups[(int)PaletteGroup];
 | 
						|
 | 
						|
            if (palette == null || palette.Length == 0)
 | 
						|
                palette = BaseChart.PaletteColor1;
 | 
						|
 | 
						|
            int colorIndex = 0;
 | 
						|
 | 
						|
            DefaultPaletteColor =
 | 
						|
                pieChart.GetPaletteColor(colorIndex++, palette, ReversePaletteColors);
 | 
						|
 | 
						|
            if (PieRings != null)
 | 
						|
            {
 | 
						|
                foreach (PieRing pieRing in PieRings)
 | 
						|
                {
 | 
						|
                    foreach (PieSeriesPoint psp in pieRing.Psps)
 | 
						|
                    {
 | 
						|
                        psp.DefaultPaletteColor = 
 | 
						|
                            pieChart.GetPaletteColor(colorIndex++, palette, ReversePaletteColors);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (true);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region AddSeriesPoint
 | 
						|
 | 
						|
        internal override void AddSeriesPoint(object valueX, object[] valuesY, object dataItem)
 | 
						|
        {
 | 
						|
            PieSeriesPoint sp = new PieSeriesPoint(valueX, valuesY);
 | 
						|
 | 
						|
            sp.DataItem = dataItem;
 | 
						|
 | 
						|
            SeriesPoints.Add(sp);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region ClearSeriesPoints
 | 
						|
 | 
						|
        internal override void ClearSeriesPoints()
 | 
						|
        {
 | 
						|
            SeriesPoints.Clear();
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetActiveSeriesPointCollection
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets the current 'active' SeriesPointCollection (useful when
 | 
						|
        /// 'ShowInnerRings' is set to false).
 | 
						|
        /// </summary>
 | 
						|
        /// <returns></returns>
 | 
						|
        public PieSeriesPointCollection GetActiveSeriesPointCollection()
 | 
						|
        {
 | 
						|
            PieChart pieChart = Parent as PieChart;
 | 
						|
 | 
						|
            if (pieChart != null)
 | 
						|
            {
 | 
						|
                return ((ShowAllRingsEx(pieChart) == true)
 | 
						|
                    ? SeriesPoints : (ActiveSeriesPointCollection ?? SeriesPoints));
 | 
						|
            }
 | 
						|
 | 
						|
            return (null);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region SetActiveSeriesPointCollection
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Sets the current 'active' SeriesPointCollection (useful when
 | 
						|
        /// 'ShowInnerRings' is set to false).
 | 
						|
        /// </summary>
 | 
						|
        /// <param name="spc"></param>
 | 
						|
        public void SetActiveSeriesPointCollection(PieSeriesPointCollection spc)
 | 
						|
        {
 | 
						|
            if (spc == null || ValidSeriesPointSet(SeriesPoints, spc) == true)
 | 
						|
                ActiveSeriesPointCollection = spc;
 | 
						|
            else
 | 
						|
                throw new Exception("Not a valid PieSeriesPointSet for the series.");
 | 
						|
 | 
						|
            InvalidateLayout();
 | 
						|
        }
 | 
						|
 | 
						|
        #region ValidSeriesPointSet
 | 
						|
 | 
						|
        private bool ValidSeriesPointSet(PieSeriesPointCollection spc, PieSeriesPointCollection aspc)
 | 
						|
        {
 | 
						|
            if (aspc == spc)
 | 
						|
                return (true);
 | 
						|
 | 
						|
            if (spc.PieSlices != null)
 | 
						|
            {
 | 
						|
                foreach (PieSeriesPoint psp in spc.PieSlices)
 | 
						|
                {
 | 
						|
                    if (psp.SeriesPoints == aspc)
 | 
						|
                        return (true);
 | 
						|
 | 
						|
                    if (ValidSeriesPointSet(psp.SeriesPoints, aspc) == true)
 | 
						|
                        return (true);
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (false);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetPieSeriesPointCollection
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets the SeriesPointCollection containing the given PieSeriesPoint
 | 
						|
        /// </summary>
 | 
						|
        /// <param name="psp"></param>
 | 
						|
        /// <returns></returns>
 | 
						|
        public PieSeriesPointCollection GetPieSeriesPointCollection(PieSeriesPoint psp)
 | 
						|
        {
 | 
						|
            return (psp.Parent as PieSeriesPointCollection);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetPieLabels
 | 
						|
 | 
						|
        internal List<PieLabel> GetPieLabels(Graphics g, PieChart pieChart)
 | 
						|
        {
 | 
						|
            List<PieLabel> pieLabels = new List<PieLabel>();
 | 
						|
 | 
						|
            if (ShowAllRingsEx(pieChart) == true)
 | 
						|
            {
 | 
						|
                PieRing pieRing = GetOuterRing(pieChart);
 | 
						|
 | 
						|
                if (pieRing != null)
 | 
						|
                {
 | 
						|
                    foreach (PieSeriesPoint psp in pieRing.Psps)
 | 
						|
                    {
 | 
						|
                        SetPieLabel(g, pieChart, psp);
 | 
						|
 | 
						|
                        if (psp.PieLabel != null)
 | 
						|
                            pieLabels.Add(psp.PieLabel);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                PieSeriesPointCollection spc = GetActiveSeriesPointCollection();
 | 
						|
 | 
						|
                if (spc != null)
 | 
						|
                {
 | 
						|
                    foreach (PieSeriesPoint psp in spc)
 | 
						|
                    {
 | 
						|
                        SetPieLabel(g, pieChart, psp);
 | 
						|
 | 
						|
                        if (psp.PieLabel != null)
 | 
						|
                            pieLabels.Add(psp.PieLabel);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (pieLabels);
 | 
						|
        }
 | 
						|
 | 
						|
        #region SetPieLabel
 | 
						|
 | 
						|
        private void SetPieLabel(
 | 
						|
            Graphics g, PieChart pieChart, PieSeriesPoint psp)
 | 
						|
        {
 | 
						|
            psp.PieLabel = null;
 | 
						|
 | 
						|
            if (psp.IsDisplayed == true && psp.SweepAngleEx != 0 &&
 | 
						|
                psp.IsInOtherEx == false && psp.IsEmpty == false)
 | 
						|
            {
 | 
						|
                ChartSliceVisualStyle sstyle = psp.GetEffectiveSliceStyle(pieChart, this);
 | 
						|
 | 
						|
                if (IsOuterSliceLabelVisible(pieChart, psp) == true)
 | 
						|
                {
 | 
						|
                    SliceOuterLabelVisualStyle lstyle = sstyle.SliceOuterLabelStyle;
 | 
						|
                    SliceLabelDisplayMode displayMode = psp.SliceLabelDisplayModeEx;
 | 
						|
 | 
						|
                    if (displayMode == SliceLabelDisplayMode.Outer ||
 | 
						|
                        displayMode == SliceLabelDisplayMode.InnerAndOuter ||
 | 
						|
                        displayMode == SliceLabelDisplayMode.NotSet)
 | 
						|
                    {
 | 
						|
                        string outerlabel = psp.OuterSliceLabelEx;
 | 
						|
 | 
						|
                        if (string.IsNullOrEmpty(outerlabel) == false)
 | 
						|
                            SetPieLabelEx(g, pieChart, psp, outerlabel, lstyle);
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        if (psp.InnerLabelDisplayed == false)
 | 
						|
                        {
 | 
						|
                            string outerlabel = psp.OuterSliceLabelEx;
 | 
						|
 | 
						|
                            if (string.IsNullOrEmpty(outerlabel) == false)
 | 
						|
                            {
 | 
						|
                                SetPieLabelEx(g, pieChart, psp, outerlabel, lstyle);
 | 
						|
                            }
 | 
						|
                            else
 | 
						|
                            {
 | 
						|
                                string innerlabel = psp.InnerSliceLabelEx;
 | 
						|
 | 
						|
                                if (string.IsNullOrEmpty(innerlabel) == false)
 | 
						|
                                    SetPieLabelEx(g, pieChart, psp, innerlabel, lstyle);
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetOuterRing
 | 
						|
 | 
						|
        private PieRing GetOuterRing(PieChart pieChart)
 | 
						|
        {
 | 
						|
            if (ShowAllRingsEx(pieChart) == false)
 | 
						|
            {
 | 
						|
                PieSeriesPointCollection spc = (ActiveSeriesPointCollection ?? SeriesPoints);
 | 
						|
 | 
						|
                return (spc.PieRing);
 | 
						|
            }
 | 
						|
 | 
						|
            if (PieRings.Count > 0)
 | 
						|
            {
 | 
						|
                foreach (PieRing pieRing in PieRings)
 | 
						|
                {
 | 
						|
                    if (pieRing.IsOuterRing == true)
 | 
						|
                        return (pieRing);
 | 
						|
                }
 | 
						|
 | 
						|
                return (PieRings[0]);
 | 
						|
            }
 | 
						|
 | 
						|
            return (null);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region IsOuterSliceLabelVisible
 | 
						|
 | 
						|
        private bool IsOuterSliceLabelVisible(PieChart pieChart, PieSeriesPoint psp)
 | 
						|
        {
 | 
						|
            if (psp.SliceLabelVisibilityEx == SliceLabelVisibility.Never)
 | 
						|
                return (false);
 | 
						|
 | 
						|
            switch (psp.SliceLabelDisplayModeEx)
 | 
						|
            {
 | 
						|
                case SliceLabelDisplayMode.Outer:
 | 
						|
                case SliceLabelDisplayMode.InnerAndOuter:
 | 
						|
                case SliceLabelDisplayMode.InnerXorOuter:
 | 
						|
                    return (true);
 | 
						|
            }
 | 
						|
 | 
						|
            return (false);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region SetPieLabelEx
 | 
						|
 | 
						|
        private void SetPieLabelEx(Graphics g, PieChart pieChart,
 | 
						|
            PieSeriesPoint psp, string text, SliceOuterLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            string s = GetSliceLabel(pieChart, psp, false, text);
 | 
						|
 | 
						|
            if (String.IsNullOrEmpty(s) == false)
 | 
						|
            {
 | 
						|
                PieLabel pl = new PieLabel(psp, s);
 | 
						|
 | 
						|
                pl.LabelSize = MeasurePieLabel(g, pieChart, psp, pl, 0, lstyle);
 | 
						|
 | 
						|
                psp.PieLabel = pl;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region MeasurePieLabel
 | 
						|
 | 
						|
        internal Size MeasurePieLabel(Graphics g, PieChart pieChart,
 | 
						|
            PieSeriesPoint psp, PieLabel pl, int cwidth, SliceOuterLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            float fheight = lstyle.Font.GetHeight();
 | 
						|
 | 
						|
            int maxWidth = GetMaxPieTextWidth(g, pieChart, lstyle);
 | 
						|
            int maxHeight = GetMaxPieTextHeight(g, pieChart, fheight, lstyle);
 | 
						|
 | 
						|
            int minWidth = GetMinPieTextWidth(g, pieChart, lstyle);
 | 
						|
            int minHeight = GetMinPieTextHeight(g, pieChart, fheight, lstyle);
 | 
						|
 | 
						|
            using (StringFormat sf = new StringFormat())
 | 
						|
            {
 | 
						|
                lstyle.GetStringFormatFlags(sf, false);
 | 
						|
 | 
						|
                if (cwidth != 0)
 | 
						|
                    cwidth -= Dpi.Width(lstyle.Padding.Horizontal);
 | 
						|
 | 
						|
                Size size = g.MeasureString(pl.Label,
 | 
						|
                    lstyle.Font, cwidth != 0 ? cwidth : maxWidth, sf).ToSize();
 | 
						|
 | 
						|
                size.Width += Dpi.Width1;
 | 
						|
 | 
						|
                size = AdjustForPadding(pieChart, psp, size);
 | 
						|
 | 
						|
                size.Height = MathHelper.Clamp(size.Height, minHeight, maxHeight);
 | 
						|
                size.Width = MathHelper.Clamp(size.Width, minWidth, maxWidth);
 | 
						|
 | 
						|
                if (lstyle.MaxLineCount > 1)
 | 
						|
                {
 | 
						|
                    int lineHeight = (int)(Math.Ceiling(fheight)) * lstyle.MaxLineCount;
 | 
						|
 | 
						|
                    if (size.Height > lineHeight)
 | 
						|
                        size.Height = lineHeight;
 | 
						|
                }
 | 
						|
 | 
						|
                return (size);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetMaxPieTextWidth
 | 
						|
 | 
						|
        private int GetMaxPieTextWidth(
 | 
						|
            Graphics g, PieChart pieChart, SliceOuterLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            double maxWidth = lstyle.MaxLabelWidth;
 | 
						|
 | 
						|
            if (double.IsNaN(maxWidth) == false)
 | 
						|
            {
 | 
						|
                if (Math.Abs(maxWidth) >= 1)
 | 
						|
                    return ((int)maxWidth);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                maxWidth = .5;
 | 
						|
            }
 | 
						|
 | 
						|
            return ((int)(pieChart.ContentBoundsEx.Width * maxWidth));
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetMaxPieTextHeight
 | 
						|
 | 
						|
        private int GetMaxPieTextHeight(
 | 
						|
            Graphics g, PieChart pieChart, float fheight, SliceOuterLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            double maxHeight = lstyle.MaxLabelHeight;
 | 
						|
 | 
						|
            if (double.IsNaN(maxHeight) == false)
 | 
						|
            {
 | 
						|
                if (Math.Abs(maxHeight) >= 1)
 | 
						|
                    return ((int)maxHeight);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                maxHeight = .5;
 | 
						|
            }
 | 
						|
 | 
						|
            double height = pieChart.ContentBoundsEx.Height * maxHeight;
 | 
						|
 | 
						|
            int n = (int)(height / fheight);
 | 
						|
 | 
						|
            return ((int)(fheight * n));
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetMinPieTextWidth
 | 
						|
 | 
						|
        private int GetMinPieTextWidth(
 | 
						|
            Graphics g, PieChart pieChart, SliceOuterLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            double minWidth = lstyle.MinLabelWidth;
 | 
						|
 | 
						|
            if (double.IsNaN(minWidth) == false)
 | 
						|
            {
 | 
						|
                if (Math.Abs(minWidth) >= 1)
 | 
						|
                    return ((int)minWidth);
 | 
						|
 | 
						|
                return ((int)(pieChart.ContentBoundsEx.Width * minWidth));
 | 
						|
            }
 | 
						|
 | 
						|
            return (0);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetMinPieTextHeight
 | 
						|
 | 
						|
        private int GetMinPieTextHeight(
 | 
						|
            Graphics g, PieChart pieChart, float fheight, SliceOuterLabelVisualStyle lstyle)
 | 
						|
        {
 | 
						|
            double minHeight = lstyle.MinLabelHeight;
 | 
						|
 | 
						|
            if (double.IsNaN(minHeight) == false)
 | 
						|
            {
 | 
						|
                if (Math.Abs(minHeight) >= 1)
 | 
						|
                    return ((int)minHeight);
 | 
						|
 | 
						|
                double height = pieChart.ContentBoundsEx.Height * minHeight;
 | 
						|
 | 
						|
                int n = (int)(height / fheight);
 | 
						|
 | 
						|
                return ((int)(fheight * n));
 | 
						|
            }
 | 
						|
 | 
						|
            return ((int)fheight);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region AdjustForPadding
 | 
						|
 | 
						|
        private Size AdjustForPadding(PieChart pieChart, PieSeriesPoint psp, Size size)
 | 
						|
        {
 | 
						|
            SliceOuterLabelVisualStyle sstyle =
 | 
						|
                psp.GetEffectiveSliceStyle(pieChart, psp.ChartSeries).SliceOuterLabelStyle;
 | 
						|
 | 
						|
            size.Width += Dpi.Width(sstyle.Padding.Horizontal);
 | 
						|
            size.Height += Dpi.Width(sstyle.Padding.Vertical);
 | 
						|
 | 
						|
            return (size);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetOtherPieSeriesPoint
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets the 'Other' PieSeriesPoint
 | 
						|
        /// </summary>
 | 
						|
        /// <returns></returns>
 | 
						|
        public PieSeriesPoint GetOtherPieSeriesPoint()
 | 
						|
        {
 | 
						|
            return (SeriesPoints.OtherSlicePsp);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Mouse support
 | 
						|
 | 
						|
        #region ProcessMouseEnter
 | 
						|
 | 
						|
        internal void ProcessMouseEnter(EventArgs e, PieChart pieChart)
 | 
						|
        {
 | 
						|
            SetToolTip(pieChart.ShowToolTips ? GetToolTipText(pieChart) : string.Empty);
 | 
						|
        }
 | 
						|
 | 
						|
        #region SetToolTip
 | 
						|
 | 
						|
        private static string _toolTipText;
 | 
						|
 | 
						|
        private void SetToolTip(string toolTipText)
 | 
						|
        {
 | 
						|
            ChartControl chartControl = ChartControl;
 | 
						|
 | 
						|
            if (chartControl != null)
 | 
						|
            {
 | 
						|
                if (chartControl.ToolTipText != _toolTipText)
 | 
						|
                    chartControl.ToolTip.Hide(chartControl);
 | 
						|
 | 
						|
                chartControl.ToolTipText = toolTipText;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetToolTipText
 | 
						|
 | 
						|
        private string GetToolTipText(PieChart pieChart)
 | 
						|
        {
 | 
						|
            PieSeriesPoint psp = pieChart.HitPsp;
 | 
						|
 | 
						|
            if (psp == null || "".Equals(psp.ToolTipText))
 | 
						|
                return (string.Empty);
 | 
						|
 | 
						|
            if (_toolTipText == null)
 | 
						|
            {
 | 
						|
                ChartControl chartControl = ChartControl;
 | 
						|
 | 
						|
                string s = "";
 | 
						|
 | 
						|
                if (chartControl.DoGetToolTipEvent(pieChart, this, psp, ref s) == false)
 | 
						|
                    s = psp.ToolTipTextEx;
 | 
						|
 | 
						|
                _toolTipText = psp.FormatItemText(s);
 | 
						|
            }
 | 
						|
 | 
						|
            return (_toolTipText);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region ProcessMouseLeave
 | 
						|
 | 
						|
        internal void ProcessMouseLeave(EventArgs e, PieChart pieChart)
 | 
						|
        {
 | 
						|
            ChartControl chartControl = ChartControl;
 | 
						|
 | 
						|
            if (chartControl != null)
 | 
						|
                chartControl.ToolTipText = "";
 | 
						|
 | 
						|
            _toolTipText = null;
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region ProcessMouseDown
 | 
						|
 | 
						|
        internal bool ProcessMouseDown(
 | 
						|
            MouseEventArgs e, PieChart pieChart, PieSeriesPoint psp)
 | 
						|
        {
 | 
						|
            pieChart.IsDragging = false;
 | 
						|
            pieChart.PspDragType = PspDragType.None;
 | 
						|
 | 
						|
            if ((Control.MouseButtons & MouseButtons.Left) == MouseButtons.Left)
 | 
						|
            {
 | 
						|
                _MouseDownPsp = psp;
 | 
						|
 | 
						|
                Point cpt = pieChart.GetLocalAdjustedPoint(pieChart.CenterPoint);
 | 
						|
 | 
						|
                Point rpt = e.Location;
 | 
						|
                _MouseDownRadius = MathHelper.GetPointRadius(ref rpt, cpt);
 | 
						|
 | 
						|
                if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
 | 
						|
                {
 | 
						|
                    _MouseDownOffset = (int)pieChart.ExplodedOffsetEx;
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    PieSeriesPoint rootPsp = (ShowAllRingsEx(pieChart) == true)
 | 
						|
                        ? psp.RootPsp : psp;
 | 
						|
 | 
						|
                    _MouseDownOffset = (double.IsNaN(rootPsp.DetachedOffset) == false)
 | 
						|
                        ? (int)rootPsp.DetachedOffset : 0;
 | 
						|
                }
 | 
						|
 | 
						|
                MouseClickSliceAction mca = GetMouseClickSliceAction(pieChart);
 | 
						|
 | 
						|
                switch (mca)
 | 
						|
                {
 | 
						|
                    case MouseClickSliceAction.Explode:
 | 
						|
                    case MouseClickSliceAction.Detach:
 | 
						|
                        InitPspDrag(pieChart, psp);
 | 
						|
                        break;
 | 
						|
 | 
						|
                    case MouseClickSliceAction.Select:
 | 
						|
                        ProcessSliceSelect(e, pieChart, psp);
 | 
						|
                        break;
 | 
						|
                }
 | 
						|
 | 
						|
                return (true);
 | 
						|
            }
 | 
						|
 | 
						|
            return (false);
 | 
						|
        }
 | 
						|
 | 
						|
        #region InitPspDrag
 | 
						|
 | 
						|
        private bool InitPspDrag(PieChart pieChart, PieSeriesPoint psp)
 | 
						|
        {
 | 
						|
            if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
 | 
						|
            {
 | 
						|
                if (pieChart.EnableShiftDragExplode == true)
 | 
						|
                {
 | 
						|
                    pieChart.PspDragType = PspDragType.Explode;
 | 
						|
 | 
						|
                    return (true);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                if (GetEnableDragDetach(pieChart) == true)
 | 
						|
                {
 | 
						|
                    pieChart.PspDragType = PspDragType.Detach;
 | 
						|
 | 
						|
                    return (psp.IsSelected);
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (false);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region ProcessSliceSelect
 | 
						|
 | 
						|
        private void ProcessSliceSelect(
 | 
						|
            MouseEventArgs e, PieChart pieChart, PieSeriesPoint psp)
 | 
						|
        {
 | 
						|
            bool select = true;
 | 
						|
 | 
						|
            if ((pieChart.MultiSelect == true) &&
 | 
						|
                (Control.ModifierKeys & Keys.Control) == Keys.Control)
 | 
						|
            {
 | 
						|
                select = !psp.IsSelected;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                if (InitPspDrag(pieChart, psp) == true)
 | 
						|
                    return;
 | 
						|
 | 
						|
                int selCount = pieChart.GetSelectionCount();
 | 
						|
 | 
						|
                if (selCount != 1 || psp.IsSelected == false)
 | 
						|
                    pieChart.SetSelected(false);
 | 
						|
            }
 | 
						|
 | 
						|
            ProcessSliceSelectEx(pieChart, psp, select);
 | 
						|
        }
 | 
						|
 | 
						|
        #region ProcessSliceSelectEx
 | 
						|
 | 
						|
        private void ProcessSliceSelectEx(
 | 
						|
            PieChart pieChart, PieSeriesPoint psp, bool select)
 | 
						|
        {
 | 
						|
            PieSelectionMode psm = GetPieSelectionMode(pieChart);
 | 
						|
 | 
						|
            switch (psm)
 | 
						|
            {
 | 
						|
                case PieSelectionMode.Pie:
 | 
						|
                    pieChart.SetSelected(select);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case PieSelectionMode.Series:
 | 
						|
                    SelectPspSeries(SeriesPoints, true, select);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case PieSelectionMode.Ring:
 | 
						|
                    SelectPspRing(psp, select);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case PieSelectionMode.Slice:
 | 
						|
                    SelectPspSlice(pieChart, psp, select);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case PieSelectionMode.Point:
 | 
						|
                    psp.IsSelected = select;
 | 
						|
                    break;
 | 
						|
            }
 | 
						|
 | 
						|
            ChartControl.DoPieSelectionChangedEvent(pieChart, this, psp, psm);
 | 
						|
        }
 | 
						|
 | 
						|
        #region SelectPspSeries
 | 
						|
 | 
						|
        private void SelectPspSeries(
 | 
						|
            PieSeriesPointCollection spc, bool showInner, bool select)
 | 
						|
        {
 | 
						|
            if (spc != null)
 | 
						|
            {
 | 
						|
                foreach (PieSeriesPoint psp in spc)
 | 
						|
                {
 | 
						|
                    if (psp.AllowSelect == true)
 | 
						|
                    {
 | 
						|
                        psp.IsSelected = select;
 | 
						|
 | 
						|
                        if (showInner == true)
 | 
						|
                            SelectPspSeries(psp.SeriesPoints, true, select);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region SelectPspRing
 | 
						|
 | 
						|
        private void SelectPspRing(PieSeriesPoint psp, bool select)
 | 
						|
        {
 | 
						|
            if (psp.PieRing != null)
 | 
						|
            {
 | 
						|
                if (psp.PieRing.AllowSelect == true)
 | 
						|
                {
 | 
						|
                    foreach (PieSeriesPoint rpsp in psp.PieRing.Psps)
 | 
						|
                    {
 | 
						|
                        if (rpsp.AllowSelect == true)
 | 
						|
                            rpsp.IsSelected = select;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region SelectPspSlice
 | 
						|
 | 
						|
        private void SelectPspSlice(
 | 
						|
            PieChart pieChart, PieSeriesPoint psp, bool select)
 | 
						|
        {
 | 
						|
            PieSeriesPoint rootPsp = (ShowAllRingsEx(pieChart) == true)
 | 
						|
                ? psp.RootPsp : psp;
 | 
						|
 | 
						|
            if (rootPsp != null)
 | 
						|
            {
 | 
						|
                if (rootPsp.AllowSelect == true)
 | 
						|
                {
 | 
						|
                    rootPsp.IsSelected = select;
 | 
						|
 | 
						|
                    SelectPspSliceEx(rootPsp.SeriesPoints, select);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region SelectPspSliceEx
 | 
						|
 | 
						|
        private void SelectPspSliceEx(PieSeriesPointCollection spc, bool select)
 | 
						|
        {
 | 
						|
            if (spc != null)
 | 
						|
            {
 | 
						|
                foreach (PieSeriesPoint psp in spc)
 | 
						|
                {
 | 
						|
                    if (psp.AllowSelect == true)
 | 
						|
                    {
 | 
						|
                        psp.IsSelected = select;
 | 
						|
 | 
						|
                        SelectPspSliceEx(psp.SeriesPoints, select);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region ProcessMouseMove
 | 
						|
 | 
						|
        internal void ProcessMouseMove(MouseEventArgs e, PieChart pieChart)
 | 
						|
        {
 | 
						|
            if (IsMouseDown == true && _MouseDownPsp != null)
 | 
						|
                ProcessMouseDownMove(e, pieChart);
 | 
						|
        }
 | 
						|
 | 
						|
        #region ProcessMouseDownMove
 | 
						|
 | 
						|
        private bool ProcessMouseDownMove(MouseEventArgs e, PieChart pieChart)
 | 
						|
        {
 | 
						|
            Point pt = e.Location;
 | 
						|
 | 
						|
            if (pieChart.IsDragging == false)
 | 
						|
            {
 | 
						|
                if (Math.Abs(MouseDownPoint.X - pt.X) > 3 ||
 | 
						|
                    Math.Abs(MouseDownPoint.Y - pt.Y) > 3)
 | 
						|
                {
 | 
						|
                    pieChart.IsDragging = true;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                int deltaOffset = GetDeltaOffset(pieChart, pt);
 | 
						|
 | 
						|
                MouseClickSliceAction mca = GetMouseClickSliceAction(pieChart);
 | 
						|
 | 
						|
                switch (pieChart.PspDragType)
 | 
						|
                {
 | 
						|
                    case PspDragType.Detach:
 | 
						|
                        if (GetEnableDragDetach(pieChart) == true)
 | 
						|
                            DetachSelectedPsps(pieChart, mca, deltaOffset);
 | 
						|
                        break;
 | 
						|
 | 
						|
                    case PspDragType.Explode:
 | 
						|
                        if (pieChart.EnableShiftDragExplode == true)
 | 
						|
                            ExplodePie(pieChart, deltaOffset);
 | 
						|
                        break;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (true);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetDeltaOffset
 | 
						|
 | 
						|
        private int GetDeltaOffset(PieChart pieChart, Point pt)
 | 
						|
        {
 | 
						|
            PieSeriesPoint psp = pieChart.HitPsp;
 | 
						|
 | 
						|
            if (psp != null)
 | 
						|
            {
 | 
						|
                Point cpt = pieChart.GetLocalAdjustedPoint(pieChart.CenterPoint);
 | 
						|
 | 
						|
                Point rpt = pt;
 | 
						|
                double radius = MathHelper.GetPointRadius(ref rpt, cpt);
 | 
						|
 | 
						|
                if (ShowAllRingsEx(pieChart) == true)
 | 
						|
                {
 | 
						|
                    double pspAngle = MathHelper.GetPointAngle(rpt);
 | 
						|
 | 
						|
                    double angle = psp.CenterAngle - pspAngle;
 | 
						|
                    double delta = Math.Cos(MathHelper.ToRadians(angle)) * radius;
 | 
						|
 | 
						|
                    return ((int)delta);
 | 
						|
                }
 | 
						|
 | 
						|
                return ((int)radius);
 | 
						|
            }
 | 
						|
 | 
						|
            return (0);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region DetachSelectedPsps
 | 
						|
 | 
						|
        private void DetachSelectedPsps(
 | 
						|
            PieChart pieChart, MouseClickSliceAction mca, int deltaOffset)
 | 
						|
        {
 | 
						|
            int offset = Math.Max(0, deltaOffset - _MouseDownRadius + _MouseDownOffset);
 | 
						|
            offset = Math.Min(offset, pieChart.MaxDetachedOffset);
 | 
						|
 | 
						|
            PieSeriesPoint pspRoot =
 | 
						|
                ShowAllRingsEx(pieChart) ? _MouseDownPsp.RootPsp : _MouseDownPsp;
 | 
						|
 | 
						|
            PieSelectionMode psm = GetPieSelectionMode(pieChart);
 | 
						|
 | 
						|
            bool detachChange = false;
 | 
						|
 | 
						|
            switch (psm)
 | 
						|
            {
 | 
						|
                case PieSelectionMode.Pie:
 | 
						|
                    foreach (PieSeries series in pieChart.ChartSeries)
 | 
						|
                    {
 | 
						|
                        if (series.IsDisplayed == true)
 | 
						|
                        {
 | 
						|
                            foreach (PieSeriesPoint psp in series.SeriesPoints)
 | 
						|
                                detachChange |= DetachPsp(psp, offset);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    break;
 | 
						|
 | 
						|
                case PieSelectionMode.Series:
 | 
						|
                case PieSelectionMode.Ring:
 | 
						|
                    if (pspRoot.PieRing.AllowDetach == true)
 | 
						|
                    {
 | 
						|
                        foreach (PieSeriesPoint psp in pspRoot.PieRing.Psps)
 | 
						|
                            detachChange |= DetachPsp(psp, offset);
 | 
						|
                    }
 | 
						|
                    break;
 | 
						|
 | 
						|
                case PieSelectionMode.Slice:
 | 
						|
                case PieSelectionMode.Point:
 | 
						|
                    if (mca == MouseClickSliceAction.Select)
 | 
						|
                    {
 | 
						|
                        if (pspRoot.PieRing.AllowDetach == true)
 | 
						|
                        {
 | 
						|
                            foreach (PieSeriesPoint psp in pspRoot.PieRing.Psps)
 | 
						|
                            {
 | 
						|
                                if (psp.IsSelected == true)
 | 
						|
                                    detachChange |= DetachPsp(psp, offset);
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        detachChange |= DetachPsp(pspRoot, offset);
 | 
						|
                    }
 | 
						|
                    break;
 | 
						|
            }
 | 
						|
 | 
						|
            ChartControl.DoPieDetachChangedEvent(pieChart, this, psm);
 | 
						|
        }
 | 
						|
 | 
						|
        #region DetachPsp
 | 
						|
 | 
						|
        private void DetachPsp(PieSeriesPoint psp)
 | 
						|
        {
 | 
						|
            DetachPsp(psp, psp.DetachedOffset);
 | 
						|
        }
 | 
						|
 | 
						|
        private bool DetachPsp(PieSeriesPoint psp, double offset)
 | 
						|
        {
 | 
						|
            if (psp.AllowDetach == true)
 | 
						|
            {
 | 
						|
                if (psp.DetachedOffset != offset || psp.IsDetached != (offset > 0))
 | 
						|
                {
 | 
						|
                    psp.DetachedOffset = offset;
 | 
						|
                    psp.IsDetached = (offset > 0);
 | 
						|
 | 
						|
                    return (true);
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (false);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region ExplodePie
 | 
						|
 | 
						|
        private void ExplodePie(PieChart pieChart, int deltaOffset)
 | 
						|
        {
 | 
						|
            int offset = Math.Max(0, deltaOffset - _MouseDownRadius + _MouseDownOffset);
 | 
						|
 | 
						|
            offset = Math.Min(offset, pieChart.MaxExplodedOffset);
 | 
						|
 | 
						|
            if (pieChart.ExplodedOffset != offset || pieChart.IsExploded != (offset > 0))
 | 
						|
            {
 | 
						|
                pieChart.IsExploded = (offset > 0);
 | 
						|
                pieChart.ExplodedOffset = offset;
 | 
						|
 | 
						|
                ChartControl.DoPieExplodeChangedEvent(pieChart, this);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region ProcessMouseUp
 | 
						|
 | 
						|
        internal void ProcessMouseUp(MouseEventArgs e, PieChart pieChart)
 | 
						|
        {
 | 
						|
            if (pieChart.IsDragging == false)
 | 
						|
            {
 | 
						|
                PieSeriesPoint psp = pieChart.HitPsp;
 | 
						|
 | 
						|
                if (psp != null && psp == _MouseDownPsp)
 | 
						|
                {
 | 
						|
                    ChartControl chartControl = ChartControl;
 | 
						|
 | 
						|
                    if (chartControl.DoChartMouseClickEvent(pieChart, psp, e) == false)
 | 
						|
                    {
 | 
						|
                        MouseClickSliceAction mca = GetMouseClickSliceAction(pieChart);
 | 
						|
 | 
						|
                        switch (mca)
 | 
						|
                        {
 | 
						|
                            case MouseClickSliceAction.Explode:
 | 
						|
                                pieChart.IsExploded = !pieChart.IsExploded;
 | 
						|
                                break;
 | 
						|
 | 
						|
                            case MouseClickSliceAction.Detach:
 | 
						|
                                DetachPsp(ShowAllRingsEx(pieChart) ? psp.RootPsp : psp);
 | 
						|
                                break;
 | 
						|
 | 
						|
                            case MouseClickSliceAction.Select:
 | 
						|
                                if ((Control.ModifierKeys & Keys.Control) == Keys.None)
 | 
						|
                                {
 | 
						|
                                    int selCount = pieChart.GetSelectionCount();
 | 
						|
 | 
						|
                                    if (selCount != 1 || psp.IsSelected == false)
 | 
						|
                                        pieChart.SetSelected(false);
 | 
						|
 | 
						|
                                    ProcessSliceSelectEx(pieChart, psp, true);
 | 
						|
                                }
 | 
						|
                                break;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region ProcessMouseDoubleClick
 | 
						|
 | 
						|
        internal bool ProcessMouseDoubleClick(
 | 
						|
            MouseEventArgs e, PieChart pieChart, PieSeriesPoint psp)
 | 
						|
        {
 | 
						|
            if (e.Button == MouseButtons.Left)
 | 
						|
            {
 | 
						|
                MouseDoubleClickSliceAction mdca = GetMouseDoubleClickSliceAction(pieChart);
 | 
						|
 | 
						|
                switch (mdca)
 | 
						|
                {
 | 
						|
                    case MouseDoubleClickSliceAction.Detach:
 | 
						|
                        psp.IsDetached = !psp.IsDetached;
 | 
						|
                        break;
 | 
						|
 | 
						|
                    case MouseDoubleClickSliceAction.Explode:
 | 
						|
                        pieChart.IsExploded = !pieChart.IsExploded;
 | 
						|
                        break;
 | 
						|
 | 
						|
                    case MouseDoubleClickSliceAction.ChangeActiveRing:
 | 
						|
                        Keys keys = Control.ModifierKeys;
 | 
						|
 | 
						|
                        if ((keys & Keys.Shift) == Keys.Shift)
 | 
						|
                            ProcessPieDrillUp(pieChart, psp);
 | 
						|
 | 
						|
                        else if ((keys & Keys.Control) == Keys.None)
 | 
						|
                            ProcessPieDrillDown(pieChart, psp);
 | 
						|
                        break;
 | 
						|
                }
 | 
						|
 | 
						|
                return (true);
 | 
						|
            }
 | 
						|
 | 
						|
            return (false);
 | 
						|
        }
 | 
						|
 | 
						|
        #region ProcessPieDrillUp
 | 
						|
 | 
						|
        private void ProcessPieDrillUp(PieChart pieChart, PieSeriesPoint psp)
 | 
						|
        {
 | 
						|
            PieSeriesPointCollection spc1 = psp.Parent as PieSeriesPointCollection;
 | 
						|
 | 
						|
            if (spc1 != null)
 | 
						|
            {
 | 
						|
                PieSeriesPoint psp2 = spc1.Parent as PieSeriesPoint;
 | 
						|
 | 
						|
                if (psp2 != null)
 | 
						|
                {
 | 
						|
                    PieSeriesPointCollection spc2 = GetPieSeriesPointCollection(psp2);
 | 
						|
 | 
						|
                    if (spc2 != null)
 | 
						|
                    {
 | 
						|
                        ChartControl chartControl = ChartControl;
 | 
						|
 | 
						|
                        if (chartControl.DoPieRingLevelChangingEvent(pieChart, spc1, spc2) == false)
 | 
						|
                        {
 | 
						|
                            SetActiveSeriesPointCollection(spc2);
 | 
						|
 | 
						|
                            chartControl.DoPieRingLevelChangedEvent(pieChart, spc1, spc2);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region ProcessPieDrillDown
 | 
						|
 | 
						|
        private void ProcessPieDrillDown(PieChart pieChart, PieSeriesPoint psp)
 | 
						|
        {
 | 
						|
            if (psp.ChartSeries.ShowAllRingsEx(pieChart) == false)
 | 
						|
            {
 | 
						|
                PieSeriesPointCollection spc1 = psp.Parent as PieSeriesPointCollection;
 | 
						|
 | 
						|
                if (psp.SeriesPoints.Count > 0)
 | 
						|
                {
 | 
						|
                    ChartControl chartControl = ChartControl;
 | 
						|
                    PieSeriesPointCollection spc2 = psp.SeriesPoints;
 | 
						|
 | 
						|
                    if (chartControl.DoPieRingLevelChangingEvent(pieChart, spc1, spc2) == false)
 | 
						|
                    {
 | 
						|
                        SetActiveSeriesPointCollection(psp.SeriesPoints);
 | 
						|
 | 
						|
                        chartControl.DoPieRingLevelChangedEvent(pieChart, spc1, spc2);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region SetSelected
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Selects or clears all series PieSeriesPoints.
 | 
						|
        /// </summary>
 | 
						|
        /// <param name="select"></param>
 | 
						|
        public void SetSelected(bool select)
 | 
						|
        {
 | 
						|
            PieSeriesPointCollection spc = SeriesPoints;
 | 
						|
 | 
						|
            spc.SetSelected(select);
 | 
						|
 | 
						|
            if (spc.OtherSlicePsp != null)
 | 
						|
                spc.OtherSlicePsp.IsSelected = select;
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetVisibleSelectionCount
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets the count of the currently Visible selected pie series points.
 | 
						|
        /// </summary>
 | 
						|
        /// <returns></returns>
 | 
						|
        public int GetVisibleSelectionCount()
 | 
						|
        {
 | 
						|
            int count = GetVisibleSelectionCountEx(SeriesPoints);
 | 
						|
 | 
						|
            return (count);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetVisibleSelectionCountEx
 | 
						|
 | 
						|
        private int GetVisibleSelectionCountEx(PieSeriesPointCollection spc)
 | 
						|
        {
 | 
						|
            int count = 0;
 | 
						|
 | 
						|
            if (spc != null && spc.Count > 0)
 | 
						|
            {
 | 
						|
                foreach (PieSeriesPoint psp in spc)
 | 
						|
                {
 | 
						|
                    if (psp.IsSelected == true && psp.Visible == true)
 | 
						|
                        count++;
 | 
						|
 | 
						|
                    count += GetVisibleSelectionCountEx(psp.SeriesPoints);
 | 
						|
                }
 | 
						|
 | 
						|
                if (spc.OtherSlicePsp != null)
 | 
						|
                {
 | 
						|
                    if (spc.OtherSlicePsp.IsSelected == true && spc.OtherSlicePsp.Visible == true)
 | 
						|
                        count++;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (count);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetVisibleSelectedPoints
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets a list of the currently Visible selected pie series points.
 | 
						|
        /// </summary>
 | 
						|
        /// <returns></returns>
 | 
						|
        public List<PieSeriesPoint> GetVisibleSelectedPoints()
 | 
						|
        {
 | 
						|
            List<PieSeriesPoint> list = new List<PieSeriesPoint>();
 | 
						|
 | 
						|
            GetVisibleSelectedPointsEx(list, SeriesPoints);
 | 
						|
 | 
						|
            return (list);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetVisibleSelectedPointsEx
 | 
						|
 | 
						|
        private void GetVisibleSelectedPointsEx(
 | 
						|
            List<PieSeriesPoint> list, PieSeriesPointCollection spc)
 | 
						|
        {
 | 
						|
            if (spc != null && spc.Count > 0)
 | 
						|
            {
 | 
						|
                foreach (PieSeriesPoint psp in spc)
 | 
						|
                {
 | 
						|
                    if (psp.IsSelected == true && psp.Visible == true)
 | 
						|
                        list.Add(psp);
 | 
						|
 | 
						|
                    GetVisibleSelectedPointsEx(list, psp.SeriesPoints);
 | 
						|
                }
 | 
						|
 | 
						|
                if (spc.OtherSlicePsp != null)
 | 
						|
                {
 | 
						|
                    if (spc.OtherSlicePsp.IsSelected == true && spc.OtherSlicePsp.Visible == true)
 | 
						|
                        list.Add(spc.OtherSlicePsp);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetSelectionCount
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets a count of the selected pie series points.
 | 
						|
        /// </summary>
 | 
						|
        /// <returns></returns>
 | 
						|
        public int GetSelectionCount()
 | 
						|
        {
 | 
						|
            int count = GetSelectionCountEx(SeriesPoints);
 | 
						|
 | 
						|
            return (count);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetSelectionCountEx
 | 
						|
 | 
						|
        private int GetSelectionCountEx(PieSeriesPointCollection spc)
 | 
						|
        {
 | 
						|
            int count = 0;
 | 
						|
 | 
						|
            if (spc != null && spc.Count > 0)
 | 
						|
            {
 | 
						|
                foreach (PieSeriesPoint psp in spc)
 | 
						|
                {
 | 
						|
                    if (psp.IsSelected == true)
 | 
						|
                        count++;
 | 
						|
 | 
						|
                    count += GetSelectionCountEx(psp.SeriesPoints);
 | 
						|
                }
 | 
						|
 | 
						|
                if (spc.OtherSlicePsp != null)
 | 
						|
                {
 | 
						|
                    if (spc.OtherSlicePsp.IsSelected == true )
 | 
						|
                        count++;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (count);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetSelectedPoints
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets a list of the currently selected pie series points.
 | 
						|
        /// </summary>
 | 
						|
        /// <returns></returns>
 | 
						|
        public List<PieSeriesPoint> GetSelectedPoints()
 | 
						|
        {
 | 
						|
            List<PieSeriesPoint> list = new List<PieSeriesPoint>();
 | 
						|
 | 
						|
            GetSelectedPointsEx(list, SeriesPoints);
 | 
						|
 | 
						|
            return (list);
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetSelectedPointsEx
 | 
						|
 | 
						|
        private void GetSelectedPointsEx(
 | 
						|
            List<PieSeriesPoint> list, PieSeriesPointCollection spc)
 | 
						|
        {
 | 
						|
            if (spc != null && spc.Count > 0)
 | 
						|
            {
 | 
						|
                foreach (PieSeriesPoint psp in spc)
 | 
						|
                {
 | 
						|
                    if (psp.IsSelected == true)
 | 
						|
                        list.Add(psp);
 | 
						|
 | 
						|
                    GetSelectedPointsEx(list, psp.SeriesPoints);
 | 
						|
                }
 | 
						|
 | 
						|
                if (spc.OtherSlicePsp != null)
 | 
						|
                {
 | 
						|
                    if (spc.OtherSlicePsp.IsSelected == true)
 | 
						|
                        list.Add(spc.OtherSlicePsp);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Style handling
 | 
						|
 | 
						|
        #region StyleChanged
 | 
						|
 | 
						|
        protected override void StyleChanged(object sender, PropertyChangedEventArgs e)
 | 
						|
        {
 | 
						|
            base.StyleChanged(sender, e);
 | 
						|
 | 
						|
            if (sender is ChartLegendItemVisualStyles && LegendItem != null)
 | 
						|
                InvalidateRender(LegendItem.Bounds);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region InvalidateRender
 | 
						|
 | 
						|
        public override void InvalidateRender()
 | 
						|
        {
 | 
						|
            BaseChart chart = Parent as BaseChart;
 | 
						|
 | 
						|
            if (chart != null)
 | 
						|
                chart.InvalidateRender();
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region InvalidateRecalc
 | 
						|
 | 
						|
        internal override void InvalidateRecalc()
 | 
						|
        {
 | 
						|
            SeriesRangeChanged = true;
 | 
						|
 | 
						|
            base.InvalidateRecalc();
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region ILegendItem
 | 
						|
 | 
						|
        #region GetLegendItem
 | 
						|
 | 
						|
        public override ChartLegendItem GetLegendItem()
 | 
						|
        {
 | 
						|
            LegendItem = null;
 | 
						|
 | 
						|
            if (ShowInLegend == true)
 | 
						|
            {
 | 
						|
                PieChart pieChart = Parent as PieChart;
 | 
						|
 | 
						|
                if (pieChart != null)
 | 
						|
                {
 | 
						|
                    if (pieChart.VisibleSeriesCount > 1)
 | 
						|
                    {
 | 
						|
                        if (pieChart.Legend.ShowPieSeriesInLegend == true)
 | 
						|
                        {
 | 
						|
                            LegendItem = base.GetLegendItem();
 | 
						|
 | 
						|
                            LegendItem.ShowCheckBox = pieChart.Legend.ShowPieSeriesCheckBoxes;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (LegendItem);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region AddSubLegendItems
 | 
						|
 | 
						|
        internal override void AddSubLegendItems(List<ChartLegendItem> list)
 | 
						|
        {
 | 
						|
            PieChart pieChart = Parent as PieChart;
 | 
						|
 | 
						|
            if (pieChart != null)
 | 
						|
            {
 | 
						|
                if (ShowInLegend == true)
 | 
						|
                {
 | 
						|
                    ChartLegend legend = pieChart.Legend;
 | 
						|
 | 
						|
                    if (ShowAllRingsEx(pieChart) == true)
 | 
						|
                    {
 | 
						|
                        if (PieRings != null && PieRings.Count > 0)
 | 
						|
                        {
 | 
						|
                            bool addRings =
 | 
						|
                                ((PieRings.Count > 1) && 
 | 
						|
                                 (pieChart.Legend.ShowPieRingsInLegend == true));
 | 
						|
 | 
						|
                            foreach (PieRing pieRing in PieRings)
 | 
						|
                            {
 | 
						|
                                if (addRings == true)
 | 
						|
                                {
 | 
						|
                                    ChartLegendItem litem = pieRing.GetLegendItem();
 | 
						|
 | 
						|
                                    if (litem != null)
 | 
						|
                                    {
 | 
						|
                                        litem.ShowCheckBox = legend.ShowPieRingCheckBoxes;
 | 
						|
                                        list.Add(litem);
 | 
						|
                                    }
 | 
						|
                                }
 | 
						|
 | 
						|
                                if (legend.ShowPieSeriesPointsInLegend == true)
 | 
						|
                                    AddSubLegendItemsEx(legend, list, pieRing.GetLegendItems());
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        PieSeriesPointCollection spc = GetActiveSeriesPointCollection();
 | 
						|
 | 
						|
                        if (spc != null)
 | 
						|
                        {
 | 
						|
                            if (spc.PieSlices != null)
 | 
						|
                                spc = spc.PieSlices;
 | 
						|
 | 
						|
                            if (spc != null)
 | 
						|
                            {
 | 
						|
                                foreach (PieSeriesPoint psp in spc)
 | 
						|
                                {
 | 
						|
                                    if (psp.IsDisplayable == true)
 | 
						|
                                        AddSubLegendItemsEx(legend, list, psp.GetLegendItems());
 | 
						|
                                }
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region AddSubLegendItemsEx
 | 
						|
 | 
						|
        private void AddSubLegendItemsEx(ChartLegend legend,
 | 
						|
            List<ChartLegendItem> list, List<ChartLegendItem> items)
 | 
						|
        {
 | 
						|
            if (items != null && items.Count > 0)
 | 
						|
            {
 | 
						|
                foreach (ChartLegendItem item in items)
 | 
						|
                {
 | 
						|
                    item.ShowCheckBox = legend.ShowPieSeriesPointCheckBoxes;
 | 
						|
 | 
						|
                    if (legend.CombineLikeItems == true)
 | 
						|
                    {
 | 
						|
                        ChartLegendItem likeItem = FindLikeItems(list, item);
 | 
						|
 | 
						|
                        if (likeItem == null)
 | 
						|
                        {
 | 
						|
                            item.ChartControl = ChartControl;
 | 
						|
 | 
						|
                            likeItem = new ChartLegendItem();
 | 
						|
 | 
						|
                            likeItem.Parent = legend;
 | 
						|
                            likeItem.ChartControl = ChartControl;
 | 
						|
 | 
						|
                            likeItem.Name = item.Name;
 | 
						|
                            likeItem.ItemText = item.ItemText;
 | 
						|
                            likeItem.IsEnabled = item.IsEnabled;
 | 
						|
 | 
						|
                            list.Add(likeItem);
 | 
						|
                        }
 | 
						|
 | 
						|
                        item.LikeItem = likeItem;
 | 
						|
 | 
						|
                        likeItem.ChartItems.AddRange(item.ChartItems);
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        list.Add(item);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region FindLikeItems
 | 
						|
 | 
						|
        private ChartLegendItem FindLikeItems(List<ChartLegendItem> list, ChartLegendItem item)
 | 
						|
        {
 | 
						|
            string itemName = item.Name ?? item.ItemText;
 | 
						|
 | 
						|
            if (String.IsNullOrEmpty(itemName) == false)
 | 
						|
            {
 | 
						|
                foreach (ChartLegendItem likeItem in list)
 | 
						|
                {
 | 
						|
                    string likeName = likeItem.Name ?? likeItem.ItemText;
 | 
						|
 | 
						|
                    if (String.IsNullOrEmpty(likeName) == false)
 | 
						|
                    {
 | 
						|
                        if (likeName.Equals(itemName) == true)
 | 
						|
                            return (likeItem);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            return (null);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetLegendItemColorEx
 | 
						|
 | 
						|
        internal override Color GetLegendItemColorEx()
 | 
						|
        {
 | 
						|
            return (Color.Empty);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RenderLegendItemMarkerEx
 | 
						|
 | 
						|
        internal override void RenderLegendItemMarkerEx(
 | 
						|
            Graphics g, ChartLegendItem litem, ChartLegendItemVisualStyle style)
 | 
						|
        {
 | 
						|
            Rectangle bounds = litem.MarkerBounds;
 | 
						|
 | 
						|
            bounds.Width--;
 | 
						|
            bounds.Height--;
 | 
						|
 | 
						|
            Color color = GetLegendItemColor();
 | 
						|
 | 
						|
            using (GraphicsPath path = new GraphicsPath())
 | 
						|
            {
 | 
						|
                path.AddEllipse(bounds);
 | 
						|
 | 
						|
                using (Brush br = new SolidBrush(color))
 | 
						|
                    g.FillPath(br, path);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region TrackLegendItem
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Gets whether legend item tracking is enabled.
 | 
						|
        /// </summary>
 | 
						|
        [Browsable(false)]
 | 
						|
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
 | 
						|
        public bool TrackLegendItem
 | 
						|
        {
 | 
						|
            get
 | 
						|
            {
 | 
						|
                PieChart pieChart = Parent as PieChart;
 | 
						|
 | 
						|
                if (pieChart != null)
 | 
						|
                {
 | 
						|
                    return (pieChart.Legend.TrackingMode == LegendTrackingMode.ChartAndLegend ||
 | 
						|
                        pieChart.Legend.TrackingMode == LegendTrackingMode.Legend);
 | 
						|
                }
 | 
						|
 | 
						|
                return (false);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region FormatItemText
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Formats the provided item text.
 | 
						|
        /// </summary>
 | 
						|
        [Browsable(false)]
 | 
						|
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
 | 
						|
        public string FormatItemText(string text)
 | 
						|
        {
 | 
						|
            return (text);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region OnCheckStateChanged
 | 
						|
 | 
						|
        internal override void OnCheckStateChanged()
 | 
						|
        {
 | 
						|
            if (LegendItem != null)
 | 
						|
                LegendItem.UpdateCheckState();
 | 
						|
 | 
						|
            foreach (PieRing pieRing in PieRings)
 | 
						|
            {
 | 
						|
                if (pieRing.LegendItem != null)
 | 
						|
                {
 | 
						|
                    pieRing.LegendItem.IsEnabled = pieRing.IsEnabled;
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    foreach (PieSeriesPoint psp in pieRing.Psps)
 | 
						|
                    {
 | 
						|
                        if (psp.LegendItem != null)
 | 
						|
                            psp.LegendItem.IsEnabled = psp.IsEnabled;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            base.OnCheckStateChanged();
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Copy/CopyTo
 | 
						|
 | 
						|
        public override ChartVisualElement Copy()
 | 
						|
        {
 | 
						|
            ChartSeries copy = new ChartSeries();
 | 
						|
 | 
						|
            CopyTo(copy);
 | 
						|
 | 
						|
            return (copy);
 | 
						|
        }
 | 
						|
 | 
						|
        public override void CopyTo(ChartVisualElement copy)
 | 
						|
        {
 | 
						|
            PieSeries c = copy as PieSeries;
 | 
						|
 | 
						|
            if (c != null)
 | 
						|
            {
 | 
						|
                base.CopyTo(c);
 | 
						|
 | 
						|
                c.CenterFirstSlice = CenterFirstSlice;
 | 
						|
 | 
						|
                if (_CustomPalette != null)
 | 
						|
                {
 | 
						|
                    c.CustomPalette = new Color[CustomPalette.Length];
 | 
						|
 | 
						|
                    CustomPalette.CopyTo(c.CustomPalette, 0);
 | 
						|
                }
 | 
						|
 | 
						|
                c.EnableDragDetach = EnableDragDetach;
 | 
						|
                c.ExplodedMargin = ExplodedMargin;
 | 
						|
 | 
						|
                c.MouseClickSliceAction = MouseClickSliceAction;
 | 
						|
                c.MouseDoubleClickSliceAction = MouseDoubleClickSliceAction;
 | 
						|
 | 
						|
                c.PaletteGroup = PaletteGroup;
 | 
						|
                c.PieSelectionMode = PieSelectionMode;
 | 
						|
                c.ReversePaletteColors = ReversePaletteColors;
 | 
						|
                c.RingWeight = RingWeight;
 | 
						|
 | 
						|
                c.SubSliceVisualLayout = (_SliceVisualLayout != null) ? _SliceVisualLayout.Copy() : null;
 | 
						|
 | 
						|
                foreach (PieSeriesPoint psp in SeriesPoints)
 | 
						|
                    c.SeriesPoints.Add(psp.Copy());
 | 
						|
 | 
						|
                c.ShowAllRings = ShowAllRings;
 | 
						|
                c.ShowOtherSlice = ShowOtherSlice;
 | 
						|
 | 
						|
                c.SubSliceVisualLayout = (_SliceVisualLayout != null) ? SubSliceVisualLayout.Copy() : null;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region GetSerialData
 | 
						|
 | 
						|
        internal override SerialElementCollection GetSerialData(string serialName)
 | 
						|
        {
 | 
						|
            SerialElementCollection sec = new SerialElementCollection();
 | 
						|
 | 
						|
            if (serialName != null)
 | 
						|
            {
 | 
						|
                if (serialName.Equals("") == true)
 | 
						|
                    serialName = "PieSeries";
 | 
						|
 | 
						|
                sec.AddStartElement(serialName);
 | 
						|
            }
 | 
						|
 | 
						|
            sec.AddValue("CenterFirstSlice", CenterFirstSlice, Tbool.NotSet);
 | 
						|
 | 
						|
            if (_CustomPalette != null && _CustomPalette.Length > 0)
 | 
						|
            {
 | 
						|
                sec.AddStartElement("CustomPalette count=\"" + _CustomPalette.Length + "\"");
 | 
						|
 | 
						|
                foreach (Color color in _CustomPalette)
 | 
						|
                    sec.AddValue("PaletteColor", color);
 | 
						|
 | 
						|
                sec.AddEndElement("CustomPalette");
 | 
						|
            }
 | 
						|
 | 
						|
            sec.AddValue("EnableDragDetach", EnableDragDetach, Tbool.NotSet);
 | 
						|
            sec.AddValue("ExplodedMargin", ExplodedMargin, double.NaN);
 | 
						|
 | 
						|
            sec.AddValue("MouseClickSliceAction", MouseClickSliceAction, MouseClickSliceAction.NotSet);
 | 
						|
            sec.AddValue("MouseDoubleClickSliceAction", MouseDoubleClickSliceAction, MouseDoubleClickSliceAction.NotSet);
 | 
						|
 | 
						|
            sec.AddValue("PaletteGroup", PaletteGroup, PaletteGroup.NotSet);
 | 
						|
            sec.AddValue("PieSelectionMode", PieSelectionMode, PieSelectionMode.NotSet);
 | 
						|
            sec.AddValue("ReversePaletteColors", ReversePaletteColors, false);
 | 
						|
            sec.AddValue("RingWeight", RingWeight, 100);
 | 
						|
 | 
						|
            if (_SeriesPoints != null)
 | 
						|
            {
 | 
						|
                PieSeriesPointCollection spc = _SeriesPoints;
 | 
						|
 | 
						|
                if (spc.Count > 0)
 | 
						|
                {
 | 
						|
                    sec.AddStartElement("SeriesPoints count=\"" + spc.Count + "\"");
 | 
						|
 | 
						|
                    foreach (PieSeriesPoint psp in spc)
 | 
						|
                        sec.AddElement(psp.GetSerialData());
 | 
						|
 | 
						|
                    sec.AddEndElement("SeriesPoints");
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            sec.AddValue("ShowAllRings", ShowAllRings, Tbool.NotSet);
 | 
						|
            sec.AddValue("ShowOtherSlice", ShowOtherSlice, Tbool.NotSet);
 | 
						|
 | 
						|
            if (_SliceVisualLayout != null)
 | 
						|
                sec.AddElement(_SliceVisualLayout.GetSerialData(true));
 | 
						|
 | 
						|
            sec.AddElement(base.GetSerialData(null));
 | 
						|
 | 
						|
            if (serialName != null)
 | 
						|
                sec.AddEndElement(serialName);
 | 
						|
 | 
						|
            return (sec);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region PutSerialData
 | 
						|
 | 
						|
        #region ProcessValue
 | 
						|
 | 
						|
        internal override void ProcessValue(SerialElement se)
 | 
						|
        {
 | 
						|
            ChartXy chartXy = Parent as ChartXy;
 | 
						|
 | 
						|
            switch (se.Name)
 | 
						|
            {
 | 
						|
                case "CenterFirstSlice":
 | 
						|
                    CenterFirstSlice = (Tbool)se.GetValueEnum(typeof(Tbool));
 | 
						|
                    break;
 | 
						|
 | 
						|
                case "EnableDragDetach":
 | 
						|
                    EnableDragDetach = (Tbool)se.GetValueEnum(typeof(Tbool));
 | 
						|
                    break;
 | 
						|
 | 
						|
                case "ExplodedMargin":
 | 
						|
                    ExplodedMargin = double.Parse(se.StringValue);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case "MouseClickSliceAction":
 | 
						|
                    MouseClickSliceAction = (MouseClickSliceAction)se.GetValueEnum(typeof(MouseClickSliceAction));
 | 
						|
                    break;
 | 
						|
 | 
						|
                case "MouseDoubleClickSliceAction":
 | 
						|
                    MouseDoubleClickSliceAction = (MouseDoubleClickSliceAction)se.GetValueEnum(typeof(MouseDoubleClickSliceAction));
 | 
						|
                    break;
 | 
						|
 | 
						|
                case "PaletteColor":
 | 
						|
                    CustomPalette[se.ValueIndex] = se.GetValueColor();
 | 
						|
                    break;
 | 
						|
 | 
						|
                case "PaletteGroup":
 | 
						|
                    PaletteGroup = (PaletteGroup)se.GetValueEnum(typeof(PaletteGroup));
 | 
						|
                    break;
 | 
						|
 | 
						|
                case "PieSelectionMode":
 | 
						|
                    PieSelectionMode = (PieSelectionMode)se.GetValueEnum(typeof(PieSelectionMode));
 | 
						|
                    break;
 | 
						|
 | 
						|
                case "ReversePaletteColors":
 | 
						|
                    ReversePaletteColors = bool.Parse(se.StringValue);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case "RingWeight":
 | 
						|
                    RingWeight = int.Parse(se.StringValue);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case "ShowAllRings":
 | 
						|
                    ShowAllRings = (Tbool)se.GetValueEnum(typeof(Tbool));
 | 
						|
                    break;
 | 
						|
 | 
						|
                case "ShowOtherSlice":
 | 
						|
                    ShowOtherSlice = (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 "CustomPalette":
 | 
						|
                    if (se.ArrayCount > 0)
 | 
						|
                    {
 | 
						|
                        CustomPalette = new Color[se.ArrayCount];
 | 
						|
 | 
						|
                        sec.PutSerialData(this);
 | 
						|
                    }
 | 
						|
                    break;
 | 
						|
 | 
						|
                case "SeriesPoint":
 | 
						|
                    PieSeriesPoint psp = new PieSeriesPoint();
 | 
						|
 | 
						|
                    sec.PutSerialData(psp);
 | 
						|
 | 
						|
                    SeriesPoints.Add(psp);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case "SeriesPoints":
 | 
						|
                    if (se.ArrayCount > 0)
 | 
						|
                    {
 | 
						|
                        SeriesPoints = new PieSeriesPointCollection();
 | 
						|
 | 
						|
                        sec.PutSerialData(this);
 | 
						|
                    }
 | 
						|
                    break;
 | 
						|
 | 
						|
                case "SliceVisualLayout":
 | 
						|
                    sec.PutSerialData(SubSliceVisualLayout);
 | 
						|
                    break;
 | 
						|
 | 
						|
                default:
 | 
						|
                    base.ProcessCollection(se);
 | 
						|
                    break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Series States
 | 
						|
 | 
						|
        [Flags]
 | 
						|
        private enum States : uint
 | 
						|
        {
 | 
						|
            FilterIgnoreMatchCase = (1U << 0),
 | 
						|
 | 
						|
            IsSorted = (1U << 1),
 | 
						|
            IsRotated = (1U << 2),
 | 
						|
 | 
						|
            StackQualitativePoints = (1U << 3),
 | 
						|
            DisplayLinePointsOnTop = (1U << 4),
 | 
						|
 | 
						|
            EnableEmptyValues = (1U << 5),
 | 
						|
            ShowEmptyLines = (1U << 6),
 | 
						|
            ShowEmptyPoints = (1U << 7),
 | 
						|
            ShowOriginValueLabels = (1U << 8),
 | 
						|
            ShowHiLoBarMedianLines = (1U << 9),
 | 
						|
 | 
						|
            NeedToUpdateBindings = (1U << 10),
 | 
						|
 | 
						|
            IsInnerRingSeries = (1U << 11),
 | 
						|
            IsOuterRingSeries = (1U << 12),
 | 
						|
 | 
						|
            IsOffset = (1U << 13),
 | 
						|
            IsDetached = (1U << 14),
 | 
						|
 | 
						|
            ShowInnerRingsEx = (1U << 15),
 | 
						|
            ReversePaletteColors = (1U << 16),
 | 
						|
        }
 | 
						|
 | 
						|
        #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()
 | 
						|
        {
 | 
						|
            Visible = false;
 | 
						|
 | 
						|
            SeriesPoints = null;
 | 
						|
            SubSliceVisualLayout = null;
 | 
						|
 | 
						|
            base.Dispose();
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
    }
 | 
						|
 | 
						|
    #region WordPos
 | 
						|
 | 
						|
    internal class WordPos
 | 
						|
    {
 | 
						|
        public string Text;
 | 
						|
 | 
						|
        public int Index;
 | 
						|
        public int Length;
 | 
						|
    }
 | 
						|
 | 
						|
    #endregion
 | 
						|
 | 
						|
    #region WordPosLine
 | 
						|
 | 
						|
    internal class WordPosLine
 | 
						|
    {
 | 
						|
        public double ArcWidth;
 | 
						|
        public double LineWidth;
 | 
						|
        public double Offset;
 | 
						|
 | 
						|
        public List<WordPos> Wps = new List<WordPos>();
 | 
						|
    }
 | 
						|
 | 
						|
    #endregion
 | 
						|
 | 
						|
    #region enums
 | 
						|
 | 
						|
    #region SliceRenderType
 | 
						|
 | 
						|
    public enum SliceRenderType
 | 
						|
    {
 | 
						|
        /// <summary>
 | 
						|
        /// Full slice.
 | 
						|
        /// </summary>
 | 
						|
        FullSlice,
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Extent slice (partial slice).
 | 
						|
        /// </summary>
 | 
						|
        ExtentSlice,
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Extentwhitespace.
 | 
						|
        /// </summary>
 | 
						|
        ExtentWhitespace,
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// 'Other' slice whitespace.
 | 
						|
        /// </summary>
 | 
						|
        OtherWhitespace,
 | 
						|
    }
 | 
						|
 | 
						|
    #endregion
 | 
						|
 | 
						|
    #region ExtentFillRange
 | 
						|
 | 
						|
    public enum ExtentFillRange
 | 
						|
    {
 | 
						|
        /// <summary>
 | 
						|
        /// Not set (default is ByPoint)
 | 
						|
        /// </summary>
 | 
						|
        NotSet = 0,
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Extents are filled according to each individual
 | 
						|
        /// PieSeriesPoint extent value.
 | 
						|
        /// </summary>
 | 
						|
        ByPoint,
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Extents are filled according to the slice
 | 
						|
        /// maximum extent value.
 | 
						|
        /// </summary>
 | 
						|
        BySlice,
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Extents are filled according to the associated
 | 
						|
        /// PieRing maximum extent value.
 | 
						|
        /// </summary>
 | 
						|
        ByRing,
 | 
						|
    }
 | 
						|
 | 
						|
    #endregion
 | 
						|
 | 
						|
    #region SliceImageCropMode
 | 
						|
 | 
						|
    public enum SliceImageCropMode
 | 
						|
    {
 | 
						|
        NotSet = -1,
 | 
						|
 | 
						|
        NoAction,
 | 
						|
        ClipImage,
 | 
						|
        HideImage,
 | 
						|
    }
 | 
						|
 | 
						|
    #endregion
 | 
						|
 | 
						|
    #region SliceImageRadiusAnchor
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Defines the anchor for the slice image (ie. the image's bounding edge).
 | 
						|
    /// </summary>
 | 
						|
    public enum SliceImageRadiusAnchor
 | 
						|
    {
 | 
						|
        /// <summary>
 | 
						|
        /// NotSet
 | 
						|
        /// </summary>
 | 
						|
        NotSet = -1,
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// The pie InnerRadius will be the anchor. 
 | 
						|
        /// </summary>
 | 
						|
        InnerRadius,
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// The pie ExtentRadius will be the anchor. The 'ExtentRadius' denotes
 | 
						|
        /// how far the slice extends out from the slice center - which may not
 | 
						|
        /// be as far as the OuterRadius (specified by the ValuesY[1] value).
 | 
						|
        /// </summary>
 | 
						|
        ExtentRadius,
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// The pie OuterRadius will be the anchor. 
 | 
						|
        /// </summary>
 | 
						|
        OuterRadius,
 | 
						|
    }
 | 
						|
 | 
						|
    #endregion
 | 
						|
 | 
						|
    #region PieRefLineDisplayMode
 | 
						|
 | 
						|
    [Flags]
 | 
						|
    /// <summary>
 | 
						|
    /// Defines the type of ReferenceLine to display.
 | 
						|
    /// </summary>
 | 
						|
    public enum PieRefLineDisplayMode
 | 
						|
    {
 | 
						|
        /// <summary>
 | 
						|
        /// NotSet
 | 
						|
        /// </summary>
 | 
						|
        NotSet = 0,
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// No Reference lines
 | 
						|
        /// </summary>
 | 
						|
        None = (1 << 0),
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Extent Average Line. 
 | 
						|
        /// </summary>
 | 
						|
        ExtentAverage = (1 << 3),
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Extent Minimum Line.
 | 
						|
        /// </summary>
 | 
						|
        ExtentMaximum = (1 << 2),
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Extent Minimum Line.
 | 
						|
        /// </summary>
 | 
						|
        ExtentMinimum = (1 << 1),
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Outer Extent Line.
 | 
						|
        /// </summary>
 | 
						|
        ExtentOuterRadius = (1 << 4),
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// All User defined Lines.
 | 
						|
        /// </summary>
 | 
						|
        UserDefined = (1 << 5),
 | 
						|
    }
 | 
						|
 | 
						|
    #endregion
 | 
						|
 | 
						|
    #endregion
 | 
						|
}
 |