/*
ScPl - A plotting library for .NET

LegendBase.cs
Copyright (C) 2003
Matt Howlett

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
   
2. Redistributions in binary form must reproduce the following text in 
   the documentation and / or other materials provided with the 
   distribution: 
   
   "This product includes software developed as part of 
   the ScPl plotting library project available from: 
   http://www.netcontrols.org/scpl/" 

------------------------------------------------------------------------

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

$Id: LegendBase.cs,v 1.2 2004/06/24 11:10:31 mhowlett Exp $

*/

using System;
using System.Collections;
using System.Drawing;

namespace scpl
{

	#region LegendBase
	/// <summary>
	/// Provides functionality for drawing legends.
	/// </summary>
	/// <remarks>
	/// The class is quite closely tied to PlotSurface2D. 
	/// </remarks>
	public class LegendBase
	{
		#region Constructor
		/// <summary>
		/// Parameterless constructor.
		/// </summary>
		public LegendBase()
		{
			this.Font = new Font(new FontFamily("Arial"), 10, FontStyle.Regular, GraphicsUnit.Pixel);
			this.BackgroundColor = Color.White;
			this.BorderColor = Color.Black;
			this.TextColor = Color.Black;
			this.borderStyle_ = BorderType.Shadow;
		}
		#endregion
		#region method GetBoundingBox
		/// <summary>
		/// Return the bounding box of the legend.
		/// </summary>
		/// <param name="xPos">Legend horizontal position.</param>
		/// <param name="yPos">Legend vertical position.</param>
		/// <param name="plots">The trace plot ArrayList.</param>
		/// <param name="scale">scale?</param>
		/// <returns>The RectangleF holding the bounding box.</returns>
		public RectangleF GetBoundingBox( int xPos, int yPos, ArrayList plots, float scale )
		{
			System.Drawing.Bitmap b = new System.Drawing.Bitmap(1,1);
			Graphics g = Graphics.FromImage(b);
			return this.Draw( g, xPos, yPos, plots, scale );
		}
		#endregion
		#region method Draw
		/// <summary>
		/// Draws the legend.
		/// </summary>
		/// <param name="g">The Graphics surface used for rendering.</param>
		/// <param name="xPos">Horizontal position.</param>
		/// <param name="yPos">Vertical position.</param>
		/// <param name="plots">The trace plot ArrayList.</param>
		/// <param name="scale">scale?</param>
		/// <returns></returns>
		public RectangleF Draw( Graphics g, float xPos, float yPos, ArrayList plots, float scale )
		{	

			int labelCount = 0;

			// determine max width and max height of label strings.
			float maxHt = 0.0f;
			float maxWd = 0.0f;
			for (int i=0; i<plots.Count; ++i)
			{
				if (!(plots[i] is IPlot))
				{
					continue;
				}
				
				IPlot p = (IPlot)plots[i];
				
				if (!p.ShowLegendLine)
				{
					continue;
				}

				float lHt = g.MeasureString( p.Label, FontScaler.scaleFont(this.font_,scale) ).Height;
				float lWd = g.MeasureString( p.Label, FontScaler.scaleFont(this.font_,scale) ).Width;
				if ( lHt > maxHt )
				{
					maxHt = lHt;
				}
				if ( lWd > maxWd )
				{
					maxWd = lWd;
				}

				++labelCount;
			}

			float lineLength = 20.0f;
			float lineHeight = maxHt;
			float hSpacing = 5.0f * scale;
			float vSpacing = 3.0f * scale; 
			float boxWidth = hSpacing * 3.0f + lineLength + maxWd;
			float boxHeight = vSpacing * (float)(labelCount+1) + maxHt * (float)labelCount;

			float totalWidth = boxWidth;
			float totalHeight = boxHeight;

			// draw box..
			if ( this.BorderStyle == BorderType.Line )
			{
				g.FillRectangle( new SolidBrush( this.bgColor_ ), xPos, yPos, boxWidth, boxHeight );
				g.DrawRectangle( new Pen( this.borderColor_ ), xPos, yPos, boxWidth, boxHeight );
			}
			else if ( this.BorderStyle == BorderType.Shadow )
			{
				float offset = 4.0f * (float)scale;
				g.FillRectangle( new SolidBrush( Color.LightGray ), xPos+offset, yPos+offset, boxWidth, boxHeight );
				g.FillRectangle( new SolidBrush( this.bgColor_ ), xPos, yPos, boxWidth, boxHeight );
				g.DrawRectangle( new Pen( this.borderColor_ ), xPos, yPos, boxWidth, boxHeight );

				totalWidth += offset;
				totalHeight += offset;
			}
				/*
				else if ( this.BorderStyle == BorderType.Curved )
				{
					// TODO. make this nice.
				} 
				*/
			else
			{
				// do nothing.
			}

			// now draw entries in box..
			labelCount = 0;

			int unnamedCount = 0;
			for (int i=0; i<plots.Count; ++i)
			{
				if (!(plots[i] is IPlot))
				{
					continue;
				}

				IPlot p = (IPlot)plots[i];

				if (!p.ShowLegendLine)
				{
					continue;
				}

				float lineXPos = xPos + hSpacing;
				float lineYPos = yPos + vSpacing + (float)labelCount*(vSpacing+maxHt);
				p.DrawLegendLine( g, new RectangleF( lineXPos, lineYPos, lineLength, lineHeight ) );
				float textXPos = lineXPos + hSpacing + lineLength;
				float textYPos = lineYPos;
				string label = p.Label;
				if (label == "")
				{
					unnamedCount += 1;
					label = "Series " + unnamedCount.ToString();
				}
				g.DrawString( label, FontScaler.scaleFont(this.Font,scale),
					new SolidBrush( this.textColor_ ), textXPos, textYPos );

				++labelCount;
			}
			return new RectangleF( xPos, yPos, totalWidth, totalHeight );
		}
		#endregion
		#region get/set Font
		/// <summary>
		/// The legend Font.
		/// </summary>
		public Font Font
		{
			get
			{
				return this.font_;
			}
			set
			{
				this.font_ = value;
			}
		}
		private Font font_;
		#endregion
		#region get/set TextColor
		public Color TextColor
		{
			get
			{
				return this.textColor_;
			}
			set
			{
				this.textColor_ = value;
			}
		}
		Color textColor_;
		#endregion
		#region get/set BackgroundColor
		public Color BackgroundColor
		{
			get
			{
				return bgColor_;
			}
			set
			{
				bgColor_ = value;
			}
		}
		Color bgColor_;
		#endregion
		#region BorderColor
		public Color BorderColor
		{
			get
			{
				return borderColor_;
			}
			set
			{
				borderColor_ = value;
			}
		}
		Color borderColor_;
		#endregion
		#region enum BorderType
		/// <summary>
		/// The types of legend borders (enum).
		/// </summary>
		public enum BorderType
		{
			/// <summary>
			/// No border.
			/// </summary>
			None = 0,
			/// <summary>
			/// Line border.
			/// </summary>
			Line = 1,
			/// <summary>
			/// Shaded border.
			/// </summary>
			Shadow = 2
			//Curved = 3
		}
		#endregion

		#region BorderStyle
		/// <summary>
		/// The border style of the legend.
		/// </summary>
		public Legend.BorderType BorderStyle
		{
			get
			{
				return borderStyle_;
			}
			set
			{
				borderStyle_ = value;
			}
		}
		private scpl.Legend.BorderType borderStyle_;
		#endregion
	}
	#endregion

}
