Initial commit

This commit is contained in:
2016-03-05 14:06:38 +01:00
commit 92e69371b4
254 changed files with 58742 additions and 0 deletions
+439
View File
@@ -0,0 +1,439 @@
/*
* NPlot - A charting library for .NET
*
* LegendBase.cs
* Copyright (C) 2003-2006 Matt Howlett and others.
* All rights reserved.
*
* 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 above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of NPlot nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
*/
using System;
using System.Collections;
using System.Drawing;
namespace NPlot
{
/// <summary>
/// Provides functionality for drawing legends.
/// </summary>
/// <remarks>
/// The class is quite closely tied to PlotSurface2D.
/// </remarks>
public class LegendBase
{
/// <summary>
/// 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;
this.autoScaleText_ = false;
}
/// <summary>
/// Get the bounding box of the rectangle.
/// </summary>
/// <param name="position">the position of the top left of the legend.</param>
/// <param name="plots">Array of plot objects to appear in the legend.</param>
/// <param name="scale">if the legend is set to scale, the amount to scale by.</param>>
/// <returns></returns>
/// <remarks>do implementation that doesn't call draw. Change xPos, yPos to PointF</remarks>
public Rectangle GetBoundingBox( Point position, ArrayList plots, float scale )
{
System.Drawing.Bitmap b = new System.Drawing.Bitmap(1,1);
Graphics g = Graphics.FromImage(b);
return this.Draw( g, position, plots, scale );
}
/// <summary>
/// Draw The legend
/// </summary>
/// <param name="g">The graphics surface on which to draw</param>
/// <param name="position">The position of the top left of the axis.</param>
/// <param name="plots">Array of plot objects to appear in the legend.</param>
/// <param name="scale">if the legend is set to scale, the amount to scale by.</param>
/// <returns>bounding box</returns>
public Rectangle Draw( Graphics g, Point position, ArrayList plots, float scale )
{
// first of all determine the Font to use in the legend.
Font textFont;
if (this.AutoScaleText)
{
textFont = Utils.ScaleFont( this.font_, scale );
}
else
{
textFont = this.font_;
}
// determine max width and max height of label strings and
// count the labels.
int labelCount = 0;
int maxHt = 0;
int maxWd = 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.ShowInLegend)
{
continue;
}
string label = p.Label;
if (label == "")
{
unnamedCount += 1;
label = "Series " + unnamedCount.ToString();
}
SizeF labelSize = g.MeasureString( label, textFont );
if ( labelSize.Height > maxHt )
{
maxHt = (int)labelSize.Height;
}
if ( labelSize.Width > maxWd )
{
maxWd = (int)labelSize.Width;
}
++labelCount;
}
bool extendingHorizontally = numberItemsHorizontally_ == -1;
bool extendingVertically = numberItemsVertically_ == -1;
// determine width in legend items count units.
int widthInItemCount = 0;
if (extendingVertically)
{
if (labelCount >= numberItemsHorizontally_)
{
widthInItemCount = numberItemsHorizontally_;
}
else
{
widthInItemCount = labelCount;
}
}
else if (extendingHorizontally)
{
widthInItemCount = labelCount / numberItemsVertically_;
if (labelCount % numberItemsVertically_ != 0)
widthInItemCount += 1;
}
else
{
throw new NPlotException( "logic error in legend base" );
}
// determine height of legend in items count units.
int heightInItemCount = 0;
if (extendingHorizontally)
{
if (labelCount >= numberItemsVertically_)
{
heightInItemCount = numberItemsVertically_;
}
else
{
heightInItemCount = labelCount;
}
}
else // extendingVertically
{
heightInItemCount = labelCount / numberItemsHorizontally_;
if (labelCount % numberItemsHorizontally_ != 0)
heightInItemCount += 1;
}
int lineLength = 20;
int hSpacing = (int)(5.0f * scale);
int vSpacing = (int)(3.0f * scale);
int boxWidth = (int) ((float)widthInItemCount * (lineLength + maxWd + hSpacing * 2.0f ) + hSpacing);
int boxHeight = (int)((float)heightInItemCount * (maxHt + vSpacing) + vSpacing);
int totalWidth = boxWidth;
int totalHeight = boxHeight;
// draw box around the legend.
if ( this.BorderStyle == BorderType.Line )
{
g.FillRectangle( new SolidBrush( this.bgColor_ ), position.X, position.Y, boxWidth, boxHeight );
g.DrawRectangle( new Pen( this.borderColor_ ), position.X, position.Y, boxWidth, boxHeight );
}
else if ( this.BorderStyle == BorderType.Shadow )
{
int offset = (int)(4.0f * scale);
g.FillRectangle( new SolidBrush( Color.FromArgb(128, Color.Gray) ), position.X+offset, position.Y+offset, boxWidth, boxHeight );
g.FillRectangle( new SolidBrush( this.bgColor_ ), position.X, position.Y, boxWidth, boxHeight );
g.DrawRectangle( new Pen( this.borderColor_ ), position.X, position.Y, 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;
unnamedCount = 0;
int plotCount = -1;
for (int i=0; i<plots.Count; ++i)
{
if (!(plots[i] is IPlot))
{
continue;
}
IPlot p = (IPlot)plots[i];
if (!p.ShowInLegend)
{
continue;
}
plotCount += 1;
int xpos, ypos;
if (extendingVertically)
{
xpos = plotCount % numberItemsHorizontally_;
ypos = plotCount / numberItemsHorizontally_;
}
else
{
xpos = plotCount / numberItemsVertically_;
ypos = plotCount % numberItemsVertically_;
}
int lineXPos = (int)(position.X + hSpacing + xpos * (lineLength + maxWd + hSpacing * 2.0f));
int lineYPos = (int)(position.Y + vSpacing + ypos * (vSpacing + maxHt));
p.DrawInLegend( g, new Rectangle( lineXPos, lineYPos, lineLength, maxHt ) );
int textXPos = lineXPos + hSpacing + lineLength;
int textYPos = lineYPos;
string label = p.Label;
if (label == "")
{
unnamedCount += 1;
label = "Series " + unnamedCount.ToString();
}
g.DrawString( label, textFont,
new SolidBrush( this.textColor_ ), textXPos, textYPos );
++labelCount;
}
return new Rectangle( position.X, position.Y, totalWidth, totalHeight );
}
/// <summary>
/// The font used to draw text in the legend.
/// </summary>
public Font Font
{
get
{
return this.font_;
}
set
{
this.font_ = value;
}
}
private Font font_;
/// <summary>
/// The color used to draw text in the legend.
/// </summary>
public Color TextColor
{
get
{
return this.textColor_;
}
set
{
this.textColor_ = value;
}
}
Color textColor_;
/// <summary>
/// The background color of the legend.
/// </summary>
public Color BackgroundColor
{
get
{
return bgColor_;
}
set
{
bgColor_ = value;
}
}
Color bgColor_;
/// <summary>
/// The color of the legend border.
/// </summary>
public Color BorderColor
{
get
{
return borderColor_;
}
set
{
borderColor_ = value;
}
}
Color borderColor_;
/// <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
}
/// <summary>
/// The border style to use for the legend.
/// </summary>
public Legend.BorderType BorderStyle
{
get
{
return borderStyle_;
}
set
{
borderStyle_ = value;
}
}
private NPlot.Legend.BorderType borderStyle_;
/// <summary>
/// Whether or not to auto scale text in the legend according the physical
/// dimensions of the plot surface.
/// </summary>
public bool AutoScaleText
{
get
{
return autoScaleText_;
}
set
{
autoScaleText_ = value;
}
}
bool autoScaleText_;
/// <summary>
/// Setting this does two things. First of all, it sets the maximum number of
/// items in the legend vertically. Second of all, it makes the legend grow
/// horizontally (as it must given this constraint).
/// </summary>
public int NumberItemsVertically
{
set
{
this.numberItemsVertically_ = value;
this.numberItemsHorizontally_ = -1;
}
}
int numberItemsVertically_ = -1;
/// <summary>
/// Setting this does two things. First of all, it sets the maximum number of
/// items in the legend horizontally. Second of all, it makes the legend grow
/// vertically (as it must given this constraint).
/// </summary>
public int NumberItemsHorizontally
{
set
{
this.numberItemsHorizontally_ = value;
this.numberItemsVertically_ = -1;
}
}
int numberItemsHorizontally_ = 1;
}
}