public void Draw(GraphicsWrapper g, RectangleF clipping, RectangleF space, float totalItemWidth) { if (Visible == false) { return; } if (VerticalLineSpacing.HasValue) { float actualSpacing = _verticalLineSpacing.Value * totalItemWidth; if (ConsiderScale) { int xScaling = Math.Abs((int)(1 / g.DrawingSpaceTransformClone.Elements[0])); if (xScaling > 1) { actualSpacing = actualSpacing * xScaling; } } // Set starting to the closes compatible position. float starting = (int)(space.Left / actualSpacing); starting = starting * actualSpacing; for (float x = starting; x <= space.Right; x += actualSpacing) {// Vertical lines. if (x >= clipping.X && x <= clipping.X + clipping.Width + actualSpacing) { g.DrawLine(_pen, x, Math.Max(space.Top, clipping.Top), x, Math.Min(space.Bottom, clipping.Bottom)); } } } if (HorizontalLineSpacing.HasValue) { float actualSpacing = _horizontalLineSpacing.Value; if (ConsiderScale && double.IsInfinity(g.DrawingSpaceTransformClone.Elements[3]) == false && g.DrawingSpaceTransformClone.Elements[3] != 0) { int yScaling = Math.Abs((int)(1 / g.DrawingSpaceTransformClone.Elements[3])); if (yScaling > 1) { actualSpacing = actualSpacing * yScaling; } } // Set starting to the closes compatible position. float starting = (int)(space.Top / actualSpacing); starting = starting * actualSpacing; for (float y = starting; y <= space.Bottom; y += actualSpacing) {// Horizontal lines. if (y >= clipping.Y && y <= clipping.Y + clipping.Height) { g.DrawLine(_pen, Math.Max(space.Left, clipping.Left), y, Math.Min(space.Right, clipping.Right), y); } } } }
public override void Draw(ChartPane managingPane, GraphicsWrapper g, int unitsUnification, RectangleF clippingRectangle, float itemWidth, float itemMargin) { PointF drawingPoint = new PointF(); if (this.Visible == false) { return; } lock (this) { Image image; foreach (float value in _values) {// Images mode does not apply unit unification if (double.IsNaN(value) == false && drawingPoint.X >= clippingRectangle.X && drawingPoint.X <= clippingRectangle.X + clippingRectangle.Width && _images.ContainsKey((int)value)) { image = _images[(int)value]; g.DrawImage(image, drawingPoint.X + _imagesDisplacement.X - image.Width / 2, drawingPoint.Y + _imagesDisplacement.Y + (float)value); } drawingPoint.X += itemMargin + itemWidth; } } }
public void SynchronizeWithMasterPane() { if (_masterPane == null || _masterPaneSynchronizationMode == MasterPaneSynchronizationModeEnum.None) { return; } SystemMonitor.CheckThrow(_masterPaneSynchronizationMode == MasterPaneSynchronizationModeEnum.XAxis, "Mode not supported."); GraphicsWrapper.SynchronizeDrawingSpaceXAxis(_masterPane.GraphicsWrapper); this.YAxisLabelsPosition = _masterPane.YAxisLabelsPosition; //this.AutoScrollToEnd = _masterPane.AutoScrollToEnd; this.LimitedView = _masterPane.LimitedView; Crosshair.Visible = _masterPane.Crosshair.Visible; RectangleF screen = GraphicsWrapper.ActualSpaceToDrawingSpace(ActualDrawingSpaceArea); FitHorizontalAreaToScreen(screen); UpdateMasterSynchronizationState(true); WinFormsHelper.BeginFilteredManagedInvoke(this, TimeSpan.FromMilliseconds(100), Refresh); //this.Invalidate(); }
/// <summary> /// This is a chance for the Series to draw custom messages on the given location (typically top left corner). /// The result must be the next valid drawing point down (how much space was used for drawing by current series). /// </summary> public virtual PointF DrawCustomMessages(ChartPane managingPane, GraphicsWrapper g, PointF drawingLocation) { if (Visible == false) { return(drawingLocation); } foreach (KeyValuePair <string, Color> pair in CustomMessages) { Brush brush = managingPane.TitleFontBrush; if (pair.Value.IsEmpty == false) { brush = new SolidBrush(pair.Value); } Font font = managingPane.TitleFont; if (CustomMessagesFont != null) { font = CustomMessagesFont; } drawingLocation = DrawCustomMessage(g, font, brush, pair.Key, drawingLocation); } return(drawingLocation); }
/// <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)); } }
public override void Draw(GraphicsWrapper g, PointF?mousePosition, RectangleF clippingRectangle, RectangleF drawingSpace) { if (Visible == false) { return; } if (_controlPoints.Count < 1) { return; } PointF point1 = _controlPoints[0]; PointF point2; if (_controlPoints.Count < 2) { point2 = mousePosition.Value; } else { point2 = _controlPoints[1]; } // Clipping opitmization. RectangleF rectangle = new RectangleF( Math.Min(point1.X, point2.X), Math.Min(point1.Y, point2.Y), Math.Abs(point2.X - point1.X), Math.Abs(point2.Y - point1.Y)); if (rectangle.IntersectsWith(clippingRectangle) == false) { return; } // Draw base line. g.DrawLine(_dashedLinePen, point1, point2); float baseLevel = point1.Y; float height = point2.Y - point1.Y; // Draw fibbonacci levels. float[] levels = new float[] { 0, 23.6f, 38.2f, 50, 61.8f, 100 }; for (int i = 0; i < levels.Length; i++) { float actualLevel = baseLevel + height * levels[i] / 100f; g.DrawLine(_solidLinePen, point1.X, actualLevel, point2.X, actualLevel); g.DrawString(levels[i].ToString(), DefaultDynamicObjectFont, Brushes.White, point1.X, actualLevel); } if (Selected) { DrawControlPoints(g); } }
/// <summary> /// Helper. /// </summary> protected PointF DrawCustomMessage(GraphicsWrapper g, Font font, Brush brush, string message, PointF drawingLocation) { if (font != null && brush != null) { SizeF size = g.MeasureString(message, font); g.DrawString(message, font, brush, drawingLocation); drawingLocation.Y += size.Height; } return(drawingLocation); }
/// <summary> /// /// </summary> protected void DrawItemSet(LinesChartSeries.ChartTypeEnum type, GraphicsWrapper g, Pen pen, Brush fill, int unitsUnification, RectangleF clippingRectangle, float itemWidth, float itemMargin, object tag) { PointF drawingPoint = new PointF(); int startIndex, endIndex; GetDrawingRangeIndecesFromClippingRectange(clippingRectangle, drawingPoint, unitsUnification, out startIndex, out endIndex, itemWidth, itemMargin); // Need to go up to (ItemsCount + unitsUnification) since the size of the step is (unitsUnification). for (int i = startIndex + unitsUnification - 1; i < endIndex && i < ItemsCount + unitsUnification; i += unitsUnification) { int actualIndex = i; int actualPreviousIndex = Math.Max(0, i - unitsUnification); if (actualIndex < 0 || actualIndex >= ItemsCount) {// Cycle conditions are loose and this is possible. continue; } switch (type) { case LinesChartSeries.ChartTypeEnum.ColoredArea: DrawColorAreaItem(g, ref drawingPoint, pen, fill, actualIndex, actualPreviousIndex, itemWidth, itemMargin, tag); break; case LinesChartSeries.ChartTypeEnum.Histogram: DrawHistogramBar(g, ref drawingPoint, pen, fill, actualIndex, actualPreviousIndex, itemWidth, itemMargin, unitsUnification, tag); break; case LinesChartSeries.ChartTypeEnum.Line: { float previousValue = GetDrawingValueAt(actualPreviousIndex, tag); float value = GetDrawingValueAt(actualIndex, tag); if (float.IsNaN(previousValue) == false && float.IsNaN(value) == false && float.IsInfinity(previousValue) == false && float.IsInfinity(value) == false) { g.DrawLine(pen, drawingPoint.X, drawingPoint.Y + previousValue, drawingPoint.X + itemMargin + itemWidth, drawingPoint.Y + value); } break; } default: break; } drawingPoint.X = (i + 1) * (itemMargin + itemWidth); } }
public override void Draw(GraphicsWrapper g, PointF? mousePosition, RectangleF clippingRectangle, RectangleF drawingSpace) { if (Visible == false) { return; } if (_controlPoints.Count < 1) { return; } PointF point1 = _controlPoints[0]; PointF point2; if (_controlPoints.Count < 2) { point2 = mousePosition.Value; } else { point2 = _controlPoints[1]; } // Clipping opitmization. RectangleF rectangle = new RectangleF( Math.Min(point1.X, point2.X), Math.Min(point1.Y, point2.Y), Math.Abs(point2.X - point1.X), Math.Abs(point2.Y - point1.Y)); if (rectangle.IntersectsWith(clippingRectangle) == false) { return; } // Draw base line. g.DrawLine(_dashedLinePen, point1, point2); float baseLevel = point1.Y; float height = point2.Y - point1.Y; // Draw fibbonacci levels. float[] levels = new float[] { 0, 23.6f, 38.2f, 50, 61.8f, 100 }; for (int i = 0; i < levels.Length; i++) { float actualLevel = baseLevel + height * levels[i] / 100f; g.DrawLine(_solidLinePen, point1.X, actualLevel, point2.X, actualLevel); g.DrawString(levels[i].ToString(), DefaultDynamicObjectFont, Brushes.White, point1.X, actualLevel); } if (Selected) { DrawControlPoints(g); } }
public void SynchronizeDrawingSpaceXAxis(GraphicsWrapper masterWrapper) { lock (this) { // The current transformation matrix. float[] elements = _drawingSpaceTransform.Elements; // Modify the matrix only in X direction. elements[0] = masterWrapper.DrawingSpaceTransformClone.Elements[0]; elements[4] = masterWrapper.DrawingSpaceTransformClone.Elements[4]; _drawingSpaceTransform = new Matrix(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5]); } }
void DrawHistogramBar(GraphicsWrapper g, ref PointF drawingPoint, Pen pen, Brush fill, int index, int previousItemIndex, float itemWidth, float itemMargin, int unitsUnification, object tag) { float y = drawingPoint.Y; float height = 0; if (unitsUnification > 1) { double heightSum = 0; int actualSumCount = 0; for (int i = previousItemIndex; i <= index; i++) { float value = GetDrawingValueAt(i, tag); if (float.IsNaN(value) || float.IsInfinity(value)) { continue; } heightSum += value; actualSumCount++; } if (actualSumCount == 0) { return; } height = (float)(heightSum / actualSumCount); } else { height = GetDrawingValueAt(index, tag); } if (height < 0) { y += height; height = -height; } if (fill != null) { g.FillRectangle(fill, drawingPoint.X, y, (itemWidth) * unitsUnification, height); } }
public override void Draw(GraphicsWrapper g, PointF? mousePosition, RectangleF clippingRectangle, RectangleF drawingSpace) { if (Visible == false) { return; } foreach (double level in _levels) { if (level >= drawingSpace.Y && level <= drawingSpace.Y + drawingSpace.Height) { g.DrawLine(_pen, drawingSpace.X, (float)level, drawingSpace.X + drawingSpace.Width, (float)level); } } }
public void Draw(GraphicsWrapper g, RectangleF drawingSpaceClipping, CustomObject.DrawingOrderEnum drawingOrder) { foreach (CustomObject customObject in _dynamicCustomObjects) { if (customObject.DrawingOrder == drawingOrder) { customObject.Draw(g, _pane.CurrentDrawingSpaceMousePosition, drawingSpaceClipping, _pane.DrawingSpace); } } if (_currentObjectBuilt != null) { _currentObjectBuilt.Draw(g, _pane.CurrentDrawingSpaceMousePosition, drawingSpaceClipping, _pane.DrawingSpace); } }
/// <summary> /// Main drawing routine. /// </summary> public override void Draw(ChartPane managingPane, GraphicsWrapper g, int unitsUnification, RectangleF clippingRectangle, float itemWidth, float itemMargin) { TracerHelper.Trace(ReflectionHelper.GetCallingMethod(2).Name); if (Visible == false) { return; } lock (this) { base.Draw(g, _data.AsReadOnly(), unitsUnification, clippingRectangle, itemWidth, itemMargin, _maxVolume, null); } }
public override void Draw(GraphicsWrapper g, PointF?mousePosition, RectangleF clippingRectangle, RectangleF drawingSpace) { if (Visible == false) { return; } foreach (double level in _levels) { if (level >= drawingSpace.Y && level <= drawingSpace.Y + drawingSpace.Height) { g.DrawLine(_pen, drawingSpace.X, (float)level, drawingSpace.X + drawingSpace.Width, (float)level); } } }
protected void DrawIcon(GraphicsWrapper g, Pen pen, Brush fill, Rectangle rectangle) { if (Visible == false) { return; } if (fill != null) { g.FillRectangle(fill, rectangle); } if (pen != null) { g.DrawRectangle(pen, rectangle); } }
/// <summary> /// Control points selection rectangle is rendered in absolute size, ignoring scaling. /// </summary> /// <param name="g"></param> /// <param name="pen">Pass null to use default control point pen.</param> protected void DrawControlPoints(GraphicsWrapper g) { float xMargin = 0.5f * Math.Abs(_defaultAbsoluteControlPointSelectionRectanglesSize / g.DrawingSpaceTransformClone.Elements[0]); float yMargin = 0.5f * Math.Abs(_defaultAbsoluteControlPointSelectionRectanglesSize / g.DrawingSpaceTransformClone.Elements[3]); for (int i = 0; i < _controlPoints.Count; i++) { PointF point = _controlPoints[i]; if (_selectedControlPoints.Contains(i)) { g.DrawRectangle(_defaultSelectedControlPointPen, point.X - xMargin, point.Y - yMargin, xMargin * 2, yMargin * 2); } else { g.DrawRectangle(_defaultControlPointPen, point.X - xMargin, point.Y - yMargin, xMargin * 2, yMargin * 2); } } }
void DrawOrders(GraphicsWrapper g, int index, PointF drawingPoint, float itemWidth, float itemMargin, List <Order> openingOrders, List <Order> closingOrders, DataBar orderBarData, float lastBarX) { // Width is same as items in real coordinates. float actualImageHeight = _imageDown.Height / Math.Abs(g.DrawingSpaceTransformClone.Elements[3]); float yToXScaling = Math.Abs(g.DrawingSpaceTransformClone.Elements[0] / g.DrawingSpaceTransformClone.Elements[3]); PointF updatedImageDrawingPoint = drawingPoint; foreach (Order order in openingOrders) { DrawOrder(g, ref updatedImageDrawingPoint, order, itemWidth, itemMargin, yToXScaling, orderBarData, lastBarX, true); } foreach (Order order in closingOrders) { DrawOrder(g, ref updatedImageDrawingPoint, order, itemWidth, itemMargin, yToXScaling, orderBarData, lastBarX, false); } }
///// <summary> ///// Helper method, draws histogram bars. ///// </summary> //protected void DrawHistogramBars(GraphicsWrapper g, Pen pen, Brush fill, int unitsUnification, // RectangleF clippingRectangle, float itemWidth, float itemMargin, object tag) //{ // PointF drawingPoint = new PointF(); // int startIndex, endIndex; // GetDrawingRangeIndecesFromClippingRectange(clippingRectangle, drawingPoint, unitsUnification, out startIndex, out endIndex, itemWidth, itemMargin); // for (int i = startIndex + unitsUnification - 1; i < endIndex && i < MaximumIndex + unitsUnification - 1; i += unitsUnification) // { // int actualIndex = i; // int actualPreviousIndex = i - unitsUnification; // if (actualIndex >= MaximumIndex) // { // actualIndex = MaximumIndex - 1; // } // DrawHistogramBar(g, ref drawingPoint, pen, fill, actualIndex, actualPreviousIndex, // itemWidth, itemMargin, unitsUnification, tag); // drawingPoint.X = i * (itemMargin + itemWidth); // } //} //protected void DrawColoredArea(GraphicsWrapper g, Pen pen, Brush fill, int unitsUnification, // RectangleF clippingRectangle, float itemWidth, float itemMargin, object tag) //{ // PointF drawingPoint = new PointF(); // int startIndex, endIndex; // GetDrawingRangeIndecesFromClippingRectange(clippingRectangle, drawingPoint, unitsUnification, out startIndex, out endIndex, itemWidth, itemMargin); // for (int i = startIndex + unitsUnification - 1; i < endIndex && i < MaximumIndex + unitsUnification - 1; i += unitsUnification) // { // int actualIndex = i; // int actualPreviousIndex = i - unitsUnification; // if (actualIndex >= MaximumIndex) // { // actualIndex = MaximumIndex - 1; // } // DrawColorAreaItem(g, ref drawingPoint, pen, fill, actualIndex, // actualPreviousIndex, itemWidth, itemMargin, tag); // drawingPoint.X = i * (itemMargin + itemWidth); // } //} protected void DrawColorAreaItem(GraphicsWrapper g, ref PointF drawingPoint, Pen pen, Brush fill, int index, int previousItemIndex, float itemWidth, float itemMargin, object tag) { float indexValue = GetDrawingValueAt(index, tag); float previousItemIndexValue = GetDrawingValueAt(previousItemIndex, tag); int unificationCount = index - previousItemIndex; for (int i = previousItemIndex; i <= index; i++) { if (float.IsNaN(previousItemIndexValue)) { previousItemIndexValue = GetDrawingValueAt(i, tag); } else if (float.IsNaN(indexValue)) { indexValue = GetDrawingValueAt(i, tag); } } if (float.IsNaN(indexValue) || float.IsNaN(previousItemIndexValue)) {// Failed to find reasonable values to draw. return; } if (fill != null) { g.FillPolygon(fill, new PointF[] { drawingPoint, new PointF(drawingPoint.X + (itemMargin + itemWidth) * unificationCount, drawingPoint.Y), new PointF(drawingPoint.X + (itemMargin + itemWidth) * unificationCount, drawingPoint.Y + indexValue), new PointF(drawingPoint.X, drawingPoint.Y + previousItemIndexValue) }); } if (pen != null) { g.DrawLine(pen, drawingPoint.X, drawingPoint.Y + previousItemIndexValue, drawingPoint.X + (itemMargin + itemWidth) * unificationCount, drawingPoint.Y + indexValue); } }
public override void Draw(ChartPane managingPane, GraphicsWrapper g, int unitsUnification, RectangleF clippingRectangle, float itemWidth, float itemMargin) { if (this.Visible == false) { return; } lock (this) { for (int i = 0; i < _valueSets.Count; i++) { Pen pen = _defaultPen; if (_valueSetsPens[i] == null) { pen = _valueSetsPens[i]; } base.DrawItemSet(_chartType, g, pen, _defaultFill, unitsUnification, clippingRectangle, itemWidth, itemMargin, _valueSets[i]); } } // Lock }
public override void Draw(GraphicsWrapper g, PointF?mousePosition, RectangleF clippingRectangle, RectangleF drawingSpace) { if (Visible == false || _controlPoints.Count < 1) { return; } if (clippingRectangle.Contains(_controlPoints[0]) == false) {// Clipping opitmization. return; } SizeF size = g.MeasureString(_text, DefaultDynamicObjectFont); if (size.Height < 0) { _rectangle = new RectangleF(_controlPoints[0].X, _controlPoints[0].Y + size.Height, size.Width, -size.Height); } else { _rectangle = new RectangleF(_controlPoints[0].X, _controlPoints[0].Y, size.Width, size.Height); } g.DrawString(_text, DefaultDynamicObjectFont, _brush, _controlPoints[0]); if (Selected || IsBuilding) { g.DrawLine(Pens.Red, _rectangle.Location, new PointF(_rectangle.X + _rectangle.Width, _rectangle.Y)); } // Rounding rectangle. //g.DrawRectangle(Pens.White, _rectangle); if (Selected) { DrawControlPoints(g); } }
/// <summary> /// Enter locked. /// </summary> void DrawBar(GraphicsWrapper g, ref PointF startingPoint, DataBar barData, float itemWidth, float itemMargin, int itemUnitification) { float xMiddle = startingPoint.X + itemWidth / 2; float xHalfWidth = itemWidth / 2; Pen pen = _risingBarPen; if (barData.IsRising == false) { pen = _fallingBarPen; } if (pen == null) { return; } float yDisplacement = startingPoint.Y; g.DrawLine(pen, xMiddle, yDisplacement + (float)barData.Low, xMiddle, yDisplacement + (float)barData.High); g.DrawLine(pen, xMiddle, yDisplacement + (float)barData.Open, xMiddle - xHalfWidth, yDisplacement + (float)barData.Open); g.DrawLine(pen, xMiddle, yDisplacement + (float)barData.Close, xMiddle + xHalfWidth, yDisplacement + (float)barData.Close); }
void DrawSelection(GraphicsWrapper g) { if (CurrentSelectionRectangle.HasValue == false) { return; } RectangleF selectionRectangle = CurrentSelectionRectangle.Value; if (selectionRectangle.Width > 0 && selectionRectangle.Height > 0 && _lastDrawingSpaceMouseRightButtonPosition.HasValue && _currentDrawingSpaceMousePosition.HasValue) { if (_selectionPen != null) { g.DrawRectangle(_selectionPen, selectionRectangle.X, selectionRectangle.Y, selectionRectangle.Width, selectionRectangle.Height); } if (_selectionFill != null) { g.FillRectangle(_selectionFill, selectionRectangle); } } }
void DrawDrawingSpace(GraphicsWrapper g) { RectangleF drawingSpaceClipping = _actualDrawingSpaceArea; drawingSpaceClipping.X -= _seriesItemMargin + _seriesItemWidth; drawingSpaceClipping.Y -= _seriesItemMargin + _seriesItemWidth; drawingSpaceClipping.Width += 2 * (_seriesItemMargin + _seriesItemWidth); drawingSpaceClipping.Height += 2 * (_seriesItemMargin + _seriesItemWidth); drawingSpaceClipping = GraphicsWrapper.ActualSpaceToDrawingSpace(drawingSpaceClipping); //drawingSpaceClipping.Y = DrawingSpace.Y - 10; //drawingSpaceClipping.Height = DrawingSpace.Height + 10; // Grid. _drawingSpaceGrid.Draw(g, drawingSpaceClipping, _drawingSpace, _seriesItemMargin + _seriesItemWidth); // Show clipping rectangle. if (ShowClippingRectangle) { Pen clippingRectanglePen = (Pen)Pens.DarkGray.Clone(); clippingRectanglePen.DashStyle = DashStyle.Dash; g.DrawRectangle(clippingRectanglePen, drawingSpaceClipping.X, drawingSpaceClipping.Y, drawingSpaceClipping.Width, drawingSpaceClipping.Height); } // Draw custom objects - pre series. _customObjectsManager.Draw(g, drawingSpaceClipping, CustomObject.DrawingOrderEnum.PreSeries); // Series. foreach (ChartSeries series in _series) { series.Draw(this, g, CurrentUnitUnification, drawingSpaceClipping, _seriesItemWidth, _seriesItemMargin); } // Draw custom objects - post series. _customObjectsManager.Draw(g, drawingSpaceClipping, CustomObject.DrawingOrderEnum.PostSeries); }
/// <summary> /// Override this routine, to add the price labels at the space outside of the current drawing pane. /// </summary> /// <param name="managingPane"></param> /// <param name="g"></param> public override void DrawInitialActualSpaceOverlays(ChartPane managingPane, GraphicsWrapper g) { base.DrawInitialActualSpaceOverlays(managingPane, g); if (_dataProvider == null || _dataProvider.OperationalState != OperationalStateEnum.Operational) { return; } decimal? ask = _dataProvider.Quotes.Ask; decimal? bid = _dataProvider.Quotes.Bid; if (ask.HasValue == false || bid.HasValue == false) { return; } // Measure based on a default format of 6 symbols. SizeF size = g.MeasureString("00.0000", managingPane.LabelsFont); Brush fillBrush = managingPane.LabelsFill; if (fillBrush == null) { fillBrush = managingPane.ActualDrawingSpaceAreaFill; } if (_showCurrentAskLine) { PointF position = managingPane.GraphicsWrapper.DrawingSpaceToActualSpace(new PointF(0, (float)_dataProvider.Quotes.Ask), true); position.X = managingPane.Width - managingPane.ActualDrawingSpaceAreaMarginRight; position.Y -= size.Height; if (fillBrush != null) { g.FillRectangle(fillBrush, new RectangleF(position.X, position.Y, size.Width, size.Height)); } if (managingPane.LabelsFont != null && managingPane.LabelsFontBrush != null) { g.DrawString(ask.Value.ToString(_dataProvider.SessionInfo.ValueFormat), managingPane.LabelsFont, managingPane.LabelsFontBrush, position); g.DrawRectangle(managingPane.ActualDrawingSpaceAreaBorderPen, new RectangleF(position.X, position.Y, size.Width/* - 2*/, size.Height)); } } if (_showCurrentBidLine) { PointF position = managingPane.GraphicsWrapper.DrawingSpaceToActualSpace(new PointF(0, (float)_dataProvider.Quotes.Bid), true); position.X = managingPane.Width - managingPane.ActualDrawingSpaceAreaMarginRight; if (fillBrush != null) { g.FillRectangle(fillBrush, new RectangleF(position.X, position.Y, size.Width, size.Height)); } if (managingPane.LabelsFont != null && managingPane.LabelsFontBrush != null) { g.DrawString(bid.Value.ToString(_dataProvider.SessionInfo.ValueFormat), managingPane.LabelsFont, managingPane.LabelsFontBrush, position); g.DrawRectangle(managingPane.ActualDrawingSpaceAreaBorderPen, new RectangleF(position.X, position.Y, size.Width/* - 2*/, size.Height)); } } }
void DrawOrder(GraphicsWrapper g, ref PointF updatedImageDrawingPoint, Order order, float itemWidth, float itemMargin, float yToXScaling, DataBar orderBarData, float lastBarX, bool drawOpening) { Image image = _imageUp; Brush brush = Brushes.Green; Pen dashedPen = _buyDashedPen; Pen pen = Pens.GreenYellow; if (order.IsBuy == false) { image = _imageDown; brush = Brushes.Red; pen = Pens.Red; dashedPen = _sellDashedPen; } if (drawOpening == false) { image = _imageCross; } if (order.OpenPrice.HasValue == false) { SystemMonitor.OperationError("Order with no open price assigned for drawing.", TracerItem.PriorityEnum.Low); return; } float price = (float)order.OpenPrice.Value; if (drawOpening == false) { if (order.ClosePrice.HasValue == false) { return; } price = (float)order.ClosePrice.Value; } if (drawOpening && _showPendingOrdersTracing && (order is ActiveOrder && order.State == OrderStateEnum.Executed) && _dataProvider.Quotes.Bid.HasValue && _dataProvider.Quotes.Ask.HasValue) {// Open orders tracking line. PointF point1 = new PointF(updatedImageDrawingPoint.X + itemWidth / 2f, updatedImageDrawingPoint.Y + price); float sellPrice = (float)_dataProvider.Quotes.Bid; if (order.IsBuy == false) { sellPrice = (float)_dataProvider.Quotes.Ask; } PointF point2 = new PointF(lastBarX - itemWidth / 2f, updatedImageDrawingPoint.Y + sellPrice); g.DrawLine(dashedPen, point1, point2); } //if (drawOpening && _showClosedOrdersTracing && order.IsOpen == false) //{// Closed order tracking. // Close order tracing is implemented in main draw function. //} if (_showOrderSpot) { PointF basePoint = new PointF(updatedImageDrawingPoint.X, updatedImageDrawingPoint.Y + price); float height = (yToXScaling * itemWidth); if (order.IsBuy == false) { height = -height; } if (drawOpening) { g.FillPolygon(brush, new PointF[] { basePoint, new PointF(basePoint.X + itemWidth, basePoint.Y), new PointF(basePoint.X + (itemWidth / 2f), basePoint.Y + height) }); g.DrawPolygon(Pens.White, new PointF[] { basePoint, new PointF(basePoint.X + itemWidth, basePoint.Y), new PointF(basePoint.X + (itemWidth / 2f), basePoint.Y + height) }); float drawToLeft = (float)(1.5 * itemWidth); float drawToRight = (float)(2.5 * itemWidth); // Take profit level. if (order.TakeProfit.HasValue && order.TakeProfit.Value != 0) { g.DrawLine(pen, updatedImageDrawingPoint.X - drawToLeft, updatedImageDrawingPoint.Y + (float)order.TakeProfit, updatedImageDrawingPoint.X + drawToRight, updatedImageDrawingPoint.Y + (float)order.TakeProfit); g.DrawLine(pen, updatedImageDrawingPoint.X + itemWidth / 2f, updatedImageDrawingPoint.Y + (float)order.TakeProfit, updatedImageDrawingPoint.X + itemWidth / 2f, updatedImageDrawingPoint.Y + (float)order.TakeProfit - height); } // Stop loss level. if (order.StopLoss.HasValue && order.StopLoss.Value != 0) { g.DrawLine(pen, updatedImageDrawingPoint.X - drawToLeft, updatedImageDrawingPoint.Y + (float)order.StopLoss, updatedImageDrawingPoint.X + drawToRight, updatedImageDrawingPoint.Y + (float)order.StopLoss); g.DrawLine(pen, updatedImageDrawingPoint.X + itemWidth / 2f, updatedImageDrawingPoint.Y + (float)order.StopLoss, updatedImageDrawingPoint.X + itemWidth / 2f, updatedImageDrawingPoint.Y + (float)order.StopLoss + height); } } else { g.DrawRectangle(Pens.White, basePoint.X, basePoint.Y, itemWidth, yToXScaling * itemWidth); } } float imageHeight = 2 * (yToXScaling * itemWidth); if (_showOrderArrow) { float x = updatedImageDrawingPoint.X - (itemWidth / 2f); float y = updatedImageDrawingPoint.Y + (float)orderBarData.Low - (yToXScaling * itemWidth); float width = 2 * itemWidth; float height = -imageHeight; GraphicsWrapper.NormalizedRectangle(ref x, ref y, ref width, ref height); RectangleF rectange = new RectangleF(x, y, width, height); // Draw up image. g.DrawImage(image, rectange.X, rectange.Y, rectange.Width, rectange.Height); if (order == _selectedOrder) {// This is selected order. g.DrawRectangle(Pens.White, rectange); } _ordersArrows[order] = rectange; updatedImageDrawingPoint.Y -= 1.2f * imageHeight; } }
/// <summary> /// /// </summary> /// <param name="g"></param> /// <param name="unitsUnification">Draw a few units as one. Used when zooming is too big to show each unit - so unify them. 1 means no unification, 10 means unify 10 units together</param> /// <param name="clippingRectangle"></param> /// <param name="itemWidth"></param> /// <param name="itemMargin"></param> public abstract void Draw(ChartPane managingPane, GraphicsWrapper g, int unitsUnification, RectangleF clippingRectangle, float itemWidth, float itemMargin);
public override void DrawSeriesIcon(GraphicsWrapper g, Rectangle rectangle) { foreach (string name in _outputResultSetsPens.Keys) { base.DrawIcon(g, _outputResultSetsPens[name], Brushes.White, rectangle); return; } // If none are available, draw a simple black and white icon. base.DrawIcon(g, Pens.White, Brushes.Black, rectangle); }
/// <summary> /// Override this routine, to add the price labels at the space outside of the current drawing pane. /// </summary> /// <param name="managingPane"></param> /// <param name="g"></param> public override void DrawInitialActualSpaceOverlays(ChartPane managingPane, GraphicsWrapper g) { base.DrawInitialActualSpaceOverlays(managingPane, g); if (_dataProvider == null || _dataProvider.OperationalState != OperationalStateEnum.Operational) { return; } decimal?ask = _dataProvider.Quotes.Ask; decimal?bid = _dataProvider.Quotes.Bid; if (ask.HasValue == false || bid.HasValue == false) { return; } // Measure based on a default format of 6 symbols. SizeF size = g.MeasureString("00.0000", managingPane.LabelsFont); Brush fillBrush = managingPane.LabelsFill; if (fillBrush == null) { fillBrush = managingPane.ActualDrawingSpaceAreaFill; } if (_showCurrentAskLine) { PointF position = managingPane.GraphicsWrapper.DrawingSpaceToActualSpace(new PointF(0, (float)_dataProvider.Quotes.Ask), true); position.X = managingPane.Width - managingPane.ActualDrawingSpaceAreaMarginRight; position.Y -= size.Height; if (fillBrush != null) { g.FillRectangle(fillBrush, new RectangleF(position.X, position.Y, size.Width, size.Height)); } if (managingPane.LabelsFont != null && managingPane.LabelsFontBrush != null) { g.DrawString(ask.Value.ToString(_dataProvider.SessionInfo.ValueFormat), managingPane.LabelsFont, managingPane.LabelsFontBrush, position); g.DrawRectangle(managingPane.ActualDrawingSpaceAreaBorderPen, new RectangleF(position.X, position.Y, size.Width /* - 2*/, size.Height)); } } if (_showCurrentBidLine) { PointF position = managingPane.GraphicsWrapper.DrawingSpaceToActualSpace(new PointF(0, (float)_dataProvider.Quotes.Bid), true); position.X = managingPane.Width - managingPane.ActualDrawingSpaceAreaMarginRight; if (fillBrush != null) { g.FillRectangle(fillBrush, new RectangleF(position.X, position.Y, size.Width, size.Height)); } if (managingPane.LabelsFont != null && managingPane.LabelsFontBrush != null) { g.DrawString(bid.Value.ToString(_dataProvider.SessionInfo.ValueFormat), managingPane.LabelsFont, managingPane.LabelsFontBrush, position); g.DrawRectangle(managingPane.ActualDrawingSpaceAreaBorderPen, new RectangleF(position.X, position.Y, size.Width /* - 2*/, size.Height)); } } }
public override void DrawSeriesIcon(GraphicsWrapper g, Rectangle rectangle) { base.DrawIcon(g, _defaultPen, _defaultFill, rectangle); }
public abstract void Draw(GraphicsWrapper g, PointF?mousePosition, RectangleF clippingRectangle, RectangleF drawingSpace);
/// <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)); } }
protected virtual void DrawGraphicSeriesLabels(GraphicsWrapper g, int initialMarginLeft) { _currentLabelsRectangles = new Rectangle[_series.Count]; for (int i = 0; i < _series.Count; i++) { if (i == 0) { _currentLabelsRectangles[0].X = initialMarginLeft; } else { _currentLabelsRectangles[i].X = _currentLabelsRectangles[i - 1].Right + (int)_labelsMargin; } _currentLabelsRectangles[i].Y = (int)_labelsTopMargin; SizeF seriesSize = g.MeasureString(_series[i].Name, _labelsFont); _currentLabelsRectangles[i].Size = new Size((int)seriesSize.Width, (int)seriesSize.Height); int iconWidth = 18; // Add space for series icon _currentLabelsRectangles[i].Width += iconWidth; if (_labelsFill != null) { g.FillRectangle(_labelsFill, _currentLabelsRectangles[i]); } if (_labelsFont != null) { g.DrawString(_series[i].Name, _labelsFont, _labelsFontBrush, _currentLabelsRectangles[i].X + iconWidth, _currentLabelsRectangles[i].Y); } _series[i].DrawSeriesIcon(g, new Rectangle(_currentLabelsRectangles[i].X + 2, _currentLabelsRectangles[i].Y + 2, 14, _currentLabelsRectangles[i].Height - 4)); } }
/// <summary> /// Allows the chart series to render information on the external overlaying part of the chart pane. /// </summary> /// <param name="g"></param> /// <param name="clippingRectangle">Rectangle describing the entire drawing area.</param> public virtual void DrawInitialActualSpaceOverlays(ChartPane managingPane, GraphicsWrapper g) { }
public override void Draw(ChartPane managingPane, GraphicsWrapper g, int unitsUnification, RectangleF clippingRectangle, float itemWidth, float itemMargin) { if (this.Visible == false || Indicator == null) { return; } lock (Indicator.Results) { foreach (string name in Indicator.Results.SetsNamesUnsafe) { LinesChartSeries.ChartTypeEnum? chartType = Indicator.Results.GetResultSetChartType(name); if (chartType.HasValue == false) {// No specific value assigned means go for default. chartType = DefaultChartType; } base.DrawItemSet(chartType.Value, g, _outputResultSetsPens[name], _defaultBrush, unitsUnification, clippingRectangle, itemWidth, itemMargin, name); } } foreach(string name in Indicator.Parameters.DynamicNames) {// Render fixed lines. if (name.Contains(FixedLinePrefix)) { object value = Indicator.Parameters.GetDynamic(name); if (value == null) { continue; } float floatValue = Convert.ToSingle(value); int dashMove = 0;// ((int)x % DashSize); g.DrawLine(_defaultDashedPen, clippingRectangle.X + dashMove, floatValue, clippingRectangle.X + clippingRectangle.Width, floatValue); } } }
/// <summary> /// Main drawing routine. /// </summary> public override void Draw(ChartPane managingPane, GraphicsWrapper g, int unitsUnification, RectangleF clippingRectangle, float itemWidth, float itemMargin) { //TracerHelper.Trace(TracerHelper.GetCallingMethod(2).Name); if (Visible == false) { return; } if (_dataProvider == null) { return; } IDataBarHistoryProvider dataBarProvider = CurrentDataBarProvider; if (dataBarProvider == null) { return; } lock (dataBarProvider) { base.Draw(g, dataBarProvider.BarsUnsafe, unitsUnification, clippingRectangle, itemWidth, itemMargin, _maxVolume, null); } // Draw ask/bid line. if (_dataProvider.OperationalState == CommonSupport.OperationalStateEnum.Operational && _dataProvider.Quotes != null && _dataProvider.Quotes.Bid.HasValue && _dataProvider.Quotes.Ask.HasValue) { if (_showCurrentAskLine) { float price = (float)_dataProvider.Quotes.Ask; g.DrawLine(_priceLevelPen, clippingRectangle.X, price, clippingRectangle.X + clippingRectangle.Width, price); } if (_showCurrentBidLine) { float price = (float)_dataProvider.Quotes.Bid; g.DrawLine(_priceLevelPen, clippingRectangle.X, price, clippingRectangle.X + clippingRectangle.Width, price); } } List <Order> ordersOpening; // Draw orders locations on chart. lock (this) { if (_orderExecutionProvider == null) { return; } } // Render orders. ordersOpening = new List <Order>(); ITradeEntityManagement history = _orderExecutionProvider.TradeEntities; if (history != null && _dataProvider != null) { lock (history) { ordersOpening.AddRange(history.GetOrdersBySymbol(_dataProvider.SessionInfo.Symbol)); } } // Use for orders closes. List <Order> ordersClosing = new List <Order>(); foreach (Order order in ordersOpening) { if (order.State == OrderStateEnum.Closed) {// Only add orders already closed. ordersClosing.Add(order); } } // This is used later on, since ordersClosing is modified. List <Order> ordersClosed = new List <Order>(ordersClosing); // TradeEntities opening at current bar. List <Order> pendingOpeningOrders = new List <Order>(); // Order closing at current bar. List <Order> pendingClosingOrders = new List <Order>(); PointF drawingPoint = new PointF(); int startIndex, endIndex; GetDrawingRangeIndecesFromClippingRectange(clippingRectangle, drawingPoint, unitsUnification, out startIndex, out endIndex, itemWidth, itemMargin); lock (dataBarProvider) { float lastBarX = (itemMargin + itemWidth) * dataBarProvider.BarCount; for (int i = startIndex; i < endIndex && i < dataBarProvider.BarCount && (ordersOpening.Count > 0 || ordersClosing.Count > 0); i++) { // Foreach bar, draw orders (and closeVolume). while (ordersOpening.Count > 0) { // All orders before now. if (ordersOpening[0].OpenTime < (dataBarProvider.BarsUnsafe[i].DateTime - Period)) { // Order before time period. if ((ordersOpening[0].State == OrderStateEnum.Executed /*|| * ordersOpening[0].State == OrderInformation.OrderStateEnum.Submitted*/) && _showPendingOrdersTracing) {// Since it is an open pending order, we shall also need to draw it as well. pendingOpeningOrders.Add(ordersOpening[0]); } ordersOpening.RemoveAt(0); continue; } if (ordersOpening[0].OpenTime > dataBarProvider.BarsUnsafe[i].DateTime) {// Order after time period - look no further. break; } // Order open is within the current period. // Only if order is part of the current period - add to pending. pendingOpeningOrders.Add(ordersOpening[0]); ordersOpening.RemoveAt(0); } for (int j = ordersClosing.Count - 1; j >= 0; j--) { if (ordersClosing[j].CloseTime >= (dataBarProvider.BarsUnsafe[i].DateTime - dataBarProvider.Period) && ordersClosing[j].CloseTime <= dataBarProvider.BarsUnsafe[i].DateTime) {// Order close is within the current period. pendingClosingOrders.Add(ordersClosing[j]); ordersClosing.RemoveAt(j); } } drawingPoint.X = i * (itemMargin + itemWidth); DrawOrders(g, i, drawingPoint, itemWidth, itemMargin, pendingOpeningOrders, pendingClosingOrders, dataBarProvider.BarsUnsafe[i], lastBarX); pendingOpeningOrders.Clear(); pendingClosingOrders.Clear(); } if (_showClosedOrdersTracing && dataBarProvider.BarCount > 0 && startIndex < dataBarProvider.BarCount) {// Since a closed order may be before or after (or during) the curren set of periods - make a special search and render for them. endIndex = Math.Max(0, endIndex); endIndex = Math.Min(dataBarProvider.BarCount - 1, endIndex); foreach (Order order in ordersClosed) { if (order.OpenTime.HasValue && order.CloseTime.HasValue && order.OpenTime.Value <= dataBarProvider.BarsUnsafe[endIndex].DateTime && order.CloseTime.Value >= dataBarProvider.BarsUnsafe[startIndex].DateTime - dataBarProvider.Period) { int openIndex = dataBarProvider.GetIndexAtTime(order.OpenTime.Value); int closeIndex = dataBarProvider.GetIndexAtTime(order.CloseTime.Value); Pen pen = _buyDashedPen; if (order.IsBuy == false) { pen = _sellDashedPen; } Decimal?doubleOpenValue = order.OpenPrice; Decimal?doubleCloseValue = order.ClosePrice; if (doubleOpenValue.HasValue == false) { SystemMonitor.Error("Invalid open price value for closed order to draw."); continue; } if (doubleCloseValue.HasValue == false) { SystemMonitor.Error("Invalid close price value for closed order to draw."); continue; } g.DrawLine(pen, new PointF(openIndex * (itemWidth + itemMargin), (float)doubleOpenValue), new PointF(closeIndex * (itemWidth + itemMargin), (float)doubleCloseValue)); } } } } // Lock }
/// <summary> /// /// </summary> public abstract void DrawSeriesIcon(GraphicsWrapper g, Rectangle rectangle);
/// <summary> /// This is a chance for the Series to draw custom messages on the given location (typically top left corner). /// The result must be the next valid drawing point down (how much space was used for drawing by current series). /// </summary> public virtual PointF DrawCustomMessages(ChartPane managingPane, GraphicsWrapper g, PointF drawingLocation) { if (Visible == false) { return drawingLocation; } foreach (KeyValuePair<string, Color> pair in CustomMessages) { Brush brush = managingPane.TitleFontBrush; if (pair.Value.IsEmpty == false) { brush = new SolidBrush(pair.Value); } Font font = managingPane.TitleFont; if (CustomMessagesFont != null) { font = CustomMessagesFont; } drawingLocation = DrawCustomMessage(g, font, brush, pair.Key, drawingLocation); } return drawingLocation; }
public override void Draw(GraphicsWrapper g, PointF?mousePosition, RectangleF clippingRectangle, RectangleF drawingSpace) { if (Visible == false) { return; } if (_controlPoints.Count < 1) { return; } PointF point1 = _controlPoints[0]; PointF point2; if (mousePosition.HasValue) { point2 = mousePosition.Value; } else { point2 = point1; } if (_controlPoints.Count == 2) { point2 = _controlPoints[1]; } // Clipping opitmization. RectangleF rectangle = new RectangleF( Math.Min(point1.X, point2.X), Math.Min(point1.Y, point2.Y), Math.Abs(point2.X - point1.X), Math.Abs(point2.Y - point1.Y)); if (rectangle.IntersectsWith(clippingRectangle) == false) { return; } SimpleLine line = new SimpleLine(point1, point2); PointF vec = new PointF(line.XDelta, line.YDelta); vec = g.DrawingSpaceToActualSpace(vec, false); vec = new PointF(vec.Y, vec.X); // Rotate PointF vec1 = SimpleLine.RotatePoint(vec, -(float)Math.PI / 2 + 0.3f); PointF vec2 = SimpleLine.RotatePoint(vec, -(float)Math.PI / 2 - 0.3f); // Scale vec1 = new PointF(vec1.X * 0.35f, vec1.Y * 0.35f); vec2 = new PointF(vec2.X * 0.35f, vec2.Y * 0.35f); vec1 = g.ActualSpaceToDrawingSpace(vec1, false); vec2 = g.ActualSpaceToDrawingSpace(vec2, false); g.DrawLine(_pen, point1, point2); g.FillPolygon(_brush, new PointF[] { point2, new PointF(point2.X + vec1.X, point2.Y + vec1.Y), new PointF(point2.X + vec2.X, point2.Y + vec2.Y) }); if (Selected) { DrawControlPoints(g); } }
public override void DrawInitialActualSpaceOverlays(ChartPane managingPane, GraphicsWrapper g) { base.DrawInitialActualSpaceOverlays(managingPane, g); }
/// <summary> /// Main drawing routine. /// </summary> public override void Draw(ChartPane managingPane, GraphicsWrapper g, int unitsUnification, RectangleF clippingRectangle, float itemWidth, float itemMargin) { //TracerHelper.Trace(TracerHelper.GetCallingMethod(2).Name); if (Visible == false) { return; } if (_dataProvider == null) { return; } IDataBarHistoryProvider dataBarProvider = CurrentDataBarProvider; if (dataBarProvider == null) { return; } lock (dataBarProvider) { base.Draw(g, dataBarProvider.BarsUnsafe, unitsUnification, clippingRectangle, itemWidth, itemMargin, _maxVolume, null); } // Draw ask/bid line. if (_dataProvider.OperationalState == CommonSupport.OperationalStateEnum.Operational && _dataProvider.Quotes != null && _dataProvider.Quotes.Bid.HasValue && _dataProvider.Quotes.Ask.HasValue) { if (_showCurrentAskLine) { float price = (float)_dataProvider.Quotes.Ask; g.DrawLine(_priceLevelPen, clippingRectangle.X, price, clippingRectangle.X + clippingRectangle.Width, price); } if (_showCurrentBidLine) { float price = (float)_dataProvider.Quotes.Bid; g.DrawLine(_priceLevelPen, clippingRectangle.X, price, clippingRectangle.X + clippingRectangle.Width, price); } } List<Order> ordersOpening; // Draw orders locations on chart. lock(this) { if (_orderExecutionProvider == null) { return; } } // Render orders. ordersOpening = new List<Order>(); ITradeEntityManagement history = _orderExecutionProvider.TradeEntities; if (history != null && _dataProvider != null) { lock (history) { ordersOpening.AddRange(history.GetOrdersBySymbol(_dataProvider.SessionInfo.Symbol)); } } // Use for orders closes. List<Order> ordersClosing = new List<Order>(); foreach (Order order in ordersOpening) { if (order.State == OrderStateEnum.Closed) {// Only add orders already closed. ordersClosing.Add(order); } } // This is used later on, since ordersClosing is modified. List<Order> ordersClosed = new List<Order>(ordersClosing); // TradeEntities opening at current bar. List<Order> pendingOpeningOrders = new List<Order>(); // Order closing at current bar. List<Order> pendingClosingOrders = new List<Order>(); PointF drawingPoint = new PointF(); int startIndex, endIndex; GetDrawingRangeIndecesFromClippingRectange(clippingRectangle, drawingPoint, unitsUnification, out startIndex, out endIndex, itemWidth, itemMargin); lock (dataBarProvider) { float lastBarX = (itemMargin + itemWidth) * dataBarProvider.BarCount; for (int i = startIndex; i < endIndex && i < dataBarProvider.BarCount && (ordersOpening.Count > 0 || ordersClosing.Count > 0); i++) {// Foreach bar, draw orders (and closeVolume). while (ordersOpening.Count > 0) {// All orders before now. if (ordersOpening[0].OpenTime < (dataBarProvider.BarsUnsafe[i].DateTime - Period)) {// Order before time period. if ((ordersOpening[0].State == OrderStateEnum.Executed /*|| ordersOpening[0].State == OrderInformation.OrderStateEnum.Submitted*/) && _showPendingOrdersTracing) {// Since it is an open pending order, we shall also need to draw it as well. pendingOpeningOrders.Add(ordersOpening[0]); } ordersOpening.RemoveAt(0); continue; } if (ordersOpening[0].OpenTime > dataBarProvider.BarsUnsafe[i].DateTime) {// Order after time period - look no further. break; } // Order open is within the current period. // Only if order is part of the current period - add to pending. pendingOpeningOrders.Add(ordersOpening[0]); ordersOpening.RemoveAt(0); } for (int j = ordersClosing.Count - 1; j >= 0; j--) { if (ordersClosing[j].CloseTime >= (dataBarProvider.BarsUnsafe[i].DateTime - dataBarProvider.Period) && ordersClosing[j].CloseTime <= dataBarProvider.BarsUnsafe[i].DateTime) {// Order close is within the current period. pendingClosingOrders.Add(ordersClosing[j]); ordersClosing.RemoveAt(j); } } drawingPoint.X = i * (itemMargin + itemWidth); DrawOrders(g, i, drawingPoint, itemWidth, itemMargin, pendingOpeningOrders, pendingClosingOrders, dataBarProvider.BarsUnsafe[i], lastBarX); pendingOpeningOrders.Clear(); pendingClosingOrders.Clear(); } if (_showClosedOrdersTracing && dataBarProvider.BarCount > 0 && startIndex < dataBarProvider.BarCount) {// Since a closed order may be before or after (or during) the curren set of periods - make a special search and render for them. endIndex = Math.Max(0, endIndex); endIndex = Math.Min(dataBarProvider.BarCount - 1, endIndex); foreach (Order order in ordersClosed) { if (order.OpenTime.HasValue && order.CloseTime.HasValue && order.OpenTime.Value <= dataBarProvider.BarsUnsafe[endIndex].DateTime && order.CloseTime.Value >= dataBarProvider.BarsUnsafe[startIndex].DateTime - dataBarProvider.Period) { int openIndex = dataBarProvider.GetIndexAtTime(order.OpenTime.Value); int closeIndex = dataBarProvider.GetIndexAtTime(order.CloseTime.Value); Pen pen = _buyDashedPen; if (order.IsBuy == false) { pen = _sellDashedPen; } Decimal? doubleOpenValue = order.OpenPrice; Decimal? doubleCloseValue = order.ClosePrice; if (doubleOpenValue.HasValue == false) { SystemMonitor.Error("Invalid open price value for closed order to draw."); continue; } if (doubleCloseValue.HasValue == false) { SystemMonitor.Error("Invalid close price value for closed order to draw."); continue; } g.DrawLine(pen, new PointF(openIndex * (itemWidth + itemMargin), (float)doubleOpenValue), new PointF(closeIndex * (itemWidth + itemMargin), (float)doubleCloseValue)); } } } } // Lock }
public override void DrawSeriesIcon(GraphicsWrapper g, Rectangle rectangle) { base.DrawIcon(g, RisingBarPen, RisingBarFill, rectangle); }
/// <summary> /// Helper. /// </summary> protected PointF DrawCustomMessage(GraphicsWrapper g, Font font, Brush brush, string message, PointF drawingLocation) { if (font != null && brush != null) { SizeF size = g.MeasureString(message, font); g.DrawString(message, font, brush, drawingLocation); drawingLocation.Y += size.Height; } return drawingLocation; }
void DrawOrders(GraphicsWrapper g, int index, PointF drawingPoint, float itemWidth, float itemMargin, List<Order> openingOrders, List<Order> closingOrders, DataBar orderBarData, float lastBarX) { // Width is same as items in real coordinates. float actualImageHeight = _imageDown.Height / Math.Abs(g.DrawingSpaceTransformClone.Elements[3]); float yToXScaling = Math.Abs(g.DrawingSpaceTransformClone.Elements[0] / g.DrawingSpaceTransformClone.Elements[3]); PointF updatedImageDrawingPoint = drawingPoint; foreach (Order order in openingOrders) { DrawOrder(g, ref updatedImageDrawingPoint, order, itemWidth, itemMargin, yToXScaling, orderBarData, lastBarX, true); } foreach (Order order in closingOrders) { DrawOrder(g, ref updatedImageDrawingPoint, order, itemWidth, itemMargin, yToXScaling, orderBarData, lastBarX, false); } }
protected virtual void DrawPostActualSpaceOverlays(GraphicsWrapper g) { if (_titleFont != null && _titleFontBrush != null) { // Title SizeF titleSize = g.MeasureString(_chartName, _titleFont); Rectangle titleRectangle = new Rectangle(_actualDrawingSpaceArea.Left, _actualDrawingSpaceArea.Top, (int)titleSize.Width, (int)titleSize.Height); g.DrawString(_chartName, _titleFont, _titleFontBrush, titleRectangle.Location); PointF drawingLocation = new PointF(_actualDrawingSpaceArea.Left, titleRectangle.Height + _actualDrawingSpaceArea.Top); // After the title, render any messages the chart series might have. foreach (ChartSeries series in _series) { drawingLocation = series.DrawCustomMessages(this, g, drawingLocation); } } if (_actualDrawingSpaceAreaBorderPen != null) { // Border g.DrawRectangle(_actualDrawingSpaceAreaBorderPen, _actualDrawingSpaceArea.X - 1, _actualDrawingSpaceArea.Y - 1, _actualDrawingSpaceArea.Width + 1, _actualDrawingSpaceArea.Height + 1); } }
public override PointF DrawCustomMessages(ChartPane managingPane, GraphicsWrapper g, PointF drawingLocation) { if (Visible == false) { return drawingLocation; } // Draw any standard messages first (if any). drawingLocation = base.DrawCustomMessages(managingPane, g, drawingLocation); Font font = managingPane.TitleFont; if (CustomMessagesFont != null) { font = CustomMessagesFont; } foreach (FFNewsCustom.NewsEvent eventItem in Indicator.VisibleNewsEvents) { TimeSpan span = (eventItem.DateTime - DateTime.UtcNow); int hours = (int)Math.Abs(Math.Floor(span.TotalHours)); string message; if (span.TotalSeconds < 0) { message = hours.ToString() + " hrs " + Math.Abs(span.Minutes).ToString() + " mins since " + eventItem.Country + ": " + eventItem.Title; } else { message = hours.ToString() + " hrs " + span.Minutes.ToString() + " mins until " + eventItem.Country + ": " + eventItem.Title; } drawingLocation = DrawCustomMessage(g, font, Indicator.TitleBrush, message, drawingLocation); float drawingLocationOriginalX = drawingLocation.X; SizeF size = new SizeF(); if (font != null && Indicator.ImpactBrush != null) { // Draw impact part. string impactString = "Impact: " + eventItem.Impact.ToString(); size = g.MeasureString(impactString, font); g.DrawString(impactString, font, Indicator.ImpactBrush, drawingLocation); drawingLocation.X += size.Width; } // Draw previous part. if (string.IsNullOrEmpty(eventItem.Previous) == false) { if (font != null && Indicator.PreviousBrush != null) { string previousString = "Previous: " + eventItem.Previous; size = g.MeasureString(previousString, font); g.DrawString(previousString, font, Indicator.PreviousBrush, drawingLocation); drawingLocation.X += size.Width; } } if (string.IsNullOrEmpty(eventItem.Forecast) == false) { if (font != null && Indicator.ForecastBrush != null) { string forecastString = "Forecast: " + eventItem.Forecast; size = g.MeasureString(forecastString, font); g.DrawString(forecastString, font, Indicator.ForecastBrush, drawingLocation); drawingLocation.X += size.Width; } } drawingLocation.X = drawingLocationOriginalX; drawingLocation.Y += size.Height; } return drawingLocation; }