public override void Draw(Graphics g, AdvancedRect dataArea) { PointF pt = new PointF( Plot.XAxis.DataToCoordinate(X, dataArea), Plot.YAxes[YAxisName].DataToCoordinate(Y, dataArea)); using (Pen p = crosshairPen.CreatePen()) { g.DrawLine(p, pt.X - crosshairCircleRadius, pt.Y, pt.X + crosshairCircleRadius, pt.Y); g.DrawLine(p, pt.X, pt.Y - crosshairCircleRadius, pt.X, pt.Y + crosshairCircleRadius); g.DrawEllipse(p, pt.X - crosshairCircleRadius, pt.Y - crosshairCircleRadius, crosshairCircleRadius * 2, crosshairCircleRadius * 2); SizeF size = Size(g); switch (crosshair) { case AnnotationCrosshair.Left: g.DrawLine(p, pt.X + crosshairCircleRadius, pt.Y, pt.X + crosshairCircleRadius + crosshairHandleSize, pt.Y); pt.X += crosshairCircleRadius; pt.X += crosshairHandleSize; pt.Y -= size.Height / 2; break; case AnnotationCrosshair.Right: g.DrawLine(p, pt.X - crosshairCircleRadius, pt.Y, pt.X - crosshairCircleRadius - crosshairHandleSize, pt.Y); pt.X -= crosshairCircleRadius; pt.X -= crosshairHandleSize; pt.X -= size.Width; pt.Y -= size.Height / 2; break; case AnnotationCrosshair.Bottom: g.DrawLine(p, pt.X, pt.Y - crosshairCircleRadius, pt.X, pt.Y - crosshairCircleRadius - crosshairHandleSize); pt.X -= size.Width / 2; pt.Y -= size.Height; pt.Y -= crosshairCircleRadius; pt.Y -= crosshairHandleSize; break; case AnnotationCrosshair.Top: g.DrawLine(p, pt.X, pt.Y + crosshairCircleRadius, pt.X, pt.Y + crosshairCircleRadius + crosshairHandleSize); pt.X -= size.Width / 2; pt.Y += crosshairCircleRadius; pt.Y += crosshairHandleSize; break; } } DrawTextBox(g, pt); }
public override void Draw(Graphics g, AxisCollection yAxisCollection, XAxis xAxis, AdvancedRect area) { if (data.Count == 0) { return; } GraphicsState _s = g.Save(); g.SmoothingMode = SmoothingMode.AntiAlias; NumericAxis yAxis = yAxisCollection[YAxisName]; using (Pen p = line.CreatePen()) using (Symbol s = (SymbolStyle != SymbolStyle.NoSymbols) ? symbol.CreateSymbol() : null) { // find continuous groups of non-null Y points // if our yAxis is LogRate, then we need to find continuous // groups of non-null, >0 Y points. Yay. int start = 0, end = 0, i = 0; while (i < data.Count) { // chomp all nulls // then draw all non-nulls while (i < data.Count && (data.GetY(i) == null || (yAxis.LogAxis && data.GetY(i) <= 0))) { i++; } // found a non-null at i. start = i; while (i < data.Count && data.GetY(i) != null && (!yAxis.LogAxis || data.GetY(i) > 0)) { i++; } // found a null at i; end = i; if (start != end) { drawLines(g, p, s, xAxis, yAxis, area, start, end); } } } g.Restore(_s); }
public void DrawY(Graphics g, AdvancedRect area, AdvancedRect plotArea) { drawArea = area; GraphicsState _s = g.Save(); //using (Brush br = new SolidBrush(Color.Purple)) // g.FillRectangle(br, area.Rect); if (title != null) { using (Brush br = titleFont.CreateBrush()) using (Font f = titleFont.CreateFont()) { SizeF titleSize = g.MeasureString(title, f); GraphicsState s = g.Save(); if (rightSide) { g.TranslateTransform(area.BottomRight.X, area.Center.Y - (titleSize.Width / 2)); g.RotateTransform(90); } else { g.TranslateTransform(area.TopLeft.X, area.Center.Y + (titleSize.Width / 2)); g.RotateTransform(-90); } StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; g.DrawString(title, f, br, new PointF(0, 0)); g.Restore(s); } } if (!logAxis) { int maxIntervals = (int)Math.Ceiling(area.Height * 1.25); // calculate label and tick mark intervals using (Brush br = labelFont.CreateBrush()) using (Font f = labelFont.CreateFont()) using (Pen p = tickPen.CreatePen()) { foreach (double v in GenerateTickLocations(maxIntervals)) { string txt = FormatLabel(v); float yCoord = DataToCoordinate(v, area); if (yCoord < area.TopLeft.Y || yCoord > area.BottomRight.Y) { continue; } SizeF sz = g.MeasureString(txt, f); if (rightSide) { g.DrawLine(p, area.TopLeft.X, yCoord, area.TopLeft.X + tickLength, yCoord); g.DrawString(txt, f, br, area.TopLeft.X + tickLength, yCoord - (sz.Height / 2)); } else { g.DrawLine(p, area.BottomRight.X, yCoord, area.BottomRight.X - tickLength, yCoord); g.DrawString(txt, f, br, area.BottomRight.X - sz.Width - tickLength, yCoord - (sz.Height / 2)); } } } if (gridlinesEnabled) { using (Pen p = gridlinePen.CreatePen()) { foreach (double v in GenerateTickLocations(maxIntervals)) { float yCoord = DataToCoordinate(v, area); if (yCoord < area.TopLeft.Y || yCoord > area.BottomRight.Y) { continue; } g.DrawLine(p, plotArea.TopLeft.X, yCoord, plotArea.BottomRight.X, yCoord); } } } } else { // log axis drawing int start = (int)Math.Floor(Math.Log10(ScaleMinimum)); int end = (int)Math.Ceiling(Math.Log10(ScaleMaximum)); using (Brush br = labelFont.CreateBrush()) using (Font f = labelFont.CreateFont()) using (Pen p = tickPen.CreatePen()) using (Pen p2 = gridlinePen.CreatePen()) { for (int i = start; i <= end; i++) { double v = Math.Pow(10, i); float yCoord = DataToCoordinate(v, area); // ticks and labels string txt = FormatLabel(v); SizeF sz = g.MeasureString(txt, f); if (yCoord >= area.TopLeft.Y && yCoord <= area.BottomRight.Y) { if (rightSide) { g.DrawLine(p, area.TopLeft.X, yCoord, area.TopLeft.X + tickLength, yCoord); g.DrawString(txt, f, br, area.TopLeft.X + tickLength, yCoord - (sz.Height / 2)); } else { g.DrawLine(p, area.BottomRight.X, yCoord, area.BottomRight.X - tickLength, yCoord); g.DrawString(txt, f, br, area.BottomRight.X - sz.Width - tickLength, yCoord - (sz.Height / 2)); } } if (gridlinesEnabled && i != end) { double v2 = Math.Pow(10, i + 1); double delta = (v2 - v) / 9; for (int j = 1; j < 10; j++) { double v3 = v + (delta * j); yCoord = DataToCoordinate(v3, area); if (yCoord > area.TopLeft.Y && yCoord < area.BottomRight.Y) { g.DrawLine(p2, plotArea.TopLeft.X, yCoord, plotArea.BottomRight.X, yCoord); } } } } } } // Because there can be multiple Y axises that are not always next to the data area, // we draw our own border. The plot might stroke over it again later, but that's // not such a big deal. using (Pen p = borderPen.CreatePen()) { if (rightSide) { g.DrawLine(p, area.TopLeft, new PointF(area.TopLeft.X, area.BottomRight.Y)); } else { g.DrawLine(p, area.BottomRight, new PointF(area.BottomRight.X, area.TopLeft.Y)); } } g.Restore(_s); }
public void DrawX(Graphics g, AdvancedRect area, AdvancedRect plotArea) { drawArea = area; //using (Brush br = new SolidBrush(Color.Green)) // g.FillRectangle(br, area.Rect); GraphicsState _s = g.Save(); using (Font f = titleFont.CreateFont()) using (Brush br = titleFont.CreateBrush()) { string txt = "Time ("; if (weeklyLabels) { txt += "weeks)"; } else if (monthlyLabels || quarterlyLabels) { txt += "months)"; } else if (yearlyLabels) { txt += "years)"; } SizeF sz = g.MeasureString(txt, f); g.DrawString(txt, f, br, area.Center.X - (sz.Width / 2), area.BottomRight.Y - sz.Height); } using (Brush br = labelFont.CreateBrush()) using (Font f = labelFont.CreateFont()) using (Pen p = tickPen.CreatePen()) using (Pen pgrid = gridlinePen.CreatePen()) using (Pen pminor = minorTickPen.CreatePen()) { float tick = tickLength; float dayTick = minorTickLength; TimeSpan dur; if (weeklyLabels) { dur = week; } else if (monthlyLabels) { dur = month; } else if (quarterlyLabels) { dur = new TimeSpan(month.Ticks * 3); } else { dur = year; } int cnt = (int)(ScaleMinimum.Ticks / dur.Ticks); while (true) { TimeSpan loc = new TimeSpan(dur.Ticks * cnt); float x1 = DataToCoordinate(loc, area); cnt++; if (x1 < area.TopLeft.X) { continue; } if (x1 > area.BottomRight.X) { break; } g.DrawLine(p, x1, area.TopLeft.Y, x1, area.TopLeft.Y + tick); if (gridlinesEnabled && x1 != area.TopLeft.X && x1 != area.BottomRight.X) { g.DrawLine(pgrid, x1, plotArea.TopLeft.Y, x1, plotArea.BottomRight.Y); } if (dailyTicks) { for (int d = 0; d < 7; d++) { float xd = DataToCoordinate(loc + new TimeSpan(d, 0, 0, 0), area); if (xd > area.TopLeft.X && xd < area.BottomRight.X) { g.DrawLine(pminor, xd, area.TopLeft.Y, xd, area.TopLeft.Y + dayTick); } } } int labelNumber = cnt - 1; if (quarterlyLabels) { labelNumber *= 3; } string txt = String.Format("{0}", labelNumber); SizeF sz = g.MeasureString(txt, f); g.DrawString(txt, f, br, x1 - (sz.Width / 2), area.TopLeft.Y + tick); } } g.Restore(_s); }
public void PaintOn(Graphics g, RectangleF _area) { GraphicsState _s = g.Save(); // _area is assumed to be provided in the same coordinate system as // g.PageUnit provides. The plotting library works assuming that // PageUnit is Inch, so we must transform the Rectangle into the // appropriate rect. PointF[] trans = new PointF[] { new PointF(_area.Left, _area.Top), new PointF(_area.Left + _area.Width, _area.Top + _area.Height) }; g.TransformPoints(CoordinateSpace.Device, CoordinateSpace.Page, trans); g.PageUnit = GraphicsUnit.Inch; g.TransformPoints(CoordinateSpace.Page, CoordinateSpace.Device, trans); AdvancedRect area = new AdvancedRect(trans[0], trans[1]); using (Brush bg = background.CreateBrush()) g.FillRectangle(bg, area.Rect); outerMargins.Apply(ref area); //using (Brush tmp = new SolidBrush(Color.Red)) // g.FillRectangle(tmp, area.Rect); SizeF headerSize = new SizeF(0, 0); if (centerHeader != null) { using (Brush br = centerHeaderFont.CreateBrush()) using (Font f = centerHeaderFont.CreateFont()) { headerSize = g.MeasureString(centerHeader, f); g.DrawString(centerHeader, f, br, area.Center.X - (headerSize.Width / 2), area.TopLeft.Y); } } if (rightHeader != null || leftHeader != null) { using (Brush left_br = leftHeaderFont.CreateBrush()) using (Font left_f = leftHeaderFont.CreateFont()) using (Brush right_br = rightHeaderFont.CreateBrush()) using (Font right_f = rightHeaderFont.CreateFont()) { SizeF leftHeaderSize = (leftHeader != null) ? g.MeasureString(leftHeader, left_f) : new SizeF(0, 0); SizeF rightHeaderSize = (rightHeader != null) ? g.MeasureString(rightHeader, right_f) : new SizeF(0, 0); // determine y location = is this going to be aligned to the bottom of the center // header, or underneath it? underneath is necessary if the two will hit each other. float left_xLoc = area.TopLeft.X; float right_xLoc = area.BottomRight.X - rightHeaderSize.Width; float left_yLoc; float right_yLoc; if ((right_xLoc - 0.2f) < (area.Center.X + (headerSize.Width / 2)) || (left_xLoc + leftHeaderSize.Width + 0.2f) > (area.Center.X - (headerSize.Width / 2))) { // looks like we're too close - have to move down a bit. left_yLoc = right_yLoc = area.TopLeft.Y + headerSize.Height; headerSize.Height += Math.Max(rightHeaderSize.Height, leftHeaderSize.Height); } else { // We're good to place it next to the header. // But, check our height - are the side headers bigger than the center header? if (rightHeaderSize.Height > headerSize.Height || leftHeaderSize.Height > headerSize.Height) { // the side headers are bigger than the center header. Make enough room. headerSize.Height = Math.Max(leftHeaderSize.Height, rightHeaderSize.Height); } right_yLoc = area.TopLeft.Y + (headerSize.Height - rightHeaderSize.Height); left_yLoc = area.TopLeft.Y + (headerSize.Height - leftHeaderSize.Height); } if (rightHeader != null) { g.DrawString(rightHeader, right_f, right_br, right_xLoc, right_yLoc); } if (leftHeader != null) { g.DrawString(leftHeader, left_f, left_br, left_xLoc, left_yLoc); } } } if (headerSize.Height != 0) { area.TopLeft.Y += headerSize.Height; area.TopLeft.Y += 0.1f; } if (displayLegend) { area.BottomRight.Y -= DrawLegend(g, area); } float yAxisWidthLeft = yAxes.CalculateWidthLeft(g); float yAxisWidthRight = yAxes.CalculateWidthRight(g); float xAxisHeight = xAxis.CalculateHeight(g, area.Width - yAxisWidthLeft - yAxisWidthRight); AdvancedRect xAxisArea = area.Clone(); xAxisArea.TopLeft.X += yAxisWidthLeft; xAxisArea.BottomRight.X -= yAxisWidthRight; xAxisArea.TopLeft.Y = xAxisArea.BottomRight.Y - xAxisHeight; // calculate internal data area area.TopLeft.X += yAxisWidthLeft; area.BottomRight.X -= yAxisWidthRight; area.BottomRight.Y -= xAxisHeight; yAxes.Draw(g, area); xAxis.DrawX(g, xAxisArea, area); series.Draw(g, yAxes, xAxis, area); annotations.Draw(g, area); using (Pen p = borderPen.CreatePen()) { g.DrawLine(p, area.TopLeft.X, area.TopLeft.Y, area.TopLeft.X, area.BottomRight.Y); g.DrawLine(p, area.TopLeft.X, area.TopLeft.Y, area.BottomRight.X, area.TopLeft.Y); g.DrawLine(p, area.BottomRight.X, area.BottomRight.Y, area.BottomRight.X, area.TopLeft.Y); g.DrawLine(p, area.BottomRight.X, area.BottomRight.Y, area.TopLeft.X, area.BottomRight.Y); } dataArea = area; g.Restore(_s); }
public PenSymbol(PenDescription f, float size) : base(size) { p = f.CreatePen(); }
public void DrawX(Graphics g, AdvancedRect area, AdvancedRect plotArea) { drawArea = area; //using (Brush br = new SolidBrush(Color.Green)) // g.FillRectangle(br, area.Rect); GraphicsState _s = g.Save(); using (Brush br = labelFont.CreateBrush()) using (Font f = labelFont.CreateFont()) using (Font f2 = smallLabelFont.CreateFont()) using (Pen p = tickPen.CreatePen()) using (Pen pgrid = gridlinePen.CreatePen()) using (Pen pminor = minorTickPen.CreatePen()) { CalculateNext nextMajor = GetNextMajorFunction(); // Same dealy-o, but for minor ticks / labels. CalculateNext nextMinor = null; if (axisType == AxisType.MonthsHorizontalWithDailyTicks || axisType == AxisType.MonthsHorizontalWithDailyLabels) { nextMinor = delegate(DateTime dt) { return(cal.AddDays(dt, 1)); } } ; else if (axisType == AxisType.DailyWithHourlyTicks || axisType == AxisType.DailyWithHourlyLabels) { nextMinor = delegate(DateTime dt) { return(cal.AddHours(dt, 1)); } } ; else if (axisType == AxisType.Quarters) { nextMinor = delegate(DateTime dt) { return(cal.AddMonths(dt, 1)); } } ; // Determine major label format -- {0} is the major label v, // {1} is the quarter string majorLabel = null; if (axisType == AxisType.Quarters) { majorLabel = "Q{1} {0:\\'yy}"; } else if (axisType == AxisType.DailyWithHourlyTicks || axisType == AxisType.DailyWithHourlyLabels) { majorLabel = "{0:MMM %d \\'yy}"; } else { majorLabel = "{0:MMM \\'yy}"; } // Determine minor label format: string minorLabel = null; if (axisType == AxisType.MonthsHorizontalWithDailyLabels) { minorLabel = "{0:%d}"; } else if (axisType == AxisType.DailyWithHourlyLabels) { minorLabel = "{0:%h%t}"; } // Add some extra spacing if putting minor labels in. float minorLabelSpacing = 0; if (nextMinor != null && minorLabel != null) { minorLabelSpacing = 1f / 16; } // StringFormat for drawing major labels: StringFormat majorForm = new StringFormat(); if (axisType == AxisType.MonthsVertical || axisType == AxisType.Quarters) { majorForm.FormatFlags = StringFormatFlags.DirectionVertical; } // Determine first major label value. DateTime dtLeft; if (axisType == AxisType.Quarters) { // set v to beginning of quarter which ScaleMinimum is in dtLeft = new DateTime(ScaleMinimum.Year, (((ScaleMinimum.Month - 1) / 3) * 3) + 1, 1); } else if (axisType == AxisType.DailyWithHourlyTicks || axisType == AxisType.DailyWithHourlyLabels) { // set v to beginning of day dtLeft = new DateTime(ScaleMinimum.Year, ScaleMinimum.Month, ScaleMinimum.Day); } else { // set v to beginning of month dtLeft = new DateTime(ScaleMinimum.Year, ScaleMinimum.Month, 1); } for (int i = 0; i < calculateNumLabels(); i++) { float xLeft = DataToCoordinate(dtLeft, area); xLeft = Math.Max(xLeft, area.TopLeft.X); if (xLeft > area.BottomRight.X) { break; } DateTime dtRight = nextMajor(dtLeft); float xRight = DataToCoordinate(dtRight, area); xRight = Math.Min(xRight, area.BottomRight.X); // Major ticks & gridlines: g.DrawLine(p, xLeft, area.TopLeft.Y, xLeft, area.TopLeft.Y + tickLength); if (gridlinesEnabled && xLeft > area.TopLeft.X && xLeft < area.BottomRight.X) { g.DrawLine(pgrid, xLeft, plotArea.TopLeft.Y, xLeft, plotArea.BottomRight.Y); } // Minor ticks: if (nextMinor != null) { DateTime dtMinorLeft = nextMinor(dtLeft); while (dtMinorLeft < dtRight) { float xMinorLeft = DataToCoordinate(dtMinorLeft, area); if (xMinorLeft > area.TopLeft.X && xMinorLeft < area.BottomRight.X) { g.DrawLine(pminor, xMinorLeft, area.TopLeft.Y, xMinorLeft, area.TopLeft.Y + minorTickLength); } dtMinorLeft = nextMinor(dtMinorLeft); } } if (minorLabel != null && nextMinor != null) { DateTime dtMinorLeft = dtLeft; while (dtMinorLeft < dtRight) { DateTime dtMinorRight = nextMinor(dtMinorLeft); float xMinorLeft = DataToCoordinate(dtMinorLeft, area); float xMinorRight = DataToCoordinate(dtMinorRight, area); if (xMinorLeft >= area.TopLeft.X && xMinorRight <= area.BottomRight.X) { string dtxt = String.Format(minorLabel, dtMinorLeft); SizeF dsz = g.MeasureString(dtxt, f2); float xlabel = ((xMinorLeft + xMinorRight) / 2) - (dsz.Width / 2); if (xlabel > area.TopLeft.X && (xlabel + dsz.Width) < area.BottomRight.X) { g.DrawString(dtxt, f2, br, ((xMinorLeft + xMinorRight) / 2) - (dsz.Width / 2), area.TopLeft.Y); } } dtMinorLeft = dtMinorRight; } } // Draw major label: string txt = String.Format(majorLabel, dtLeft, (dtLeft.Month / 3) + 1); SizeF sz = g.MeasureString(txt, f, 100, majorForm); float draw_x = ((xLeft + xRight) / 2) - (sz.Width / 2); if (draw_x > area.TopLeft.X && (draw_x + sz.Width) < area.BottomRight.X) { g.DrawString(txt, f, br, ((xLeft + xRight) / 2) - (sz.Width / 2), area.TopLeft.Y + tickLength + minorLabelSpacing, majorForm); } dtLeft = dtRight; } // one final tick to signify end of last visible month float xL = DataToCoordinate(dtLeft, area); if (xL < area.BottomRight.X) { g.DrawLine(p, xL, area.TopLeft.Y, xL, area.TopLeft.Y + tickLength); if (gridlinesEnabled) { g.DrawLine(pgrid, xL, plotArea.TopLeft.Y, xL, plotArea.BottomRight.Y); } } } g.Restore(_s); }