/*
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.Controls.Primitives;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Globalization;
using System.Collections.ObjectModel;
#else
using System;
using System.Windows;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Windows.Browser;
#endif
using Visifire.Commons;
using System.Windows.Data;
namespace Visifire.Charts
{
///
/// Visifire.Charts.Axis class
///
#if SL
[System.Windows.Browser.ScriptableType]
#endif
public class Axis : ObservableObject
{
#region Public Methods
///
/// Initializes a new instance of the Visifire.Charts.Axis class
///
public Axis()
{
// Initialize list of ChartGrid list
Grids = new ChartGridCollection();
// Initialize list of Ticks list
Ticks = new TicksCollection();
// Initialize AxisLabels element
AxisLabels = new AxisLabels();
// Attach event handler on collection changed event with chart grid collection
Grids.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Grids_CollectionChanged);
// Attach event handler on collection changed event with ticks collection
Ticks.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Ticks_CollectionChanged);
InternalAxisMinimum = Double.NaN;
InternalAxisMaximum = Double.NaN;
}
public override void Bind()
{
#if SL
Binding b = new Binding("Background");
b.Source = this;
this.SetBinding(InternalBackgroundProperty, b);
b = new Binding("Padding");
b.Source = this;
this.SetBinding(InternalPaddingProperty, b);
b = new Binding("Opacity");
b.Source = this;
this.SetBinding(InternalOpacityProperty, b);
#endif
}
#endregion
#region Public Properties
///
/// Identifies the Visifire.Charts.Axis.AxisLabels dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.AxisLabels dependency property.
///
public static DependencyProperty AxisLabelsProperty = DependencyProperty.Register
("AxisLabels",
typeof(AxisLabels),
typeof(Axis),
new PropertyMetadata(OnAxisLabelsPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.HrefTarget dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.HrefTarget dependency property.
///
public static readonly DependencyProperty HrefTargetProperty = DependencyProperty.Register
("HrefTarget",
typeof(HrefTargets),
typeof(Axis),
new PropertyMetadata(OnHrefTargetChanged));
///
/// Identifies the Visifire.Charts.Axis.Href dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.Href dependency property.
///
public static readonly DependencyProperty HrefProperty = DependencyProperty.Register
("Href",
typeof(String),
typeof(Axis),
new PropertyMetadata(OnHrefChanged));
#if WPF
///
/// Identifies the Visifire.Charts.Axis.Padding dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.Padding dependency property.
///
public new static readonly DependencyProperty PaddingProperty = DependencyProperty.Register
("Padding",
typeof(Thickness),
typeof(Axis),
new PropertyMetadata(OnPaddingPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.Background dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.Background dependency property.
///
public new static readonly DependencyProperty BackgroundProperty = DependencyProperty.Register
("Background",
typeof(Brush),
typeof(Axis),
new PropertyMetadata(OnBackgroundPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.Opacity dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.Opacity dependency property.
///
public new static readonly DependencyProperty OpacityProperty = DependencyProperty.Register
("Opacity",
typeof(Double),
typeof(Axis),
new PropertyMetadata(1.0, OnOpacityPropertyChanged));
#endif
///
/// Identifies the Visifire.Charts.Axis.Interval dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.Interval dependency property.
///
public static readonly DependencyProperty IntervalProperty = DependencyProperty.Register
("Interval",
typeof(Nullable),
typeof(Axis),
new PropertyMetadata(OnIntervalPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.LineColor dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.LineColor dependency property.
///
public static readonly DependencyProperty LineColorProperty = DependencyProperty.Register
("LineColor",
typeof(Brush),
typeof(Axis),
new PropertyMetadata(OnLineColorPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.LineThickness dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.LineThickness dependency property.
///
public static readonly DependencyProperty LineThicknessProperty = DependencyProperty.Register
("LineThickness",
typeof(Double),
typeof(Axis),
new PropertyMetadata(OnLineThicknessPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.LineStyle dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.LineStyle dependency property.
///
public static readonly DependencyProperty LineStyleProperty = DependencyProperty.Register
("LineStyle",
typeof(LineStyles),
typeof(Axis),
new PropertyMetadata(OnLineStylePropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.Title dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.Title dependency property.
///
public static readonly DependencyProperty TitleProperty = DependencyProperty.Register
("Title",
typeof(String),
typeof(Axis),
new PropertyMetadata(OnTitlePropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.TitleFontColor dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.TitleFontColor dependency property.
///
public static readonly DependencyProperty TitleFontColorProperty = DependencyProperty.Register
("TitleFontColor",
typeof(Brush),
typeof(Axis),
new PropertyMetadata(OnTitleFontColorPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.TitleFontFamily dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.TitleFontFamily dependency property.
///
public static readonly DependencyProperty TitleFontFamilyProperty = DependencyProperty.Register
("TitleFontFamily",
typeof(FontFamily),
typeof(Axis),
new PropertyMetadata(OnTitleFontFamilyPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.TitleFontSize dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.TitleFontSize dependency property.
///
public static readonly DependencyProperty TitleFontSizeProperty = DependencyProperty.Register
("TitleFontSize",
typeof(Double),
typeof(Axis),
new PropertyMetadata(OnTitleFontSizePropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.TitleFontStyle dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.TitleFontStyle dependency property.
///
public static readonly DependencyProperty TitleFontStyleProperty = DependencyProperty.Register
("TitleFontStyle",
typeof(FontStyle),
typeof(Axis),
new PropertyMetadata(OnTitleFontStylePropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.TitleFontWeight dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.TitleFontWeight dependency property.
///
public static readonly DependencyProperty TitleFontWeightProperty = DependencyProperty.Register
("TitleFontWeight",
typeof(FontWeight),
typeof(Axis),
new PropertyMetadata(OnTitleFontWeightPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.AxisType dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.AxisType dependency property.
///
public static readonly DependencyProperty AxisTypeProperty = DependencyProperty.Register
("AxisType",
typeof(AxisTypes),
typeof(Axis),
new PropertyMetadata(OnAxisTypePropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.AxisMaximum dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.AxisMaximum dependency property.
///
public static readonly DependencyProperty AxisMaximumProperty = DependencyProperty.Register
("AxisMaximum",
typeof(Object),
typeof(Axis),
new PropertyMetadata(null, OnAxisMaximumPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.AxisMinimum dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.AxisMinimum dependency property.
///
public static readonly DependencyProperty AxisMinimumProperty = DependencyProperty.Register
("AxisMinimum",
typeof(Object),
typeof(Axis),
new PropertyMetadata(null, OnAxisMinimumPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.IncludeZero dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.IncludeZero dependency property.
///
public static readonly DependencyProperty IncludeZeroProperty = DependencyProperty.Register
("IncludeZero",
typeof(Boolean),
typeof(Axis),
new PropertyMetadata(OnIncludeZeroPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.StartFromZero dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.StartFromZero dependency property.
///
public static readonly DependencyProperty StartFromZeroProperty = DependencyProperty.Register
("StartFromZero",
typeof(Nullable),
typeof(Axis),
new PropertyMetadata(OnStartFromZeroPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.Prefix dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.Prefix dependency property.
///
public static readonly DependencyProperty PrefixProperty = DependencyProperty.Register
("Prefix",
typeof(String),
typeof(Axis),
new PropertyMetadata(OnPrefixPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.Suffix dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.Suffix dependency property.
///
public static readonly DependencyProperty SuffixProperty = DependencyProperty.Register
("Suffix",
typeof(String),
typeof(Axis),
new PropertyMetadata(OnSuffixPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.ScalingSet dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.ScalingSet dependency property.
///
public static readonly DependencyProperty ScalingSetProperty = DependencyProperty.Register
("ScalingSet",
typeof(String),
typeof(Axis),
new PropertyMetadata(OnScalingSetPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.ValueFormatString dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.ValueFormatString dependency property.
///
public static readonly DependencyProperty ValueFormatStringProperty = DependencyProperty.Register
("ValueFormatString",
typeof(String),
typeof(Axis),
new PropertyMetadata(OnValueFormatStringPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.ScrollBarOffset dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.ScrollBarOffset dependency property.
///
public static readonly DependencyProperty ScrollBarOffsetProperty = DependencyProperty.Register
("ScrollBarOffset",
typeof(Double),
typeof(Axis),
new PropertyMetadata(Double.NaN, OnScrollBarOffsetChanged));
// Using a DependencyProperty as the backing store for ScrollBarScale. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ScrollBarScaleProperty =
DependencyProperty.Register("ScrollBarScale", typeof(double), typeof(Axis), new PropertyMetadata(Double.NaN, OnScrollBarScalePropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.Enabled dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.Enabled dependency property.
///
public static readonly DependencyProperty EnabledProperty = DependencyProperty.Register
("Enabled",
typeof(Nullable),
typeof(Axis),
new PropertyMetadata(OnEnabledPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.InternalIntervalType dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.InternalIntervalType dependency property.
///
public static readonly DependencyProperty IntervalTypeProperty = DependencyProperty.Register
("IntervalType",
typeof(IntervalTypes),
typeof(Axis),
new PropertyMetadata(OnIntervalTypePropertyChanged));
///
/// Height of the Axis
///
#if SL
[ScriptableMember]
#endif
public new Double Height
{
get;
internal set;
}
///
/// Width of the Axis
///
#if SL
[ScriptableMember]
#endif
public new Double Width
{
get;
internal set;
}
///
/// Get or set the "AxisLabels element" property of the axis
///
public IntervalTypes IntervalType
{
get
{
return (IntervalTypes)GetValue(IntervalTypeProperty);
}
set
{
SetValue(IntervalTypeProperty, value);
}
}
///
/// Get or set the "AxisLabels element" property of the axis
///
public AxisLabels AxisLabels
{
get
{
return (AxisLabels)GetValue(AxisLabelsProperty);
}
set
{
SetValue(AxisLabelsProperty, 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
}
}
///
/// Get or set the Cursor property
///
public new Cursor Cursor
{
get
{
return base.Cursor;
}
set
{
if (base.Cursor != value)
{
base.Cursor = value;
FirePropertyChanged("Cursor");
}
}
}
///
/// Get or set the href target property of the axis
///
public HrefTargets HrefTarget
{
get
{
return (HrefTargets)GetValue(HrefTargetProperty);
}
set
{
SetValue(HrefTargetProperty, value);
}
}
///
/// Get or set the href property of the axis
///
public String Href
{
get
{
return (String)GetValue(HrefProperty);
}
set
{
SetValue(HrefProperty, value);
}
}
///
/// Get or set the background property of the axis
///
public new Brush Background
{
get
{
return (Brush)GetValue(BackgroundProperty);
}
set
{
#if SL
if (Background != value)
{
InternalBackground = value;
SetValue(BackgroundProperty, value);
FirePropertyChanged("Background");
}
#else
SetValue(BackgroundProperty, value);
#endif
}
}
///
/// Get or set the interval for all the axis elements
///
#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);
_axisIntervalOverride = (Double)value;
}
}
///
/// Get or set the Color of the axis line
///
public Brush LineColor
{
get
{
return (Brush)GetValue(LineColorProperty);
}
set
{
SetValue(LineColorProperty, value);
}
}
///
/// Get or set the thickness of the axis line
///
public Double LineThickness
{
get
{
return (Double)GetValue(LineThicknessProperty);
}
set
{
SetValue(LineThicknessProperty, value);
}
}
///
/// Get or set the style of the axis line. It takes values like "Dashed", "Dotted" etc
///
public LineStyles LineStyle
{
get
{
return (LineStyles)GetValue(LineStyleProperty);
}
set
{
SetValue(LineStyleProperty, value);
}
}
///
/// Get or set the padding of the axis
///
public new Thickness Padding
{
get
{
return (Thickness)GetValue(PaddingProperty);
}
set
{
#if WPF
SetValue(PaddingProperty, value);
#else
InternalPadding = value;
SetValue(PaddingProperty, value);
FirePropertyChanged("Padding");
#endif
}
}
///
/// Get or set the title for the axis
///
public String Title
{
get
{
return (String)GetValue(TitleProperty);
}
set
{
SetValue(TitleProperty, value);
}
}
///
/// Get or set the font color for axis title
///
public Brush TitleFontColor
{
get
{
return (Brush)GetValue(TitleFontColorProperty);
}
set
{
SetValue(TitleFontColorProperty, value);
}
}
///
/// Get or set the font family for axis title
///
public FontFamily TitleFontFamily
{
get
{
return (FontFamily)GetValue(TitleFontFamilyProperty);
}
set
{
SetValue(TitleFontFamilyProperty, value);
}
}
///
/// Get or set the font size for axis title
///
public Double TitleFontSize
{
get
{
return (Double)GetValue(TitleFontSizeProperty);
}
set
{
SetValue(TitleFontSizeProperty, value);
}
}
///
/// Get or set Sets the font style for axis title
///
public FontStyle TitleFontStyle
{
get
{
return (FontStyle)GetValue(TitleFontStyleProperty);
}
set
{
SetValue(TitleFontStyleProperty, value);
}
}
///
/// Get or set the font weight for axis title
///
public FontWeight TitleFontWeight
{
get
{
return (FontWeight)GetValue(TitleFontWeightProperty);
}
set
{
SetValue(TitleFontWeightProperty, value);
}
}
///
/// Get or set the axis type (Primary or Secondary)
///
public AxisTypes AxisType
{
get
{
return (AxisTypes)GetValue(AxisTypeProperty);
}
set
{
SetValue(AxisTypeProperty, value);
}
}
///
/// Get or set the maximum value for the axis
///
//#if SL
// [System.ComponentModel.TypeConverter(typeof(Converters.NullableDoubleConverter))]
//#endif
public Object AxisMaximum
{
get
{
return (Object)GetValue(AxisMaximumProperty);
}
set
{
SetValue(AxisMaximumProperty, value);
}
}
///
/// Get or set the minimum value for the axis
///
//#if SL
// [System.ComponentModel.TypeConverter(typeof(Converters.NullableDoubleConverter))]
//#endif
public Object AxisMinimum
{
get
{
return (Object)GetValue(AxisMinimumProperty);
}
set
{
SetValue(AxisMinimumProperty, value);
}
}
///
/// Include zero within the axis range
///
public Boolean IncludeZero
{
get
{
return (Boolean)GetValue(IncludeZeroProperty);
}
set
{
SetValue(IncludeZeroProperty, value);
}
}
///
/// Get or set dateTime from zero property of the axis.
/// Forces the axis to include zero or atleast have either AxisMinimum or AxisMaximum as zero
///
[System.ComponentModel.TypeConverter(typeof(NullableBoolConverter))]
public Nullable StartFromZero
{
get
{
if ((Nullable)GetValue(StartFromZeroProperty) == null)
{
if (AxisRepresentation == AxisRepresentations.AxisY)
return true;
else
return false;
}
else
return (Nullable)GetValue(StartFromZeroProperty);
}
set
{
SetValue(StartFromZeroProperty, value);
}
}
///
/// Get or set the prefix for the axis labels used in the axis
///
public String Prefix
{
get
{
return (String)GetValue(PrefixProperty);
}
set
{
SetValue(PrefixProperty, value);
}
}
///
/// Get or set the suffix for the axis labels used in the axis
///
public String Suffix
{
get
{
return (String)GetValue(SuffixProperty);
}
set
{
SetValue(SuffixProperty, value);
}
}
///
/// Get or set the scaling values for the axis
///
public String ScalingSet
{
get
{
return (String)GetValue(ScalingSetProperty);
}
set
{
SetValue(ScalingSetProperty, value);
}
}
///
/// Get or set the format string that can be used with the axis labels
///
public String ValueFormatString
{
get
{
return String.IsNullOrEmpty((String)GetValue(ValueFormatStringProperty)) ? "###,##0.##" : (String)GetValue(ValueFormatStringProperty);
}
set
{
SetValue(ValueFormatStringProperty, value);
}
}
///
/// Get or set scrollbar offset value property of the axis.
/// ScrollBarOffset value can be accessed after the chart is rendered. Value range from 0 to 1
///
public Double ScrollBarOffset
{
get
{
return (Double)GetValue(ScrollBarOffsetProperty);
}
set
{
if (value < 0 || value > 1)
throw new Exception("Value does not fall under the expected range. ScrollBarOffset always varies from 0 to 1.");
SetValue(ScrollBarOffsetProperty, value);
}
}
///
/// ScrollBarScale sets the size of ScrollBar thumb.
/// Example, if ScrollBarScale is set to 0.5, width of ScrollBar thumb will be
/// half of the ScrollBar width which in turn increase the PlotArea width to
/// double the actual width of PlotArea.
///
public Double ScrollBarScale
{
get { return (Double)GetValue(ScrollBarScaleProperty); }
set {
if (value <= 0 || value > 1)
throw new Exception("Value does not fall under the expected range. ScrollBarScale always varies from 0 to 1.");
SetValue(ScrollBarScaleProperty, value);
}
}
///
/// Get or set enabled property of the axis
///
[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);
}
}
///
/// Collection of grids for an axis
///
public ChartGridCollection Grids
{
get;
set;
}
///
/// Collection of ticks for an axis
///
public TicksCollection Ticks
{
get;
set;
}
#endregion
#region Public Events And Delegates
#endregion
#region Protected Methods
#endregion
#region Internal Properties
#if SL
///
/// Identifies the Visifire.Charts.Axis.Padding dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.Padding dependency property.
///
private static readonly DependencyProperty InternalPaddingProperty = DependencyProperty.Register
("InternalPadding",
typeof(Thickness),
typeof(Axis),
new PropertyMetadata(OnPaddingPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.Opacity dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.Opacity dependency property.
///
private static readonly DependencyProperty InternalOpacityProperty = DependencyProperty.Register
("InternalOpacity",
typeof(Double),
typeof(Axis),
new PropertyMetadata(1.0, OnOpacityPropertyChanged));
///
/// Identifies the Visifire.Charts.Axis.Background dependency property.
///
///
/// The identifier for the Visifire.Charts.Axis.Background dependency property.
///
private static readonly DependencyProperty InternalBackgroundProperty = DependencyProperty.Register
("InternalBackground",
typeof(Brush),
typeof(Axis),
new PropertyMetadata(OnBackgroundPropertyChanged));
#endif
///
/// Get or set the Background property of title
///
internal Brush InternalBackground
{
get
{
return (Brush)((_internalBackground == null) ? GetValue(BackgroundProperty) : _internalBackground);
}
set
{
_internalBackground = value;
}
}
///
/// Get or set the Padding property of title
///
public Thickness InternalPadding
{
get
{
return (Thickness)((_internalPadding == null) ? GetValue(PaddingProperty) : _internalPadding);
}
set
{
_internalPadding = value;
}
}
///
/// Get or set the Opacity property
///
internal Double InternalOpacity
{
get
{
return (Double)(Double.IsNaN(_internalOpacity) ? GetValue(OpacityProperty) : _internalOpacity);
}
set
{
_internalOpacity = value;
}
}
///
/// AxisMinimum Numeric value
///
internal Double AxisMinimumNumeric = Double.NaN;
///
/// AxisMinimum DateTime value
///
internal DateTime AxisMinimumDateTime;
///
/// AxisMaximum numeric value
///
internal Double AxisMaximumNumeric = Double.NaN;
///
/// AxisMaximum DateTime value
///
internal DateTime AxisMaximumDateTime;
///
/// Internal interval type used to handle auto interval type
///
internal IntervalTypes InternalIntervalType
{
get;
set;
}
///
/// Axis is a DateTime axis
///
internal Boolean IsDateTimeAxis
{
get;
set;
}
///
/// Axis XValue Types
///
internal ChartValueTypes XValueType
{
get;
set;
}
///
/// Axis Minimum Date
///
internal DateTime MinDate
{
get;
set;
}
///
/// Axis Maximum Date
///
internal DateTime MaxDate
{
get;
set;
}
internal TimeSpan MinDateRange
{
get;
set;
}
internal TimeSpan MaxDateRange
{
get;
set;
}
///
/// Returns the visual element for the Axis
///
internal StackPanel Visual
{
get;
set;
}
///
/// Internal axis minimum is used for internal calculation purpose
///
internal Double InternalAxisMinimum
{
get;
set;
}
///
/// Internal axis maximum is used for internal calculation purpose
///
internal Double InternalAxisMaximum
{
get;
set;
}
///
/// Internal interval is used for internal calculation purpose
///
internal Double InternalInterval
{
get;
set;
}
///
/// Keep tracks about current offsetvalue of the axis scrollviewer
///
internal Double CurrentScrollScrollBarOffset
{
get;
set;
}
///
/// Get or set the data maximum for the axis
///
internal Double Maximum
{
get;
set;
}
///
/// Get or set the data minimum for the axis
///
internal Double Minimum
{
get;
set;
}
///
/// Get or set majorgrid element
///
internal ChartGrid MajorGridsElement
{
get;
set;
}
///
/// Get or set the scroll bar
///
internal ScrollBar ScrollBarElement
{
get;
set;
}
///
/// Get or set axis scrollviewer element
///
internal Canvas ScrollViewerElement
{
get;
set;
}
///
/// Get or set the major ticks
///
internal Ticks MajorTicksElement
{
get;
set;
}
///
/// Get or set the axis title element
///
internal Title AxisTitleElement
{
get;
set;
}
///
/// Get or set the axis manager of the axis
///
internal AxisManager AxisManager
{
get;
set;
}
///
/// Scrollable size of PlotArea
///
internal Double ScrollableSize
{
get;
set;
}
///
/// Line for axis
///
internal Line AxisLine
{
get;
set;
}
///
/// Get or set the axis orientation.
/// Vertical = AxisY for all types except bar,
/// Horizontal = AxesX for types except bar
///
internal Orientation AxisOrientation
{
get
{
return _orientation;
}
set
{
_orientation = value;
}
}
///
/// Get or set the axis representation
///
internal AxisRepresentations AxisRepresentation
{
get;
set;
}
///
/// Details about plot groups
///
internal PlotDetails PlotDetails
{
get;
set;
}
///
/// Scale values of axis
///
internal List ScaleValues
{
get
{
return _scaleValues;
}
}
///
/// Scale units of axis
///
internal List ScaleUnits
{
get
{
return _scaleUnits;
}
}
///
/// Get or set the axis dateTime offset
///
internal Double StartOffset
{
get;
set;
}
///
/// Get or set the axis end offset
///
internal Double EndOffset
{
get;
set;
}
///
/// Get or set the axis skip offset
///
internal Int32 SkipOffset
{
get;
set;
}
#endregion
#region Private Properties
///
/// StackPanel used for internal purpose
///
private Canvas InternalStackPanel
{
get;
set;
}
#region Hidden Control Properties
///
/// Get or set
///
private new FontFamily FontFamily
{
get;
set;
}
private new static DependencyProperty FontFamilyProperty = DependencyProperty.Register
("FontFamily",
typeof(FontFamily),
typeof(Axis),
null);
private new Double FontSize
{
get;
set;
}
private new static DependencyProperty FontSizeProperty = DependencyProperty.Register
("FontSize",
typeof(Double),
typeof(Axis),
null);
private new FontStretch FontStretch
{
get;
set;
}
private new static DependencyProperty FontStretchProperty = DependencyProperty.Register
("FontStretch",
typeof(FontStretch),
typeof(Axis),
null);
private new FontStyle FontStyle
{
get;
set;
}
private new static DependencyProperty FontStyleProperty = DependencyProperty.Register
("FontStyle",
typeof(FontStyle),
typeof(Axis),
null);
private new FontWeight FontWeight
{
get;
set;
}
private new static DependencyProperty FontWeightProperty = DependencyProperty.Register
("FontWeight",
typeof(FontWeight),
typeof(Axis),
null);
private new Brush Foreground
{
get;
set;
}
private new static DependencyProperty ForegroundProperty = DependencyProperty.Register
("Foreground",
typeof(Brush),
typeof(Axis),
null);
private new Thickness BorderThickness
{
get;
set;
}
private new static DependencyProperty BorderThicknessProperty = DependencyProperty.Register
("BorderThickness",
typeof(Thickness),
typeof(Axis),
null);
private new Brush BorderBrush
{
get;
set;
}
private new static DependencyProperty BorderBrushProperty = DependencyProperty.Register
("BorderBrush",
typeof(Brush),
typeof(Axis),
null);
#endregion
#endregion
#region Private Delegates
#endregion
#region Private Methods
//
/// Event handler attached with Padding property changed event of AxisLabels elements
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnPaddingPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.InternalPadding = (Thickness)e.NewValue;
axis.FirePropertyChanged("Padding");
}
///
/// Event handler manages background property change of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnBackgroundPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.InternalBackground = (Brush)e.NewValue;
axis.FirePropertyChanged("Background");
}
///
/// OpacityProperty changed call back function
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnOpacityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.InternalOpacity= (Double) e.NewValue;
axis.FirePropertyChanged("Opacity");
}
///
/// Event handler manages axislabels property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnAxisLabelsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
if (axis.Chart != null)
axis.AxisLabels.Chart = axis.Chart;
axis.AxisLabels.Parent = axis;
axis.AxisLabels.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(AxisLabels_PropertyChanged);
axis.FirePropertyChanged("AxisLabels");
}
///
/// Event handler manages property change event of axislabels element
///
/// ObservableObject
/// PropertyChangedEventArgs
private static void AxisLabels_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
(sender as AxisLabels).Parent.FirePropertyChanged(e.PropertyName);
}
///
/// Event handler manages href target property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnHrefTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("HrefTarget");
}
///
/// Event handler manages href property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnHrefChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("Href");
}
///
/// Event handler manages interval property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnIntervalPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("Interval");
}
///
/// Event handler manages linecolor property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnLineColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("LineColor");
}
///
/// Event handler manages linethickness property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnLineThicknessPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("LineThickness");
}
///
/// Event handler manages linestyle property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnLineStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("LineStyle");
}
///
/// Event handler manages title property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnTitlePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("Title");
}
///
/// Event handler manages titlefontcolor property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnTitleFontColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("TitleFontColor");
}
///
/// Event handler manages titlefontfamily property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnTitleFontFamilyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("TitleFontFamily");
}
///
/// Event handler manages titlefontsize property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnTitleFontSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("TitleFontSize");
}
///
/// Event handler manages titlefontstyle property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnTitleFontStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("TitleFontStyle");
}
///
/// Event handler manages title fontweight property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnTitleFontWeightPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("TitleFontWeight");
}
///
/// Event handler manages axistype property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnAxisTypePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("AxisType");
}
///
/// Event handler manages axis maximum property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnAxisMaximumPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
Double numericVal = axis.AxisMaximumNumeric;
DateTime dateTimeValue = axis.AxisMaximumDateTime;
Axis.ConvertValueToDateTimeOrNumeric("AxisMaximum", e.NewValue, ref numericVal, ref dateTimeValue, out axis._axisMaximumValueType);
axis.AxisMaximumNumeric = numericVal;
axis.AxisMaximumDateTime = dateTimeValue;
axis.FirePropertyChanged("AxisMaximum");
}
///
/// Event handler manages axis minimum property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnAxisMinimumPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
Double numericVal = axis.AxisMinimumNumeric;
DateTime dateTimeValue = axis.AxisMinimumDateTime;
Axis.ConvertValueToDateTimeOrNumeric("AxisMinimum", e.NewValue, ref numericVal, ref dateTimeValue, out axis._axisMinimumValueType);
axis.AxisMinimumNumeric = numericVal;
axis.AxisMinimumDateTime = dateTimeValue;
axis.FirePropertyChanged("AxisMinimum");
}
private static void ConvertValueToDateTimeOrNumeric(String propertyName, Object newValue, ref Double numericVal, ref DateTime dateTimeValue, out ChartValueTypes valueType)
{
// Double / Int32 value entered in Managed Code
if (newValue.GetType().Equals(typeof(Double)) || newValue.GetType().Equals(typeof(Int32)))
{
numericVal = Convert.ToDouble(newValue);
valueType = ChartValueTypes.Numeric;
}
// DateTime value entered in Managed Code
else if ((newValue.GetType().Equals(typeof(DateTime))))
{
dateTimeValue = (DateTime)newValue;
valueType = ChartValueTypes.DateTime;
}
// Double / Int32 / DateTime entered in XAML
else if ((newValue.GetType().Equals(typeof(String))))
{
DateTime dateTimeresult;
Double doubleResult;
if (String.IsNullOrEmpty(newValue.ToString()))
{
numericVal = Double.NaN;
valueType = ChartValueTypes.Numeric;
}
// Double entered in XAML
else if (Double.TryParse((string)newValue, System.Globalization.NumberStyles.Number, System.Globalization.CultureInfo.InvariantCulture, out doubleResult))
{
numericVal = doubleResult;
valueType = ChartValueTypes.Numeric;
}
// DateTime entered in XAML
else if (DateTime.TryParse((string)newValue, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out dateTimeresult))
{
dateTimeValue = dateTimeresult;
valueType = ChartValueTypes.DateTime;
}
else
{
System.Diagnostics.Debug.WriteLine("Invalid Input for " + propertyName);
throw new Exception("Invalid Input for " + propertyName);
}
}
else
{
System.Diagnostics.Debug.WriteLine("Invalid Input for " + propertyName);
throw new Exception("Invalid Input for " + propertyName);
}
}
///
/// Event handler manages include zero property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnIncludeZeroPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("IncludeZero");
}
///
/// Event handler manages dateTime from zero property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnStartFromZeroPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("StartFromZero");
}
///
/// Event handler manages prefix property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnPrefixPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("Prefix");
}
///
/// Event handler manages suffix property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnSuffixPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("Suffix");
}
///
/// Event handler manages scaling set property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnScalingSetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.ParseScalingSets((String)e.NewValue);
axis.FirePropertyChanged("ScalingSet");
}
///
/// Event handler manages value format string property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnValueFormatStringPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("ValueFormatString");
}
///
/// Event handler manages scrollbar offset property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnScrollBarOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
if (axis._isScrollToOffsetEnabled)
axis.SetScrollBarValueFromOffset((Double)e.NewValue);
}
private static void OnScrollBarScalePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
//if (axis._isScrollToOffsetEnabled)
// axis.SetScrollBarValueFromOffset((Double)e.NewValue);
axis.FirePropertyChanged("ScrollBarScale");
if (axis.Chart != null && (axis.Chart as Chart).ChartArea != null)
{
if (axis.IsNotificationEnable)
{
(axis.Chart as Chart).ChartArea.IsAutoCalculatedScrollBarScale = false;
}
else
{
(axis.Chart as Chart).ChartArea.IsAutoCalculatedScrollBarScale = true;
}
}
}
///
/// Event handler manages enabled property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.FirePropertyChanged("Enabled");
}
///
/// Event handler manages interval type property change event of axis
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnIntervalTypePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Axis axis = d as Axis;
axis.InternalIntervalType = (IntervalTypes)e.NewValue;
axis.FirePropertyChanged("IntervalType");
}
///
/// Set up axis manager and calculate axis values
///
private void SetUpAxisManager()
{
// Get the minimum and maximum value dependeing on the axis representation value
Minimum = AxisRepresentation == AxisRepresentations.AxisX ? PlotDetails.GetAxisXMinimumDataValue(this) : PlotDetails.GetAxisYMinimumDataValue(this);
Maximum = AxisRepresentation == AxisRepresentations.AxisX ? PlotDetails.GetAxisXMaximumDataValue(this) : PlotDetails.GetAxisYMaximumDataValue(this);
Boolean overflowValidity = (AxisRepresentation == AxisRepresentations.AxisX);
Boolean stackingOverride = PlotDetails.GetStacked100OverrideState();
// Create and initialize the AxisManagers
AxisManager = new AxisManager(Maximum, Minimum, (Boolean)StartFromZero, overflowValidity, stackingOverride, AxisRepresentation);
// Set the include zero state
AxisManager.IncludeZero = IncludeZero;
// settings specific to axis X
if (AxisRepresentation == AxisRepresentations.AxisX)
{
Double interval = GenerateDefaultInterval();
if (IsDateTimeAxis)
{
if (interval > 0 || !Double.IsNaN(interval))
{
AxisManager.Interval = interval;
InternalInterval = interval;
}
else
{
// if interval is greater than zero then set the interval of the axis manager
if (Interval > 0 || !Double.IsNaN((Double)Interval))
{
AxisManager.Interval = (Double)Interval;
InternalInterval = (Double)Interval;
}
}
}
else if (interval > 0 || !Double.IsNaN(interval))
{
AxisManager.Interval = interval;
InternalInterval = interval;
}
}
else
{
// if interval is greater than zero then set the interval of the axis manager
if (Interval > 0 || !Double.IsNaN((Double)Interval))
{
AxisManager.Interval = (Double)Interval;
InternalInterval = (Double)Interval;
}
}
// set the axis maximum value if user has provided it
if (!Double.IsNaN((Double)AxisMaximumNumeric))
{
AxisManager.AxisMaximumValue = (Double)AxisMaximumNumeric;
InternalAxisMaximum = (Double)AxisMaximumNumeric;
}
// set the axis minimum value if the user has provided it
if (!Double.IsNaN((Double)AxisMinimumNumeric))
{
AxisManager.AxisMinimumValue = (Double)AxisMinimumNumeric;
InternalAxisMinimum = (Double)AxisMinimumNumeric;
}
// Calculate the various parameters for creating the axis
AxisManager.Calculate();
// Set axis specific limits based on axis limits.
// if (AxisRepresentation == AxisRepresentations.AxisX && !(Boolean)StartFromZero)
// if (!SetAxesXLimits())
// return;
if (AxisRepresentation == AxisRepresentations.AxisX)
if (!SetAxesXLimits())
return;
// Settings specific to axis y
if (this.AxisRepresentation == AxisRepresentations.AxisY && this.AxisType == AxisTypes.Primary)
{
// Set the internal axis limits the one obtained from axis manager
InternalAxisMaximum = AxisManager.AxisMaximumValue;
InternalAxisMinimum = AxisManager.AxisMinimumValue;
}
else if (this.AxisRepresentation == AxisRepresentations.AxisY && this.AxisType == AxisTypes.Secondary)
{
var axisYPrimary = (from axis in (Chart as Chart).InternalAxesY where axis.AxisRepresentation == AxisRepresentations.AxisY && axis.AxisType == AxisTypes.Primary select axis);
Axis primaryAxisY = null;
if (axisYPrimary.Count() > 0)
primaryAxisY = axisYPrimary.First();
if (Double.IsNaN((double)Interval) && primaryAxisY != null)
{
// number of interval in the primary axis
Double primaryAxisIntervalCount = ((double)primaryAxisY.InternalAxisMaximum - (double)primaryAxisY.InternalAxisMinimum) / (double)primaryAxisY.InternalInterval;
// This will set the internal overriding flag
AxisManager.AxisMinimumValue = AxisManager.AxisMinimumValue;
AxisManager.AxisMaximumValue = AxisManager.AxisMaximumValue;
// This interval will reflect the interval in primary axis it is not same as that of primary axis
AxisManager.Interval = (AxisManager.AxisMaximumValue - AxisManager.AxisMinimumValue) / primaryAxisIntervalCount;
AxisManager.Calculate();
}
InternalAxisMaximum = AxisManager.AxisMaximumValue;
InternalAxisMinimum = AxisManager.AxisMinimumValue;
}
else
{
// Set the internal axis limits the one obtained from axis manager
InternalAxisMaximum = AxisManager.AxisMaximumValue;
InternalAxisMinimum = AxisManager.AxisMinimumValue;
}
InternalInterval = AxisManager.Interval;
}
///
/// Applies setting for vertical type axis
///
private void ApplyVerticalAxisSettings()
{
// Apply settings based on the axis type
switch (AxisType)
{
case AxisTypes.Primary:
ApplyVerticalPrimaryAxisSettings();
break;
case AxisTypes.Secondary:
ApplyVerticalSecondaryAxisSettings();
break;
}
}
///
/// Apply axis title properties
///
private void ApplyTitleProperties()
{
#region Apply AxisTitle Properties
AxisTitleElement.IsNotificationEnable = false;
if (this.TitleFontFamily != null)
AxisTitleElement.InternalFontFamily = this.TitleFontFamily;
if (this.TitleFontSize != 0)
AxisTitleElement.InternalFontSize = this.TitleFontSize;
if (this.TitleFontStyle != null)
AxisTitleElement.InternalFontStyle = this.TitleFontStyle;
if (this.TitleFontWeight != null)
AxisTitleElement.InternalFontWeight = this.TitleFontWeight;
if (!String.IsNullOrEmpty(this.Title) && String.IsNullOrEmpty(AxisTitleElement.Text))
AxisTitleElement.Text = GetFormattedMultilineText(this.Title);
AxisTitleElement.InternalFontColor = Visifire.Charts.Chart.CalculateFontColor((Chart as Chart), this.TitleFontColor, false);
AxisTitleElement.IsNotificationEnable = true;
#endregion
}
///
/// Create line for axis
///
/// Y1
/// Y2
/// X1
/// X2
/// Axis width
/// Axis height
private void CreateAxisLine(Double y1, Double y2, Double x1, Double x2, Double width, Double height)
{
AxisLine = new Line() { Y1 = y1, Y2 = y2, X1 = x1, X2 = x2, Width = width, Height = height };
AxisLine.StrokeThickness = LineThickness;
AxisLine.Stroke = LineColor;
AxisLine.StrokeDashArray = ExtendedGraphics.GetDashArray(LineStyle);
}
///
/// Clip vertical axis
///
/// Ticks width
private void ClipVerticalAxis(Double ticksWidth)
{
// Clip at top or bottom of the scrallable axis in order to avoid axislabel clip
if (Height != ScrollableSize)
{
// clip addition value at top or bottom of the scrallable axis in order to avoid axislabel clip
Double clipAdditionValue = 4;
PathGeometry pathGeometry = new PathGeometry();
pathGeometry.Figures = new PathFigureCollection();
PathFigure pathFigure = new PathFigure();
pathFigure.StartPoint = new Point(0, -(clipAdditionValue - 1));
pathFigure.Segments = new PathSegmentCollection();
// Do not change the order of the lines below
// Segmens required to create the rectangle
pathFigure.Segments.Add(Graphics.GetLineSegment(new Point(ScrollViewerElement.Width - ticksWidth, -(clipAdditionValue - 1))));
pathFigure.Segments.Add(Graphics.GetLineSegment(new Point(ScrollViewerElement.Width - ticksWidth, 0)));
pathFigure.Segments.Add(Graphics.GetLineSegment(new Point(ScrollViewerElement.Width, 0)));
pathFigure.Segments.Add(Graphics.GetLineSegment(new Point(ScrollViewerElement.Width, Height)));
pathFigure.Segments.Add(Graphics.GetLineSegment(new Point(ScrollViewerElement.Width - ticksWidth, Height)));
pathFigure.Segments.Add(Graphics.GetLineSegment(new Point(ScrollViewerElement.Width - ticksWidth, Height + clipAdditionValue)));
pathFigure.Segments.Add(Graphics.GetLineSegment(new Point(0, Height + clipAdditionValue)));
pathGeometry.Figures.Add(pathFigure);
ScrollViewerElement.Clip = pathGeometry;
}
}
///
/// Applies setting for primary vertical axis (Primary axis Y or Primary axis X in Bar)
///
private void ApplyVerticalPrimaryAxisSettings()
{
// Set the parameters fo the Axis Stack panel
Visual.Children.Add(new Border() { Width = this.InternalPadding.Left });
Visual.HorizontalAlignment = HorizontalAlignment.Left;
Visual.VerticalAlignment = VerticalAlignment.Stretch;
Visual.Orientation = Orientation.Horizontal;
InternalStackPanel.Width = 0;
InternalStackPanel.HorizontalAlignment = HorizontalAlignment.Left;
InternalStackPanel.VerticalAlignment = VerticalAlignment.Stretch;
ScrollViewerElement.VerticalAlignment = VerticalAlignment.Stretch;
// Set the parameters for the scroll bar
ScrollBarElement.Orientation = Orientation.Vertical;
ScrollBarElement.Width = 10;
// Set the parameters for the axis labels
AxisLabels.Placement = PlacementTypes.Left;
AxisLabels.Height = ScrollableSize;
CreateAxisLine(StartOffset, Height - EndOffset, LineThickness / 2, LineThickness / 2, LineThickness, this.Height);
// Set parameters for the Major Grids
foreach (ChartGrid grid in Grids)
grid.Placement = PlacementTypes.Left;
// Generate the visual object for the required elements
AxisLabels.CreateVisualObject();
// Set the alignement for the axis Title
AxisTitleElement.InternalHorizontalAlignment = HorizontalAlignment.Left;
AxisTitleElement.InternalVerticalAlignment = VerticalAlignment.Center;
CreateAxisTitleVisual(new Thickness(INNER_MARGIN, 0, INNER_MARGIN, 0));
// Place the visual elements in the axis stack panel
if (!String.IsNullOrEmpty(Title))
{
Visual.Children.Add(AxisTitleElement.Visual);
}
if (AxisLabels.Visual != null)
{
InternalStackPanel.Width += AxisLabels.Visual.Width;
if (Height == ScrollableSize)
{
if (AxisLabels.Visual != null)
Visual.Children.Add(AxisLabels.Visual);
}
else
{
InternalStackPanel.Children.Add(AxisLabels.Visual);
}
}
Double ticksWidth = 0;
List ticks = Ticks.Reverse().ToList();
foreach (Ticks tick in ticks)
{
tick.SetParms(PlacementTypes.Left, Double.NaN, ScrollableSize);
tick.CreateVisualObject();
if (tick.Visual != null)
{
if (Height == ScrollableSize)
Visual.Children.Add(tick.Visual);
else
{
InternalStackPanel.Children.Add(tick.Visual);
tick.Visual.SetValue(Canvas.LeftProperty, InternalStackPanel.Width + ticksWidth);
ticksWidth += tick.Visual.Width;
}
}
}
InternalStackPanel.Width += ticksWidth;
if (Height != ScrollableSize)
{
ScrollViewerElement.Children.Add(InternalStackPanel);
Visual.Children.Add(ScrollViewerElement);
}
Visual.Children.Add(AxisLine);
InternalStackPanel.Width += AxisLine.Width;
ScrollViewerElement.Width = InternalStackPanel.Width;
ClipVerticalAxis(ticksWidth);
}
///
/// Applies setting for secondary vertical axis (Secondary axis Y or Secondary axis X in Bar)
///
private void ApplyVerticalSecondaryAxisSettings()
{
// Set the parameters fo the Axis Stack panel
Visual.HorizontalAlignment = HorizontalAlignment.Right;
Visual.VerticalAlignment = VerticalAlignment.Stretch;
Visual.Orientation = Orientation.Horizontal;
InternalStackPanel.HorizontalAlignment = HorizontalAlignment.Right;
InternalStackPanel.VerticalAlignment = VerticalAlignment.Stretch;
InternalStackPanel.SizeChanged += delegate(object sender, SizeChangedEventArgs e)
{
ScrollViewerElement.Width = e.NewSize.Width;
};
ScrollViewerElement.VerticalAlignment = VerticalAlignment.Stretch;
// Set the parameters for the scroll bar
ScrollBarElement.Orientation = Orientation.Vertical;
ScrollBarElement.Width = 10;
// Set the parameters for the axis labels
AxisLabels.Placement = PlacementTypes.Right;
AxisLabels.Height = ScrollableSize;
CreateAxisLine(StartOffset, Height - EndOffset, LineThickness / 2, LineThickness / 2, LineThickness, this.Height);
// Set parameters for the Major Grids
foreach (ChartGrid grid in Grids)
grid.Placement = PlacementTypes.Right;
// Set the alignement for the axis Title
AxisTitleElement.InternalHorizontalAlignment = HorizontalAlignment.Right;
AxisTitleElement.InternalVerticalAlignment = VerticalAlignment.Center;
// Generate the visual object for the required elements
AxisLabels.CreateVisualObject();
// Place the visual elements in the axis stack panel
Visual.Children.Add(AxisLine);
foreach (Ticks tick in Ticks)
{
tick.SetParms(PlacementTypes.Right, Double.NaN, ScrollableSize);
tick.CreateVisualObject();
if (tick.Visual != null)
{
if (Height == ScrollableSize)
Visual.Children.Add(tick.Visual);
else
InternalStackPanel.Children.Add(tick.Visual);
}
}
if (Height == ScrollableSize)
{
if (AxisLabels.Visual != null)
Visual.Children.Add(AxisLabels.Visual);
}
else
{
InternalStackPanel.Children.Add(AxisLabels.Visual);
ScrollViewerElement.Children.Add(InternalStackPanel);
Visual.Children.Add(ScrollViewerElement);
}
CreateAxisTitleVisual(new Thickness(INNER_MARGIN, 0, INNER_MARGIN, 0));
if (!String.IsNullOrEmpty(Title))
{
Visual.Children.Add(AxisTitleElement.Visual);
}
Visual.Children.Add(new Border() { Width = this.InternalPadding.Right });
}
///
/// Applies setting for primary horizontal axis (Primary axis X or Primary axis Y in Bar)
///
private void ApplyHorizontalPrimaryAxisSettings()
{
// Set the parameters fo the Axis Stack panel
Visual.HorizontalAlignment = HorizontalAlignment.Stretch;
Visual.VerticalAlignment = VerticalAlignment.Bottom;
Visual.Orientation = Orientation.Vertical;
InternalStackPanel.Height = 0;
InternalStackPanel.HorizontalAlignment = HorizontalAlignment.Stretch;
InternalStackPanel.VerticalAlignment = VerticalAlignment.Bottom;
ScrollViewerElement.HorizontalAlignment = HorizontalAlignment.Stretch;
// Set the parameters for the scroll bar
ScrollBarElement.Orientation = Orientation.Horizontal;
ScrollBarElement.Height = 10;
// Set the parameters for the axis labels
AxisLabels.Placement = PlacementTypes.Bottom;
AxisLabels.Width = ScrollableSize;
CreateAxisLine(LineThickness / 2, LineThickness / 2, StartOffset, Width - EndOffset, this.Width, LineThickness);
// Set parameters for the Major Grids
foreach (ChartGrid grid in Grids)
grid.Placement = PlacementTypes.Bottom;
// Set the alignement for the axis Title
AxisTitleElement.InternalHorizontalAlignment = HorizontalAlignment.Center;
AxisTitleElement.InternalVerticalAlignment = VerticalAlignment.Bottom;
// Generate the visual object for the required elements
AxisLabels.CreateVisualObject();
// Place the visual elements in the axis stack panel
Visual.Children.Add(AxisLine);
Double ticksHeight = 0;
//AxisLabels.Visual.Background = new SolidColorBrush(Colors.Orange);
foreach (Ticks tick in Ticks)
{
tick.SetParms(PlacementTypes.Bottom, ScrollableSize, Double.NaN);
tick.CreateVisualObject();
if (tick.Visual != null)
{
if (Width == ScrollableSize)
Visual.Children.Add(tick.Visual);
else
{
InternalStackPanel.Children.Add(tick.Visual);
tick.Visual.SetValue(Canvas.TopProperty, ticksHeight);
ticksHeight += tick.Visual.Height;
}
}
}
InternalStackPanel.Height += ticksHeight;
if (Width == ScrollableSize)
{
if (AxisLabels.Visual != null)
Visual.Children.Add(AxisLabels.Visual);
}
else
{
if (AxisLabels.Visual != null)
{
InternalStackPanel.Width = AxisLabels.Visual.Width;
AxisLabels.Visual.SetValue(Canvas.TopProperty, InternalStackPanel.Height);
InternalStackPanel.Children.Add(AxisLabels.Visual);
InternalStackPanel.Height += AxisLabels.Visual.Height;
}
ScrollViewerElement.Children.Add(InternalStackPanel);
Visual.Children.Add(ScrollViewerElement);
}
ScrollViewerElement.Height = InternalStackPanel.Height;
ClipHorizontalAxis(ticksHeight);
CreateAxisTitleVisual(new Thickness(0, INNER_MARGIN, 0, INNER_MARGIN));
if (!String.IsNullOrEmpty(Title))
{
Visual.Children.Add(AxisTitleElement.Visual);
}
Visual.Children.Add(new Border() { Height = this.InternalPadding.Bottom });
}
///
/// Clip horizontal axis
///
/// Ticks height
private void ClipHorizontalAxis(Double ticksHeight)
{
// Clip at left or right the scrallable axis in order to avoid axislabel clip
if (Width != ScrollableSize)
{
// clip addition value at right or left of the scrallable axis in order to avoid axislabel clip
Double clipAdditionValue = 4;
PathGeometry pathGeometry = new PathGeometry();
pathGeometry.Figures = new PathFigureCollection();
PathFigure pathFigure = new PathFigure();
pathFigure.StartPoint = new Point(0, 0);
pathFigure.Segments = new PathSegmentCollection();
// Do not change the order of the lines below
pathFigure.Segments.Add(Graphics.GetLineSegment(new Point(Width, 0)));
pathFigure.Segments.Add(Graphics.GetLineSegment(new Point(Width, ticksHeight)));
pathFigure.Segments.Add(Graphics.GetLineSegment(new Point(Width + clipAdditionValue, ticksHeight)));
pathFigure.Segments.Add(Graphics.GetLineSegment(new Point(Width + clipAdditionValue, ScrollViewerElement.Height)));
pathFigure.Segments.Add(Graphics.GetLineSegment(new Point(-clipAdditionValue, ScrollViewerElement.Height)));
pathFigure.Segments.Add(Graphics.GetLineSegment(new Point(-clipAdditionValue, ticksHeight)));
pathFigure.Segments.Add(Graphics.GetLineSegment(new Point(0, ticksHeight)));
pathGeometry.Figures.Add(pathFigure);
ScrollViewerElement.Clip = pathGeometry;
}
}
///
/// Applies setting for secondary horizontal axis (Secondary axis X or Secondary axis Y in Bar)
///
private void ApplyHorizontalSecondaryAxisSettings()
{
// Set the parameters fo the Axis Stack panel
Visual.Children.Add(new Border() { Height = this.InternalPadding.Top });
Visual.HorizontalAlignment = HorizontalAlignment.Stretch;
Visual.VerticalAlignment = VerticalAlignment.Top;
Visual.Orientation = Orientation.Vertical;
InternalStackPanel.HorizontalAlignment = HorizontalAlignment.Stretch;
InternalStackPanel.VerticalAlignment = VerticalAlignment.Top;
InternalStackPanel.SizeChanged += delegate(object sender, SizeChangedEventArgs e)
{
ScrollViewerElement.Height = e.NewSize.Height;
};
ScrollViewerElement.HorizontalAlignment = HorizontalAlignment.Stretch;
// Set the parameters for the scroll bar
ScrollBarElement.Orientation = Orientation.Horizontal;
ScrollBarElement.Height = 10;
// Set the parameters for the axis labels
AxisLabels.Placement = PlacementTypes.Top;
AxisLabels.Width = ScrollableSize;
CreateAxisLine(LineThickness / 2, LineThickness / 2, StartOffset, Width - EndOffset, this.Width, LineThickness);
// Set parameters for the Major Grids
foreach (ChartGrid grid in Grids)
grid.Placement = PlacementTypes.Top;
// Set the alignement for the axis Title
AxisTitleElement.InternalHorizontalAlignment = HorizontalAlignment.Center;
AxisTitleElement.InternalVerticalAlignment = VerticalAlignment.Top;
AxisLabels.CreateVisualObject();
CreateAxisTitleVisual(new Thickness(0, INNER_MARGIN, 0, INNER_MARGIN));
// Place the visual elements in the axis stack panel
if (!String.IsNullOrEmpty(Title))
{
Visual.Children.Add(AxisTitleElement.Visual);
}
if (AxisLabels.Visual != null)
{
if (Width == ScrollableSize)
Visual.Children.Add(AxisLabels.Visual);
else
InternalStackPanel.Children.Add(AxisLabels.Visual);
}
List ticks = Ticks.Reverse().ToList();
foreach (Ticks tick in ticks)
{
tick.SetParms(PlacementTypes.Top, ScrollableSize, Double.NaN);
tick.CreateVisualObject();
if (tick.Visual != null)
{
if (Width == ScrollableSize)
Visual.Children.Add(tick.Visual);
else
InternalStackPanel.Children.Add(tick.Visual);
}
}
if (Width != ScrollableSize)
{
ScrollViewerElement.Children.Add(InternalStackPanel);
Visual.Children.Add(ScrollViewerElement);
}
Visual.Children.Add(AxisLine);
}
///
/// Create axis title visual
///
/// Margin between axis title and axis scale
private void CreateAxisTitleVisual(Thickness margin)
{
AxisTitleElement.InternalMargin = margin;
AxisTitleElement.IsNotificationEnable = false;
RECAL:
AxisTitleElement.CreateVisualObject(new ElementData() { Element = this });
#if WPF
AxisTitleElement.Visual.FlowDirection = FlowDirection.LeftToRight;
#endif
Size size = Graphics.CalculateVisualSize(AxisTitleElement.Visual);
if (AxisOrientation == Orientation.Horizontal)
{
if (size.Width > Width && Width != 0)
{
if (AxisTitleElement.InternalFontSize == 0.2)
goto RETURN;
AxisTitleElement.InternalFontSize -= 0.2;
goto RECAL;
}
}
else
{
if (size.Height > Height && Height != 0)
{
if (AxisTitleElement.InternalFontSize == 0.2)
goto RETURN;
AxisTitleElement.InternalFontSize -= 0.2;
goto RECAL;
}
}
RETURN:
AxisTitleElement.IsNotificationEnable = true;
}
///
/// Set the axis limits considering the width of the columns that will be drawn in the chart
///
private bool SetAxesXLimits()
{
//if (PlotDetails.DrawingDivisionFactor > 0)
{
if (!SetAxisLimitForMinimumGap())
return false;
}
MatchLeftAndRightGaps();
return true;
}
///
/// Set the limits such that the gap between plot area and the Columns will be minimum
///
private bool SetAxisLimitForMinimumGap()
{
Double minimumDifference = PlotDetails.GetMaxOfMinDifferencesForXValue();
Double minValue = minimumDifference;
if (Double.IsInfinity(minValue))
{
minValue = (AxisManager.AxisMaximumValue - AxisManager.AxisMinimumValue) * .8;
}
if (AxisMinimum != null && IsDateTimeAxis)
{
AxisMinimumNumeric = DateTimeHelper.DateDiff(AxisMinimumDateTime, MinDate, MinDateRange, MaxDateRange, InternalIntervalType, XValueType);
AxisManager.AxisMinimumValue = AxisMinimumNumeric;
AxisManager.Calculate();
}
if (AxisMaximum != null && IsDateTimeAxis)
{
AxisMaximumNumeric = DateTimeHelper.DateDiff(AxisMaximumDateTime, MinDate, MinDateRange, MaxDateRange, InternalIntervalType, XValueType);
AxisManager.AxisMaximumValue = AxisMaximumNumeric;
AxisManager.Calculate();
}
if (Double.IsNaN((Double)AxisMinimumNumeric) && !(Boolean)StartFromZero)
{
if (PlotDetails.DrawingDivisionFactor != 0)
{
AxisManager.AxisMinimumValue = AxisManager.MinimumValue - (minValue / 2 * 1.1);
}
else
{
AxisManager.AxisMinimumValue = AxisManager.MinimumValue - (minValue) / 2 * .4;
}
if (XValueType != ChartValueTypes.Numeric)
{
DateTime startDate;
Double start;
startDate = DateTimeHelper.AlignDateTime(MinDate, 1, InternalIntervalType);
start = DateTimeHelper.DateDiff(startDate, MinDate, MinDateRange, MaxDateRange, InternalIntervalType, XValueType);
if (AxisManager.AxisMinimumValue > start)
{
AxisManager.AxisMinimumValue = start;
}
else
{
Double temp = Math.Floor((start - AxisManager.AxisMinimumValue) / InternalInterval);
if (!Double.IsInfinity(temp) && temp >= 1)
start = (start - Math.Floor(temp) * InternalInterval);
}
DateTime tempFirstLabelDate = DateTimeHelper.XValueToDateTime(MinDate, start, InternalIntervalType);
FirstLabelDate = DateTimeHelper.AlignDateTime(tempFirstLabelDate, InternalInterval < 1 ? InternalInterval : 1, InternalIntervalType);
FirstLabelPosition = DateTimeHelper.DateDiff(FirstLabelDate, MinDate, MinDateRange, MaxDateRange, InternalIntervalType, XValueType);
if (AxisManager.AxisMinimumValue > FirstLabelPosition)
{
FirstLabelDate = tempFirstLabelDate;
FirstLabelPosition = DateTimeHelper.DateDiff(FirstLabelDate, MinDate, MinDateRange, MaxDateRange, InternalIntervalType, XValueType);
}
}
}
else
{
if (!Double.IsNaN(AxisMinimumNumeric))
AxisManager.AxisMinimumValue = (Double)AxisMinimumNumeric;
FirstLabelPosition = AxisManager.AxisMinimumValue;
if (XValueType != ChartValueTypes.Numeric)
FirstLabelDate = DateTimeHelper.XValueToDateTime(MinDate, AxisManager.AxisMinimumValue, InternalIntervalType);
}
if (Double.IsNaN((Double)AxisMaximumNumeric))
{
if (PlotDetails.DrawingDivisionFactor != 0 && Double.IsNaN((Double)AxisMaximumNumeric))
{
AxisManager.AxisMaximumValue = AxisManager.MaximumValue + (minValue) / 2 * 1.1;
}
else
{
AxisManager.AxisMaximumValue = AxisManager.MaximumValue + (minValue) / 2 * .4;
}
}
else
{
AxisManager.AxisMaximumValue = (Double)AxisMaximumNumeric;
}
return true;
}
internal Double FirstLabelPosition
{
get;
set;
}
internal DateTime FirstLabelDate
{
get;
set;
}
///
/// Calculate and set axis manager maximum and minimum value in order to match equal gaps at the right and left side of the chart
///
private void MatchLeftAndRightGaps()
{
Double minimumDifference = PlotDetails.GetMaxOfMinDifferencesForXValue();
if (Double.IsNaN((Double)AxisMinimumNumeric))
{
if (Double.IsNaN((Double)AxisMaximumNumeric))
{
if ((AxisManager.AxisMaximumValue - Maximum) <= (Minimum - AxisManager.AxisMinimumValue))
{
// This part makes the gaps equal
AxisManager.AxisMaximumValue = Maximum + Minimum - AxisManager.AxisMinimumValue;
}
}
else
{
AxisManager.AxisMaximumValue = (Double)AxisMaximumNumeric;
}
}
}
///
/// Convert scaling sets from string to unit and value array
///
/// ScalingSets as string
private void ParseScalingSets(String scalingSets)
{
if (String.IsNullOrEmpty(scalingSets)) return;
// scaling sets are available in the form of value,unit;value,unit;value,unit;
String[] pairs = scalingSets.Split(';');
// Since scale has to be successively multiplied initialize it to 1
Double scale = 1;
// variable to store the parsed double value
Double parsedValue;
_scaleUnits = new List();
_scaleValues = new List();
for (Int32 i = 0; i < pairs.Length; i++)
{
// split the individual pairs available in "value,unit" form
String[] sets = pairs[i].Split(',');
// if either of value or unit is missing then throw this exception
if (sets.Length != 2)
throw new Exception("Invalid scaling set parameters. should be of the form value,unit;value,unit;...");
// parse the value part of the string as double
parsedValue = Double.Parse(sets[0], CultureInfo.InvariantCulture);
// multiply the scale with the parsed value and store it
scale *= parsedValue;
_scaleValues.Add(scale);
// store the unit in the units list
_scaleUnits.Add(sets[1]);
}
}
///
/// Apply axis visual properties
///
private void ApplyVisualProperty()
{
Visual.Cursor = (Cursor == null) ? Cursors.Arrow : Cursor;
AttachHref(Chart, Visual, Href, HrefTarget);
AttachToolTip(Chart, this, Visual);
AttachEvents2Visual(this, this.Visual);
Visual.Opacity = this.InternalOpacity;
}
///
/// Calculate and return default interval for axis
///
/// Interval as Double
private Double GenerateDefaultInterval()
{
if (_isDateTimeAutoInterval ||
(XValueType != ChartValueTypes.Numeric && IntervalType != IntervalTypes.Years && Double.IsNaN((Double)Interval) && Double.IsNaN((Double)AxisLabels.Interval) && !Double.IsNaN(InternalInterval) && InternalInterval >= 1))
return InternalInterval;
if (AxisType == AxisTypes.Primary)
{
if (Double.IsNaN((Double)Interval) && Double.IsNaN((Double)AxisLabels.Interval) && PlotDetails.IsAllPrimaryAxisXLabelsPresent)
{
List uniqueXValues = (from entry in PlotDetails.AxisXPrimaryLabels orderby entry.Key select entry.Key).ToList();
if (uniqueXValues.Count > 0)
{
Double minDiff = Double.MaxValue;
for (Int32 i = 0; i < uniqueXValues.Count - 1; i++)
{
minDiff = Math.Min(minDiff, Math.Abs(uniqueXValues[i] - uniqueXValues[i + 1]));
}
if (minDiff != Double.MaxValue)
return minDiff;
}
}
}
else
{
if (Double.IsNaN((Double)Interval) && Double.IsNaN((Double)AxisLabels.Interval) && PlotDetails.IsAllSecondaryAxisXLabelsPresent)
{
List uniqueXValues = (from entry in PlotDetails.AxisXSecondaryLabels orderby entry.Key select entry.Key).ToList();
if (uniqueXValues.Count > 0)
{
Double minDiff = Double.MaxValue;
for (Int32 i = 0; i < uniqueXValues.Count - 1; i++)
{
minDiff = Math.Min(minDiff, Math.Abs(uniqueXValues[i] - uniqueXValues[i + 1]));
}
if (minDiff != Double.MaxValue)
return minDiff;
}
}
}
return (Double)Interval;
}
///
/// Event handler manages the addition and removal of ticks from axis
///
private void Ticks_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
Boolean isAutoTick = false;
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
if (e.NewItems != null)
{
foreach (Ticks tick in e.NewItems)
{
if (tick._isAutoGenerated)
isAutoTick = true;
if (Chart != null)
tick.Chart = Chart;
tick.PropertyChanged -= tick_PropertyChanged;
tick.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(tick_PropertyChanged);
}
}
}
if (!isAutoTick)
this.FirePropertyChanged("Ticks");
}
///
/// Event handler manages the addition and removal of chartgrid from axis
///
private void Grids_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
Boolean isAutoGrids = false;
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
if (e.NewItems != null)
{
foreach (ChartGrid grid in e.NewItems)
{
if (grid._isAutoGenerated)
isAutoGrids = true;
if (Chart != null)
grid.Chart = Chart;
grid.PropertyChanged -= grid_PropertyChanged;
grid.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(grid_PropertyChanged);
}
}
}
if (!isAutoGrids)
this.FirePropertyChanged("Grids");
}
///
/// Event handler attached with PropertyChanged event of chartgrids
///
/// ObservableObject
/// PropertyChangedEventArgs
private void grid_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
this.FirePropertyChanged(e.PropertyName);
}
///
/// Event handler attached with PropertyChanged event of ticks
///
/// ObservableObject
/// PropertyChangedEventArgs
private void tick_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
this.FirePropertyChanged(e.PropertyName);
}
///
/// Applies axis settings for horizontal type axis
///
private void ApplyHorizontalAxisSettings()
{
// Apply settings based on the axis type
switch (AxisType)
{
case AxisTypes.Primary:
ApplyHorizontalPrimaryAxisSettings();
break;
case AxisTypes.Secondary:
ApplyHorizontalSecondaryAxisSettings();
break;
}
}
#endregion
#region Internal Methods
///
/// Calculate total tick length from an axis
///
///
///
///
///
internal static void CalculateTotalTickLength(Chart chart, ref Double tickLengthOfAxisX, ref Double tickLengthOfPrimaryAxisY, ref Double tickLengthOfSecondaryAxisY)
{
tickLengthOfAxisX = (from tick in chart.AxesX[0].Ticks
where (Boolean)chart.AxesX[0].Enabled && (Boolean)tick.Enabled
select tick.TickLength).Sum();
if (tickLengthOfAxisX == 0)
tickLengthOfAxisX = 5;
tickLengthOfPrimaryAxisY = (from axis in chart.AxesY
where axis.AxisType == AxisTypes.Primary
from tick in axis.Ticks
where (Boolean)axis.Enabled && (Boolean)tick.Enabled
select tick.TickLength).Sum();
if (tickLengthOfPrimaryAxisY == 0)
tickLengthOfPrimaryAxisY = 8;
tickLengthOfSecondaryAxisY = (from axis in chart.AxesY
where axis.AxisType == AxisTypes.Secondary
from tick in axis.Ticks
where (Boolean)axis.Enabled && (Boolean)tick.Enabled
select tick.TickLength).Sum();
if (tickLengthOfSecondaryAxisY == 0)
tickLengthOfSecondaryAxisY = 8;
}
///
/// Converts pixel position to value
///
/// Pixel width of the scale
/// Pixel position
/// Double
internal Double PixelPositionToXValue(Double maxWidth, Double pixelPosition)
{
return Graphics.PixelPositionToValue(0, maxWidth, InternalAxisMinimum, InternalAxisMaximum, pixelPosition);
}
///
/// Converts pixel position to value
///
/// Pixel width of the scale
/// Pixel position
/// Double
internal Double PixelPositionToYValue(Double maxHeight, Double pixelPosition)
{
return Graphics.PixelPositionToValue(maxHeight, 0, InternalAxisMinimum, InternalAxisMaximum, pixelPosition);
}
///
/// Add prefix and suffix
///
///
///
internal string AddPrefixAndSuffix(String str)
{
return Prefix + str + Suffix;
}
///
/// Return formatted string from a given value depending upon scaling set and value format string
///
/// Double value
/// String
internal String GetFormattedString(Double value)
{
String str = value.ToString();
if (ScaleValues != null && ScaleUnits != null)
{
String sUnit = ScaleUnits[0];
Double sValue = ScaleValues[0];
for (Int32 i = 0; i < ScaleValues.Count; i++)
{
if ((Math.Abs(value) / ScaleValues[i]) < 1)
{
break;
}
sValue = ScaleValues[i];
sUnit = ScaleUnits[i];
}
str = (value / sValue).ToString(ValueFormatString) + sUnit;
}
else
{
str = value.ToString(ValueFormatString);
}
str = AddPrefixAndSuffix(str);
return str;
}
///
/// Associate a scrollbar with itself
///
internal void SetScrollBar()
{
if (this.AxisOrientation == Orientation.Vertical)
ScrollBarElement = (AxisType == AxisTypes.Primary) ? Chart._leftAxisScrollBar : Chart._rightAxisScrollBar;
else
ScrollBarElement = (AxisType == AxisTypes.Primary) ? Chart._bottomAxisScrollBar : Chart._topAxisScrollBar;
}
///
/// Set axis scroll value to scrollbar associated with this axis
///
/// Scrollbar offset
internal void SetScrollBarValueFromOffset(Double offset)
{
if (ScrollBarElement != null)
{
Double value = GetScrollBarValueFromOffset(offset);
ScrollBarElement.SetValue(ScrollBar.ValueProperty, value);
if (Scroll != null)
Scroll(ScrollBarElement, new ScrollEventArgs(ScrollEventType.First, value));
}
}
///
/// Get axis scroll value in pixel from scrollbar offset
///
/// Scrollbar offset
internal Double GetScrollBarValueFromOffset(Double offset)
{
if (Double.IsNaN(offset))
offset = 0;
offset = (ScrollBarElement.Maximum - ScrollBarElement.Minimum) * offset + ScrollBarElement.Minimum;
if (PlotDetails.ChartOrientation == ChartOrientationType.Horizontal)
offset = ScrollBarElement.Maximum - offset;
return offset;
}
///
/// Set up ticks for axis
///
private void SetUpTicks()
{
if (Ticks.Count == 0)
Ticks.Add(new Ticks() { _isAutoGenerated = true });
foreach (Ticks tick in Ticks)
{
tick.IsNotificationEnable = false;
if (AxisRepresentation.ToString() == "AxisX")
tick.ApplyStyleFromTheme(Chart, "AxisXTicks");
else if (AxisRepresentation.ToString() == "AxisY")
tick.ApplyStyleFromTheme(Chart, "AxisYTicks");
tick.Maximum = AxisManager.AxisMaximumValue;
tick.Minimum = AxisManager.AxisMinimumValue;
tick.DataMaximum = Maximum;
tick.DataMinimum = Minimum;
//tick.TickLength = 5;
tick.ParentAxis = this;
tick.IsNotificationEnable = true;
}
}
///
/// Set up grids for axis
///
private void SetUpGrids()
{
if (Grids.Count == 0 && AxisRepresentation.ToString() != "AxisX")
Grids.Add(new ChartGrid() { _isAutoGenerated = true });
foreach (ChartGrid grid in Grids)
{
grid.IsNotificationEnable = false;
grid.Maximum = AxisManager.AxisMaximumValue;
grid.Minimum = AxisManager.AxisMinimumValue;
grid.DataMaximum = Maximum;
grid.DataMinimum = Minimum;
grid.ParentAxis = this;
grid.IsNotificationEnable = true;
}
}
///
/// Set up axis labels for axis
///
private void SetUpAxisLabels()
{
// set the params to create Axis Labels
AxisLabels.Maximum = AxisManager.AxisMaximumValue;
AxisLabels.Minimum = AxisManager.AxisMinimumValue;
AxisLabels.DataMaximum = Maximum;
AxisLabels.DataMinimum = Minimum;
AxisLabels.ParentAxis = this;
AxisLabels.InternalRows = (Int32)AxisLabels.Rows;
//AxisLabels.Padding = this.Padding;
if (AxisRepresentation == AxisRepresentations.AxisX)
{
if (AxisType == AxisTypes.Primary)
{
AxisLabels.AxisLabelContentDictionary = PlotDetails.AxisXPrimaryLabels;
AxisLabels.AllAxisLabels = PlotDetails.IsAllPrimaryAxisXLabelsPresent;
}
else
{
AxisLabels.AxisLabelContentDictionary = PlotDetails.AxisXSecondaryLabels;
AxisLabels.AllAxisLabels = PlotDetails.IsAllSecondaryAxisXLabelsPresent;
}
}
foreach (Ticks tick in Ticks)
{
tick.IsNotificationEnable = false;
tick.AllAxisLabels = AxisLabels.AllAxisLabels;
tick.AxisLabelsDictionary = AxisLabels.AxisLabelContentDictionary;
tick.IsNotificationEnable = true;
}
}
///
/// Creates the visual element for the Axis
///
/// Chart
internal void CreateVisualObject(Chart Chart)
{
IsNotificationEnable = false;
AxisLabels.IsNotificationEnable = false;
AxisLabels.Chart = Chart;
if (AxisRepresentation == AxisRepresentations.AxisX)
AxisLabels.ApplyStyleFromTheme(Chart, "AxisXLabels");
else if (AxisRepresentation == AxisRepresentations.AxisY)
AxisLabels.ApplyStyleFromTheme(Chart, "AxisYLabels");
// Create visual elements
Visual = new StackPanel() { Background = InternalBackground };
InternalStackPanel = new Canvas();
ScrollViewerElement = new Canvas();
AxisTitleElement = new Title();
ApplyVisualProperty();
ApplyTitleProperties();
SetUpAxisManager();
SetUpTicks();
SetUpGrids();
SetUpAxisLabels();
// set the placement order based on the axis orientation
switch (AxisOrientation)
{
case Orientation.Horizontal:
ApplyHorizontalAxisSettings();
break;
case Orientation.Vertical:
ApplyVerticalAxisSettings();
break;
}
IsNotificationEnable = true;
AxisLabels.IsNotificationEnable = true;
if (!(Boolean)this.Enabled)
{
Visual.Visibility = Visibility.Collapsed;
}
}
#endregion
#region Internal Events And Delegates
///
/// Scroll event of axis
///
internal event ScrollEventHandler Scroll;
#endregion
#region Data
///
/// Value type of the AxisMinimum Property
///
internal ChartValueTypes _axisMinimumValueType;
///
/// Value type of the AxisMinimum Property
///
internal ChartValueTypes _axisMaximumValueType;
///
/// Whether ScrollBar scrolling is enabled due to change of ScrollBarOffset property
///
internal Boolean _isScrollToOffsetEnabled = true;
///
/// Whether Interval is auto-calculated for DateTime Axis
///
internal Boolean _isDateTimeAutoInterval = false;
///
/// Whether all XValues are equals to zero
///
internal Boolean _isAllXValueZero = true;
///
/// Stores the orientation (vertical or horizontal) of the axis
///
private Orientation _orientation;
///
/// Stores the units extracted from the scaling sets
///
private List _scaleUnits;
///
/// Stores the values extracted from the scaling sets
///
private List _scaleValues;
///
/// Whether user has set the axis interval or not
///
private Double _axisIntervalOverride;
///
/// Margin between axis title and axis scale
///
private const Double INNER_MARGIN = 4;
Double _internalOpacity = Double.NaN;
Brush _internalBackground = null;
Nullable _internalPadding = null;
#endregion
}
}