public void Draw(Graphics g, Rectangle bounds)
{
// determine font sizes and tick scale factor.
float scale = DetermineScaleFactor(bounds.Width, bounds.Height);
// if there is nothing to plot, return.
if (m_drawables.Count == 0)
{
// draw title
float x_center = (bounds.Left + bounds.Right) / 2.0f;
float y_center = (bounds.Top + bounds.Bottom) / 2.0f;
Font scaled_font;
if (AutoScaleTitle)
{
scaled_font = Utils.ScaleFont(m_titleFont, scale);
}
else
{
scaled_font = m_titleFont;
}
g.DrawString(m_title, scaled_font, this.m_titleBrush, new PointF(x_center, y_center), m_titleDrawFormat);
return;
}
Stopwatch sw = StepTimer.Start("Determine Axis");
// determine the [non physical] axes to draw based on the axis properties set.
Axis xAxis1, xAxis2, yAxis1, yAxis2;
DetermineAxesToDraw(out xAxis1, out xAxis2, out yAxis1, out yAxis2);
// apply scale factor to axes as desired.
if (xAxis1.AutoScaleTicks)
xAxis1.TickScale = scale;
if (xAxis1.AutoScaleText)
xAxis1.FontScale = scale;
if (yAxis1.AutoScaleTicks)
yAxis1.TickScale = scale;
if (yAxis1.AutoScaleText)
yAxis1.FontScale = scale;
if (xAxis2.AutoScaleTicks)
xAxis2.TickScale = scale;
if (xAxis2.AutoScaleText)
xAxis2.FontScale = scale;
if (yAxis2.AutoScaleTicks)
yAxis2.TickScale = scale;
if (yAxis2.AutoScaleText)
yAxis2.FontScale = scale;
// determine the default physical positioning of those axes.
PhysicalAxis pXAxis1, pYAxis1, pXAxis2, pYAxis2;
DeterminePhysicalAxesToDraw(bounds, xAxis1, xAxis2, yAxis1, yAxis2, out pXAxis1, out pXAxis2, out pYAxis1, out pYAxis2);
StepTimer.Stop(sw);
float oldXAxis2Height = pXAxis2.PhysicalMin.Y;
// Apply axes constraints
for (int i = 0; i < m_axesConstraints.Count; ++i)
{
(m_axesConstraints[i]).ApplyConstraint(pXAxis1, pYAxis1, pXAxis2, pYAxis2);
}
float newXAxis2Height = pXAxis2.PhysicalMin.Y;
float titleExtraOffset = oldXAxis2Height - newXAxis2Height;
sw = StepTimer.Start("Draw Axis");
// now we are ready to define the bounding box for the plot area (to use in clipping
// operations.
m_plotAreaBoundingBoxCache = new Rectangle(
Math.Min(pXAxis1.PhysicalMin.X, pXAxis1.PhysicalMax.X),
Math.Min(pYAxis1.PhysicalMax.Y, pYAxis1.PhysicalMin.Y),
Math.Abs(pXAxis1.PhysicalMax.X - pXAxis1.PhysicalMin.X + 1),
Math.Abs(pYAxis1.PhysicalMin.Y - pYAxis1.PhysicalMax.Y + 1)
);
m_bbXAxis1Cache = pXAxis1.GetBoundingBox();
m_bbXAxis2Cache = pXAxis2.GetBoundingBox();
m_bbYAxis1Cache = pYAxis1.GetBoundingBox();
m_bbYAxis2Cache = pYAxis2.GetBoundingBox();
// Fill in the background.
g.FillRectangle(new SolidBrush(m_plotBackColor), m_plotAreaBoundingBoxCache);
// draw title
float xt = (pXAxis2.PhysicalMax.X + pXAxis2.PhysicalMin.X) / 2.0f;
float yt = bounds.Top + m_padding - titleExtraOffset;
Font scaledFont;
if (AutoScaleTitle)
{
scaledFont = Utils.ScaleFont(m_titleFont, scale);
}
else
{
scaledFont = m_titleFont;
}
g.DrawString(m_title, scaledFont, m_titleBrush, new PointF(xt, yt), m_titleDrawFormat);
//count number of new lines in title.
int nlCount = 0;
for (int i = 0; i < m_title.Length; ++i)
{
if (m_title[i] == '\n')
nlCount += 1;
}
SizeF s = g.MeasureString(m_title, scaledFont);
m_bbTitleCache = new Rectangle((int)(xt - s.Width / 2), (int)(yt), (int)(s.Width), (int)(s.Height) * (nlCount + 1));
StepTimer.Stop(sw);
//sw = StepTimer.Start("Draw IDrawables");
// draw drawables..
SmoothingMode smoothSave = g.SmoothingMode;
g.SmoothingMode = m_smoothingMode;
for (int i_o = 0; i_o < m_ordering.Count; ++i_o)
{
int i = m_ordering.Values[i_o];
IDrawable drawable = m_drawables[i];
PhysicalAxis drawXAxis;
PhysicalAxis drawYAxis;
drawXAxis = pXAxis1;
drawYAxis = pYAxis1;
// set the clipping region.. (necessary for zoom)
g.Clip = new Region(m_plotAreaBoundingBoxCache);
// plot.
drawable.Draw(g, drawXAxis, drawYAxis);
// reset it..
g.ResetClip();
}
//StepTimer.Stop(sw);
// cache the physical axes we used on this draw;
m_pXAxis1Cache = pXAxis1;
m_pYAxis1Cache = pYAxis1;
m_pXAxis2Cache = pXAxis2;
m_pYAxis2Cache = pYAxis2;
g.SmoothingMode = smoothSave;
sw = StepTimer.Start("Draw Axis Final");
// now draw axes.
Rectangle axisBounds;
pXAxis1.Draw(g, out axisBounds);
pXAxis2.Draw(g, out axisBounds);
pYAxis1.Draw(g, out axisBounds);
pYAxis2.Draw(g, out axisBounds);
StepTimer.Stop(sw);
}