/* Copyright (C) 2008 Webyog Softworks Private Limited This file is a part of Visifire Charts. Visifire is a free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. You should have received a copy of the GNU General Public License along with Visifire Charts. If not, see . If GPL is not suitable for your products or company, Webyog provides Visifire under a flexible commercial license designed to meet your specific usage and distribution requirements. If you have already obtained a commercial license from Webyog, you can use this file under those license terms. */ #if WPF using System; using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Media; using System.ComponentModel; #else using System; using System.Windows; using System.Linq; using System.Windows.Controls; using System.Windows.Media; using System.Collections.Generic; #endif using System.Windows.Data; using Visifire.Commons; namespace Visifire.Charts { /// /// Visifire.Charts.AxisLabels class /// public class AxisLabels : ObservableObject { #region Public Methods /// /// Initializes a new instance of the Visifire.Charts.AxisLabels class /// public AxisLabels() { // Apply default style from generic #if WPF if (!_defaultStyleKeyApplied) { DefaultStyleKeyProperty.OverrideMetadata(typeof(AxisLabels), new FrameworkPropertyMetadata(typeof(AxisLabels))); _defaultStyleKeyApplied = true; } #else DefaultStyleKey = typeof(AxisLabels); #endif WidthOfACharacter = Double.NaN; InternalAngle = Double.NaN; _tag = new ElementData() { Element = this }; } public override void Bind() { #if SL Binding b = new Binding("FontSize"); b.Source = this; this.SetBinding(InternalFontSizeProperty, b); b = new Binding("FontFamily"); b.Source = this; this.SetBinding(InternalFontFamilyProperty, b); b = new Binding("FontStyle"); b.Source = this; this.SetBinding(InternalFontStyleProperty, b); b = new Binding("FontWeight"); b.Source = this; this.SetBinding(InternalFontWeightProperty, b); b = new Binding("Opacity"); b.Source = this; this.SetBinding(InternalOpacityProperty, b); #endif } #endregion #region Public Properties /// /// Identifies the Visifire.Charts.AxisLabels.Interval dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.Interval dependency property. /// public static readonly DependencyProperty IntervalProperty = DependencyProperty.Register ("Interval", typeof(Nullable), typeof(AxisLabels), new PropertyMetadata(OnIntervalPropertyChanged)); /// /// Identifies the Visifire.Charts.AxisLabels.Angle dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.Angle dependency property. /// public static readonly DependencyProperty AngleProperty = DependencyProperty.Register ("Angle", typeof(Nullable), typeof(AxisLabels), new PropertyMetadata(OnAnglePropertyChanged)); /// /// Identifies the Visifire.Charts.AxisLabels.Enabled dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.Enabled dependency property. /// public static readonly DependencyProperty EnabledProperty = DependencyProperty.Register ("Enabled", typeof(Nullable), typeof(AxisLabels), new PropertyMetadata(OnEnabledPropertyChanged)); /// /// Identifies the Visifire.Charts.AxisLabels.TextAlignment dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.TextAlignment dependency property. /// public static readonly DependencyProperty TextAlignmentProperty = DependencyProperty.Register ("TextAlignment", typeof(TextAlignment), typeof(AxisLabels), new PropertyMetadata(TextAlignment.Left, OnTextAlignmentPropertyChanged)); #if WPF /// /// Identifies the Visifire.Charts.AxisLabels.FontFamily dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.FontFamily dependency property. /// public new static readonly DependencyProperty FontFamilyProperty = DependencyProperty.Register ("FontFamily", typeof(FontFamily), typeof(AxisLabels), new PropertyMetadata(OnFontFamilyPropertyChanged)); /// /// Identifies the Visifire.Charts.AxisLabels.Opacity dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.Opacity dependency property. /// public new static readonly DependencyProperty OpacityProperty = DependencyProperty.Register ("Opacity", typeof(Double), typeof(AxisLabels), new PropertyMetadata(1.0, OnOpacityPropertyChanged)); #endif /// /// Identifies the Visifire.Charts.AxisLabels.FontColor dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.FontColor dependency property. /// public static readonly DependencyProperty FontColorProperty = DependencyProperty.Register ("FontColor", typeof(Brush), typeof(AxisLabels), new PropertyMetadata(OnFontColorPropertyChanged)); #if WPF /// /// Identifies the Visifire.Charts.AxisLabels.FontStyle dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.FontStyle dependency property. /// public new static readonly DependencyProperty FontStyleProperty = DependencyProperty.Register ("FontStyle", typeof(FontStyle), typeof(AxisLabels), new PropertyMetadata(OnFontStylePropertyChanged)); /// /// Identifies the Visifire.Charts.AxisLabels.FontWeight dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.FontWeight dependency property. /// public new static readonly DependencyProperty FontWeightProperty = DependencyProperty.Register ("FontWeight", typeof(FontWeight), typeof(AxisLabels), new PropertyMetadata(OnFontWeightPropertyChanged)); /// /// Identifies the Visifire.Charts.AxisLabels.FontSize dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.FontSize dependency property. /// public new static readonly DependencyProperty FontSizeProperty = DependencyProperty.Register ("FontSize", typeof(Double), typeof(AxisLabels), new PropertyMetadata(OnFontSizePropertyChanged)); #endif /// /// Identifies the Visifire.Charts.AxisLabels.TextWrap dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.TextWrap dependency property. /// public static readonly DependencyProperty TextWrapProperty = DependencyProperty.Register ("TextWrap", typeof(Double), typeof(AxisLabels), new PropertyMetadata(Double.NaN, OnTextWrapPropertyChanged)); /// /// Identifies the Visifire.Charts.AxisLabels.Rows dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.Rows dependency property. /// public static readonly DependencyProperty RowsProperty = DependencyProperty.Register ("Rows", typeof(Nullable), typeof(AxisLabels), new PropertyMetadata(OnRowsPropertyChanged)); /// /// ToolTipText property /// ( NotImplemented ) /// [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] public override String ToolTipText { get { throw new NotImplementedException("ToolTipText property for AxisLabels is not implemented"); } set { throw new NotImplementedException("ToolTipText property for AxisLabels is not implemented"); } } /// /// Get or set the axis labels interval /// #if SL [System.ComponentModel.TypeConverter(typeof(Converters.NullableDoubleConverter))] #endif public Nullable Interval { get { if ((Nullable)GetValue(IntervalProperty) == null) return Double.NaN; else return (Nullable)GetValue(IntervalProperty); } set { SetValue(IntervalProperty, value); } } #if SL [System.ComponentModel.TypeConverter(typeof(Converters.NullableDoubleConverter))] #endif public Nullable Angle { get { if ((Nullable)GetValue(AngleProperty) == null) return InternalAngle; else return (Nullable)GetValue(AngleProperty); } set { SetValue(AngleProperty, value); } } /// /// Get or set the Opacity property /// public new Double Opacity { get { return (Double)GetValue(OpacityProperty); } set { #if SL if (Opacity != value) { InternalOpacity = value; SetValue(OpacityProperty, value); FirePropertyChanged("Opacity"); } #else SetValue(OpacityProperty, value); #endif } } /// /// Enables or disables axis labels /// [System.ComponentModel.TypeConverter(typeof(NullableBoolConverter))] public Nullable Enabled { get { if ((Nullable)GetValue(EnabledProperty) == null) return true; else return (Nullable)GetValue(EnabledProperty); } set { SetValue(EnabledProperty, value); } } /// /// Get or set the color for the text in axis labels /// public TextAlignment TextAlignment { get { return (TextAlignment)GetValue(TextAlignmentProperty); } set { SetValue(TextAlignmentProperty, value); } } /// /// Get or set the font family of axis labels /// public new FontFamily FontFamily { get { if ((FontFamily)GetValue(FontFamilyProperty) == null) return new FontFamily("Arial"); else return (FontFamily)GetValue(FontFamilyProperty); } set { #if SL if (FontFamily != value) { InternalFontFamily = value; SetValue(FontFamilyProperty, value); FirePropertyChanged("FontFamily"); } #else SetValue(FontFamilyProperty, value); #endif } } /// /// Get or set the color for the text in axis labels /// public Brush FontColor { get { return (Brush)GetValue(FontColorProperty); } set { SetValue(FontColorProperty, value); } } private static void OnFontColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { AxisLabels axisLabels = d as AxisLabels; axisLabels.UpdateVisual("FontColor", e.NewValue); } /// /// Get or set the styles for the text like "Italic" or "Normal" /// #if WPF [TypeConverter(typeof(System.Windows.FontStyleConverter))] #endif public new FontStyle FontStyle { get { return (FontStyle)(GetValue(FontStyleProperty)); } set { #if SL if (InternalFontStyle != value) { InternalFontStyle = value; SetValue(FontStyleProperty, value); UpdateVisual("FontStyle", value); } #else SetValue(FontStyleProperty, value); #endif } } /// /// Get or set how the font appears. It takes values like "Bold", "Normal", "Black" etc /// #if WPF [System.ComponentModel.TypeConverter(typeof(System.Windows.FontWeightConverter))] #endif public new FontWeight FontWeight { get { return (FontWeight)(GetValue(FontWeightProperty)); } set { #if SL if (FontWeight != value) { InternalFontWeight = value; SetValue(FontWeightProperty, value); UpdateVisual("FontWeight", value); } #else SetValue(FontWeightProperty, value); #endif } } public new Double FontSize { get { return (Double)GetValue(FontSizeProperty); } set { #if SL if (FontSize != value) { InternalFontSize = value; SetValue(FontSizeProperty, value); FirePropertyChanged("FontSize"); } #else SetValue(FontSizeProperty, value); #endif } } /// /// Get or set the number of rows of the axis labels /// #if SL [System.ComponentModel.TypeConverter(typeof(Converters.NullableInt32Converter))] #endif public Nullable Rows { get { return ((Nullable)GetValue(RowsProperty) == null) ? 0 : ((Nullable)GetValue(RowsProperty)); } set { InternalRows = (Int32)((value == null)? 0: value); SetValue(RowsProperty, value); } } /// /// Get or set the parent as Axis /// public new Axis Parent { get { return _parent; } internal set { System.Diagnostics.Debug.Assert(typeof(Axis).Equals(value.GetType()), "Unknown Parent", "DataPoint should have DataSeries as Parent"); _parent = value; } } #endregion #region Public Events #endregion #region Protected Methods #endregion #region Internal Properties #if SL /// /// Identifies the Visifire.Charts.AxisLabels.FontSize dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.FontSize dependency property. /// private static readonly DependencyProperty InternalFontSizeProperty = DependencyProperty.Register ("InternalFontSize", typeof(Double), typeof(AxisLabels), new PropertyMetadata(OnFontSizePropertyChanged)); /// Identifies the Visifire.Charts.AxisLabels.FontFamily dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.FontFamily dependency property. /// private static readonly DependencyProperty InternalFontFamilyProperty = DependencyProperty.Register ("InternalFontFamily", typeof(FontFamily), typeof(AxisLabels), new PropertyMetadata(OnFontFamilyPropertyChanged)); /// /// Identifies the Visifire.Charts.AxisLabels.FontStyle dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.FontStyle dependency property. /// private static readonly DependencyProperty InternalFontStyleProperty = DependencyProperty.Register ("InternalFontStyle", typeof(FontStyle), typeof(AxisLabels), new PropertyMetadata(OnFontStylePropertyChanged)); /// /// Identifies the Visifire.Charts.AxisLabels.FontWeight dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.FontWeight dependency property. /// private static readonly DependencyProperty InternalFontWeightProperty = DependencyProperty.Register ("InternalFontWeight", typeof(FontWeight), typeof(AxisLabels), new PropertyMetadata(OnFontWeightPropertyChanged)); /// /// Identifies the Visifire.Charts.AxisLabels.Opacity dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.Opacity dependency property. /// private static readonly DependencyProperty InternalOpacityProperty = DependencyProperty.Register ("InternalOpacity", typeof(Double), typeof(AxisLabels), new PropertyMetadata(1.0, OnOpacityPropertyChanged)); #endif /// /// Get or set the FontFamily property of title /// internal FontFamily InternalFontFamily { get { FontFamily retVal; if (_internalFontFamily == null) retVal = (FontFamily)GetValue(FontFamilyProperty); else retVal = _internalFontFamily; return (retVal == null) ? new FontFamily("Verdana") : retVal; } set { _internalFontFamily = value; } } /// /// Get or set the FontSize property of title /// internal Double InternalFontSize { get { return (Double)(Double.IsNaN(_internalFontSize) ? GetValue(FontSizeProperty) : _internalFontSize); } set { _internalFontSize = value; } } /// /// Get or set the FontStyle property of title text /// #if WPF [TypeConverter(typeof(System.Windows.FontStyleConverter))] #endif internal FontStyle InternalFontStyle { get { return (FontStyle)((_internalFontStyle == null) ? GetValue(FontStyleProperty) : _internalFontStyle); } set { _internalFontStyle = value; } } /// /// Get or set the FontWeight property of title text /// #if WPF [System.ComponentModel.TypeConverter(typeof(System.Windows.FontWeightConverter))] #endif internal FontWeight InternalFontWeight { get { return (FontWeight)((_internalFontWeight == null) ? GetValue(FontWeightProperty) : _internalFontWeight); } set { _internalFontWeight = value; } } /// /// Get or set the Opacity property /// internal Double InternalOpacity { get { return (Double)(Double.IsNaN(_internalOpacity) ? GetValue(OpacityProperty) : _internalOpacity); } set { _internalOpacity = value; } } /// /// Average width of a character after applying /// internal Double WidthOfACharacter { get; set; } /// /// Get or set the axis labels angle /// internal Nullable InternalAngle { get; set; } /// /// Visual element for axis labels /// internal Canvas Visual { get; private set; } /// /// Get or set the maximum width of the labels relative to chart size. Value range is 0 - 1. /// public Double TextWrap { get { return (Double)GetValue(TextWrapProperty); } set { SetValue(TextWrapProperty, value); } } /// /// Get or set the number of rows of the axis labels /// internal Int32 InternalRows { get; set; } /// /// Actual minimum value of the axis /// internal Double Minimum { get; set; } /// /// Actual maximum value of the axis /// internal Double Maximum { get; set; } /// /// Visual minimum for the axis /// internal Double DataMinimum { get; set; } /// /// Visual maximum for the axis /// internal Double DataMaximum { get; set; } /// /// Get or set the width of the axis labels canvas, will be used only with the Horizontal axis /// internal new Double Width { get; set; } /// /// Get or set the height of the axis labels canvas, will be used ony with the vertical axis /// internal new Double Height { get; set; } /// /// Placement decides how the labels have to be positioned /// internal PlacementTypes Placement { get; set; } /// /// Reference to the dictionary in the PlotDetails that contains the required labels /// internal Dictionary AxisLabelContentDictionary { get; set; } /// /// Flag indicating whether all unique XValues have labels or not /// internal Boolean AllAxisLabels { get; set; } /// /// Reference to the axis which holds this axis labels /// internal Axis ParentAxis { get; set; } /// /// Number of pixels by which the top of the axis labels has overshot the actual canvas top /// internal Double TopOverflow { get; private set; } /// /// Number of pixels by which the bottom of the axislabels has overshot the actual canvas bottom /// internal Double BottomOverflow { get; private set; } /// /// Number of pixels by which the left of the axislabels has overshot the actual canvas left /// internal Double LeftOverflow { get; private set; } /// /// Number of pixels by which the right of the axislabels has overshot the actual canvas right /// internal Double RightOverflow { get; private set; } /// /// List of axis labels /// internal List AxisLabelList { get; set; } /// /// List of position values for the labels /// internal List LabelValues { get; set; } #endregion #region Private Delegates #endregion #region Private Methods /// /// Event handler attached with Interval property changed event of axislabels element /// /// DependencyObject /// DependencyPropertyChangedEventArgs private static void OnIntervalPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { AxisLabels axisLabels = d as AxisLabels; axisLabels.FirePropertyChanged("Interval"); } /// /// Event handler attached with Angle property changed event of axislabels element /// /// DependencyObject /// DependencyPropertyChangedEventArgs private static void OnAnglePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { AxisLabels axisLabels = d as AxisLabels; axisLabels.InternalAngle = (Nullable)e.NewValue; axisLabels.FirePropertyChanged("Angle"); } /// /// Event handler attached with Enabled property changed event of axislabels element /// /// DependencyObject /// DependencyPropertyChangedEventArgs private static void OnEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { AxisLabels axisLabels = d as AxisLabels; axisLabels.FirePropertyChanged("Enabled"); } /// /// Event handler attached with TextAlignment property changed event of axislabels element /// /// DependencyObject /// DependencyPropertyChangedEventArgs private static void OnTextAlignmentPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { AxisLabels axisLabels = d as AxisLabels; axisLabels.FirePropertyChanged("TextAlignment"); } /// /// Event handler attached with FontFamily property changed event of axislabels element /// /// DependencyObject /// DependencyPropertyChangedEventArgs private static void OnFontFamilyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { AxisLabels axisLabels = d as AxisLabels; if (e.NewValue == null || e.OldValue == null) { axisLabels.InternalFontFamily = (FontFamily)e.NewValue; axisLabels.FirePropertyChanged("FontFamily"); } else if (e.NewValue.ToString() != e.OldValue.ToString()) { axisLabels.InternalFontFamily = (FontFamily)e.NewValue; axisLabels.FirePropertyChanged("FontFamily"); } } /// /// Event handler attached with FontStyle property changed event of axislabels element /// /// DependencyObject /// DependencyPropertyChangedEventArgs private static void OnFontStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { AxisLabels axisLabels = d as AxisLabels; axisLabels.InternalFontStyle = (FontStyle)e.NewValue; axisLabels.UpdateVisual("FontStyle", e.NewValue); } /// /// Event handler attached with FontWeight property changed event of axislabels element /// /// DependencyObject /// DependencyPropertyChangedEventArgs private static void OnFontWeightPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { AxisLabels axisLabels = d as AxisLabels; axisLabels.InternalFontWeight = (FontWeight)e.NewValue; axisLabels.UpdateVisual("FontWeight", e.NewValue); } /// /// Event handler attached with FontSize property changed event of axislabels element /// /// DependencyObject /// DependencyPropertyChangedEventArgs private static void OnFontSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { AxisLabels axisLabels = d as AxisLabels; axisLabels.InternalFontSize = (Double)e.NewValue; axisLabels.FirePropertyChanged("FontSize"); } /// /// OpacityProperty changed call back function /// /// DependencyObject /// DependencyPropertyChangedEventArgs private static void OnOpacityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { AxisLabels axisLabels = d as AxisLabels; axisLabels.InternalOpacity = (Double)e.NewValue; axisLabels.FirePropertyChanged("Opacity"); } /// /// Event handler attached with TextWrap property changed event of axislabels element /// /// DependencyObject /// DependencyPropertyChangedEventArgs private static void OnTextWrapPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { AxisLabels axisLabels = d as AxisLabels; if((Double)e.NewValue < 0 || (Double)e.NewValue > 1) throw new Exception("Wrong property value. Range of TextWrapProperty varies from 0 to 1."); axisLabels.FirePropertyChanged("TextWrap"); } /// /// Event handler attached with Rows property changed event of axislabels element /// /// DependencyObject /// DependencyPropertyChangedEventArgs private static void OnRowsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { AxisLabels axisLabels = d as AxisLabels; axisLabels.FirePropertyChanged("Rows"); } /// /// Create a instance of a Visifire.Charts.AxisLabel /// /// Text as string /// AxisLabel private AxisLabel CreateLabel(String text) { AxisLabel label = new AxisLabel(); label.Text = text; label.Placement = this.Placement; return label; } /// /// Calculate auto interval /// /// Current interval /// Width of the axis /// Number of labels /// Angle of labels /// Number of rows /// Double private Double CalculateAutoInterval(Double CurrentInterval, Double AxisWidth, Int32 NoOfLabels, Double Angle, Int32 Rows) { Double retVal = 1; Angle = Double.IsNaN(Angle)? 0 :Angle; CalculateHorizontalOverflow(); return retVal; } /// /// Creates a set of labels /// private Boolean CreateLabels() { // Calculate interval Double interval = (Double)Interval; if (Double.IsNaN(interval) || interval <= 0) interval = ParentAxis.InternalInterval; // Set the begining of the axis labels same as that of the Axis Minimum. Decimal index = (Decimal)Minimum; // initialize the loop begin and end parameters Decimal minval = (Decimal)Minimum; Decimal maxVal = (Decimal)Maximum; // initialize the loop index increment values Decimal gap = (Decimal)interval; Int32 count = 0; // if the axis labels belong to axis x if (ParentAxis.AxisRepresentation == AxisRepresentations.AxisX) { // if the data minimum - interval is less than the actual minimum if (Double.IsNaN((Double)Parent.AxisMinimumNumeric)) { if (ParentAxis.XValueType != ChartValueTypes.Numeric) { index = (Decimal)ParentAxis.FirstLabelPosition; } else { if ((DataMinimum - Minimum) / interval >= 1) index = (Decimal)(DataMinimum - Math.Floor((DataMinimum - Minimum) / interval) * interval); else index = (Decimal)DataMinimum; } } //if (ParentAxis.SkipOfset > 0) //{ // if ((Double)Parent.AxisMinimum < DataMinimum) // index = (Decimal)DataMinimum; //} if (AllAxisLabels && AxisLabelContentDictionary.Count > 0) { Dictionary.Enumerator enumerator = AxisLabelContentDictionary.GetEnumerator(); enumerator.MoveNext(); Int32 dictionaryIndex = 0; //index = (Decimal)enumerator.Current.Key; for (; dictionaryIndex < AxisLabelContentDictionary.Count - 1; dictionaryIndex++) { enumerator.MoveNext(); //index = Math.Min(index, (Decimal)enumerator.Current.Key); } enumerator.Dispose(); } minval = index; if (minval != maxVal) { if (!Double.IsNaN(TextWrap)) CalculatAvgWidthOfAChar(); for (; index <= maxVal;) { // if (!((AllAxisLabels) && (AxisLabelContentDictionary.Count > 0) && (index > (Decimal)DataMaximum))) { String labelContent = ""; if (AxisLabelContentDictionary.ContainsKey((Double)index)) { if (ParentAxis.AxisOrientation == Orientation.Vertical) labelContent = AutoFormatMultilineText(AxisLabelContentDictionary[(Double)index], false); else labelContent = AutoFormatMultilineText(AxisLabelContentDictionary[(Double)index], true); } else { if (ParentAxis.XValueType == ChartValueTypes.Date) { DateTime dt = ParentAxis.MinDate; Decimal tempIndex = index; if (ParentAxis._isAllXValueZero) tempIndex--; dt = DateTimeHelper.UpdateDate(Parent.FirstLabelDate, (Double)interval * count, ParentAxis.InternalIntervalType); //dt = DateTimeHelper.AlignDateTime(dt, ParentAxis.InternalInterval, ParentAxis.InternalIntervalType); //if (ParentAxis.InternalIntervalType == IntervalTypes.Years) // dt = new DateTime(dt.Year, 1, 1, 0, 0, 0); labelContent = FormatDate(dt, ParentAxis); } else if (ParentAxis.XValueType == ChartValueTypes.Time) { DateTime dt = ParentAxis.MinDate; Decimal tempIndex = index; System.Diagnostics.Debug.WriteLine("Index=" + index.ToString()); if (ParentAxis._isAllXValueZero) tempIndex--; dt = DateTimeHelper.UpdateDate(Parent.FirstLabelDate, (Double)interval * count, ParentAxis.InternalIntervalType); labelContent = FormatDate(dt, ParentAxis); } else if (ParentAxis.XValueType == ChartValueTypes.DateTime) { DateTime dt = ParentAxis.MinDate; Decimal tempIndex = index; if (ParentAxis._isAllXValueZero) tempIndex--; dt = DateTimeHelper.UpdateDate(Parent.FirstLabelDate, (Double)interval * count, ParentAxis.InternalIntervalType); if (ParentAxis.IntervalType == IntervalTypes.Years || ParentAxis.InternalIntervalType == IntervalTypes.Years || ParentAxis.IntervalType == IntervalTypes.Months || ParentAxis.InternalIntervalType == IntervalTypes.Months || ParentAxis.IntervalType == IntervalTypes.Weeks || ParentAxis.InternalIntervalType == IntervalTypes.Weeks || ParentAxis.IntervalType == IntervalTypes.Days || ParentAxis.InternalIntervalType == IntervalTypes.Days ) dt = new DateTime(dt.Year, dt.Month, dt.Day, 0, 0, 0, 0); labelContent = FormatDate(dt, ParentAxis); } else labelContent = GetFormattedString((Double)index); } AxisLabel label = CreateLabel(labelContent); AxisLabelList.Add(label); LabelValues.Add((Double)index); } if (ParentAxis.IsDateTimeAxis) { count++; DateTime dt = DateTimeHelper.UpdateDate(Parent.FirstLabelDate, (Double)(count * gap), ParentAxis.InternalIntervalType); Decimal oneUnit = (Decimal)DateTimeHelper.DateDiff(dt, Parent.FirstLabelDate, ParentAxis.MinDateRange, ParentAxis.MaxDateRange, ParentAxis.InternalIntervalType, ParentAxis.XValueType); index = minval + oneUnit; } else { index = minval + (++count) * gap; } } } else { return false; } } else { if (minval != maxVal) { AxisLabel label; // Create and save the first label label = CreateLabel(GetFormattedString(Minimum)); AxisLabelList.Add(label); LabelValues.Add(Minimum); // Shift the maximum inwards so that the last label is not created // the reason for this is some times due to double approximation the last label doesnt get created // thats why the last label is explicitly created and hence must not be created in the following loop maxVal = (Decimal)(Maximum - interval / 2); //Create and save intermediate labels for (index = minval + (++count) * gap; index <= maxVal; index = minval + (++count) * gap) { label = CreateLabel(GetFormattedString((Double)index)); AxisLabelList.Add(label); LabelValues.Add((Double)index); } //create and save the last label label = CreateLabel(GetFormattedString(Maximum)); AxisLabelList.Add(label); LabelValues.Add(Maximum); } else { return false; } } return true; } /// /// Calculate average width of a character /// /// private void CalculatAvgWidthOfAChar() { AxisLabel label = new AxisLabel(); label.Text ="ABCDabcd01"; ApplyAxisLabelFontProperties(label); label.CreateVisualObject(false, null); WidthOfACharacter = label.ActualTextWidth / 10; } /// /// Set DateTime in AxisXLabel /// /// DataPoint /// Axis /// Axis labels private String FormatDate(DateTime dt, Axis axis) { String valueFormatString = axis.XValueType == ChartValueTypes.Date ? "M/d/yyyy" : axis.XValueType == ChartValueTypes.Time ? "h:mm:ss tt" : "M/d/yyyy h:mm:ss tt"; valueFormatString = (String.IsNullOrEmpty((String)axis.GetValue(Axis.ValueFormatStringProperty))) ? valueFormatString : axis.ValueFormatString; return axis.AddPrefixAndSuffix(dt.ToString(valueFormatString, System.Globalization.CultureInfo.CurrentCulture)); } /// /// Auto formats the AxisLabel text if bigger for Vertical charts /// /// Text as String /// Formatted text as String private String AutoFormatMultilineText(String text, Boolean autoIncrementWrapAt) { String multiLineText = ""; if (!Double.IsNaN(TextWrap)) { AxisLabel label = CreateLabel(text); ApplyAxisLabelFontProperties(label); label.CreateVisualObject(false, null); Double MaxLabelWidth = (ParentAxis.PlotDetails.ChartOrientation == ChartOrientationType.Vertical) ? Chart.ActualHeight : Chart.ActualWidth; MaxLabelWidth *= TextWrap; Int32 wrapAt = (Int32)(MaxLabelWidth / WidthOfACharacter); if ((ParentAxis.PlotDetails.ChartOrientation == ChartOrientationType.Vertical && label.ActualHeight > MaxLabelWidth) || (label.ActualWidth > MaxLabelWidth)) { Int32 charCount = 0; foreach (Char c in text) { if (c != ' ') { charCount++; multiLineText += c; } else if (charCount >= wrapAt) { multiLineText += "\n"; charCount = 0; if (autoIncrementWrapAt) wrapAt += 2; } else multiLineText += c; } } else multiLineText = text; } else multiLineText = text; multiLineText = GetFormattedMultilineText(multiLineText); return multiLineText; } /// /// Sets the position of labels based on the placement type /// private void SetLabelPosition() { switch (Placement) { case PlacementTypes.Top: PositionLabelsTop(); break; case PlacementTypes.Left: PositionLabelsLeft(); break; case PlacementTypes.Right: PositionLabelsRight(); break; case PlacementTypes.Bottom: PositionLabelsBottom(); break; } } /// /// Labels will be positioned for the axis that will appear above the plot area /// private void PositionLabelsTop() { Double startOffset = Double.IsNaN(ParentAxis.StartOffset) ? 0 : ParentAxis.StartOffset; Double endOffset = Double.IsNaN(ParentAxis.EndOffset) ? 0 : ParentAxis.EndOffset; // Check if the width is valid or not if (Double.IsNaN(Width) || Width <= 0) return; // set the width of the canvas Visual.Width = Width; // Variable to calculate the height of the visual canvas Double height = 0; // Calculate Default placement values CalculateHorizontalDefaults(); // Calculate the height of the labels for (Int32 i = 0; i < AxisLabelList.Count; i++) { AxisLabel label = AxisLabelList[i]; //Set size affecting font properties ApplyAxisLabelFontProperties(label); // set the label position label.Position = new Point(0, 0); // create the label visual element label.CreateVisualObject(false, null); // get the max height of the labels height = Math.Max(Math.Max(height, label.ActualHeight), _maxRowHeight); } for (Int32 i = 0; i < AxisLabelList.Count; i++) { AxisLabel label = AxisLabelList[i]; // get the position of the label Double position = Graphics.ValueToPixelPosition(startOffset, Width - endOffset, Minimum, Maximum, LabelValues[i]); // Create the visual element again label.CreateVisualObject(false, null); //Calculate vertical Position Double top = 0; if (GetAngle() != 0) { top = Math.Abs((label.ActualTextHeight / 2) * Math.Sin(Math.PI / 2 - AxisLabel.GetRadians(GetAngle()))); } // Set the new position label.Position = new Point(position, height * (Int32)InternalRows - top - ((i % (Int32)InternalRows) * _maxRowHeight) + Padding.Top); // Create the visual element again label.CreateVisualObject(true, _tag); // add the element to the visual canvas Visual.Children.Add(label.Visual); } // set the height of the visual canvas Visual.Height = height * (Int32)InternalRows + Padding.Top; // calculate the overflow due to this set of axis labels CalculateHorizontalOverflow(); } /// /// Labels will be positioned for the axis that will appear to the left of the plot area /// private void PositionLabelsLeft() { Double startOffset = Double.IsNaN(ParentAxis.StartOffset) ? 0 : ParentAxis.StartOffset; Double endOffset = Double.IsNaN(ParentAxis.EndOffset) ? 0 : ParentAxis.EndOffset; // Check if the height is valid or not if (Double.IsNaN(Height) || Height <= 0) return; // set the height of the canvas Visual.Height = Height; // Variable to calculate the height of the visual canvas Double width = 0; //Calculate Defaults for the vertical axis CalculateVerticalDefaults(); // Calculate the width of the labels for (Int32 i = 0; i < AxisLabelList.Count; i++) { AxisLabel label = AxisLabelList[i]; // set size affecting pararameters ApplyAxisLabelFontProperties(label); // set the label position label.Position = new Point(0, 0); // create the label visual element label.CreateVisualObject(false, null); // get the max width of the labels width = Math.Max(width, label.ActualWidth); } for (Int32 i = 0; i < AxisLabelList.Count; i++) { AxisLabel label = AxisLabelList[i]; // get the position of the label Double position = Graphics.ValueToPixelPosition(Height - endOffset, startOffset, Minimum, Maximum, LabelValues[i]); // Create the visual element again label.CreateVisualObject(false, null); //Calculate horizontal Position Double left = 1; if (GetAngle() != 0) { left = Math.Abs((label.ActualTextHeight / 2) * Math.Cos(Math.PI / 2 - AxisLabel.GetRadians(GetAngle()))); } // Set the new position label.Position = new Point(width - left + Padding.Left, position); // Create the visual element again label.CreateVisualObject(true, _tag); // add the element to the visual canvas Visual.Children.Add(label.Visual); } // set the width of the visual canvas Visual.Width = width + Padding.Left; // calculate the overflow due to this set of axis labels CalculateVerticalOverflow(); } /// /// Labels will be positioned for the axis that will appear to the right of the plot area /// private void PositionLabelsRight() { Double startOffset = Double.IsNaN(ParentAxis.StartOffset) ? 0 : ParentAxis.StartOffset; Double endOffset = Double.IsNaN(ParentAxis.EndOffset) ? 0 : ParentAxis.EndOffset; // Check if the height is valid or not if (Double.IsNaN(Height) || Height <= 0) return; // set the height of the canvas Visual.Height = Height; // Variable to calculate the height of the visual canvas Double width = 0; //Calculate Defaults for the vertical axis CalculateVerticalDefaults(); // Calculate the width of the labels for (Int32 i = 0; i < AxisLabelList.Count; i++) { AxisLabel label = AxisLabelList[i]; //Set size affecting font properties ApplyAxisLabelFontProperties(label); // get the position of the label Double position = Graphics.ValueToPixelPosition(Height - endOffset, startOffset, Minimum, Maximum, LabelValues[i]); // Create the visual element again label.CreateVisualObject(false, null); //Calculate horizontal Position Double left = 1; if (GetAngle() != 0) { left = Math.Abs((label.ActualTextHeight / 2) * Math.Cos(Math.PI / 2 - AxisLabel.GetRadians(GetAngle()))); } // Set the new position label.Position = new Point(left, position); // Create the visual element again label.CreateVisualObject(true, _tag); // add the element to the visual canvas Visual.Children.Add(label.Visual); // get the max width of the labels width = Math.Max(width, label.ActualWidth); } // set the width of the visual canvas Visual.Width = width + Padding.Right; // calculate the overflow due to this set of axis labels CalculateVerticalOverflow(); } /// /// Apply font properties of axislabels /// /// AxisLabel private void ApplyAxisLabelFontProperties(AxisLabel label) { //Set size affecting font properties label.FontSize = InternalFontSize; label.FontColor = Charts.Chart.CalculateFontColor((Chart as Chart), FontColor, false); label.FontFamily = InternalFontFamily; label.FontStyle = InternalFontStyle; label.FontWeight = InternalFontWeight; label.TextAlignment = TextAlignment; label.Angle = GetAngle(); } /// /// Labels will be positioned for the axis that will appear to the bottom of the plot area /// private void PositionLabelsBottom() { Double startOffset = Double.IsNaN(ParentAxis.StartOffset) ? 0 : ParentAxis.StartOffset; Double endOffset = Double.IsNaN(ParentAxis.EndOffset) ? 0 : ParentAxis.EndOffset; // Check if the width is valid or not if (Double.IsNaN(Width) || Width <= 0) return; // set the width of the canvas Visual.Width = Width; // Variable to calculate the height of the visual canvas Double height = 0; // Calculate Default placement values CalculateHorizontalDefaults(); // Calculate the height of the labels and position them for (Int32 i = 0; i < AxisLabelList.Count; i += (ParentAxis.SkipOffset + 1)) { AxisLabel label = AxisLabelList[i]; //Set size affecting font properties ApplyAxisLabelFontProperties(label); // get the position of the label Double position = Graphics.ValueToPixelPosition(startOffset, Width - endOffset, Minimum, Maximum, LabelValues[i]); //Calculate vertical Position Double top = 0; // Create the visual element again label.CreateVisualObject(false, null); if (GetAngle() != 0) { top = Math.Abs((label.ActualTextHeight / 2) * Math.Sin(Math.PI / 2 - AxisLabel.GetRadians(GetAngle()))); } // Set the new position label.Position = new Point(position, top + ((i % (Int32)InternalRows) * _maxRowHeight)); // Create the visual element again label.CreateVisualObject(true, _tag); // add the element to the visual canvas Visual.Children.Add(label.Visual); // get the max height of the labels height = Math.Max(Math.Max(height, label.ActualHeight), _maxRowHeight); } // set the height of the visual canvas Visual.Height = height * (Int32)InternalRows + Padding.Bottom; // calculate the overflow due to this set of axis labels CalculateHorizontalOverflow(); } /// /// This is for axis with placement setting as top or bottom /// private void CalculateHorizontalOverflow() { // Check if the label list contains any labels or not (if not then set the overflow to 0) if (AxisLabelList.Count > 0) { LeftOverflow = (from axisLabel in AxisLabelList select axisLabel.ActualLeft).Min(); RightOverflow = (from axisLabel in AxisLabelList select (axisLabel.ActualLeft + axisLabel.ActualWidth)).Max() - Width; } else { LeftOverflow = 0; RightOverflow = 0; } // if over flow is negative only then an actual overflow has ocured if ((Boolean)ParentAxis.Enabled) LeftOverflow = LeftOverflow > 0 ? 0 : Math.Abs(LeftOverflow); else LeftOverflow = 0; // if over flow is positive only then an actual overflow has ocured RightOverflow = RightOverflow < 0 ? 0 : RightOverflow; // For top or bottom these will remain zero TopOverflow = 0; BottomOverflow = 0; } /// /// This is for axis with placement setting as left or right /// private void CalculateVerticalOverflow() { // Check if the label list contains any labels or not (if not then set the overflow to 0) if (AxisLabelList.Count > 0) { TopOverflow = (from axisLabel in AxisLabelList select axisLabel.ActualTop).Min(); BottomOverflow = ((from axisLabel in AxisLabelList select (axisLabel.ActualTop + axisLabel.ActualHeight)).Max()) - Height; } else { TopOverflow = 0; BottomOverflow = 0; } // if over flow is negative only then an actual overflow has ocured TopOverflow = TopOverflow > 0 ? 0 : Math.Abs(TopOverflow); // if over flow is positive only then an actual overflow has ocured BottomOverflow = BottomOverflow < 0 ? 0 : BottomOverflow; // For left or right these will remain zero LeftOverflow = 0; RightOverflow = 0; } /// /// Returns the proper angle value for calculation /// private Double GetAngle() { return Double.IsNaN((Double)this.InternalAngle) ? 0 : (Double)this.InternalAngle; } /// /// Calculates default font size based on a scaling criteria /// /// Double /// FontSize as Double private Double CalculateFontSize(Double area) { if (Double.IsNaN(InternalFontSize) || InternalFontSize <= 0) { return Graphics.DefaultFontSizes[1]; } else return InternalFontSize; } /// /// Calculate auto font size /// /// Double /// Double /// FontSize as Double private Double AutoAdjustFontSize(Double initialFontSize, Double width) { Double minimumFontSize = 8; Double fontSize = initialFontSize; TextBlock textBlock = new TextBlock(); Double labelsWidth = 0; Size textBlockSize; for (; fontSize > minimumFontSize; fontSize -= 2) { textBlock.FontSize = fontSize; labelsWidth = 0; foreach (AxisLabel label in AxisLabelList) { textBlock.Text = " " + label.Text + " "; textBlockSize = Graphics.CalculateTextBlockSize(AxisLabel.GetRadians(GetAngle()), textBlock); labelsWidth += textBlockSize.Width; } if (labelsWidth <= width) break; } return fontSize; } private Int32 CalculateRows() { TextBlock textBlock = new TextBlock(); textBlock = SetFontProperties(textBlock); //Calculate interval Double interval = (Double)((Double.IsNaN((Double)Interval) && Interval <= 0) ? Interval : ParentAxis.InternalInterval); Double pixelInterval = Graphics.ValueToPixelPosition(0, Width, Minimum, Maximum, interval + Minimum); List labelWidths = new List(); Double maxRowHeight = 0; Size textBlockSize; foreach (AxisLabel label in AxisLabelList) { textBlock.Text = " " + label.Text + " "; textBlockSize = Graphics.CalculateTextBlockSize(AxisLabel.GetRadians(GetAngle()), textBlock); if (!Double.IsNaN((Double)this.InternalAngle)) { #if WPF textBlockSize.Width = (Math.Cos(AxisLabel.GetRadians(GetAngle())) * textBlock.DesiredSize.Height) + textBlock.DesiredSize.Height / 2; #else textBlockSize.Width = (Math.Cos(AxisLabel.GetRadians(GetAngle())) * textBlock.ActualHeight) + textBlock.ActualHeight / 2; #endif } maxRowHeight = Math.Max(maxRowHeight, textBlockSize.Height); labelWidths.Add(textBlockSize.Width); } _maxRowHeight = maxRowHeight; Boolean overlap; Int32 rows; for (rows = 1; rows <= 3; rows++) { overlap = false; for (Int32 i = 0; i < labelWidths.Count - rows; i++) { Double labelFittingSize = labelWidths[i] / 2 + labelWidths[i + rows] / 2; if (labelFittingSize > pixelInterval * rows) { overlap = true; break; } } if (!overlap) break; } return rows; } /// /// Calculate number of rows for axislabels /// /// private Int32 CalculateNumberOfRows() { if (InternalRows <= 0) { Int32 rows; rows = CalculateRows(); return rows; } else return (Int32)InternalRows; } /// /// Set properties of a textblock /// /// TextBlock /// TextBlock private TextBlock SetFontProperties(TextBlock textBlock) { textBlock.FontSize = InternalFontSize; /* set other font properties */ textBlock.FontFamily = InternalFontFamily; textBlock.FontStyle = InternalFontStyle; textBlock.FontWeight = InternalFontWeight; return textBlock; } /// /// Get max height of axislabels /// /// Double private Double GetMaxHeight() { TextBlock textBlock = new TextBlock(); textBlock = SetFontProperties(textBlock); Double maxRowHeight = 0; Size textBlockSize; Int32 labelIndex = 0; for (labelIndex = 0; labelIndex < AxisLabelList.Count ; labelIndex += (ParentAxis.SkipOffset + 1)) { AxisLabel label = AxisLabelList[labelIndex]; textBlock.Text = label.Text; textBlockSize = Graphics.CalculateTextBlockSize(AxisLabel.GetRadians(GetAngle()), textBlock); maxRowHeight = Math.Max(maxRowHeight, textBlockSize.Height); } return maxRowHeight; } /// /// Calculate default values for angle and rows of axis /// private void CalculateHorizontalDefaults() { IsNotificationEnable = false; Double width = Double.IsNaN(Width) ? 0 : Width; Double height = Double.IsNaN(Height) ? 0 : Height; Double max = Math.Max(width, height); if (Double.IsNaN(InternalFontSize) || InternalFontSize <= 0) { Double initialFontSize = CalculateFontSize(max); InternalFontSize = initialFontSize; } if (InternalRows <= 0) { Int32 rows = CalculateNumberOfRows(); if (rows > 2 && Double.IsNaN((Double)InternalAngle)) { InternalRows = 1; InternalAngle = ((Chart as Chart).IsScrollingActivated && ParentAxis.XValueType != ChartValueTypes.Numeric) ? -90 : -45; if ((Double.IsNaN((Double)ParentAxis.Interval) && Double.IsNaN((Double)Interval) || (ParentAxis.IntervalType == IntervalTypes.Auto && ParentAxis.IsDateTimeAxis))) ParentAxis.SkipOffset = CalculateSkipOffset((int)InternalRows, (Double)InternalAngle, Width); else { ParentAxis.SkipOffset = 0; rows = CalculateRows(); InternalRows = rows; } } else if (rows >= 2 && !Double.IsNaN((Double)InternalAngle) && (Double.IsNaN((Double)ParentAxis.Interval) && Double.IsNaN((Double)Interval) || (ParentAxis.IntervalType == IntervalTypes.Auto && ParentAxis.IsDateTimeAxis))) { InternalRows = 1; ParentAxis.SkipOffset = CalculateSkipOffset((int)InternalRows, (Double)InternalAngle, Width); } else { InternalRows = rows; } } else { Int32 rows = CalculateNumberOfRows(); if (rows > 2 && Double.IsNaN((Double)InternalAngle)) { InternalAngle = ((Chart as Chart).IsScrollingActivated && ParentAxis.XValueType != ChartValueTypes.Numeric) ? -90 : -45; } } _maxRowHeight = GetMaxHeight(); IsNotificationEnable = true; } /// /// Calculate skip offset for axis labels /// /// Number of rows /// Rotation angle of labels /// Width of the axis /// Offset as Int32 private Int32 CalculateSkipOffset(Int32 noOfRows, Double angle, Double axisWidth) { Int32 skipOffset = 0; // Skip offset Boolean overlap = true; Double interval = (Double)((Double.IsNaN((Double)Interval) && Interval <= 0) ? Interval : ParentAxis.InternalInterval); //Double interval = (Double)((Double.IsNaN((Double)Interval) || Interval <= 0) ? ParentAxis.InternalInterval : Interval); Double pixelInterval; TextBlock textBlock = new TextBlock(); textBlock = SetFontProperties(textBlock); //textBlock.Text = "ABCD"; Double maxHeight = 0; List labelHeights = new List(); foreach (AxisLabel label in AxisLabelList) { textBlock.Text = label.Text; #if WPF Size textBlockSize = Graphics.CalculateVisualSize(textBlock); labelHeights.Add(textBlockSize.Height); #else labelHeights.Add(textBlock.ActualHeight); #endif } for (Int32 i = 0; i < labelHeights.Count - 1; i++) { maxHeight = Math.Max(maxHeight, (labelHeights[i] + labelHeights[i + 1]) / 2 + 2); } while(overlap) { pixelInterval = Graphics.ValueToPixelPosition(0, Width, Minimum, Maximum, interval + skipOffset + Minimum); #if WPF if (pixelInterval >= maxHeight) #else if (pixelInterval >= maxHeight) #endif { overlap = false; } else skipOffset++; } return skipOffset; } /// /// Returns formatted string from a given value depending upon scaling set and value format string /// /// Double value /// String private String GetFormattedString(Double value) { return (ParentAxis != null)? ParentAxis.GetFormattedString(value) : value.ToString(); } /// /// Calculate default values for vertical axis /// private void CalculateVerticalDefaults() { Double width = Double.IsNaN(Width) ? 0 : Width; Double height = Double.IsNaN(Height) ? 0 : Height; Double max = Math.Max(width, height); if (Double.IsNaN(InternalFontSize) || InternalFontSize <= 0) { InternalFontSize = CalculateFontSize(max); } } #endregion #region Private Properties /// /// Identifies the Visifire.Charts.AxisLabels.ToolTipText dependency property. /// /// /// The identifier for the Visifire.Charts.AxisLabels.ToolTipText dependency property. /// private new static readonly DependencyProperty ToolTipTextProperty = DependencyProperty.Register ("ToolTipText", typeof(String), typeof(AxisLabels), null); #endregion #region Internal Methods /// /// Update visual used for partial update /// /// Name of the property /// Value of the property internal override void UpdateVisual(string propertyName, object value) { if (Visual != null) { foreach (AxisLabel axisLabel in AxisLabelList) { ApplyAxisLabelFontProperties(axisLabel); axisLabel.ApplyProperties(axisLabel); } } else FirePropertyChanged(propertyName); } /// /// Creates a visual object for the element /// internal void CreateVisualObject() { // Create a new Visual = new Canvas(); if (!(Boolean)Enabled) { Visual = null; return; } // Create new Labels list AxisLabelList = new List(); // List to store the values for which the labels are created LabelValues = new List(); if (InternalFontSize != _savedFontSize || InternalAngle != _savedAngle || InternalRows != _savedRows) _isRedraw = false; // check if this is a first time draw or a redraw if (_isRedraw) { // if redraw then restore the original values InternalAngle = _savedAngle; InternalFontSize = _savedFontSize; InternalRows = _savedRows; } else { // Preserve the original values for future use _savedAngle = (Double)InternalAngle; _savedFontSize = InternalFontSize; _savedRows = (Int32)InternalRows; _isRedraw = true; } // create the required labels CreateLabels(); // Set the position of the labels SetLabelPosition(); Visual.Opacity = InternalOpacity; } #endregion #region Internal Events #endregion #region Data /// /// Saved max row height /// private Double _maxRowHeight; /// /// Saved font size of axislabels /// private Double _savedFontSize; /// /// Saved number of rows /// private Int32 _savedRows; /// /// Saved old angle /// private Double _savedAngle; /// /// Whether the axis need to redraw /// private Boolean _isRedraw; /// /// Parent axis /// private Axis _parent; private Double _internalFontSize = Double.NaN; private FontFamily _internalFontFamily = null; internal Brush InternalFontColor; Nullable _internalFontStyle = null; Nullable _internalFontWeight = null; Double _internalOpacity = Double.NaN; ElementData _tag; #if WPF /// /// Whether the default style is applied /// private static Boolean _defaultStyleKeyApplied; #endif #endregion } }