//============================================================================
//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
//Copyright ?2004 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
//=============================================================================
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Runtime.Serialization;
using System.Security.Permissions;
namespace DrawGraph
{
///
/// A class that encapsulates color-fill properties for an object. The class
/// is used in , , ,
/// , and objects.
///
///
/// John Champion
/// $Revision: 3.22 $ $Date: 2007/01/26 09:01:49 $
[Serializable]
public class Fill : ISerializable, ICloneable
{
#region Fields
///
/// Private field that stores the fill color. Use the public
/// property to access this value. This property is
/// only applicable if the is not .
///
private Color _color;
///
/// Private field that stores the secondary color for gradientByValue fills. Use the public
/// property to access this value. This property is
/// only applicable if the is ,
/// , or .
///
private Color _secondaryValueGradientColor;
///
/// Private field that stores the custom fill brush. Use the public
/// property to access this value. This property is
/// only applicable if the
/// property is set to .
///
protected Brush _brush;
///
/// Private field that determines the type of color fill. Use the public
/// property to access this value. The fill color
/// is determined by the property or
/// .
///
private FillType _type;
///
/// Private field that determines if the brush will be scaled to the bounding box
/// of the filled object. If this value is false, then the brush will only be aligned
/// with the filled object based on the and
/// properties.
///
private bool _isScaled;
///
/// Private field that determines how the brush will be aligned with the filled object
/// in the horizontal direction. This value is a enumeration.
/// This field only applies if is false.
/// properties.
///
///
///
private AlignH _alignH;
///
/// Private field that determines how the brush will be aligned with the filled object
/// in the vertical direction. This value is a enumeration.
/// This field only applies if is false.
/// properties.
///
///
///
private AlignV _alignV;
private double _rangeMin;
private double _rangeMax;
private double _rangeDefault;
private Bitmap _gradientBM;
///
/// Private field that saves the image passed to the constructor.
/// This is used strictly for serialization.
///
private Image _image;
///
/// Private field that saves the image wrapmode passed to the constructor.
/// This is used strictly for serialization.
///
private WrapMode _wrapMode;
///
/// Private field that saves the list of colors used to create the
/// in the constructor. This is used strictly
/// for serialization.
///
private Color[] _colorList;
///
/// Private field that saves the list of positions used to create the
/// in the constructor. This is used strictly
/// for serialization.
///
private float[] _positionList;
///
/// Private field the saves the angle of the fill. This is used strictly for serialization.
///
private float _angle;
#endregion
#region Defaults
///
/// A simple struct that defines the
/// default property values for the class.
///
public struct Default
{
// Default Fill properties
///
/// The default scaling mode for fills.
/// This is the default value for the property.
///
public static bool IsScaled = true;
///
/// The default horizontal alignment for fills.
/// This is the default value for the property.
///
public static AlignH AlignH = AlignH.Center;
///
/// The default vertical alignment for fills.
/// This is the default value for the property.
///
public static AlignV AlignV = AlignV.Center;
}
#endregion
#region Constructors
///
/// Generic initializer to default values
///
private void Init()
{
_color = Color.White;
_secondaryValueGradientColor = Color.White;
_brush = null;
_type = FillType.None;
_isScaled = Default.IsScaled;
_alignH = Default.AlignH;
_alignV = Default.AlignV;
_rangeMin = 0.0;
_rangeMax = 1.0;
_rangeDefault = double.MaxValue;
_gradientBM = null;
_colorList = null;
_positionList = null;
_angle = 0;
_image = null;
_wrapMode = WrapMode.Tile;
}
///
/// The default constructor. Initialized to no fill.
///
public Fill()
{
Init();
}
///
/// Constructor that specifies the color, brush, and type for this fill.
///
/// The color of the fill for solid fills
/// A custom brush for fills. Can be a ,
/// , or .
/// The for this fill.
public Fill( Color color, Brush brush, FillType type )
{
Init();
_color = color;
_brush = brush;
_type = type;
}
///
/// Constructor that creates a solid color-fill, setting to
/// , and setting to the
/// specified color value.
///
/// The color of the solid fill
public Fill( Color color )
{
Init();
_color = color;
if ( color != Color.Empty )
_type = FillType.Solid;
}
///
/// Constructor that creates a linear gradient color-fill, setting to
/// using the specified colors and angle.
///
/// The first color for the gradient fill
/// The second color for the gradient fill
/// The angle (degrees) of the gradient fill
public Fill( Color color1, Color color2, float angle )
{
Init();
_color = color2;
ColorBlend blend = new ColorBlend( 2 );
blend.Colors[0] = color1;
blend.Colors[1] = color2;
blend.Positions[0] = 0.0f;
blend.Positions[1] = 1.0f;
_type = FillType.Brush;
this.CreateBrushFromBlend( blend, angle );
}
///
/// Constructor that creates a linear gradient color-fill, setting to
/// using the specified colors.
///
/// The first color for the gradient fill
/// The second color for the gradient fill
public Fill( Color color1, Color color2 ) : this( color1, color2, 0.0F )
{
}
///
/// Constructor that creates a linear gradient color-fill, setting to
/// using the specified colors. This gradient fill
/// consists of three colors.
///
/// The first color for the gradient fill
/// The second color for the gradient fill
/// The third color for the gradient fill
public Fill( Color color1, Color color2, Color color3 ) :
this( color1, color2, color3, 0.0f )
{
}
///
/// Constructor that creates a linear gradient color-fill, setting to
/// using the specified colors. This gradient fill
/// consists of three colors
///
/// The first color for the gradient fill
/// The second color for the gradient fill
/// The third color for the gradient fill
/// The angle (degrees) of the gradient fill
public Fill( Color color1, Color color2, Color color3, float angle )
{
Init();
_color = color3;
ColorBlend blend = new ColorBlend( 3 );
blend.Colors[0] = color1;
blend.Colors[1] = color2;
blend.Colors[2] = color3;
blend.Positions[0] = 0.0f;
blend.Positions[1] = 0.5f;
blend.Positions[2] = 1.0f;
_type = FillType.Brush;
this.CreateBrushFromBlend( blend, angle );
}
///
/// Constructor that creates a linear gradient multi-color-fill, setting to
/// using the specified colors. This gradient fill
/// consists of many colors based on a object. The gradient
/// angle is defaulted to zero.
///
/// The object that defines the colors
/// and positions along the gradient.
public Fill( ColorBlend blend ) :
this( blend, 0.0F )
{
}
///
/// Constructor that creates a linear gradient multi-color-fill, setting to
/// using the specified colors. This gradient fill
/// consists of many colors based on a object, drawn at the
/// specified angle (degrees).
///
/// The object that defines the colors
/// and positions along the gradient.
/// The angle (degrees) of the gradient fill
public Fill( ColorBlend blend, float angle )
{
Init();
_type = FillType.Brush;
this.CreateBrushFromBlend( blend, angle );
}
///
/// Constructor that creates a linear gradient multi-color-fill, setting to
/// using the specified colors. This gradient fill
/// consists of many colors based on an array of objects, drawn at an
/// angle of zero (degrees). The array is used to create
/// a object assuming a even linear distribution of the colors
/// across the gradient.
///
/// The array of objects that defines the colors
/// along the gradient.
public Fill( Color[] colors ) :
this( colors, 0.0F )
{
}
///
/// Constructor that creates a linear gradient multi-color-fill, setting to
/// using the specified colors. This gradient fill
/// consists of many colors based on an array of objects, drawn at the
/// specified angle (degrees). The array is used to create
/// a object assuming a even linear distribution of the colors
/// across the gradient.
///
/// The array of objects that defines the colors
/// along the gradient.
/// The angle (degrees) of the gradient fill
public Fill( Color[] colors, float angle )
{
Init();
_color = colors[ colors.Length - 1 ];
ColorBlend blend = new ColorBlend();
blend.Colors = colors;
blend.Positions = new float[colors.Length];
blend.Positions[0] = 0.0F;
for ( int i=1; i
/// Constructor that creates a linear gradient multi-color-fill, setting to
/// using the specified colors. This gradient fill
/// consists of many colors based on an array of objects, drawn at the
/// an angle of zero (degrees). The array is used to create
/// a object assuming a even linear distribution of the colors
/// across the gradient.
///
/// The array of objects that defines the colors
/// along the gradient.
/// The array of floating point values that defines the color
/// positions along the gradient. Values should range from 0 to 1.
public Fill( Color[] colors, float[] positions ) :
this( colors, positions, 0.0F )
{
}
///
/// Constructor that creates a linear gradient multi-color-fill, setting to
/// using the specified colors. This gradient fill
/// consists of many colors based on an array of objects, drawn at the
/// specified angle (degrees). The array is used to create
/// a object assuming a even linear distribution of the colors
/// across the gradient.
///
/// The array of objects that defines the colors
/// along the gradient.
/// The array of floating point values that defines the color
/// positions along the gradient. Values should range from 0 to 1.
/// The angle (degrees) of the gradient fill
public Fill( Color[] colors, float[] positions, float angle )
{
Init();
_color = colors[ colors.Length - 1 ];
ColorBlend blend = new ColorBlend();
blend.Colors = colors;
blend.Positions = positions;
_type = FillType.Brush;
this.CreateBrushFromBlend( blend, angle );
}
///
/// Constructor that creates a texture fill, setting to
/// and using the specified image.
///
/// The to use for filling
/// The class that controls the image wrapping properties
public Fill( Image image, WrapMode wrapMode )
{
Init();
_color = Color.White;
_brush = new TextureBrush( image, wrapMode );
_type = FillType.Brush;
_image = image;
_wrapMode = wrapMode;
}
///
/// Constructor that creates a fill, using a user-supplied, custom
/// . The brush will be scaled to fit the destination screen object
/// unless you manually change to false;
///
/// The to use for fancy fills. Typically, this would
/// be a or a class
public Fill( Brush brush ) : this( brush, Default.IsScaled )
{
}
///
/// Constructor that creates a fill, using a user-supplied, custom
/// . The brush will be scaled to fit the destination screen object
/// according to the parameter.
///
/// The to use for fancy fills. Typically, this would
/// be a or a class
/// Determines if the brush will be scaled to fit the bounding box
/// of the destination object. true to scale it, false to leave it unscaled
public Fill( Brush brush, bool isScaled )
{
Init();
_isScaled = isScaled;
_color = Color.White;
_brush = (Brush) brush.Clone();
_type = FillType.Brush;
}
///
/// Constructor that creates a fill, using a user-supplied, custom
/// . This constructor will make the brush unscaled (see ),
/// but it provides and parameters to control
/// alignment of the brush with respect to the filled object.
///
/// The to use for fancy fills. Typically, this would
/// be a or a class
/// Controls the horizontal alignment of the brush within the filled object
/// (see
/// Controls the vertical alignment of the brush within the filled object
/// (see
public Fill( Brush brush, AlignH alignH, AlignV alignV )
{
Init();
_alignH = alignH;
_alignV = alignV;
_isScaled = false;
_color = Color.White;
_brush = (Brush) brush.Clone();
_type = FillType.Brush;
}
///
/// The Copy Constructor
///
/// The Fill object from which to copy
public Fill( Fill rhs )
{
_color = rhs._color;
_secondaryValueGradientColor = rhs._color;
if ( rhs._brush != null )
_brush = (Brush) rhs._brush.Clone();
else
_brush = null;
_type = rhs._type;
_alignH = rhs.AlignH;
_alignV = rhs.AlignV;
_isScaled = rhs.IsScaled;
_rangeMin = rhs._rangeMin;
_rangeMax = rhs._rangeMax;
_rangeDefault = rhs._rangeDefault;
_gradientBM = null;
if ( rhs._colorList != null )
_colorList = (Color[]) rhs._colorList.Clone();
else
_colorList = null;
if ( rhs._positionList != null )
{
_positionList = (float[]) rhs._positionList.Clone();
}
else
_positionList = null;
if ( rhs._image != null )
_image = (Image) rhs._image.Clone();
else
_image = null;
_angle = rhs._angle;
_wrapMode = rhs._wrapMode;
}
///
/// 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 Fill Clone()
{
return new Fill( this );
}
private void CreateBrushFromBlend( ColorBlend blend, float angle )
{
_angle = angle;
_colorList = (Color[]) blend.Colors.Clone();
_positionList = (float[]) blend.Positions.Clone();
_brush = new LinearGradientBrush( new Rectangle( 0, 0, 100, 100 ),
Color.Red, Color.White, angle );
((LinearGradientBrush)_brush).InterpolationColors = blend;
}
#endregion
#region Serialization
///
/// Current schema value that defines the version of the serialized file
///
public const int schema = 10;
// schema changed to 2 with addition of rangeDefault
// schema changed to 10 with version 5 refactor -- not backwards compatible
///
/// Constructor for deserializing objects
///
/// A instance that defines the serialized data
///
/// A instance that contains the serialized data
///
protected Fill( SerializationInfo info, StreamingContext context )
{
Init();
// 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( "schema" );
_color = (Color) info.GetValue( "color", typeof(Color) );
_secondaryValueGradientColor = (Color) info.GetValue( "secondaryValueGradientColor", typeof( Color ) );
//brush = (Brush) info.GetValue( "brush", typeof(Brush) );
//brushHolder = (BrushHolder) info.GetValue( "brushHolder", typeof(BrushHolder) );
_type = (FillType) info.GetValue( "type", typeof(FillType) );
_isScaled = info.GetBoolean( "isScaled" );
_alignH = (AlignH) info.GetValue( "alignH", typeof(AlignH) );
_alignV = (AlignV) info.GetValue( "alignV", typeof(AlignV) );
_rangeMin = info.GetDouble( "rangeMin" );
_rangeMax = info.GetDouble( "rangeMax" );
//BrushHolder brushHolder = (BrushHolder) info.GetValue( "brushHolder", typeof( BrushHolder ) );
//brush = brush;
_colorList = (Color[]) info.GetValue( "colorList", typeof(Color[]) );
_positionList = (float[]) info.GetValue( "positionList", typeof(float[]) );
_angle = info.GetSingle( "angle" );
_image = (Image) info.GetValue( "image", typeof(Image) );
_wrapMode = (WrapMode) info.GetValue( "wrapMode", typeof(WrapMode) );
if ( _colorList != null && _positionList != null )
{
ColorBlend blend = new ColorBlend();
blend.Colors = _colorList;
blend.Positions = _positionList;
CreateBrushFromBlend( blend, _angle );
}
else if ( _image != null )
{
_brush = new TextureBrush( _image, _wrapMode );
}
_rangeDefault = info.GetDouble( "rangeDefault" );
}
///
/// 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 virtual void GetObjectData( SerializationInfo info, StreamingContext context )
{
info.AddValue( "schema", schema );
info.AddValue( "color", _color );
info.AddValue( "secondaryValueGradientColor", _secondaryValueGradientColor );
//info.AddValue( "brush", brush );
//info.AddValue( "brushHolder", brushHolder );
info.AddValue( "type", _type );
info.AddValue( "isScaled", _isScaled );
info.AddValue( "alignH", _alignH );
info.AddValue( "alignV", _alignV );
info.AddValue( "rangeMin", _rangeMin );
info.AddValue( "rangeMax", _rangeMax );
//BrushHolder brushHolder = new BrushHolder();
//brush = brush;
//info.AddValue( "brushHolder", brushHolder );
info.AddValue( "colorList", _colorList );
info.AddValue( "positionList", _positionList );
info.AddValue( "angle", _angle );
info.AddValue( "image", _image );
info.AddValue( "wrapMode", _wrapMode );
info.AddValue( "rangeDefault", _rangeDefault );
}
#endregion
#region Properties
///
/// The fill color. This property is used as a single color to make a solid fill
/// ( is ), or it can be used in
/// combination with to make a
///
/// when is and
/// is null.
///
///
public Color Color
{
get { return _color; }
set { _color = value; }
}
///
/// Gets or sets the secondary color for gradientByValue fills.
///
///
/// This property is only applicable if the is
/// ,
/// , or
/// . Once the gradient-by-value logic picks
/// a color, a new gradient will be created using the SecondaryValueGradientColor, the
/// resulting gradient-by-value color, and the angle setting for this
/// . Use a value of Color.Empty to have
/// a solid-color resulting from a gradient-by-value
/// .
///
public Color SecondaryValueGradientColor
{
get { return _secondaryValueGradientColor; }
set { _secondaryValueGradientColor = value; }
}
///
/// The custom fill brush. This can be a , a
/// , or a . This property is
/// only applicable if the property is set
/// to .
///
public Brush Brush
{
get { return _brush; }
set { _brush = value; }
}
///
/// Determines the type of fill, which can be either solid
/// color () or a custom brush
/// (). See for
/// more information.
///
///
public FillType Type
{
get { return _type; }
set { _type = value; }
}
///
/// This property determines the type of color fill.
/// Returns true if the property is either
/// or
/// . If set to true, this property
/// will automatically set the to
/// . If set to false, this property
/// will automatically set the to
/// . In order to get a regular
/// solid-color fill, you have to manually set
/// to .
///
///
///
///
public bool IsVisible
{
get { return _type != FillType.None; }
set { _type = value ? ( _type == FillType.None ? FillType.Brush : _type ) : FillType.None; }
}
///
/// Determines if the brush will be scaled to the bounding box
/// of the filled object. If this value is false, then the brush will only be aligned
/// with the filled object based on the and
/// properties.
///
public bool IsScaled
{
get { return _isScaled; }
set { _isScaled = value; }
}
///
/// Determines how the brush will be aligned with the filled object
/// in the horizontal direction. This value is a enumeration.
/// This field only applies if is false.
///
///
public AlignH AlignH
{
get { return _alignH; }
set { _alignH = value; }
}
///
/// Determines how the brush will be aligned with the filled object
/// in the vertical direction. This value is a enumeration.
/// This field only applies if is false.
///
///
public AlignV AlignV
{
get { return _alignV; }
set { _alignV = value; }
}
///
/// Returns a boolean value indicating whether or not this fill is a "Gradient-By-Value"
/// type. This is true for , ,
/// or .
///
///
/// The gradient by value fill method allows the fill color for each point or bar to
/// be based on a value for that point (either X, Y, or Z in the .
/// For example, assume a class is defined with a linear gradient ranging from
/// to and the
/// is set to . If is set to
/// 100.0 and is set to 200.0, then a point that has a Y value of
/// 100 or less will be colored blue, a point with a Y value of 200 or more will be
/// colored red, and a point between 100 and 200 will have a color based on a linear scale
/// between blue and red. Note that the fill color is always solid for any given point.
/// You can use the Z value from along with
/// to color individual points according to some
/// property that is independent of the X,Y point pair.
///
/// true if this is a Gradient-by-value type, false otherwise
///
///
///
public bool IsGradientValueType
{
get { return _type == FillType.GradientByX || _type == FillType.GradientByY ||
_type == FillType.GradientByZ || _type == FillType.GradientByColorValue; }
}
///
/// The minimum user-scale value for the gradient-by-value determination. This defines
/// the user-scale value for the start of the gradient.
///
///
///
///
///
///
///
/// A double value, in user scale unit
public double RangeMin
{
get { return _rangeMin; }
set { _rangeMin = value; }
}
///
/// The maximum user-scale value for the gradient-by-value determination. This defines
/// the user-scale value for the end of the gradient.
///
///
///
///
///
///
///
/// A double value, in user scale unit
public double RangeMax
{
get { return _rangeMax; }
set { _rangeMax = value; }
}
///
/// The default user-scale value for the gradient-by-value determination. This defines the
/// value that will be used when there is no point value available, or the actual point value
/// is invalid.
///
///
/// Note that this value, when defined, will determine the color that is used in the legend.
/// If this value is set to double.MaxValue, then it remains "undefined." In this case, the
/// legend symbols will actually be filled with a color gradient representing the range of
/// colors.
///
///
///
///
///
///
///
/// A double value, in user scale unit
public double RangeDefault
{
get { return _rangeDefault; }
set { _rangeDefault = value; }
}
#endregion
#region Methods
///
/// Create a fill brush using current properties. This method will construct a brush based on the
/// settings of ,
/// and . If
/// is set to and
///
/// is null, then a will be created between the colors of
/// and .
///
/// A rectangle that bounds the object to be filled. This determines
/// the start and end of the gradient fill.
/// A class representing the fill brush
public Brush MakeBrush( RectangleF rect )
{
// just provide a default value for the valueFraction
// return MakeBrush( rect, new PointPair( 0.5, 0.5, 0.5 ) );
return MakeBrush( rect, null );
}
///
/// Create a fill brush using current properties. This method will construct a brush based on the
/// settings of ,
/// and . If
/// is set to and
///
/// is null, then a will be created between the colors of
/// and .
///
/// A rectangle that bounds the object to be filled. This determines
/// the start and end of the gradient fill.
/// The data value to be used for a value-based
/// color gradient. This is only applicable for ,
/// or .
/// A class representing the fill brush
public Brush MakeBrush( RectangleF rect, PointPair dataValue )
{
// get a brush
if ( this.IsVisible && ( !_color.IsEmpty || _brush != null ) )
{
if ( rect.Height < 1.0F )
rect.Height = 1.0F;
if ( rect.Width < 1.0F )
rect.Width = 1.0F;
//Brush brush;
if ( _type == FillType.Brush )
{
return ScaleBrush( rect, _brush, _isScaled );
}
else if ( IsGradientValueType )
{
if ( dataValue != null )
{
if ( !_secondaryValueGradientColor.IsEmpty )
{
// Go ahead and create a new Fill so we can do all the scaling, etc.,
// that is associated with a gradient
Fill tmpFill = new Fill( _secondaryValueGradientColor,
GetGradientColor( dataValue ), _angle );
return tmpFill.MakeBrush( rect );
}
else
return new SolidBrush( GetGradientColor( dataValue ) );
}
else if ( _rangeDefault != double.MaxValue )
{
if ( !_secondaryValueGradientColor.IsEmpty )
{
// Go ahead and create a new Fill so we can do all the scaling, etc.,
// that is associated with a gradient
Fill tmpFill = new Fill( _secondaryValueGradientColor,
GetGradientColor( _rangeDefault ), _angle );
return tmpFill.MakeBrush( rect );
}
else
return new SolidBrush( GetGradientColor( _rangeDefault ) );
}
else
return ScaleBrush( rect, _brush, true );
}
else
return new SolidBrush( _color );
}
// Always return a suitable default
return new SolidBrush( Color.White );
}
internal Color GetGradientColor( PointPair dataValue )
{
double val;
if ( dataValue == null )
val = _rangeDefault;
else if ( _type == FillType.GradientByColorValue )
val = dataValue.ColorValue;
else if ( _type == FillType.GradientByZ )
val = dataValue.Z;
else if ( _type == FillType.GradientByY )
val = dataValue.Y;
else
val = dataValue.X;
return GetGradientColor( val );
}
internal Color GetGradientColor( double val )
{
double valueFraction;
if ( Double.IsInfinity( val ) || double.IsNaN( val ) || val == PointPair.Missing )
val = _rangeDefault;
if ( _rangeMax - _rangeMin < 1e-20 || val == double.MaxValue )
valueFraction = 0.5;
else
valueFraction = ( val - _rangeMin ) / ( _rangeMax - _rangeMin );
if ( valueFraction < 0.0 )
valueFraction = 0.0;
else if ( valueFraction > 1.0 )
valueFraction = 1.0;
if ( _gradientBM == null )
{
RectangleF rect = new RectangleF( 0, 0, 100, 1 );
_gradientBM = new Bitmap( 100, 1 );
Graphics gBM = Graphics.FromImage( _gradientBM );
Brush tmpBrush = ScaleBrush( rect, _brush, true );
gBM.FillRectangle( tmpBrush, rect );
}
return _gradientBM.GetPixel( (int) (99.9 * valueFraction), 0 );
}
private Brush ScaleBrush( RectangleF rect, Brush brush, bool isScaled )
{
if ( brush != null )
{
if ( brush is SolidBrush )
{
return (Brush) brush.Clone();
}
else if ( brush is LinearGradientBrush )
{
LinearGradientBrush linBrush = (LinearGradientBrush) brush.Clone();
if ( isScaled )
{
linBrush.ScaleTransform( rect.Width / linBrush.Rectangle.Width,
rect.Height / linBrush.Rectangle.Height, MatrixOrder.Append );
linBrush.TranslateTransform( rect.Left - linBrush.Rectangle.Left,
rect.Top - linBrush.Rectangle.Top, MatrixOrder.Append );
}
else
{
float dx = 0,
dy = 0;
switch ( _alignH )
{
case AlignH.Left:
dx = rect.Left - linBrush.Rectangle.Left;
break;
case AlignH.Center:
dx = ( rect.Left + rect.Width / 2.0F ) - linBrush.Rectangle.Left;
break;
case AlignH.Right:
dx = ( rect.Left + rect.Width ) - linBrush.Rectangle.Left;
break;
}
switch ( _alignV )
{
case AlignV.Top:
dy = rect.Top - linBrush.Rectangle.Top;
break;
case AlignV.Center:
dy = ( rect.Top + rect.Height / 2.0F ) - linBrush.Rectangle.Top;
break;
case AlignV.Bottom:
dy = ( rect.Top + rect.Height) - linBrush.Rectangle.Top;
break;
}
linBrush.TranslateTransform( dx, dy, MatrixOrder.Append );
}
return linBrush;
} // LinearGradientBrush
else if ( brush is TextureBrush )
{
TextureBrush texBrush = (TextureBrush) brush.Clone();
if ( isScaled )
{
texBrush.ScaleTransform( rect.Width / texBrush.Image.Width,
rect.Height / texBrush.Image.Height, MatrixOrder.Append );
texBrush.TranslateTransform( rect.Left, rect.Top, MatrixOrder.Append );
}
else
{
float dx = 0,
dy = 0;
switch ( _alignH )
{
case AlignH.Left:
dx = rect.Left;
break;
case AlignH.Center:
dx = ( rect.Left + rect.Width / 2.0F );
break;
case AlignH.Right:
dx = ( rect.Left + rect.Width );
break;
}
switch ( _alignV )
{
case AlignV.Top:
dy = rect.Top;
break;
case AlignV.Center:
dy = ( rect.Top + rect.Height / 2.0F );
break;
case AlignV.Bottom:
dy = ( rect.Top + rect.Height);
break;
}
texBrush.TranslateTransform( dx, dy, MatrixOrder.Append );
}
return texBrush;
}
else // other brush type
{
return (Brush) brush.Clone();
}
}
else
// If they didn't provide a brush, make one using the fillcolor gradient to white
return new LinearGradientBrush( rect, Color.White, _color, 0F );
}
///
/// Fill the background of the area, using the
/// fill type from this .
///
///
/// A graphic device object to be drawn into. This is normally e.Graphics from the
/// PaintEventArgs argument to the Paint() method.
///
/// The struct specifying the area
/// to be filled
public void Draw( Graphics g, RectangleF rect )
{
Draw( g, rect, null );
/*
if ( this.IsVisible )
{
using( Brush brush = this.MakeBrush( rect ) )
{
g.FillRectangle( brush, rect );
//brush.Dispose();
}
}
*/
}
///
/// Fill the background of the area, using the
/// fill type from this .
///
///
/// A graphic device object to be drawn into. This is normally e.Graphics from the
/// PaintEventArgs argument to the Paint() method.
///
/// The struct specifying the area
/// to be filled
/// The data value to be used in case it's a
/// , , or
/// .
public void Draw( Graphics g, RectangleF rect, PointPair pt )
{
if ( this.IsVisible )
{
using ( Brush brush = this.MakeBrush( rect, pt ) )
{
g.FillRectangle( brush, rect );
}
}
}
#endregion
}
}