// (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;
}
}
}