1955 lines
60 KiB
C#

using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace DevComponents.DotNetBar.Charts.Style
{
/// <summary>
/// Represents the visual style of a series Slice.
/// </summary>
[TypeConverter(typeof(VisualStylesConverter))]
public class SliceLabelVisualStyle : BaseVisualStyle
{
#region Private variables
private Tbool _AllowWrap = Tbool.NotSet;
private SliceLabelAlignment _Alignment = SliceLabelAlignment.NotSet;
private Background _Background;
private Color _TextColor = Color.Empty;
private Font _Font;
private int _MaxLineCount = -1;
#endregion
#region Public properties
#region Alignment
/// <summary>
/// Gets or sets the alignment of the label.
/// </summary>
[DefaultValue(SliceLabelAlignment.NotSet), Category("Layout")]
[Description("Indicates the alignment of the label.")]
public SliceLabelAlignment Alignment
{
get { return (_Alignment); }
set
{
if (value != _Alignment)
{
_Alignment = value;
OnPropertyChangedEx("Alignment", VisualChangeType.Layout);
}
}
}
#endregion
#region AllowWrap
/// <summary>
/// Gets or sets whether text wrapping is permitted
/// </summary>
[DefaultValue(Tbool.NotSet), Category("Appearance")]
[Description("Indicates whether text wrapping is permitted.")]
public Tbool AllowWrap
{
get { return (_AllowWrap); }
set
{
if (value != _AllowWrap)
{
_AllowWrap = value;
OnPropertyChangedEx("AllowWrap", VisualChangeType.Layout);
}
}
}
#endregion
#region Background
/// <summary>
/// Gets or sets the style background.
/// </summary>
[Description("Indicates the style background")]
public Background Background
{
get
{
if (_Background == null)
{
_Background = Background.Empty;
UpdateChangeHandler(null, _Background);
}
return (_Background);
}
set
{
if (_Background != value)
{
UpdateChangeHandler(_Background, value);
_Background = value;
OnPropertyChangedEx("Background", VisualChangeType.Render);
}
}
}
/// <summary>
/// Gets whether property should be serialized.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
private bool ShouldSerializeBackground()
{
return (_Background != null && _Background.IsEmpty == false);
}
/// <summary>
/// Resets property to its default value.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
private void ResetBackground()
{
Background = null;
}
#endregion
#region Font
/// <summary>
/// Gets or sets the style Font
/// </summary>
[DefaultValue(null)]
[Description("Indicates the style Font")]
public Font Font
{
get { return (_Font); }
set
{
if (_Font != value)
{
_Font = value;
OnPropertyChangedEx("Font", VisualChangeType.Layout);
}
}
}
#endregion
#region MaxLineCount
/// <summary>
/// Gets or sets the maximum number of lines for label text.
/// </summary>
[DefaultValue(-1), Category("Appearance")]
[Description("Indicates the maximum number of lines for label text.")]
public int MaxLineCount
{
get { return (_MaxLineCount); }
set
{
if (value != _MaxLineCount)
{
_MaxLineCount = value;
OnPropertyChangedEx("MaxLineCount", VisualChangeType.Layout);
}
}
}
#endregion
#region TextColor
/// <summary>
/// Gets or sets the Text color.
/// </summary>
[Description("Indicates the Text color")]
public Color TextColor
{
get { return (_TextColor); }
set
{
if (_TextColor != value)
{
_TextColor = value;
OnPropertyChangedEx("TextColor", VisualChangeType.Render);
}
}
}
/// <summary>
/// Gets whether property should be serialized.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
private bool ShouldSerializeTextColor()
{
return (_TextColor.IsEmpty == false);
}
/// <summary>
/// Resets property to its default value.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
private void ResetTextColor()
{
TextColor = Color.Empty;
}
#endregion
#region IsEmpty
/// <summary>
/// Gets whether the style is logically Empty.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("Gets whether the style is logically Empty.")]
public override bool IsEmpty
{
get
{
return ((_Alignment == SliceLabelAlignment.NotSet) &&
(_AllowWrap == Tbool.NotSet) &&
(_Background == null || _Background.IsEmpty == true) &&
(_Font == null) &&
(_MaxLineCount < 0) &&
(_TextColor.IsEmpty == true) &&
(base.IsEmpty == true));
}
}
#endregion
#endregion
#region GetStringFormatFlags
internal void GetStringFormatFlags(StringFormat sf, bool flip)
{
if (_AllowWrap == Tbool.False || _MaxLineCount == 1)
sf.FormatFlags |= StringFormatFlags.NoWrap;
sf.Trimming = StringTrimming.EllipsisCharacter;
switch (Alignment)
{
case SliceLabelAlignment.OuterLeft:
sf.LineAlignment = (flip ? StringAlignment.Far : StringAlignment.Near);
break;
case SliceLabelAlignment.NotSet:
case SliceLabelAlignment.OuterCenter:
sf.LineAlignment = (flip ? StringAlignment.Far : StringAlignment.Near);
sf.Alignment = StringAlignment.Center;
break;
case SliceLabelAlignment.OuterRight:
sf.LineAlignment = (flip ? StringAlignment.Far : StringAlignment.Near);
sf.Alignment = StringAlignment.Far;
break;
case SliceLabelAlignment.MiddleLeft:
sf.LineAlignment = StringAlignment.Center;
sf.Alignment = StringAlignment.Near;
break;
case SliceLabelAlignment.MiddleCenter:
sf.LineAlignment = StringAlignment.Center;
sf.Alignment = StringAlignment.Center;
break;
case SliceLabelAlignment.MiddleRight:
sf.LineAlignment = StringAlignment.Center;
sf.Alignment = StringAlignment.Far;
break;
case SliceLabelAlignment.InnerLeft:
sf.LineAlignment = (flip ? StringAlignment.Near : StringAlignment.Far);
sf.Alignment = StringAlignment.Near;
break;
case SliceLabelAlignment.InnerCenter:
sf.LineAlignment = (flip ? StringAlignment.Near : StringAlignment.Far);
sf.Alignment = StringAlignment.Center;
break;
case SliceLabelAlignment.InnerRight:
sf.LineAlignment = (flip ? StringAlignment.Near : StringAlignment.Far);
sf.Alignment = StringAlignment.Far;
break;
}
}
#endregion
#region ApplyStyle
/// <summary>
/// Applies the style to instance of this style.
/// </summary>
/// <param name="style">Style to apply.</param>
public void ApplyStyle(SliceLabelVisualStyle style)
{
if (style != null)
{
base.ApplyStyle(style);
if (style.Alignment != SliceLabelAlignment.NotSet)
Alignment = style._Alignment;
if (style.AllowWrap != Tbool.NotSet)
AllowWrap = style._AllowWrap;
if (style._Background != null && style._Background.IsEmpty == false)
Background = style._Background.Copy();
if (style.Font != null)
Font = style.Font;
if (style.MaxLineCount >= 0)
MaxLineCount = style._MaxLineCount;
if (style._TextColor.IsEmpty == false)
TextColor = style._TextColor;
}
}
#endregion
#region ApplyDefaults
public override void ApplyDefaults()
{
if (_Alignment == SliceLabelAlignment.NotSet)
_Alignment = SliceLabelAlignment.OuterCenter;
if (_AllowWrap == Tbool.NotSet)
_AllowWrap = Tbool.True;
if (_Font == null)
_Font = SystemFonts.DefaultFont;
if (_TextColor.IsEmpty == true)
_TextColor = Color.Black;
base.ApplyDefaults();
}
#endregion
#region Copy
/// <summary>
/// Returns the copy of the style.
/// </summary>
/// <returns>Copy of the style.</returns>
public new SliceLabelVisualStyle Copy()
{
SliceLabelVisualStyle style = new SliceLabelVisualStyle();
CopyTo(style);
return (style);
}
#endregion
#region CopyTo
/// <summary>
/// Returns the copy of the style.
/// </summary>
/// <returns>Copy of the style.</returns>
public void CopyTo(SliceLabelVisualStyle style)
{
base.CopyTo(style);
style.Alignment = _Alignment;
style.AllowWrap = _AllowWrap;
style.Background = (_Background != null) ? _Background.Copy() : null;
style.Font = (_Font != null) ? (Font)_Font.Clone() : null;
style.MaxLineCount = _MaxLineCount;
style.TextColor = _TextColor;
}
#endregion
#region GetSerialData
internal override SerialElementCollection GetSerialData(string serialName)
{
SerialElementCollection sec = new SerialElementCollection();
if (serialName != null)
{
if (serialName.Equals("") == true)
serialName = "SliceLabelVisualStyle";
sec.AddStartElement(serialName);
}
sec.AddValue("Alignment", _Alignment, SliceLabelAlignment.NotSet);
sec.AddValue("AllowWrap", _AllowWrap, Tbool.NotSet);
if (_Background != null && _Background.IsEmpty == false)
sec.AddElement(_Background.GetSerialData("Background"));
if (_Font != null)
sec.AddValue("Font", XmlSerializableFont.ConvertToString(Font));
sec.AddValue("MaxLineCount", _MaxLineCount, 0);
sec.AddValue("TextColor", _TextColor, Color.Empty);
sec.AddElement(base.GetSerialData(null));
if (serialName != null)
sec.AddEndElement(serialName);
return (sec);
}
#endregion
#region PutSerialData
#region ProcessValue
internal override void ProcessValue(SerialElement se)
{
switch (se.Name)
{
case "AllowWrap":
AllowWrap = (Tbool)se.GetValueEnum(typeof(Tbool));
break;
case "Alignment":
Alignment = (SliceLabelAlignment)se.GetValueEnum(typeof(SliceLabelAlignment));
break;
case "Font":
Font = XmlSerializableFont.ConvertFromString(se.StringValue);
break;
case "MaxLineCount":
MaxLineCount = int.Parse(se.StringValue);
break;
case "TextColor":
TextColor = se.GetValueColor();
break;
default:
base.ProcessValue(se);
break;
}
}
#endregion
#region ProcessCollection
internal override void ProcessCollection(SerialElement se)
{
SerialElementCollection sec = se.Sec;
switch (se.Name)
{
case "Background":
sec.PutSerialData(Background);
break;
default:
base.ProcessCollection(se);
break;
}
}
#endregion
#endregion
#region IDisposable
/// <summary>
/// Dispose
/// </summary>
public override void Dispose()
{
Background = null;
base.Dispose();
}
#endregion
}
/// <summary>
/// Represents the visual style of a series Slice.
/// </summary>
[TypeConverter(typeof(VisualStylesConverter))]
public class SliceInnerLabelVisualStyle : SliceLabelVisualStyle
{
#region Private variables
private Tbool _AutoRotate = Tbool.NotSet;
private Tbool _AutoOrientLabel = Tbool.NotSet;
private double _AngleMargin = double.NaN;
private double _OuterRadiusOffset = double.NaN;
private double _InnerRadiusOffset = double.NaN;
private double _CustomAngleOffset = double.NaN;
private double _CustomRadiusOffset = double.NaN;
private double _CustomFontAngle = double.NaN;
private double _CustomWidth = double.NaN;
private double _CustomHeight = double.NaN;
private OuterRadiusOffsetBase _OuterRadiusOffsetBase = OuterRadiusOffsetBase.NotSet;
#endregion
#region Public properties
#region AngleMargin
/// <summary>
/// Gets or sets the margin (in degrees) to inset the label from
/// both the start and ending slice angles.
/// </summary>
[DefaultValue(double.NaN), Category("Appearance")]
[Description("Indicates the margin (in degrees) to inset the label from both the start and ending slice angles.")]
[Editor("DevComponents.Charts.Design.AngleMarginRangeValueEditor, DevComponents.Charts.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public double AngleMargin
{
get { return (_AngleMargin); }
set
{
if (value != _AngleMargin)
{
_AngleMargin = value;
OnPropertyChangedEx("AngleMargin", VisualChangeType.Layout);
}
}
}
#endregion
#region AutoOrientLabel
/// <summary>
/// Gets or sets whether the label will be auto oriented away from being upside down.
/// </summary>
[DefaultValue(Tbool.NotSet), Category("Behavior")]
[Description("Indicates whether the label will be auto oriented away from being upside down.")]
public Tbool AutoOrientLabel
{
get { return (_AutoOrientLabel); }
set
{
if (_AutoOrientLabel != value)
{
_AutoOrientLabel = value;
OnPropertyChangedEx("AutoOrientLabel", VisualChangeType.Layout);
}
}
}
#endregion
#region AutoRotate
/// <summary>
/// Gets or sets whether the label is auto rotated to match
/// the angle of the slice (only valid for 'Custom' orientation mode).
/// </summary>
[DefaultValue(Tbool.NotSet), Category("Display")]
[Description("Indicates whether the label is auto rotated to match the angle of the slice (only valid for 'Custom' orientation mode).")]
public Tbool AutoRotate
{
get { return (_AutoRotate); }
set
{
if (value != _AutoRotate)
{
_AutoRotate = value;
OnPropertyChangedEx("AutoRotate", VisualChangeType.Render);
}
}
}
#endregion
#region CustomAngleOffset
/// <summary>
/// Gets or sets the display angle offset for the label when
/// the label orientation is set to 'Custom'. The label can be
/// offset toward the end angle (positive offset) or toward
/// the start angle (negative offset). The offset is either a
/// percentage (if value is between 0 and 1) or pixel amount (if value > 1).
/// </summary>
[DefaultValue(double.NaN), Category("Display")]
[Description("Indicates the display angle offset for the label when the label orientation is set to 'Custom'. The label can be offset toward the end angle (positive offset) or toward the start angle (negative offset). The offset is either a percentage (if value is between 0 and 1) or pixel amount (if value > 1).")]
[Editor("DevComponents.Charts.Design.AngleOffsetRangeValueEditor, DevComponents.Charts.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public double CustomAngleOffset
{
get { return (_CustomAngleOffset); }
set
{
if (value != _CustomAngleOffset)
{
_CustomAngleOffset = value;
OnPropertyChangedEx("CustomAngleOffset", VisualChangeType.Render);
}
}
}
#endregion
#region CustomFontAngle
/// <summary>
/// Gets or sets the custom font angle when the label orientation
/// is set to 'Custom'. The FontAngle is the additional number of
/// degrees the label will be rotated.
/// </summary>
[DefaultValue(double.NaN), Category("Appearance")]
[Description("Indicates the custom font angle when the label orientation is set to 'Custom'. The FontAngle is the additional number of degrees the label will be rotated.")]
[Editor("DevComponents.Charts.Design.AngleRangeValueEditor, DevComponents.Charts.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public double CustomFontAngle
{
get { return (_CustomFontAngle); }
set
{
if (value != _CustomFontAngle)
{
_CustomFontAngle = value;
OnPropertyChangedEx("CustomFontAngle", VisualChangeType.Layout);
}
}
}
#endregion
#region CustomHeight
/// <summary>
/// Gets or sets the height of the bounding rectangle for the label when
/// the label orientation is set to 'Custom'. The height can be a percentage
/// of the slice height (if the value is between 0 and 1), or an absolute
/// pixel amount (if the value is > 1).
/// </summary>
[DefaultValue(double.NaN), Category("Display")]
[Description("Indicates the height of the bounding rectangle for the label when the label orientation is set to 'Custom'. The height can be a percentage of the slice height (if the value is between 0 and 1), or an absolute pixel amount (if the value is > 1).")]
[Editor("DevComponents.Charts.Design.RadiusRangeValueEditor, DevComponents.Charts.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public double CustomHeight
{
get { return (_CustomHeight); }
set
{
if (value != _CustomHeight)
{
_CustomHeight = value;
OnPropertyChangedEx("CustomHeight", VisualChangeType.Render);
}
}
}
#endregion
#region CustomRadiusOffset
/// <summary>
/// Gets or sets the display radius offset for the label when the label orientation
/// is set to 'Custom. The label can be offset toward the outer radius
/// (positive offset) or toward the inner radius (negative offset). The
/// offset can either be a percentage (if value is between 0 and 1) or pixel
/// amount (if value > 1).
/// </summary>
[DefaultValue(double.NaN), Category("Display")]
[Description("Indicates the display radius offset for the label when the label orientation is set to 'Custom. The label can be offset toward the outer radius (positive offset) or toward the inner radius (negative offset). The offset can either be a percentage (if value is between 0 and 1) or pixel amount (if value > 1)..")]
[Editor("DevComponents.Charts.Design.RadiusRangeValueEditor, DevComponents.Charts.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public double CustomRadiusOffset
{
get { return (_CustomRadiusOffset); }
set
{
if (value != _CustomRadiusOffset)
{
_CustomRadiusOffset = value;
OnPropertyChangedEx("CustomRadiusOffset", VisualChangeType.Render);
}
}
}
#endregion
#region CustomWidth
/// <summary>
/// Gets or sets the custom width for the bounding rectangle of the
/// label when the label orientation is set to 'Custom'. The width can
/// be a percentage of the slice width at the set RadiusOffset
/// (if the value is between 0 and 1), or an absolute pixel amount (if the
/// value is > 1).
/// </summary>
[DefaultValue(double.NaN), Category("Display")]
[Description("Indicates the custom width for the bounding rectangle of the label when the label orientation is set to 'Custom'. The width can be a percentage of the slice width at the set RadiusOffset (if the value is between 0 and 1), or an absolute pixel amount (if the value is > 1).")]
[Editor("DevComponents.Charts.Design.RadiusRangeValueEditor, DevComponents.Charts.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public double CustomWidth
{
get { return (_CustomWidth); }
set
{
if (value != _CustomWidth)
{
_CustomWidth = value;
OnPropertyChangedEx("CustomWidth", VisualChangeType.Render);
}
}
}
#endregion
#region InnerRadiusOffset
/// <summary>
/// Gets or sets the offset of the inner edge of the rectangular label area from the
/// outer slice radius, as measured by a percentage of the slice radius
/// (if less than 1), or absolute pixel amount (if greater than 1).
/// </summary>
[DefaultValue(double.NaN), Category("Display")]
[Description("Indicates the offset of the inner edge of the rectangular label area from the outer slice radius, as measured by a percentage of the slice radius (if less than 1), or absolute pixel amount (if greater than 1).")]
[Editor("DevComponents.Charts.Design.RadiusRangeValueEditor, DevComponents.Charts.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public double InnerRadiusOffset
{
get { return (_InnerRadiusOffset); }
set
{
if (value != _InnerRadiusOffset)
{
_InnerRadiusOffset = value;
OnPropertyChangedEx("InnerRadiusOffset", VisualChangeType.Layout);
}
}
}
#endregion
#region OuterRadiusOffset
/// <summary>
/// Gets or sets the offset of the outer edge of the rectangular label area from the
/// outer slice radius, as measured by a percentage of the slice radius
/// (if less than 1), or absolute pixel amount (if greater than 1).
/// </summary>
[DefaultValue(double.NaN), Category("Display")]
[Description("Indicates the offset of the outer edge of the rectangular label area from the outer slice radius, as measured by a percentage of the slice radius (if less than 1), or absolute pixel amount (if greater than 1).")]
[Editor("DevComponents.Charts.Design.RadiusRangeValueEditor, DevComponents.Charts.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
public double OuterRadiusOffset
{
get { return (_OuterRadiusOffset); }
set
{
if (value != _OuterRadiusOffset)
{
_OuterRadiusOffset = value;
OnPropertyChangedEx("OuterRadiusOffset", VisualChangeType.Layout);
}
}
}
#endregion
#region OuterRadiusOffsetBase
/// <summary>
/// Gets or sets whether the label's OuterRadiusOffset is relative
/// to the slice OuterRadius or the slice ExtentRadius.
/// </summary>
[Category("Behavior"), DefaultValue(OuterRadiusOffsetBase.NotSet)]
[Description("Indicates whether the label's OuterRadiusOffset is relative to the slice OuterRadius or the slice ExtentRadius.")]
public OuterRadiusOffsetBase OuterRadiusOffsetBase
{
get { return (_OuterRadiusOffsetBase); }
set
{
if (_OuterRadiusOffsetBase != value)
{
_OuterRadiusOffsetBase = value;
OnPropertyChangedEx("OuterRadiusOffsetBase", VisualChangeType.Layout);
}
}
}
#endregion
#region IsEmpty
/// <summary>
/// Gets whether the style is logically Empty.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("Gets whether the style is logically Empty.")]
public override bool IsEmpty
{
get
{
return ((double.IsNaN(_AngleMargin) == true) &&
(_AutoOrientLabel == Tbool.NotSet) &&
(_AutoRotate == Tbool.NotSet) &&
(double.IsNaN(_CustomAngleOffset) == true) &&
(double.IsNaN(_CustomHeight) == true) &&
(double.IsNaN(_CustomRadiusOffset) == true) &&
(double.IsNaN(_CustomWidth) == true) &&
(double.IsNaN(_CustomFontAngle) == true) &&
(double.IsNaN(_InnerRadiusOffset) == true) &&
(double.IsNaN(_OuterRadiusOffset) == true) &&
(_OuterRadiusOffsetBase == OuterRadiusOffsetBase.NotSet) &&
(base.IsEmpty == true));
}
}
#endregion
#endregion
#region ApplyStyle
/// <summary>
/// Applies the style to instance of this style.
/// </summary>
/// <param name="style">Style to apply.</param>
public void ApplyStyle(SliceInnerLabelVisualStyle style)
{
if (style != null)
{
base.ApplyStyle(style);
if (double.IsNaN(style._AngleMargin) == false)
AngleMargin = style._AngleMargin;
if (style.AutoOrientLabel != Tbool.NotSet)
AutoOrientLabel = style._AutoOrientLabel;
if (style._AutoRotate != Tbool.NotSet)
AutoRotate = style._AutoRotate;
if (double.IsNaN(style._CustomAngleOffset) == false)
CustomAngleOffset = style._CustomAngleOffset;
if (double.IsNaN(style._CustomHeight) == false)
CustomHeight = style._CustomHeight;
if (double.IsNaN(style._CustomRadiusOffset) == false)
CustomRadiusOffset = style._CustomRadiusOffset;
if (double.IsNaN(style._CustomWidth) == false)
CustomWidth = style._CustomWidth;
if (double.IsNaN(style._CustomFontAngle) == false)
CustomFontAngle = style._CustomFontAngle;
if (double.IsNaN(style._InnerRadiusOffset) == false)
InnerRadiusOffset = style._InnerRadiusOffset;
if (double.IsNaN(style._OuterRadiusOffset) == false)
OuterRadiusOffset = style._OuterRadiusOffset;
if (style.OuterRadiusOffsetBase != OuterRadiusOffsetBase.NotSet)
OuterRadiusOffsetBase = style._OuterRadiusOffsetBase;
}
}
#endregion
#region ApplyDefaults
public override void ApplyDefaults()
{
if (_AutoRotate == Tbool.NotSet)
_AutoRotate = Tbool.False;
if (double.IsNaN(_CustomFontAngle) == true)
_CustomFontAngle = 0;
if (double.IsNaN(_AngleMargin) == true)
_AngleMargin = 1;
if (_AutoOrientLabel == Tbool.NotSet)
_AutoOrientLabel = Tbool.True;
if (double.IsNaN(_InnerRadiusOffset) == true)
_InnerRadiusOffset = .1;
if (double.IsNaN(_OuterRadiusOffset) == true)
_OuterRadiusOffset = -.05;
if (_OuterRadiusOffsetBase == OuterRadiusOffsetBase.NotSet)
_OuterRadiusOffsetBase = OuterRadiusOffsetBase.ExtentRadius;
base.ApplyDefaults();
}
#endregion
#region Copy
/// <summary>
/// Returns the copy of the style.
/// </summary>
/// <returns>Copy of the style.</returns>
public new SliceInnerLabelVisualStyle Copy()
{
SliceInnerLabelVisualStyle style = new SliceInnerLabelVisualStyle();
CopyTo(style);
return (style);
}
#endregion
#region CopyTo
/// <summary>
/// Returns the copy of the style.
/// </summary>
/// <returns>Copy of the style.</returns>
public void CopyTo(SliceInnerLabelVisualStyle style)
{
base.CopyTo(style);
style.AngleMargin = _AngleMargin;
style.AutoOrientLabel = _AutoOrientLabel;
style.AutoRotate = _AutoRotate;
style.CustomAngleOffset = _CustomAngleOffset;
style.CustomHeight = _CustomHeight;
style.CustomRadiusOffset = _CustomRadiusOffset;
style.CustomWidth = _CustomWidth;
style.CustomFontAngle = _CustomFontAngle;
style.InnerRadiusOffset = _InnerRadiusOffset;
style.OuterRadiusOffset = _OuterRadiusOffset;
style.OuterRadiusOffsetBase = _OuterRadiusOffsetBase;
}
#endregion
#region GetSerialData
internal override SerialElementCollection GetSerialData(string serialName)
{
SerialElementCollection sec = new SerialElementCollection();
if (serialName != null)
{
if (serialName.Equals("") == true)
serialName = "SliceInnerLabelVisualStyle";
sec.AddStartElement(serialName);
}
sec.AddValue("AngleMargin", AngleMargin, double.NaN);
sec.AddValue("AutoOrientLabel", AutoOrientLabel, Tbool.NotSet);
sec.AddValue("AutoRotate", AutoRotate, Tbool.NotSet);
sec.AddValue("CustomAngleOffset", CustomAngleOffset, double.NaN);
sec.AddValue("CustomHeight", CustomHeight, double.NaN);
sec.AddValue("CustomRadiusOffset", CustomRadiusOffset, double.NaN);
sec.AddValue("CustomWidth", CustomWidth, double.NaN);
sec.AddValue("CustomFontAngle", CustomFontAngle, double.NaN);
sec.AddValue("InnerRadiusOffset", InnerRadiusOffset, double.NaN);
sec.AddValue("OuterRadiusOffset", OuterRadiusOffset, double.NaN);
sec.AddValue("OuterRadiusOffsetBase", OuterRadiusOffsetBase, OuterRadiusOffsetBase.NotSet);
sec.AddElement(base.GetSerialData(null));
if (serialName != null)
sec.AddEndElement(serialName);
return (sec);
}
#endregion
#region PutSerialData
#region ProcessValue
internal override void ProcessValue(SerialElement se)
{
switch (se.Name)
{
case "AngleMargin":
AngleMargin = double.Parse(se.StringValue);
break;
case "AutoOrientLabel":
AutoOrientLabel = (Tbool)se.GetValueEnum(typeof(Tbool));
break;
case "AutoRotate":
AutoRotate = (Tbool)se.GetValueEnum(typeof(Tbool));
break;
case "CustomAngleOffset":
CustomAngleOffset = double.Parse(se.StringValue);
break;
case "CustomFontAngle":
CustomFontAngle = double.Parse(se.StringValue);
break;
case "CustomHeight":
CustomHeight = double.Parse(se.StringValue);
break;
case "CustomRadiusOffset":
CustomRadiusOffset = double.Parse(se.StringValue);
break;
case "CustomWidth":
CustomWidth = double.Parse(se.StringValue);
break;
case "InnerRadiusOffset":
InnerRadiusOffset = double.Parse(se.StringValue);
break;
case "OuterRadiusOffset":
OuterRadiusOffset = double.Parse(se.StringValue);
break;
case "OuterRadiusOffsetBase":
OuterRadiusOffsetBase = (OuterRadiusOffsetBase)se.GetValueEnum(typeof(OuterRadiusOffsetBase));
break;
default:
base.ProcessValue(se);
break;
}
}
#endregion
#region ProcessCollection
internal override void ProcessCollection(SerialElement se)
{
SerialElementCollection sec = se.Sec;
switch (se.Name)
{
default:
base.ProcessCollection(se);
break;
}
}
#endregion
#endregion
#region IDisposable
/// <summary>
/// Dispose
/// </summary>
public override void Dispose()
{
base.Dispose();
}
#endregion
}
/// <summary>
/// Represents the visual style of a series Slice.
/// </summary>
[TypeConverter(typeof(VisualStylesConverter))]
public class SliceOuterLabelVisualStyle : SliceLabelVisualStyle
{
#region Private variables
private double _MaxLabelHeight = double.NaN;
private double _MaxLabelWidth = double.NaN;
private double _MinLabelHeight = double.NaN;
private double _MinLabelWidth = double.NaN;
private int _LabelMargin = -1;
private Tbool _DrawConnector = Tbool.NotSet;
private Color _ConnectorColor = Color.Empty;
private LinePattern _ConnectorPattern = LinePattern.NotSet;
private int _ConnectorLength = -1;
private int _ConnectorTickLength = -1;
private int _ConnectorThickness = -1;
private ChartLineVisualStyle _Border;
private Padding _Padding;
#endregion
#region Public properties
#region Border
/// <summary>
/// Gets or sets the visual style for the label border.
/// </summary>
[Category("Style")]
[Description("Indicates the visual styles for the label border.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ChartLineVisualStyle Border
{
get
{
if (_Border == null)
{
_Border = new ChartLineVisualStyle();
UpdateChangeHandler(null, _Border);
}
return (_Border);
}
set
{
if (_Border != value)
{
ChartLineVisualStyle oldValue = _Border;
_Border = value;
OnStyleChanged("Border", oldValue, value);
if (oldValue != null)
oldValue.Dispose();
}
}
}
#endregion
#region ConnectorColor
/// <summary>
/// Gets or sets the style connector color.
/// </summary>
[Description("Indicates the style connector color"), Category("Appearance")]
public Color ConnectorColor
{
get { return (_ConnectorColor); }
set
{
if (value != _ConnectorColor)
{
_ConnectorColor = value;
OnPropertyChangedEx("ConnectorColor", VisualChangeType.Render);
}
}
}
/// <summary>
/// Gets whether property should be serialized.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
private bool ShouldSerializeConnectorColor()
{
return (_ConnectorColor.IsEmpty == false);
}
/// <summary>
/// Resets property to its default value.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
private void ResetConnectorColor()
{
_ConnectorColor = Color.Empty;
}
#endregion
#region ConnectorLength
/// <summary>
/// Gets or sets the length of the line connecting the slice
/// and the slice label.
/// </summary>
[DefaultValue(-1), Category("Appearance")]
[Description("Indicates the length of the line connecting the slice and the slice label.")]
public int ConnectorLength
{
get { return (_ConnectorLength); }
set
{
if (value != _ConnectorLength)
{
if (value < 0)
throw new InvalidPropertyValueException("value cannot be negative.");
_ConnectorLength = value;
OnPropertyChangedEx("ConnectorLength", VisualChangeType.Layout);
}
}
}
#endregion
#region ConnectorPattern
/// <summary>
/// Gets or sets the style border pattern (Solid, Dash, ...)
/// </summary>
[Description("Indicates the style border pattern (Solid, Dash, ...)")]
[DefaultValue(LinePattern.NotSet), Category("Appearance")]
public LinePattern ConnectorPattern
{
get { return (_ConnectorPattern); }
set
{
if (value != _ConnectorPattern)
{
_ConnectorPattern = value;
OnPropertyChangedEx("ConnectorPattern", VisualChangeType.Render);
}
}
}
#endregion
#region ConnectorThickness
/// <summary>
/// Gets or sets the style connector thickness.
/// </summary>
[DefaultValue(-1), Category("Appearance")]
[Description("Indicates the style connector thickness.")]
public int ConnectorThickness
{
get { return (_ConnectorThickness); }
set
{
if (value != _ConnectorThickness)
{
_ConnectorThickness = value;
OnPropertyChangedEx("ConnectorThickness", VisualChangeType.Render);
}
}
}
#endregion
#region ConnectorTickLength
/// <summary>
/// Gets or sets the length of the 'tick' line connecting the
/// label text with the main connector line associated with the pie slice.
/// </summary>
[DefaultValue(-1), Category("Appearance")]
[Description("Indicates the length of the length of the 'tick' line connecting the label text with the main connector line associated with the pie slice.")]
public int ConnectorTickLength
{
get { return (_ConnectorTickLength); }
set
{
if (value != _ConnectorTickLength)
{
if (value < 0)
throw new InvalidPropertyValueException("value cannot be negative.");
_ConnectorTickLength = value;
OnPropertyChangedEx("ConnectorTickLength", VisualChangeType.Layout);
}
}
}
#endregion
#region DrawConnector
///<summary>
/// Gets or sets whether a connecting line is drawn from the slice
/// to the outer slice label.
///</summary>
[DefaultValue(Tbool.NotSet), Category("Appearance")]
[Description("Indicates whether a connecting line is drawn from the slice to the outer slice label.")]
public Tbool DrawConnector
{
get { return (_DrawConnector); }
set
{
if (value != _DrawConnector)
{
_DrawConnector = value;
OnPropertyChangedEx("DrawConnector", Style.VisualChangeType.Layout);
}
}
}
#endregion
#region LabelMargin
/// <summary>
/// Gets or sets the pixel margin between the outer label
/// and the chart outer radius, as well as between the label and
/// any adjacent slice labels.
/// </summary>
[DefaultValue(-1), Category("Appearance")]
[Description("Indicates the pixel margin between the outer label and the chart outer radius, as well as between the label and any adjacent slice labels.")]
public int LabelMargin
{
get { return (_LabelMargin); }
set
{
if (value != _LabelMargin)
{
_LabelMargin = value;
OnPropertyChangedEx("LabelMargin", VisualChangeType.Layout);
}
}
}
#endregion
#region MaxLabelHeight
/// <summary>
/// Gets or sets the maximum vertical size of the label, as
/// measured by a percentage of the chart height (if less than 1),
/// or absolute pixel amount (if greater than 1).
/// </summary>
[DefaultValue(double.NaN), Category("Appearance")]
[Description("Indicates the maximum vertical size of the label, as measured by a percentage of the chart height (if less than 1), or absolute pixel amount (if greater than 1).")]
public double MaxLabelHeight
{
get { return (_MaxLabelHeight); }
set
{
if (value != _MaxLabelHeight)
{
if (value < 0)
throw new ArgumentOutOfRangeException("value", "Must be greater than zero.");
_MaxLabelHeight = value;
OnPropertyChangedEx("MaxLabelHeight", VisualChangeType.Layout);
}
}
}
#endregion
#region MaxLabelWidth
/// <summary>
/// Gets or sets the maximum horizontal size of the label, as
/// measured by a percentage of the chart width (if less than 1),
/// or absolute pixel amount (if greater than 1).
/// </summary>
[DefaultValue(double.NaN), Category("Appearance")]
[Description("Indicates the maximum horizontal size of the label, as measured by a percentage of the chart width (if less than 1), or absolute pixel amount (if greater than 1).")]
public double MaxLabelWidth
{
get { return (_MaxLabelWidth); }
set
{
if (value != _MaxLabelWidth)
{
if (value < 0)
throw new ArgumentOutOfRangeException("value", "Must be greater than zero.");
_MaxLabelWidth = value;
OnPropertyChangedEx("MaxLabelWidth", VisualChangeType.Layout);
}
}
}
#endregion
#region MinLabelHeight
/// <summary>
/// Gets or sets the Minimum vertical size of the label, as
/// measured by a percentage of the chart height (if less than 1),
/// or absolute pixel amount (if greater than 1).
/// </summary>
[DefaultValue(double.NaN), Category("Appearance")]
[Description("Indicates the Minimum vertical size of the label, as measured by a percentage of the chart height (if less than 1), or absolute pixel amount (if greater than 1).")]
public double MinLabelHeight
{
get { return (_MinLabelHeight); }
set
{
if (value != _MinLabelHeight)
{
if (value < 0)
throw new ArgumentOutOfRangeException("value", "Must be greater than zero.");
_MinLabelHeight = value;
OnPropertyChangedEx("MinLabelHeight", VisualChangeType.Layout);
}
}
}
#endregion
#region MinLabelWidth
/// <summary>
/// Gets or sets the minimum horizontal size of the label, as
/// measured by a percentage of the chart width (if less than 1),
/// or absolute pixel amount (if greater than 1).
/// </summary>
[DefaultValue(double.NaN), Category("Appearance")]
[Description("Indicates the minimum horizontal size of the label, as measured by a percentage of the chart width (if less than 1), or absolute pixel amount (if greater than 1).")]
public double MinLabelWidth
{
get { return (_MinLabelWidth); }
set
{
if (value != _MinLabelWidth)
{
if (value < 0)
throw new ArgumentOutOfRangeException("value", "Must be greater than zero.");
_MinLabelWidth = value;
OnPropertyChangedEx("MinLabelWidth", VisualChangeType.Layout);
}
}
}
#endregion
#region Padding
/// <summary>
/// Gets or sets spacing between the content and edges of the element.
/// </summary>
[Description("Indicates the spacing between the content and edges of the element")]
public Padding Padding
{
get
{
if (_Padding == null)
{
_Padding = Padding.Empty;
UpdateChangeHandler(null, _Padding);
}
return (_Padding);
}
set
{
if (_Padding != value)
{
UpdateChangeHandler(_Padding, value);
_Padding = value;
OnPropertyChangedEx("Padding", VisualChangeType.Layout);
}
}
}
/// <summary>
/// Gets whether property should be serialized.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
private bool ShouldSerializePadding()
{
return (_Padding != null && _Padding.IsEmpty == false);
}
/// <summary>
/// Resets property to its default value.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
private void ResetPadding()
{
Padding = null;
}
#endregion
#region IsEmpty
/// <summary>
/// Gets whether the style is logically Empty.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("Gets whether the style is logically Empty.")]
public override bool IsEmpty
{
get
{
return ((_Border == null || _Border.IsEmpty == true) &&
(_ConnectorColor == Color.Empty) &&
(_ConnectorLength == -1) &&
(_ConnectorPattern == LinePattern.NotSet) &&
(_ConnectorThickness == -1) &&
(_ConnectorTickLength == -1) &&
(_DrawConnector == Tbool.NotSet) &&
(_LabelMargin == -1) &&
(_Padding == null || _Padding.IsEmpty == true) &&
(double.IsNaN(_MaxLabelHeight) == true) &&
(double.IsNaN(_MaxLabelWidth) == true) &&
(double.IsNaN(_MinLabelHeight) == true) &&
(double.IsNaN(_MinLabelWidth) == true) &&
(base.IsEmpty == true));
}
}
#endregion
#endregion
#region ApplyStyle
/// <summary>
/// Applies the style to instance of this style.
/// </summary>
/// <param name="style">Style to apply.</param>
public void ApplyStyle(SliceOuterLabelVisualStyle style)
{
if (style != null)
{
base.ApplyStyle(style);
if (style._Border != null && style._Border.IsEmpty == false)
Border = style._Border.Copy();
if (style.ConnectorColor != Color.Empty)
_ConnectorColor = style.ConnectorColor;
if (style.ConnectorLength != -1)
_ConnectorLength = style.ConnectorLength;
if (style.ConnectorPattern != LinePattern.NotSet)
_ConnectorPattern = style.ConnectorPattern;
if (style.ConnectorThickness != -1)
_ConnectorThickness = style.ConnectorThickness;
if (style.ConnectorTickLength != -1)
_ConnectorTickLength = style.ConnectorTickLength;
if (style.DrawConnector != Tbool.NotSet)
_DrawConnector = style.DrawConnector;
if (style.LabelMargin != -1)
_LabelMargin = style.LabelMargin;
if (double.IsNaN(style._MaxLabelHeight) == false)
_MaxLabelHeight = style._MaxLabelHeight;
if (double.IsNaN(style._MaxLabelWidth) == false)
_MaxLabelWidth = style._MaxLabelWidth;
if (double.IsNaN(style._MinLabelHeight) == false)
_MinLabelHeight = style._MinLabelHeight;
if (double.IsNaN(style._MinLabelWidth) == false)
_MinLabelWidth = style._MinLabelWidth;
if (style._Padding != null && style._Padding.IsEmpty == false)
Padding = style._Padding.Copy();
}
}
#endregion
#region ApplyDefaults
public override void ApplyDefaults()
{
if (_ConnectorColor == Color.Empty)
_ConnectorColor = Color.Gray;
if (_ConnectorLength == -1)
_ConnectorLength = 15;
if (_ConnectorPattern == LinePattern.NotSet)
_ConnectorPattern = LinePattern.Solid;
if (_ConnectorThickness == -1)
_ConnectorThickness = 1;
if (_ConnectorTickLength == -1)
_ConnectorTickLength = 10;
if (_DrawConnector == Tbool.NotSet)
_DrawConnector = Tbool.True;
if (double.IsNaN(_MaxLabelHeight) == true)
_MaxLabelHeight = .25;
if (double.IsNaN(_MaxLabelWidth) == true)
_MaxLabelWidth = .25;
if (_LabelMargin == -1)
_LabelMargin = 10;
base.ApplyDefaults();
}
#endregion
#region Copy
/// <summary>
/// Returns the copy of the style.
/// </summary>
/// <returns>Copy of the style.</returns>
public new SliceOuterLabelVisualStyle Copy()
{
SliceOuterLabelVisualStyle style = new SliceOuterLabelVisualStyle();
CopyTo(style);
return (style);
}
#endregion
#region CopyTo
/// <summary>
/// Returns the copy of the style.
/// </summary>
/// <returns>Copy of the style.</returns>
public void CopyTo(SliceOuterLabelVisualStyle style)
{
base.CopyTo(style);
style.Border = (_Border != null) ? _Border.Copy() : null;
style.ConnectorColor = _ConnectorColor;
style.ConnectorLength = _ConnectorLength;
style.ConnectorPattern = _ConnectorPattern;
style.ConnectorThickness = _ConnectorThickness;
style.ConnectorTickLength = _ConnectorTickLength;
style.DrawConnector = _DrawConnector;
style.LabelMargin = _LabelMargin;
style.Padding = (_Padding == null) ? null : _Padding.Copy();
style.MaxLabelHeight = _MaxLabelHeight;
style.MaxLabelWidth = _MaxLabelWidth;
style.MinLabelHeight = _MinLabelHeight;
style.MinLabelWidth = _MinLabelWidth;
}
#endregion
#region GetSerialData
internal override SerialElementCollection GetSerialData(string serialName)
{
SerialElementCollection sec = new SerialElementCollection();
if (serialName != null)
{
if (serialName.Equals("") == true)
serialName = "ChartSliceVisualStyle";
sec.AddStartElement(serialName);
}
if (_Border != null && _Border.IsEmpty == false)
sec.AddElement(_Border.GetSerialData("Border"));
sec.AddValue("ConnectorColor", ConnectorColor, Color.Empty);
sec.AddValue("ConnectorLength", ConnectorLength, -1);
sec.AddValue("ConnectorPattern", ConnectorPattern, LinePattern.NotSet);
sec.AddValue("ConnectorThickness", ConnectorThickness, -1);
sec.AddValue("ConnectorTickLength", ConnectorTickLength, -1);
sec.AddValue("DrawConnector", DrawConnector, Tbool.NotSet);
sec.AddValue("LabelMargin", LabelMargin, -1);
if (_Padding != null && _Padding.IsEmpty == false)
sec.AddElement(_Padding.GetSerialData("Padding"));
sec.AddValue("MaxLabelHeight", MaxLabelHeight, double.NaN);
sec.AddValue("MaxLabelWidth", MaxLabelWidth, double.NaN);
sec.AddValue("MinLabelHeight", MinLabelHeight, double.NaN);
sec.AddValue("MinLabelWidth", MinLabelWidth, double.NaN);
sec.AddElement(base.GetSerialData(null));
if (serialName != null)
sec.AddEndElement(serialName);
return (sec);
}
#endregion
#region PutSerialData
#region ProcessValue
internal override void ProcessValue(SerialElement se)
{
switch (se.Name)
{
case "ConnectorColor":
ConnectorColor = se.GetValueColor();
break;
case "ConnectorLength":
ConnectorLength = int.Parse(se.StringValue);
break;
case "ConnectorPattern":
ConnectorPattern = (LinePattern)se.GetValueEnum(typeof(LinePattern));
break;
case "ConnectorThickness":
ConnectorThickness = int.Parse(se.StringValue);
break;
case "ConnectorTickLength":
ConnectorTickLength = int.Parse(se.StringValue);
break;
case "DrawConnector":
DrawConnector = (Tbool)se.GetValueEnum(typeof(Tbool));
break;
case "MaxLabelHeight":
MaxLabelHeight = double.Parse(se.StringValue);
break;
case "MaxLabelWidth":
MaxLabelWidth = double.Parse(se.StringValue);
break;
case "MinLabelHeight":
MinLabelHeight = double.Parse(se.StringValue);
break;
case "MinLabelWidth":
MinLabelWidth = double.Parse(se.StringValue);
break;
default:
base.ProcessValue(se);
break;
}
}
#endregion
#region ProcessCollection
internal override void ProcessCollection(SerialElement se)
{
SerialElementCollection sec = se.Sec;
switch (se.Name)
{
case "Border":
sec.PutSerialData(Border);
break;
case "Padding":
se.Sec.PutSerialData(Padding);
break;
default:
base.ProcessCollection(se);
break;
}
}
#endregion
#endregion
#region IDisposable
/// <summary>
/// Dispose
/// </summary>
public override void Dispose()
{
Border = null;
Padding = null;
base.Dispose();
}
#endregion
}
#region OuterRadiusOffsetBase
/// <summary>
/// Defines what the label's OuterRadiusOffset is relative
/// to (slice OuterRadius or slice ExtentRadius).
/// </summary>
public enum OuterRadiusOffsetBase
{
/// <summary>
/// NotSet
/// </summary>
NotSet = -1,
/// <summary>
/// OuterRadius
/// </summary>
OuterRadius,
/// <summary>
/// ExtentRadius (default)
/// </summary>
ExtentRadius,
}
#endregion
#region SliceLabelAlignment
/// <summary>
/// SliceLabelAlignment
/// </summary>
public enum SliceLabelAlignment
{
///<summary>
/// NotSet
///</summary>
NotSet = -1,
///<summary>
/// OuterLeft
///</summary>
OuterLeft,
///<summary>
/// OuterCenter
///</summary>
OuterCenter,
///<summary>
/// OuterRight
///</summary>
OuterRight,
///<summary>
/// MiddleLeft
///</summary>
MiddleLeft,
///<summary>
/// MiddleCenter
///</summary>
MiddleCenter,
/// <summary>
/// MiddleRight
/// </summary>
MiddleRight,
/// <summary>
/// InnerLeft
/// </summary>
InnerLeft,
/// <summary>
/// InnerCenter
/// </summary>
InnerCenter,
/// <summary>
/// InnerRight
/// </summary>
InnerRight,
}
#endregion
}