public override Point[] GetSelectionPoints(ChartControl chartControl, ChartScale chartScale) { ChartPanel chartPanel = chartControl.ChartPanels[chartScale.PanelIndex]; Point entryPoint = EntryAnchor.GetPoint(chartControl, chartPanel, chartScale); Point stopPoint = RiskAnchor.GetPoint(chartControl, chartPanel, chartScale); if (!DrawTarget) { return new[] { entryPoint, stopPoint } } ; Point targetPoint = RewardAnchor.GetPoint(chartControl, chartPanel, chartScale); return(new[] { entryPoint, stopPoint, targetPoint }); }
public override Cursor GetCursor(ChartControl chartControl, ChartPanel chartPanel, ChartScale chartScale, Point point) { switch (DrawingState) { case DrawingState.Building: return(Cursors.Pen); case DrawingState.Moving: return(IsLocked ? Cursors.No : Cursors.SizeAll); case DrawingState.Editing: return(IsLocked ? Cursors.No : (editingAnchor == EntryAnchor ? Cursors.SizeNESW : Cursors.SizeNWSE)); default: // draw move cursor if cursor is near line path anywhere Point entryAnchorPixelPoint = EntryAnchor.GetPoint(chartControl, chartPanel, chartScale); // see if we are near an anchor right away. this is is cheap so no big deal to do often ChartAnchor closest = GetClosestAnchor(chartControl, chartPanel, chartScale, cursorSensitivity, point); if (closest != null) { return(IsLocked ? Cursors.Arrow : (closest == EntryAnchor ? Cursors.SizeNESW : Cursors.SizeNWSE)); } Point stopAnchorPixelPoint = RiskAnchor.GetPoint(chartControl, chartPanel, chartScale); Vector anchorsVector = stopAnchorPixelPoint - entryAnchorPixelPoint; // see if the mouse is along one of our lines for moving if (MathHelper.IsPointAlongVector(point, entryAnchorPixelPoint, anchorsVector, cursorSensitivity)) { return(IsLocked ? Cursors.Arrow : Cursors.SizeAll); } if (!DrawTarget) { return(null); } Point targetPoint = RewardAnchor.GetPoint(chartControl, chartPanel, chartScale); Vector targetToEntryVector = targetPoint - entryAnchorPixelPoint; return(MathHelper.IsPointAlongVector(point, entryAnchorPixelPoint, targetToEntryVector, cursorSensitivity) ? (IsLocked ? Cursors.Arrow : Cursors.SizeAll) : null); } }
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 bool IsAlertConditionTrue(AlertConditionItem conditionItem, Condition condition, ChartAlertValue[] values, ChartControl chartControl, ChartScale chartScale) { // dig up which anchor we are running on to determine line ChartAnchor chartAnchor = conditionItem.Tag as ChartAnchor; if (chartAnchor == null) { return(false); } ChartPanel chartPanel = chartControl.ChartPanels[PanelIndex]; double alertY = chartScale.GetYByValue(chartAnchor.Price); Point entryPoint = EntryAnchor.GetPoint(chartControl, chartPanel, chartScale); Point stopPoint = RiskAnchor.GetPoint(chartControl, chartPanel, chartScale); Point targetPoint = RewardAnchor.GetPoint(chartControl, chartPanel, chartScale); 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; // first thing, if our smallest x is greater than most recent bar, we have nothing to do yet. // do not try to check Y because lines could cross through stuff double firstBarX = chartControl.GetXByTime(values[0].Time); double firstBarY = chartScale.GetYByValue(values[0].Value); if (lineEndX < firstBarX) // bars passed our drawing tool { return(false); } Point lineStartPoint = new Point(lineStartX, alertY); Point lineEndPoint = new Point(lineEndX, alertY); Point barPoint = new Point(firstBarX, firstBarY); // NOTE: 'left / right' is relative to if line was vertical. it can end up backwards too MathHelper.PointLineLocation pointLocation = MathHelper.GetPointLineLocation(lineStartPoint, lineEndPoint, barPoint); // for vertical things, think of a vertical line rotated 90 degrees to lay flat, where it's normal vector is 'up' switch (condition) { case Condition.Greater: return(pointLocation == MathHelper.PointLineLocation.LeftOrAbove); case Condition.GreaterEqual: return(pointLocation == MathHelper.PointLineLocation.LeftOrAbove || pointLocation == MathHelper.PointLineLocation.DirectlyOnLine); case Condition.Less: return(pointLocation == MathHelper.PointLineLocation.RightOrBelow); case Condition.LessEqual: return(pointLocation == MathHelper.PointLineLocation.RightOrBelow || pointLocation == MathHelper.PointLineLocation.DirectlyOnLine); case Condition.Equals: return(pointLocation == MathHelper.PointLineLocation.DirectlyOnLine); case Condition.NotEqual: return(pointLocation != MathHelper.PointLineLocation.DirectlyOnLine); case Condition.CrossAbove: case Condition.CrossBelow: Predicate <ChartAlertValue> predicate = v => { double barX = chartControl.GetXByTime(v.Time); double barY = chartScale.GetYByValue(v.Value); Point stepBarPoint = new Point(barX, barY); // NOTE: 'left / right' is relative to if line was vertical. it can end up backwards too MathHelper.PointLineLocation ptLocation = MathHelper.GetPointLineLocation(lineStartPoint, lineEndPoint, stepBarPoint); if (condition == Condition.CrossAbove) { return(ptLocation == MathHelper.PointLineLocation.LeftOrAbove); } return(ptLocation == MathHelper.PointLineLocation.RightOrBelow); }; return(MathHelper.DidPredicateCross(values, predicate)); } return(false); }
private void DrawPriceText(ChartAnchor anchor, Point point, double price, ChartControl chartControl, ChartPanel chartPanel, ChartScale chartScale) { if (TextAlignment == TextLocation.Off) { return; } string priceString; ChartBars chartBars = GetAttachedToChartBars(); // bars can be null while chart is initializing if (chartBars == null) { return; } priceString = GetPriceString(price, chartBars); Stroke color; textleftPoint = RiskAnchor.GetPoint(chartControl, chartPanel, chartScale).X; textRightPoint = EntryAnchor.GetPoint(chartControl, chartPanel, chartScale).X; if (anchor == RewardAnchor) { color = TargetLineStroke; } else if (anchor == RiskAnchor) { color = StopLineStroke; } else if (anchor == EntryAnchor) { color = EntryLineStroke; } else { color = AnchorLineStroke; } SimpleFont wpfFont = chartControl.Properties.LabelFont ?? new SimpleFont(); SharpDX.DirectWrite.TextFormat textFormat = wpfFont.ToDirectWriteTextFormat(); textFormat.TextAlignment = SharpDX.DirectWrite.TextAlignment.Leading; textFormat.WordWrapping = SharpDX.DirectWrite.WordWrapping.NoWrap; SharpDX.DirectWrite.TextLayout textLayout = new SharpDX.DirectWrite.TextLayout(Core.Globals.DirectWriteFactory, priceString, textFormat, chartPanel.H, textFormat.FontSize); if (RiskAnchor.Time <= EntryAnchor.Time) { if (!IsExtendedLinesLeft && !IsExtendedLinesRight) { switch (TextAlignment) { case TextLocation.InsideLeft: point.X = textleftPoint; break; case TextLocation.InsideRight: point.X = textRightPoint - textLayout.Metrics.Width; break; case TextLocation.ExtremeLeft: point.X = textleftPoint; break; case TextLocation.ExtremeRight: point.X = textRightPoint - textLayout.Metrics.Width; break; } } else if (IsExtendedLinesLeft && !IsExtendedLinesRight) { switch (TextAlignment) { case TextLocation.InsideLeft: point.X = textleftPoint; break; case TextLocation.InsideRight: point.X = textRightPoint - textLayout.Metrics.Width; break; case TextLocation.ExtremeLeft: point.X = chartPanel.X; break; case TextLocation.ExtremeRight: point.X = textRightPoint - textLayout.Metrics.Width; break; } } else if (!IsExtendedLinesLeft && IsExtendedLinesRight) { switch (TextAlignment) { case TextLocation.InsideLeft: point.X = textleftPoint; break; case TextLocation.InsideRight: point.X = textRightPoint - textLayout.Metrics.Width; break; case TextLocation.ExtremeLeft: point.X = textleftPoint; break; case TextLocation.ExtremeRight: point.X = chartPanel.W - textLayout.Metrics.Width; break; } } else if (IsExtendedLinesLeft && IsExtendedLinesRight) { switch (TextAlignment) { case TextLocation.InsideLeft: point.X = textleftPoint; break; case TextLocation.InsideRight: point.X = textRightPoint - textLayout.Metrics.Width; break; case TextLocation.ExtremeRight: point.X = chartPanel.W - textLayout.Metrics.Width; break; case TextLocation.ExtremeLeft: point.X = chartPanel.X; break; } } } else if (RiskAnchor.Time >= EntryAnchor.Time) { if (!IsExtendedLinesLeft && !IsExtendedLinesRight) { switch (TextAlignment) { case TextLocation.InsideLeft: point.X = textRightPoint; break; case TextLocation.InsideRight: point.X = textleftPoint - textLayout.Metrics.Width; break; case TextLocation.ExtremeLeft: point.X = textRightPoint; break; case TextLocation.ExtremeRight: point.X = textleftPoint - textLayout.Metrics.Width; break; } } else if (IsExtendedLinesLeft && !IsExtendedLinesRight) { switch (TextAlignment) { case TextLocation.InsideLeft: point.X = textRightPoint; break; case TextLocation.InsideRight: point.X = textleftPoint - textLayout.Metrics.Width; break; case TextLocation.ExtremeLeft: point.X = chartPanel.X; break; case TextLocation.ExtremeRight: point.X = textleftPoint - textLayout.Metrics.Width; break; } } else if (!IsExtendedLinesLeft && IsExtendedLinesRight) { switch (TextAlignment) { case TextLocation.InsideLeft: point.X = textRightPoint; break; case TextLocation.InsideRight: point.X = textleftPoint - textLayout.Metrics.Width; break; case TextLocation.ExtremeLeft: point.X = textRightPoint; break; case TextLocation.ExtremeRight: point.X = chartPanel.W - textLayout.Metrics.Width; break; } } else if (IsExtendedLinesLeft && IsExtendedLinesRight) { switch (TextAlignment) { case TextLocation.InsideLeft: point.X = textRightPoint; break; case TextLocation.InsideRight: point.X = textleftPoint - textLayout.Metrics.Width; break; case TextLocation.ExtremeRight: point.X = chartPanel.W - textLayout.Metrics.Width; break; case TextLocation.ExtremeLeft: point.X = chartPanel.X; break; } } } RenderTarget.DrawTextLayout(new SharpDX.Vector2((float)point.X, (float)point.Y), textLayout, color.BrushDX, SharpDX.Direct2D1.DrawTextOptions.NoSnap); }