/// <summary> /// Paints the chart /// </summary> protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); if (ClientSize.Width == 0 || ClientSize.Height == 0) { return; } var bitmap = new Bitmap(ClientSize.Width, ClientSize.Height); Graphics g = Graphics.FromImage(bitmap); // Caption bar Data.GradientPaint(g, rectfCaption, LayoutColors.ColorCaptionBack, LayoutColors.DepthCaption); g.DrawString(chartTitle, Font, new SolidBrush(LayoutColors.ColorCaptionText), rectfCaption, stringFormatCaption); // Border g.DrawLine(penBorder, 1, captionHeight, 1, ClientSize.Height); g.DrawLine(penBorder, ClientSize.Width - Border + 1, captionHeight, ClientSize.Width - Border + 1, ClientSize.Height); g.DrawLine(penBorder, 0, ClientSize.Height - Border + 1, ClientSize.Width, ClientSize.Height - Border + 1); // Paints the background by gradient var rectChartField = new RectangleF(Border, captionHeight, ClientSize.Width - 2 * Border, ClientSize.Height - captionHeight - Border); Data.GradientPaint(g, rectChartField, LayoutColors.ColorChartBack, LayoutColors.DepthControl); if (isNotPaint) { return; } // Grid and Price labels for (int labelPrice = data.Minimum; labelPrice <= data.Minimum + countLabels * labelStep; labelPrice += labelStep) { var labelY = (int)(yBottom - (labelPrice - data.Minimum) * yScale); g.DrawString(labelPrice.ToString(CultureInfo.InvariantCulture), Font, brushFore, xRight, labelY - Font.Height / 2 - 1); g.DrawLine(penGrid, xLeft, labelY, xRight, labelY); } // Price close if (showPriceLine) { g.DrawLines(new Pen(LayoutColors.ColorChartGrid), closePricePoints); } // Equity line g.DrawLines(new Pen(LayoutColors.ColorChartEquityLine), equityPoints); // Draw Long and Short balance if (Configs.AdditionalStatistics) { g.DrawLines(new Pen(Color.Red), shortBalancePoints); g.DrawLines(new Pen(Color.Green), longBalancePoints); } // Out of Sample if (IsOOS && OOSBar > 0) { g.DrawLine(new Pen(LayoutColors.ColorChartFore), xOOSBar, yTop, xOOSBar, yBottom); Brush brushOOS = new Pen(LayoutColors.ColorChartFore).Brush; g.DrawString("OOS", Font, brushOOS, xOOSBar, yBottom - Font.Height); float widthOOSBarDate = g.MeasureString(data.DataTimeBarOOS.ToShortDateString(), Font).Width; g.DrawString(data.DataTimeBarOOS.ToShortDateString(), Font, brushOOS, xOOSBar - widthOOSBarDate, yBottom - Font.Height); } // Draw Balance Line if (data.MarginCallBar > 0) // In case of Margin Call { // Draw balance line up to Margin Call var balPoints = new PointF[data.MarginCallBar - data.FirstBar]; for (int i = 0; i < balPoints.Length; i++) { balPoints[i] = balancePoints[i]; } if (balPoints.Length > 1) { g.DrawLines(new Pen(LayoutColors.ColorChartBalanceLine), balPoints); } // Draw balance line after Margin Call var redBalancePoints = new PointF[data.Bars - data.MarginCallBar]; for (int i = 0; i < redBalancePoints.Length; i++) { redBalancePoints[i] = balancePoints[i + data.MarginCallBar - data.FirstBar]; } g.DrawLines(new Pen(LayoutColors.ColorSignalRed), redBalancePoints); // Margin Call line g.DrawLine(new Pen(LayoutColors.ColorChartCross), xMarginCallBar, yTop, xMarginCallBar, yBottom); // Margin Call label float widthMarginCallLabel = g.MeasureString(Language.T("Margin Call"), Font).Width; if (xMarginCallBar < xRight - widthMarginCallLabel) { g.DrawString(Language.T("Margin Call"), Font, brushFore, xMarginCallBar, yTop); } else if (xMarginCallBar > Space + widthMarginCallLabel) { g.DrawString(Language.T("Margin Call"), Font, brushFore, xMarginCallBar - widthMarginCallLabel, yTop); } else { g.DrawString("MC", Font, brushFore, xMarginCallBar, yTop); } } else { // Draw the balance line g.DrawLines(new Pen(LayoutColors.ColorChartBalanceLine), balancePoints); } // Scanning note var fontNote = new Font(Font.FontFamily, Font.Size - 1); if (Data.Period != DataPeriod.M1 && Configs.Autoscan && !Data.IsIntrabarData) { g.DrawString(Language.T("Load intrabar data"), fontNote, Brushes.Red, xLeft, captionHeight - 2); } else if (Data.Period != DataPeriod.M1 && isScanPerformed) { g.DrawString(Language.T("Scanned") + data.ModellingQuolity, fontNote, Brushes.LimeGreen, xLeft, captionHeight - 2); } // Scanned bars if (isScanPerformed && !isHideScanningLine && (Data.IntraBars != null && Data.IsIntrabarData || Data.Period == DataPeriod.M1 && Data.IsTickData && Configs.UseTickData)) { DataPeriod dataPeriod = Data.Period; Color color = Data.PeriodColor[Data.Period]; int fromBar = data.FirstBar; for (int bar = data.FirstBar; bar < data.Bars; bar++) { if (Data.IntraBarsPeriods[bar] == dataPeriod && bar != data.Bars - 1) { continue; } int xStart = (int)((fromBar - data.FirstBar) * xScale) + xLeft; int xEnd = (int)((bar - data.FirstBar) * xScale) + xLeft; fromBar = bar; dataPeriod = Data.IntraBarsPeriods[bar]; Data.GradientPaint(g, new RectangleF(xStart, yBottom + 4, xEnd - xStart + 2, 5), color, 60); color = Data.PeriodColor[Data.IntraBarsPeriods[bar]]; } // Tick Data if (Data.IsTickData && Configs.UseTickData) { int firstBarWithTicks = -1; int lastBarWithTicks = -1; for (int b = 0; b < data.Bars; b++) { if (firstBarWithTicks == -1 && Data.TickData[b] != null) { firstBarWithTicks = b; } if (Data.TickData[b] != null) { lastBarWithTicks = b; } } int xStart = (int)(firstBarWithTicks * xScale) + xLeft; int xEnd = (int)((lastBarWithTicks - data.FirstBar) * xScale) + xLeft; if (xStart < xLeft) { xStart = xLeft; } if (xEnd < xStart) { xEnd = xStart; } Data.DrawCheckerBoard(g, Color.ForestGreen, new Rectangle(xStart, yBottom + 5, xEnd - xStart + 2, 3)); } // Vertical coordinate axes g.DrawLine(new Pen(LayoutColors.ColorChartFore), xLeft - 1, yBottom, xLeft - 1, yBottom + 9); } // Coordinate axes g.DrawLine(new Pen(LayoutColors.ColorChartFore), xLeft - 1, yTop - Space, xLeft - 1, yBottom + 1); g.DrawLine(new Pen(LayoutColors.ColorChartFore), xLeft - 1, yBottom + 1, xRight, yBottom + 1); // Balance level g.DrawLine(new Pen(LayoutColors.ColorChartCross), xLeft, yBalance, xRight - Space + 1, yBalance); // Balance label var labelSize = new Size(labelWidth + Space, Font.Height + 2); var labelPoint = new Point(xRight - Space + 2, (int)(yBalance - Font.Height / 2.0 - 1)); var labelRect = new Rectangle(labelPoint, labelSize); g.FillRectangle(new SolidBrush(LayoutColors.ColorLabelBack), labelRect); g.DrawRectangle(new Pen(LayoutColors.ColorChartCross), labelRect); g.DrawString((Math.Round(data.NetBalance)).ToString(CultureInfo.InvariantCulture), Font, new SolidBrush(LayoutColors.ColorLabelText), labelRect, stringFormatCaption); DIBSection.DrawOnPaint(e.Graphics, bitmap, Width, Height); }
/// <summary> /// Paints the charts /// </summary> private void PnlChartPaint(object sender, PaintEventArgs e) { var pnl = (Panel)sender; Graphics g = e.Graphics; const int space = 5; const int border = 2; // Chart Title string unit = " [" + (Configs.AccountInMoney ? Configs.AccountCurrency : Language.T("points")) + "]"; string str = Language.T("Balance Chart") + unit; var font = new Font(Font.FontFamily, 9); var fCaptionHeight = (float)Math.Max(font.Height, 18); var rectfCaption = new RectangleF(0, 0, pnl.ClientSize.Width, fCaptionHeight); var stringFormatCaption = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; Data.GradientPaint(g, rectfCaption, LayoutColors.ColorCaptionBack, LayoutColors.DepthCaption); g.DrawString(str, Font, new SolidBrush(LayoutColors.ColorCaptionText), rectfCaption, stringFormatCaption); // Paint the panel background var rectClient = new RectangleF(border, fCaptionHeight, pnl.ClientSize.Width - 2 * border, pnl.Height - fCaptionHeight - border); Data.GradientPaint(g, rectClient, LayoutColors.ColorChartBack, LayoutColors.DepthControl); var penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border); g.DrawLine(penBorder, 1, fCaptionHeight, 1, pnl.ClientSize.Height); g.DrawLine(penBorder, pnl.ClientSize.Width - border + 1, fCaptionHeight, pnl.ClientSize.Width - border + 1, pnl.ClientSize.Height); g.DrawLine(penBorder, 0, pnl.ClientSize.Height - border + 1, pnl.ClientSize.Width, pnl.ClientSize.Height - border + 1); if (!isPaintChart) { if (Backtester.AmbiguousBars == 0) { string sNote = Language.T("The Comparator is useful when the backtest shows ambiguous bars!"); var rectfNote = new RectangleF(0, 30, pnl.ClientSize.Width, Font.Height); g.DrawString(sNote, Font, new SolidBrush(LayoutColors.ColorChartFore), rectfNote, stringFormatCaption); } return; } int bars = Data.Bars - Data.FirstBar; int max = (int)Math.Max(maximum, maximumRandom) + 1; int min = (int)Math.Min(minimum, minimumRandom) - 1; min = (int)Math.Floor(min / 10f) * 10; int yTop = (int)fCaptionHeight + 2 * space + 1; int yBottom = (pnl.ClientSize.Height - 2 * space - border); var labelWidth = (int) Math.Max(g.MeasureString(min.ToString(CultureInfo.InvariantCulture), Font).Width, g.MeasureString(max.ToString(CultureInfo.InvariantCulture), Font).Width); labelWidth = Math.Max(labelWidth, 30); int xRight = pnl.ClientSize.Width - border - space - labelWidth; int xLeft = border + space; // // Grid // int cntLabels = Math.Max((yBottom - yTop) / 20, 1); var delta = (float)Math.Max(Math.Round((max - min) / (float)cntLabels), 10); int step = (int)Math.Ceiling(delta / 10) * 10; cntLabels = (int)Math.Ceiling((max - min) / (float)step); max = min + cntLabels * step; float scaleY = (yBottom - yTop) / (cntLabels * (float)step); Brush brushFore = new SolidBrush(LayoutColors.ColorChartFore); var penGrid = new Pen(LayoutColors.ColorChartGrid) { DashStyle = DashStyle.Dash, DashPattern = new float[] { 4, 2 } }; // Price labels for (int label = min; label <= max; label += step) { var labelY = (int)(yBottom - (label - min) * scaleY); g.DrawString(label.ToString(CultureInfo.InvariantCulture), Font, brushFore, xRight, labelY - Font.Height / 2 - 1); g.DrawLine(penGrid, border + space, labelY, xRight, labelY); } float xScale = (xRight - 2 * space - border) / (float)bars; if (isRandom) { // Draws the random area and Min Max lines var apntMinRandom = new PointF[bars]; var apntMaxRandom = new PointF[bars]; for (int iBar = 0; iBar < bars; iBar++) { apntMinRandom[iBar].X = border + space + iBar * xScale; apntMinRandom[iBar].Y = yBottom - (afMinRandom[iBar] - min) * scaleY; apntMaxRandom[iBar].X = border + space + iBar * xScale; apntMaxRandom[iBar].Y = yBottom - (afMaxRandom[iBar] - min) * scaleY; } apntMinRandom[0].Y = apntMaxRandom[0].Y; var path = new GraphicsPath(); path.AddLines(apntMinRandom); path.AddLine(apntMinRandom[bars - 1], apntMaxRandom[bars - 1]); path.AddLines(apntMaxRandom); var region = new Region(path); g.FillRegion(brushRandArea, region); g.DrawLines(penRandBands, apntMinRandom); g.DrawLines(penRandBands, apntMaxRandom); } // Draws the lines for (int m = 0; m < countMethods; m++) { if (!AchboxMethods[m].Checked) { continue; } var apntLines = new PointF[bars]; for (int iBar = 0; iBar < bars; iBar++) { apntLines[iBar].X = border + space + iBar * xScale; apntLines[iBar].Y = yBottom - (afMethods[m, iBar] - min) * scaleY; } var pen = new Pen(LayoutColors.ColorSignalRed); switch ((InterpolationMethod)AchboxMethods[m].Tag) { case InterpolationMethod.Pessimistic: pen = penPessimistic; break; case InterpolationMethod.Shortest: pen = penShortest; break; case InterpolationMethod.Nearest: pen = penNearest; break; case InterpolationMethod.Optimistic: pen = penOptimistic; break; case InterpolationMethod.Random: pen = penRandom; break; } g.DrawLines(pen, apntLines); } // Draws the average balance var apntBalance = new PointF[bars]; for (int bar = 0; bar < bars; bar++) { apntBalance[bar].X = border + space + bar * xScale; apntBalance[bar].Y = yBottom - (afBalance[bar] - min) * scaleY; } g.DrawLines(penBalance, apntBalance); // Coordinate axes g.DrawLine(new Pen(LayoutColors.ColorChartFore), xLeft - 1, yTop - space, xLeft - 1, yBottom); g.DrawLine(new Pen(LayoutColors.ColorChartFore), xLeft, yBottom, xRight, yBottom); // Balance label float fBalanceY = yBottom - (afBalance[bars - 1] - min) * scaleY; g.DrawLine(new Pen(LayoutColors.ColorChartCross), xLeft, fBalanceY, xRight - space, fBalanceY); var szBalance = new Size(labelWidth + space, Font.Height + 2); var point = new Point(xRight - space + 2, (int)(fBalanceY - Font.Height / 2.0 - 1)); var rec = new Rectangle(point, szBalance); string sBalance = ((int)afBalance[bars - 1]).ToString(CultureInfo.InvariantCulture); g.FillRectangle(new SolidBrush(LayoutColors.ColorLabelBack), rec); g.DrawRectangle(new Pen(LayoutColors.ColorChartCross), rec); g.DrawString(sBalance, Font, new SolidBrush(LayoutColors.ColorLabelText), rec, stringFormatCaption); // Scanning note var fontNote = new Font(Font.FontFamily, Font.Size - 1); if (Configs.Autoscan && !Data.IsIntrabarData) { g.DrawString(Language.T("Load intrabar data"), fontNote, Brushes.Red, xLeft, fCaptionHeight - 2); } else if (Backtester.IsScanPerformed) { g.DrawString(Language.T("Scanned") + " MQ " + Data.ModellingQuality.ToString("N2") + "%", fontNote, Brushes.LimeGreen, border + space, fCaptionHeight - 2); } // Scanned bars if (Backtester.IsScanPerformed && (Data.IntraBars != null && Data.IsIntrabarData || Data.Period == DataPeriod.M1 && Data.IsTickData && Configs.UseTickData)) { g.DrawLine(new Pen(LayoutColors.ColorChartFore), xLeft - 1, yBottom, xLeft - 1, yBottom + 8); DataPeriod dataPeriod = Data.Period; Color color = Data.PeriodColor[Data.Period]; int iFromBar = Data.FirstBar; for (int bar = Data.FirstBar; bar < Data.Bars; bar++) { if (Data.IntraBarsPeriods[bar] != dataPeriod || bar == Data.Bars - 1) { int xStart = (int)((iFromBar - Data.FirstBar) * xScale) + xLeft; int xEnd = (int)((bar - Data.FirstBar) * xScale) + xLeft; iFromBar = bar; dataPeriod = Data.IntraBarsPeriods[bar]; Data.GradientPaint(g, new RectangleF(xStart, yBottom + 3, xEnd - xStart + 2, 5), color, 60); color = Data.PeriodColor[Data.IntraBarsPeriods[bar]]; } } // Tick Data if (Data.IsTickData && Configs.UseTickData) { int firstBarWithTicks = -1; int lastBarWithTicks = -1; for (int b = 0; b < Data.Bars; b++) { if (firstBarWithTicks == -1 && Data.TickData[b] != null) { firstBarWithTicks = b; } if (Data.TickData[b] != null) { lastBarWithTicks = b; } } int xStart = (int)(firstBarWithTicks * xScale) + xLeft; int xEnd = (int)((lastBarWithTicks - Data.FirstBar) * xScale) + xLeft; if (xStart < xLeft) { xStart = xLeft; } if (xEnd < xStart) { xEnd = xStart; } Data.DrawCheckerBoard(g, Color.ForestGreen, new Rectangle(xStart, yBottom + 4, xEnd - xStart + 2, 3)); } } }
/// <summary> /// Repaint the panel Info /// </summary> private void PnlInfoPaint(object sender, PaintEventArgs e) { // +------------------------------------------------------+ // | Data | // |------------------- ----------------------------------+ // | Period | Bars | From | Until | Cover | % | Label | // |------------------------------------------------------+ //xp0 xp1 xp2 xp3 xp4 xp5 xp6 xp7 Graphics g = e.Graphics; g.Clear(LayoutColors.ColorControlBack); if (!Data.IsData || !Data.IsResult) { return; } var pnl = (Panel)sender; const int border = 2; const int xp0 = border; const int xp1 = 80; const int xp2 = 140; const int xp3 = 200; const int xp4 = 260; const int xp5 = 320; const int xp6 = 370; int xp7 = pnl.ClientSize.Width - border; var size = new Size(xp7 - xp0, infoRowHeight); var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Near }; // Caption background var pntStart = new PointF(0, 0); SizeF szfCaption = new Size(pnl.ClientSize.Width - 0, 2 * infoRowHeight); var rectfCaption = new RectangleF(pntStart, szfCaption); Data.GradientPaint(g, rectfCaption, LayoutColors.ColorCaptionBack, LayoutColors.DepthCaption); // Caption Text var stringFormatCaption = new StringFormat { LineAlignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter, FormatFlags = StringFormatFlags.NoWrap, Alignment = StringAlignment.Near }; string stringCaptionText = Language.T("Intrabar Data"); float captionWidth = Math.Min(InfoPanel.ClientSize.Width, xp7 - xp0); float captionTextWidth = g.MeasureString(stringCaptionText, fontInfo).Width; float captionTextX = Math.Max((captionWidth - captionTextWidth) / 2f, 0); var pfCaptionText = new PointF(captionTextX, 0); var sfCaptionText = new SizeF(captionWidth - captionTextX, infoRowHeight); rectfCaption = new RectangleF(pfCaptionText, sfCaptionText); Brush brush = new SolidBrush(LayoutColors.ColorCaptionText); // First caption row g.DrawString(stringCaptionText, fontInfo, brush, rectfCaption, stringFormatCaption); // Second title row g.DrawString(Language.T("Period"), fontInfo, brush, (xp1 + xp0) / 2f, infoRowHeight, sf); g.DrawString(Language.T("Bars"), fontInfo, brush, (xp2 + xp1) / 2f, infoRowHeight, sf); g.DrawString(Language.T("From"), fontInfo, brush, (xp3 + xp2) / 2f, infoRowHeight, sf); g.DrawString(Language.T("Until"), fontInfo, brush, (xp4 + xp3) / 2f, infoRowHeight, sf); g.DrawString(Language.T("Coverage"), fontInfo, brush, (xp5 + xp4) / 2f, infoRowHeight, sf); g.DrawString("%", fontInfo, brush, (xp6 + xp5) / 2f, infoRowHeight, sf); g.DrawString(Language.T("Label"), fontInfo, brush, (xp7 + xp6) / 2f, infoRowHeight, sf); brush = new SolidBrush(LayoutColors.ColorControlText); int allPeriods = Enum.GetValues(typeof(DataPeriod)).Length; for (int period = 0; period <= allPeriods; period++) { int y = (period + 2) * infoRowHeight; var point = new Point(xp0, y); if (Math.Abs(period % 2f - 0) > 0.0001) { g.FillRectangle(new SolidBrush(LayoutColors.ColorEvenRowBack), new Rectangle(point, size)); } } // Tick statistics if (isTickDataFile) { g.DrawString(Language.T("Tick"), fontInfo, brush, (xp1 + xp0) / 2, 2 * infoRowHeight, sf); if (Data.IsTickData && Configs.UseTickData) { int firstBarWithTicks = -1; int lastBarWithTicks = -1; int tickBars = 0; for (int b = 0; b < Data.Bars; b++) { if (firstBarWithTicks == -1 && Data.TickData[b] != null) { firstBarWithTicks = b; } if (Data.TickData[b] != null) { lastBarWithTicks = b; tickBars++; } } double percentage = 100d * tickBars / Data.Bars; int y = 2 * infoRowHeight; string ticks = (Data.Ticks > 999999) ? (Data.Ticks / 1000).ToString(CultureInfo.InvariantCulture) + "K" : Data.Ticks.ToString(CultureInfo.InvariantCulture); g.DrawString(ticks, fontInfo, brush, (xp2 + xp1) / 2, y, sf); g.DrawString((firstBarWithTicks + 1).ToString(CultureInfo.InvariantCulture), fontInfo, brush, (xp3 + xp2) / 2, y, sf); g.DrawString((lastBarWithTicks + 1).ToString(CultureInfo.InvariantCulture), fontInfo, brush, (xp4 + xp3) / 2, y, sf); g.DrawString(tickBars.ToString(CultureInfo.InvariantCulture), fontInfo, brush, (xp5 + xp4) / 2, y, sf); g.DrawString(percentage.ToString("F2"), fontInfo, brush, (xp6 + xp5) / 2, y, sf); Data.DrawCheckerBoard(g, Color.ForestGreen, new Rectangle(xp6 + 10, y + 4, xp7 - xp6 - 20, 9)); } } for (int prd = 0; prd < allPeriods; prd++) { int startY = isTickDataFile ? 3 : 2; int y = (prd + startY) * infoRowHeight; var period = (DataPeriod)Enum.GetValues(typeof(DataPeriod)).GetValue(prd); int intraBars = Data.IntraBars == null || !Data.IsIntrabarData ? 0 : Data.IntraBars[prd]; int fromBar = 0; int untilBar = 0; int coveredBars = 0; double percentage = 0; bool isMultyAreas = false; if (intraBars > 0) { bool isFromBarFound = false; bool isUntilBarFound = false; untilBar = Data.Bars; for (int bar = 0; bar < Data.Bars; bar++) { if (!isFromBarFound && Data.IntraBarsPeriods[bar] == period) { fromBar = bar; isFromBarFound = true; } if (isFromBarFound && !isUntilBarFound && (Data.IntraBarsPeriods[bar] != period || bar == Data.Bars - 1)) { if (bar < Data.Bars - 1) { isUntilBarFound = true; untilBar = bar; } else { untilBar = Data.Bars; } coveredBars = untilBar - fromBar; } if (isFromBarFound && isUntilBarFound && Data.IntraBarsPeriods[bar] == period) { isMultyAreas = true; coveredBars++; } } if (isFromBarFound) { percentage = 100d * coveredBars / Data.Bars; fromBar++; } else { fromBar = 0; untilBar = 0; coveredBars = 0; percentage = 0; } } else if (period == Data.Period) { intraBars = Data.Bars; fromBar = 1; untilBar = Data.Bars; coveredBars = Data.Bars; percentage = 100; } g.DrawString(Data.DataPeriodToString(period), fontInfo, brush, (xp1 + xp0) / 2, y, sf); if (coveredBars > 0 || period == Data.Period) { g.DrawString(intraBars.ToString(CultureInfo.InvariantCulture), fontInfo, brush, (xp2 + xp1) / 2, y, sf); g.DrawString(fromBar.ToString(CultureInfo.InvariantCulture), fontInfo, brush, (xp3 + xp2) / 2, y, sf); g.DrawString(untilBar.ToString(CultureInfo.InvariantCulture), fontInfo, brush, (xp4 + xp3) / 2, y, sf); g.DrawString(coveredBars.ToString(CultureInfo.InvariantCulture) + (isMultyAreas ? "*" : ""), fontInfo, brush, (xp5 + xp4) / 2, y, sf); g.DrawString(percentage.ToString("F2"), fontInfo, brush, (xp6 + xp5) / 2, y, sf); var rectf = new RectangleF(xp6 + 10, y + 4, xp7 - xp6 - 20, 9); Data.GradientPaint(g, rectf, Data.PeriodColor[period], 60); } } var penLine = new Pen(LayoutColors.ColorJournalLines); g.DrawLine(penLine, xp1, 2 * infoRowHeight, xp1, pnl.ClientSize.Height); g.DrawLine(penLine, xp2, 2 * infoRowHeight, xp2, pnl.ClientSize.Height); g.DrawLine(penLine, xp3, 2 * infoRowHeight, xp3, pnl.ClientSize.Height); g.DrawLine(penLine, xp4, 2 * infoRowHeight, xp4, pnl.ClientSize.Height); g.DrawLine(penLine, xp5, 2 * infoRowHeight, xp5, pnl.ClientSize.Height); g.DrawLine(penLine, xp6, 2 * infoRowHeight, xp6, pnl.ClientSize.Height); // Border var penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border); g.DrawLine(penBorder, 1, 2 * infoRowHeight, 1, pnl.ClientSize.Height); g.DrawLine(penBorder, pnl.ClientSize.Width - border + 1, 2 * infoRowHeight, pnl.ClientSize.Width - border + 1, pnl.ClientSize.Height); g.DrawLine(penBorder, 0, pnl.ClientSize.Height - border + 1, pnl.ClientSize.Width, pnl.ClientSize.Height - border + 1); }