/*
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.Windows.Controls;
using System.Windows.Media;
using System.Windows.Input;
using System.Windows.Shapes;
#else
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Input;
#endif
using Visifire.Commons;
namespace Visifire.Charts
{
///
/// TrendLine can be used to draw lines to indicate significance of certain points
///
public class TrendLine : ObservableObject
{
#region Public Methods
///
/// Initializes a new instance of the Visifire.Charts.TrendLine class
///
public TrendLine()
{
}
#endregion
#region Public Properties
///
/// Identifies the Visifire.Charts.TrendLine.Enabled dependency property.
///
///
/// The identifier for the Visifire.Charts.TrendLine.Enabled dependency property.
///
public static readonly DependencyProperty EnabledProperty = DependencyProperty.Register(
"Enabled",
typeof(Nullable),
typeof(TrendLine),
new PropertyMetadata(OnEnabledPropertyChanged));
#if WPF
///
/// Identifies the Visifire.Charts.TrendLine.Opacity dependency property.
///
///
/// The identifier for the Visifire.Charts.TrendLine.Opacity dependency property.
///
public new static readonly DependencyProperty OpacityProperty = DependencyProperty.Register
("Opacity",
typeof(Double),
typeof(TrendLine),
new PropertyMetadata(1.0, OnOpacityPropertyChanged));
#endif
///
/// Identifies the Visifire.Charts.TrendLine.LineColor dependency property.
///
///
/// The identifier for the Visifire.Charts.TrendLine.LineColor dependency property.
///
public static readonly DependencyProperty LineColorProperty = DependencyProperty.Register(
"LineColor",
typeof(Brush),
typeof(TrendLine),
new PropertyMetadata(OnLineColorPropertyChanged));
///
/// Identifies the Visifire.Charts.TrendLine.LineThickness dependency property.
///
///
/// The identifier for the Visifire.Charts.TrendLine.LineThickness dependency property.
///
public static readonly DependencyProperty LineThicknessProperty = DependencyProperty.Register(
"LineThickness",
typeof(Double),
typeof(TrendLine),
new PropertyMetadata(OnLineThicknessPropertyChanged));
///
/// Identifies the Visifire.Charts.TrendLine.LineStyle dependency property.
///
///
/// The identifier for the Visifire.Charts.TrendLine.LineStyle dependency property.
///
public static readonly DependencyProperty LineStyleProperty = DependencyProperty.Register(
"LineStyle",
typeof(LineStyles),
typeof(TrendLine),
new PropertyMetadata(OnLineStylePropertyChanged));
///
/// Identifies the Visifire.Charts.TrendLine.ShadowEnabled dependency property.
///
///
/// The identifier for the Visifire.Charts.TrendLine.ShadowEnabled dependency property.
///
public static readonly DependencyProperty ShadowEnabledProperty = DependencyProperty.Register(
"ShadowEnabled",
typeof(bool),
typeof(TrendLine),
new PropertyMetadata(OnShadowEnabledPropertyChanged));
///
/// Identifies the Visifire.Charts.TrendLine.Value dependency property.
///
///
/// The identifier for the Visifire.Charts.TrendLine.Value dependency property.
///
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value",
typeof(Object),
typeof(TrendLine),
new PropertyMetadata(OnValuePropertyChanged));
///
/// Identifies the Visifire.Charts.TrendLine.HrefTarget dependency property.
///
///
/// The identifier for the Visifire.Charts.TrendLine.HrefTarget dependency property.
///
public static readonly DependencyProperty HrefTargetProperty = DependencyProperty.Register(
"HrefTarget",
typeof(HrefTargets),
typeof(TrendLine),
new PropertyMetadata(OnHrefTargetChanged));
///
/// Identifies the Visifire.Charts.TrendLine.Href dependency property.
///
///
/// The identifier for the Visifire.Charts.TrendLine.Href dependency property.
///
public static readonly DependencyProperty HrefProperty = DependencyProperty.Register(
"Href",
typeof(String),
typeof(TrendLine),
new PropertyMetadata(OnHrefChanged));
///
/// Identifies the Visifire.Charts.TrendLine.AxisType dependency property.
///
///
/// The identifier for the Visifire.Charts.TrendLine.AxisType dependency property.
///
public static readonly DependencyProperty AxisTypeProperty = DependencyProperty.Register(
"AxisType",
typeof(AxisTypes),
typeof(TrendLine),
new PropertyMetadata(OnAxisTypePropertyChanged));
///
/// Identifies the Visifire.Charts.TrendLine.Orientation dependency property.
///
///
/// The identifier for the Visifire.Charts.TrendLine.Orientation dependency property.
///
public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(
"Orientation",
typeof(Orientation),
typeof(TrendLine),
new PropertyMetadata(Orientation.Horizontal, OnOrientationPropertyChanged));
///
/// Enables or disables the TrendLine
///
[System.ComponentModel.TypeConverter(typeof(NullableBoolConverter))]
public Nullable Enabled
{
get
{
if ((Nullable)GetValue(EnabledProperty) == null)
return true;
else
return (Nullable)GetValue(EnabledProperty);
}
set
{
SetValue(EnabledProperty, value);
}
}
///
/// Get or set the Opacity property
///
public new Double Opacity
{
get
{
return (Double)GetValue(OpacityProperty);
}
set
{
#if SL
if (Opacity != value)
{
SetValue(OpacityProperty, value);
FirePropertyChanged("Opacity");
}
#else
SetValue(OpacityProperty, value);
#endif
}
}
///
/// Get or set the Cursor property
///
public new Cursor Cursor
{
get
{
return base.Cursor;
}
set
{
if (base.Cursor != value)
{
base.Cursor = value;
FirePropertyChanged("Cursor");
}
}
}
///
/// Get or set the Color of the TrendLine
///
public Brush LineColor
{
get
{
return (Brush)GetValue(LineColorProperty) == null ? new SolidColorBrush(Colors.Red) : (Brush)GetValue(LineColorProperty);
}
set
{
SetValue(LineColorProperty, value);
}
}
///
/// Get or set the Line thickness of TrendLine
///
public Double LineThickness
{
get
{
return (Double)GetValue(LineThicknessProperty) == 0 ? 2 : (Double)GetValue(LineThicknessProperty);
}
set
{
SetValue(LineThicknessProperty, value);
}
}
///
/// Get or set the Line style of TrendLine
///
public LineStyles LineStyle
{
get
{
return (LineStyles)GetValue(LineStyleProperty);
}
set
{
SetValue(LineStyleProperty, value);
}
}
///
/// Whether shadow is enebled for the TrendLine
///
public bool ShadowEnabled
{
get
{
return (bool)GetValue(ShadowEnabledProperty);
}
set
{
SetValue(ShadowEnabledProperty, value);
}
}
///
/// Get or set the Value of the TrendLine
///
public Object Value
{
get
{
return (Object)GetValue(ValueProperty);
}
set
{
SetValue(ValueProperty, value);
}
}
///
/// Get or set the AxisType of the TrendLine
///
public AxisTypes AxisType
{
get
{
return (AxisTypes)GetValue(AxisTypeProperty);
}
set
{
SetValue(AxisTypeProperty, value);
}
}
///
/// Get or set the Orientation of the TrendLine.
/// Whether the TrendLine should be vertically oriented or horizontally oriented
///
public Orientation Orientation
{
get
{
return (Orientation)GetValue(OrientationProperty);
}
set
{
SetValue(OrientationProperty, value);
}
}
///
/// Get or set the HrefTarget property of TrendLine
///
public HrefTargets HrefTarget
{
get
{
return (HrefTargets)GetValue(HrefTargetProperty);
}
set
{
SetValue(HrefTargetProperty, value);
}
}
///
/// Get or set the Href property of TrendLine
///
public String Href
{
get
{
return (String)GetValue(HrefProperty);
}
set
{
SetValue(HrefProperty, value);
}
}
#endregion
#region Public Events And Delegates
#endregion
#region Protected Methods
#endregion
#region Internal Properties
///
/// Get or set the Value of the TrendLine
///
internal DateTime InternalDateValue
{
get;
set;
}
///
/// Get or set the Value of the TrendLine
///
internal Double InternalNumericValue
{
get;
set;
}
///
/// Axis reference
///
internal Axis ReferingAxis
{
get;
set;
}
///
/// TrendLine canvas
///
internal Canvas Visual
{
get;
set;
}
#endregion
#region Private Properties
///
/// Line visual
///
private Line Line
{
get;
set;
}
///
/// Shadow visual
///
private Line Shadow
{
get;
set;
}
#endregion
#region Private Delegates
#endregion
#region Private Methods
///
/// EnabledProperty changed call back function
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TrendLine source = d as TrendLine;
source.FirePropertyChanged("Enabled");
}
#if WPF
///
/// OpacityProperty changed call back function
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnOpacityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TrendLine source = d as TrendLine;
source.FirePropertyChanged("Opacity");
}
#endif
///
/// LineColorProperty changed call back function
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnLineColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TrendLine source = d as TrendLine;
source.UpdateVisual("LineColor", e.NewValue);
}
///
/// LineThicknessProperty changed call back function
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnLineThicknessPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TrendLine source = d as TrendLine;
//source.FirePropertyChanged("LineThickness");
source.UpdateVisual("LineThickness", e.NewValue);
}
///
/// LineStyleProperty changed call back function
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnLineStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TrendLine source = d as TrendLine;
source.UpdateVisual("LineStyle", e.NewValue);
}
///
/// ShadowEnabledProperty changed call back function
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnShadowEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TrendLine trendLine = d as TrendLine;
trendLine.UpdateVisual("ShadowEnabled", e.NewValue);
}
///
/// ValueProperty changed call back function
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TrendLine trendLine = d as TrendLine;
// Double / Int32 value entered in Managed Code
if (e.NewValue.GetType().Equals(typeof(Double)) || e.NewValue.GetType().Equals(typeof(Int32)))
{
trendLine.InternalNumericValue = Convert.ToDouble(e.NewValue);
}
// DateTime value entered in Managed Code
else if ((e.NewValue.GetType().Equals(typeof(DateTime))))
{
trendLine.InternalDateValue = (DateTime)e.NewValue;
}
// Double / Int32 / DateTime entered in XAML
else if ((e.NewValue.GetType().Equals(typeof(String))))
{
DateTime dateTimeresult;
Double doubleResult;
if (String.IsNullOrEmpty(e.NewValue.ToString()))
{
trendLine.InternalNumericValue = Double.NaN;
}
// Double entered in XAML
else if (Double.TryParse((string)e.NewValue, System.Globalization.NumberStyles.Number, System.Globalization.CultureInfo.InvariantCulture, out doubleResult))
{
trendLine.InternalNumericValue = doubleResult;
}
// DateTime entered in XAML
else if (DateTime.TryParse((string)e.NewValue, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out dateTimeresult))
{
trendLine.InternalDateValue = dateTimeresult;
}
else
{
System.Diagnostics.Debug.WriteLine("Invalid Input for AxisMaximum");
throw new Exception("Invalid Input for AxisMaximum");
}
}
else
{
System.Diagnostics.Debug.WriteLine("Invalid Input for AxisMaximum");
throw new Exception("Invalid Input for AxisMaximum");
}
//trendLine.FirePropertyChanged("Value");
trendLine.UpdateVisual("Value", e.NewValue);
}
///
/// AxisTypeProperty changed call back function
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnAxisTypePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TrendLine source = d as TrendLine;
source.FirePropertyChanged("AxisType");
}
///
/// OrientationProperty changed call back function
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnOrientationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TrendLine source = d as TrendLine;
source.FirePropertyChanged("Orientation");
}
///
/// HrefTargetProperty changed call back function
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnHrefTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TrendLine trendLine = d as TrendLine;
trendLine.FirePropertyChanged("HrefTarget");
}
///
/// HrefProperty changed call back function
///
/// DependencyObject
/// DependencyPropertyChangedEventArgs
private static void OnHrefChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TrendLine trendLine = d as TrendLine;
trendLine.FirePropertyChanged("Href");
}
///
/// Apply properties of TrendLine to line visual and line-shadow visual
///
private void ApplyProperties()
{
Line.Stroke = LineColor;
Line.StrokeThickness = LineThickness;
Line.StrokeDashArray = ExtendedGraphics.GetDashArray(LineStyle);
Shadow.StrokeThickness = LineThickness + 2;
Shadow.StrokeDashArray = ExtendedGraphics.GetDashArray(LineStyle);
Shadow.Stroke = new SolidColorBrush(Colors.LightGray);
Shadow.Opacity = 0.7;
Shadow.StrokeDashCap = PenLineCap.Round;
Shadow.StrokeLineJoin = PenLineJoin.Round;
Shadow.Visibility = ShadowEnabled ? Visibility.Visible : Visibility.Collapsed;
}
#endregion
#region Internal Methods
///
/// UpdateVisual is used for partial rendering
///
/// Name of the property
/// Value of the property
internal override void UpdateVisual(string propertyName, object value)
{
if (Line == null || Shadow == null)
FirePropertyChanged(propertyName);
else if (propertyName == "Value")
{
Chart chart = (Chart as Chart);
Axis axis = chart.PlotDetails.GetAxisXFromChart(chart, AxisType);
chart.PlotDetails.SetTrendLineValue(this, axis);
Canvas visualCanvas = (Chart as Chart).ChartArea.ChartVisualCanvas;
PositionTheLine(visualCanvas.Width, visualCanvas.Height);
}
else
ApplyProperties();
}
///
/// Set the position of line
///
///
///
private void PositionTheLine(Double width, Double height)
{
Double shadowThickness = LineThickness + 2;
switch (Orientation)
{
case Orientation.Vertical:
Line.Y1 = 0;
Line.Y2 = height;
Line.X1 = Graphics.ValueToPixelPosition(0,
width,
(Double)ReferingAxis.InternalAxisMinimum,
(Double)ReferingAxis.InternalAxisMaximum,
InternalNumericValue);
Line.X2 = Line.X1;
Visual.Height = height;
Visual.Width = shadowThickness;
break;
case Orientation.Horizontal:
Line.X1 = 0;
Line.X2 = width;
Line.Y1 = Graphics.ValueToPixelPosition(height,
0,
(Double)ReferingAxis.InternalAxisMinimum,
(Double)ReferingAxis.InternalAxisMaximum,
InternalNumericValue);
Line.Y2 = Line.Y1;
Visual.Height = shadowThickness;
Visual.Width = width;
break;
}
if (Orientation == Orientation.Horizontal)
{
Shadow.X1 = Line.X1;
Shadow.X2 = Line.X2 + 3;
Shadow.Y1 = Line.Y1 + 3;
Shadow.Y2 = Line.Y2 + 3;
}
else
{
Shadow.X1 = Line.X1 + 3;
Shadow.X2 = Line.X2 + 3;
Shadow.Y1 = Line.Y1 + 3;
Shadow.Y2 = Line.Y2;
}
}
///
/// Create visual objects for TrendLine
///
/// Width of the ChartCanvas
/// Height of the ChartCanvas
internal void CreateVisualObject(Double width, Double height)
{
if (ReferingAxis == null || !(Boolean)Enabled)
{
Visual = null;
return;
}
Visual = new Canvas();
Visual.Opacity = this.Opacity;
Visual.Cursor = this.Cursor;
Double shadowThickness = LineThickness + 2;
Line = new Line() { Tag = new ElementData() { Element = this } };
Shadow = new Line() { IsHitTestVisible = false };
ApplyProperties();
PositionTheLine(width, height);
Visual.Children.Add(Shadow);
Visual.Children.Add(Line);
AttachToolTip(ReferingAxis.Chart, this, Line);
AttachHref(ReferingAxis.Chart, Line, Href, HrefTarget);
}
#endregion
#region Internal Events And Delegates
#endregion
#region Data
#endregion
}
}