1 //-------------------------------------------------------------
2 // <copyright company=
\92Microsoft Corporation
\92>
3 // Copyright © Microsoft Corporation. All Rights Reserved.
5 //-------------------------------------------------------------
6 // @owner=alexgor, deliant
7 //=================================================================
10 // Namespace: DataVisualization.Charting
12 // Classes: CustomLabelsCollection, CustomLabel, LabelStyle
14 // Purpose: LabelStyle and CustomLabel classes are used to determine
15 // chart axis labels. Labels can be automatically
16 // generated based on the series data or be
\93manually
\94
19 // Reviewed: AG - Jul 31, 2002
20 // AG - Microsoft 14, 2007
22 //===================================================================
24 #region Used namespaces
27 using System.Collections;
28 using System.Collections.Specialized;
29 using System.Collections.Generic;
30 using System.ComponentModel;
31 using System.ComponentModel.Design;
34 using System.Drawing.Design;
35 using System.Drawing.Drawing2D;
36 using System.Drawing.Text;
39 using System.Windows.Forms.DataVisualization.Charting.Data;
40 using System.Windows.Forms.DataVisualization.Charting.ChartTypes;
41 using System.Windows.Forms.DataVisualization.Charting.Utilities;
42 using System.Windows.Forms.DataVisualization.Charting.Borders3D;
43 using System.Windows.Forms.DataVisualization.Charting;
44 using System.Globalization;
45 using System.ComponentModel.Design.Serialization;
46 using System.Reflection;
50 using System.Web.UI.DataVisualization.Charting;
51 using System.Web.UI.DataVisualization.Charting.Data;
52 using System.Web.UI.DataVisualization.Charting.Utilities;
53 using System.Web.UI.DataVisualization.Charting.ChartTypes;
59 namespace System.Windows.Forms.DataVisualization.Charting
61 namespace System.Web.UI.DataVisualization.Charting
64 #region Labels enumerations
67 /// An enumeration that specifies a mark for custom labels.
69 public enum LabelMarkStyle
72 /// No label marks are used.
77 /// Labels use side marks.
82 /// Labels use line and side marks.
88 /// Draws a box around the label. The box always starts at the axis position.
95 /// An enumeration of custom grid lines and tick marks flags used in the custom labels.
98 public enum GridTickTypes
101 /// No tick mark or grid line are shown.
106 /// Tick mark is shown.
111 /// Grid line is shown.
116 /// Tick mark and grid line are shown.
118 All = TickMark | Gridline
123 /// An enumeration of label styles for circular chart area axis.
125 internal enum CircularAxisLabelsStyle
128 /// Style depends on number of labels.
133 /// Label text positions around the circular area.
138 /// Label text is always horizontal.
143 /// Label text has the same angle as circular axis.
150 /// The CustomLabelsCollection class is a strongly typed collection of
151 /// custom axis labels.
154 SRDescription("DescriptionAttributeCustomLabelsCollection_CustomLabelsCollection"),
157 [AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
158 [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
160 public class CustomLabelsCollection : ChartElementCollection<CustomLabel>
165 /// Custom labels collection object constructor
167 /// <param name="axis">Reference to the axis object.</param>
168 internal CustomLabelsCollection(Axis axis) : base(axis)
177 get { return Parent as Axis; }
181 #region Labels adding methods
184 /// Adds a custom label into the collection.
186 /// <param name="fromPosition">Label left position.</param>
187 /// <param name="toPosition">Label right position.</param>
188 /// <param name="text">Label text.</param>
189 /// <returns>Newly added item.</returns>
190 public CustomLabel Add(double fromPosition, double toPosition, string text)
192 CustomLabel label = new CustomLabel(fromPosition, toPosition, text, 0, LabelMarkStyle.None);
198 /// Adds one custom label into the collection. Custom label flag may be specified.
200 /// <param name="fromPosition">Label left position.</param>
201 /// <param name="toPosition">Label right position.</param>
202 /// <param name="text">Label text.</param>
203 /// <param name="customLabel">Indicates if label is custom (created by user).</param>
204 /// <returns>Newly added item.</returns>
205 internal CustomLabel Add(double fromPosition, double toPosition, string text, bool customLabel)
207 CustomLabel label = new CustomLabel(fromPosition, toPosition, text, 0, LabelMarkStyle.None);
208 label.customLabel = customLabel;
214 /// Adds a custom label into the collection.
216 /// <param name="fromPosition">Label left position.</param>
217 /// <param name="toPosition">Label right position.</param>
218 /// <param name="text">Label text.</param>
219 /// <param name="rowIndex">Label row index.</param>
220 /// <param name="markStyle">Label marking style.</param>
221 /// <returns>Newly added item.</returns>
222 public CustomLabel Add(double fromPosition, double toPosition, string text, int rowIndex, LabelMarkStyle markStyle)
224 CustomLabel label = new CustomLabel(fromPosition, toPosition, text, rowIndex, markStyle);
230 /// Adds a custom label into the collection.
232 /// <param name="fromPosition">Label left position.</param>
233 /// <param name="toPosition">Label right position.</param>
234 /// <param name="text">Label text.</param>
235 /// <param name="rowIndex">Label row index.</param>
236 /// <param name="markStyle">Label marking style.</param>
237 /// <returns>Index of newly added item.</returns>
238 /// <param name="gridTick">Custom grid line and tick mark flag.</param>
239 public CustomLabel Add(double fromPosition, double toPosition, string text, int rowIndex, LabelMarkStyle markStyle, GridTickTypes gridTick)
241 CustomLabel label = new CustomLabel(fromPosition, toPosition, text, rowIndex, markStyle, gridTick);
248 /// Adds multiple custom labels to the collection.
249 /// The labels will be DateTime labels with the specified interval type,
250 /// and will be generated for the axis range that is determined by the minimum and maximum arguments.
252 /// <param name="labelsStep">The label step determines how often the custom labels will be drawn.</param>
253 /// <param name="intervalType">Unit of measurement of the label step.</param>
254 /// <param name="min">Minimum value..</param>
255 /// <param name="max">Maximum value..</param>
256 /// <param name="format">Label text format.</param>
257 /// <param name="rowIndex">Label row index.</param>
258 /// <param name="markStyle">Label marking style.</param>
259 public void Add(double labelsStep, DateTimeIntervalType intervalType, double min, double max, string format, int rowIndex, LabelMarkStyle markStyle)
261 // Find labels range min/max values
265 !double.IsNaN(this.Axis.Minimum) &&
266 !double.IsNaN(this.Axis.Maximum))
268 min = this.Axis.Minimum;
269 max = this.Axis.Maximum;
271 double fromX = Math.Min(min, max);
272 double toX = Math.Max(min, max);
274 this.SuspendUpdates();
278 // Loop through all label points
279 double labelStart = fromX;
281 while (labelStart < toX)
283 // Determine label end location
284 if (intervalType == DateTimeIntervalType.Number)
286 labelEnd = labelStart + labelsStep;
288 else if (intervalType == DateTimeIntervalType.Milliseconds)
290 labelEnd = DateTime.FromOADate(labelStart).AddMilliseconds(labelsStep).ToOADate();
292 else if (intervalType == DateTimeIntervalType.Seconds)
294 labelEnd = DateTime.FromOADate(labelStart).AddSeconds(labelsStep).ToOADate();
296 else if (intervalType == DateTimeIntervalType.Minutes)
298 labelEnd = DateTime.FromOADate(labelStart).AddMinutes(labelsStep).ToOADate();
300 else if (intervalType == DateTimeIntervalType.Hours)
302 labelEnd = DateTime.FromOADate(labelStart).AddHours(labelsStep).ToOADate();
304 else if (intervalType == DateTimeIntervalType.Days)
306 labelEnd = DateTime.FromOADate(labelStart).AddDays(labelsStep).ToOADate();
308 else if (intervalType == DateTimeIntervalType.Weeks)
310 labelEnd = DateTime.FromOADate(labelStart).AddDays(7 * labelsStep).ToOADate();
312 else if (intervalType == DateTimeIntervalType.Months)
314 labelEnd = DateTime.FromOADate(labelStart).AddMonths((int)labelsStep).ToOADate();
316 else if (intervalType == DateTimeIntervalType.Years)
318 labelEnd = DateTime.FromOADate(labelStart).AddYears((int)labelsStep).ToOADate();
322 // Unsupported step type
323 throw (new ArgumentException(SR.ExceptionAxisLabelsIntervalTypeUnsupported(intervalType.ToString())));
330 // Generate label text
331 ChartValueType valueType = ChartValueType.Double;
332 if (intervalType != DateTimeIntervalType.Number)
334 if (this.Axis.GetAxisValuesType() == ChartValueType.DateTimeOffset)
335 valueType = ChartValueType.DateTimeOffset;
337 valueType = ChartValueType.DateTime;
339 string text = ValueConverter.FormatValue(
343 labelStart + (labelEnd - labelStart) / 2,
346 ChartElementType.AxisLabels);
349 CustomLabel label = new CustomLabel(labelStart, labelEnd, text, rowIndex, markStyle);
352 labelStart = labelEnd;
357 this.ResumeUpdates();
362 /// Adds multiple custom labels to the collection.
363 /// The labels will be DateTime labels with the specified interval type,
364 /// and will be generated for the axis range that is determined by the minimum and maximum arguments.
366 /// <param name="labelsStep">The label step determines how often the custom labels will be drawn.</param>
367 /// <param name="intervalType">Unit of measurement of the label step.</param>
368 public void Add(double labelsStep, DateTimeIntervalType intervalType)
370 Add(labelsStep, intervalType, 0, 0, "", 0, LabelMarkStyle.None);
374 /// Adds multiple custom labels to the collection.
375 /// The labels will be DateTime labels with the specified interval type,
376 /// and will be generated for the axis range that is determined by the minimum and maximum arguments.
378 /// <param name="labelsStep">The label step determines how often the custom labels will be drawn.</param>
379 /// <param name="intervalType">Unit of measurement of the label step.</param>
380 /// <param name="format">Label text format.</param>
381 public void Add(double labelsStep, DateTimeIntervalType intervalType, string format)
383 Add(labelsStep, intervalType, 0, 0, format, 0, LabelMarkStyle.None);
387 /// Adds multiple custom labels to the collection.
388 /// The labels will be DateTime labels with the specified interval type,
389 /// and will be generated for the axis range that is determined by the minimum and maximum arguments.
391 /// <param name="labelsStep">The label step determines how often the custom labels will be drawn.</param>
392 /// <param name="intervalType">Unit of measurement of the label step.</param>
393 /// <param name="format">Label text format.</param>
394 /// <param name="rowIndex">Label row index.</param>
395 /// <param name="markStyle">Label marking style.</param>
396 public void Add(double labelsStep, DateTimeIntervalType intervalType, string format, int rowIndex, LabelMarkStyle markStyle)
398 Add(labelsStep, intervalType, 0, 0, format, rowIndex, markStyle);
407 /// The CustomLabel class represents a single custom axis label. Text and
408 /// position along the axis is provided by the caller.
411 SRDescription("DescriptionAttributeCustomLabel_CustomLabel"),
412 DefaultProperty("Text"),
414 #if Microsoft_CONTROL
415 public class CustomLabel : ChartNamedElement
418 [AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
419 [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
421 public class CustomLabel : ChartNamedElement, IChartMapArea
424 #region Fields and Constructors
426 // Private data members, which store properties values
427 private double _fromPosition = 0;
428 private double _toPosition = 0;
429 private string _text = "";
430 private LabelMarkStyle _labelMark = LabelMarkStyle.None;
431 private Color _foreColor = Color.Empty;
432 private Color _markColor = Color.Empty;
433 private int _labelRowIndex = 0;
435 // Custom grid lines and tick marks flags
436 private GridTickTypes _gridTick = GridTickTypes.None;
438 // Indicates if label was automatically created or cpecified by user (custom)
439 internal bool customLabel = true;
441 // Image associated with the label
442 private string _image = string.Empty;
444 // Image transparent color
445 private Color _imageTransparentColor = Color.Empty;
448 private string _tooltip = string.Empty;
450 private Axis _axis = null;
451 #if !Microsoft_CONTROL
453 // URL target of the label image.
454 private string _imageUrl = string.Empty;
456 // Other attributes of the label image map area.
457 private string _imageMapAreaAttributes = string.Empty;
459 private string _imagePostbackValue = String.Empty;
462 private string _url = string.Empty;
464 // Other attributes of the label image map area.
465 private string _mapAreaAttributes = string.Empty;
467 private string _postbackValue = String.Empty;
470 #endif // !Microsoft_CONTROL
479 /// Default constructor
486 /// CustomLabel constructor
488 /// <param name="fromPosition">From position.</param>
489 /// <param name="toPosition">To position.</param>
490 /// <param name="text">Label text.</param>
491 /// <param name="labelRow">Label row index.</param>
492 /// <param name="markStyle">Label mark style.</param>
493 public CustomLabel(double fromPosition, double toPosition, string text, int labelRow, LabelMarkStyle markStyle)
495 this._fromPosition = fromPosition;
496 this._toPosition = toPosition;
498 this._labelRowIndex = labelRow;
499 this._labelMark = markStyle;
500 this._gridTick = GridTickTypes.None;
504 /// CustomLabel constructor
506 /// <param name="fromPosition">From position.</param>
507 /// <param name="toPosition">To position.</param>
508 /// <param name="text">Label text.</param>
509 /// <param name="labelRow">Label row index.</param>
510 /// <param name="markStyle">Label mark style.</param>
511 /// <param name="gridTick">Custom grid line and tick marks flag.</param>
512 public CustomLabel(double fromPosition, double toPosition, string text, int labelRow, LabelMarkStyle markStyle, GridTickTypes gridTick)
514 this._fromPosition = fromPosition;
515 this._toPosition = toPosition;
517 this._labelRowIndex = labelRow;
518 this._labelMark = markStyle;
519 this._gridTick = gridTick;
524 #region Helper methods
527 /// Returns a cloned label object.
529 /// <returns>Copy of current custom label.</returns>
530 public CustomLabel Clone()
532 CustomLabel newLabel = new CustomLabel();
534 newLabel.FromPosition = this.FromPosition;
535 newLabel.ToPosition = this.ToPosition;
536 newLabel.Text = this.Text;
537 newLabel.ForeColor = this.ForeColor;
538 newLabel.MarkColor = this.MarkColor;
539 newLabel.RowIndex = this.RowIndex;
540 newLabel.LabelMark = this.LabelMark;
541 newLabel.GridTicks = this.GridTicks;
545 newLabel.ToolTip = this.ToolTip;
546 newLabel.Tag = this.Tag;
547 newLabel.Image = this.Image;
548 newLabel.ImageTransparentColor = this.ImageTransparentColor;
550 #if !Microsoft_CONTROL
551 newLabel.Url = this.Url;
552 newLabel.MapAreaAttributes = this.MapAreaAttributes;
553 newLabel.ImageUrl = this.ImageUrl;
554 newLabel.ImageMapAreaAttributes = this.ImageMapAreaAttributes;
555 #endif // !Microsoft_CONTROL
562 internal override IChartElement Parent
573 _axis = Parent.Parent as Axis;
579 /// Gets the axis to which this object is attached to.
581 /// <returns>Axis.</returns>
584 DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
585 SerializationVisibilityAttribute(SerializationVisibility.Hidden),
597 #region CustomLabel properties
600 /// Gets or sets the tooltip of the custom label.
603 #if !Microsoft_CONTROL
604 PersistenceMode(PersistenceMode.Attribute),
605 #endif //!Microsoft_CONTROL
606 SRCategory("CategoryAttributeMapArea"),
608 SRDescription("DescriptionAttributeToolTip"),
611 public string ToolTip
615 this._tooltip = value;
619 return this._tooltip;
624 #if !Microsoft_CONTROL
627 /// URL target of the custom label.
630 SRCategory("CategoryAttributeMapArea"),
632 SRDescription("DescriptionAttributeUrl"),
634 PersistenceMode(PersistenceMode.Attribute),
635 Editor(Editors.UrlValueEditor.Editor, Editors.UrlValueEditor.Base)
650 /// Gets or sets the other attributes of the custom label map area.
653 SRCategory("CategoryAttributeMapArea"),
655 SRDescription("DescriptionAttributeMapAreaAttributes"),
657 PersistenceMode(PersistenceMode.Attribute)
659 public string MapAreaAttributes
663 this._mapAreaAttributes = value;
667 return this._mapAreaAttributes;
672 /// Gets or sets the postback value which can be processed on a click event.
674 /// <value>The value which is passed to a click event as an argument.</value>
676 [SRCategory(SR.Keys.CategoryAttributeMapArea)]
677 [SRDescription(SR.Keys.DescriptionAttributePostBackValue)]
678 public string PostBackValue
682 return this._postbackValue;
686 this._postbackValue = value;
691 /// Gets or sets the URL target of the custom label image.
694 SRCategory("CategoryAttributeMapArea"),
696 SRDescription("DescriptionAttributeCustomLabel_ImageUrl"),
698 PersistenceMode(PersistenceMode.Attribute),
699 Editor(Editors.UrlValueEditor.Editor, Editors.UrlValueEditor.Base),
700 System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")
702 public string ImageUrl
706 this._imageUrl = value;
710 return this._imageUrl;
715 /// Gets or sets the other attributes of the map area of the custom label image.
718 SRCategory("CategoryAttributeMapArea"),
720 SRDescription("DescriptionAttributeMapAreaAttributes"),
722 PersistenceMode(PersistenceMode.Attribute)
724 public string ImageMapAreaAttributes
728 this._imageMapAreaAttributes = value;
732 return this._imageMapAreaAttributes;
737 /// Gets or sets the postback value which can be processed on a click event.
739 /// <value>The value which is passed to a click event as an argument.</value>
741 [SRCategory(SR.Keys.CategoryAttributeMapArea)]
742 [SRDescription(SR.Keys.DescriptionAttributePostBackValue)]
743 public string ImagePostBackValue
747 return this._imagePostbackValue;
751 this._imagePostbackValue = value;
756 #endif // !Microsoft_CONTROL
759 /// Gets or sets the label image.
762 SRCategory("CategoryAttributeAppearance"),
765 SRDescription("DescriptionAttributeCustomLabel_Image"),
766 Editor(Editors.ImageValueEditor.Editor, Editors.ImageValueEditor.Base),
767 #if !Microsoft_CONTROL
768 PersistenceMode(PersistenceMode.Attribute),
770 NotifyParentPropertyAttribute(true)
786 /// Gets or sets a color which will be replaced with a transparent color while drawing the image.
789 SRCategory("CategoryAttributeAppearance"),
791 DefaultValue(typeof(Color), ""),
792 NotifyParentPropertyAttribute(true),
793 SRDescription("DescriptionAttributeImageTransparentColor"),
794 TypeConverter(typeof(ColorConverter)),
795 Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
796 #if !Microsoft_CONTROL
797 PersistenceMode(PersistenceMode.Attribute)
800 public Color ImageTransparentColor
804 return _imageTransparentColor;
808 _imageTransparentColor = value;
816 /// Custom label name. This property is for internal use only.
819 SRCategory("CategoryAttributeAppearance"),
820 SRDescription("DescriptionAttributeCustomLabel_Name"),
821 DefaultValue("Custom LabelStyle"),
822 DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
823 DesignOnlyAttribute(true),
824 SerializationVisibilityAttribute(SerializationVisibility.Hidden)
826 public override string Name
839 /// Gets or sets a property which specifies whether
840 /// custom tick marks and grid lines will be drawn in the center of the label.
843 SRCategory("CategoryAttributeAppearance"),
845 DefaultValue(GridTickTypes.None),
846 SRDescription("DescriptionAttributeCustomLabel_GridTicks"),
847 Editor(Editors.FlagsEnumUITypeEditor.Editor, Editors.FlagsEnumUITypeEditor.Base)
849 public GridTickTypes GridTicks
863 /// Gets or sets the end position of the custom label in axis coordinates.
866 SRCategory("CategoryAttributeAppearance"),
869 SRDescription("DescriptionAttributeCustomLabel_From"),
870 #if !Microsoft_CONTROL
871 PersistenceMode(PersistenceMode.Attribute),
873 TypeConverter(typeof(AxisLabelDateValueConverter))
875 public double FromPosition
879 return _fromPosition;
883 _fromPosition = value;
889 /// Gets or sets the starting position of the custom label in axis coordinates.
892 SRCategory("CategoryAttributeAppearance"),
895 SRDescription("DescriptionAttributeCustomLabel_To"),
896 #if !Microsoft_CONTROL
897 PersistenceMode(PersistenceMode.Attribute),
899 TypeConverter(typeof(AxisLabelDateValueConverter))
901 public double ToPosition
915 /// Gets or sets the text of the custom label.
918 SRCategory("CategoryAttributeAppearance"),
921 SRDescription("DescriptionAttributeCustomLabel_Text"),
922 #if !Microsoft_CONTROL
923 PersistenceMode(PersistenceMode.Attribute)
940 /// Gets or sets the text color of the custom label.
943 SRCategory("CategoryAttributeAppearance"),
945 DefaultValue(typeof(Color), ""),
946 SRDescription("DescriptionAttributeForeColor"),
947 NotifyParentPropertyAttribute(true),
948 TypeConverter(typeof(ColorConverter)),
949 Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
950 #if !Microsoft_CONTROL
951 PersistenceMode(PersistenceMode.Attribute)
954 public Color ForeColor
968 /// Gets or sets the color of the label mark line of the custom label.
971 SRCategory("CategoryAttributeAppearance"),
973 DefaultValue(typeof(Color), ""),
974 SRDescription("DescriptionAttributeCustomLabel_MarkColor"),
975 NotifyParentPropertyAttribute(true),
976 TypeConverter(typeof(ColorConverter)),
977 Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
978 #if !Microsoft_CONTROL
979 PersistenceMode(PersistenceMode.Attribute)
982 public Color MarkColor
996 /// Gets or sets the row index of the custom label.
999 SRCategory("CategoryAttributeAppearance"),
1002 SRDescription("DescriptionAttributeCustomLabel_RowIndex"),
1003 #if !Microsoft_CONTROL
1004 PersistenceMode(PersistenceMode.Attribute)
1011 return this._labelRowIndex;
1017 throw (new InvalidOperationException(SR.ExceptionAxisLabelRowIndexIsNegative));
1020 this._labelRowIndex = value;
1026 /// Gets or sets a property which define the marks for the labels in the second row.
1029 SRCategory("CategoryAttributeAppearance"),
1031 DefaultValue(LabelMarkStyle.None),
1032 SRDescription("DescriptionAttributeCustomLabel_LabelMark"),
1033 #if !Microsoft_CONTROL
1034 PersistenceMode(PersistenceMode.Attribute)
1037 public LabelMarkStyle LabelMark
1055 /// The LabelStyle class contains properties which define the visual appearance of
1056 /// the axis labels, their interval and position. This class is also
1057 /// responsible for calculating the position of all the labels and
1061 SRDescription("DescriptionAttributeLabel_Label"),
1062 DefaultProperty("Enabled"),
1065 [AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
1066 [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
1068 public class LabelStyle : ChartElement
1072 // Reference to the Axis
1073 private Axis _axis = null;
1075 // Private data members, which store properties values
1076 private bool _enabled = true;
1078 internal double intervalOffset = double.NaN;
1079 internal double interval = double.NaN;
1080 internal DateTimeIntervalType intervalType = DateTimeIntervalType.NotSet;
1081 internal DateTimeIntervalType intervalOffsetType = DateTimeIntervalType.NotSet;
1083 private FontCache _fontCache = new FontCache();
1085 private Color _foreColor = Color.Black;
1086 internal int angle = 0;
1087 internal bool isStaggered = false;
1088 private bool _isEndLabelVisible = true;
1089 private bool _truncatedLabels = false;
1090 private string _format = "";
1094 #region Constructors
1097 /// Public default constructor.
1101 _font = _fontCache.DefaultFont;
1105 /// Public constructor.
1107 /// <param name="axis">Axis which owns the grid.</param>
1108 internal LabelStyle(Axis axis)
1116 #region Axis labels drawing methods
1119 /// Draws axis labels on the circular chart area.
1121 /// <param name="graph">Reference to the Chart Graphics object.</param>
1122 internal void PaintCircular( ChartGraphics graph )
1124 // Label string drawing format
1125 using (StringFormat format = new StringFormat())
1127 format.FormatFlags |= StringFormatFlags.LineLimit;
1128 format.Trimming = StringTrimming.EllipsisCharacter;
1130 // Labels are disabled for this axis
1131 if (!_axis.LabelStyle.Enabled)
1134 // Draw text with anti-aliasing
1136 if( (graph.AntiAliasing & AntiAliasing.Text) == AntiAliasing.Text )
1138 graph.TextRenderingHint = TextRenderingHint.AntiAlias;
1142 graph.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
1146 // Gets axis labels style
1147 CircularAxisLabelsStyle labelsStyle = this._axis.ChartArea.GetCircularAxisLabelsStyle();
1149 // Get list of circular axes with labels
1150 ArrayList circularAxes = this._axis.ChartArea.GetCircularAxisList();
1152 // Draw each axis label
1154 foreach (CircularChartAreaAxis circAxis in circularAxes)
1156 if (circAxis.Title.Length > 0)
1158 //******************************************************************
1159 //** Calculate label position corner position
1160 //******************************************************************
1161 PointF labelRelativePosition = new PointF(
1162 this._axis.ChartArea.circularCenter.X,
1163 this._axis.ChartArea.PlotAreaPosition.Y);
1165 // Adjust labels Y position
1166 labelRelativePosition.Y -= _axis.markSize + Axis.elementSpacing;
1168 // Convert to absolute
1169 PointF[] labelPosition = new PointF[] { graph.GetAbsolutePoint(labelRelativePosition) };
1171 // Get label rotation angle
1172 float labelAngle = circAxis.AxisPosition;
1173 ICircularChartType chartType = this._axis.ChartArea.GetCircularChartType();
1174 if (chartType != null && chartType.XAxisCrossingSupported())
1176 if (!double.IsNaN(this._axis.ChartArea.AxisX.Crossing))
1178 labelAngle += (float)this._axis.ChartArea.AxisX.Crossing;
1182 // Make sure angle is presented as a positive number
1183 while (labelAngle < 0)
1185 labelAngle = 360f + labelAngle;
1188 // Set graphics rotation matrix
1189 Matrix newMatrix = new Matrix();
1190 newMatrix.RotateAt(labelAngle, graph.GetAbsolutePoint(this._axis.ChartArea.circularCenter));
1191 newMatrix.TransformPoints(labelPosition);
1193 // Set text alignment
1194 format.LineAlignment = StringAlignment.Center;
1195 format.Alignment = StringAlignment.Near;
1196 if (labelsStyle != CircularAxisLabelsStyle.Radial)
1198 if (labelAngle < 5f || labelAngle > 355f)
1200 format.Alignment = StringAlignment.Center;
1201 format.LineAlignment = StringAlignment.Far;
1203 if (labelAngle < 185f && labelAngle > 175f)
1205 format.Alignment = StringAlignment.Center;
1206 format.LineAlignment = StringAlignment.Near;
1208 if (labelAngle > 185f && labelAngle < 355f)
1210 format.Alignment = StringAlignment.Far;
1215 if (labelAngle > 180f)
1217 format.Alignment = StringAlignment.Far;
1222 // Set text rotation angle
1223 float textAngle = labelAngle;
1224 if (labelsStyle == CircularAxisLabelsStyle.Radial)
1226 if (labelAngle > 180)
1235 else if (labelsStyle == CircularAxisLabelsStyle.Circular)
1237 format.Alignment = StringAlignment.Center;
1238 format.LineAlignment = StringAlignment.Far;
1241 // Set text rotation matrix
1242 Matrix oldMatrix = graph.Transform;
1243 if (labelsStyle == CircularAxisLabelsStyle.Radial || labelsStyle == CircularAxisLabelsStyle.Circular)
1245 Matrix textRotationMatrix = oldMatrix.Clone();
1246 textRotationMatrix.RotateAt(textAngle, labelPosition[0]);
1247 graph.Transform = textRotationMatrix;
1250 // Get axis titl (label) color
1251 Color labelColor = _foreColor;
1252 if (!circAxis.TitleForeColor.IsEmpty)
1254 labelColor = circAxis.TitleForeColor;
1258 using (Brush brush = new SolidBrush(labelColor))
1261 circAxis.Title.Replace("\\n", "\n"),
1262 (_axis.autoLabelFont == null) ? _font : _axis.autoLabelFont,
1268 // Process selection region
1269 if (this._axis.Common.ProcessModeRegions)
1271 SizeF size = graph.MeasureString(circAxis.Title.Replace("\\n", "\n"), (_axis.autoLabelFont == null) ? _font : _axis.autoLabelFont);
1272 RectangleF labelRect = GetLabelPosition(
1276 PointF[] points = new PointF[]
1279 new PointF(labelRect.Right, labelRect.Y),
1280 new PointF(labelRect.Right, labelRect.Bottom),
1281 new PointF(labelRect.X, labelRect.Bottom)
1284 using (GraphicsPath path = new GraphicsPath())
1286 path.AddPolygon(points);
1287 path.CloseAllFigures();
1288 path.Transform(graph.Transform);
1289 this._axis.Common.HotRegionsList.AddHotRegion(
1292 ChartElementType.AxisLabels,
1298 if(labelsStyle == CircularAxisLabelsStyle.Radial || labelsStyle == CircularAxisLabelsStyle.Circular)
1300 graph.Transform = oldMatrix;
1311 /// Gets rectangle position of the label.
1313 /// <param name="position">Original label position.</param>
1314 /// <param name="size">Label text size.</param>
1315 /// <param name="format">Label string format.</param>
1316 /// <returns>Label rectangle position.</returns>
1317 internal static RectangleF GetLabelPosition(
1320 StringFormat format)
1322 // Calculate label position rectangle
1323 RectangleF labelPosition = RectangleF.Empty;
1324 labelPosition.Width = size.Width;
1325 labelPosition.Height = size.Height;
1327 if(format.Alignment == StringAlignment.Far)
1329 labelPosition.X = position.X - size.Width;
1331 else if(format.Alignment == StringAlignment.Near)
1333 labelPosition.X = position.X;
1335 else if(format.Alignment == StringAlignment.Center)
1337 labelPosition.X = position.X - size.Width/2F;
1340 if(format.LineAlignment == StringAlignment.Far)
1342 labelPosition.Y = position.Y - size.Height;
1344 else if(format.LineAlignment == StringAlignment.Near)
1346 labelPosition.Y = position.Y;
1348 else if(format.LineAlignment == StringAlignment.Center)
1350 labelPosition.Y = position.Y - size.Height/2F;
1353 return labelPosition;
1357 /// Draws axis labels.
1359 /// <param name="graph">Reference to the Chart Graphics object.</param>
1360 /// <param name="backElements">Back elements of the axis should be drawn in 3D scene.</param>
1361 internal void Paint( ChartGraphics graph, bool backElements )
1363 // Label string drawing format
1364 using (StringFormat format = new StringFormat())
1366 format.FormatFlags |= StringFormatFlags.LineLimit;
1367 format.Trimming = StringTrimming.EllipsisCharacter;
1369 // Labels are disabled for this axis
1370 if (!_axis.LabelStyle.Enabled)
1372 // deliant fix-> VSTS #157848, #143286 - drawing custom label in empty axis
1373 if (Double.IsNaN(_axis.ViewMinimum) || Double.IsNaN(_axis.ViewMaximum))
1377 // Draw labels in 3D space
1378 if (this._axis.ChartArea.Area3DStyle.Enable3D && !this._axis.ChartArea.chartAreaIsCurcular)
1380 this.Paint3D(graph, backElements);
1384 // Initialize all labels position rectangle
1385 RectangleF rectLabels = _axis.ChartArea.Position.ToRectangleF();
1386 float labelSize = _axis.labelSize;
1388 if (_axis.AxisPosition == AxisPosition.Left)
1390 rectLabels.Width = labelSize;
1391 if (_axis.GetIsMarksNextToAxis())
1392 rectLabels.X = (float)_axis.GetAxisPosition();
1394 rectLabels.X = _axis.PlotAreaPosition.X;
1396 rectLabels.X -= labelSize + _axis.markSize;
1398 // Set label text alignment
1399 format.Alignment = StringAlignment.Far;
1400 format.LineAlignment = StringAlignment.Center;
1402 else if (_axis.AxisPosition == AxisPosition.Right)
1404 rectLabels.Width = labelSize;
1405 if (_axis.GetIsMarksNextToAxis())
1406 rectLabels.X = (float)_axis.GetAxisPosition();
1408 rectLabels.X = _axis.PlotAreaPosition.Right;
1409 rectLabels.X += _axis.markSize;
1411 // Set label text alignment
1412 format.Alignment = StringAlignment.Near;
1413 format.LineAlignment = StringAlignment.Center;
1415 else if (_axis.AxisPosition == AxisPosition.Top)
1417 rectLabels.Height = labelSize;
1418 if (_axis.GetIsMarksNextToAxis())
1419 rectLabels.Y = (float)_axis.GetAxisPosition();
1421 rectLabels.Y = _axis.PlotAreaPosition.Y;
1422 rectLabels.Y -= labelSize + _axis.markSize;
1424 // Set label text alignment
1425 format.Alignment = StringAlignment.Center;
1426 format.LineAlignment = StringAlignment.Far;
1428 else if (_axis.AxisPosition == AxisPosition.Bottom)
1430 rectLabels.Height = labelSize;
1431 if (_axis.GetIsMarksNextToAxis())
1432 rectLabels.Y = (float)_axis.GetAxisPosition();
1434 rectLabels.Y = _axis.PlotAreaPosition.Bottom;
1435 rectLabels.Y += _axis.markSize;
1437 // Set label text alignment
1438 format.Alignment = StringAlignment.Center;
1439 format.LineAlignment = StringAlignment.Near;
1442 // Calculate bounding rectangle
1443 RectangleF boundaryRect = rectLabels;
1444 if (boundaryRect != RectangleF.Empty && _axis.totlaGroupingLabelsSize > 0)
1446 if (_axis.AxisPosition == AxisPosition.Left)
1448 boundaryRect.X += _axis.totlaGroupingLabelsSize;
1449 boundaryRect.Width -= _axis.totlaGroupingLabelsSize;
1451 else if (_axis.AxisPosition == AxisPosition.Right)
1453 boundaryRect.Width -= _axis.totlaGroupingLabelsSize;
1455 else if (_axis.AxisPosition == AxisPosition.Top)
1457 boundaryRect.Y += _axis.totlaGroupingLabelsSize;
1458 boundaryRect.Height -= _axis.totlaGroupingLabelsSize;
1460 else if (_axis.AxisPosition == AxisPosition.Bottom)
1462 boundaryRect.Height -= _axis.totlaGroupingLabelsSize;
1466 // Check if the AJAX zooming and scrolling mode is enabled.
1467 // Labels are drawn slightly different in this case.
1468 bool ajaxScrollingEnabled = false;
1469 bool firstFrame = true;
1470 bool lastFrame = true;
1472 // Draw all labels from the collection
1474 foreach (CustomLabel label in this._axis.CustomLabels)
1476 bool truncatedLeft = false;
1477 bool truncatedRight = false;
1478 double labelFrom = label.FromPosition;
1479 double labelTo = label.ToPosition;
1480 bool useRelativeCoordiantes = false;
1481 double labelFromRelative = double.NaN;
1482 double labelToRelative = double.NaN;
1484 // Skip if label middle point is outside current scaleView
1485 if (label.RowIndex == 0)
1487 double middlePoint = (label.FromPosition + label.ToPosition) / 2.0;
1488 decimal viewMin = (decimal)_axis.ViewMinimum;
1489 decimal viewMax = (decimal)_axis.ViewMaximum;
1491 if (ajaxScrollingEnabled)
1493 // Skip very first and last labels if they are partialy outside the scaleView
1496 if ((decimal)label.FromPosition < (decimal)_axis.Minimum)
1503 if ((decimal)label.ToPosition > (decimal)_axis.Maximum)
1509 // Skip label only if it is compleltly out of the scaleView
1510 if ((decimal)label.ToPosition < viewMin ||
1511 (decimal)label.FromPosition > viewMax)
1516 // RecalculateAxesScale label index starting from the first frame.
1517 // Index is used to determine position of the offset labels
1518 if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
1523 // Get first series attached to this axis
1524 Series axisSeries = null;
1525 if (_axis.axisType == AxisName.X || _axis.axisType == AxisName.X2)
1527 List<string> seriesArray = _axis.ChartArea.GetXAxesSeries((_axis.axisType == AxisName.X) ? AxisType.Primary : AxisType.Secondary, _axis.SubAxisName);
1528 if (seriesArray.Count > 0)
1530 axisSeries = _axis.Common.DataManager.Series[seriesArray[0]];
1531 if (axisSeries != null && !axisSeries.IsXValueIndexed)
1538 // Set start position and iterate through label positions
1539 // NOTE: Labels offset should not be taken in the account
1540 double currentPosition = _axis.Minimum;
1541 while (currentPosition < _axis.Maximum)
1543 if (currentPosition >= middlePoint)
1548 currentPosition += ChartHelper.GetIntervalSize(currentPosition, _axis.LabelStyle.GetInterval(), _axis.LabelStyle.GetIntervalType(),
1549 axisSeries, 0.0, DateTimeIntervalType.Number, true);
1557 // Skip label if label middle point is not in the scaleView
1558 if ((decimal)middlePoint < viewMin ||
1559 (decimal)middlePoint > viewMax)
1567 // Make sure label To and From coordinates are processed by one scale segment based
1568 // on the label middle point position.
1569 if (_axis.ScaleSegments.Count > 0)
1571 AxisScaleSegment scaleSegment = _axis.ScaleSegments.FindScaleSegmentForAxisValue(middlePoint);
1572 _axis.ScaleSegments.AllowOutOfScaleValues = true;
1573 _axis.ScaleSegments.EnforceSegment(scaleSegment);
1578 // Use center point instead of the To/From if label takes all scaleView
1579 // This is done to avoid issues with labels drawing with high
1581 if ((decimal)label.FromPosition < viewMin &&
1582 (decimal)label.ToPosition > viewMax)
1584 // Indicates that chart relative coordinates should be used instead of axis values
1585 useRelativeCoordiantes = true;
1587 // Calculate label From/To in relative coordinates using
1588 // label middle point and 100% width.
1589 labelFromRelative = _axis.GetLinearPosition(middlePoint) - 50.0;
1590 labelToRelative = labelFromRelative + 100.0;
1595 // Skip labels completly outside the scaleView
1596 if (label.ToPosition <= _axis.ViewMinimum || label.FromPosition >= _axis.ViewMaximum)
1601 // Check if label is partially visible.
1602 if (!ajaxScrollingEnabled &&
1603 _axis.ScaleView.IsZoomed)
1605 if (label.FromPosition < _axis.ViewMinimum)
1607 truncatedLeft = true;
1608 labelFrom = _axis.ViewMinimum;
1610 if (label.ToPosition > _axis.ViewMaximum)
1612 truncatedRight = true;
1613 labelTo = _axis.ViewMaximum;
1618 // Calculate single label position
1619 RectangleF rect = rectLabels;
1621 // Label is in the first row
1622 if (label.RowIndex == 0)
1624 if (_axis.AxisPosition == AxisPosition.Left)
1626 rect.X = rectLabels.Right - _axis.unRotatedLabelSize;
1627 rect.Width = _axis.unRotatedLabelSize;
1629 // Adjust label rectangle if offset labels are used
1630 if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
1633 if (labelIndex % 2 != 0F)
1635 rect.X += rect.Width;
1639 else if (_axis.AxisPosition == AxisPosition.Right)
1641 rect.Width = _axis.unRotatedLabelSize;
1643 // Adjust label rectangle if offset labels are used
1644 if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
1647 if (labelIndex % 2 != 0F)
1649 rect.X += rect.Width;
1653 else if (_axis.AxisPosition == AxisPosition.Top)
1655 rect.Y = rectLabels.Bottom - _axis.unRotatedLabelSize;
1656 rect.Height = _axis.unRotatedLabelSize;
1658 // Adjust label rectangle if offset labels are used
1659 if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
1662 if (labelIndex % 2 != 0F)
1664 rect.Y += rect.Height;
1668 else if (_axis.AxisPosition == AxisPosition.Bottom)
1670 rect.Height = _axis.unRotatedLabelSize;
1672 // Adjust label rectangle if offset labels are used
1673 if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
1676 if (labelIndex % 2 != 0F)
1678 rect.Y += rect.Height;
1683 // Increase label index
1687 // Label is in the second row
1688 else if (label.RowIndex > 0)
1690 if (_axis.AxisPosition == AxisPosition.Left)
1692 rect.X += _axis.totlaGroupingLabelsSizeAdjustment;
1693 for (int index = _axis.groupingLabelSizes.Length; index > label.RowIndex; index--)
1695 rect.X += _axis.groupingLabelSizes[index - 1];
1697 rect.Width = _axis.groupingLabelSizes[label.RowIndex - 1];
1699 else if (_axis.AxisPosition == AxisPosition.Right)
1701 rect.X = rect.Right - _axis.totlaGroupingLabelsSize - _axis.totlaGroupingLabelsSizeAdjustment;// + Axis.elementSpacing * 0.25f;
1702 for (int index = 1; index < label.RowIndex; index++)
1704 rect.X += _axis.groupingLabelSizes[index - 1];
1706 rect.Width = _axis.groupingLabelSizes[label.RowIndex - 1];
1708 else if (_axis.AxisPosition == AxisPosition.Top)
1710 rect.Y += _axis.totlaGroupingLabelsSizeAdjustment;
1711 for (int index = _axis.groupingLabelSizes.Length; index > label.RowIndex; index--)
1713 rect.Y += _axis.groupingLabelSizes[index - 1];
1715 rect.Height = _axis.groupingLabelSizes[label.RowIndex - 1];
1717 if (_axis.AxisPosition == AxisPosition.Bottom)
1719 rect.Y = rect.Bottom - _axis.totlaGroupingLabelsSize - _axis.totlaGroupingLabelsSizeAdjustment;
1720 for (int index = 1; index < label.RowIndex; index++)
1722 rect.Y += _axis.groupingLabelSizes[index - 1];
1724 rect.Height = _axis.groupingLabelSizes[label.RowIndex - 1];
1728 // Unknown label row value
1731 throw (new InvalidOperationException(SR.ExceptionAxisLabelIndexIsNegative));
1734 // Set label From and To coordinates
1735 double fromPosition = _axis.GetLinearPosition(labelFrom);
1736 double toPosition = _axis.GetLinearPosition(labelTo);
1737 if (useRelativeCoordiantes)
1739 useRelativeCoordiantes = false;
1740 fromPosition = labelFromRelative;
1741 toPosition = labelToRelative;
1744 if (_axis.AxisPosition == AxisPosition.Top || _axis.AxisPosition == AxisPosition.Bottom)
1746 rect.X = (float)Math.Min(fromPosition, toPosition);
1747 rect.Width = (float)Math.Max(fromPosition, toPosition) - rect.X;
1749 // Adjust label To/From position if offset labels are used
1750 if (label.RowIndex == 0 &&
1751 ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1)))
1753 rect.X -= rect.Width / 2F;
1759 rect.Y = (float)Math.Min(fromPosition, toPosition);
1760 rect.Height = (float)Math.Max(fromPosition, toPosition) - rect.Y;
1762 // Adjust label To/From position if offset labels are used
1763 if (label.RowIndex == 0 &&
1764 ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1)))
1766 rect.Y -= rect.Height / 2F;
1772 using (Brush brush = new SolidBrush((label.ForeColor.IsEmpty) ? _foreColor : label.ForeColor))
1774 graph.DrawLabelStringRel(_axis,
1780 label.ImageTransparentColor,
1781 (_axis.autoLabelFont == null) ? _font : _axis.autoLabelFont,
1785 (_axis.autoLabelAngle < -90) ? angle : _axis.autoLabelAngle,
1786 (!this.TruncatedLabels || label.RowIndex > 0) ? RectangleF.Empty : boundaryRect,
1792 // Clear scale segment enforcement
1793 _axis.ScaleSegments.EnforceSegment(null);
1794 _axis.ScaleSegments.AllowOutOfScaleValues = false;
1801 #region 3D Axis labels drawing methods
1804 /// Get a rectangle between chart area position and plotting area on specified side.
1805 /// Also sets axis labels string formatting for the specified labels position.
1807 /// <param name="area">Chart area object.</param>
1808 /// <param name="position">Position in chart area.</param>
1809 /// <param name="stringFormat">Axis labels string format.</param>
1810 /// <returns>Axis labels rectangle.</returns>
1811 private RectangleF GetAllLabelsRect(ChartArea area, AxisPosition position, StringFormat stringFormat)
1813 // Find axis with same position
1814 Axis labelsAxis = null;
1815 foreach(Axis curAxis in area.Axes)
1817 if(curAxis.AxisPosition == position)
1819 labelsAxis = curAxis;
1824 if(labelsAxis == null)
1826 return RectangleF.Empty;
1829 // Calculate rect for different positions
1830 RectangleF rectLabels = area.Position.ToRectangleF();
1831 if( position == AxisPosition.Left )
1833 rectLabels.Width = labelsAxis.labelSize;
1834 if( labelsAxis.GetIsMarksNextToAxis() )
1836 rectLabels.X = (float)labelsAxis.GetAxisPosition();
1837 rectLabels.Width = (float)Math.Max(rectLabels.Width, rectLabels.X - labelsAxis.PlotAreaPosition.X);
1841 rectLabels.X = labelsAxis.PlotAreaPosition.X;
1844 rectLabels.X -= rectLabels.Width;
1846 if(area.IsSideSceneWallOnLeft() || area.Area3DStyle.WallWidth == 0)
1848 rectLabels.X -= labelsAxis.markSize;
1851 // Set label text alignment
1852 stringFormat.Alignment = StringAlignment.Far;
1853 stringFormat.LineAlignment = StringAlignment.Center;
1855 else if( position == AxisPosition.Right )
1857 rectLabels.Width = labelsAxis.labelSize;
1858 if( labelsAxis.GetIsMarksNextToAxis() )
1860 rectLabels.X = (float)labelsAxis.GetAxisPosition();
1861 rectLabels.Width = (float)Math.Max(rectLabels.Width, labelsAxis.PlotAreaPosition.Right - rectLabels.X);
1865 rectLabels.X = labelsAxis.PlotAreaPosition.Right;
1868 if(!area.IsSideSceneWallOnLeft() || area.Area3DStyle.WallWidth == 0)
1870 rectLabels.X += labelsAxis.markSize;
1873 // Set label text alignment
1874 stringFormat.Alignment = StringAlignment.Near;
1875 stringFormat.LineAlignment = StringAlignment.Center;
1877 else if( position == AxisPosition.Top )
1879 rectLabels.Height = labelsAxis.labelSize;
1880 if( labelsAxis.GetIsMarksNextToAxis() )
1882 rectLabels.Y = (float)labelsAxis.GetAxisPosition();
1883 rectLabels.Height = (float)Math.Max(rectLabels.Height, rectLabels.Y - labelsAxis.PlotAreaPosition.Y);
1887 rectLabels.Y = labelsAxis.PlotAreaPosition.Y;
1890 rectLabels.Y -= rectLabels.Height;
1892 if(area.Area3DStyle.WallWidth == 0)
1894 rectLabels.Y -= labelsAxis.markSize;
1897 // Set label text alignment
1898 stringFormat.Alignment = StringAlignment.Center;
1899 stringFormat.LineAlignment = StringAlignment.Far;
1901 else if( position == AxisPosition.Bottom )
1903 rectLabels.Height = labelsAxis.labelSize;
1904 if( labelsAxis.GetIsMarksNextToAxis() )
1906 rectLabels.Y = (float)labelsAxis.GetAxisPosition();
1907 rectLabels.Height = (float)Math.Max(rectLabels.Height, labelsAxis.PlotAreaPosition.Bottom - rectLabels.Y);
1911 rectLabels.Y = labelsAxis.PlotAreaPosition.Bottom;
1913 rectLabels.Y += labelsAxis.markSize;
1915 // Set label text alignment
1916 stringFormat.Alignment = StringAlignment.Center;
1917 stringFormat.LineAlignment = StringAlignment.Near;
1924 /// Gets position of axis labels.
1925 /// Top and Bottom axis labels can be drawn on the sides (left or right)
1926 /// of the plotting area. If angle between axis and it's projection is
1927 /// between -25 and 25 degrees the axis are drawn at the bottom/top,
1928 /// otherwise labels are moved on the left or right side.
1930 /// <param name="axis">Axis object.</param>
1931 /// <returns>Position where axis labels should be drawn.</returns>
1932 private AxisPosition GetLabelsPosition(Axis axis)
1934 // Get angle between 2D axis and it's 3D projection.
1935 double axisAngle = axis.GetAxisProjectionAngle();
1937 // Pick the side to draw the labels on
1938 if(axis.AxisPosition == AxisPosition.Bottom)
1940 if(axisAngle <= -25 )
1941 return AxisPosition.Right;
1942 else if(axisAngle >= 25 )
1943 return AxisPosition.Left;
1945 else if(axis.AxisPosition == AxisPosition.Top)
1947 if(axisAngle <= -25 )
1948 return AxisPosition.Left;
1949 else if(axisAngle >= 25 )
1950 return AxisPosition.Right;
1953 // Labels are on the same side as the axis
1954 return axis.AxisPosition;
1958 /// Draws axis labels in 3D space.
1960 /// <param name="graph">Reference to the Chart Graphics object.</param>
1961 /// <param name="backElements">Back elements of the axis should be drawn in 3D scene.</param>
1962 internal void Paint3D( ChartGraphics graph, bool backElements )
1964 // Label string drawing format
1965 using (StringFormat format = new StringFormat())
1967 format.Trimming = StringTrimming.EllipsisCharacter;
1969 // Calculate single pixel size in relative coordinates
1970 SizeF pixelSize = graph.GetRelativeSize(new SizeF(1f, 1f));
1972 //********************************************************************
1973 //** Determine the side of the plotting area to draw the labels on.
1974 //********************************************************************
1975 AxisPosition labelsPosition = GetLabelsPosition(_axis);
1977 //*****************************************************************
1978 //** Set the labels Z position
1979 //*****************************************************************
1981 float labelsZPosition = _axis.GetMarksZPosition(out axisOnEdge);
1983 // Adjust Z position for the "bent" tick marks
1984 bool adjustForWallWidth = false;
1985 if (this._axis.AxisPosition == AxisPosition.Top &&
1986 !this._axis.ChartArea.ShouldDrawOnSurface(SurfaceNames.Top, backElements, false))
1988 adjustForWallWidth = true;
1990 if (this._axis.AxisPosition == AxisPosition.Left &&
1991 !this._axis.ChartArea.ShouldDrawOnSurface(SurfaceNames.Left, backElements, false))
1993 adjustForWallWidth = true;
1995 if (this._axis.AxisPosition == AxisPosition.Right &&
1996 !this._axis.ChartArea.ShouldDrawOnSurface(SurfaceNames.Right, backElements, false))
1998 adjustForWallWidth = true;
2001 if (adjustForWallWidth && this._axis.ChartArea.Area3DStyle.WallWidth > 0)
2003 if (this._axis.MajorTickMark.TickMarkStyle == TickMarkStyle.InsideArea)
2005 labelsZPosition -= this._axis.ChartArea.areaSceneWallWidth.Width;
2007 else if (this._axis.MajorTickMark.TickMarkStyle == TickMarkStyle.OutsideArea)
2009 labelsZPosition -= this._axis.MajorTickMark.Size + this._axis.ChartArea.areaSceneWallWidth.Width;
2011 else if (this._axis.MajorTickMark.TickMarkStyle == TickMarkStyle.AcrossAxis)
2013 labelsZPosition -= this._axis.MajorTickMark.Size / 2f + this._axis.ChartArea.areaSceneWallWidth.Width;
2017 //*****************************************************************
2018 //** Check if labels should be drawn as back or front element.
2019 //*****************************************************************
2020 bool labelsInsidePlotArea = (this._axis.GetIsMarksNextToAxis() && !axisOnEdge);
2021 if (backElements == labelsInsidePlotArea)
2027 //********************************************************************
2028 //** Initialize all labels position rectangle
2029 //********************************************************************
2030 RectangleF rectLabels = this.GetAllLabelsRect(this._axis.ChartArea, this._axis.AxisPosition, format);
2032 //********************************************************************
2033 //** Calculate bounding rectangle used to truncate labels on the
2034 //** chart area boundary if TruncatedLabels property is set to true.
2035 //********************************************************************
2036 RectangleF boundaryRect = rectLabels;
2037 if (boundaryRect != RectangleF.Empty && _axis.totlaGroupingLabelsSize > 0)
2039 if (this._axis.AxisPosition == AxisPosition.Left)
2041 boundaryRect.X += _axis.totlaGroupingLabelsSize;
2042 boundaryRect.Width -= _axis.totlaGroupingLabelsSize;
2044 else if (this._axis.AxisPosition == AxisPosition.Right)
2046 boundaryRect.Width -= _axis.totlaGroupingLabelsSize;
2048 else if (this._axis.AxisPosition == AxisPosition.Top)
2050 boundaryRect.Y += _axis.totlaGroupingLabelsSize;
2051 boundaryRect.Height -= _axis.totlaGroupingLabelsSize;
2053 else if (this._axis.AxisPosition == AxisPosition.Bottom)
2055 boundaryRect.Height -= _axis.totlaGroupingLabelsSize;
2059 // Pre-calculated height of the first labels row
2060 float firstLabelsRowHeight = -1f;
2062 // For 3D axis labels the first row of labels
2063 // has to be drawn after all other rows because
2065 for (int selectionRow = 0; selectionRow <= this._axis.GetGroupLabelLevelCount(); selectionRow++)
2067 //********************************************************************
2068 //** Draw all labels from the collection
2069 //********************************************************************
2071 foreach (CustomLabel label in this._axis.CustomLabels)
2073 bool truncatedLeft = false;
2074 bool truncatedRight = false;
2075 double labelFrom = label.FromPosition;
2076 double labelTo = label.ToPosition;
2078 if (label.RowIndex != selectionRow)
2083 // Skip if label middle point is outside current scaleView
2084 if (label.RowIndex == 0)
2086 double middlePoint = (label.FromPosition + label.ToPosition) / 2.0;
2087 if ((decimal)middlePoint < (decimal)_axis.ViewMinimum ||
2088 (decimal)middlePoint > (decimal)_axis.ViewMaximum)
2095 // Skip labels completly outside the scaleView
2096 if (label.ToPosition <= _axis.ViewMinimum || label.FromPosition >= _axis.ViewMaximum)
2101 // Check if label is partially visible
2102 if (_axis.ScaleView.IsZoomed)
2104 if (label.FromPosition < _axis.ViewMinimum)
2106 truncatedLeft = true;
2107 labelFrom = _axis.ViewMinimum;
2109 if (label.ToPosition > _axis.ViewMaximum)
2111 truncatedRight = true;
2112 labelTo = _axis.ViewMaximum;
2118 // Calculate single label position
2119 RectangleF rect = rectLabels;
2121 // Label is in the first row
2122 if (label.RowIndex == 0)
2124 if (this._axis.AxisPosition == AxisPosition.Left)
2126 if (!this._axis.GetIsMarksNextToAxis())
2128 rect.X = rectLabels.Right - _axis.unRotatedLabelSize;
2129 rect.Width = _axis.unRotatedLabelSize;
2132 // Adjust label rectangle if offset labels are used
2133 if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
2136 if (labelIndex % 2 != 0F)
2138 rect.X += rect.Width;
2142 else if (this._axis.AxisPosition == AxisPosition.Right)
2144 if (!this._axis.GetIsMarksNextToAxis())
2146 rect.Width = _axis.unRotatedLabelSize;
2149 // Adjust label rectangle if offset labels are used
2150 if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
2153 if (labelIndex % 2 != 0F)
2155 rect.X += rect.Width;
2159 else if (this._axis.AxisPosition == AxisPosition.Top)
2161 if (!this._axis.GetIsMarksNextToAxis())
2163 rect.Y = rectLabels.Bottom - _axis.unRotatedLabelSize;
2164 rect.Height = _axis.unRotatedLabelSize;
2167 // Adjust label rectangle if offset labels are used
2168 if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
2171 if (labelIndex % 2 != 0F)
2173 rect.Y += rect.Height;
2177 else if (this._axis.AxisPosition == AxisPosition.Bottom)
2179 if (!this._axis.GetIsMarksNextToAxis())
2181 rect.Height = _axis.unRotatedLabelSize;
2184 // Adjust label rectangle if offset labels are used
2185 if ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1))
2188 if (labelIndex % 2 != 0F)
2190 rect.Y += rect.Height;
2195 // Increase label index
2199 // Label is in the second row
2200 else if (label.RowIndex > 0)
2202 // Hide grouping labels (where index of row > 0) when they are displayed
2203 // not on the same side as their axis. Fixes MS issue #64.
2204 if (labelsPosition != this._axis.AxisPosition)
2209 if (_axis.AxisPosition == AxisPosition.Left)
2211 rect.X += _axis.totlaGroupingLabelsSizeAdjustment;
2212 for (int index = _axis.groupingLabelSizes.Length; index > label.RowIndex; index--)
2214 rect.X += _axis.groupingLabelSizes[index - 1];
2216 rect.Width = _axis.groupingLabelSizes[label.RowIndex - 1];
2218 else if (_axis.AxisPosition == AxisPosition.Right)
2220 rect.X = rect.Right - _axis.totlaGroupingLabelsSize - _axis.totlaGroupingLabelsSizeAdjustment;// + Axis.elementSpacing * 0.25f;
2221 for (int index = 1; index < label.RowIndex; index++)
2223 rect.X += _axis.groupingLabelSizes[index - 1];
2225 rect.Width = _axis.groupingLabelSizes[label.RowIndex - 1];
2227 else if (_axis.AxisPosition == AxisPosition.Top)
2229 rect.Y += _axis.totlaGroupingLabelsSizeAdjustment;
2230 for (int index = _axis.groupingLabelSizes.Length; index > label.RowIndex; index--)
2232 rect.Y += _axis.groupingLabelSizes[index - 1];
2234 rect.Height = _axis.groupingLabelSizes[label.RowIndex - 1];
2236 if (_axis.AxisPosition == AxisPosition.Bottom)
2238 rect.Y = rect.Bottom - _axis.totlaGroupingLabelsSize - _axis.totlaGroupingLabelsSizeAdjustment;
2239 for (int index = 1; index < label.RowIndex; index++)
2241 rect.Y += _axis.groupingLabelSizes[index - 1];
2243 rect.Height = _axis.groupingLabelSizes[label.RowIndex - 1];
2247 // Unknown label row value
2250 throw (new InvalidOperationException(SR.ExceptionAxisLabelRowIndexMustBe1Or2));
2253 //********************************************************************
2254 //** Set label From and To coordinates.
2255 //********************************************************************
2256 double fromPosition = _axis.GetLinearPosition(labelFrom);
2257 double toPosition = _axis.GetLinearPosition(labelTo);
2258 if (this._axis.AxisPosition == AxisPosition.Top || this._axis.AxisPosition == AxisPosition.Bottom)
2260 rect.X = (float)Math.Min(fromPosition, toPosition);
2261 rect.Width = (float)Math.Max(fromPosition, toPosition) - rect.X;
2262 if (rect.Width < pixelSize.Width)
2264 rect.Width = pixelSize.Width;
2267 // Adjust label To/From position if offset labels are used
2268 if (label.RowIndex == 0 &&
2269 ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1)))
2271 rect.X -= rect.Width / 2F;
2277 rect.Y = (float)Math.Min(fromPosition, toPosition);
2278 rect.Height = (float)Math.Max(fromPosition, toPosition) - rect.Y;
2279 if (rect.Height < pixelSize.Height)
2281 rect.Height = pixelSize.Height;
2284 // Adjust label To/From position if offset labels are used
2285 if (label.RowIndex == 0 &&
2286 ((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1)))
2288 rect.Y -= rect.Height / 2F;
2293 // Save original rect
2294 RectangleF initialRect = new RectangleF(rect.Location, rect.Size);
2296 //********************************************************************
2297 //** Transform and adjust label rectangle coordinates in 3D space.
2298 //********************************************************************
2299 Point3D[] rectPoints = new Point3D[3];
2300 if (this._axis.AxisPosition == AxisPosition.Left)
2302 rectPoints[0] = new Point3D(rect.Right, rect.Y, labelsZPosition);
2303 rectPoints[1] = new Point3D(rect.Right, rect.Y + rect.Height / 2f, labelsZPosition);
2304 rectPoints[2] = new Point3D(rect.Right, rect.Bottom, labelsZPosition);
2305 this._axis.ChartArea.matrix3D.TransformPoints(rectPoints);
2306 rect.Y = rectPoints[0].Y;
2307 rect.Height = rectPoints[2].Y - rect.Y;
2308 rect.Width = rectPoints[1].X - rect.X;
2310 else if (this._axis.AxisPosition == AxisPosition.Right)
2312 rectPoints[0] = new Point3D(rect.X, rect.Y, labelsZPosition);
2313 rectPoints[1] = new Point3D(rect.X, rect.Y + rect.Height / 2f, labelsZPosition);
2314 rectPoints[2] = new Point3D(rect.X, rect.Bottom, labelsZPosition);
2315 this._axis.ChartArea.matrix3D.TransformPoints(rectPoints);
2316 rect.Y = rectPoints[0].Y;
2317 rect.Height = rectPoints[2].Y - rect.Y;
2318 rect.Width = rect.Right - rectPoints[1].X;
2319 rect.X = rectPoints[1].X;
2321 else if (this._axis.AxisPosition == AxisPosition.Top)
2323 // Transform 3 points of the rectangle
2324 rectPoints[0] = new Point3D(rect.X, rect.Bottom, labelsZPosition);
2325 rectPoints[1] = new Point3D(rect.X + rect.Width / 2f, rect.Bottom, labelsZPosition);
2326 rectPoints[2] = new Point3D(rect.Right, rect.Bottom, labelsZPosition);
2327 this._axis.ChartArea.matrix3D.TransformPoints(rectPoints);
2329 if (labelsPosition == AxisPosition.Top)
2331 rect.X = rectPoints[0].X;
2332 rect.Width = rectPoints[2].X - rect.X;
2333 rect.Height = rectPoints[1].Y - rect.Y;
2335 else if (labelsPosition == AxisPosition.Right)
2337 RectangleF rightLabelsRect = this.GetAllLabelsRect(this._axis.ChartArea, labelsPosition, format);
2338 rect.Y = rectPoints[0].Y;
2339 rect.Height = rectPoints[2].Y - rect.Y;
2340 rect.X = rectPoints[1].X;
2341 rect.Width = rightLabelsRect.Right - rect.X;
2343 else if (labelsPosition == AxisPosition.Left)
2345 RectangleF rightLabelsRect = this.GetAllLabelsRect(this._axis.ChartArea, labelsPosition, format);
2346 rect.Y = rectPoints[2].Y;
2347 rect.Height = rectPoints[0].Y - rect.Y;
2348 rect.X = rightLabelsRect.X;
2349 rect.Width = rectPoints[1].X - rightLabelsRect.X;
2352 else if (this._axis.AxisPosition == AxisPosition.Bottom)
2354 // Transform 3 points of the rectangle
2355 rectPoints[0] = new Point3D(rect.X, rect.Y, labelsZPosition);
2356 rectPoints[1] = new Point3D(rect.X + rect.Width / 2f, rect.Y, labelsZPosition);
2357 rectPoints[2] = new Point3D(rect.Right, rect.Y, labelsZPosition);
2358 this._axis.ChartArea.matrix3D.TransformPoints(rectPoints);
2360 if (labelsPosition == AxisPosition.Bottom)
2362 rect.X = rectPoints[0].X;
2363 rect.Width = rectPoints[2].X - rect.X;
2364 rect.Height = rect.Bottom - rectPoints[1].Y;
2365 rect.Y = rectPoints[1].Y;
2367 else if (labelsPosition == AxisPosition.Right)
2369 RectangleF rightLabelsRect = this.GetAllLabelsRect(this._axis.ChartArea, labelsPosition, format);
2370 rect.Y = rectPoints[2].Y;
2371 rect.Height = rectPoints[0].Y - rect.Y;
2372 rect.X = rectPoints[1].X;
2373 rect.Width = rightLabelsRect.Right - rect.X;
2375 // Adjust label rect by shifting it down by quarter of the tick size
2376 if (this._axis.autoLabelAngle == 0)
2378 rect.Y += this._axis.markSize / 4f;
2381 else if (labelsPosition == AxisPosition.Left)
2383 RectangleF rightLabelsRect = this.GetAllLabelsRect(this._axis.ChartArea, labelsPosition, format);
2384 rect.Y = rectPoints[0].Y;
2385 rect.Height = rectPoints[2].Y - rect.Y;
2386 rect.X = rightLabelsRect.X;
2387 rect.Width = rectPoints[1].X - rightLabelsRect.X;
2389 // Adjust label rect by shifting it down by quarter of the tick size
2390 if (this._axis.autoLabelAngle == 0)
2392 rect.Y += this._axis.markSize / 4f;
2397 // Find axis with same position
2398 Axis labelsAxis = null;
2399 foreach (Axis curAxis in this._axis.ChartArea.Axes)
2401 if (curAxis.AxisPosition == labelsPosition)
2403 labelsAxis = curAxis;
2408 //********************************************************************
2409 //** Adjust font angles for Top and Bottom axis
2410 //********************************************************************
2411 int labelsFontAngle = (_axis.autoLabelAngle < -90) ? angle : _axis.autoLabelAngle;
2412 if (labelsPosition != this._axis.AxisPosition)
2414 if ((this._axis.AxisPosition == AxisPosition.Top || this._axis.AxisPosition == AxisPosition.Bottom) &&
2415 (labelsFontAngle == 90 || labelsFontAngle == -90))
2417 labelsFontAngle = 0;
2419 else if (this._axis.AxisPosition == AxisPosition.Bottom)
2421 if (labelsPosition == AxisPosition.Left && labelsFontAngle > 0)
2423 labelsFontAngle = -labelsFontAngle;
2425 else if (labelsPosition == AxisPosition.Right && labelsFontAngle < 0)
2427 labelsFontAngle = -labelsFontAngle;
2430 else if (this._axis.AxisPosition == AxisPosition.Top)
2432 if (labelsPosition == AxisPosition.Left && labelsFontAngle < 0)
2434 labelsFontAngle = -labelsFontAngle;
2436 else if (labelsPosition == AxisPosition.Right && labelsFontAngle > 0)
2438 labelsFontAngle = -labelsFontAngle;
2443 //********************************************************************
2444 //** NOTE: Code below improves chart labels readability in scenarios
2445 //** described in MS issue #65.
2447 //** Prevent labels in the first row from overlapping the grouping
2448 //** labels in the rows below. The solution only apply to the limited
2449 //** use cases defined by the condition below.
2450 //********************************************************************
2451 StringFormatFlags oldFormatFlags = format.FormatFlags;
2453 if (label.RowIndex == 0 &&
2454 labelsFontAngle == 0 &&
2455 _axis.groupingLabelSizes != null &&
2456 _axis.groupingLabelSizes.Length > 0 &&
2457 this._axis.AxisPosition == AxisPosition.Bottom &&
2458 labelsPosition == AxisPosition.Bottom &&
2459 !((this._axis.autoLabelOffset == -1) ? this.IsStaggered : (this._axis.autoLabelOffset == 1)))
2461 if (firstLabelsRowHeight == -1f)
2463 // Calculate first labels row max height
2464 Point3D[] labelPositionPoints = new Point3D[1];
2465 labelPositionPoints[0] = new Point3D(initialRect.X, initialRect.Bottom - _axis.totlaGroupingLabelsSize - _axis.totlaGroupingLabelsSizeAdjustment, labelsZPosition);
2466 this._axis.ChartArea.matrix3D.TransformPoints(labelPositionPoints);
2468 float height = labelPositionPoints[0].Y - rect.Y;
2470 firstLabelsRowHeight = (height > 0f) ? height : rect.Height;
2473 // Resuse pre-calculated first labels row height
2474 rect.Height = firstLabelsRowHeight;
2476 // Change current string format to prevent strings to go out of the
2477 // specified bounding rectangle
2478 if ((format.FormatFlags & StringFormatFlags.LineLimit) == 0)
2480 format.FormatFlags |= StringFormatFlags.LineLimit;
2485 //********************************************************************
2486 //** Draw label text.
2487 //********************************************************************
2489 using (Brush brush = new SolidBrush((label.ForeColor.IsEmpty) ? _foreColor : label.ForeColor))
2491 graph.DrawLabelStringRel(
2498 label.ImageTransparentColor,
2499 (_axis.autoLabelFont == null) ? _font : _axis.autoLabelFont,
2504 (!this.TruncatedLabels || label.RowIndex > 0) ? RectangleF.Empty : boundaryRect,
2510 // Restore old string format that was temporary modified
2511 if (format.FormatFlags != oldFormatFlags)
2513 format.FormatFlags = oldFormatFlags;
2522 #region Helper methods
2525 /// Sets the axis to which this object attached to.
2527 /// <returns>Axis object.</returns>
2530 set { _axis = value; }
2535 /// Invalidate chart picture
2537 internal override void Invalidate()
2539 #if Microsoft_CONTROL
2541 if(this._axis != null)
2543 this._axis.Invalidate();
2551 #region Label properties
2554 /// Gets or sets the interval offset of the label.
2557 SRCategory("CategoryAttributeData"),
2559 SRDescription("DescriptionAttributeLabel_IntervalOffset"),
2560 DefaultValue(Double.NaN),
2561 #if !Microsoft_CONTROL
2562 PersistenceMode(PersistenceMode.Attribute),
2564 RefreshPropertiesAttribute(RefreshProperties.All),
2565 TypeConverter(typeof(AxisElementIntervalValueConverter))
2567 public double IntervalOffset
2571 return intervalOffset;
2575 intervalOffset = value;
2583 /// Gets the interval offset.
2585 /// <returns></returns>
2586 internal double GetIntervalOffset()
2588 if(double.IsNaN(intervalOffset) && this._axis != null)
2590 return this._axis.IntervalOffset;
2592 return intervalOffset;
2596 /// Gets or sets the unit of measurement of the label offset.
2599 SRCategory("CategoryAttributeData"),
2601 DefaultValue(DateTimeIntervalType.NotSet),
2602 SRDescription("DescriptionAttributeLabel_IntervalOffsetType"),
2603 RefreshPropertiesAttribute(RefreshProperties.All),
2604 #if !Microsoft_CONTROL
2605 PersistenceMode(PersistenceMode.Attribute)
2608 public DateTimeIntervalType IntervalOffsetType
2612 return intervalOffsetType;
2616 intervalOffsetType = value;
2623 /// Gets the type of the interval offset.
2625 /// <returns></returns>
2626 internal DateTimeIntervalType GetIntervalOffsetType()
2628 if(intervalOffsetType == DateTimeIntervalType.NotSet && this._axis != null)
2630 return this._axis.IntervalOffsetType;
2632 return intervalOffsetType;
2636 /// Gets or sets the interval size of the label.
2639 SRCategory("CategoryAttributeData"),
2641 DefaultValue(Double.NaN),
2642 SRDescription("DescriptionAttributeLabel_Interval"),
2643 TypeConverter(typeof(AxisElementIntervalValueConverter)),
2644 #if !Microsoft_CONTROL
2645 PersistenceMode(PersistenceMode.Attribute),
2648 public double Interval
2658 // Reset original property value fields
2659 if (this._axis != null)
2661 this._axis.tempLabelInterval = interval;
2670 /// Gets the interval.
2672 /// <returns></returns>
2673 internal double GetInterval()
2675 if(double.IsNaN(interval) && this._axis != null)
2677 return this._axis.Interval;
2683 /// Gets or sets the unit of measurement of the interval size of the label.
2686 SRCategory("CategoryAttributeData"),
2688 DefaultValue(DateTimeIntervalType.NotSet),
2689 SRDescription("DescriptionAttributeLabel_IntervalType"),
2690 RefreshPropertiesAttribute(RefreshProperties.All),
2691 #if !Microsoft_CONTROL
2692 PersistenceMode(PersistenceMode.Attribute)
2695 public DateTimeIntervalType IntervalType
2699 return intervalType;
2703 intervalType = value;
2705 // Reset original property value fields
2706 if (this._axis != null)
2708 this._axis.tempLabelIntervalType = intervalType;
2717 /// Gets the type of the interval.
2719 /// <returns></returns>
2720 internal DateTimeIntervalType GetIntervalType()
2722 if(intervalType == DateTimeIntervalType.NotSet && this._axis != null)
2724 return this._axis.IntervalType;
2726 return intervalType;
2730 /// Gets or sets the font of the label.
2733 SRCategory("CategoryAttributeAppearance"),
2735 DefaultValue(typeof(Font), "Microsoft Sans Serif, 8pt"),
2736 SRDescription("DescriptionAttributeLabel_Font"),
2737 #if !Microsoft_CONTROL
2738 PersistenceMode(PersistenceMode.Attribute)
2749 // Turn off labels autofitting
2750 if (this._axis != null && this._axis.Common!=null && this._axis.Common.Chart != null)
2752 if(!this._axis.Common.Chart.serializing)
2754 this._axis.IsLabelAutoFit = false;
2764 /// Gets or sets the fore color of the label.
2767 SRCategory("CategoryAttributeAppearance"),
2769 DefaultValue(typeof(Color), "Black"),
2770 SRDescription("DescriptionAttributeFontColor"),
2771 NotifyParentPropertyAttribute(true),
2772 TypeConverter(typeof(ColorConverter)),
2773 Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
2774 #if !Microsoft_CONTROL
2775 PersistenceMode(PersistenceMode.Attribute)
2778 public Color ForeColor
2792 /// Gets or sets a value that represents the angle at which font is drawn.
2795 SRCategory("CategoryAttributeAppearance"),
2798 SRDescription("DescriptionAttributeLabel_FontAngle"),
2799 #if !Microsoft_CONTROL
2800 PersistenceMode(PersistenceMode.Attribute),
2802 RefreshPropertiesAttribute(RefreshProperties.All)
2812 if(value < -90 || value > 90)
2814 throw (new ArgumentOutOfRangeException("value", SR.ExceptionAxisLabelFontAngleInvalid));
2817 // Turn of label offset if angle is not 0, 90 or -90
2818 if(IsStaggered && value != 0 && value != -90 && value != 90)
2820 IsStaggered = false;
2823 // Turn off labels autofitting
2824 if(this._axis != null && this._axis.Common!=null && this._axis.Common.Chart != null)
2826 if (!this._axis.Common.Chart.serializing)
2828 this._axis.IsLabelAutoFit = false;
2838 /// Gets or sets a property which specifies whether the labels are shown with offset.
2841 SRCategory("CategoryAttributeAppearance"),
2843 DefaultValue(false),
2844 SRDescription("DescriptionAttributeLabel_OffsetLabels"),
2845 #if !Microsoft_CONTROL
2846 PersistenceMode(PersistenceMode.Attribute),
2848 RefreshPropertiesAttribute(RefreshProperties.All)
2850 public bool IsStaggered
2858 // Make sure that angle is 0, 90 or -90
2859 if(value && (this.Angle != 0 || this.Angle != -90 || this.Angle != 90))
2864 // Turn off labels autofitting
2865 if (this._axis != null && this._axis.Common != null && this._axis.Common.Chart != null)
2867 if (!this._axis.Common.Chart.serializing)
2869 this._axis.IsLabelAutoFit = false;
2873 isStaggered = value;
2880 /// Gets or sets a property which specifies whether the labels are shown at axis ends.
2883 SRCategory("CategoryAttributeAppearance"),
2886 SRDescription("DescriptionAttributeLabel_ShowEndLabels"),
2887 #if !Microsoft_CONTROL
2888 PersistenceMode(PersistenceMode.Attribute)
2891 public bool IsEndLabelVisible
2895 return _isEndLabelVisible;
2899 _isEndLabelVisible = value;
2905 /// Gets or sets a property which specifies whether the label can be truncated.
2908 SRCategory("CategoryAttributeAppearance"),
2910 DefaultValue(false),
2911 SRDescription("DescriptionAttributeLabel_TruncatedLabels"),
2912 #if !Microsoft_CONTROL
2913 PersistenceMode(PersistenceMode.Attribute)
2916 public bool TruncatedLabels
2920 return _truncatedLabels;
2924 _truncatedLabels = value;
2930 /// Gets or sets the formatting string for the label text.
2933 SRCategory("CategoryAttributeAppearance"),
2936 SRDescription("DescriptionAttributeLabel_Format"),
2937 #if !Microsoft_CONTROL
2938 PersistenceMode(PersistenceMode.Attribute),
2941 public string Format
2955 /// Gets or sets a property which indicates whether the label is enabled.
2958 SRCategory("CategoryAttributeAppearance"),
2961 SRDescription("DescriptionAttributeLabel_Enabled"),
2962 #if !Microsoft_CONTROL
2963 PersistenceMode(PersistenceMode.Attribute)
2980 #region IDisposable Members
2983 /// Releases unmanaged and - optionally - managed resources
2985 /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
2986 protected override void Dispose(bool disposing)
2990 //Free managed resources
2991 if (_fontCache!=null)
2993 _fontCache.Dispose();