/// <summary> /// Draw additional image. /// </summary> protected override void DrawInitialActualSpaceOverlays(GraphicsWrapper g, TimeBasedChartSeries timeBasedSeries) { base.DrawInitialActualSpaceOverlays(g, timeBasedSeries); if (_showMasterSynchronizationImage && _masterSynchronizationImage != null) { g.DrawImageUnscaledAndClipped(_masterSynchronizationImage, new Rectangle(4, (int)LabelsTopMargin, _masterSynchronizationImage.Width, _masterSynchronizationImage.Height)); } }
/// <summary> /// Initial part of drawing, called by Draw(). /// Method takes care of setting up the basic drawing parameters of the chart, required for the drawing /// to be done; also draws the system overlays. /// </summary> protected virtual void DrawInitialActualSpaceOverlays(GraphicsWrapper g, TimeBasedChartSeries timeBasedSeries) { // Since this is dependant on current graphics scaling, also recalculate it here now. UpdateYAxisSpacings(); CalculateActualDrawingSpaceAreaMarginTopAndBottom(); if (XAxisLabels) {// X Axis Labels float totalItemWidth = _seriesItemWidth + _seriesItemMargin; float actualXSpacing = _xAxisLabelSpacing * totalItemWidth; // Consider X axis label scaling. int xScaling = Math.Abs((int)(1 / _graphicsWrapper.DrawingSpaceTransformClone.Elements[0])); if (xScaling > 1) { actualXSpacing = actualXSpacing * xScaling; } // Set starting to the closes compatible positionactualXSpacing // TODO : this can be optimized further by narrowing the range of xStart to end float xStart = (int)(_drawingSpaceDisplayLimit.X / actualXSpacing); xStart = xStart * actualXSpacing; SizeF xAxisLabelTypicalSize = g.MeasureString("00/00/000 00:00", _axisLabelsFont); for (float i = xStart; i < _drawingSpaceDisplayLimit.X + _drawingSpaceDisplayLimit.Width; i += actualXSpacing) { PointF point = GraphicsWrapper.DrawingSpaceToActualSpace(new PointF(i, 0), true); if (point.X > (_actualDrawingSpaceArea.X - 2) && point.X < (_actualDrawingSpaceArea.X + _actualDrawingSpaceArea.Width + 2 - xAxisLabelTypicalSize.Width)) { int index = (int)(i / totalItemWidth); string message = string.Empty; if (timeBasedSeries != null) {// If there is a leading dateAssignedSeries show labels based on its timing. if (index < timeBasedSeries.ItemsCount) { message = GeneralHelper.GetShortDateTime(timeBasedSeries.GetTimeAtIndex(index)); } } else { message = index.ToString(_xAxisLabelsFormat); } if (_axisLabelsFont != null && _xAxisLabelsFontBrush != null) { g.DrawString(message, _axisLabelsFont, _xAxisLabelsFontBrush, point.X, _actualDrawingSpaceArea.Y + _actualDrawingSpaceArea.Height); } // Draw the small line indicating where the string applies for. g.DrawLine(_actualDrawingSpaceAreaBorderPen, point.X, _actualDrawingSpaceArea.Y + _actualDrawingSpaceArea.Height, point.X, _actualDrawingSpaceArea.Y + _actualDrawingSpaceArea.Height + 5); } } } // X Axis Labels. _actualDrawingSpaceAreaMarginLeft = _additionalDrawingSpaceAreaMarginLeft + 5; _actualDrawingSpaceAreaMarginRight = _additionalDrawingSpaceAreaMarginRight + 5; if (YAxisLabels) {// Y Axis Labels. int yAxisLabelsWidth = 0; // Set starting to the closes compatible positionactualYSpacing int maxDecimalPlaces = _autoYAxisLabelSpacing.ToString().Length - 1; float yStart = (int)(_drawingSpaceDisplayLimit.Y / _autoYAxisLabelSpacing); yStart = yStart * _autoYAxisLabelSpacing; // Round off to a fixed number of post decimal point digits, will only work for values under 1 yStart = (float)Math.Round(yStart, maxDecimalPlaces); // This must auto adjust to format the number properly and always fit in 6 spaces. // Specify positive, negative and zero formats. //_yAxisLabelsFormat = " #0.###;-#0.###; Zero"; int separatorPosition = _yAxisLabelsFormat.IndexOf(";", 0) - 1; // The default is 6 positions total for the y axis labels. yAxisLabelsWidth = ((int)g.MeasureString(_yAxisLabelsFormat.Substring(0, separatorPosition), _axisLabelsFont).Width); // Calculate the current margin and confirm with any controling subscriber. int labelSpacingMargin = yAxisLabelsWidth; if (_yAxisLabelsPosition == YAxisLabelPosition.Left || _yAxisLabelsPosition == YAxisLabelPosition.Both) { _actualDrawingSpaceAreaMarginLeft += labelSpacingMargin; } if (_yAxisLabelsPosition == YAxisLabelPosition.Right || _yAxisLabelsPosition == YAxisLabelPosition.Both) { _actualDrawingSpaceAreaMarginRight += labelSpacingMargin; } if (_yAxisLabelsPosition != YAxisLabelPosition.None) { // A maximum of 10000 steps allowed for this drawing, otherwise some bug is probably present. if ((_drawingSpaceDisplayLimit.Y + _drawingSpaceDisplayLimit.Height - yStart) / _autoYAxisLabelSpacing < 10000) { // Pass 2 - actually draw the labels and label lines at the established and confirmed location. for (float i = yStart; i < _drawingSpaceDisplayLimit.Y + _drawingSpaceDisplayLimit.Height; i += _autoYAxisLabelSpacing) { float iRound = (float)Math.Round(i, maxDecimalPlaces); PointF point = GraphicsWrapper.DrawingSpaceToActualSpace(new PointF(0, iRound), true); if (point.Y <= _actualDrawingSpaceArea.Y - 5 || point.Y >= _actualDrawingSpaceArea.Y + _actualDrawingSpaceArea.Height) { continue; } // Draw labels on the left. if (_yAxisLabelsPosition == YAxisLabelPosition.Left || _yAxisLabelsPosition == YAxisLabelPosition.Both) { if (_axisLabelsFont != null && _yAxisLabelsFontBrush != null) { g.DrawString((iRound).ToString(_yAxisLabelsFormat), _axisLabelsFont, _yAxisLabelsFontBrush, _actualDrawingSpaceAreaMarginLeft - yAxisLabelsWidth - 3, point.Y); } // Draw the small line indicating where the string applies for. g.DrawLine(_actualDrawingSpaceAreaBorderPen, _actualDrawingSpaceAreaMarginLeft - 5, point.Y, _actualDrawingSpaceAreaMarginLeft, point.Y); } // Draw labels on the right. if (_yAxisLabelsPosition == YAxisLabelPosition.Right || _yAxisLabelsPosition == YAxisLabelPosition.Both) { if (_axisLabelsFont != null && _yAxisLabelsFontBrush != null) { g.DrawString((iRound).ToString(_yAxisLabelsFormat), _axisLabelsFont, _yAxisLabelsFontBrush, this.Width - yAxisLabelsWidth - 3, point.Y); } if (point.Y >= _actualDrawingSpaceArea.Y) { // Draw the small line indicating where the string applies for. g.DrawLine(_actualDrawingSpaceAreaBorderPen, this.Width - yAxisLabelsWidth - 6, point.Y, this.Width - yAxisLabelsWidth - 3, point.Y); } } } } else { SystemMonitor.OperationError("Too many steps in drawing planned."); } } } foreach (ChartSeries series in _series) { series.DrawInitialActualSpaceOverlays(this, g); } UpdateActualDrawingSpaceArea(); // Actual space, drawing area, grid. _actualSpaceGrid.Draw(g, _actualDrawingSpaceArea, _actualDrawingSpaceArea, 1); if (ShowSeriesLabels) { DrawGraphicSeriesLabels(g, _actualDrawingSpaceArea.Left); } // Show if (_customObjectsManager.IsBuildingObject) { g.DrawImageUnscaledAndClipped(_customObjectDrawingImage, new Rectangle(4, (int)LabelsTopMargin, _customObjectDrawingImage.Width, _customObjectDrawingImage.Height)); } }