//============================================================================
//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
//Copyright ?2006 John Champion
//
//This library is free software; you can redistribute it and/or
//modify it under the terms of the GNU Lesser General Public
//License as published by the Free Software Foundation; either
//version 2.1 of the License, or (at your option) any later version.
//
//This library is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
//Lesser General Public License for more details.
//
//You should have received a copy of the GNU Lesser General Public
//License along with this library; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//=============================================================================
#region Using directives
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Runtime.Serialization;
using System.Security.Permissions;
#endregion
namespace DrawGraph
{
///
/// This class handles the drawing of the curve objects.
///
///
/// John Champion
/// $Revision: 3.10 $ $Date: 2007/04/16 00:03:02 $
[Serializable]
public class JapaneseCandleStick : OHLCBar, ICloneable, ISerializable
{
#region Fields
///
/// Private field to store the class to be used for filling the
/// candlestick "bars" when the value is greater than
/// the value. See the public property
/// to access this value.
///
private Fill _risingFill;
///
/// Private field to store the class to be used for filling the
/// candlestick "bars" when the value is less than
/// the value. See the public property
/// to access this value.
///
private Fill _fallingFill;
///
/// Private field to store the class to be used for drawing the
/// candlestick "bars" when the value is greater than
/// the value. See the public property
/// to access this value.
///
private Border _risingBorder;
///
/// Private field to store the class to be used for drawing the
/// candlestick "bars" when the value is less than
/// the value. See the public property
/// to access this value.
///
private Border _fallingBorder;
///
/// Private field that stores the CandleStick color when the
/// value is less than the value. Use the public
/// property to access this value.
///
protected Color _fallingColor;
#endregion
#region Defaults
///
/// A simple struct that defines the
/// default property values for the class.
///
public new struct Default
{
///
/// The default fillcolor for drawing the rising case CandleSticks
/// ( property).
///
public static Color RisingColor = Color.White;
///
/// The default fillcolor for drawing the falling case CandleSticks
/// ( property).
///
public static Color FallingColor = Color.Black;
///
/// The default color for the border of the rising CandleSticks
/// ( property).
///
public static Color RisingBorder = Color.Black;
///
/// The default color for the border of the falling CandleSticks
/// ( property).
///
public static Color FallingBorder = Color.Black;
}
#endregion
#region Properties
///
/// Gets or sets the class that is used to fill the candlestick
/// "bars" when the value is greater than the
/// value.
///
public Fill RisingFill
{
get { return _risingFill; }
set { _risingFill = value; }
}
///
/// Gets or sets the class that is used to fill the candlestick
/// "bars" when the value is less than the
/// value.
///
public Fill FallingFill
{
get { return _fallingFill; }
set { _fallingFill = value; }
}
///
/// The instance to be used for drawing the border frame of
/// the candlestick "bars" when the value is greater than the
/// value.
///
public Border RisingBorder
{
get { return _risingBorder; }
set { _risingBorder = value; }
}
///
/// The instance to be used for drawing the border frame of
/// the candlestick "bars" when the value is less than the
/// value.
///
public Border FallingBorder
{
get { return _fallingBorder; }
set { _fallingBorder = value; }
}
///
/// Gets or sets the data for this
/// when the value of the candlestick is
/// falling.
///
/// This property only controls the color of
/// the vertical line when the value is falling. The rising color is controlled
/// by the property.
///
public Color FallingColor
{
get { return _fallingColor; }
set { _fallingColor = value; }
}
#endregion
#region Constructors
///
/// Default constructor that sets all properties to
/// default values as defined in the class.
///
public JapaneseCandleStick() : base()
{
_risingFill = new Fill( Default.RisingColor );
_fallingFill = new Fill( Default.FallingColor );
_risingBorder = new Border( Default.RisingBorder, LineBase.Default.Width );
_fallingBorder = new Border( Default.FallingBorder, LineBase.Default.Width );
_fallingColor = Default.FallingColor;
}
///
/// The Copy Constructor
///
/// The object from which to copy
public JapaneseCandleStick( JapaneseCandleStick rhs ) : base( rhs )
{
_risingFill = rhs._risingFill.Clone();
_fallingFill = rhs._fallingFill.Clone();
_risingBorder = rhs._risingBorder.Clone();
_fallingBorder = rhs._fallingBorder.Clone();
_fallingColor = rhs._fallingColor;
}
///
/// Implement the interface in a typesafe manner by just
/// calling the typed version of
///
/// A deep copy of this object
object ICloneable.Clone()
{
return this.Clone();
}
///
/// Typesafe, deep-copy clone method.
///
/// A new, independent copy of this class
public new JapaneseCandleStick Clone()
{
return new JapaneseCandleStick( this );
}
#endregion
#region Serialization
///
/// Current schema value that defines the version of the serialized file
///
public const int schema2 = 11;
///
/// Constructor for deserializing objects
///
/// A instance that defines the serialized data
///
/// A instance that contains the serialized data
///
protected JapaneseCandleStick( SerializationInfo info, StreamingContext context ) :
base( info, context )
{
// The schema value is just a file version parameter. You can use it to make future versions
// backwards compatible as new member variables are added to classes
int sch = info.GetInt32( "schema2" );
_risingFill = (Fill)info.GetValue( "risingFill", typeof( Fill ) );
_fallingFill = (Fill)info.GetValue( "fallingFill", typeof( Fill ) );
_risingBorder = (Border)info.GetValue( "risingBorder", typeof( Border ) );
_fallingBorder = (Border)info.GetValue( "fallingBorder", typeof( Border ) );
if ( schema2 >= 11 )
_fallingColor = (Color) info.GetValue( "fallingColor", typeof( Color ) );
}
///
/// Populates a instance with the data needed to serialize the target object
///
/// A instance that defines the serialized data
/// A instance that contains the serialized data
[SecurityPermissionAttribute( SecurityAction.Demand, SerializationFormatter = true )]
public override void GetObjectData( SerializationInfo info, StreamingContext context )
{
base.GetObjectData( info, context );
info.AddValue( "schema2", schema2 );
info.AddValue( "risingFill", _risingFill );
info.AddValue( "fallingFill", _fallingFill );
info.AddValue( "risingBorder", _risingBorder );
info.AddValue( "fallingBorder", _fallingBorder );
info.AddValue( "fallingColor", _fallingColor );
}
#endregion
#region Rendering Methods
///
/// Draw the to the specified
/// device at the specified location.
///
///
/// A graphic device object to be drawn into. This is normally e.Graphics from the
/// PaintEventArgs argument to the Paint() method.
///
///
/// A reference to the object that is the parent or
/// owner of this object.
///
/// boolean value that indicates if the "base" axis for this
/// is the X axis. True for an base,
/// false for a or base.
/// The independent axis position of the center of the candlestick in
/// pixel units
/// The high value position of the candlestick in
/// pixel units
/// The low value position of the candlestick in
/// pixel units
/// The opening value position of the candlestick in
/// pixel units
/// The closing value position of the candlestick in
/// pixel units
/// The scaled width of one-half of a bar, in pixels
///
/// The scaling factor for the features of the graph based on the . This
/// scaling factor is calculated by the method. The scale factor
/// represents a linear multiple to be applied to font sizes, symbol sizes, etc.
/// A pen with the attribute for this
///
///
/// The instance to be used for filling this
///
///
/// The instance to be used for drawing the
/// border around the filled box
/// The to be used for determining the
/// , just in case it's a ,
/// , or
///
public void Draw( Graphics g, GraphPane pane, bool isXBase,
float pixBase, float pixHigh, float pixLow,
float pixOpen, float pixClose, float halfSize,
float scaleFactor, Pen pen, Fill fill, Border border, PointPair pt )
{
//float halfSize = (int) ( _size * scaleFactor / 2.0f + 0.5f );
if ( pixBase != PointPair.Missing && Math.Abs( pixLow ) < 1000000 &&
Math.Abs( pixHigh ) < 1000000)
{
RectangleF rect;
if ( isXBase )
{
rect = new RectangleF( pixBase - halfSize, Math.Min( pixOpen, pixClose ),
halfSize * 2.0f, Math.Abs( pixOpen - pixClose ) );
g.DrawLine( pen, pixBase, pixHigh, pixBase, pixLow );
}
else
{
rect = new RectangleF( Math.Min( pixOpen, pixClose ), pixBase - halfSize,
Math.Abs( pixOpen - pixClose ), halfSize * 2.0f );
g.DrawLine( pen, pixHigh, pixBase, pixLow, pixBase );
}
if ( _isOpenCloseVisible && Math.Abs( pixOpen ) < 1000000 &&
Math.Abs( pixClose ) < 1000000 )
{
if ( rect.Width == 0 )
rect.Width = 1;
if ( rect.Height == 0 )
rect.Height = 1;
fill.Draw( g, rect, pt );
border.Draw( g, pane, scaleFactor, rect );
}
}
}
///
/// Draw all the 's to the specified
/// device as a candlestick at each defined point.
///
///
/// A graphic device object to be drawn into. This is normally e.Graphics from the
/// PaintEventArgs argument to the Paint() method.
///
///
/// A reference to the object that is the parent or
/// owner of this object.
///
/// A object representing the
/// 's to be drawn.
/// The class instance that defines the base (independent)
/// axis for the
/// The class instance that defines the value (dependent)
/// axis for the
///
/// The scaling factor to be used for rendering objects. This is calculated and
/// passed down by the parent object using the
/// method, and is used to proportionally adjust
/// font sizes, etc. according to the actual size of the graph.
///
public void Draw( Graphics g, GraphPane pane, JapaneseCandleStickItem curve,
Axis baseAxis, Axis valueAxis, float scaleFactor )
{
//ValueHandler valueHandler = new ValueHandler( pane, false );
float pixBase, pixHigh, pixLow, pixOpen, pixClose;
if ( curve.Points != null )
{
//float halfSize = _size * scaleFactor;
float halfSize = GetBarWidth( pane, baseAxis, scaleFactor );
Color tColor = _color;
Color tFallingColor = _fallingColor;
float tPenWidth = _width;
Fill tRisingFill = _risingFill;
Fill tFallingFill = _fallingFill;
Border tRisingBorder = _risingBorder;
Border tFallingBorder = _fallingBorder;
if ( curve.IsSelected )
{
tColor = Selection.Border.Color;
tFallingColor = Selection.Border.Color;
tPenWidth = Selection.Border.Width;
tRisingFill = Selection.Fill;
tFallingFill = Selection.Fill;
tRisingBorder = Selection.Border;
tFallingBorder = Selection.Border;
}
using ( Pen risingPen = new Pen( tColor, tPenWidth ) )
using ( Pen fallingPen = new Pen( tFallingColor, tPenWidth ) )
{
// Loop over each defined point
for ( int i = 0; i < curve.Points.Count; i++ )
{
PointPair pt = curve.Points[i];
double date = pt.X;
double high = pt.Y;
double low = pt.Z;
double open = PointPair.Missing;
double close = PointPair.Missing;
if ( pt is StockPt )
{
open = ( pt as StockPt ).Open;
close = ( pt as StockPt ).Close;
}
// Any value set to double max is invalid and should be skipped
// This is used for calculated values that are out of range, divide
// by zero, etc.
// Also, any value <= zero on a log scale is invalid
if ( !curve.Points[i].IsInvalid3D &&
( date > 0 || !baseAxis._scale.IsLog ) &&
( ( high > 0 && low > 0 ) || !valueAxis._scale.IsLog ) )
{
pixBase = (int) ( baseAxis.Scale.Transform( curve.IsOverrideOrdinal, i, date ) + 0.5 );
//pixBase = baseAxis.Scale.Transform( curve.IsOverrideOrdinal, i, date );
pixHigh = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, i, high );
pixLow = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, i, low );
if ( PointPair.IsValueInvalid( open ) )
pixOpen = Single.MaxValue;
else
pixOpen = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, i, open );
if ( PointPair.IsValueInvalid( close ) )
pixClose = Single.MaxValue;
else
pixClose = valueAxis.Scale.Transform( curve.IsOverrideOrdinal, i, close );
if ( !curve.IsSelected && this._gradientFill.IsGradientValueType )
{
using ( Pen tPen = GetPen( pane, scaleFactor, pt ) )
Draw( g, pane, baseAxis is XAxis || baseAxis is X2Axis,
pixBase, pixHigh, pixLow, pixOpen,
pixClose, halfSize, scaleFactor,
( tPen ),
( close > open ? tRisingFill : tFallingFill ),
( close > open ? tRisingBorder : tFallingBorder ), pt );
}
else
Draw( g, pane, baseAxis is XAxis || baseAxis is X2Axis,
pixBase, pixHigh, pixLow, pixOpen,
pixClose, halfSize, scaleFactor,
( close > open ? risingPen : fallingPen ),
( close > open ? tRisingFill : tFallingFill ),
( close > open ? tRisingBorder : tFallingBorder ), pt );
}
}
}
}
}
#endregion
}
}