// (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.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Windows.Media;
using System.Windows.Shapes;
#if !DEFINITION_SERIES_COMPATIBILITY_MODE
namespace System.Windows.Controls.DataVisualization.Charting
{
///
/// Represents a control that contains a data series to be rendered in X/Y
/// line format.
///
/// Preview
[StyleTypedProperty(Property = DataPointStyleName, StyleTargetType = typeof(AreaDataPoint))]
[StyleTypedProperty(Property = "LegendItemStyle", StyleTargetType = typeof(LegendItem))]
[StyleTypedProperty(Property = "PathStyle", StyleTargetType = typeof(Path))]
[TemplatePart(Name = DataPointSeries.PlotAreaName, Type = typeof(Canvas))]
[SuppressMessage("Microsoft.Maintainability", "CA1501:AvoidExcessiveInheritance", Justification = "Depth of hierarchy is necessary to avoid code duplication.")]
public partial class AreaSeries : LineAreaBaseSeries, IAnchoredToOrigin
{
#region public Geometry Geometry
///
/// Gets the geometry property.
///
public Geometry Geometry
{
get { return GetValue(GeometryProperty) as Geometry; }
private set { SetValue(GeometryProperty, value); }
}
///
/// Identifies the Geometry dependency property.
///
public static readonly DependencyProperty GeometryProperty =
DependencyProperty.Register(
"Geometry",
typeof(Geometry),
typeof(AreaSeries),
null);
#endregion public Geometry Geometry
#region public Style PathStyle
///
/// Gets or sets the style of the Path object that follows the data
/// points.
///
public Style PathStyle
{
get { return GetValue(PathStyleProperty) as Style; }
set { SetValue(PathStyleProperty, value); }
}
///
/// Identifies the PathStyle dependency property.
///
public static readonly DependencyProperty PathStyleProperty =
DependencyProperty.Register(
"PathStyle",
typeof(Style),
typeof(AreaSeries),
null);
#endregion public Style PathStyle
#if !SILVERLIGHT
///
/// Initializes the static members of the AreaSeries class.
///
[SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline", Justification = "Dependency properties are initialized in-line.")]
static AreaSeries()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(AreaSeries), new FrameworkPropertyMetadata(typeof(AreaSeries)));
}
#endif
///
/// Initializes a new instance of the AreaSeries class.
///
public AreaSeries()
{
#if SILVERLIGHT
this.DefaultStyleKey = typeof(AreaSeries);
#endif
}
///
/// Acquire a horizontal linear axis and a vertical linear axis.
///
/// The first data point.
protected override void GetAxes(DataPoint firstDataPoint)
{
GetAxes(
firstDataPoint,
(axis) => axis.Orientation == AxisOrientation.X,
() =>
{
IAxis axis = CreateRangeAxisFromData(firstDataPoint.IndependentValue);
if (axis == null)
{
axis = new CategoryAxis();
}
axis.Orientation = AxisOrientation.X;
return axis;
},
(axis) =>
{
IRangeAxis rangeAxis = axis as IRangeAxis;
return rangeAxis != null && rangeAxis.Origin != null && axis.Orientation == AxisOrientation.Y;
},
() =>
{
DisplayAxis axis = (DisplayAxis)CreateRangeAxisFromData(firstDataPoint.DependentValue);
if (axis == null || (axis as IRangeAxis).Origin == null)
{
throw new InvalidOperationException(Properties.Resources.DataPointSeriesWithAxes_NoSuitableAxisAvailableForPlottingDependentValue);
}
axis.ShowGridLines = true;
axis.Orientation = AxisOrientation.Y;
return axis;
});
}
///
/// Updates the Series shape object from a collection of Points.
///
/// Collection of Points.
protected override void UpdateShapeFromPoints(IEnumerable points)
{
UnitValue originCoordinate = ActualDependentRangeAxis.GetPlotAreaCoordinate(ActualDependentRangeAxis.Origin);
UnitValue maximumCoordinate = ActualDependentRangeAxis.GetPlotAreaCoordinate(ActualDependentRangeAxis.Range.Maximum);
if (points.Any() && ValueHelper.CanGraph(originCoordinate.Value) && ValueHelper.CanGraph(maximumCoordinate.Value))
{
double originY = Math.Floor(originCoordinate.Value);
PathFigure figure = new PathFigure();
figure.IsClosed = true;
figure.IsFilled = true;
double maximum = maximumCoordinate.Value;
Point startPoint;
IEnumerator pointEnumerator = points.GetEnumerator();
pointEnumerator.MoveNext();
startPoint = new Point(pointEnumerator.Current.X, maximum - originY);
figure.StartPoint = startPoint;
Point lastPoint;
do
{
lastPoint = pointEnumerator.Current;
figure.Segments.Add(new LineSegment { Point = pointEnumerator.Current });
}
while (pointEnumerator.MoveNext());
figure.Segments.Add(new LineSegment { Point = new Point(lastPoint.X, maximum - originY) });
if (figure.Segments.Count > 1)
{
PathGeometry geometry = new PathGeometry();
geometry.Figures.Add(figure);
Geometry = geometry;
return;
}
}
else
{
Geometry = null;
}
}
///
/// Remove value margins from the side of the data points to ensure
/// that area chart is flush against the edge of the chart.
///
/// The value margin consumer.
/// A sequence of value margins.
protected override IEnumerable GetValueMargins(IValueMarginConsumer consumer)
{
if (consumer == ActualIndependentAxis)
{
return Enumerable.Empty();
}
return base.GetValueMargins(consumer);
}
///
/// Gets the axis to which the series is anchored.
///
IRangeAxis IAnchoredToOrigin.AnchoredAxis
{
get { return AnchoredAxis; }
}
///
/// Gets the axis to which the series is anchored.
///
protected IRangeAxis AnchoredAxis
{
get { return ActualDependentRangeAxis; }
}
}
}
#endif