public override void OnRender(ChartControl chartControl, ChartScale chartScale) { if (Anchors.All(a => a.IsEditing)) { return; } RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive; ChartPanel chartPanel = chartControl.ChartPanels[PanelIndex]; Point anchorStartPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale); Point anchorEndPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale); Point anchorExtensionPoint = ExtensionAnchor.GetPoint(chartControl, chartPanel, chartScale); Point midPointExtension = new Point((anchorExtensionPoint.X + anchorEndPoint.X) / 2, (anchorExtensionPoint.Y + anchorEndPoint.Y) / 2); if (CalculationMethod == AndrewsPitchforkCalculationMethod.Schiff) { anchorStartPoint = new Point(anchorStartPoint.X, (anchorStartPoint.Y + anchorEndPoint.Y) / 2); } else if (CalculationMethod == AndrewsPitchforkCalculationMethod.ModifiedSchiff) { anchorStartPoint = new Point((anchorEndPoint.X + anchorStartPoint.X) / 2, (anchorEndPoint.Y + anchorStartPoint.Y) / 2); } AnchorLineStroke.RenderTarget = RenderTarget; RetracementLineStroke.RenderTarget = RenderTarget; // Align to full pixel to avoid unneeded aliasing double strokePixAdj = AnchorLineStroke.Width % 2 == 0 ? 0.5d : 0d; Vector pixelAdjustVec = new Vector(strokePixAdj, strokePixAdj); SharpDX.Vector2 startVec = (anchorStartPoint + pixelAdjustVec).ToVector2(); SharpDX.Vector2 endVec = (anchorEndPoint + pixelAdjustVec).ToVector2(); SharpDX.Direct2D1.Brush tmpBrush = IsInHitTest ? chartControl.SelectionBrush : AnchorLineStroke.BrushDX; SharpDX.Vector2 startOriginVec = (StartAnchor.GetPoint(chartControl, chartPanel, chartScale) + pixelAdjustVec).ToVector2(); RenderTarget.DrawLine(startOriginVec, endVec, tmpBrush, AnchorLineStroke.Width, AnchorLineStroke.StrokeStyle); // Is second anchor set yet? Check both so we correctly re-draw during extension anchor editing if (ExtensionAnchor.IsEditing && EndAnchor.IsEditing) { return; } SharpDX.Vector2 extVector = anchorExtensionPoint.ToVector2(); tmpBrush = IsInHitTest ? chartControl.SelectionBrush : RetracementLineStroke.BrushDX; RenderTarget.DrawLine(endVec, extVector, tmpBrush, RetracementLineStroke.Width, RetracementLineStroke.StrokeStyle); // If we're doing a hit test pass, don't draw price levels at all, we dont want those to count for // hit testing if (IsInHitTest || PriceLevels == null || !PriceLevels.Any()) { return; } SetAllPriceLevelsRenderTarget(); // Calculate total y range for % calculation on each level double totalPriceRange = EndAnchor.Price - ExtensionAnchor.Price; double startPrice = ExtensionAnchor.Price; float minLevelY = float.MaxValue; float maxLevelY = float.MinValue; // Store values to use in correct render order Point lastEndPoint = new Point(0, 0); Point lastStartPoint = new Point(0, 0); Stroke lastStroke = null; List <Tuple <PriceLevel, Point> > textPoints = new List <Tuple <PriceLevel, Point> >(); foreach (PriceLevel priceLevel in PriceLevels.Where(pl => pl.IsVisible && pl.Stroke != null).OrderBy(pl => pl.Value)) { double levelPrice = (startPrice + ((priceLevel.Value / 100) * totalPriceRange)); float pixelY = chartScale.GetYByValue(levelPrice); float pixelX = anchorExtensionPoint.X > anchorEndPoint.X ? priceLevel.Value >= 0 ? (float)(anchorExtensionPoint.X - (Math.Abs((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100)))) : (float)(anchorExtensionPoint.X + ((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100))): priceLevel.Value >= 0 ? (float)(anchorExtensionPoint.X + ((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100))) : (float)(anchorExtensionPoint.X - (Math.Abs((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100)))); Point startPoint = new Point(pixelX, pixelY); Point endPoint = new Point(startPoint.X + (midPointExtension.X - anchorStartPoint.X), startPoint.Y + (midPointExtension.Y - anchorStartPoint.Y)); Point maxLevelPoint = GetExtendedPoint(startPoint, endPoint); if (priceLevel.Value == 50) { RenderTarget.DrawLine(startVec, maxLevelPoint.ToVector2(), priceLevel.Stroke.BrushDX, priceLevel.Stroke.Width, priceLevel.Stroke.StrokeStyle); } else { RenderTarget.DrawLine(startPoint.ToVector2(), maxLevelPoint.ToVector2(), priceLevel.Stroke.BrushDX, priceLevel.Stroke.Width, priceLevel.Stroke.StrokeStyle); } if (lastStroke == null) { lastStroke = new Stroke(); } else { SharpDX.Direct2D1.PathGeometry lineGeometry = new SharpDX.Direct2D1.PathGeometry(Core.Globals.D2DFactory); SharpDX.Direct2D1.GeometrySink sink = lineGeometry.Open(); sink.BeginFigure(lastEndPoint.ToVector2(), SharpDX.Direct2D1.FigureBegin.Filled); // Does the fill color need to fill a corner? Check and add a point if (lastEndPoint.Y != maxLevelPoint.Y && lastEndPoint.X != maxLevelPoint.X) { double boundaryX; double boundaryY; if (lastEndPoint.Y <= ChartPanel.Y || lastEndPoint.Y >= ChartPanel.Y + ChartPanel.H) { boundaryY = lastEndPoint.Y; boundaryX = maxLevelPoint.X; } else { boundaryY = maxLevelPoint.Y; boundaryX = lastEndPoint.X; } sink.AddLine(new SharpDX.Vector2((float)boundaryX, (float)boundaryY)); } sink.AddLine(maxLevelPoint.ToVector2()); sink.AddLine(startPoint.ToVector2()); sink.AddLine(lastStartPoint.ToVector2()); sink.EndFigure(SharpDX.Direct2D1.FigureEnd.Closed); sink.Close(); RenderTarget.FillGeometry(lineGeometry, lastStroke.BrushDX); lineGeometry.Dispose(); } if (IsTextDisplayed) { textPoints.Add(new Tuple <PriceLevel, Point>(priceLevel, maxLevelPoint)); } priceLevel.Stroke.CopyTo(lastStroke); lastStroke.Opacity = PriceLevelOpacity; lastStartPoint = startPoint; lastEndPoint = maxLevelPoint; minLevelY = Math.Min(pixelY, minLevelY); maxLevelY = Math.Max(pixelY, maxLevelY); } // Render text last so it's on top of the price level colors if (IsTextDisplayed) { foreach (Tuple <PriceLevel, Point> textPoint in textPoints) { DrawPriceLevelText(0, 0, textPoint.Item2, textPoint.Item1, chartPanel); } } }
public override void OnRender(ChartControl chartControl, ChartScale chartScale) { if (!IsVisible) { return; } if (Anchors.All(a => a.IsEditing)) { return; } // this will be true right away to fix a restoral issue, so check if we really want to set reward if (needsRatioUpdate && DrawTarget) { SetReward(); } ChartPanel chartPanel = chartControl.ChartPanels[PanelIndex]; Point entryPoint = EntryAnchor.GetPoint(chartControl, chartPanel, chartScale); Point stopPoint = RiskAnchor.GetPoint(chartControl, chartPanel, chartScale); Point targetPoint = RewardAnchor.GetPoint(chartControl, chartPanel, chartScale); AnchorLineStroke.RenderTarget = RenderTarget; EntryLineStroke.RenderTarget = RenderTarget; StopLineStroke.RenderTarget = RenderTarget; // first of all, turn on anti-aliasing to smooth out our line RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive; RenderTarget.DrawLine(entryPoint.ToVector2(), stopPoint.ToVector2(), AnchorLineStroke.BrushDX, AnchorLineStroke.Width, AnchorLineStroke.StrokeStyle); double anchorMinX = DrawTarget ? new[] { entryPoint.X, stopPoint.X, targetPoint.X }.Min() : new[] { entryPoint.X, stopPoint.X }.Min(); double anchorMaxX = DrawTarget ? new[] { entryPoint.X, stopPoint.X, targetPoint.X }.Max() : new[] { entryPoint.X, stopPoint.X }.Max(); double lineStartX = IsExtendedLinesLeft ? chartPanel.X : anchorMinX; double lineEndX = IsExtendedLinesRight ? chartPanel.X + chartPanel.W : anchorMaxX; SharpDX.Vector2 entryStartVector = new SharpDX.Vector2((float)lineStartX, (float)entryPoint.Y); SharpDX.Vector2 entryEndVector = new SharpDX.Vector2((float)lineEndX, (float)entryPoint.Y); SharpDX.Vector2 stopStartVector = new SharpDX.Vector2((float)lineStartX, (float)stopPoint.Y); SharpDX.Vector2 stopEndVector = new SharpDX.Vector2((float)lineEndX, (float)stopPoint.Y); // don't try and draw the target stuff until we have calculated the target SharpDX.Direct2D1.Brush tmpBrush = IsInHitTest ? chartControl.SelectionBrush : AnchorLineStroke.BrushDX; if (DrawTarget) { AnchorLineStroke.RenderTarget = RenderTarget; RenderTarget.DrawLine(entryPoint.ToVector2(), targetPoint.ToVector2(), tmpBrush, AnchorLineStroke.Width, AnchorLineStroke.StrokeStyle); TargetLineStroke.RenderTarget = RenderTarget; SharpDX.Vector2 targetStartVector = new SharpDX.Vector2((float)lineStartX, (float)targetPoint.Y); SharpDX.Vector2 targetEndVector = new SharpDX.Vector2((float)lineEndX, (float)targetPoint.Y); tmpBrush = IsInHitTest ? chartControl.SelectionBrush : TargetLineStroke.BrushDX; RenderTarget.DrawLine(targetStartVector, targetEndVector, tmpBrush, TargetLineStroke.Width, TargetLineStroke.StrokeStyle); DrawPriceText(RewardAnchor, targetPoint, targetPrice, chartControl, chartPanel, chartScale); } tmpBrush = IsInHitTest ? chartControl.SelectionBrush : EntryLineStroke.BrushDX; RenderTarget.DrawLine(entryStartVector, entryEndVector, tmpBrush, EntryLineStroke.Width, EntryLineStroke.StrokeStyle); DrawPriceText(EntryAnchor, entryPoint, entryPrice, chartControl, chartPanel, chartScale); tmpBrush = IsInHitTest ? chartControl.SelectionBrush : StopLineStroke.BrushDX; RenderTarget.DrawLine(stopStartVector, stopEndVector, tmpBrush, StopLineStroke.Width, StopLineStroke.StrokeStyle); DrawPriceText(RiskAnchor, stopPoint, stopPrice, chartControl, chartPanel, chartScale); }
public override void OnMouseDown(ChartControl chartControl, ChartPanel chartPanel, ChartScale chartScale, ChartAnchor dataPoint) { switch (DrawingState) { case DrawingState.Building: if (StartAnchor.IsEditing) { dataPoint.CopyDataValues(StartAnchor); // Give end anchor something to start with so we dont try to render it with bad values right away dataPoint.CopyDataValues(EndAnchor); StartAnchor.IsEditing = false; } else if (EndAnchor.IsEditing) { dataPoint.CopyDataValues(EndAnchor); // Give extension anchor something nearby to start with dataPoint.CopyDataValues(ExtensionAnchor); EndAnchor.IsEditing = false; } else if (ExtensionAnchor.IsEditing) { dataPoint.CopyDataValues(ExtensionAnchor); ExtensionAnchor.IsEditing = false; } // Is initial building done (all anchors set) if (Anchors.All(a => !a.IsEditing)) { DrawingState = DrawingState.Normal; IsSelected = false; } break; case DrawingState.Normal: Point point = dataPoint.GetPoint(chartControl, chartPanel, chartScale); editingAnchor = GetClosestAnchor(chartControl, chartPanel, chartScale, cursorSensitivity, point); if (editingAnchor != null) { editingAnchor.IsEditing = true; DrawingState = DrawingState.Editing; } else { if (GetCursor(chartControl, chartPanel, chartScale, point) == Cursors.SizeAll) { DrawingState = DrawingState.Moving; } else if (GetCursor(chartControl, chartPanel, chartScale, point) == Cursors.SizeNESW || GetCursor(chartControl, chartPanel, chartScale, point) == Cursors.SizeNWSE) { DrawingState = DrawingState.Editing; } else if (GetCursor(chartControl, chartPanel, chartScale, point) == Cursors.Arrow) { DrawingState = DrawingState.Editing; } else if (GetCursor(chartControl, chartPanel, chartScale, point) == null) { IsSelected = false; } } break; } }