//============================================================================
//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.Runtime.Serialization;
using System.Security.Permissions;
namespace DrawGraph
{
	/// 
	/// This class encapsulates the chart  that is displayed
	/// in the 
	/// 
	/// 
	///  John Champion 
	///  $Revision: 3.38 $ $Date: 2007/03/11 02:08:16 $ 
	[Serializable]
	public class Legend : ICloneable, ISerializable
	{
	#region private Fields
	
		///  Private field to hold the bounding rectangle around the legend.
		/// This bounding rectangle varies with the number of legend entries, font sizes,
		/// etc., and is re-calculated by  at each redraw.
		/// Use the public readonly property  to access this
		/// rectangle.
		/// 
		private RectangleF	_rect;
		/// Private field to hold the legend location setting.  This field
		/// contains the  enum type to specify the area of
		/// the graph where the legend will be positioned.  Use the public property
		///  to access this value.
		/// 
		/// 
		private LegendPos	_position;
		/// 
		/// Private field to enable/disable horizontal stacking of the legend entries.
		/// If this value is false, then the legend entries will always be a single column.
		/// Use the public property  to access this value.
		/// 
		/// 
		private bool		_isHStack;
		/// 
		/// Private field to enable/disable drawing of the entire legend.
		/// If this value is false, then the legend will not be drawn.
		/// Use the public property  to access this value.
		/// 
		private bool		_isVisible;
		/// 
		/// Private field that stores the  data for this
		/// .  Use the public property  to
		/// access this value.
		/// 
		private Fill		_fill;
		/// 
		/// Private field that stores the  data for this
		/// .  Use the public property  to
		/// access this value.
		/// 
		private Border		_border;		
		/// 
		/// Private field to maintain the  class that
		/// maintains font attributes for the entries in this legend.  Use
		/// the  property to access this class.
		/// 
		private FontSpec	_fontSpec;
		/// 
		/// Private field to maintain the  location.  This object
		/// is only applicable if the  property is set to
		/// .
		/// 
		private Location	_location;
		/// 
		/// Private temporary field to maintain the number of columns (horizontal stacking) to be used
		/// for drawing the .  This value is only valid during a draw operation.
		/// 
		private int			_hStack;
		/// 
		/// Private temporary field to maintain the width of each column in the
		/// .  This value is only valid during a draw operation.
		/// 
		private float		_legendItemWidth;
		/// 
		/// Private temporary field to maintain the height of each row in the
		/// .  This value is only valid during a draw operation.
		/// 
		private float		_legendItemHeight;
		/// 
		/// Private field to store the gap between the legend and the chart rectangle.
		/// 
		private float _gap;
		// CJBL
		/// 
		/// Private field to select output order of legend entries.
		/// 
		private bool _isReverse;
		/// 
		/// Private temporary field to maintain the characteristic "gap" for the legend.
		/// This is normal the height of the largest font in the legend.
		/// This value is only valid during a draw operation.
		/// 
		private float		_tmpSize;
	#endregion
	#region Defaults
		/// 
		/// A simple struct that defines the
		/// default property values for the  class.
		/// 
		public struct Default
		{
			// Default Legend properties
			/// 
			/// The default pen width for the  border border.
			/// ( property).  Units are in pixels.
			/// 
			public static float BorderWidth = 1;
			/// 
			/// The default color for the  border border.
			/// ( property). 
			/// 
			public static Color BorderColor = Color.Black;
			/// 
			/// The default color for the  background.
			/// ( property).  Use of this
			/// color depends on the status of the 
			/// property.
			/// 
			public static Color FillColor = Color.White;
			/// 
			/// The default custom brush for filling in this .
			/// 
			public static Brush FillBrush = null;
			/// 
			/// The default fill mode for the  background.
			/// 
			public static FillType FillType = FillType.Brush;
			/// 
			/// The default location for the  on the graph
			/// ( property).  This property is
			/// defined as a  enumeration.
			/// 
			public static LegendPos Position = LegendPos.Top;
			/// 
			/// The default border mode for the .
			/// ( property). true
			/// to draw a border around the ,
			/// false otherwise.
			/// 
			public static bool IsBorderVisible = true;
			/// 
			/// The default display mode for the .
			/// ( property). true
			/// to show the legend,
			/// false to hide it.
			/// 
			public static bool IsVisible = true;
			/// 
			/// The default fill mode for the  background
			/// ( property).
			/// true to fill-in the background with color,
			/// false to leave the background transparent.
			/// 
			public static bool IsFilled = true;
			/// 
			/// The default horizontal stacking mode for the 
			/// ( property).
			/// true to allow horizontal legend item stacking, false to allow
			/// only vertical legend orientation.
			/// 
			public static bool IsHStack = true;
			/// 
			/// The default font family for the  entries
			/// ( property).
			/// 
			public static string FontFamily = "Arial";
			/// 
			/// The default font size for the  entries
			/// ( property).  Units are
			/// in points (1/72 inch).
			/// 
			public static float FontSize = 12;
			/// 
			/// The default font color for the  entries
			/// ( property).
			/// 
			public static Color FontColor = Color.Black;
			/// 
			/// The default font bold mode for the  entries
			/// ( property). true
			/// for a bold typeface, false otherwise.
			/// 
			public static bool FontBold = false;
			/// 
			/// The default font italic mode for the  entries
			/// ( property). true
			/// for an italic typeface, false otherwise.
			/// 
			public static bool FontItalic = false;
			/// 
			/// The default font underline mode for the  entries
			/// ( property). true
			/// for an underlined typeface, false otherwise.
			/// 
			public static bool FontUnderline = false;
			/// 
			/// The default color for filling in the scale text background
			/// (see  property).
			/// 
			public static Color FontFillColor = Color.White;
			/// 
			/// The default custom brush for filling in the scale text background
			/// (see  property).
			/// 
			public static Brush FontFillBrush = null;
			/// 
			/// The default fill mode for filling in the scale text background
			/// (see  property).
			/// 
			public static FillType FontFillType = FillType.None;
			/// 
			/// The default gap size between the legend and the .
			/// This is the default value of .
			/// 
			public static float Gap = 0.5f;
			/// 
			/// Default value for the  property.
			/// 
			public static bool IsReverse = false;
		}
	#endregion
	#region Properties
		/// 
		/// Get the bounding rectangle for the  in screen coordinates
		/// 
		/// A screen rectangle in pixel units
		public RectangleF Rect
		{
			get { return _rect; }
		}
		/// 
		/// Access to the  class used to render
		/// the  entries
		/// 
		/// A reference to a  object
		/// 
		/// 
		/// 
		/// 
		/// 
		/// 
		public FontSpec FontSpec
		{
			get { return _fontSpec; }
			set
			{
				if ( value == null )
					throw new ArgumentNullException( "Uninitialized FontSpec in Legend" );
				_fontSpec = value;
			}
		}
		/// 
		/// Gets or sets a property that shows or hides the  entirely
		/// 
		///  true to show the , false to hide it 
		/// 
		public bool IsVisible
		{
			get { return _isVisible; }
			set { _isVisible = value; }
		}
		/// 
		/// The  class used to draw the border border around this .
		/// 
		public Border Border
		{
			get { return _border; }
			set { _border = value; }
		}		
		/// 
		/// Gets or sets the  data for this
		///  background.
		/// 
		public Fill	Fill
		{
			get { return _fill; }
			set { _fill = value; }
		}
		
		/// 
		/// Sets or gets a property that allows the  items to
		/// stack horizontally in addition to the vertical stacking
		/// 
		/// true to allow horizontal stacking, false otherwise
		/// 
		/// 
		public bool IsHStack
		{
			get { return _isHStack; }
			set { _isHStack = value; }
		}
		/// 
		/// Sets or gets the location of the  on the
		///  using the  enum type
		/// 
		/// 
		public LegendPos Position
		{
			get { return _position; }
			set { _position = value; }
		}
		/// 
		/// Gets or sets the  data for the .
		/// This property is only applicable if  is set
		/// to .
		/// 
		public Location Location
		{
			get { return _location; }
			set { _location = value; }
		}
		/// 
		/// Gets or sets the gap size between the legend and the .
		/// 
		/// 
		/// This is expressed as a fraction of the largest scaled character height for any
		/// of the fonts used in the legend.  Each  in the legend can
		/// optionally have its own  specification.
		/// 
		public float Gap
		{
			get { return _gap; }
			set { _gap = value; }
		}
		/// 
		/// Gets or sets a value that determines if the legend entries are displayed in normal order
		/// (matching the order in the , or in reverse order.
		/// 
		public bool IsReverse
		{
			get { return _isReverse; }
			set { _isReverse = value; }
		}
	#endregion
	#region Constructors
		/// 
		/// Default constructor that sets all  properties to default
		/// values as defined in the  class.
		/// 
		public Legend()
		{
			_position = Default.Position;
			_isHStack = Default.IsHStack;
			_isVisible = Default.IsVisible;
			this.Location = new Location( 0, 0, CoordType.PaneFraction );
			
			_fontSpec = new FontSpec( Default.FontFamily, Default.FontSize,
				Default.FontColor, Default.FontBold,
				Default.FontItalic, Default.FontUnderline,
				Default.FontFillColor, Default.FontFillBrush,
				Default.FontFillType );						
			_fontSpec.Border.IsVisible = false;
			
			_border = new Border( Default.IsBorderVisible, Default.BorderColor, Default.BorderWidth );
			_fill = new Fill( Default.FillColor, Default.FillBrush, Default.FillType );
			_gap = Default.Gap;
			_isReverse = Default.IsReverse;
		}
		/// 
		/// The Copy Constructor
		/// 
		/// The XAxis object from which to copy
		public Legend( Legend rhs )
		{
			_rect = rhs.Rect;
			_position = rhs.Position;
			_isHStack = rhs.IsHStack;
			_isVisible = rhs.IsVisible;
			
			_location = rhs.Location;
			_border = rhs.Border.Clone();
			_fill = rhs.Fill.Clone();
			
			_fontSpec = rhs.FontSpec.Clone();
			_gap = rhs._gap;
			_isReverse = rhs._isReverse;
		}
		/// 
		/// 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 Legend Clone()
		{
			return new Legend( this );
		}
		#endregion
	#region Serialization
		/// 
		/// Current schema value that defines the version of the serialized file
		/// 
		public const int schema = 11;
		/// 
		/// Constructor for deserializing objects
		/// 
		/// A  instance that defines the serialized data
		/// 
		/// A  instance that contains the serialized data
		/// 
		protected Legend( SerializationInfo info, StreamingContext 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( "schema" );
			_position = (LegendPos) info.GetValue( "position", typeof(LegendPos) );
			_isHStack = info.GetBoolean( "isHStack" );
			_isVisible = info.GetBoolean( "isVisible" );
			_fill = (Fill) info.GetValue( "fill", typeof(Fill) );
			_border = (Border) info.GetValue( "border", typeof(Border) );
			_fontSpec = (FontSpec) info.GetValue( "fontSpec", typeof(FontSpec) );
			_location = (Location) info.GetValue( "location", typeof(Location) );
			_gap = info.GetSingle( "gap" );
			if ( schema >= 11 )
				_isReverse = info.GetBoolean( "isReverse" );
		}
		/// 
		/// 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( "position", _position );
			info.AddValue( "isHStack", _isHStack );
			info.AddValue( "isVisible", _isVisible );
			info.AddValue( "fill", _fill );
			info.AddValue( "border", _border );
			info.AddValue( "fontSpec", _fontSpec );
			info.AddValue( "location", _location );
			info.AddValue( "gap", _gap );
			info.AddValue( "isReverse", _isReverse );
		}
	#endregion
	#region Rendering Methods
		/// 
		/// Render the  to the specified  device.
		/// 
		/// 
		/// This method is normally only called by the Draw method
		/// of the parent  object.
		/// 
		/// 
		/// 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.
		/// 
		/// 
		/// 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, PaneBase pane, float scaleFactor )
		{
			// if the legend is not visible, do nothing
			if ( ! _isVisible )
				return;
								
			// Fill the background with the specified color if required
			_fill.Draw( g, _rect );
		
			PaneList paneList = GetPaneList( pane );
			float halfGap = _tmpSize / 2.0F;
			// Check for bad data values
			if ( _hStack <= 0 )
				_hStack = 1;
			if ( _legendItemWidth <= 0 )
				_legendItemWidth = 100;
			if ( _legendItemHeight <= 0 )
				_legendItemHeight = _tmpSize;
			//float gap = pane.ScaledGap( scaleFactor );
			int		iEntry = 0;
			float	x, y;
			
			// Get a brush for the legend label text
			using ( SolidBrush brushB = new SolidBrush( Color.Black ) )
			{
				foreach ( GraphPane tmpPane in paneList )
				{
					// Loop for each curve in the CurveList collection
					//foreach ( CurveItem curve in tmpPane.CurveList )
					int count = tmpPane.CurveList.Count;
					for ( int i = 0; i < count; i++ )
					{
						CurveItem curve = tmpPane.CurveList[_isReverse ? count - i - 1 : i];
						if ( curve._label._text != "" && curve._label._isVisible )
						{
							// Calculate the x,y (TopLeft) location of the current
							// curve legend label
							// assuming:
							//  charHeight/2 for the left margin, plus legendWidth for each
							//    horizontal column
							//  legendHeight is the line spacing, with no extra margin above
							x = _rect.Left + halfGap / 2.0F +
								( iEntry % _hStack ) * _legendItemWidth;
							y = _rect.Top + (int)( iEntry / _hStack ) * _legendItemHeight;
							// Draw the legend label for the current curve
							FontSpec tmpFont = ( curve._label._fontSpec != null ) ?
										curve._label._fontSpec : this.FontSpec;
							// This is required because, for long labels, the centering can affect the
							// position in GDI+.
							tmpFont.StringAlignment = StringAlignment.Near;
							tmpFont.Draw( g, pane, curve._label._text,
									x + 2.5F * _tmpSize, y + _legendItemHeight / 2.0F,
									AlignH.Left, AlignV.Center, scaleFactor );
							RectangleF rect = new RectangleF( x, y + _legendItemHeight / 4.0F,
								2 * _tmpSize, _legendItemHeight / 2.0F );
							curve.DrawLegendKey( g, tmpPane, rect, scaleFactor );
							// maintain a curve count for positioning
							iEntry++;
						}
					}
					if ( pane is MasterPane && ( (MasterPane)pane ).IsUniformLegendEntries )
						break;
				}
				// Draw a border around the legend if required
				if ( iEntry > 0 )
					this.Border.Draw( g, pane, scaleFactor, _rect );
			}
		}
		private float GetMaxHeight( PaneList paneList, Graphics g, float scaleFactor )
		{
			// Set up some scaled dimensions for calculating sizes and locations
			float defaultCharHeight = this.FontSpec.GetHeight( scaleFactor );
			float maxCharHeight = defaultCharHeight;
			// Find the largest charHeight, just in case the curves have individual fonts defined
			foreach ( GraphPane tmpPane in paneList )
			{
				foreach ( CurveItem curve in tmpPane.CurveList )
				{
					if ( curve._label._text != string.Empty && curve._label._isVisible )
					{
						float tmpHeight = defaultCharHeight;
						if ( curve._label._fontSpec != null )
							tmpHeight = curve._label._fontSpec.GetHeight( scaleFactor );
						// Account for multiline legend entries
						tmpHeight *= curve._label._text.Split( '\n' ).Length;
						if ( tmpHeight > maxCharHeight )
							maxCharHeight = tmpHeight;
					}
				}
			}
			return maxCharHeight;
		}
		/// 
		/// Determine if a mouse point is within the legend, and if so, which legend
		/// entry () is nearest.
		/// 
		/// The screen point, in pixel coordinates.
		/// 
		/// A reference to the  object that is the parent or
		/// owner of this object.
		/// 
		/// 
		/// 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.
		/// 
		/// The index number of the  legend
		/// entry that is under the mouse point.  The  object is
		/// accessible via CurveList[index].
		/// 
		/// true if the mouse point is within the  bounding
		/// box, false otherwise.
		/// 
		public bool FindPoint( PointF mousePt, PaneBase pane, float scaleFactor, out int index )
		{
			index = -1;
			
			if ( _rect.Contains( mousePt ) )
			{
				int j = (int) ( ( mousePt.Y - _rect.Top ) / _legendItemHeight );
				int i = (int) ( ( mousePt.X - _rect.Left - _tmpSize / 2.0f ) / _legendItemWidth );
				if ( i < 0 )
					i = 0;
				if ( i >= _hStack )
					i = _hStack - 1;
					
				int pos = i + j * _hStack;
				index = 0;
				PaneList paneList = GetPaneList( pane );
				foreach ( GraphPane tmpPane in paneList )
				{
					foreach ( CurveItem curve in tmpPane.CurveList )
					{
						if ( curve._label._isVisible && curve._label._text != string.Empty )
						{
							if ( pos == 0 )
								return true;
							pos--;
						}
						index++;
					}
				}
				return true;
			}
			else
				return false;
		}
		
		private PaneList GetPaneList( PaneBase pane )
		{
			// For a single GraphPane, create a PaneList to contain it
			// Otherwise, just use the paneList from the MasterPane
			PaneList paneList;
			
			if ( pane is GraphPane )
			{
				paneList = new PaneList();
				paneList.Add( (GraphPane) pane );
			}
			else
				paneList = ((MasterPane)pane).PaneList;
			
			return paneList;
		}
		/// 
		/// Calculate the  rectangle (),
		/// taking into account the number of required legend
		/// entries, and the legend drawing preferences.
		/// 
		/// Adjust the size of the
		///  for the parent  to accomodate the
		/// space required by the legend.
		/// 
		/// 
		/// 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.
		/// 
		/// 
		/// 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.
		/// 
		/// 
		/// The rectangle that contains the area bounded by the axes, in pixel units.
		/// 
		/// 
		public void CalcRect( Graphics g, PaneBase pane, float scaleFactor,
			ref RectangleF tChartRect )
		{
			// Start with an empty rectangle
			_rect = Rectangle.Empty;
			_hStack = 1;
			_legendItemWidth = 1;
			_legendItemHeight = 0;
			RectangleF clientRect = pane.CalcClientRect( g, scaleFactor );
				
			// If the legend is invisible, don't do anything
			if ( !_isVisible )
				return;
		
			int		nCurve = 0;
			PaneList paneList = GetPaneList( pane );
			_tmpSize = GetMaxHeight( paneList, g, scaleFactor );
			float	halfGap = _tmpSize / 2.0F,
					maxWidth = 0,
					tmpWidth,
					gapPix = _gap * _tmpSize;
			foreach ( GraphPane tmpPane in paneList )
			{
				// Loop through each curve in the curve list
				// Find the maximum width of the legend labels
				//foreach ( CurveItem curve in tmpPane.CurveList )
				//foreach ( CurveItem curve in GetIterator( tmpPane.CurveList, _isReverse ) )
				int count = tmpPane.CurveList.Count;
				for ( int i = 0; i < count; i++ )
				{
					CurveItem curve = tmpPane.CurveList[_isReverse ? count - i - 1 : i];
					if ( curve._label._text != string.Empty && curve._label._isVisible )
					{
						// Calculate the width of the label save the max width
						FontSpec tmpFont = ( curve._label._fontSpec != null ) ?
										curve._label._fontSpec : this.FontSpec;
						tmpWidth = tmpFont.GetWidth( g, curve._label._text, scaleFactor );
						if ( tmpWidth > maxWidth )
							maxWidth = tmpWidth;
						// Save the maximum symbol height for line-type curves
						if ( curve is LineItem && ( (LineItem) curve ).Symbol.Size > _legendItemHeight )
							_legendItemHeight = ( (LineItem) curve ).Symbol.Size;
						nCurve++;
					}
				}
				if ( pane is MasterPane && ((MasterPane)pane).IsUniformLegendEntries )				
					break ;
			}
			float widthAvail;
		
			// Is this legend horizontally stacked?
			
			if ( _isHStack )
			{
				// Determine the available space for horizontal stacking
				switch( _position )
				{
						// Never stack if the legend is to the right or left
					case LegendPos.Right:
					case LegendPos.Left:
						widthAvail = 0;
						break;
		
						// for the top & bottom, the axis border width is available
					case LegendPos.Top:
					case LegendPos.TopCenter:
					case LegendPos.Bottom:
					case LegendPos.BottomCenter :
						widthAvail = tChartRect.Width;
						break;
		
						// for the top & bottom flush left, the panerect less margins is available
					case LegendPos.TopFlushLeft:
					case LegendPos.BottomFlushLeft:
						widthAvail = clientRect.Width;
						break;
		
						// for inside the axis area or Float, use 1/2 of the axis border width
					case LegendPos.InsideTopRight:
					case LegendPos.InsideTopLeft:
					case LegendPos.InsideBotRight:
					case LegendPos.InsideBotLeft:
					case LegendPos.Float:
						widthAvail = tChartRect.Width / 2;
						break;
		
						// shouldn't ever happen
					default:
						widthAvail = 0;
						break;
				}
		
				// width of one legend entry
				_legendItemWidth = 3 * _tmpSize + maxWidth;
				// Calculate the number of columns in the legend
				// Normally, the legend is:
				//     available width / ( max width of any entry + space for line&symbol )
				if ( maxWidth > 0 )
					_hStack = (int) ( (widthAvail - halfGap) / _legendItemWidth );
		
				// You can never have more columns than legend entries
				if ( _hStack > nCurve )
					_hStack = nCurve;
		
				// a saftey check
				if ( _hStack == 0 )
					_hStack = 1;
			}
			else
				_legendItemWidth = 3.5F * _tmpSize + maxWidth;
		
			// legend is:
			//   item:     space  line  space  text   space
			//   width:     wid  4*wid   wid  maxWid   wid 
			// The symbol is centered on the line
			//
			// legend begins 3 * wid to the right of the plot rect
			//
			// The height of the legend is the actual height of the lines of text
			//   (nCurve * hite) plus wid on top and wid on the bottom
		
			// total legend width
			float totLegWidth = _hStack * _legendItemWidth;	
		
			// The total legend height
			_legendItemHeight = _legendItemHeight * (float) scaleFactor + halfGap;
			if ( _tmpSize > _legendItemHeight )
				_legendItemHeight = _tmpSize;
			float totLegHeight = (float) Math.Ceiling( (double) nCurve / (double) _hStack )
				* _legendItemHeight;
			
			RectangleF newRect = new RectangleF();
			
			// Now calculate the legend rect based on the above determined parameters
			// Also, adjust the ChartRect to reflect the space for the legend
			if ( nCurve > 0 )
			{
				newRect = new RectangleF( 0, 0, totLegWidth, totLegHeight );
				// The switch statement assigns the left and top edges, and adjusts the ChartRect
				// as required.  The right and bottom edges are calculated at the bottom of the switch.
				switch( _position )
				{
					case LegendPos.Right:
						newRect.X = clientRect.Right - totLegWidth;
						newRect.Y = tChartRect.Top;
						tChartRect.Width -= totLegWidth + gapPix;
						break;
					case LegendPos.Top:
						newRect.X = tChartRect.Left;
						newRect.Y = clientRect.Top;
						tChartRect.Y += totLegHeight + gapPix;
						tChartRect.Height -= totLegHeight + gapPix;
						break;
					case LegendPos.TopFlushLeft:
						newRect.X = clientRect.Left;
						newRect.Y = clientRect.Top;
						tChartRect.Y += totLegHeight + gapPix * 1.5f;
						tChartRect.Height -= totLegHeight + gapPix * 1.5f;
						break;
					case LegendPos.TopCenter:
						newRect.X = tChartRect.Left + ( tChartRect.Width - totLegWidth ) / 2;
						newRect.Y = tChartRect.Top;
						tChartRect.Y += totLegHeight + gapPix;
						tChartRect.Height -= totLegHeight + gapPix;
						break;
					case LegendPos.Bottom:
						newRect.X = tChartRect.Left;
						newRect.Y = clientRect.Bottom - totLegHeight;
						tChartRect.Height -= totLegHeight + gapPix;
						break;
					case LegendPos.BottomFlushLeft:
						newRect.X = clientRect.Left;
						newRect.Y = clientRect.Bottom - totLegHeight;
						tChartRect.Height -= totLegHeight + gapPix;
						break;
					case LegendPos.BottomCenter:
						newRect.X = tChartRect.Left + ( tChartRect.Width - totLegWidth ) / 2;
						newRect.Y = clientRect.Bottom - totLegHeight;
						tChartRect.Height -= totLegHeight + gapPix;
						break;
					case LegendPos.Left:
						newRect.X = clientRect.Left;
						newRect.Y = tChartRect.Top;
						tChartRect.X += totLegWidth + halfGap;
						tChartRect.Width -= totLegWidth + gapPix;
						break;
					case LegendPos.InsideTopRight:
						newRect.X = tChartRect.Right - totLegWidth;
						newRect.Y = tChartRect.Top;
						break;
					case LegendPos.InsideTopLeft:
						newRect.X = tChartRect.Left;
						newRect.Y = tChartRect.Top;
						break;
					case LegendPos.InsideBotRight:
						newRect.X = tChartRect.Right - totLegWidth;
						newRect.Y = tChartRect.Bottom - totLegHeight;
						break;
					case LegendPos.InsideBotLeft:
						newRect.X = tChartRect.Left;
						newRect.Y = tChartRect.Bottom - totLegHeight;
						break;
					case LegendPos.Float:
						newRect.Location = this.Location.TransformTopLeft( pane, totLegWidth, totLegHeight );
						break;
				}
			}
			
			_rect = newRect;
		}
//		/// 
//		/// Private method to the render region that gives the iterator depending on the attribute
//		/// 
//		/// 
//		/// 
//		/// 
//		private IEnumerable GetIterator(CurveList c, bool forward)
//		{
//			return forward ? c.Forward : c.Backward;
//		}
	#endregion
	}
}