You've already forked linux-packaging-mono
Rewrite with hard-coded offsets into the PE file format to discern if a binary is PE32 or PE32+, and then to determine if it contains a "CLR Data Directory" entry that looks valid. Tested with PE32 and PE32+ compiled Mono binaries, PE32 and PE32+ native binaries, and a random assortment of garbage files. Former-commit-id: 9e7ac86ec84f653a2f79b87183efd5b0ebda001b
3003 lines
108 KiB
C#
3003 lines
108 KiB
C#
//-------------------------------------------------------------
|
||
// <copyright company=’Microsoft Corporation’>
|
||
// Copyright © Microsoft Corporation. All Rights Reserved.
|
||
// </copyright>
|
||
//-------------------------------------------------------------
|
||
// @owner=alexgor, deliant
|
||
//=================================================================
|
||
// File: LabelStyle.cs
|
||
//
|
||
// Namespace: DataVisualization.Charting
|
||
//
|
||
// Classes: CustomLabelsCollection, CustomLabel, LabelStyle
|
||
//
|
||
// Purpose: LabelStyle and CustomLabel classes are used to determine
|
||
// chart axis labels. Labels can be automatically
|
||
// generated based on the series data or be “manually”
|
||
// set by the user.
|
||
//
|
||
// Reviewed: AG - Jul 31, 2002
|
||
// AG - Microsoft 14, 2007
|
||
//
|
||
//===================================================================
|
||
|
||
#region Used namespaces
|
||
|
||
using System;
|
||
using System.Collections;
|
||
using System.Collections.Specialized;
|
||
using System.Collections.Generic;
|
||
using System.ComponentModel;
|
||
using System.ComponentModel.Design;
|
||
using System.Data;
|
||
using System.Drawing;
|
||
using System.Drawing.Design;
|
||
using System.Drawing.Drawing2D;
|
||
using System.Drawing.Text;
|
||
|
||
#if Microsoft_CONTROL
|
||
using System.Windows.Forms.DataVisualization.Charting.Data;
|
||
using System.Windows.Forms.DataVisualization.Charting.ChartTypes;
|
||
using System.Windows.Forms.DataVisualization.Charting.Utilities;
|
||
using System.Windows.Forms.DataVisualization.Charting.Borders3D;
|
||
using System.Windows.Forms.DataVisualization.Charting;
|
||
using System.Globalization;
|
||
using System.ComponentModel.Design.Serialization;
|
||
using System.Reflection;
|
||
#else
|
||
using System.Web;
|
||
using System.Web.UI;
|
||
using System.Web.UI.DataVisualization.Charting;
|
||
using System.Web.UI.DataVisualization.Charting.Data;
|
||
using System.Web.UI.DataVisualization.Charting.Utilities;
|
||
using System.Web.UI.DataVisualization.Charting.ChartTypes;
|
||
#endif
|
||
|
||
#endregion
|
||
|
||
#if Microsoft_CONTROL
|
||
namespace System.Windows.Forms.DataVisualization.Charting
|
||
#else
|
||
namespace System.Web.UI.DataVisualization.Charting
|
||
#endif
|
||
{
|
||
#region Labels enumerations
|
||
|
||
/// <summary>
|
||
/// An enumeration that specifies a mark for custom labels.
|
||
/// </summary>
|
||
public enum LabelMarkStyle
|
||
{
|
||
/// <summary>
|
||
/// No label marks are used.
|
||
/// </summary>
|
||
None,
|
||
|
||
/// <summary>
|
||
/// Labels use side marks.
|
||
/// </summary>
|
||
SideMark,
|
||
|
||
/// <summary>
|
||
/// Labels use line and side marks.
|
||
/// </summary>
|
||
LineSideMark,
|
||
|
||
|
||
/// <summary>
|
||
/// Draws a box around the label. The box always starts at the axis position.
|
||
/// </summary>
|
||
Box
|
||
};
|
||
|
||
|
||
/// <summary>
|
||
/// An enumeration of custom grid lines and tick marks flags used in the custom labels.
|
||
/// </summary>
|
||
[Flags]
|
||
public enum GridTickTypes
|
||
{
|
||
/// <summary>
|
||
/// No tick mark or grid line are shown.
|
||
/// </summary>
|
||
None = 0,
|
||
|
||
/// <summary>
|
||
/// Tick mark is shown.
|
||
/// </summary>
|
||
TickMark = 1,
|
||
|
||
/// <summary>
|
||
/// Grid line is shown.
|
||
/// </summary>
|
||
Gridline = 2,
|
||
|
||
/// <summary>
|
||
/// Tick mark and grid line are shown.
|
||
/// </summary>
|
||
All = TickMark | Gridline
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// An enumeration of label styles for circular chart area axis.
|
||
/// </summary>
|
||
internal enum CircularAxisLabelsStyle
|
||
{
|
||
/// <summary>
|
||
/// Style depends on number of labels.
|
||
/// </summary>
|
||
Auto,
|
||
|
||
/// <summary>
|
||
/// Label text positions around the circular area.
|
||
/// </summary>
|
||
Circular,
|
||
|
||
/// <summary>
|
||
/// Label text is always horizontal.
|
||
/// </summary>
|
||
Horizontal,
|
||
|
||
/// <summary>
|
||
/// Label text has the same angle as circular axis.
|
||
/// </summary>
|
||
Radial
|
||
}
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// The CustomLabelsCollection class is a strongly typed collection of
|
||
/// custom axis labels.
|
||
/// </summary>
|
||
[
|
||
SRDescription("DescriptionAttributeCustomLabelsCollection_CustomLabelsCollection"),
|
||
]
|
||
#if ASPPERM_35
|
||
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
||
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
||
#endif
|
||
public class CustomLabelsCollection : ChartElementCollection<CustomLabel>
|
||
{
|
||
#region Constructors
|
||
|
||
/// <summary>
|
||
/// Custom labels collection object constructor
|
||
/// </summary>
|
||
/// <param name="axis">Reference to the axis object.</param>
|
||
internal CustomLabelsCollection(Axis axis) : base(axis)
|
||
{
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Properties
|
||
internal Axis Axis
|
||
{
|
||
get { return Parent as Axis; }
|
||
}
|
||
#endregion
|
||
|
||
#region Labels adding methods
|
||
|
||
/// <summary>
|
||
/// Adds a custom label into the collection.
|
||
/// </summary>
|
||
/// <param name="fromPosition">Label left position.</param>
|
||
/// <param name="toPosition">Label right position.</param>
|
||
/// <param name="text">Label text.</param>
|
||
/// <returns>Newly added item.</returns>
|
||
public CustomLabel Add(double fromPosition, double toPosition, string text)
|
||
{
|
||
CustomLabel label = new CustomLabel(fromPosition, toPosition, text, 0, LabelMarkStyle.None);
|
||
Add(label);
|
||
return label;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Adds one custom label into the collection. Custom label flag may be specified.
|
||
/// </summary>
|
||
/// <param name="fromPosition">Label left position.</param>
|
||
/// <param name="toPosition">Label right position.</param>
|
||
/// <param name="text">Label text.</param>
|
||
/// <param name="customLabel">Indicates if label is custom (created by user).</param>
|
||
/// <returns>Newly added item.</returns>
|
||
internal CustomLabel Add(double fromPosition, double toPosition, string text, bool customLabel)
|
||
{
|
||
CustomLabel label = new CustomLabel(fromPosition, toPosition, text, 0, LabelMarkStyle.None);
|
||
label.customLabel = customLabel;
|
||
Add(label);
|
||
return label;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Adds a custom label into the collection.
|
||
/// </summary>
|
||
/// <param name="fromPosition">Label left position.</param>
|
||
/// <param name="toPosition">Label right position.</param>
|
||
/// <param name="text">Label text.</param>
|
||
/// <param name="rowIndex">Label row index.</param>
|
||
/// <param name="markStyle">Label marking style.</param>
|
||
/// <returns>Newly added item.</returns>
|
||
public CustomLabel Add(double fromPosition, double toPosition, string text, int rowIndex, LabelMarkStyle markStyle)
|
||
{
|
||
CustomLabel label = new CustomLabel(fromPosition, toPosition, text, rowIndex, markStyle);
|
||
Add(label);
|
||
return label;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Adds a custom label into the collection.
|
||
/// </summary>
|
||
/// <param name="fromPosition">Label left position.</param>
|
||
/// <param name="toPosition">Label right position.</param>
|
||
/// <param name="text">Label text.</param>
|
||
/// <param name="rowIndex">Label row index.</param>
|
||
/// <param name="markStyle">Label marking style.</param>
|
||
/// <returns>Index of newly added item.</returns>
|
||
/// <param name="gridTick">Custom grid line and tick mark flag.</param>
|
||
public CustomLabel Add(double fromPosition, double toPosition, string text, int rowIndex, LabelMarkStyle markStyle, GridTickTypes gridTick)
|
||
{
|
||
CustomLabel label = new CustomLabel(fromPosition, toPosition, text, rowIndex, markStyle, gridTick);
|
||
Add(label);
|
||
return label;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Adds multiple custom labels to the collection.
|
||
/// The labels will be DateTime labels with the specified interval type,
|
||
/// and will be generated for the axis range that is determined by the minimum and maximum arguments.
|
||
/// </summary>
|
||
/// <param name="labelsStep">The label step determines how often the custom labels will be drawn.</param>
|
||
/// <param name="intervalType">Unit of measurement of the label step.</param>
|
||
/// <param name="min">Minimum value..</param>
|
||
/// <param name="max">Maximum value..</param>
|
||
/// <param name="format">Label text format.</param>
|
||
/// <param name="rowIndex">Label row index.</param>
|
||
/// <param name="markStyle">Label marking style.</param>
|
||
public void Add(double labelsStep, DateTimeIntervalType intervalType, double min, double max, string format, int rowIndex, LabelMarkStyle markStyle)
|
||
{
|
||
// Find labels range min/max values
|
||
if(min == 0.0 &&
|
||
max == 0.0 &&
|
||
this.Axis != null &&
|
||
!double.IsNaN(this.Axis.Minimum) &&
|
||
!double.IsNaN(this.Axis.Maximum))
|
||
{
|
||
min = this.Axis.Minimum;
|
||
max = this.Axis.Maximum;
|
||
}
|
||
double fromX = Math.Min(min, max);
|
||
double toX = Math.Max(min, max);
|
||
|
||
this.SuspendUpdates();
|
||
try
|
||
{
|
||
|
||
// Loop through all label points
|
||
double labelStart = fromX;
|
||
double labelEnd = 0;
|
||
while (labelStart < toX)
|
||
{
|
||
// Determine label end location
|
||
if (intervalType == DateTimeIntervalType.Number)
|
||
{
|
||
labelEnd = labelStart + labelsStep;
|
||
}
|
||
else if (intervalType == DateTimeIntervalType.Milliseconds)
|
||
{
|
||
labelEnd = DateTime.FromOADate(labelStart).AddMilliseconds(labelsStep).ToOADate();
|
||
}
|
||
else if (intervalType == DateTimeIntervalType.Seconds)
|
||
{
|
||
labelEnd = DateTime.FromOADate(labelStart).AddSeconds(labelsStep).ToOADate();
|
||
}
|
||
else if (intervalType == DateTimeIntervalType.Minutes)
|
||
{
|
||
labelEnd = DateTime.FromOADate(labelStart).AddMinutes(labelsStep).ToOADate();
|
||
}
|
||
else if (intervalType == DateTimeIntervalType.Hours)
|
||
{
|
||
labelEnd = DateTime.FromOADate(labelStart).AddHours(labelsStep).ToOADate();
|
||
}
|
||
else if (intervalType == DateTimeIntervalType.Days)
|
||
{
|
||
labelEnd = DateTime.FromOADate(labelStart).AddDays(labelsStep).ToOADate();
|
||
}
|
||
else if (intervalType == DateTimeIntervalType.Weeks)
|
||
{
|
||
labelEnd = DateTime.FromOADate(labelStart).AddDays(7 * labelsStep).ToOADate();
|
||
}
|
||
else if (intervalType == DateTimeIntervalType.Months)
|
||
{
|
||
labelEnd = DateTime.FromOADate(labelStart).AddMonths((int)labelsStep).ToOADate();
|
||
}
|
||
else if (intervalType == DateTimeIntervalType.Years)
|
||
{
|
||
labelEnd = DateTime.FromOADate(labelStart).AddYears((int)labelsStep).ToOADate();
|
||
}
|
||
else
|
||
{
|
||
// Unsupported step type
|
||
throw (new ArgumentException(SR.ExceptionAxisLabelsIntervalTypeUnsupported(intervalType.ToString())));
|
||
}
|
||
if (labelEnd > toX)
|
||
{
|
||
labelEnd = toX;
|
||
}
|
||
|
||
// Generate label text
|
||
ChartValueType valueType = ChartValueType.Double;
|
||
if (intervalType != DateTimeIntervalType.Number)
|
||
{
|
||
if (this.Axis.GetAxisValuesType() == ChartValueType.DateTimeOffset)
|
||
valueType = ChartValueType.DateTimeOffset;
|
||
else
|
||
valueType = ChartValueType.DateTime;
|
||
}
|
||
string text = ValueConverter.FormatValue(
|
||
this.Common.Chart,
|
||
this.Axis,
|
||
null,
|
||
labelStart + (labelEnd - labelStart) / 2,
|
||
format,
|
||
valueType,
|
||
ChartElementType.AxisLabels);
|
||
|
||
// Add label
|
||
CustomLabel label = new CustomLabel(labelStart, labelEnd, text, rowIndex, markStyle);
|
||
this.Add(label);
|
||
|
||
labelStart = labelEnd;
|
||
}
|
||
}
|
||
finally
|
||
{
|
||
this.ResumeUpdates();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Adds multiple custom labels to the collection.
|
||
/// The labels will be DateTime labels with the specified interval type,
|
||
/// and will be generated for the axis range that is determined by the minimum and maximum arguments.
|
||
/// </summary>
|
||
/// <param name="labelsStep">The label step determines how often the custom labels will be drawn.</param>
|
||
/// <param name="intervalType">Unit of measurement of the label step.</param>
|
||
public void Add(double labelsStep, DateTimeIntervalType intervalType)
|
||
{
|
||
Add(labelsStep, intervalType, 0, 0, "", 0, LabelMarkStyle.None);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Adds multiple custom labels to the collection.
|
||
/// The labels will be DateTime labels with the specified interval type,
|
||
/// and will be generated for the axis range that is determined by the minimum and maximum arguments.
|
||
/// </summary>
|
||
/// <param name="labelsStep">The label step determines how often the custom labels will be drawn.</param>
|
||
/// <param name="intervalType">Unit of measurement of the label step.</param>
|
||
/// <param name="format">Label text format.</param>
|
||
public void Add(double labelsStep, DateTimeIntervalType intervalType, string format)
|
||
{
|
||
Add(labelsStep, intervalType, 0, 0, format, 0, LabelMarkStyle.None);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Adds multiple custom labels to the collection.
|
||
/// The labels will be DateTime labels with the specified interval type,
|
||
/// and will be generated for the axis range that is determined by the minimum and maximum arguments.
|
||
/// </summary>
|
||
/// <param name="labelsStep">The label step determines how often the custom labels will be drawn.</param>
|
||
/// <param name="intervalType">Unit of measurement of the label step.</param>
|
||
/// <param name="format">Label text format.</param>
|
||
/// <param name="rowIndex">Label row index.</param>
|
||
/// <param name="markStyle">Label marking style.</param>
|
||
public void Add(double labelsStep, DateTimeIntervalType intervalType, string format, int rowIndex, LabelMarkStyle markStyle)
|
||
{
|
||
Add(labelsStep, intervalType, 0, 0, format, rowIndex, markStyle);
|
||
}
|
||
|
||
#endregion
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// The CustomLabel class represents a single custom axis label. Text and
|
||
/// position along the axis is provided by the caller.
|
||
/// </summary>
|
||
[
|
||
SRDescription("DescriptionAttributeCustomLabel_CustomLabel"),
|
||
DefaultProperty("Text"),
|
||
]
|
||
#if Microsoft_CONTROL
|
||
public class CustomLabel : ChartNamedElement
|
||
#else
|
||
#if ASPPERM_35
|
||
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
||
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
||
#endif
|
||
public class CustomLabel : ChartNamedElement, IChartMapArea
|
||
#endif
|
||
{
|
||
#region Fields and Constructors
|
||
|
||
// Private data members, which store properties values
|
||
private double _fromPosition = 0;
|
||
private double _toPosition = 0;
|
||
private string _text = "";
|
||
private LabelMarkStyle _labelMark = LabelMarkStyle.None;
|
||
private Color _foreColor = Color.Empty;
|
||
private Color _markColor = Color.Empty;
|
||
private int _labelRowIndex = 0;
|
||
|
||
// Custom grid lines and tick marks flags
|
||
private GridTickTypes _gridTick = GridTickTypes.None;
|
||
|
||
// Indicates if label was automatically created or cpecified by user (custom)
|
||
internal bool customLabel = true;
|
||
|
||
// Image associated with the label
|
||
private string _image = string.Empty;
|
||
|
||
// Image transparent color
|
||
private Color _imageTransparentColor = Color.Empty;
|
||
|
||
// Label tooltip
|
||
private string _tooltip = string.Empty;
|
||
|
||
private Axis _axis = null;
|
||
#if !Microsoft_CONTROL
|
||
|
||
// URL target of the label image.
|
||
private string _imageUrl = string.Empty;
|
||
|
||
// Other attributes of the label image map area.
|
||
private string _imageMapAreaAttributes = string.Empty;
|
||
|
||
private string _imagePostbackValue = String.Empty;
|
||
|
||
// Label tooltip
|
||
private string _url = string.Empty;
|
||
|
||
// Other attributes of the label image map area.
|
||
private string _mapAreaAttributes = string.Empty;
|
||
|
||
private string _postbackValue = String.Empty;
|
||
|
||
|
||
#endif // !Microsoft_CONTROL
|
||
|
||
|
||
|
||
#endregion
|
||
|
||
#region Constructors
|
||
|
||
/// <summary>
|
||
/// Default constructor
|
||
/// </summary>
|
||
public CustomLabel()
|
||
{
|
||
}
|
||
|
||
/// <summary>
|
||
/// CustomLabel constructor
|
||
/// </summary>
|
||
/// <param name="fromPosition">From position.</param>
|
||
/// <param name="toPosition">To position.</param>
|
||
/// <param name="text">Label text.</param>
|
||
/// <param name="labelRow">Label row index.</param>
|
||
/// <param name="markStyle">Label mark style.</param>
|
||
public CustomLabel(double fromPosition, double toPosition, string text, int labelRow, LabelMarkStyle markStyle)
|
||
{
|
||
this._fromPosition = fromPosition;
|
||
this._toPosition = toPosition;
|
||
this._text = text;
|
||
this._labelRowIndex = labelRow;
|
||
this._labelMark = markStyle;
|
||
this._gridTick = GridTickTypes.None;
|
||
}
|
||
|
||
/// <summary>
|
||
/// CustomLabel constructor
|
||
/// </summary>
|
||
/// <param name="fromPosition">From position.</param>
|
||
/// <param name="toPosition">To position.</param>
|
||
/// <param name="text">Label text.</param>
|
||
/// <param name="labelRow">Label row index.</param>
|
||
/// <param name="markStyle">Label mark style.</param>
|
||
/// <param name="gridTick">Custom grid line and tick marks flag.</param>
|
||
public CustomLabel(double fromPosition, double toPosition, string text, int labelRow, LabelMarkStyle markStyle, GridTickTypes gridTick)
|
||
{
|
||
this._fromPosition = fromPosition;
|
||
this._toPosition = toPosition;
|
||
this._text = text;
|
||
this._labelRowIndex = labelRow;
|
||
this._labelMark = markStyle;
|
||
this._gridTick = gridTick;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Helper methods
|
||
|
||
/// <summary>
|
||
/// Returns a cloned label object.
|
||
/// </summary>
|
||
/// <returns>Copy of current custom label.</returns>
|
||
public CustomLabel Clone()
|
||
{
|
||
CustomLabel newLabel = new CustomLabel();
|
||
|
||
newLabel.FromPosition = this.FromPosition;
|
||
newLabel.ToPosition = this.ToPosition;
|
||
newLabel.Text = this.Text;
|
||
newLabel.ForeColor = this.ForeColor;
|
||
newLabel.MarkColor = this.MarkColor;
|
||
newLabel.RowIndex = this.RowIndex;
|
||
newLabel.LabelMark = this.LabelMark;
|
||
newLabel.GridTicks = this.GridTicks;
|
||
|
||
|
||
|
||
newLabel.ToolTip = this.ToolTip;
|
||
newLabel.Tag = this.Tag;
|
||
newLabel.Image = this.Image;
|
||
newLabel.ImageTransparentColor = this.ImageTransparentColor;
|
||
|
||
#if !Microsoft_CONTROL
|
||
newLabel.Url = this.Url;
|
||
newLabel.MapAreaAttributes = this.MapAreaAttributes;
|
||
newLabel.ImageUrl = this.ImageUrl;
|
||
newLabel.ImageMapAreaAttributes = this.ImageMapAreaAttributes;
|
||
#endif // !Microsoft_CONTROL
|
||
|
||
|
||
|
||
return newLabel;
|
||
}
|
||
|
||
internal override IChartElement Parent
|
||
{
|
||
get
|
||
{
|
||
return base.Parent;
|
||
}
|
||
set
|
||
{
|
||
base.Parent = value;
|
||
if (value != null)
|
||
{
|
||
_axis = Parent.Parent as Axis;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets the axis to which this object is attached to.
|
||
/// </summary>
|
||
/// <returns>Axis.</returns>
|
||
[
|
||
Browsable(false),
|
||
DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
|
||
SerializationVisibilityAttribute(SerializationVisibility.Hidden),
|
||
]
|
||
public Axis Axis
|
||
{
|
||
get
|
||
{
|
||
return _axis;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region CustomLabel properties
|
||
|
||
/// <summary>
|
||
/// Gets or sets the tooltip of the custom label.
|
||
/// </summary>
|
||
[
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute),
|
||
#endif //!Microsoft_CONTROL
|
||
SRCategory("CategoryAttributeMapArea"),
|
||
Bindable(true),
|
||
SRDescription("DescriptionAttributeToolTip"),
|
||
DefaultValue("")
|
||
]
|
||
public string ToolTip
|
||
{
|
||
set
|
||
{
|
||
this._tooltip = value;
|
||
}
|
||
get
|
||
{
|
||
return this._tooltip;
|
||
}
|
||
}
|
||
|
||
|
||
#if !Microsoft_CONTROL
|
||
|
||
/// <summary>
|
||
/// URL target of the custom label.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeMapArea"),
|
||
Bindable(true),
|
||
SRDescription("DescriptionAttributeUrl"),
|
||
DefaultValue(""),
|
||
PersistenceMode(PersistenceMode.Attribute),
|
||
Editor(Editors.UrlValueEditor.Editor, Editors.UrlValueEditor.Base)
|
||
]
|
||
public string Url
|
||
{
|
||
set
|
||
{
|
||
this._url = value;
|
||
}
|
||
get
|
||
{
|
||
return this._url;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the other attributes of the custom label map area.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeMapArea"),
|
||
Bindable(true),
|
||
SRDescription("DescriptionAttributeMapAreaAttributes"),
|
||
DefaultValue(""),
|
||
PersistenceMode(PersistenceMode.Attribute)
|
||
]
|
||
public string MapAreaAttributes
|
||
{
|
||
set
|
||
{
|
||
this._mapAreaAttributes = value;
|
||
}
|
||
get
|
||
{
|
||
return this._mapAreaAttributes;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the postback value which can be processed on a click event.
|
||
/// </summary>
|
||
/// <value>The value which is passed to a click event as an argument.</value>
|
||
[DefaultValue("")]
|
||
[SRCategory(SR.Keys.CategoryAttributeMapArea)]
|
||
[SRDescription(SR.Keys.DescriptionAttributePostBackValue)]
|
||
public string PostBackValue
|
||
{
|
||
get
|
||
{
|
||
return this._postbackValue;
|
||
}
|
||
set
|
||
{
|
||
this._postbackValue = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the URL target of the custom label image.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeMapArea"),
|
||
Bindable(true),
|
||
SRDescription("DescriptionAttributeCustomLabel_ImageUrl"),
|
||
DefaultValue(""),
|
||
PersistenceMode(PersistenceMode.Attribute),
|
||
Editor(Editors.UrlValueEditor.Editor, Editors.UrlValueEditor.Base),
|
||
System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")
|
||
]
|
||
public string ImageUrl
|
||
{
|
||
set
|
||
{
|
||
this._imageUrl = value;
|
||
}
|
||
get
|
||
{
|
||
return this._imageUrl;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the other attributes of the map area of the custom label image.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeMapArea"),
|
||
Bindable(true),
|
||
SRDescription("DescriptionAttributeMapAreaAttributes"),
|
||
DefaultValue(""),
|
||
PersistenceMode(PersistenceMode.Attribute)
|
||
]
|
||
public string ImageMapAreaAttributes
|
||
{
|
||
set
|
||
{
|
||
this._imageMapAreaAttributes = value;
|
||
}
|
||
get
|
||
{
|
||
return this._imageMapAreaAttributes;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the postback value which can be processed on a click event.
|
||
/// </summary>
|
||
/// <value>The value which is passed to a click event as an argument.</value>
|
||
[DefaultValue("")]
|
||
[SRCategory(SR.Keys.CategoryAttributeMapArea)]
|
||
[SRDescription(SR.Keys.DescriptionAttributePostBackValue)]
|
||
public string ImagePostBackValue
|
||
{
|
||
get
|
||
{
|
||
return this._imagePostbackValue;
|
||
}
|
||
set
|
||
{
|
||
this._imagePostbackValue = value;
|
||
}
|
||
}
|
||
|
||
|
||
#endif // !Microsoft_CONTROL
|
||
|
||
/// <summary>
|
||
/// Gets or sets the label image.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(""),
|
||
SRDescription("DescriptionAttributeCustomLabel_Image"),
|
||
Editor(Editors.ImageValueEditor.Editor, Editors.ImageValueEditor.Base),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute),
|
||
#endif
|
||
NotifyParentPropertyAttribute(true)
|
||
]
|
||
public string Image
|
||
{
|
||
get
|
||
{
|
||
return _image;
|
||
}
|
||
set
|
||
{
|
||
_image = value;
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a color which will be replaced with a transparent color while drawing the image.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(typeof(Color), ""),
|
||
NotifyParentPropertyAttribute(true),
|
||
SRDescription("DescriptionAttributeImageTransparentColor"),
|
||
TypeConverter(typeof(ColorConverter)),
|
||
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute)
|
||
#endif
|
||
]
|
||
public Color ImageTransparentColor
|
||
{
|
||
get
|
||
{
|
||
return _imageTransparentColor;
|
||
}
|
||
set
|
||
{
|
||
_imageTransparentColor = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// Custom label name. This property is for internal use only.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
SRDescription("DescriptionAttributeCustomLabel_Name"),
|
||
DefaultValue("Custom LabelStyle"),
|
||
DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
|
||
DesignOnlyAttribute(true),
|
||
SerializationVisibilityAttribute(SerializationVisibility.Hidden)
|
||
]
|
||
public override string Name
|
||
{
|
||
get
|
||
{
|
||
return base.Name;
|
||
}
|
||
set
|
||
{
|
||
base.Name = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a property which specifies whether
|
||
/// custom tick marks and grid lines will be drawn in the center of the label.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(GridTickTypes.None),
|
||
SRDescription("DescriptionAttributeCustomLabel_GridTicks"),
|
||
Editor(Editors.FlagsEnumUITypeEditor.Editor, Editors.FlagsEnumUITypeEditor.Base)
|
||
]
|
||
public GridTickTypes GridTicks
|
||
{
|
||
get
|
||
{
|
||
return _gridTick;
|
||
}
|
||
set
|
||
{
|
||
_gridTick = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the end position of the custom label in axis coordinates.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(0.0),
|
||
SRDescription("DescriptionAttributeCustomLabel_From"),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute),
|
||
#endif
|
||
TypeConverter(typeof(AxisLabelDateValueConverter))
|
||
]
|
||
public double FromPosition
|
||
{
|
||
get
|
||
{
|
||
return _fromPosition;
|
||
}
|
||
set
|
||
{
|
||
_fromPosition = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the starting position of the custom label in axis coordinates.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(0.0),
|
||
SRDescription("DescriptionAttributeCustomLabel_To"),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute),
|
||
#endif
|
||
TypeConverter(typeof(AxisLabelDateValueConverter))
|
||
]
|
||
public double ToPosition
|
||
{
|
||
get
|
||
{
|
||
return _toPosition;
|
||
}
|
||
set
|
||
{
|
||
_toPosition = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the text of the custom label.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(""),
|
||
SRDescription("DescriptionAttributeCustomLabel_Text"),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute)
|
||
#endif
|
||
]
|
||
public string Text
|
||
{
|
||
get
|
||
{
|
||
return _text;
|
||
}
|
||
set
|
||
{
|
||
_text = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the text color of the custom label.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(typeof(Color), ""),
|
||
SRDescription("DescriptionAttributeForeColor"),
|
||
NotifyParentPropertyAttribute(true),
|
||
TypeConverter(typeof(ColorConverter)),
|
||
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute)
|
||
#endif
|
||
]
|
||
public Color ForeColor
|
||
{
|
||
get
|
||
{
|
||
return _foreColor;
|
||
}
|
||
set
|
||
{
|
||
_foreColor = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the color of the label mark line of the custom label.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(typeof(Color), ""),
|
||
SRDescription("DescriptionAttributeCustomLabel_MarkColor"),
|
||
NotifyParentPropertyAttribute(true),
|
||
TypeConverter(typeof(ColorConverter)),
|
||
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute)
|
||
#endif
|
||
]
|
||
public Color MarkColor
|
||
{
|
||
get
|
||
{
|
||
return _markColor;
|
||
}
|
||
set
|
||
{
|
||
_markColor = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the row index of the custom label.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(0),
|
||
SRDescription("DescriptionAttributeCustomLabel_RowIndex"),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute)
|
||
#endif
|
||
]
|
||
public int RowIndex
|
||
{
|
||
get
|
||
{
|
||
return this._labelRowIndex;
|
||
}
|
||
set
|
||
{
|
||
if(value < 0)
|
||
{
|
||
throw (new InvalidOperationException(SR.ExceptionAxisLabelRowIndexIsNegative));
|
||
}
|
||
|
||
this._labelRowIndex = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a property which define the marks for the labels in the second row.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(LabelMarkStyle.None),
|
||
SRDescription("DescriptionAttributeCustomLabel_LabelMark"),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute)
|
||
#endif
|
||
]
|
||
public LabelMarkStyle LabelMark
|
||
{
|
||
get
|
||
{
|
||
return _labelMark;
|
||
}
|
||
set
|
||
{
|
||
_labelMark = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// The LabelStyle class contains properties which define the visual appearance of
|
||
/// the axis labels, their interval and position. This class is also
|
||
/// responsible for calculating the position of all the labels and
|
||
/// drawing them.
|
||
/// </summary>
|
||
[
|
||
SRDescription("DescriptionAttributeLabel_Label"),
|
||
DefaultProperty("Enabled"),
|
||
]
|
||
#if ASPPERM_35
|
||
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
||
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
||
#endif
|
||
public class LabelStyle : ChartElement
|
||
{
|
||
#region Fields
|
||
|
||
// Reference to the Axis
|
||
private Axis _axis = null;
|
||
|
||
// Private data members, which store properties values
|
||
private bool _enabled = true;
|
||
|
||
internal double intervalOffset = double.NaN;
|
||
internal double interval = double.NaN;
|
||
internal DateTimeIntervalType intervalType = DateTimeIntervalType.NotSet;
|
||
internal DateTimeIntervalType intervalOffsetType = DateTimeIntervalType.NotSet;
|
||
|
||
private FontCache _fontCache = new FontCache();
|
||
private Font _font;
|
||
private Color _foreColor = Color.Black;
|
||
internal int angle = 0;
|
||
internal bool isStaggered = false;
|
||
private bool _isEndLabelVisible = true;
|
||
private bool _truncatedLabels = false;
|
||
private string _format = "";
|
||
|
||
#endregion
|
||
|
||
#region Constructors
|
||
|
||
/// <summary>
|
||
/// Public default constructor.
|
||
/// </summary>
|
||
public LabelStyle()
|
||
{
|
||
_font = _fontCache.DefaultFont;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Public constructor.
|
||
/// </summary>
|
||
/// <param name="axis">Axis which owns the grid.</param>
|
||
internal LabelStyle(Axis axis)
|
||
: this()
|
||
{
|
||
_axis = axis;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Axis labels drawing methods
|
||
|
||
/// <summary>
|
||
/// Draws axis labels on the circular chart area.
|
||
/// </summary>
|
||
/// <param name="graph">Reference to the Chart Graphics object.</param>
|
||
internal void PaintCircular( ChartGraphics graph )
|
||
{
|
||
// Label string drawing format
|
||
using (StringFormat format = new StringFormat())
|
||
{
|
||
format.FormatFlags |= StringFormatFlags.LineLimit;
|
||
format.Trimming = StringTrimming.EllipsisCharacter;
|
||
|
||
// Labels are disabled for this axis
|
||
if (!_axis.LabelStyle.Enabled)
|
||
return;
|
||
|
||
// Draw text with anti-aliasing
|
||
/*
|
||
if( (graph.AntiAliasing & AntiAliasing.Text) == AntiAliasing.Text )
|
||
{
|
||
graph.TextRenderingHint = TextRenderingHint.AntiAlias;
|
||
}
|
||
else
|
||
{
|
||
graph.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
|
||
}
|
||
*/
|
||
|
||
// Gets axis labels style
|
||
CircularAxisLabelsStyle labelsStyle = this._axis.ChartArea.GetCircularAxisLabelsStyle();
|
||
|
||
// Get list of circular axes with labels
|
||
ArrayList circularAxes = this._axis.ChartArea.GetCircularAxisList();
|
||
|
||
// Draw each axis label
|
||
int index = 0;
|
||
foreach (CircularChartAreaAxis circAxis in circularAxes)
|
||
{
|
||
if (circAxis.Title.Length > 0)
|
||
{
|
||
//******************************************************************
|
||
//** Calculate label position corner position
|
||
//******************************************************************
|
||
PointF labelRelativePosition = new PointF(
|
||
this._axis.ChartArea.circularCenter.X,
|
||
this._axis.ChartArea.PlotAreaPosition.Y);
|
||
|
||
// Adjust labels Y position
|
||
labelRelativePosition.Y -= _axis.markSize + Axis.elementSpacing;
|
||
|
||
// Convert to absolute
|
||
PointF[] labelPosition = new PointF[] { graph.GetAbsolutePoint(labelRelativePosition) };
|
||
|
||
// Get label rotation angle
|
||
float labelAngle = circAxis.AxisPosition;
|
||
ICircularChartType chartType = this._axis.ChartArea.GetCircularChartType();
|
||
if (chartType != null && chartType.XAxisCrossingSupported())
|
||
{
|
||
if (!double.IsNaN(this._axis.ChartArea.AxisX.Crossing))
|
||
{
|
||
labelAngle += (float)this._axis.ChartArea.AxisX.Crossing;
|
||
}
|
||
}
|
||
|
||
// Make sure angle is presented as a positive number
|
||
while (labelAngle < 0)
|
||
{
|
||
labelAngle = 360f + labelAngle;
|
||
}
|
||
|
||
// Set graphics rotation matrix
|
||
Matrix newMatrix = new Matrix();
|
||
newMatrix.RotateAt(labelAngle, graph.GetAbsolutePoint(this._axis.ChartArea.circularCenter));
|
||
newMatrix.TransformPoints(labelPosition);
|
||
|
||
// Set text alignment
|
||
format.LineAlignment = StringAlignment.Center;
|
||
format.Alignment = StringAlignment.Near;
|
||
if (labelsStyle != CircularAxisLabelsStyle.Radial)
|
||
{
|
||
if (labelAngle < 5f || labelAngle > 355f)
|
||
{
|
||
format.Alignment = StringAlignment.Center;
|
||
format.LineAlignment = StringAlignment.Far;
|
||
}
|
||
if (labelAngle < 185f && labelAngle > 175f)
|
||
{
|
||
format.Alignment = StringAlignment.Center;
|
||
format.LineAlignment = StringAlignment.Near;
|
||
}
|
||
if (labelAngle > 185f && labelAngle < 355f)
|
||
{
|
||
format.Alignment = StringAlignment.Far;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (labelAngle > 180f)
|
||
{
|
||
format.Alignment = StringAlignment.Far;
|
||
}
|
||
}
|
||
|
||
|
||
// Set text rotation angle
|
||
float textAngle = labelAngle;
|
||
if (labelsStyle == CircularAxisLabelsStyle.Radial)
|
||
{
|
||
if (labelAngle > 180)
|
||
{
|
||
textAngle += 90f;
|
||
}
|
||
else
|
||
{
|
||
textAngle -= 90f;
|
||
}
|
||
}
|
||
else if (labelsStyle == CircularAxisLabelsStyle.Circular)
|
||
{
|
||
format.Alignment = StringAlignment.Center;
|
||
format.LineAlignment = StringAlignment.Far;
|
||
}
|
||
|
||
// Set text rotation matrix
|
||
Matrix oldMatrix = graph.Transform;
|
||
if (labelsStyle == CircularAxisLabelsStyle.Radial || labelsStyle == CircularAxisLabelsStyle.Circular)
|
||
{
|
||
Matrix textRotationMatrix = oldMatrix.Clone();
|
||
textRotationMatrix.RotateAt(textAngle, labelPosition[0]);
|
||
graph.Transform = textRotationMatrix;
|
||
}
|
||
|
||
// Get axis titl (label) color
|
||
Color labelColor = _foreColor;
|
||
if (!circAxis.TitleForeColor.IsEmpty)
|
||
{
|
||
labelColor = circAxis.TitleForeColor;
|
||
}
|
||
|
||
// Draw label
|
||
using (Brush brush = new SolidBrush(labelColor))
|
||
{
|
||
graph.DrawString(
|
||
circAxis.Title.Replace("\\n", "\n"),
|
||
(_axis.autoLabelFont == null) ? _font : _axis.autoLabelFont,
|
||
brush,
|
||
labelPosition[0],
|
||
format);
|
||
}
|
||
|
||
// Process selection region
|
||
if (this._axis.Common.ProcessModeRegions)
|
||
{
|
||
SizeF size = graph.MeasureString(circAxis.Title.Replace("\\n", "\n"), (_axis.autoLabelFont == null) ? _font : _axis.autoLabelFont);
|
||
RectangleF labelRect = GetLabelPosition(
|
||
labelPosition[0],
|
||
size,
|
||
format);
|
||
PointF[] points = new PointF[]
|
||
{
|
||
labelRect.Location,
|
||
new PointF(labelRect.Right, labelRect.Y),
|
||
new PointF(labelRect.Right, labelRect.Bottom),
|
||
new PointF(labelRect.X, labelRect.Bottom)
|
||
};
|
||
|
||
using (GraphicsPath path = new GraphicsPath())
|
||
{
|
||
path.AddPolygon(points);
|
||
path.CloseAllFigures();
|
||
path.Transform(graph.Transform);
|
||
this._axis.Common.HotRegionsList.AddHotRegion(
|
||
path,
|
||
false,
|
||
ChartElementType.AxisLabels,
|
||
circAxis.Title);
|
||
}
|
||
}
|
||
|
||
// Restore graphics
|
||
if(labelsStyle == CircularAxisLabelsStyle.Radial || labelsStyle == CircularAxisLabelsStyle.Circular)
|
||
{
|
||
graph.Transform = oldMatrix;
|
||
}
|
||
}
|
||
|
||
++index;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets rectangle position of the label.
|
||
/// </summary>
|
||
/// <param name="position">Original label position.</param>
|
||
/// <param name="size">Label text size.</param>
|
||
/// <param name="format">Label string format.</param>
|
||
/// <returns>Label rectangle position.</returns>
|
||
internal static RectangleF GetLabelPosition(
|
||
PointF position,
|
||
SizeF size,
|
||
StringFormat format)
|
||
{
|
||
// Calculate label position rectangle
|
||
RectangleF labelPosition = RectangleF.Empty;
|
||
labelPosition.Width = size.Width;
|
||
labelPosition.Height = size.Height;
|
||
|
||
if(format.Alignment == StringAlignment.Far)
|
||
{
|
||
labelPosition.X = position.X - size.Width;
|
||
}
|
||
else if(format.Alignment == StringAlignment.Near)
|
||
{
|
||
labelPosition.X = position.X;
|
||
}
|
||
else if(format.Alignment == StringAlignment.Center)
|
||
{
|
||
labelPosition.X = position.X - size.Width/2F;
|
||
}
|
||
|
||
if(format.LineAlignment == StringAlignment.Far)
|
||
{
|
||
labelPosition.Y = position.Y - size.Height;
|
||
}
|
||
else if(format.LineAlignment == StringAlignment.Near)
|
||
{
|
||
labelPosition.Y = position.Y;
|
||
}
|
||
else if(format.LineAlignment == StringAlignment.Center)
|
||
{
|
||
labelPosition.Y = position.Y - size.Height/2F;
|
||
}
|
||
|
||
return labelPosition;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Draws axis labels.
|
||
/// </summary>
|
||
/// <param name="graph">Reference to the Chart Graphics object.</param>
|
||
/// <param name="backElements">Back elements of the axis should be drawn in 3D scene.</param>
|
||
internal void Paint( ChartGraphics graph, bool backElements )
|
||
{
|
||
// Label string drawing format
|
||
using (StringFormat format = new StringFormat())
|
||
{
|
||
format.FormatFlags |= StringFormatFlags.LineLimit;
|
||
format.Trimming = StringTrimming.EllipsisCharacter;
|
||
|
||
// Labels are disabled for this axis
|
||
if (!_axis.LabelStyle.Enabled)
|
||
return;
|
||
// deliant fix-> VSTS #157848, #143286 - drawing custom label in empty axis
|
||
if (Double.IsNaN(_axis.ViewMinimum) || Double.IsNaN(_axis.ViewMaximum))
|
||
return;
|
||
|
||
|
||
// Draw labels in 3D space
|
||
if (this._axis.ChartArea.Area3DStyle.Enable3D && !this._axis.ChartArea.chartAreaIsCurcular)
|
||
{
|
||
this.Paint3D(graph, backElements);
|
||
return;
|
||
}
|
||
|
||
// Initialize all labels position rectangle
|
||
RectangleF rectLabels = _axis.ChartArea.Position.ToRectangleF();
|
||
float labelSize = _axis.labelSize;
|
||
|
||
if (_axis.AxisPosition == AxisPosition.Left)
|
||
{
|
||
rectLabels.Width = labelSize;
|
||
if (_axis.GetIsMarksNextToAxis())
|
||
rectLabels.X = (float)_axis.GetAxisPosition();
|
||
else
|
||
rectLabels.X = _axis.PlotAreaPosition.X;
|
||
|
||
rectLabels.X -= labelSize + _axis.markSize;
|
||
|
||
// Set label text alignment
|
||
format.Alignment = StringAlignment.Far;
|
||
format.LineAlignment = StringAlignment.Center;
|
||
}
|
||
else if (_axis.AxisPosition == AxisPosition.Right)
|
||
{
|
||
rectLabels.Width = labelSize;
|
||
if (_axis.GetIsMarksNextToAxis())
|
||
rectLabels.X = (float)_axis.GetAxisPosition();
|
||
else
|
||
rectLabels.X = _axis.PlotAreaPosition.Right;
|
||
rectLabels.X += _axis.markSize;
|
||
|
||
// Set label text alignment
|
||
format.Alignment = StringAlignment.Near;
|
||
format.LineAlignment = StringAlignment.Center;
|
||
}
|
||
else if (_axis.AxisPosition == AxisPosition.Top)
|
||
{
|
||
rectLabels.Height = labelSize;
|
||
if (_axis.GetIsMarksNextToAxis())
|
||
rectLabels.Y = (float)_axis.GetAxisPosition();
|
||
else
|
||
rectLabels.Y = _axis.PlotAreaPosition.Y;
|
||
rectLabels.Y -= labelSize + _axis.markSize;
|
||
|
||
// Set label text alignment
|
||
format.Alignment = StringAlignment.Center;
|
||
format.LineAlignment = StringAlignment.Far;
|
||
}
|
||
else if (_axis.AxisPosition == AxisPosition.Bottom)
|
||
{
|
||
rectLabels.Height = labelSize;
|
||
if (_axis.GetIsMarksNextToAxis())
|
||
rectLabels.Y = (float)_axis.GetAxisPosition();
|
||
else
|
||
rectLabels.Y = _axis.PlotAreaPosition.Bottom;
|
||
rectLabels.Y += _axis.markSize;
|
||
|
||
// Set label text alignment
|
||
format.Alignment = StringAlignment.Center;
|
||
format.LineAlignment = StringAlignment.Near;
|
||
}
|
||
|
||
// Calculate bounding rectangle
|
||
RectangleF boundaryRect = rectLabels;
|
||
if (boundaryRect != RectangleF.Empty && _axis.totlaGroupingLabelsSize > 0)
|
||
{
|
||
if (_axis.AxisPosition == AxisPosition.Left)
|
||
{
|
||
boundaryRect.X += _axis.totlaGroupingLabelsSize;
|
||
boundaryRect.Width -= _axis.totlaGroupingLabelsSize;
|
||
}
|
||
else if (_axis.AxisPosition == AxisPosition.Right)
|
||
{
|
||
boundaryRect.Width -= _axis.totlaGroupingLabelsSize;
|
||
}
|
||
else if (_axis.AxisPosition == AxisPosition.Top)
|
||
{
|
||
boundaryRect.Y += _axis.totlaGroupingLabelsSize;
|
||
boundaryRect.Height -= _axis.totlaGroupingLabelsSize;
|
||
}
|
||
else if (_axis.AxisPosition == AxisPosition.Bottom)
|
||
{
|
||
boundaryRect.Height -= _axis.totlaGroupingLabelsSize;
|
||
}
|
||
}
|
||
|
||
// Check if the AJAX zooming and scrolling mode is enabled.
|
||
// Labels are drawn slightly different in this case.
|
||
bool ajaxScrollingEnabled = false;
|
||
bool firstFrame = true;
|
||
bool lastFrame = true;
|
||
|
||
// Draw all labels from the collection
|
||
int labelIndex = 0;
|
||
foreach (CustomLabel label in this._axis.CustomLabels)
|
||
{
|
||
bool truncatedLeft = false;
|
||
bool truncatedRight = false;
|
||
double labelFrom = label.FromPosition;
|
||
double labelTo = label.ToPosition;
|
||
bool useRelativeCoordiantes = false;
|
||
double labelFromRelative = double.NaN;
|
||
double labelToRelative = double.NaN;
|
||
|
||
// Skip if label middle point is outside current scaleView
|
||
if (label.RowIndex == 0)
|
||
{
|
||
double middlePoint = (label.FromPosition + label.ToPosition) / 2.0;
|
||
decimal viewMin = (decimal)_axis.ViewMinimum;
|
||
decimal viewMax = (decimal)_axis.ViewMaximum;
|
||
|
||
if (ajaxScrollingEnabled)
|
||
{
|
||
// Skip very first and last labels if they are partialy outside the scaleView
|
||
if (firstFrame)
|
||
{
|
||
if ((decimal)label.FromPosition < (decimal)_axis.Minimum)
|
||
{
|
||
continue;
|
||
}
|
||
}
|
||
if (lastFrame)
|
||
{
|
||
if ((decimal)label.ToPosition > (decimal)_axis.Maximum)
|
||
{
|
||
continue;
|
||
}
|
||
}
|
||
|
||
// Skip label only if it is compleltly out of the scaleView
|
||
if ((decimal)label.ToPosition < viewMin ||
|
||
(decimal)label.FromPosition > viewMax)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
// RecalculateAxesScale label index starting from the first frame.
|
||
// Index is used to determine position of the offset labels
|
||
if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
|
||
{
|
||
// Reset index
|
||
labelIndex = 0;
|
||
|
||
// Get first series attached to this axis
|
||
Series axisSeries = null;
|
||
if (_axis.axisType == AxisName.X || _axis.axisType == AxisName.X2)
|
||
{
|
||
List<string> seriesArray = _axis.ChartArea.GetXAxesSeries((_axis.axisType == AxisName.X) ? AxisType.Primary : AxisType.Secondary, _axis.SubAxisName);
|
||
if (seriesArray.Count > 0)
|
||
{
|
||
axisSeries = _axis.Common.DataManager.Series[seriesArray[0]];
|
||
if (axisSeries != null && !axisSeries.IsXValueIndexed)
|
||
{
|
||
axisSeries = null;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Set start position and iterate through label positions
|
||
// NOTE: Labels offset should not be taken in the account
|
||
double currentPosition = _axis.Minimum;
|
||
while (currentPosition < _axis.Maximum)
|
||
{
|
||
if (currentPosition >= middlePoint)
|
||
{
|
||
break;
|
||
}
|
||
|
||
currentPosition += ChartHelper.GetIntervalSize(currentPosition, _axis.LabelStyle.GetInterval(), _axis.LabelStyle.GetIntervalType(),
|
||
axisSeries, 0.0, DateTimeIntervalType.Number, true);
|
||
++labelIndex;
|
||
}
|
||
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Skip label if label middle point is not in the scaleView
|
||
if ((decimal)middlePoint < viewMin ||
|
||
(decimal)middlePoint > viewMax)
|
||
{
|
||
continue;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
// Make sure label To and From coordinates are processed by one scale segment based
|
||
// on the label middle point position.
|
||
if (_axis.ScaleSegments.Count > 0)
|
||
{
|
||
AxisScaleSegment scaleSegment = _axis.ScaleSegments.FindScaleSegmentForAxisValue(middlePoint);
|
||
_axis.ScaleSegments.AllowOutOfScaleValues = true;
|
||
_axis.ScaleSegments.EnforceSegment(scaleSegment);
|
||
}
|
||
|
||
|
||
|
||
// Use center point instead of the To/From if label takes all scaleView
|
||
// This is done to avoid issues with labels drawing with high
|
||
// zooming levels.
|
||
if ((decimal)label.FromPosition < viewMin &&
|
||
(decimal)label.ToPosition > viewMax)
|
||
{
|
||
// Indicates that chart relative coordinates should be used instead of axis values
|
||
useRelativeCoordiantes = true;
|
||
|
||
// Calculate label From/To in relative coordinates using
|
||
// label middle point and 100% width.
|
||
labelFromRelative = _axis.GetLinearPosition(middlePoint) - 50.0;
|
||
labelToRelative = labelFromRelative + 100.0;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Skip labels completly outside the scaleView
|
||
if (label.ToPosition <= _axis.ViewMinimum || label.FromPosition >= _axis.ViewMaximum)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
// Check if label is partially visible.
|
||
if (!ajaxScrollingEnabled &&
|
||
_axis.ScaleView.IsZoomed)
|
||
{
|
||
if (label.FromPosition < _axis.ViewMinimum)
|
||
{
|
||
truncatedLeft = true;
|
||
labelFrom = _axis.ViewMinimum;
|
||
}
|
||
if (label.ToPosition > _axis.ViewMaximum)
|
||
{
|
||
truncatedRight = true;
|
||
labelTo = _axis.ViewMaximum;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Calculate single label position
|
||
RectangleF rect = rectLabels;
|
||
|
||
// Label is in the first row
|
||
if (label.RowIndex == 0)
|
||
{
|
||
if (_axis.AxisPosition == AxisPosition.Left)
|
||
{
|
||
rect.X = rectLabels.Right - _axis.unRotatedLabelSize;
|
||
rect.Width = _axis.unRotatedLabelSize;
|
||
|
||
// Adjust label rectangle if offset labels are used
|
||
if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
|
||
{
|
||
rect.Width /= 2F;
|
||
if (labelIndex % 2 != 0F)
|
||
{
|
||
rect.X += rect.Width;
|
||
}
|
||
}
|
||
}
|
||
else if (_axis.AxisPosition == AxisPosition.Right)
|
||
{
|
||
rect.Width = _axis.unRotatedLabelSize;
|
||
|
||
// Adjust label rectangle if offset labels are used
|
||
if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
|
||
{
|
||
rect.Width /= 2F;
|
||
if (labelIndex % 2 != 0F)
|
||
{
|
||
rect.X += rect.Width;
|
||
}
|
||
}
|
||
}
|
||
else if (_axis.AxisPosition == AxisPosition.Top)
|
||
{
|
||
rect.Y = rectLabels.Bottom - _axis.unRotatedLabelSize;
|
||
rect.Height = _axis.unRotatedLabelSize;
|
||
|
||
// Adjust label rectangle if offset labels are used
|
||
if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
|
||
{
|
||
rect.Height /= 2F;
|
||
if (labelIndex % 2 != 0F)
|
||
{
|
||
rect.Y += rect.Height;
|
||
}
|
||
}
|
||
}
|
||
else if (_axis.AxisPosition == AxisPosition.Bottom)
|
||
{
|
||
rect.Height = _axis.unRotatedLabelSize;
|
||
|
||
// Adjust label rectangle if offset labels are used
|
||
if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
|
||
{
|
||
rect.Height /= 2F;
|
||
if (labelIndex % 2 != 0F)
|
||
{
|
||
rect.Y += rect.Height;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Increase label index
|
||
++labelIndex;
|
||
}
|
||
|
||
// Label is in the second row
|
||
else if (label.RowIndex > 0)
|
||
{
|
||
if (_axis.AxisPosition == AxisPosition.Left)
|
||
{
|
||
rect.X += _axis.totlaGroupingLabelsSizeAdjustment;
|
||
for (int index = _axis.groupingLabelSizes.Length; index > label.RowIndex; index--)
|
||
{
|
||
rect.X += _axis.groupingLabelSizes[index - 1];
|
||
}
|
||
rect.Width = _axis.groupingLabelSizes[label.RowIndex - 1];
|
||
}
|
||
else if (_axis.AxisPosition == AxisPosition.Right)
|
||
{
|
||
rect.X = rect.Right - _axis.totlaGroupingLabelsSize - _axis.totlaGroupingLabelsSizeAdjustment;// + Axis.elementSpacing * 0.25f;
|
||
for (int index = 1; index < label.RowIndex; index++)
|
||
{
|
||
rect.X += _axis.groupingLabelSizes[index - 1];
|
||
}
|
||
rect.Width = _axis.groupingLabelSizes[label.RowIndex - 1];
|
||
}
|
||
else if (_axis.AxisPosition == AxisPosition.Top)
|
||
{
|
||
rect.Y += _axis.totlaGroupingLabelsSizeAdjustment;
|
||
for (int index = _axis.groupingLabelSizes.Length; index > label.RowIndex; index--)
|
||
{
|
||
rect.Y += _axis.groupingLabelSizes[index - 1];
|
||
}
|
||
rect.Height = _axis.groupingLabelSizes[label.RowIndex - 1];
|
||
}
|
||
if (_axis.AxisPosition == AxisPosition.Bottom)
|
||
{
|
||
rect.Y = rect.Bottom - _axis.totlaGroupingLabelsSize - _axis.totlaGroupingLabelsSizeAdjustment;
|
||
for (int index = 1; index < label.RowIndex; index++)
|
||
{
|
||
rect.Y += _axis.groupingLabelSizes[index - 1];
|
||
}
|
||
rect.Height = _axis.groupingLabelSizes[label.RowIndex - 1];
|
||
}
|
||
}
|
||
|
||
// Unknown label row value
|
||
else
|
||
{
|
||
throw (new InvalidOperationException(SR.ExceptionAxisLabelIndexIsNegative));
|
||
}
|
||
|
||
// Set label From and To coordinates
|
||
double fromPosition = _axis.GetLinearPosition(labelFrom);
|
||
double toPosition = _axis.GetLinearPosition(labelTo);
|
||
if (useRelativeCoordiantes)
|
||
{
|
||
useRelativeCoordiantes = false;
|
||
fromPosition = labelFromRelative;
|
||
toPosition = labelToRelative;
|
||
}
|
||
|
||
if (_axis.AxisPosition == AxisPosition.Top || _axis.AxisPosition == AxisPosition.Bottom)
|
||
{
|
||
rect.X = (float)Math.Min(fromPosition, toPosition);
|
||
rect.Width = (float)Math.Max(fromPosition, toPosition) - rect.X;
|
||
|
||
// Adjust label To/From position if offset labels are used
|
||
if (label.RowIndex == 0 &&
|
||
((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1)))
|
||
{
|
||
rect.X -= rect.Width / 2F;
|
||
rect.Width *= 2F;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
rect.Y = (float)Math.Min(fromPosition, toPosition);
|
||
rect.Height = (float)Math.Max(fromPosition, toPosition) - rect.Y;
|
||
|
||
// Adjust label To/From position if offset labels are used
|
||
if (label.RowIndex == 0 &&
|
||
((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1)))
|
||
{
|
||
rect.Y -= rect.Height / 2F;
|
||
rect.Height *= 2F;
|
||
}
|
||
}
|
||
|
||
// Draw label
|
||
using (Brush brush = new SolidBrush((label.ForeColor.IsEmpty) ? _foreColor : label.ForeColor))
|
||
{
|
||
graph.DrawLabelStringRel(_axis,
|
||
label.RowIndex,
|
||
label.LabelMark,
|
||
label.MarkColor,
|
||
label.Text,
|
||
label.Image,
|
||
label.ImageTransparentColor,
|
||
(_axis.autoLabelFont == null) ? _font : _axis.autoLabelFont,
|
||
brush,
|
||
rect,
|
||
format,
|
||
(_axis.autoLabelAngle < -90) ? angle : _axis.autoLabelAngle,
|
||
(!this.TruncatedLabels || label.RowIndex > 0) ? RectangleF.Empty : boundaryRect,
|
||
label,
|
||
truncatedLeft,
|
||
truncatedRight);
|
||
}
|
||
|
||
// Clear scale segment enforcement
|
||
_axis.ScaleSegments.EnforceSegment(null);
|
||
_axis.ScaleSegments.AllowOutOfScaleValues = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 3D Axis labels drawing methods
|
||
|
||
/// <summary>
|
||
/// Get a rectangle between chart area position and plotting area on specified side.
|
||
/// Also sets axis labels string formatting for the specified labels position.
|
||
/// </summary>
|
||
/// <param name="area">Chart area object.</param>
|
||
/// <param name="position">Position in chart area.</param>
|
||
/// <param name="stringFormat">Axis labels string format.</param>
|
||
/// <returns>Axis labels rectangle.</returns>
|
||
private RectangleF GetAllLabelsRect(ChartArea area, AxisPosition position, StringFormat stringFormat)
|
||
{
|
||
// Find axis with same position
|
||
Axis labelsAxis = null;
|
||
foreach(Axis curAxis in area.Axes)
|
||
{
|
||
if(curAxis.AxisPosition == position)
|
||
{
|
||
labelsAxis = curAxis;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if(labelsAxis == null)
|
||
{
|
||
return RectangleF.Empty;
|
||
}
|
||
|
||
// Calculate rect for different positions
|
||
RectangleF rectLabels = area.Position.ToRectangleF();
|
||
if( position == AxisPosition.Left )
|
||
{
|
||
rectLabels.Width = labelsAxis.labelSize;
|
||
if( labelsAxis.GetIsMarksNextToAxis() )
|
||
{
|
||
rectLabels.X = (float)labelsAxis.GetAxisPosition();
|
||
rectLabels.Width = (float)Math.Max(rectLabels.Width, rectLabels.X - labelsAxis.PlotAreaPosition.X);
|
||
}
|
||
else
|
||
{
|
||
rectLabels.X = labelsAxis.PlotAreaPosition.X;
|
||
}
|
||
|
||
rectLabels.X -= rectLabels.Width;
|
||
|
||
if(area.IsSideSceneWallOnLeft() || area.Area3DStyle.WallWidth == 0)
|
||
{
|
||
rectLabels.X -= labelsAxis.markSize;
|
||
}
|
||
|
||
// Set label text alignment
|
||
stringFormat.Alignment = StringAlignment.Far;
|
||
stringFormat.LineAlignment = StringAlignment.Center;
|
||
}
|
||
else if( position == AxisPosition.Right )
|
||
{
|
||
rectLabels.Width = labelsAxis.labelSize;
|
||
if( labelsAxis.GetIsMarksNextToAxis() )
|
||
{
|
||
rectLabels.X = (float)labelsAxis.GetAxisPosition();
|
||
rectLabels.Width = (float)Math.Max(rectLabels.Width, labelsAxis.PlotAreaPosition.Right - rectLabels.X);
|
||
}
|
||
else
|
||
{
|
||
rectLabels.X = labelsAxis.PlotAreaPosition.Right;
|
||
}
|
||
|
||
if(!area.IsSideSceneWallOnLeft() || area.Area3DStyle.WallWidth == 0)
|
||
{
|
||
rectLabels.X += labelsAxis.markSize;
|
||
}
|
||
|
||
// Set label text alignment
|
||
stringFormat.Alignment = StringAlignment.Near;
|
||
stringFormat.LineAlignment = StringAlignment.Center;
|
||
}
|
||
else if( position == AxisPosition.Top )
|
||
{
|
||
rectLabels.Height = labelsAxis.labelSize;
|
||
if( labelsAxis.GetIsMarksNextToAxis() )
|
||
{
|
||
rectLabels.Y = (float)labelsAxis.GetAxisPosition();
|
||
rectLabels.Height = (float)Math.Max(rectLabels.Height, rectLabels.Y - labelsAxis.PlotAreaPosition.Y);
|
||
}
|
||
else
|
||
{
|
||
rectLabels.Y = labelsAxis.PlotAreaPosition.Y;
|
||
}
|
||
|
||
rectLabels.Y -= rectLabels.Height;
|
||
|
||
if(area.Area3DStyle.WallWidth == 0)
|
||
{
|
||
rectLabels.Y -= labelsAxis.markSize;
|
||
}
|
||
|
||
// Set label text alignment
|
||
stringFormat.Alignment = StringAlignment.Center;
|
||
stringFormat.LineAlignment = StringAlignment.Far;
|
||
}
|
||
else if( position == AxisPosition.Bottom )
|
||
{
|
||
rectLabels.Height = labelsAxis.labelSize;
|
||
if( labelsAxis.GetIsMarksNextToAxis() )
|
||
{
|
||
rectLabels.Y = (float)labelsAxis.GetAxisPosition();
|
||
rectLabels.Height = (float)Math.Max(rectLabels.Height, labelsAxis.PlotAreaPosition.Bottom - rectLabels.Y);
|
||
}
|
||
else
|
||
{
|
||
rectLabels.Y = labelsAxis.PlotAreaPosition.Bottom;
|
||
}
|
||
rectLabels.Y += labelsAxis.markSize;
|
||
|
||
// Set label text alignment
|
||
stringFormat.Alignment = StringAlignment.Center;
|
||
stringFormat.LineAlignment = StringAlignment.Near;
|
||
}
|
||
|
||
return rectLabels;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets position of axis labels.
|
||
/// Top and Bottom axis labels can be drawn on the sides (left or right)
|
||
/// of the plotting area. If angle between axis and it's projection is
|
||
/// between -25 and 25 degrees the axis are drawn at the bottom/top,
|
||
/// otherwise labels are moved on the left or right side.
|
||
/// </summary>
|
||
/// <param name="axis">Axis object.</param>
|
||
/// <returns>Position where axis labels should be drawn.</returns>
|
||
private AxisPosition GetLabelsPosition(Axis axis)
|
||
{
|
||
// Get angle between 2D axis and it's 3D projection.
|
||
double axisAngle = axis.GetAxisProjectionAngle();
|
||
|
||
// Pick the side to draw the labels on
|
||
if(axis.AxisPosition == AxisPosition.Bottom)
|
||
{
|
||
if(axisAngle <= -25 )
|
||
return AxisPosition.Right;
|
||
else if(axisAngle >= 25 )
|
||
return AxisPosition.Left;
|
||
}
|
||
else if(axis.AxisPosition == AxisPosition.Top)
|
||
{
|
||
if(axisAngle <= -25 )
|
||
return AxisPosition.Left;
|
||
else if(axisAngle >= 25 )
|
||
return AxisPosition.Right;
|
||
}
|
||
|
||
// Labels are on the same side as the axis
|
||
return axis.AxisPosition;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Draws axis labels in 3D space.
|
||
/// </summary>
|
||
/// <param name="graph">Reference to the Chart Graphics object.</param>
|
||
/// <param name="backElements">Back elements of the axis should be drawn in 3D scene.</param>
|
||
internal void Paint3D( ChartGraphics graph, bool backElements )
|
||
{
|
||
// Label string drawing format
|
||
using (StringFormat format = new StringFormat())
|
||
{
|
||
format.Trimming = StringTrimming.EllipsisCharacter;
|
||
|
||
// Calculate single pixel size in relative coordinates
|
||
SizeF pixelSize = graph.GetRelativeSize(new SizeF(1f, 1f));
|
||
|
||
//********************************************************************
|
||
//** Determine the side of the plotting area to draw the labels on.
|
||
//********************************************************************
|
||
AxisPosition labelsPosition = GetLabelsPosition(_axis);
|
||
|
||
//*****************************************************************
|
||
//** Set the labels Z position
|
||
//*****************************************************************
|
||
bool axisOnEdge;
|
||
float labelsZPosition = _axis.GetMarksZPosition(out axisOnEdge);
|
||
|
||
// Adjust Z position for the "bent" tick marks
|
||
bool adjustForWallWidth = false;
|
||
if (this._axis.AxisPosition == AxisPosition.Top &&
|
||
!this._axis.ChartArea.ShouldDrawOnSurface(SurfaceNames.Top, backElements, false))
|
||
{
|
||
adjustForWallWidth = true;
|
||
}
|
||
if (this._axis.AxisPosition == AxisPosition.Left &&
|
||
!this._axis.ChartArea.ShouldDrawOnSurface(SurfaceNames.Left, backElements, false))
|
||
{
|
||
adjustForWallWidth = true;
|
||
}
|
||
if (this._axis.AxisPosition == AxisPosition.Right &&
|
||
!this._axis.ChartArea.ShouldDrawOnSurface(SurfaceNames.Right, backElements, false))
|
||
{
|
||
adjustForWallWidth = true;
|
||
}
|
||
|
||
if (adjustForWallWidth && this._axis.ChartArea.Area3DStyle.WallWidth > 0)
|
||
{
|
||
if (this._axis.MajorTickMark.TickMarkStyle == TickMarkStyle.InsideArea)
|
||
{
|
||
labelsZPosition -= this._axis.ChartArea.areaSceneWallWidth.Width;
|
||
}
|
||
else if (this._axis.MajorTickMark.TickMarkStyle == TickMarkStyle.OutsideArea)
|
||
{
|
||
labelsZPosition -= this._axis.MajorTickMark.Size + this._axis.ChartArea.areaSceneWallWidth.Width;
|
||
}
|
||
else if (this._axis.MajorTickMark.TickMarkStyle == TickMarkStyle.AcrossAxis)
|
||
{
|
||
labelsZPosition -= this._axis.MajorTickMark.Size / 2f + this._axis.ChartArea.areaSceneWallWidth.Width;
|
||
}
|
||
}
|
||
|
||
//*****************************************************************
|
||
//** Check if labels should be drawn as back or front element.
|
||
//*****************************************************************
|
||
bool labelsInsidePlotArea = (this._axis.GetIsMarksNextToAxis() && !axisOnEdge);
|
||
if (backElements == labelsInsidePlotArea)
|
||
{
|
||
// Skip drawing
|
||
return;
|
||
}
|
||
|
||
//********************************************************************
|
||
//** Initialize all labels position rectangle
|
||
//********************************************************************
|
||
RectangleF rectLabels = this.GetAllLabelsRect(this._axis.ChartArea, this._axis.AxisPosition, format);
|
||
|
||
//********************************************************************
|
||
//** Calculate bounding rectangle used to truncate labels on the
|
||
//** chart area boundary if TruncatedLabels property is set to true.
|
||
//********************************************************************
|
||
RectangleF boundaryRect = rectLabels;
|
||
if (boundaryRect != RectangleF.Empty && _axis.totlaGroupingLabelsSize > 0)
|
||
{
|
||
if (this._axis.AxisPosition == AxisPosition.Left)
|
||
{
|
||
boundaryRect.X += _axis.totlaGroupingLabelsSize;
|
||
boundaryRect.Width -= _axis.totlaGroupingLabelsSize;
|
||
}
|
||
else if (this._axis.AxisPosition == AxisPosition.Right)
|
||
{
|
||
boundaryRect.Width -= _axis.totlaGroupingLabelsSize;
|
||
}
|
||
else if (this._axis.AxisPosition == AxisPosition.Top)
|
||
{
|
||
boundaryRect.Y += _axis.totlaGroupingLabelsSize;
|
||
boundaryRect.Height -= _axis.totlaGroupingLabelsSize;
|
||
}
|
||
else if (this._axis.AxisPosition == AxisPosition.Bottom)
|
||
{
|
||
boundaryRect.Height -= _axis.totlaGroupingLabelsSize;
|
||
}
|
||
}
|
||
|
||
// Pre-calculated height of the first labels row
|
||
float firstLabelsRowHeight = -1f;
|
||
|
||
// For 3D axis labels the first row of labels
|
||
// has to be drawn after all other rows because
|
||
// of hot regions.
|
||
for (int selectionRow = 0; selectionRow <= this._axis.GetGroupLabelLevelCount(); selectionRow++)
|
||
{
|
||
//********************************************************************
|
||
//** Draw all labels from the collection
|
||
//********************************************************************
|
||
int labelIndex = 0;
|
||
foreach (CustomLabel label in this._axis.CustomLabels)
|
||
{
|
||
bool truncatedLeft = false;
|
||
bool truncatedRight = false;
|
||
double labelFrom = label.FromPosition;
|
||
double labelTo = label.ToPosition;
|
||
|
||
if (label.RowIndex != selectionRow)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
// Skip if label middle point is outside current scaleView
|
||
if (label.RowIndex == 0)
|
||
{
|
||
double middlePoint = (label.FromPosition + label.ToPosition) / 2.0;
|
||
if ((decimal)middlePoint < (decimal)_axis.ViewMinimum ||
|
||
(decimal)middlePoint > (decimal)_axis.ViewMaximum)
|
||
{
|
||
continue;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Skip labels completly outside the scaleView
|
||
if (label.ToPosition <= _axis.ViewMinimum || label.FromPosition >= _axis.ViewMaximum)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
// Check if label is partially visible
|
||
if (_axis.ScaleView.IsZoomed)
|
||
{
|
||
if (label.FromPosition < _axis.ViewMinimum)
|
||
{
|
||
truncatedLeft = true;
|
||
labelFrom = _axis.ViewMinimum;
|
||
}
|
||
if (label.ToPosition > _axis.ViewMaximum)
|
||
{
|
||
truncatedRight = true;
|
||
labelTo = _axis.ViewMaximum;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
// Calculate single label position
|
||
RectangleF rect = rectLabels;
|
||
|
||
// Label is in the first row
|
||
if (label.RowIndex == 0)
|
||
{
|
||
if (this._axis.AxisPosition == AxisPosition.Left)
|
||
{
|
||
if (!this._axis.GetIsMarksNextToAxis())
|
||
{
|
||
rect.X = rectLabels.Right - _axis.unRotatedLabelSize;
|
||
rect.Width = _axis.unRotatedLabelSize;
|
||
}
|
||
|
||
// Adjust label rectangle if offset labels are used
|
||
if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
|
||
{
|
||
rect.Width /= 2F;
|
||
if (labelIndex % 2 != 0F)
|
||
{
|
||
rect.X += rect.Width;
|
||
}
|
||
}
|
||
}
|
||
else if (this._axis.AxisPosition == AxisPosition.Right)
|
||
{
|
||
if (!this._axis.GetIsMarksNextToAxis())
|
||
{
|
||
rect.Width = _axis.unRotatedLabelSize;
|
||
}
|
||
|
||
// Adjust label rectangle if offset labels are used
|
||
if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
|
||
{
|
||
rect.Width /= 2F;
|
||
if (labelIndex % 2 != 0F)
|
||
{
|
||
rect.X += rect.Width;
|
||
}
|
||
}
|
||
}
|
||
else if (this._axis.AxisPosition == AxisPosition.Top)
|
||
{
|
||
if (!this._axis.GetIsMarksNextToAxis())
|
||
{
|
||
rect.Y = rectLabels.Bottom - _axis.unRotatedLabelSize;
|
||
rect.Height = _axis.unRotatedLabelSize;
|
||
}
|
||
|
||
// Adjust label rectangle if offset labels are used
|
||
if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
|
||
{
|
||
rect.Height /= 2F;
|
||
if (labelIndex % 2 != 0F)
|
||
{
|
||
rect.Y += rect.Height;
|
||
}
|
||
}
|
||
}
|
||
else if (this._axis.AxisPosition == AxisPosition.Bottom)
|
||
{
|
||
if (!this._axis.GetIsMarksNextToAxis())
|
||
{
|
||
rect.Height = _axis.unRotatedLabelSize;
|
||
}
|
||
|
||
// Adjust label rectangle if offset labels are used
|
||
if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
|
||
{
|
||
rect.Height /= 2F;
|
||
if (labelIndex % 2 != 0F)
|
||
{
|
||
rect.Y += rect.Height;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Increase label index
|
||
++labelIndex;
|
||
}
|
||
|
||
// Label is in the second row
|
||
else if (label.RowIndex > 0)
|
||
{
|
||
// Hide grouping labels (where index of row > 0) when they are displayed
|
||
// not on the same side as their axis. Fixes MS issue #64.
|
||
if (labelsPosition != this._axis.AxisPosition)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
if (_axis.AxisPosition == AxisPosition.Left)
|
||
{
|
||
rect.X += _axis.totlaGroupingLabelsSizeAdjustment;
|
||
for (int index = _axis.groupingLabelSizes.Length; index > label.RowIndex; index--)
|
||
{
|
||
rect.X += _axis.groupingLabelSizes[index - 1];
|
||
}
|
||
rect.Width = _axis.groupingLabelSizes[label.RowIndex - 1];
|
||
}
|
||
else if (_axis.AxisPosition == AxisPosition.Right)
|
||
{
|
||
rect.X = rect.Right - _axis.totlaGroupingLabelsSize - _axis.totlaGroupingLabelsSizeAdjustment;// + Axis.elementSpacing * 0.25f;
|
||
for (int index = 1; index < label.RowIndex; index++)
|
||
{
|
||
rect.X += _axis.groupingLabelSizes[index - 1];
|
||
}
|
||
rect.Width = _axis.groupingLabelSizes[label.RowIndex - 1];
|
||
}
|
||
else if (_axis.AxisPosition == AxisPosition.Top)
|
||
{
|
||
rect.Y += _axis.totlaGroupingLabelsSizeAdjustment;
|
||
for (int index = _axis.groupingLabelSizes.Length; index > label.RowIndex; index--)
|
||
{
|
||
rect.Y += _axis.groupingLabelSizes[index - 1];
|
||
}
|
||
rect.Height = _axis.groupingLabelSizes[label.RowIndex - 1];
|
||
}
|
||
if (_axis.AxisPosition == AxisPosition.Bottom)
|
||
{
|
||
rect.Y = rect.Bottom - _axis.totlaGroupingLabelsSize - _axis.totlaGroupingLabelsSizeAdjustment;
|
||
for (int index = 1; index < label.RowIndex; index++)
|
||
{
|
||
rect.Y += _axis.groupingLabelSizes[index - 1];
|
||
}
|
||
rect.Height = _axis.groupingLabelSizes[label.RowIndex - 1];
|
||
}
|
||
}
|
||
|
||
// Unknown label row value
|
||
else
|
||
{
|
||
throw (new InvalidOperationException(SR.ExceptionAxisLabelRowIndexMustBe1Or2));
|
||
}
|
||
|
||
//********************************************************************
|
||
//** Set label From and To coordinates.
|
||
//********************************************************************
|
||
double fromPosition = _axis.GetLinearPosition(labelFrom);
|
||
double toPosition = _axis.GetLinearPosition(labelTo);
|
||
if (this._axis.AxisPosition == AxisPosition.Top || this._axis.AxisPosition == AxisPosition.Bottom)
|
||
{
|
||
rect.X = (float)Math.Min(fromPosition, toPosition);
|
||
rect.Width = (float)Math.Max(fromPosition, toPosition) - rect.X;
|
||
if (rect.Width < pixelSize.Width)
|
||
{
|
||
rect.Width = pixelSize.Width;
|
||
}
|
||
|
||
// Adjust label To/From position if offset labels are used
|
||
if (label.RowIndex == 0 &&
|
||
((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1)))
|
||
{
|
||
rect.X -= rect.Width / 2F;
|
||
rect.Width *= 2F;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
rect.Y = (float)Math.Min(fromPosition, toPosition);
|
||
rect.Height = (float)Math.Max(fromPosition, toPosition) - rect.Y;
|
||
if (rect.Height < pixelSize.Height)
|
||
{
|
||
rect.Height = pixelSize.Height;
|
||
}
|
||
|
||
// Adjust label To/From position if offset labels are used
|
||
if (label.RowIndex == 0 &&
|
||
((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1)))
|
||
{
|
||
rect.Y -= rect.Height / 2F;
|
||
rect.Height *= 2F;
|
||
}
|
||
}
|
||
|
||
// Save original rect
|
||
RectangleF initialRect = new RectangleF(rect.Location, rect.Size);
|
||
|
||
//********************************************************************
|
||
//** Transform and adjust label rectangle coordinates in 3D space.
|
||
//********************************************************************
|
||
Point3D[] rectPoints = new Point3D[3];
|
||
if (this._axis.AxisPosition == AxisPosition.Left)
|
||
{
|
||
rectPoints[0] = new Point3D(rect.Right, rect.Y, labelsZPosition);
|
||
rectPoints[1] = new Point3D(rect.Right, rect.Y + rect.Height / 2f, labelsZPosition);
|
||
rectPoints[2] = new Point3D(rect.Right, rect.Bottom, labelsZPosition);
|
||
this._axis.ChartArea.matrix3D.TransformPoints(rectPoints);
|
||
rect.Y = rectPoints[0].Y;
|
||
rect.Height = rectPoints[2].Y - rect.Y;
|
||
rect.Width = rectPoints[1].X - rect.X;
|
||
}
|
||
else if (this._axis.AxisPosition == AxisPosition.Right)
|
||
{
|
||
rectPoints[0] = new Point3D(rect.X, rect.Y, labelsZPosition);
|
||
rectPoints[1] = new Point3D(rect.X, rect.Y + rect.Height / 2f, labelsZPosition);
|
||
rectPoints[2] = new Point3D(rect.X, rect.Bottom, labelsZPosition);
|
||
this._axis.ChartArea.matrix3D.TransformPoints(rectPoints);
|
||
rect.Y = rectPoints[0].Y;
|
||
rect.Height = rectPoints[2].Y - rect.Y;
|
||
rect.Width = rect.Right - rectPoints[1].X;
|
||
rect.X = rectPoints[1].X;
|
||
}
|
||
else if (this._axis.AxisPosition == AxisPosition.Top)
|
||
{
|
||
// Transform 3 points of the rectangle
|
||
rectPoints[0] = new Point3D(rect.X, rect.Bottom, labelsZPosition);
|
||
rectPoints[1] = new Point3D(rect.X + rect.Width / 2f, rect.Bottom, labelsZPosition);
|
||
rectPoints[2] = new Point3D(rect.Right, rect.Bottom, labelsZPosition);
|
||
this._axis.ChartArea.matrix3D.TransformPoints(rectPoints);
|
||
|
||
if (labelsPosition == AxisPosition.Top)
|
||
{
|
||
rect.X = rectPoints[0].X;
|
||
rect.Width = rectPoints[2].X - rect.X;
|
||
rect.Height = rectPoints[1].Y - rect.Y;
|
||
}
|
||
else if (labelsPosition == AxisPosition.Right)
|
||
{
|
||
RectangleF rightLabelsRect = this.GetAllLabelsRect(this._axis.ChartArea, labelsPosition, format);
|
||
rect.Y = rectPoints[0].Y;
|
||
rect.Height = rectPoints[2].Y - rect.Y;
|
||
rect.X = rectPoints[1].X;
|
||
rect.Width = rightLabelsRect.Right - rect.X;
|
||
}
|
||
else if (labelsPosition == AxisPosition.Left)
|
||
{
|
||
RectangleF rightLabelsRect = this.GetAllLabelsRect(this._axis.ChartArea, labelsPosition, format);
|
||
rect.Y = rectPoints[2].Y;
|
||
rect.Height = rectPoints[0].Y - rect.Y;
|
||
rect.X = rightLabelsRect.X;
|
||
rect.Width = rectPoints[1].X - rightLabelsRect.X;
|
||
}
|
||
}
|
||
else if (this._axis.AxisPosition == AxisPosition.Bottom)
|
||
{
|
||
// Transform 3 points of the rectangle
|
||
rectPoints[0] = new Point3D(rect.X, rect.Y, labelsZPosition);
|
||
rectPoints[1] = new Point3D(rect.X + rect.Width / 2f, rect.Y, labelsZPosition);
|
||
rectPoints[2] = new Point3D(rect.Right, rect.Y, labelsZPosition);
|
||
this._axis.ChartArea.matrix3D.TransformPoints(rectPoints);
|
||
|
||
if (labelsPosition == AxisPosition.Bottom)
|
||
{
|
||
rect.X = rectPoints[0].X;
|
||
rect.Width = rectPoints[2].X - rect.X;
|
||
rect.Height = rect.Bottom - rectPoints[1].Y;
|
||
rect.Y = rectPoints[1].Y;
|
||
}
|
||
else if (labelsPosition == AxisPosition.Right)
|
||
{
|
||
RectangleF rightLabelsRect = this.GetAllLabelsRect(this._axis.ChartArea, labelsPosition, format);
|
||
rect.Y = rectPoints[2].Y;
|
||
rect.Height = rectPoints[0].Y - rect.Y;
|
||
rect.X = rectPoints[1].X;
|
||
rect.Width = rightLabelsRect.Right - rect.X;
|
||
|
||
// Adjust label rect by shifting it down by quarter of the tick size
|
||
if (this._axis.autoLabelAngle == 0)
|
||
{
|
||
rect.Y += this._axis.markSize / 4f;
|
||
}
|
||
}
|
||
else if (labelsPosition == AxisPosition.Left)
|
||
{
|
||
RectangleF rightLabelsRect = this.GetAllLabelsRect(this._axis.ChartArea, labelsPosition, format);
|
||
rect.Y = rectPoints[0].Y;
|
||
rect.Height = rectPoints[2].Y - rect.Y;
|
||
rect.X = rightLabelsRect.X;
|
||
rect.Width = rectPoints[1].X - rightLabelsRect.X;
|
||
|
||
// Adjust label rect by shifting it down by quarter of the tick size
|
||
if (this._axis.autoLabelAngle == 0)
|
||
{
|
||
rect.Y += this._axis.markSize / 4f;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Find axis with same position
|
||
Axis labelsAxis = null;
|
||
foreach (Axis curAxis in this._axis.ChartArea.Axes)
|
||
{
|
||
if (curAxis.AxisPosition == labelsPosition)
|
||
{
|
||
labelsAxis = curAxis;
|
||
break;
|
||
}
|
||
}
|
||
|
||
//********************************************************************
|
||
//** Adjust font angles for Top and Bottom axis
|
||
//********************************************************************
|
||
int labelsFontAngle = (_axis.autoLabelAngle < -90) ? angle : _axis.autoLabelAngle;
|
||
if (labelsPosition != this._axis.AxisPosition)
|
||
{
|
||
if ((this._axis.AxisPosition == AxisPosition.Top || this._axis.AxisPosition == AxisPosition.Bottom) &&
|
||
(labelsFontAngle == 90 || labelsFontAngle == -90))
|
||
{
|
||
labelsFontAngle = 0;
|
||
}
|
||
else if (this._axis.AxisPosition == AxisPosition.Bottom)
|
||
{
|
||
if (labelsPosition == AxisPosition.Left && labelsFontAngle > 0)
|
||
{
|
||
labelsFontAngle = -labelsFontAngle;
|
||
}
|
||
else if (labelsPosition == AxisPosition.Right && labelsFontAngle < 0)
|
||
{
|
||
labelsFontAngle = -labelsFontAngle;
|
||
}
|
||
}
|
||
else if (this._axis.AxisPosition == AxisPosition.Top)
|
||
{
|
||
if (labelsPosition == AxisPosition.Left && labelsFontAngle < 0)
|
||
{
|
||
labelsFontAngle = -labelsFontAngle;
|
||
}
|
||
else if (labelsPosition == AxisPosition.Right && labelsFontAngle > 0)
|
||
{
|
||
labelsFontAngle = -labelsFontAngle;
|
||
}
|
||
}
|
||
}
|
||
|
||
//********************************************************************
|
||
//** NOTE: Code below improves chart labels readability in scenarios
|
||
//** described in MS issue #65.
|
||
//**
|
||
//** Prevent labels in the first row from overlapping the grouping
|
||
//** labels in the rows below. The solution only apply to the limited
|
||
//** use cases defined by the condition below.
|
||
//********************************************************************
|
||
StringFormatFlags oldFormatFlags = format.FormatFlags;
|
||
|
||
if (label.RowIndex == 0 &&
|
||
labelsFontAngle == 0 &&
|
||
_axis.groupingLabelSizes != null &&
|
||
_axis.groupingLabelSizes.Length > 0 &&
|
||
this._axis.AxisPosition == AxisPosition.Bottom &&
|
||
labelsPosition == AxisPosition.Bottom &&
|
||
!((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1)))
|
||
{
|
||
if (firstLabelsRowHeight == -1f)
|
||
{
|
||
// Calculate first labels row max height
|
||
Point3D[] labelPositionPoints = new Point3D[1];
|
||
labelPositionPoints[0] = new Point3D(initialRect.X, initialRect.Bottom - _axis.totlaGroupingLabelsSize - _axis.totlaGroupingLabelsSizeAdjustment, labelsZPosition);
|
||
this._axis.ChartArea.matrix3D.TransformPoints(labelPositionPoints);
|
||
|
||
float height = labelPositionPoints[0].Y - rect.Y;
|
||
|
||
firstLabelsRowHeight = (height > 0f) ? height : rect.Height;
|
||
}
|
||
|
||
// Resuse pre-calculated first labels row height
|
||
rect.Height = firstLabelsRowHeight;
|
||
|
||
// Change current string format to prevent strings to go out of the
|
||
// specified bounding rectangle
|
||
if ((format.FormatFlags & StringFormatFlags.LineLimit) == 0)
|
||
{
|
||
format.FormatFlags |= StringFormatFlags.LineLimit;
|
||
}
|
||
}
|
||
|
||
|
||
//********************************************************************
|
||
//** Draw label text.
|
||
//********************************************************************
|
||
|
||
using (Brush brush = new SolidBrush((label.ForeColor.IsEmpty) ? _foreColor : label.ForeColor))
|
||
{
|
||
graph.DrawLabelStringRel(
|
||
labelsAxis,
|
||
label.RowIndex,
|
||
label.LabelMark,
|
||
label.MarkColor,
|
||
label.Text,
|
||
label.Image,
|
||
label.ImageTransparentColor,
|
||
(_axis.autoLabelFont == null) ? _font : _axis.autoLabelFont,
|
||
brush,
|
||
rect,
|
||
format,
|
||
labelsFontAngle,
|
||
(!this.TruncatedLabels || label.RowIndex > 0) ? RectangleF.Empty : boundaryRect,
|
||
label,
|
||
truncatedLeft,
|
||
truncatedRight);
|
||
}
|
||
|
||
// Restore old string format that was temporary modified
|
||
if (format.FormatFlags != oldFormatFlags)
|
||
{
|
||
format.FormatFlags = oldFormatFlags;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Helper methods
|
||
|
||
/// <summary>
|
||
/// Sets the axis to which this object attached to.
|
||
/// </summary>
|
||
/// <returns>Axis object.</returns>
|
||
internal Axis Axis
|
||
{
|
||
set { _axis = value; }
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Invalidate chart picture
|
||
/// </summary>
|
||
internal override void Invalidate()
|
||
{
|
||
#if Microsoft_CONTROL
|
||
|
||
if(this._axis != null)
|
||
{
|
||
this._axis.Invalidate();
|
||
}
|
||
#endif
|
||
base.Invalidate();
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Label properties
|
||
|
||
/// <summary>
|
||
/// Gets or sets the interval offset of the label.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeData"),
|
||
Bindable(true),
|
||
SRDescription("DescriptionAttributeLabel_IntervalOffset"),
|
||
DefaultValue(Double.NaN),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute),
|
||
#endif
|
||
RefreshPropertiesAttribute(RefreshProperties.All),
|
||
TypeConverter(typeof(AxisElementIntervalValueConverter))
|
||
]
|
||
public double IntervalOffset
|
||
{
|
||
get
|
||
{
|
||
return intervalOffset;
|
||
}
|
||
set
|
||
{
|
||
intervalOffset = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// Gets the interval offset.
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
internal double GetIntervalOffset()
|
||
{
|
||
if(double.IsNaN(intervalOffset) && this._axis != null)
|
||
{
|
||
return this._axis.IntervalOffset;
|
||
}
|
||
return intervalOffset;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the unit of measurement of the label offset.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeData"),
|
||
Bindable(true),
|
||
DefaultValue(DateTimeIntervalType.NotSet),
|
||
SRDescription("DescriptionAttributeLabel_IntervalOffsetType"),
|
||
RefreshPropertiesAttribute(RefreshProperties.All),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute)
|
||
#endif
|
||
]
|
||
public DateTimeIntervalType IntervalOffsetType
|
||
{
|
||
get
|
||
{
|
||
return intervalOffsetType;
|
||
}
|
||
set
|
||
{
|
||
intervalOffsetType = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Gets the type of the interval offset.
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
internal DateTimeIntervalType GetIntervalOffsetType()
|
||
{
|
||
if(intervalOffsetType == DateTimeIntervalType.NotSet && this._axis != null)
|
||
{
|
||
return this._axis.IntervalOffsetType;
|
||
}
|
||
return intervalOffsetType;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the interval size of the label.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeData"),
|
||
Bindable(true),
|
||
DefaultValue(Double.NaN),
|
||
SRDescription("DescriptionAttributeLabel_Interval"),
|
||
TypeConverter(typeof(AxisElementIntervalValueConverter)),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute),
|
||
#endif
|
||
]
|
||
public double Interval
|
||
{
|
||
get
|
||
{
|
||
return interval;
|
||
}
|
||
set
|
||
{
|
||
interval = value;
|
||
|
||
// Reset original property value fields
|
||
if (this._axis != null)
|
||
{
|
||
this._axis.tempLabelInterval = interval;
|
||
}
|
||
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Gets the interval.
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
internal double GetInterval()
|
||
{
|
||
if(double.IsNaN(interval) && this._axis != null)
|
||
{
|
||
return this._axis.Interval;
|
||
}
|
||
return interval;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the unit of measurement of the interval size of the label.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeData"),
|
||
Bindable(true),
|
||
DefaultValue(DateTimeIntervalType.NotSet),
|
||
SRDescription("DescriptionAttributeLabel_IntervalType"),
|
||
RefreshPropertiesAttribute(RefreshProperties.All),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute)
|
||
#endif
|
||
]
|
||
public DateTimeIntervalType IntervalType
|
||
{
|
||
get
|
||
{
|
||
return intervalType;
|
||
}
|
||
set
|
||
{
|
||
intervalType = value;
|
||
|
||
// Reset original property value fields
|
||
if (this._axis != null)
|
||
{
|
||
this._axis.tempLabelIntervalType = intervalType;
|
||
}
|
||
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Gets the type of the interval.
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
internal DateTimeIntervalType GetIntervalType()
|
||
{
|
||
if(intervalType == DateTimeIntervalType.NotSet && this._axis != null)
|
||
{
|
||
return this._axis.IntervalType;
|
||
}
|
||
return intervalType;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the font of the label.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(typeof(Font), "Microsoft Sans Serif, 8pt"),
|
||
SRDescription("DescriptionAttributeLabel_Font"),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute)
|
||
#endif
|
||
]
|
||
public Font Font
|
||
{
|
||
get
|
||
{
|
||
return _font;
|
||
}
|
||
set
|
||
{
|
||
// Turn off labels autofitting
|
||
if (this._axis != null && this._axis.Common!=null && this._axis.Common.Chart != null)
|
||
{
|
||
if(!this._axis.Common.Chart.serializing)
|
||
{
|
||
this._axis.IsLabelAutoFit = false;
|
||
}
|
||
}
|
||
|
||
_font = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the fore color of the label.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(typeof(Color), "Black"),
|
||
SRDescription("DescriptionAttributeFontColor"),
|
||
NotifyParentPropertyAttribute(true),
|
||
TypeConverter(typeof(ColorConverter)),
|
||
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute)
|
||
#endif
|
||
]
|
||
public Color ForeColor
|
||
{
|
||
get
|
||
{
|
||
return _foreColor;
|
||
}
|
||
set
|
||
{
|
||
_foreColor = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a value that represents the angle at which font is drawn.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(0),
|
||
SRDescription("DescriptionAttributeLabel_FontAngle"),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute),
|
||
#endif
|
||
RefreshPropertiesAttribute(RefreshProperties.All)
|
||
]
|
||
public int Angle
|
||
{
|
||
get
|
||
{
|
||
return angle;
|
||
}
|
||
set
|
||
{
|
||
if(value < -90 || value > 90)
|
||
{
|
||
throw (new ArgumentOutOfRangeException("value", SR.ExceptionAxisLabelFontAngleInvalid));
|
||
}
|
||
|
||
// Turn of label offset if angle is not 0, 90 or -90
|
||
if(IsStaggered && value != 0 && value != -90 && value != 90)
|
||
{
|
||
IsStaggered = false;
|
||
}
|
||
|
||
// Turn off labels autofitting
|
||
if(this._axis != null && this._axis.Common!=null && this._axis.Common.Chart != null)
|
||
{
|
||
if (!this._axis.Common.Chart.serializing)
|
||
{
|
||
this._axis.IsLabelAutoFit = false;
|
||
}
|
||
}
|
||
|
||
angle = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a property which specifies whether the labels are shown with offset.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(false),
|
||
SRDescription("DescriptionAttributeLabel_OffsetLabels"),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute),
|
||
#endif
|
||
RefreshPropertiesAttribute(RefreshProperties.All)
|
||
]
|
||
public bool IsStaggered
|
||
{
|
||
get
|
||
{
|
||
return isStaggered;
|
||
}
|
||
set
|
||
{
|
||
// Make sure that angle is 0, 90 or -90
|
||
if(value && (this.Angle != 0 || this.Angle != -90 || this.Angle != 90))
|
||
{
|
||
this.Angle = 0;
|
||
}
|
||
|
||
// Turn off labels autofitting
|
||
if (this._axis != null && this._axis.Common != null && this._axis.Common.Chart != null)
|
||
{
|
||
if (!this._axis.Common.Chart.serializing)
|
||
{
|
||
this._axis.IsLabelAutoFit = false;
|
||
}
|
||
}
|
||
|
||
isStaggered = value;
|
||
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a property which specifies whether the labels are shown at axis ends.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(true),
|
||
SRDescription("DescriptionAttributeLabel_ShowEndLabels"),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute)
|
||
#endif
|
||
]
|
||
public bool IsEndLabelVisible
|
||
{
|
||
get
|
||
{
|
||
return _isEndLabelVisible;
|
||
}
|
||
set
|
||
{
|
||
_isEndLabelVisible = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a property which specifies whether the label can be truncated.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(false),
|
||
SRDescription("DescriptionAttributeLabel_TruncatedLabels"),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute)
|
||
#endif
|
||
]
|
||
public bool TruncatedLabels
|
||
{
|
||
get
|
||
{
|
||
return _truncatedLabels;
|
||
}
|
||
set
|
||
{
|
||
_truncatedLabels = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the formatting string for the label text.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(""),
|
||
SRDescription("DescriptionAttributeLabel_Format"),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute),
|
||
#endif
|
||
]
|
||
public string Format
|
||
{
|
||
get
|
||
{
|
||
return _format;
|
||
}
|
||
set
|
||
{
|
||
_format = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets a property which indicates whether the label is enabled.
|
||
/// </summary>
|
||
[
|
||
SRCategory("CategoryAttributeAppearance"),
|
||
Bindable(true),
|
||
DefaultValue(true),
|
||
SRDescription("DescriptionAttributeLabel_Enabled"),
|
||
#if !Microsoft_CONTROL
|
||
PersistenceMode(PersistenceMode.Attribute)
|
||
#endif
|
||
]
|
||
public bool Enabled
|
||
{
|
||
get
|
||
{
|
||
return _enabled;
|
||
}
|
||
set
|
||
{
|
||
_enabled = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region IDisposable Members
|
||
|
||
/// <summary>
|
||
/// Releases unmanaged and - optionally - managed resources
|
||
/// </summary>
|
||
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
|
||
protected override void Dispose(bool disposing)
|
||
{
|
||
if (disposing)
|
||
{
|
||
//Free managed resources
|
||
if (_fontCache!=null)
|
||
{
|
||
_fontCache.Dispose();
|
||
_fontCache = null;
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
}
|
||
}
|