CUstom Report Item -Report Service display arrow as the indictor of Range Chart
public class Spread { public string AssetClass { get; set; } public double StartValue { get; set; } public double EndValue { get; set; } public static List<Spread> GetSpreads() { Random r1 = new Random(), r2 = new Random(); List<Spread> spreads = new List<Spread>(); for (int i = 0; i < 20; i++) { int x=r1.Next(30,150); Spread s = new Spread { AssetClass = "Asset " + i, StartValue =x, EndValue =(int)(x+ x*(r2.NextDouble()-0.5)/3) }; spreads.Add(s); } return spreads; } }
void DrawSpreadChart(Graphics g, Spread[] spreads) { g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; DrawCaptial(g); DrawSubCaptial(g); DrawYLebal(g); DrawYAxis(spreads, g); DrawXLebal(g); DrawXAxis(spreads, g); DrawGrid(g); DrawIndictor(spreads, g); } //15 properties can be set for Spread chart int spread_width = 600;//1.Width of Spread Chart int spread_hight = 400;//2.Hight of Spread Chart #region Captial string caption = "European GSM Week Spreads";//3.Caption of Spread Chart string fontFamily = "Times New Roman";//4.Font Family of Spread Chart int captionSize = 8;//5.Caption Size int captionPxes = 8; void DrawCaptial(Graphics g) { using (Font font = new Font(fontFamily , captionSize , FontStyle.Bold, GraphicsUnit.Point)) { captionPxes =(int)Math.Ceiling ( font.GetHeight()); Rectangle rect = new Rectangle(0, 0, spread_width,captionPxes ); // Create a StringFormat object with the each line of text, and the block // of text centered on the page. StringFormat stringFormat = new StringFormat(); stringFormat.Alignment = StringAlignment.Center; stringFormat.LineAlignment = StringAlignment.Center; // Draw the text and the surrounding rectangle. g.DrawString(caption, font, Brushes.Black , rect, stringFormat); //g.DrawRectangle(Pens.Black, rect); } } string subCaption = "(<200bps)";//6.Sub-Caption of Spread Chart int subCaptionSize = 6; //7.Sub-Caption size int subCpatialPxes = 6; void DrawSubCaptial(Graphics g) { using (Font font = new Font(fontFamily, subCaptionSize, FontStyle.Bold, GraphicsUnit.Point)) { subCpatialPxes =(int)Math.Ceiling ( font.GetHeight()); Rectangle rect = new Rectangle(0, captionPxes , spread_width ,subCpatialPxes ); // Create a StringFormat object with the each line of text, and the block // of text centered on the page. StringFormat stringFormat = new StringFormat(); stringFormat.Alignment = StringAlignment.Center; stringFormat.LineAlignment = StringAlignment.Center ; // Draw the text and the surrounding rectangle. g.DrawString(subCaption , font, Brushes.Black, rect, stringFormat); //g.DrawRectangle(Pens.Red, rect); } } #endregion #region Y Label string ylabel = "Asset Class";//8.Label of Y Axis int yLabelSize = 8;//9.Label font size int yLabelPxes; void DrawYLebal(Graphics g) { using (Font font = new Font(fontFamily, yLabelSize, FontStyle.Bold , GraphicsUnit.Point)) { yLabelPxes=(int)Math .Ceiling (font.GetHeight ()); Rectangle rect = new Rectangle(0, captionPxes +subCpatialPxes,yLabelPxes , spread_hight-captionPxes -subCpatialPxes ); StringFormat stringFormat = new StringFormat(); stringFormat.FormatFlags = StringFormatFlags.DirectionVertical; stringFormat.Alignment = StringAlignment.Center ; stringFormat.LineAlignment = StringAlignment.Center; g.ResetTransform(); g.DrawString(ylabel , font, Brushes.Black , rect , stringFormat); //g.DrawRectangle(Pens.Black, rect); } } #endregion #region Y Axis int yGradeSize = 6;//10.Font size of Y Axis Grade double yGradeHight = 10; int maxYGradePxes = 10; int gradeLen = 2;//11.Grade Length for X/Y Axis int endY; int startY; int startX; int yCount; void DrawYAxis( Spread[] spreads,Graphics g) { yCount = spreads.Length; maxYGradePxes = (int)Math.Ceiling(spreads.Max(x => MeasueLegth(x.AssetClass, yGradeSize, FontStyle.Bold , g).Width)); startY = captionPxes + subCpatialPxes; startX = yLabelPxes + maxYGradePxes + gradeLen; endY = spread_hight - GetHightPxes(xLabelSize, FontStyle.Bold) - GetHightPxes(xGradeSize, FontStyle.Bold ); yGradeHight = (endY -startY )*1.0/spreads .Count() ; g.DrawLine(Pens.Black, new Point(startX , startY), new Point(startX , endY)); using (Font font = new Font(fontFamily, yGradeSize , FontStyle.Bold , GraphicsUnit.Point)) { for (int i = 0; i < spreads.Length; i++) { int y = (int)(startY + yGradeHight * i); Rectangle rect = new Rectangle(yLabelPxes, y, maxYGradePxes, (int)yGradeHight); // Create a StringFormat object with the each line of text, and the block // of text centered on the page. StringFormat stringFormat = new StringFormat(); stringFormat.Alignment = StringAlignment.Far; stringFormat.LineAlignment = StringAlignment.Center; // Draw the text and the surrounding rectangle. g.DrawString(spreads[i].AssetClass, font, Brushes.Black, rect, stringFormat); //g.DrawRectangle(Pens.Black, rect); g.DrawLine(Pens.Black, new Point(yLabelPxes + maxYGradePxes , y), new Point(yLabelPxes + maxYGradePxes + gradeLen, y)); } g.DrawLine(Pens.Black, new Point(yLabelPxes + maxYGradePxes, endY ), new Point(yLabelPxes + maxYGradePxes + gradeLen, endY )); } } #endregion #region X Label string xLabel = "Spreads";//12.Label of X Axis int xLabelSize = 8;//13.Size of X Axis Label int xLabelHightPxes = 10; void DrawXLebal(Graphics g) { using (Font font = new Font(fontFamily, xLabelSize , FontStyle.Bold, GraphicsUnit.Point)) { xLabelHightPxes = (int)Math.Ceiling(font.GetHeight()); Rectangle rect = new Rectangle(yLabelPxes +maxYGradePxes +gradeLen , spread_hight -xLabelHightPxes , spread_width-yLabelPxes -maxYGradePxes -gradeLen , xLabelHightPxes ); // Create a StringFormat object with the each line of text, and the block // of text centered on the page. StringFormat stringFormat = new StringFormat(); stringFormat.Alignment = StringAlignment.Center; stringFormat.LineAlignment = StringAlignment.Center; // Draw the text and the surrounding rectangle. g.DrawString(xLabel , font, Brushes.Black, rect, stringFormat); //g.DrawRectangle(Pens.Red, rect); } } #endregion #region X Axis int xGradeSize = 6; //14.Size of X Grade int xInternal = 10; //15.The step length of X Axis double xgradwith; int xcount; int minX; int maxX; int endX; void DrawXAxis(Spread[] spreads, Graphics g) { var xs = spreads.SelectMany(x => new double[] { x.StartValue, x.EndValue }).ToArray(); double _minX = xs.Min(), _maxX = xs.Max(); minX = ((int)Math.Floor ( _minX / xInternal)) * xInternal; maxX = ((int)Math.Ceiling(_maxX / xInternal)) * xInternal; int margRight = (int)Math.Ceiling(MeasueLegth(maxX.ToString(), xGradeSize, FontStyle.Bold , g).Width / 2); endX = spread_width - margRight; xcount = (maxX - minX) / xInternal+1; xgradwith = (spread_width - margRight - startX)*1.0 / xcount; g.DrawLine(Pens.Black, new Point(startX , endY ), new Point(spread_width -margRight , endY)); using (Font font = new Font(fontFamily, xGradeSize , FontStyle.Bold , GraphicsUnit.Point)) { for (int i = 0; i <= xcount; i++) { string xg = (minX + i * xInternal).ToString(); var xgS = MeasueLegth(xg, xGradeSize, FontStyle.Regular, g) ; double xv = startX + i * xgradwith; Rectangle rect = new Rectangle((int)(xv-xgS.Width/2), endY +gradeLen , (int) Math.Ceiling( xgS.Width) , (int) Math.Ceiling( xgS .Height)); // Create a StringFormat object with the each line of text, and the block // of text centered on the page. StringFormat stringFormat = new StringFormat(); stringFormat.Alignment = StringAlignment.Center ; stringFormat.LineAlignment = StringAlignment.Center; // Draw the text and the surrounding rectangle. g.DrawString(xg, font, Brushes.Black, rect, stringFormat); //g.DrawRectangle(Pens.Black, rect); g.DrawLine(Pens.Black, new Point((int)xv , endY ), new Point((int)xv , endY +gradeLen )); } } } #endregion #region Grids void DrawGrid(Graphics g) { int gridMarg =(int) Math.Floor( yGradeHight /3); for (int r = 0; r <= yCount / 3; r++) { int y0 = (int)(startY + 3*r * yGradeHight +gridMarg ); if (r == 0) y0 = startY ; int y1 = (int)(startY + 3 * (r + 1) * yGradeHight - gridMarg); if (y1 > endY) y1 = endY; for (int c = 1; c <= xcount; c++) { int x =(int)( startX + c * xgradwith); g.DrawLine(Pens.LightGray , x, y0, x, y1); } } } #endregion #region Indictor int arrow_rect_half_hight = 2; //a halft of the hight of the rectangle of the arrow int arrow_triangle_add_half_hight = 2;//a half of the triangle ofthe arrow more than arrow_rect_half_hight int arrow_triagle_width = 8;//the width of the triangle ofthe arrow void DrawIndictor(Spread[] spreads, Graphics g) { double unit = (endX - startX) / (maxX - minX); for (int i = 0; i < spreads.Length; i++) { Spread s = spreads[i]; int y = (int)(startY + (i + 0.5) * yGradeHight); int x0 = (int)(startX + (Math.Min(s.StartValue, s.EndValue) - minX) * unit); int x1 = (int)(startX + (Math.Max(s.StartValue, s.EndValue) - minX) * unit); Point[] ps; if (x1 - x0 < arrow_triagle_width) ps = new Point[] { new Point(x0,y-arrow_rect_half_hight ), new Point(x1,y-arrow_rect_half_hight ), new Point(x1,y+arrow_rect_half_hight ), new Point (x0,y+arrow_rect_half_hight ), new Point(x0,y-arrow_rect_half_hight )}; else if (x1 - x0 == arrow_triagle_width) { ps = new Point[] { new Point(x0,y-arrow_rect_half_hight-arrow_triangle_add_half_hight ), new Point(x1,y ), new Point (x0,y+arrow_rect_half_hight+arrow_triangle_add_half_hight ), new Point(x0,y-arrow_rect_half_hight-arrow_triangle_add_half_hight )}; } else if (s.EndValue > s.StartValue) { ps = new Point[] { new Point(x0, y-arrow_rect_half_hight ), new Point(x1-arrow_triagle_width , y-arrow_rect_half_hight), new Point(x1-arrow_triagle_width , y-arrow_rect_half_hight-arrow_triangle_add_half_hight), new Point(x1, y) , new Point(x1-arrow_triagle_width , y+arrow_rect_half_hight+arrow_triangle_add_half_hight), new Point(x1-arrow_triagle_width , y+arrow_rect_half_hight), new Point(x0, y+arrow_rect_half_hight ), new Point(x0, y-arrow_rect_half_hight ),}; } else { ps = new Point[] { new Point(x1, y-arrow_rect_half_hight ), new Point(x0+arrow_triagle_width , y-arrow_rect_half_hight), new Point(x0+arrow_triagle_width , y-arrow_rect_half_hight-arrow_triangle_add_half_hight), new Point(x0, y) , new Point(x0+arrow_triagle_width , y+arrow_rect_half_hight+arrow_triangle_add_half_hight), new Point(x0+arrow_triagle_width , y+arrow_rect_half_hight), new Point(x1, y+arrow_rect_half_hight ), new Point(x1, y-arrow_rect_half_hight ),}; } if (s.StartValue < s.EndValue) g.FillPolygon(Brushes.Red, ps); else g.FillPolygon(Brushes.Green, ps); } } #endregion #region Helpers int GetHightPxes(int size, FontStyle style) { using (Font font = new Font(fontFamily, size ,style, GraphicsUnit.Point)) { return (int)Math.Ceiling(font.GetHeight()); } } SizeF MeasueLegth(string txt, int size, FontStyle style, Graphics g) { using (Font font = new Font(fontFamily, size ,style, GraphicsUnit.Point)) { return g.MeasureString (txt ,font ); } } #endregion