/*
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.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Animation;
#else
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Collections.Generic;
#endif
using System.Linq;
using Visifire.Commons;
namespace Visifire.Charts
{
///
/// Visifire.Charts.PointChart class
///
internal class PointChart
{
#region Public Methods
#endregion
#region Public Properties
#endregion
#region Public Events And Delegates
#endregion
#region Protected Methods
#endregion
#region Internal Properties
#endregion
#region Private Properties
#endregion
#region Private Delegates
#endregion
#region Private Methods
///
/// Apply animation for point chart
///
/// Point chart grid
/// Stroyboard
/// Width of the chart canvas
/// Height of the chart canvas
/// Storyboard
private static Storyboard ApplyPointChartAnimation(DataSeries currentDataSeries, Panel pointGrid, Storyboard storyboard, Double width, Double height)
{
#if WPF
if (storyboard != null && storyboard.GetValue(System.Windows.Media.Animation.Storyboard.TargetProperty) != null)
storyboard.Stop();
#else
if (storyboard != null)
storyboard.Stop();
#endif
TransformGroup group = new TransformGroup();
ScaleTransform scaleTransform = new ScaleTransform() { ScaleX = 0, ScaleY = 0, CenterX = 0.5, CenterY = 0.5 };
TranslateTransform translateTransform = new TranslateTransform() { X = 0, Y = 0 };
group.Children.Add(scaleTransform);
group.Children.Add(translateTransform);
pointGrid.RenderTransform = group;
Random rand = new Random((Int32)DateTime.Now.Ticks);
double begin = rand.NextDouble();
pointGrid.Measure(new Size(Double.MaxValue, Double.MaxValue));
DoubleCollection times = Graphics.GenerateDoubleCollection(0, 0.5, 0.75, 1);
DoubleCollection scaleValues = Graphics.GenerateDoubleCollection(0, 1, 0.5, 1);
DoubleCollection translateXValues = Graphics.GenerateDoubleCollection(pointGrid.DesiredSize.Width / 2, 0, pointGrid.DesiredSize.Width / 4, 0);
DoubleCollection translateYValues = Graphics.GenerateDoubleCollection(pointGrid.DesiredSize.Height / 2, 0, pointGrid.DesiredSize.Height / 4, 0);
List splines1 = AnimationHelper.GenerateKeySplineList(new Point(0, 0.5), new Point(0.5, 1), new Point(0, 0.5), new Point(0.5, 1), new Point(0, 0.5), new Point(0.5, 1), new Point(0, 0.5), new Point(0.5, 1));
List splines2 = AnimationHelper.GenerateKeySplineList(new Point(0, 0.5), new Point(0.5, 1), new Point(0, 0.5), new Point(0.5, 1), new Point(0, 0.5), new Point(0.5, 1), new Point(0, 0.5), new Point(0.5, 1));
List splines3 = AnimationHelper.GenerateKeySplineList(new Point(0, 0.5), new Point(0.5, 1), new Point(0, 0.5), new Point(0.5, 1), new Point(0, 0.5), new Point(0.5, 1), new Point(0, 0.5), new Point(0.5, 1));
List splines4 = AnimationHelper.GenerateKeySplineList(new Point(0, 0.5), new Point(0.5, 1), new Point(0, 0.5), new Point(0.5, 1), new Point(0, 0.5), new Point(0.5, 1), new Point(0, 0.5), new Point(0.5, 1));
DoubleAnimationUsingKeyFrames xScaleAnimation = AnimationHelper.CreateDoubleAnimation(currentDataSeries, scaleTransform, "(ScaleTransform.ScaleX)", begin + 0.5, times, scaleValues, splines1);
DoubleAnimationUsingKeyFrames yScaleAnimation = AnimationHelper.CreateDoubleAnimation(currentDataSeries, scaleTransform, "(ScaleTransform.ScaleY)", begin + 0.5, times, scaleValues, splines2);
DoubleAnimationUsingKeyFrames xTranslateAnimation = AnimationHelper.CreateDoubleAnimation(currentDataSeries, translateTransform, "(TranslateTransform.X)", begin + 0.5, times, translateXValues, splines3);
DoubleAnimationUsingKeyFrames yTranslateAnimation = AnimationHelper.CreateDoubleAnimation(currentDataSeries, translateTransform, "(TranslateTransform.Y)", begin + 0.5, times, translateYValues, splines4);
storyboard.Children.Add(xScaleAnimation);
storyboard.Children.Add(yScaleAnimation);
storyboard.Children.Add(xTranslateAnimation);
storyboard.Children.Add(yTranslateAnimation);
return storyboard;
}
#endregion
#region Internal Methods
///
/// Get visual object for point chart
///
/// Width of the charat
/// Height of the charat
/// plotDetails
/// List of DataSeries
/// Chart
/// Plank depth
/// Whether animation is enabled
/// Point chart canvas
internal static Canvas GetVisualObjectForPointChart(Double width, Double height, PlotDetails plotDetails, List seriesList, Chart chart, Double plankDepth, bool animationEnabled)
{
if (Double.IsNaN(width) || Double.IsNaN(height) || width <= 0 || height <= 0) return null;
DataSeries currentDataSeries = null;
Canvas visual = new Canvas() { Width = width, Height = height };
Double depth3d = plankDepth / (plotDetails.Layer3DCount == 0 ? 1 : plotDetails.Layer3DCount) * (chart.View3D ? 1 : 0);
Double visualOffset = depth3d * (plotDetails.SeriesDrawingIndex[seriesList[0]] + 1 - (plotDetails.Layer3DCount == 0 ? 0 : 1));
visual.SetValue(Canvas.TopProperty, visualOffset);
visual.SetValue(Canvas.LeftProperty, -visualOffset);
foreach (DataSeries series in seriesList)
{
if (series.Enabled == false)
continue;
PlotGroup plotGroup = series.PlotGroup;
foreach (DataPoint dataPoint in series.InternalDataPoints)
{
if (Double.IsNaN(dataPoint.InternalYValue) || (dataPoint.Enabled == false))
{
continue;
}
Double xPosition = Graphics.ValueToPixelPosition(0, width, (Double)plotGroup.AxisX.InternalAxisMinimum, (Double)plotGroup.AxisX.InternalAxisMaximum, dataPoint.InternalXValue);
Double yPosition = Graphics.ValueToPixelPosition(height, 0, (Double)plotGroup.AxisY.InternalAxisMinimum, (Double)plotGroup.AxisY.InternalAxisMaximum, dataPoint.InternalYValue);
Brush markerColor = dataPoint.Color;
markerColor = (chart.View3D ? Graphics.GetLightingEnabledBrush3D(markerColor) :
((Boolean)dataPoint.LightingEnabled ? Graphics.GetLightingEnabledBrush(markerColor, "Linear", null) : markerColor));
Size markerSize = new Size((Double)dataPoint.MarkerSize, (Double)dataPoint.MarkerSize);
Boolean markerBevel = false;
String labelText = (Boolean)dataPoint.LabelEnabled ? dataPoint.TextParser(dataPoint.LabelText) : "";
Marker marker = new Marker((MarkerTypes)dataPoint.MarkerType, (Double)dataPoint.MarkerScale, markerSize, markerBevel, markerColor, labelText);
marker.Tag = new ElementData() { Element = dataPoint };
marker.ShadowEnabled = dataPoint.Parent.ShadowEnabled;
marker.MarkerSize = new Size((Double)dataPoint.MarkerSize, (Double)dataPoint.MarkerSize);
if (marker.MarkerType != MarkerTypes.Cross)
{
if (dataPoint.BorderColor != null)
marker.BorderColor = dataPoint.BorderColor;
}
else
marker.BorderColor = markerColor;
marker.BorderThickness = ((Thickness)dataPoint.MarkerBorderThickness).Left;
if (!String.IsNullOrEmpty(labelText))
{
marker.FontColor = Chart.CalculateDataPointLabelFontColor(chart, dataPoint, dataPoint.LabelFontColor, LabelStyles.OutSide);
marker.FontSize = (Double)dataPoint.LabelFontSize;
marker.FontWeight = (FontWeight)dataPoint.LabelFontWeight;
marker.FontFamily = dataPoint.LabelFontFamily;
marker.FontStyle = (FontStyle)dataPoint.LabelFontStyle;
marker.TextBackground = dataPoint.LabelBackground;
marker.TextAlignmentX = AlignmentX.Center;
marker.TextAlignmentY = AlignmentY.Center;
if (!Double.IsNaN(dataPoint.LabelAngle) && dataPoint.LabelAngle != 0)
{
marker.LabelAngle = dataPoint.LabelAngle;
marker.TextOrientation = Orientation.Vertical;
marker.TextAlignmentX = AlignmentX.Center;
marker.TextAlignmentY = AlignmentY.Center;
marker.LabelStyle = (LabelStyles)dataPoint.LabelStyle;
}
marker.CreateVisual();
if (Double.IsNaN(dataPoint.LabelAngle) || dataPoint.LabelAngle == 0)
{
if ((yPosition - marker.TextBlockSize.Height / 2) < 0)
marker.TextAlignmentY = AlignmentY.Bottom;
else if ((yPosition + marker.TextBlockSize.Height / 2) > height)
marker.TextAlignmentY = AlignmentY.Top;
if ((xPosition - marker.TextBlockSize.Width / 2) < 0)
marker.TextAlignmentX = AlignmentX.Right;
else if ((xPosition + marker.TextBlockSize.Width / 2) > width)
marker.TextAlignmentX = AlignmentX.Left;
}
}
marker.CreateVisual();
marker.Visual.Opacity = dataPoint.InternalOpacity * dataPoint.Parent.InternalOpacity;
marker.AddToParent(visual, xPosition, yPosition, new Point(0.5, 0.5));
// Apply animation
if (animationEnabled)
{
if (dataPoint.Parent.Storyboard == null)
dataPoint.Parent.Storyboard = new Storyboard();
currentDataSeries = dataPoint.Parent;
// Apply animation to the points
dataPoint.Parent.Storyboard = ApplyPointChartAnimation(currentDataSeries, marker.Visual, dataPoint.Parent.Storyboard, width, height);
}
Faces point = new Faces();
point.VisualComponents.Add(marker.Visual);
point.Visual = marker.Visual;
point.BorderElements.Add(marker.MarkerShape);
dataPoint.Marker = marker;
dataPoint.Faces = point;
}
}
Double 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;
Double 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;
Double 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;
Double plotGroupCount = (from c in chart.PlotDetails.PlotGroups
where c.AxisY.AxisType == AxisTypes.Secondary
select c).Count();
RectangleGeometry clipRectangle = new RectangleGeometry();
clipRectangle.Rect = new Rect(-tickLengthOfPrimaryAxisY, -chart.ChartArea.PLANK_DEPTH, width + tickLengthOfSecondaryAxisY + (plotGroupCount > 0 ? tickLengthOfPrimaryAxisY : 8) + chart.ChartArea.PLANK_OFFSET, height + chart.ChartArea.PLANK_DEPTH + tickLengthOfAxisX);
visual.Clip = clipRectangle;
return visual;
}
#endregion
#region Internal Events And Delegates
#endregion
#region Data
#endregion
}
}