// (c) Copyright Microsoft Corporation. // This source is subject to the Microsoft Public License (Ms-PL). // Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // All other rights reserved. using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Shapes; using EF = System.Windows.Controls.DataVisualization.EnumerableFunctions; namespace System.Windows.Controls.DataVisualization.Charting { /// /// An axis that displays numeric values. /// public abstract class NumericAxis : RangeAxis { #region public double? ActualMaximum /// /// Gets the actual maximum value plotted on the chart. /// public double? ActualMaximum { get { return (double?)GetValue(ActualMaximumProperty); } private set { SetValue(ActualMaximumProperty, value); } } /// /// Identifies the ActualMaximum dependency property. /// public static readonly DependencyProperty ActualMaximumProperty = DependencyProperty.Register( "ActualMaximum", typeof(double?), typeof(NumericAxis), null); #endregion public double? ActualMaximum #region public double? ActualMinimum /// /// Gets the actual maximum value plotted on the chart. /// public double? ActualMinimum { get { return (double?)GetValue(ActualMinimumProperty); } private set { SetValue(ActualMinimumProperty, value); } } /// /// Identifies the ActualMinimum dependency property. /// public static readonly DependencyProperty ActualMinimumProperty = DependencyProperty.Register( "ActualMinimum", typeof(double?), typeof(NumericAxis), null); #endregion public double? ActualMinimum #region public double? Maximum /// /// Gets or sets the maximum value plotted on the axis. /// [TypeConverter(typeof(NullableConverter))] public double? Maximum { get { return (double?)GetValue(MaximumProperty); } set { SetValue(MaximumProperty, value); } } /// /// Identifies the Maximum dependency property. /// public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register( "Maximum", typeof(double?), typeof(NumericAxis), new PropertyMetadata(null, OnMaximumPropertyChanged)); /// /// MaximumProperty property changed handler. /// /// NumericAxis that changed its Maximum. /// Event arguments. private static void OnMaximumPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { NumericAxis source = (NumericAxis)d; double? newValue = (double?)e.NewValue; source.OnMaximumPropertyChanged(newValue); } /// /// MaximumProperty property changed handler. /// /// New value. protected virtual void OnMaximumPropertyChanged(double? newValue) { this.ProtectedMaximum = newValue; } #endregion public double? Maximum #region public double? Minimum /// /// Gets or sets the minimum value to plot on the axis. /// [TypeConverter(typeof(NullableConverter))] public double? Minimum { get { return (double?)GetValue(MinimumProperty); } set { SetValue(MinimumProperty, value); } } /// /// Identifies the Minimum dependency property. /// public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register( "Minimum", typeof(double?), typeof(NumericAxis), new PropertyMetadata(null, OnMinimumPropertyChanged)); /// /// MinimumProperty property changed handler. /// /// NumericAxis that changed its Minimum. /// Event arguments. private static void OnMinimumPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { NumericAxis source = (NumericAxis)d; double? newValue = (double?)e.NewValue; source.OnMinimumPropertyChanged(newValue); } /// /// MinimumProperty property changed handler. /// /// New value. protected virtual void OnMinimumPropertyChanged(double? newValue) { this.ProtectedMinimum = newValue; } #endregion public double? Minimum #region public bool ExtendRangeToOrigin /// /// Gets or sets a value indicating whether to always show the origin. /// public bool ExtendRangeToOrigin { get { return (bool)GetValue(ExtendRangeToOriginProperty); } set { SetValue(ExtendRangeToOriginProperty, value); } } /// /// Identifies the ExtendRangeToOrigin dependency property. /// public static readonly DependencyProperty ExtendRangeToOriginProperty = DependencyProperty.Register( "ExtendRangeToOrigin", typeof(bool), typeof(NumericAxis), new PropertyMetadata(false, OnExtendRangeToOriginPropertyChanged)); /// /// ExtendRangeToOriginProperty property changed handler. /// /// NumericAxis that changed its ExtendRangeToOrigin. /// Event arguments. private static void OnExtendRangeToOriginPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { NumericAxis source = (NumericAxis)d; bool oldValue = (bool)e.OldValue; bool newValue = (bool)e.NewValue; source.OnExtendRangeToOriginPropertyChanged(oldValue, newValue); } /// /// ExtendRangeToOriginProperty property changed handler. /// /// Old value. /// New value. protected virtual void OnExtendRangeToOriginPropertyChanged(bool oldValue, bool newValue) { this.ActualRange = this.OverrideDataRange(this.ActualRange); } #endregion public bool ExtendRangeToOrigin /// /// Gets the origin value on the axis. /// protected override IComparable Origin { get { return 0.0; } } /// /// Instantiates a new instance of the NumericAxis class. /// protected NumericAxis() { } /// /// Updates the typed actual maximum and minimum properties when the /// actual range changes. /// /// The actual range. protected override void OnActualRangeChanged(Range range) { if (range.HasData) { this.ActualMaximum = (double)range.Maximum; this.ActualMinimum = (double)range.Minimum; } else { this.ActualMaximum = null; this.ActualMinimum = null; } base.OnActualRangeChanged(range); } /// /// Returns a value indicating whether a value can plot. /// /// The value to plot. /// A value indicating whether a value can plot. public override bool CanPlot(object value) { double val; return ValueHelper.TryConvert(value, out val); } /// /// Returns a numeric axis label. /// /// A numeric axis label. protected override Control CreateAxisLabel() { return new NumericAxisLabel(); } /// /// Overrides the data value range and returns a range that takes the /// margins of the values into account. /// /// The range of data values. /// A range that can store both the data values and their /// margins. protected override Range OverrideDataRange(Range range) { range = base.OverrideDataRange(range); if (ExtendRangeToOrigin) { Range adjustedRange = range.ToDoubleRange(); if (!adjustedRange.HasData) { return new Range(0.0, 0.0); } else { double minimum = adjustedRange.Minimum; double maximum = adjustedRange.Maximum; if (minimum > 0.0) { minimum = 0.0; } else if (maximum < 0.0) { maximum = 0.0; } return new Range(minimum, maximum); } } return range; } } }