/* 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 } }