/*
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.Windows;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Markup;
using System.IO;
using System.Xml;
using System.Threading;
using System.Collections.ObjectModel;
#else
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Collections.ObjectModel;
#endif
using Visifire.Commons;
using System.Windows.Controls.Primitives;
namespace Visifire.Charts
{
///
/// Partially extended chart control class
///
public partial class Chart : VisifireControl
{
#region Public Methods
///
/// Load controls from template
///
private void LoadControlsFromTemplate()
{
_rootElement = GetTemplateChild(RootElementName) as Grid;
_shadowGrid = GetTemplateChild(ShadowGridName) as Grid;
_chartBorder = GetTemplateChild(ChartBorderName) as Border;
_chartLightingBorder = GetTemplateChild(ChartLightingBorderName) as Rectangle;
_bevelCanvas = GetTemplateChild(BevelCanvasName) as Canvas;
_chartAreaGrid = GetTemplateChild(ChartAreaGridName) as Grid;
_topOuterPanel = GetTemplateChild(TopOuterPanelName) as StackPanel;
_topOuterTitlePanel = GetTemplateChild(TopOuterTitlePanelName) as StackPanel;
_topOuterLegendPanel = GetTemplateChild(TopOuterLegendPanelName) as StackPanel;
_bottomOuterPanel = GetTemplateChild(BottomOuterPanelName) as StackPanel;
_bottomOuterLegendPanel = GetTemplateChild(BottomOuterLegendPanelName) as StackPanel;
_bottomOuterTitlePanel = GetTemplateChild(BottomOuterTitlePanelName) as StackPanel;
_leftOuterPanel = GetTemplateChild(LeftOuterPanelName) as StackPanel;
_leftOuterTitlePanel = GetTemplateChild(LeftOuterTitlePanelName) as StackPanel;
_leftOuterLegendPanel = GetTemplateChild(LeftOuterLegendPanelName) as StackPanel;
_rightOuterPanel = GetTemplateChild(RightOuterPanelName) as StackPanel;
_rightOuterLegendPanel = GetTemplateChild(RightOuterLegendPanelName) as StackPanel;
_rightOuterTitlePanel = GetTemplateChild(RightOuterTitlePanelName) as StackPanel;
_centerGrid = GetTemplateChild(CenterGridName) as Grid;
_centerOuterGrid = GetTemplateChild(CenterOuterGridName) as Grid;
_topOffsetGrid = GetTemplateChild(TopOffsetGridName) as Grid;
_bottomOffsetGrid = GetTemplateChild(BottomOffsetGridName) as Grid;
_leftOffsetGrid = GetTemplateChild(LeftOffsetGridName) as Grid;
_rightOffsetGrid = GetTemplateChild(RightOffsetGridName) as Grid;
_topAxisGrid = GetTemplateChild(TopAxisGridName) as Grid;
_topAxisContainer = GetTemplateChild(TopAxisContainerName) as StackPanel;
_topAxisPanel = GetTemplateChild(TopAxisPanelName) as StackPanel;
_topAxisScrollBar = GetTemplateChild(TopAxisScrollBarName) as ScrollBar;
_leftAxisGrid = GetTemplateChild(LeftAxisGridName) as Grid;
_leftAxisContainer = GetTemplateChild(LeftAxisContainerName) as StackPanel;
_leftAxisPanel = GetTemplateChild(LeftAxisPanelName) as StackPanel;
_leftAxisScrollBar = GetTemplateChild(LeftAxisScrollBarName) as ScrollBar;
_rightAxisGrid = GetTemplateChild(RightAxisGridName) as Grid;
_rightAxisContainer = GetTemplateChild(RightAxisContainerName) as StackPanel;
_rightAxisScrollBar = GetTemplateChild(RightAxisScrollBarName) as ScrollBar;
_rightAxisPanel = GetTemplateChild(RightAxisPanelName) as StackPanel;
_bottomAxisGrid = GetTemplateChild(BottomAxisGridName) as Grid;
_bottomAxisContainer = GetTemplateChild(BottomAxisContainerName) as StackPanel;
_bottomAxisScrollBar = GetTemplateChild(BottomAxisScrollBarName) as ScrollBar;
_bottomAxisPanel = GetTemplateChild(BottomAxisPanelName) as StackPanel;
_centerInnerGrid = GetTemplateChild(CenterInnerGridName) as Grid;
_innerGrid = GetTemplateChild(InnerGridName) as Grid;
_topInnerPanel = GetTemplateChild(TopInnerPanelName) as StackPanel;
_topInnerTitlePanel = GetTemplateChild(TopInnerTitlePanelName) as StackPanel;
_topInnerLegendPanel = GetTemplateChild(TopInnerLegendPanelName) as StackPanel;
_bottomInnerPanel = GetTemplateChild(BottomInnerPanelName) as StackPanel;
_bottomInnerLegendPanel = GetTemplateChild(BottomInnerLegendPanelName) as StackPanel;
_bottomInnerTitlePanel = GetTemplateChild(BottomInnerTitlePanelName) as StackPanel;
_leftInnerPanel = GetTemplateChild(LeftInnerPanelName) as StackPanel;
_leftInnerTitlePanel = GetTemplateChild(LeftInnerTitlePanelName) as StackPanel;
_leftInnerLegendPanel = GetTemplateChild(LeftInnerLegendPanelName) as StackPanel;
_rightInnerPanel = GetTemplateChild(RightInnerPanelName) as StackPanel;
_rightInnerLegendPanel = GetTemplateChild(RightInnerLegendPanelName) as StackPanel;
_rightInnerTitlePanel = GetTemplateChild(RightInnerTitlePanelName) as StackPanel;
_plotAreaGrid = GetTemplateChild(PlotAreaGridName) as Grid;
_plotAreaScrollViewer = GetTemplateChild(PlotAreaScrollViewerName) as ScrollViewer;
_plotCanvas = GetTemplateChild(PlotGridName) as Canvas;
_plotAreaShadowCanvas = GetTemplateChild(PlotAreaShadowCanvasName) as Canvas;
_drawingCanvas = GetTemplateChild(DrawingCanvasName) as Canvas;
_centerDockInsidePlotAreaPanel = GetTemplateChild(CenterDockInsidePlotAreaPanelName) as StackPanel;
_centerDockOutsidePlotAreaPanel = GetTemplateChild(CenterDockOutsidePlotAreaPanelName) as StackPanel;
_toolTipCanvas = GetTemplateChild(ToolTipCanvasName) as Canvas;
}
///
/// Set Margin for various elements to maintain effects like Shadow and Bevel
///
public void SetMarginOfElements()
{
if (ShadowEnabled)
{
_chartBorder.Margin = new Thickness(0, 0, SHADOW_DEPTH, SHADOW_DEPTH);
_bevelCanvas.Margin = new Thickness(0, 0, SHADOW_DEPTH, SHADOW_DEPTH);
}
_chartAreaMargin = new Thickness(_chartAreaGrid.Margin.Left, _chartAreaGrid.Margin.Top, _chartAreaGrid.Margin.Right, _chartAreaGrid.Margin.Bottom);
if (Bevel)
{
_chartAreaGrid.Margin = new Thickness(
_chartAreaMargin.Left + BEVEL_DEPTH,
_chartAreaMargin.Top + BEVEL_DEPTH,
_chartAreaMargin.Right + BEVEL_DEPTH,
_chartAreaMargin.Bottom + BEVEL_DEPTH);
}
}
///
/// OnApplyTemplate() function is invoked whenever application code
/// or internal processes such as a rebuilding layout pass.
///
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
LoadControlsFromTemplate();
LoadWatermark();
if (StyleDictionary == null)
LoadTheme("Theme1", false);
LoadOrUpdateColorSets();
LoadToolTips();
SetMarginOfElements();
ApplyLighting();
AttachToolTipAndEvents();
BindProperties();
_internalAnimationEnabled = AnimationEnabled;
if (_internalAnimationEnabled)
_rootElement.IsHitTestVisible = false;
_isTemplateApplied = true;
#if WPF
NameScope.SetNameScope(this._rootElement, new NameScope());
#endif
}
#endregion
#region Public Properties
///
/// Identifies the Visifire.Charts.Chart.SmartLabelEnabled dependency property.
///
public static readonly DependencyProperty SmartLabelEnabledProperty =
DependencyProperty.Register("SmartLabelEnabled",
typeof(Boolean),
typeof(Chart),
new PropertyMetadata(OnSmartLabelEnabledPropertyChanged));
///
/// Identifies the Visifire.Charts.Chart.DataPointWidth dependency property.
///
public static readonly DependencyProperty DataPointWidthProperty =
DependencyProperty.Register("DataPointWidth",
typeof(Double),
typeof(Chart),
new PropertyMetadata(Double.NaN, OnDataPointWidthPropertyChanged));
///
/// Identifies the Visifire.Charts.Chart.UniqueColors dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.UniqueColors dependency property.
///
public static readonly DependencyProperty UniqueColorsProperty = DependencyProperty.Register
("UniqueColors",
typeof(Boolean),
typeof(Chart),
new PropertyMetadata(true, OnUniqueColorsPropertyChanged));
///
/// Identifies the Visifire.Charts.Chart.ScrollingEnabled dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.ScrollingEnabled dependency property.
///
public static readonly DependencyProperty ScrollingEnabledProperty = DependencyProperty.Register
("ScrollingEnabled",
typeof(Nullable),
typeof(Chart),
new PropertyMetadata(OnScrollingEnabledPropertyChanged));
///
/// Identifies the Visifire.Charts.Chart.View3D dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.View3D dependency property.
///
public static readonly DependencyProperty View3DProperty = DependencyProperty.Register
("View3D",
typeof(Boolean),
typeof(Chart),
new PropertyMetadata(OnView3DPropertyChanged));
///
/// Identifies the Visifire.Charts.Chart.HrefTarget dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.HrefTarget dependency property.
///
public static readonly DependencyProperty HrefTargetProperty = DependencyProperty.Register
("HrefTarget",
typeof(HrefTargets),
typeof(Chart),
new PropertyMetadata(OnHrefTargetChanged));
///
/// Identifies the Visifire.Charts.Chart.Href dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.Href dependency property.
///
public static readonly DependencyProperty HrefProperty = DependencyProperty.Register
("Href",
typeof(String),
typeof(Chart),
new PropertyMetadata(OnHrefChanged));
///
/// Identifies the Visifire.Charts.Chart.Theme dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.Theme dependency property.
///
public static readonly DependencyProperty ThemeProperty = DependencyProperty.Register
("Theme",
typeof(String),
typeof(Chart),
new PropertyMetadata(OnThemePropertyChanged));
///
/// Identifies the Visifire.Charts.Chart.AnimationEnabled dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.AnimationEnabled dependency property.
///
public static readonly DependencyProperty AnimationEnabledProperty = DependencyProperty.Register
("AnimationEnabled",
typeof(Boolean),
typeof(Chart),
null);
///
/// Identifies the Visifire.Charts.Chart.InternalBorderThickness dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.InternalBorderThickness dependency property.
///
private static readonly DependencyProperty InternalBorderThicknessProperty = DependencyProperty.Register
("InternalBorderThickness",
typeof(Thickness),
typeof(Chart),
new PropertyMetadata(OnInternalBorderThicknessChanged));
///
/// Identifies the Visifire.Charts.Chart.InternalBackground dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.InternalBackground dependency property.
///
private static readonly DependencyProperty InternalBackgroundProperty = DependencyProperty.Register
("InternalBackground",
typeof(Brush),
typeof(Chart),
new PropertyMetadata(OnInternalBackgroundPropertyChanged));
///
/// Identifies the Visifire.Charts.Chart.Bevel dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.Bevel dependency property.
///
public static readonly DependencyProperty BevelProperty = DependencyProperty.Register
("Bevel",
typeof(Boolean),
typeof(Chart),
new PropertyMetadata(OnBevelPropertyChanged));
///
/// Identifies the Visifire.Charts.Chart.ColorSet dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.ColorSet dependency property.
///
public static readonly DependencyProperty ColorSetProperty = DependencyProperty.Register
("ColorSet",
typeof(String),
typeof(Chart),
new PropertyMetadata(OnColorSetPropertyChanged));
///
/// Identifies the Visifire.Charts.Chart.ColorSets dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.ColorSets dependency property.
///
public static readonly DependencyProperty ColorSetsProperty = DependencyProperty.Register
("ColorSets",
typeof(ColorSets),
typeof(Chart),
new PropertyMetadata(new ColorSets(), null));
///
/// Identifies the Visifire.Charts.Chart.LightingEnabled dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.LightingEnabled dependency property.
///
public static readonly DependencyProperty LightingEnabledProperty = DependencyProperty.Register
("LightingEnabled",
typeof(Boolean),
typeof(Chart),
new PropertyMetadata(OnLightingEnabledPropertyChanged));
///
/// Identifies the Visifire.Charts.Chart.CornerRadius dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.CornerRadius dependency property.
///
public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register
("CornerRadius",
typeof(CornerRadius),
typeof(Chart),
null);
///
/// Identifies the Visifire.Charts.Chart.ShadowEnabled dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.ShadowEnabled dependency property.
///
public static readonly DependencyProperty ShadowEnabledProperty = DependencyProperty.Register
("ShadowEnabled",
typeof(Boolean),
typeof(Chart),
new PropertyMetadata(OnShadowEnabledPropertyChanged));
///
/// Identifies the Visifire.Charts.Chart.Watermark dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.Watermark dependency property.
///
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register
("Watermark",
typeof(Boolean),
typeof(Chart),
new PropertyMetadata(true, OnWatermarkPropertyChanged));
///
/// Identifies the Visifire.Charts.Chart.PlotArea dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.PlotArea dependency property.
///
public static readonly DependencyProperty PlotAreaProperty = DependencyProperty.Register
("PlotArea",
typeof(PlotArea),
typeof(Chart),
new PropertyMetadata(OnPlotAreaPropertyChanged));
///
/// Identifies the Visifire.Charts.Chart.MinScrollingGap dependency property.
///
///
/// The identifier for the Visifire.Charts.Chart.MinScrollingGap dependency property.
///
[Obsolete]
public static readonly DependencyProperty MinimumGapProperty = DependencyProperty.Register
("MinimumGap",
typeof(Nullable),
typeof(Chart),
new PropertyMetadata(OnMinimumGapPropertyChanged));
///
/// Decides how the color will be applied to the DataPoints.
/// If UniqueColors = True and if only one DataSeries is present in Chart then each DataPoint in that DataSeries takes one color from the ColorSet given to the chart.
/// If UniqueColors = True and if more than one DataSeries are present in Chart then each series takes one color from the ColorSet provided at the chart.
/// If UniqueColors = False then each DataSeries takes one color
///
///
public Boolean UniqueColors
{
get
{
return (Boolean)GetValue(UniqueColorsProperty);
}
set
{
SetValue(UniqueColorsProperty, value);
}
}
///
/// Whether skipping of labels are allowed
/// Note: Currently implemented for Pie and Doughnut charts only
///
public Boolean SmartLabelEnabled
{
get { return (Boolean)GetValue(SmartLabelEnabledProperty); }
set { SetValue(SmartLabelEnabledProperty, value); }
}
///
/// Width of a DataPoint
///
public Double DataPointWidth
{
get { return (Double)GetValue(DataPointWidthProperty); }
set { SetValue(DataPointWidthProperty, value); }
}
///
/// Minimum gap between two DataPoint of same series in PlotArea
///
#if SL
[System.ComponentModel.TypeConverter(typeof(Converters.NullableDoubleConverter))]
#endif
[Obsolete]
public Nullable MinimumGap
{
get
{
return (Nullable)GetValue(MinimumGapProperty);
}
set
{
SetValue(MinimumGapProperty, value);
}
}
///
/// Enable or disable 3D effect
///
#if SL
[System.ComponentModel.TypeConverter(typeof(NullableBoolConverter))]
#endif
public Nullable ScrollingEnabled
{
set
{
SetValue(ScrollingEnabledProperty, value);
}
get
{
if ((Nullable)GetValue(ScrollingEnabledProperty) == null)
{
return true;
}
else
return (Nullable)GetValue(ScrollingEnabledProperty);
}
}
///
/// Enable or disable 3D effect
///
public Boolean View3D
{
set
{
SetValue(View3DProperty, value);
}
get
{
return (Boolean)GetValue(View3DProperty);
}
}
///
/// Target window Property for hyperlink
///
public HrefTargets HrefTarget
{
get
{
return (HrefTargets)GetValue(HrefTargetProperty);
}
set
{
SetValue(HrefTargetProperty, value);
}
}
///
/// Hyperlink Property
///
public String Href
{
get
{
return (String)GetValue(HrefProperty);
}
set
{
SetValue(HrefProperty, value);
}
}
///
/// Name of the theme to be applied
///
public String Theme
{
get
{
return (String)GetValue(ThemeProperty);
}
set
{
SetValue(ThemeProperty, value);
}
}
///
/// Enables or disables animation
///
public Boolean AnimationEnabled
{
get
{
if (!IsInDesignMode)
{
if (String.IsNullOrEmpty(AnimationEnabledProperty.ToString()))
{
return false;
}
else
return (Boolean)GetValue(AnimationEnabledProperty);
}
else
return false;
}
set
{
SetValue(AnimationEnabledProperty, value);
}
}
#region BorderProperties
///
/// BorderThickness property
///
public new Thickness BorderThickness
{
get
{
return (Thickness)GetValue(BorderThicknessProperty);
}
set
{
SetValue(BorderThicknessProperty, value);
SetValue(InternalBorderThicknessProperty, value);
}
}
#endregion
///
/// Background color property
///
public new Brush Background
{
get
{
return (Brush)GetValue(BackgroundProperty);
}
set
{
SetValue(BackgroundProperty, value);
SetValue(InternalBackgroundProperty, value);
}
}
///
/// Enabled or disables the bevel effect
///
public Boolean Bevel
{
get
{
return (Boolean)GetValue(BevelProperty);
}
set
{
SetValue(BevelProperty, value);
}
}
///
/// Set of colors that will be used for the InternalDataPoints
///
public String ColorSet
{
get
{
return (String)GetValue(ColorSetProperty);
}
set
{
SetValue(ColorSetProperty, value);
}
}
///
/// Set of colors that will be used for the InternalDataPoints
///
public ColorSets ColorSets
{
get
{
return (ColorSets)GetValue(ColorSetsProperty);
}
set
{
SetValue(ColorSetsProperty, value);
}
}
///
/// Enables or disables automatic color shading
///
public Boolean LightingEnabled
{
get
{
return (Boolean)GetValue(LightingEnabledProperty);
}
set
{
SetValue(LightingEnabledProperty, value);
}
}
///
/// Sets the parameter used to create rounded or elliptical corners of the element
///
#if WPF
[System.ComponentModel.TypeConverter(typeof(System.Windows.CornerRadiusConverter))]
#else
[System.ComponentModel.TypeConverter(typeof(Converters.CornerRadiusConverter))]
#endif
public CornerRadius CornerRadius
{
get
{
return (CornerRadius)GetValue(CornerRadiusProperty);
}
set
{
SetValue(CornerRadiusProperty, value);
}
}
///
/// Enables or disables the shadow for the element
///
public Boolean ShadowEnabled
{
get
{
return (Boolean)GetValue(ShadowEnabledProperty);
}
set
{
SetValue(ShadowEnabledProperty, value);
}
}
///
/// Enables or disables the "Powered by Visifire" watermark
///
public Boolean Watermark
{
get
{
return (Boolean)GetValue(WatermarkProperty);
}
set
{
SetValue(WatermarkProperty, value);
}
}
///
/// PlotArea of the chart
///
public PlotArea PlotArea
{
get
{
return (PlotArea)GetValue(PlotAreaProperty);
}
set
{
SetValue(PlotAreaProperty, value);
PlotArea.Chart = this;
PlotArea.PropertyChanged -= Element_PropertyChanged;
PlotArea.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(Element_PropertyChanged);
}
}
///
/// AxesX as AxisCollection of type Axis
///
public AxisCollection AxesX
{
get;
set;
}
///
/// AxesY as AxisCollection of type Axis
///
public AxisCollection AxesY
{
get;
set;
}
///
/// Titles as TitleCollection of type Title
///
public TitleCollection Titles
{
get;
set;
}
///
/// Legends as LegendCollection of type Legend
///
public LegendCollection Legends
{
get;
set;
}
///
/// ToolTips as ToolTipCollection of type ToolTip
///
public ToolTipCollection ToolTips
{
get;
set;
}
///
/// TrendLines as TrendLineCollection of type TrendLine
///
public TrendLineCollection TrendLines
{
get;
set;
}
///
/// Collection of DataSeries
///
public DataSeriesCollection Series
{
get;
set;
}
#endregion
#region Public Events
///
/// Event handler for the Rendered event
///
public event EventHandler Rendered
{
remove
{
_rendered -= value;
}
add
{
_rendered += value;
}
}
#endregion
#region Protected Methods
#endregion
#region Private Delegates
#endregion
#region Private Methods
///
/// Initializes the various properties of the class
///
private void Init()
{
// Initialize colorSets
//ColorSets = new ColorSets();
// Initialize tooltip
ToolTips = new ToolTipCollection();
// Initialize title list
Titles = new TitleCollection();
// Initialize legend list
Legends = new LegendCollection();
// Initialize trendLine list
TrendLines = new TrendLineCollection();
// Initialize AxesX list
AxesX = new AxisCollection();
// Initialize AxesY list
AxesY = new AxisCollection();
// Initialize Series list
Series = new DataSeriesCollection();
// Initialize PlotArea
PlotArea = new PlotArea() { Chart = this };
// Attach event handler on collection changed event with ToolTip collection
ToolTips.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(ToolTips_CollectionChanged);
// Attach event handler on collection changed event with Title collection
Titles.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Titles_CollectionChanged);
// Attach event handler on collection changed event with Legend collection
Legends.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Legends_CollectionChanged);
// Attach event handler on collection changed event with TrendLines collection
TrendLines.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(TrendLines_CollectionChanged);
// Attach event handler on collection changed event with DataSeries collection
Series.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Series_CollectionChanged);
// Attach event handler on collection changed event with axisX collection
(AxesX as AxisCollection).CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(AxesX_CollectionChanged);
// Attach event handler on collection changed event with AxisY collection
(AxesY as AxisCollection).CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(AxesY_CollectionChanged);
}
///
/// OnMouseMoveLeave chart set ToolTip position.
/// ToolTip at current mouse position over the chart control
///
/// Chart as object
/// MouseEventArgs
private void Chart_MouseLeave(object sender, MouseEventArgs e)
{
if (ToolTipEnabled)
{
if (_toolTip.Visibility == Visibility.Visible)
_toolTip.Hide();
}
else
{
_toolTip.Hide();
}
_toolTip.Text = "";
}
///
/// OnMouseMoveOver chart set ToolTip position.
/// ToolTip at current mouse position over the chart control
///
/// Chart as object
/// MouseEventArgs
private void Chart_MouseMove(object sender, MouseEventArgs e)
{
UpdateToolTipPosition(sender, e);
}
///
/// Event handler manages the addition and removal of tooltip from tooltip list of chart
///
/// ToolTips
/// NotifyCollectionChangedEventArgs
private void ToolTips_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
if (e.NewItems != null)
{
foreach (ToolTip toolTip in e.NewItems)
{
if (toolTip.Style == null && StyleDictionary != null)
{
Style myStyle = StyleDictionary["ToolTip"] as Style;
if (myStyle != null)
toolTip.Style = myStyle;
}
toolTip.Chart = this;
}
}
}
else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
{
foreach (ToolTip toolTip in e.OldItems)
(toolTip.Chart as Chart)._toolTipCanvas.Children.Remove(toolTip);
}
}
///
/// Event handler manages the addition and removal of Axis from AxesX list of chart
///
/// AxesX
/// NotifyCollectionChangedEventArgs
private void AxesX_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
Boolean isAutoAxis = false;
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
if (e.NewItems != null)
{
foreach (Axis axis in e.NewItems)
{
axis.Chart = this;
if (axis._isAutoGenerated)
isAutoAxis = true;
if (axis.AxisLabels != null)
axis.AxisLabels.Chart = this;
foreach (ChartGrid cg in axis.Grids)
cg.Chart = this;
foreach (Ticks ticks in axis.Ticks)
ticks.Chart = this;
axis.IsNotificationEnable = false;
if (axis.StartFromZero == null)
axis.StartFromZero = false;
axis.IsNotificationEnable = true;
axis.PropertyChanged -= Element_PropertyChanged;
axis.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(Element_PropertyChanged);
}
}
}
if (!isAutoAxis)
{
InvokeRender();
}
}
///
/// Event handler manages the addition and removal of Axis from AxesY list of chart
///
/// AxesY
/// NotifyCollectionChangedEventArgs
private void AxesY_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
Boolean isAutoAxis = false;
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
if (e.NewItems != null)
{
foreach (Axis axis in e.NewItems)
{
axis.Chart = this;
if (axis._isAutoGenerated)
isAutoAxis = true;
axis.AxisRepresentation = AxisRepresentations.AxisY;
if (axis.AxisLabels != null)
axis.AxisLabels.Chart = this;
foreach (ChartGrid cg in axis.Grids)
cg.Chart = this;
foreach (Ticks ticks in axis.Ticks)
ticks.Chart = this;
axis.IsNotificationEnable = false;
if (axis.StartFromZero == null)
axis.StartFromZero = true;
axis.IsNotificationEnable = true;
axis.PropertyChanged -= Element_PropertyChanged;
axis.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(Element_PropertyChanged);
}
}
}
if (!isAutoAxis)
{
InvokeRender();
}
}
///
/// Event handler manages the addition and removal of title from chart
///
/// Titles
/// NotifyCollectionChangedEventArgs
private void Titles_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
ObservableCollection titles = sender as ObservableCollection;
if (e.NewItems != null)
{
foreach (Title title in e.NewItems)
{
title.Chart = this;
title.PropertyChanged -= Element_PropertyChanged;
title.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(Element_PropertyChanged);
}
}
}
InvokeRender();
}
///
/// Event handler manages the addition and removal of legend from chart
///
/// Legend
/// NotifyCollectionChangedEventArgs
private void Legends_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
Boolean isAutoLegend = false;
if (e.NewItems != null)
{
foreach (Legend legend in e.NewItems)
{
if (legend._isAutoGenerated)
isAutoLegend = true;
if (Legends.Count > 0)
{
if (String.IsNullOrEmpty((String)legend.GetValue(NameProperty)))
legend.SetValue(NameProperty, "Legend" + Legends.IndexOf(legend));
}
legend.Chart = this;
legend.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(Element_PropertyChanged);
}
}
if (!isAutoLegend)
{
InvokeRender();
}
}
///
/// Event handler manages the addition and removal of trendLine from chart
///
/// TrendLine
/// NotifyCollectionChangedEventArgs
private void TrendLines_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
if (e.NewItems != null)
{
foreach (TrendLine trendLine in e.NewItems)
{
trendLine.Chart = this;
if (!String.IsNullOrEmpty(this.Theme))
{
trendLine.ApplyStyleFromTheme(this, "TrendLine");
}
trendLine.PropertyChanged -= Element_PropertyChanged;
trendLine.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(Element_PropertyChanged);
}
}
}
InvokeRender();
}
///
/// Event handler manages the addition and removal of DataSeries from Series list of chart
///
/// Series
/// NotifyCollectionChangedEventArgs
private void Series_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
if (e.NewItems != null)
foreach (DataSeries ds in e.NewItems)
{
ds.Chart = this;
foreach (DataPoint dp in ds.DataPoints)
{
dp.Chart = this;
}
if (!String.IsNullOrEmpty(this.Theme))
ds.ApplyStyleFromTheme(this, "DataSeries");
if (String.IsNullOrEmpty((String)ds.GetValue(NameProperty)))
{
//ds.SetValue(NameProperty, ds.GetType().Name + this.Series.IndexOf(ds).ToString() + "_" + Guid.NewGuid().ToString().Replace('-', '_'));
ds.Name = "DataSeries" + (this.Series.Count - 1).ToString() + "_" + Guid.NewGuid().ToString().Replace('-', '_');
ds._isAutoName = true;
}
else
ds._isAutoName = false;
ds.PropertyChanged -= Element_PropertyChanged;
ds.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(Element_PropertyChanged);
}
}
InvokeRender();
}
///
/// Event handler manages property change of visifire elements, like Title, Legends, DataSeries etc.
///
/// ObservableObject
/// PropertyChangedEventArgs
private void Element_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
InvokeRender();
}
///
/// Load watermark for www.visifire.com, present at the right and top side corner of the chart.
///
private void LoadWatermark()
{
if (WaterMarkElement == null)
{
WaterMarkElement = new TextBlock();
WaterMarkElement.HorizontalAlignment = HorizontalAlignment.Right;
WaterMarkElement.VerticalAlignment = VerticalAlignment.Top;
WaterMarkElement.Margin = new Thickness(0, 3, 5, 0);
WaterMarkElement.SetValue(Canvas.ZIndexProperty, 90000);
WaterMarkElement.Text = "www.visifire.com";
WaterMarkElement.TextDecorations = TextDecorations.Underline;
WaterMarkElement.Foreground = new SolidColorBrush(Colors.LightGray);
WaterMarkElement.FontSize = 9;
AttachHref(this, WaterMarkElement, "http://www.visifire.com", HrefTargets._blank);
WaterMarkElement.Visibility = (Watermark) ? Visibility.Visible : Visibility.Collapsed;
_rootElement.Children.Add(WaterMarkElement);
}
}
///
/// Load or Update color sets from chart resource
///
private void LoadOrUpdateColorSets()
{
if (EmbeddedColorSets == null)
{
string resourceName = "Visifire.Charts.ColorSets.xaml"; // Resource location for embedded color sets
using (System.IO.Stream s = typeof(Chart).Assembly.GetManifestResourceStream(resourceName))
{
if (s != null)
{
System.IO.StreamReader reader = new System.IO.StreamReader(s);
String xaml = reader.ReadToEnd();
#if WPF
EmbeddedColorSets = XamlReader.Load(new XmlTextReader(new StringReader(xaml))) as ColorSets;
#else
EmbeddedColorSets = System.Windows.Markup.XamlReader.Load(xaml) as ColorSets;
#endif
if (EmbeddedColorSets == null)
System.Diagnostics.Debug.WriteLine("Unable to load embedded ColorSets. Reload project and try again.");
//if (InternalColorSets == null)
// InternalColorSets = new ColorSets();
//if (EmbeddedColorSets != null)
// InternalColorSets.AddRange(EmbeddedColorSets);
//if (ColorSets != null)
// InternalColorSets.AddRange(ColorSets);
reader.Close();
s.Close();
}
}
}
//else
//{
// InternalColorSets.Clear();
// if (EmbeddedColorSets != null)
// InternalColorSets.AddRange(EmbeddedColorSets);
// if (ColorSets != null)
// InternalColorSets.AddRange(ColorSets);
//}
}
///
/// Some property needs to bind with the existing property in control before first time render.
/// And binding should be done only once.
///
private void BindProperties()
{
System.Windows.Data.Binding binding = new System.Windows.Data.Binding("Background");
binding.Source = this;
binding.Mode = System.Windows.Data.BindingMode.OneWay;
base.SetBinding(InternalBackgroundProperty, binding);
System.Windows.Data.Binding binding1 = new System.Windows.Data.Binding("BorderThickness");
binding1.Source = this;
binding1.Mode = System.Windows.Data.BindingMode.OneWay;
base.SetBinding(InternalBorderThicknessProperty, binding1);
}
///
/// Prepare chart area for drawing
///
private void PrepareChartAreaForDrawing()
{
// Create new ChartArea
if (ChartArea == null)
{
ChartArea = new ChartArea(this as Chart);
}
#if WPF
NameScope.SetNameScope(this._rootElement, new NameScope());
#endif
ApplyChartBevel();
ApplyChartShadow(this.ActualWidth, this.ActualHeight);
_renderLapsedCounter = 0;
}
///
/// Apply bevel effect to Chart
///
/// If success return true else false.
private Boolean ApplyChartBevel()
{
if (Bevel && _rootElement != null)
{
if (_chartBorder.ActualWidth == 0 && _chartBorder.ActualHeight == 0)
{
return false;
}
_chartAreaGrid.Margin = new Thickness(
_chartAreaMargin.Left + BEVEL_DEPTH,
_chartAreaMargin.Top + BEVEL_DEPTH,
_chartAreaMargin.Right,
_chartAreaMargin.Bottom);
_chartAreaGrid.UpdateLayout();
_bevelCanvas.Children.Clear();
Brush topBrush = Graphics.GetBevelTopBrush(this.Background);
Brush leftBrush = Graphics.GetBevelSideBrush(0, this.Background);
Brush rightBrush = Graphics.GetBevelSideBrush(170, this.Background);
Brush bottomBrush = Graphics.GetBevelSideBrush(180, this.Background);
BevelVisual = ExtendedGraphics.Get2DRectangleBevel(null,
_chartBorder.ActualWidth - _chartBorder.BorderThickness.Left - _chartBorder.BorderThickness.Right - _chartAreaMargin.Right - _chartAreaMargin.Left,
_chartBorder.ActualHeight - _chartBorder.BorderThickness.Top - _chartBorder.BorderThickness.Bottom - _chartAreaMargin.Top - _chartAreaMargin.Bottom,
BEVEL_DEPTH, BEVEL_DEPTH, topBrush, leftBrush, rightBrush, bottomBrush);
if (LightingEnabled)
{
_chartLightingBorder.Opacity = 0.4;
}
BevelVisual.Margin = new Thickness(0, 0, 0, 0);
BevelVisual.IsHitTestVisible = false;
BevelVisual.SetValue(Canvas.TopProperty, _chartAreaMargin.Top + _chartBorder.BorderThickness.Top);
BevelVisual.SetValue(Canvas.LeftProperty, _chartAreaMargin.Left + _chartBorder.BorderThickness.Left);
_bevelCanvas.Children.Add(BevelVisual);
}
return true;
}
///
/// Remove bevel effect from chart
///
private void RemoveChartBevel()
{
if (_isTemplateApplied)
{
if (BevelVisual != null && _bevelCanvas != null)
{
_bevelCanvas.Children.Clear();
_chartAreaGrid.Margin = new Thickness(0);
}
}
}
///
/// Apply lighting effect for chart
///
private void ApplyLighting()
{
if (_chartLightingBorder != null)
{
if (LightingEnabled)
{
_chartLightingBorder.Visibility = Visibility.Visible;
_chartLightingBorder.Opacity = 0.4;
}
else
{
_chartLightingBorder.Visibility = Visibility.Collapsed;
}
}
}
///
/// Apply shadow effect on chart
/// (Creates a shadow layer behind the chart)
///
/// Chart width
/// Chart height
private void ApplyChartShadow(Double width, Double height)
{
if (!_isShadowApplied && ShadowEnabled && !Double.IsNaN(height) && height != 0 && !Double.IsNaN(width) && width != 0)
{
_shadowGrid.Children.Clear();
if (_rootElement != null)
{
// Shadow grid contains multiple rectangles that give a blurred effect at the edges
ChartShadowLayer = ExtendedGraphics.Get2DRectangleShadow(null, width - Chart.SHADOW_DEPTH, height - Chart.SHADOW_DEPTH, new CornerRadius(6), new CornerRadius(6), 6);
ChartShadowLayer.Width = width - Chart.SHADOW_DEPTH;
ChartShadowLayer.Height = height - Chart.SHADOW_DEPTH;
ChartShadowLayer.IsHitTestVisible = false;
ChartShadowLayer.SetValue(Canvas.ZIndexProperty, 0);
_shadowGrid.Children.Add(ChartShadowLayer);
ChartShadowLayer.Margin = new Thickness(Chart.SHADOW_DEPTH, Chart.SHADOW_DEPTH, 0, 0);
if (this._chartBorder != null)
this._chartBorder.Margin = new Thickness(0, 0, SHADOW_DEPTH, SHADOW_DEPTH);
_isShadowApplied = true;
}
}
if (ShadowEnabled && ChartShadowLayer != null)
ChartShadowLayer.Visibility = Visibility.Visible;
}
///
/// Removes Chart shadow
///
private void RemoveShadow()
{
if (_isTemplateApplied && !ShadowEnabled)
{
_chartBorder.Margin = new Thickness(0, 0, 0, 0);
_bevelCanvas.Margin = new Thickness(0, 0, 0, 0);
_isShadowApplied = false;
if (ChartShadowLayer != null)
ChartShadowLayer.Visibility = Visibility.Collapsed;
}
}
///
/// Load theme from resource file and select specific theme using theme name
///
/// String themeName
private void LoadTheme(String themeName, Boolean isThemePropertyChanged)
{
if (String.IsNullOrEmpty(themeName))
return;
StyleDictionary = null;
string fooResourceName = "Visifire.Charts." + themeName + ".xaml";
using (System.IO.Stream s = typeof(Chart).Assembly.GetManifestResourceStream(fooResourceName))
{
if (s == null)
{
#if WPF
ResourceDictionary resource = (ResourceDictionary)Application.LoadComponent(new Uri(@"" + themeName + ".xaml", UriKind.RelativeOrAbsolute));
StyleDictionary = resource;
#else
fooResourceName = themeName + ".xaml";
System.Windows.Resources.StreamResourceInfo srif = Application.GetResourceStream(new Uri(fooResourceName, UriKind.RelativeOrAbsolute));
if (srif == null)
throw new Exception(fooResourceName + " Theme file not found as application resources.");
using (System.IO.Stream s1 = srif.Stream)
{
if (s1 != null)
{
System.IO.StreamReader reader = new System.IO.StreamReader(s1);
String xaml = reader.ReadToEnd();
StyleDictionary = System.Windows.Markup.XamlReader.Load(xaml) as ResourceDictionary;
reader.Close();
s1.Close();
}
}
#endif
}
else
{
System.IO.StreamReader reader = new System.IO.StreamReader(s);
String xaml = reader.ReadToEnd();
#if WPF
StyleDictionary = (ResourceDictionary)XamlReader.Load(new XmlTextReader(new StringReader(xaml)));
#else
StyleDictionary = System.Windows.Markup.XamlReader.Load(xaml) as ResourceDictionary;
#endif
reader.Close();
s.Close();
}
}
if (StyleDictionary != null)
{
//#if SL
// if (Style == null)
// {
// Style myStyle = StyleDictionary["Chart"] as Style;
// if (myStyle != null)
// Style = myStyle;
// }
//#else
Style myStyle = StyleDictionary["Chart"] as Style;
_isThemeChanged = isThemePropertyChanged;
if (myStyle != null)
{
if (isThemePropertyChanged)
Style = myStyle;
else if(Style == null)
Style = myStyle;
}
//#endif
}
else
{
throw new Exception("Theme file " + themeName + ".xaml not found..");
}
}
///
/// Loads default ToolTips if required.
/// Currently only one tooltip is supported
///
private void LoadToolTips()
{
if (ToolTips.Count == 0)
{
ToolTip toolTip = new ToolTip() { Chart = this, Visibility = Visibility.Collapsed };
ToolTips.Add(toolTip);
}
_toolTip = ToolTips[0];
_toolTip.Chart = this;
_toolTipCanvas.Children.Add(_toolTip);
// Attach events to the root element of the chart to track mouse movement over chart.
this._rootElement.MouseLeave += new MouseEventHandler(Chart_MouseLeave);
}
///
/// Attach events and tooltip to chart
///
private void AttachToolTipAndEvents()
{
if (!String.IsNullOrEmpty(ToolTipText))
AttachToolTip(this, this, this);
AttachEvents2Visual(this, this, this._rootElement);
AttachEvents2Visual4MouseDownEvent(this, this, this._plotCanvas);
}
///
/// DataPointWidthProperty changed call back function
///
/// Chart
/// DependencyPropertyChangedEventArgs
private static void OnSmartLabelEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart c = d as Chart;
c.InvokeRender();
}
///
/// DataPointWidthProperty changed call back function
///
/// Chart
/// DependencyPropertyChangedEventArgs
private static void OnDataPointWidthPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart c = d as Chart;
c.InvokeRender();
}
///
/// ScrollingEnabledProperty changed call back function
///
/// Chart
/// DependencyPropertyChangedEventArgs
private static void OnScrollingEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart c = d as Chart;
c.InvokeRender();
}
///
/// UniqueColorsProperty changed call back function
///
/// Chart
/// DependencyPropertyChangedEventArgs
private static void OnUniqueColorsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart c = d as Chart;
c.InvokeRender();
}
///
/// View3DProperty changed call back function
///
///
///
private static void OnView3DPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart c = d as Chart;
c.InvokeRender();
}
///
/// HrefTargetProperty changed call back function
///
/// Chart
/// DependencyPropertyChangedEventArgs
private static void OnHrefTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart c = d as Chart;
c.AttachHref(c, c, c.Href, (HrefTargets)e.NewValue);
}
///
/// HrefProperty changed call back function
///
/// Chart
/// DependencyPropertyChangedEventArgs
private static void OnHrefChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart c = d as Chart;
c.AttachHref(c, c, e.NewValue.ToString(), c.HrefTarget);
}
///
/// ThemeProperty changed call back function
///
/// Chart
/// DependencyPropertyChangedEventArgs
private static void OnThemePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart c = d as Chart;
c.LoadTheme((String)e.NewValue, (e.OldValue == null)?false:true);
c.InvokeRender();
}
///
/// InternalBorderThicknessProperty changed call back function
///
/// Chart
/// DependencyPropertyChangedEventArgs
private static void OnInternalBorderThicknessChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart c = d as Chart;
c.RemoveChartBevel();
c.InvokeRender();
}
///
/// InternalBackgroundProperty changed call back function
///
/// Chart
/// DependencyPropertyChangedEventArgs
private static void OnInternalBackgroundPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart c = d as Chart;
c.RemoveChartBevel();
c.ApplyChartBevel();
c.InvokeRender();
}
///
/// InternalPropertyProperty changed call back function
///
/// Chart
/// DependencyPropertyChangedEventArgs
private static void OnInternalPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart c = d as Chart;
if (c.ApplyChartBevel())
{
if ((Boolean)c.Bevel == true)
{
c.InvokeRender();
}
else
{
c.RemoveChartBevel();
}
}
}
///
/// Property changed call back function
///
/// Chart
/// DependencyPropertyChangedEventArgs
private static void OnBevelPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart c = d as Chart;
c.RemoveChartBevel();
c.InvokeRender();
}
///
/// Property changed call back function
///
/// Chart
/// DependencyPropertyChangedEventArgs
private static void OnColorSetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart c = d as Chart;
c.InvokeRender();
}
///
/// Property changed call back function
///
/// Chart
/// DependencyPropertyChangedEventArgs
private static void OnLightingEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart c = d as Chart;
c.ApplyLighting();
}
///
/// Property changed call back function
///
/// Chart
/// DependencyPropertyChangedEventArgs
private static void OnShadowEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart c = d as Chart;
if ((Boolean)e.NewValue == true)
{
c.ApplyChartShadow(c.ActualWidth, c.ActualHeight);
}
else
{
c.RemoveShadow();
}
c.ApplyChartBevel();
}
///
/// WaterMarkElementProperty changed call back function
///
/// Chart
/// DependencyPropertyChangedEventArgs
private static void OnWatermarkPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart c = d as Chart;
if (c.WaterMarkElement != null)
c.WaterMarkElement.Visibility = ((Boolean)e.NewValue) ? Visibility.Visible : Visibility.Collapsed;
}
///
/// PlotAreaProperty changed call back function
///
/// Chart
/// DependencyPropertyChangedEventArgs
private static void OnPlotAreaPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart chart = d as Chart;
PlotArea plotArea = (PlotArea)e.NewValue;
plotArea.Chart = chart;
plotArea.PropertyChanged -= chart.Element_PropertyChanged;
plotArea.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(chart.Element_PropertyChanged);
chart.InvokeRender();
}
///
/// MinScrollingGapProperty changed call back function
///
/// Chart
/// DependencyPropertyChangedEventArgs
private static void OnMinimumGapPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Chart c = d as Chart;
c.InvokeRender();
}
#endregion
#region Private Properties
///
/// Embedded color sets
///
private ColorSets EmbeddedColorSets
{
get;
set;
}
///
/// Chart shadow layer is created and added to ShadowGrid, present in template
///
private Grid ChartShadowLayer
{
get;
set;
}
///
/// TextBlock element for water Mark
///
private TextBlock WaterMarkElement
{
get;
set;
}
///
/// Foreground is a default property of a Control and it is not applicable in chart.
/// Hides the Foreground property in control
///
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
private new Brush Foreground
{
get;
set;
}
#endregion
#region Internal Properties
///
/// If scroll is activated by any cause then IsScrollingActivated should be set to true.
///
internal Boolean IsScrollingActivated
{
get;
set;
}
///
/// Collection of DataSeries
///
internal List InternalSeries
{
get;
set;
}
///
/// Bevel canvas as Bevel Visual
///
internal Canvas BevelVisual
{
get;
set;
}
///
/// PlotDetails holds plotting information.
/// As example, grouping of series depending upon axis types and RenderAs type of Series.
///
internal PlotDetails PlotDetails
{
get;
set;
}
///
/// Chart area is the entire area defined by the chart.
/// Chart area manages jobs related to plotting the graph.
///
internal ChartArea ChartArea
{
get;
set;
}
///
/// StyleDictionary of themes
///
internal ResourceDictionary StyleDictionary
{
get;
set;
}
///
/// AxesX as Observable collection of type Axis
///
internal IList InternalAxesX
{
get;
set;
}
///
/// AxesY as Observable collection of type Axis
///
internal IList InternalAxesY
{
get;
set;
}
#endregion
#region Internal Methods
///
/// Visually select the DataPoints which are selected
///
///
internal static void SelectDataPoints(Chart chart)
{
if (chart == null || chart.InternalSeries == null)
return;
foreach (DataSeries ds in chart.InternalSeries)
{
if (ds.SelectionEnabled)
{
foreach (DataPoint dp in ds.DataPoints)
{
if (dp.Selected)
{
dp.Select(true);
if (ds.SelectionMode == SelectionModes.Single)
dp.DeSelectOthers();
}
else
dp.DeSelect(dp, true, true);
}
}
}
}
///
/// Get ColorSet by ColorSet name
///
/// Name of the ColorSet
/// ColorSet
internal ColorSet GetColorSetByName(String id)
{
ColorSet colorSet = null;
if (ColorSets != null && ColorSets.Count > 0)
colorSet = ColorSets.GetColorSetByName(id);
if(colorSet == null)
colorSet = EmbeddedColorSets.GetColorSetByName(id);
return colorSet;
}
///
/// Fire Rendered event
///
internal void FireRenderedEvent()
{
if (_rendered != null)
_rendered(this, null);
}
///
/// Check if exception occurred due to negative size error
///
/// ArgumentException
/// Boolean
internal Boolean CheckSizeError(ArgumentException e)
{
if (e == null)
return false;
String stackTrace = e.StackTrace.TrimStart();
if (stackTrace.Contains("set_Height(Double value)")
|| stackTrace.Contains("set_Width(Double value)")
|| e.Message == "Height must be non-negative." || e.Message == "Width must be non-negative.")
{
#if DEBUG
System.Diagnostics.Debug.WriteLine("------------------------------------------");
System.Diagnostics.Debug.WriteLine("The following SizeChanged Error is handled");
System.Diagnostics.Debug.WriteLine("------------------------------------------");
System.Diagnostics.Debug.WriteLine(e.Message);
if (e.StackTrace != null)
System.Diagnostics.Debug.WriteLine(e.StackTrace);
System.Diagnostics.Debug.WriteLine("------------------------------------------");
#endif
return true;
}
else
return false;
}
///
/// On ToolTipText PropertyChanged event, this function is invoked
///
/// New text value
internal override void OnToolTipTextPropertyChanged(string newValue)
{
base.OnToolTipTextPropertyChanged(newValue);
DetachToolTip(this._toolTipCanvas);
if (!String.IsNullOrEmpty(newValue))
AttachToolTip(this, this, this);
}
///
/// Update position of the tooltip according to mouse position
///
/// FrameworkElement
/// MouseEventArgs
internal void UpdateToolTipPosition(object sender, MouseEventArgs e)
{
if (ToolTipEnabled && (Boolean)_toolTip.Enabled)
{
Double actualX = e.GetPosition(this).X;
Double x = actualX;
Double y = e.GetPosition(this).Y;
#region Set position of ToolTip
_toolTip.Measure(new Size(Double.MaxValue, Double.MaxValue));
_toolTip.UpdateLayout();
Size toolTipSize = Visifire.Commons.Graphics.CalculateVisualSize(_toolTip._borderElement);
y = y - (toolTipSize.Height + 5);
x = x - toolTipSize.Width / 2;
if (x <= 0)
{
x = e.GetPosition(this).X + 10;
y = e.GetPosition(this).Y + 20;
if ((y + toolTipSize.Height) >= this.ActualHeight)
y = this.ActualHeight - toolTipSize.Height;
}
if ((x + toolTipSize.Width) >= this.ActualWidth)
{
x = e.GetPosition(this).X - toolTipSize.Width;
y = e.GetPosition(this).Y - toolTipSize.Height;
}
if (y < 0)
y = e.GetPosition(this).Y + 20;
if (x + toolTipSize.Width > this.ActualWidth)
x = x + toolTipSize.Width - this.ActualWidth;
if (toolTipSize.Width == _toolTip.MaxWidth)
x = 0;
if (x < 0)
x = 0;
// If tooltip still goes out of towards y
if (!Double.IsNaN(this.ActualHeight) && y + toolTipSize.Height > this.ActualHeight)
{
y = 0;
x = actualX + 10;
if (x <= 0)
x = e.GetPosition(this).X + 10;
if ((x + toolTipSize.Width) >= this.ActualWidth)
x = e.GetPosition(this).X - toolTipSize.Width;
if (x + toolTipSize.Width > this.ActualWidth)
x = x + toolTipSize.Width - this.ActualWidth;
if (toolTipSize.Width == _toolTip.MaxWidth)
x = 0;
if (x < 0)
x = 0;
}
_toolTip.SetValue(Canvas.LeftProperty, x);
_toolTip.SetValue(Canvas.TopProperty, y);
#endregion
}
else
{
_toolTip.Hide();
}
}
///
/// Get collection of titles which are docked inside PlotArea
/// using LINQ
///
/// List of Titles docked inside PlotArea
internal List GetTitlesDockedInsidePlotArea()
{
if (Titles != null)
{
var titlesDockedInsidePlotArea =
from title in Titles
where (title.DockInsidePlotArea == true)
select title;
return titlesDockedInsidePlotArea.ToList();
}
return null;
}
///
/// Get collection of titles which are docked outside PlotArea
/// using LINQ
///
/// List of Titles docked out side PlotArea
internal List GetTitlesDockedOutSidePlotArea()
{
if (Titles != null)
{
var titlesDockedOutSidePlotArea =
from title in Titles
where (title.DockInsidePlotArea == false)
select title;
return titlesDockedOutSidePlotArea.ToList();
}
else
return null;
}
///
/// Render is a delegate to a method that takes no arguments and does not return a value,
/// which is pushed onto the System.Windows.Threading.Dispatcher event queue.
///
internal void InvokeRender()
{
if (_isTemplateApplied)
{
if (_renderLock)
_renderLapsedCounter++;
else
{
#if WPF
if (Application.Current != null && Application.Current.Dispatcher.Thread != Thread.CurrentThread)
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Background, new RenderDelegate(Render));
else
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new RenderDelegate(Render));
#else
if (IsInDesignMode)
Render();
else
this.Dispatcher.BeginInvoke(Render);
#endif
}
}
}
///
/// Render redraws the chart
///
internal void Render()
{
if (_isTemplateApplied && !_renderLock && _rootElement != null)
{
if (Double.IsNaN(this.ActualWidth) || Double.IsNaN(this.ActualHeight) || this.ActualWidth == 0 || this.ActualHeight == 0)
return;
_renderLock = true;
try
{
PrepareChartAreaForDrawing();
ChartArea.Draw(this);
}
catch (Exception e)
{
_renderLock = false;
if (CheckSizeError(e as ArgumentException))
return;
else
throw new Exception(e.Message, e);
}
}
}
///
/// Calculate font color of DataPoint labels depending upon chart background
///
/// Chart
/// DataPoint
/// labelFontColor
/// labelStyle
/// Brush
internal static Brush CalculateDataPointLabelFontColor(Chart chart, DataPoint dataPoint, Brush labelFontColor, LabelStyles labelStyle)
{
Brush returnBrush = dataPoint.LabelFontColor;
if (labelFontColor == null)
{
Double intensity;
if (labelStyle == LabelStyles.Inside && dataPoint.Parent.RenderAs != RenderAs.Line)
{
intensity = Graphics.GetBrushIntensity(dataPoint.Color);
returnBrush = Graphics.GetDefaultFontColor(intensity);
}
else
{
if (chart.PlotArea.InternalBackground == null)
{
if (chart.Background == null)
{
returnBrush = new SolidColorBrush(Colors.Black);
}
else
{
intensity = Graphics.GetBrushIntensity(chart.Background);
returnBrush = Graphics.GetDefaultFontColor(intensity);
}
}
else
{
intensity = Graphics.GetBrushIntensity(chart.PlotArea.InternalBackground);
returnBrush = Graphics.GetDefaultFontColor(intensity);
}
}
}
return returnBrush;
}
///
/// Calculate FontColor for text elements over chart depending upon chart background and dockInsidePlotArea
///
/// Chart
/// FontColor
/// DockInsidePlotArea
/// Brush
internal static Brush CalculateFontColor(Chart chart, Brush color, Boolean dockInsidePlotArea)
{
Brush brush = color;
Double intensity;
if (color == null)
{
if (!dockInsidePlotArea)
{
if (chart != null)
{
if (Graphics.AreBrushesEqual(chart.Background, new SolidColorBrush(Colors.Transparent)) || chart.Background == null)
{
brush = new SolidColorBrush(Colors.Black);
}
else
{
intensity = Graphics.GetBrushIntensity(chart.Background);
brush = Graphics.GetDefaultFontColor(intensity);
}
}
}
else
{
if (chart.PlotArea != null)
{
if (Graphics.AreBrushesEqual(chart.PlotArea.InternalBackground, new SolidColorBrush(Colors.Transparent)) || chart.PlotArea.InternalBackground == null)
{
if (Graphics.AreBrushesEqual(chart.Background, new SolidColorBrush(Colors.Transparent)) || chart.Background == null)
{
brush = new SolidColorBrush(Colors.Black);
}
else
{
intensity = Graphics.GetBrushIntensity(chart.Background);
brush = Graphics.GetDefaultFontColor(intensity);
}
}
else
{
intensity = Graphics.GetBrushIntensity(chart.PlotArea.InternalBackground);
brush = Graphics.GetDefaultFontColor(intensity);
}
}
}
}
return brush;
}
#endregion
#region Internal Events And Delegates
#if WPF
///
/// RenderDelegate is used for attaching Render() function as target while Invoking Render() using Dispatcher.
///
internal delegate void RenderDelegate();
#endif
#endregion
#region Data
private EventHandler _rendered;
///
/// Whether shadow effect of chart is applied or not
///
private Boolean _isShadowApplied;
///
/// Chart area margin
///
private Thickness _chartAreaMargin;
///
/// Shadow Depth for chart
///
internal static Double SHADOW_DEPTH = 4;
///
/// Bevel Depth for chart
///
internal static Double BEVEL_DEPTH = 5;
///
/// Number of time render call is lapsed or failed due to render lock
///
internal Int32 _renderLapsedCounter;
///
/// Render lock is used to protect chart from multiple render
///
internal bool _renderLock = false;
///
/// Is used to handle inactive animation after first time render
///
internal Boolean _internalAnimationEnabled = false;
//#if WPF
///
/// Whether Theme is changed by the user
///
internal Boolean _isThemeChanged = false;
//#endif
#endregion
}
}