public override void OnRender(ChartControl chartControl, ChartScale chartScale) { base.OnRender(chartControl, chartScale); InitializeDrawingTools(); //Calculate where to draw the text. //Refer to parent class Lines.cs OnRender method for more information. ChartPanel panel = chartControl.ChartPanels[chartScale.PanelIndex]; double strokePixAdj = ((double)(Stroke.Width % 2)).ApproxCompare(0) == 0 ? 0.5d : 0d; Vector pixelAdjustVec = new Vector(strokePixAdj, strokePixAdj); Point endPoint = EndAnchor.GetPoint(chartControl, panel, chartScale); Point endPointAdjusted = endPoint + pixelAdjustVec; SharpDX.Vector2 endVec = endPointAdjusted.ToVector2(); //Calculate the current price. string text = (Text != "" ? Text : chartControl.Instrument.MasterInstrument.FormatPrice(chartScale.GetValueByY(endVec.Y), true)); //Set properties for rectangle to draw the object. TextLayout tl = new TextLayout(Core.Globals.DirectWriteFactory, text, cachedTextFormat, ChartPanel.W, ChartPanel.H); SharpDX.RectangleF rect = new SharpDX.RectangleF(); rect.X = (float)endVec.X; rect.Y = (float)endVec.Y - 6f; rect.Width = (float)-(tl.Metrics.Width); rect.Height = (float)-(tl.Metrics.Height); //Draw the text. using (SharpDX.Direct2D1.Brush myDxBrush = TextColor.ToDxBrush(RenderTarget)) { chartScale.GetValueByY(endVec.Y); RenderTarget.DrawText(string.Format("{0}", text), cachedTextFormat, rect, myDxBrush); } }
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: if (IsLocked) { return(Cursors.No); } if (editingAnchor == TextAnchor) { return(Cursors.SizeNESW); } return(editingAnchor == StartAnchor ? Cursors.SizeNESW : Cursors.SizeNWSE); default: // 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) { if (IsLocked) { return(Cursors.Arrow); } return(closest == StartAnchor ? Cursors.SizeNESW : Cursors.SizeNWSE); } // draw move cursor if cursor is near line path anywhere Point startAnchorPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale); Point endAnchorPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale); Point txtAnchorPoint = TextAnchor.GetPoint(chartControl, chartPanel, chartScale); Vector startEndVector = endAnchorPoint - startAnchorPoint; Vector endToTextVector = txtAnchorPoint - endAnchorPoint; //Text Outline Box Path as well UpdateTextLayout(chartControl, ChartPanel, chartScale); Point bottomLeft = new Point(txtAnchorPoint.X - textLayout.MaxWidth - textMargin, txtAnchorPoint.Y); Point topLeft = new Point(bottomLeft.X, txtAnchorPoint.Y - textLayout.MaxHeight - 2 * textMargin); Point topRight = new Point(txtAnchorPoint.X, txtAnchorPoint.Y - textLayout.MaxHeight - 2 * textMargin); Vector txtBottomLeft = bottomLeft - txtAnchorPoint; Vector bottomLeftTopLeft = topLeft - bottomLeft; Vector topLeftTopRight = topRight - topLeft; Vector topRightTxt = txtAnchorPoint - topRight; if (MathHelper.IsPointAlongVector(point, startAnchorPoint, startEndVector, cursorSensitivity) || MathHelper.IsPointAlongVector(point, endAnchorPoint, endToTextVector, cursorSensitivity) || MathHelper.IsPointAlongVector(point, txtAnchorPoint, txtBottomLeft, cursorSensitivity) || MathHelper.IsPointAlongVector(point, bottomLeft, bottomLeftTopLeft, cursorSensitivity) || MathHelper.IsPointAlongVector(point, topLeft, topLeftTopRight, cursorSensitivity) || MathHelper.IsPointAlongVector(point, topRight, topRightTxt, cursorSensitivity)) { return(IsLocked ? Cursors.Arrow : Cursors.SizeAll); } return(null); } }
public override void OnRender(ChartControl chartControl, ChartScale chartScale) { LineColor.RenderTarget = RenderTarget; // first of all, turn on anti-aliasing to smooth out our line RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive; ChartPanel panel = chartControl.ChartPanels[chartScale.PanelIndex]; // draw a line from start measure point to end measure point. Point lineStartPoint = StartAnchor.GetPoint(chartControl, panel, chartScale); Point lineEndPoint = EndAnchor.GetPoint(chartControl, panel, chartScale); // align to full pixel to avoid unneeded aliasing double strokePixAdjust = (LineColor.Width % 2).ApproxCompare(0) == 0 ? 0.5d : 0d; Vector strokePixAdjustVec = new Vector(strokePixAdjust, strokePixAdjust); SharpDX.Vector2 endVec = (lineEndPoint + strokePixAdjustVec).ToVector2(); SharpDX.Direct2D1.Brush tmpBrush = IsInHitTest ? chartControl.SelectionBrush : LineColor.BrushDX; RenderTarget.DrawLine((lineStartPoint + strokePixAdjustVec).ToVector2(), endVec, tmpBrush, LineColor.Width, LineColor.StrokeStyle); if (ShouldDrawText) { UpdateTextLayout(chartControl, ChartPanel, chartScale); textDeviceBrush.RenderTarget = RenderTarget; // Text rec uses same settings as mini data box textBackgroundDeviceBrush.Brush = Application.Current.FindResource("ChartControl.DataBoxBackground") as Brush; textBackgroundDeviceBrush.RenderTarget = RenderTarget; Brush borderBrush = Application.Current.FindResource("BorderThinBrush") as Brush; object thicknessResource = Application.Current.FindResource("BorderThinThickness"); double thickness = thicknessResource as double? ?? 1; Stroke textBorderStroke = new Stroke(borderBrush ?? LineColor.Brush, DashStyleHelper.Solid, Convert.ToSingle(thickness)) { RenderTarget = RenderTarget }; Point textEndPoint = TextAnchor.GetPoint(chartControl, panel, chartScale); SharpDX.Vector2 textEndVec = (textEndPoint + strokePixAdjustVec).ToVector2(); RenderTarget.DrawLine(endVec, textEndVec, LineColor.BrushDX, LineColor.Width, LineColor.StrokeStyle); float rectPixAdjust = (float)(strokePixAdjust / 2f); SharpDX.RectangleF rect = new SharpDX.RectangleF((float)(textEndPoint.X - textLayout.MaxWidth - textMargin + rectPixAdjust), (float)(textEndPoint.Y - textLayout.MaxHeight - textMargin + rectPixAdjust), textLayout.MaxWidth + textMargin * 2f, textLayout.MaxHeight + textMargin); if (textBackgroundDeviceBrush.BrushDX != null && !IsInHitTest) { RenderTarget.FillRectangle(rect, textBackgroundDeviceBrush.BrushDX); } RenderTarget.DrawRectangle(rect, textBorderStroke.BrushDX, textBorderStroke.Width, textBorderStroke.StrokeStyle); if (textDeviceBrush.BrushDX != null && !IsInHitTest) { RenderTarget.DrawTextLayout(new SharpDX.Vector2((float)(rect.X + textMargin + strokePixAdjust), (float)(rect.Y + textMargin + strokePixAdjust)), textLayout, textDeviceBrush.BrushDX); } } }
public override Cursor GetCursor(ChartControl chartControl, ChartPanel chartPanel, ChartScale chartScale, Point point) { if (!IsVisible) { return(null); } switch (DrawingState) { case DrawingState.Building: return(Cursors.Pen); case DrawingState.Moving: return(IsLocked ? Cursors.No : Cursors.SizeAll); case DrawingState.Editing: if (IsLocked) { return(Cursors.No); } return(editingAnchor == StartAnchor ? Cursors.SizeNESW : Cursors.SizeNWSE); default: Point startAnchorPixelPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale); ChartAnchor closest = GetClosestAnchor(chartControl, chartPanel, chartScale, cursorSensitivity, point); if (closest != null) { if (IsLocked) { return(Cursors.Arrow); } return(closest == StartAnchor ? Cursors.SizeNESW : Cursors.SizeNWSE); } // Check the anchor lines for cursor Point endAnchorPixelPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale); Point extAnchorPixelPoint = ExtensionAnchor.GetPoint(chartControl, chartPanel, chartScale); Point midAnchorPixelPoint = new Point((endAnchorPixelPoint.X + extAnchorPixelPoint.X) / 2, (endAnchorPixelPoint.Y + extAnchorPixelPoint.Y) / 2); Vector startToEndVec = endAnchorPixelPoint - startAnchorPixelPoint; Vector endToExtVec = extAnchorPixelPoint - endAnchorPixelPoint; Vector startToMidVec = midAnchorPixelPoint - startAnchorPixelPoint; foreach (Tuple <Point, Point> endPoint in GetAndrewsEndPoints(chartControl, chartScale)) { Vector andrewVector = endPoint.Item1 - endPoint.Item2; if (MathHelper.IsPointAlongVector(point, endPoint.Item2, andrewVector, cursorSensitivity)) { return(IsLocked ? Cursors.Arrow : Cursors.SizeAll); } } return(MathHelper.IsPointAlongVector(point, startAnchorPixelPoint, startToEndVec, cursorSensitivity) || MathHelper.IsPointAlongVector(point, endAnchorPixelPoint, endToExtVec, cursorSensitivity) || MathHelper.IsPointAlongVector(point, startAnchorPixelPoint, startToMidVec, cursorSensitivity) ? (IsLocked ? Cursors.Arrow : Cursors.SizeAll) : null); } }
public override bool IsVisibleOnChart(ChartControl chartControl, ChartScale chartScale, DateTime firstTimeOnChart, DateTime lastTimeOnChart) { // First check any of the actual anchors are visible, we are immediately done foreach (ChartAnchor anchor in Anchors) { if (anchor.IsEditing || anchor.Time >= firstTimeOnChart && anchor.Time <= lastTimeOnChart) { return(true); } } // Calculate extensions and see if they extend into our visible times 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); } double totalPriceRange = EndAnchor.Price - ExtensionAnchor.Price; double startPrice = ExtensionAnchor.Price; foreach (PriceLevel priceLevel in PriceLevels.Where(pl => pl.IsVisible && pl.Stroke != null)) { double levelPrice = (startPrice + ((priceLevel.Value / 100) * totalPriceRange)); float pixelY = chartScale.GetYByValue(levelPrice); float pixelX = anchorExtensionPoint.X > anchorEndPoint.X ? (float)(anchorExtensionPoint.X - (Math.Abs((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100)))) : (float)(anchorExtensionPoint.X + ((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); double padding = 5d; foreach (Point chkPoint in new[] { startPoint, maxLevelPoint, endPoint }) { if (chkPoint.X >= chartPanel.X - padding && chkPoint.X <= chartPanel.W + chartPanel.X + padding && chkPoint.Y >= chartPanel.Y - padding && chkPoint.Y <= chartPanel.Y + chartPanel.H + padding) { return(true); } } } return(false); }
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: if (IsLocked) { return(Cursors.No); } return(editingAnchor == StartAnchor ? Cursors.SizeNESW : Cursors.SizeNWSE); default: // draw move cursor if cursor is near line path anywhere Point startPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale); ChartAnchor closest = GetClosestAnchor(chartControl, chartPanel, chartScale, cursorSensitivity, point); if (closest != null) { if (IsLocked) { return(Cursors.Arrow); } return(closest == StartAnchor ? Cursors.SizeNESW : Cursors.SizeNWSE); } Point endPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale); Point minPoint = startPoint; Point maxPoint = endPoint; /*Vector totalVector = maxPoint - minPoint; * return MathHelper.IsPointAlongVector(point, minPoint, totalVector, cursorSensitivity) ? * IsLocked ? Cursors.Arrow : Cursors.SizeAll : null;*/ Vector DelVector1 = maxPoint - new Point(minPoint.X, maxPoint.Y); Vector DelVector2 = maxPoint - new Point(maxPoint.X, minPoint.Y); Vector DelVector3 = minPoint - new Point(maxPoint.X, minPoint.Y); Vector DelVector4 = minPoint - new Point(minPoint.X, maxPoint.Y); return /*MathHelper.IsPointAlongVector(point, minPoint, totalVector, cursorSensitivity)||*/ /*MathHelper.IsPointAlongVector(point, minPoint, DelVector1, cursorSensitivity)|| * MathHelper.IsPointAlongVector(point, minPoint, DelVector2, cursorSensitivity)|| * MathHelper.IsPointAlongVector(point, maxPoint, DelVector3, cursorSensitivity)|| * MathHelper.IsPointAlongVector(point, maxPoint, DelVector4, cursorSensitivity)*/ (MathHelper.IsPointInsideTriangle(point, minPoint, maxPoint, new Point(minPoint.X, maxPoint.Y)) || MathHelper.IsPointInsideTriangle(point, minPoint, maxPoint, new Point(maxPoint.X, minPoint.Y))? IsLocked ? Cursors.Arrow : Cursors.SizeAll : null); } }
public override Point[] GetSelectionPoints(ChartControl chartControl, ChartScale chartScale) { ChartPanel chartPanel = chartControl.ChartPanels[PanelIndex]; Point startPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale); Point endPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale); double middleX = chartPanel.X + chartPanel.W / 2; double middleY = chartPanel.Y + chartPanel.H / 2; Point midPoint = new Point((startPoint.X + endPoint.X) / 2, (startPoint.Y + endPoint.Y) / 2); return(new[] { startPoint, midPoint, endPoint }.Select(p => Mode == RegionHighlightMode.Time ? new Point(p.X, middleY) : new Point(middleX, p.Y)).ToArray()); }
public sealed override Point[] GetSelectionPoints(ChartControl chartControl, ChartScale chartScale) { ChartPanel chartPanel = chartControl.ChartPanels[chartScale.PanelIndex]; Point startPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale); Point endPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale); int totalWidth = chartPanel.W + chartPanel.X; int totalHeight = chartPanel.Y + chartPanel.H; //Vector strokeAdj = new Vector(Stroke.Width / 2, Stroke.Width / 2); //Point midPoint = startPoint + ((endPoint - startPoint) / 2); return(new[] { startPoint /*, midPoint*/, endPoint }); }
public override bool IsAlertConditionTrue(AlertConditionItem conditionItem, Condition condition, ChartAlertValue[] values, ChartControl chartControl, ChartScale chartScale) { ChartPanel chartPanel = chartControl.ChartPanels[PanelIndex]; double barX = chartControl.GetXByTime(values[0].Time); double barY = chartScale.GetYByValue(values[0].Value); Point startPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale); Point endPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale); Point barPoint = new Point(barX, barY); if (arcGeometry == null || arcGeometry.IsDisposed) { UpdateArcGeometry(chartControl, chartPanel, chartScale); } // Bars have not yet reached edge of drawing tool if (barX < Math.Min(startPoint.X, endPoint.X)) { return(false); } // Do two things, make sure the point is on the right side of the line (the side arc is sweeped into), // and if it is, then check if it is in arc geo MathHelper.PointLineLocation ptLineLocation = MathHelper.GetPointLineLocation(startPoint, endPoint, barPoint); // If its not right/above , its past the line the arc sweeps on, so ignore if (ptLineLocation != MathHelper.PointLineLocation.RightOrBelow) { return(false); } // Our only conditions are cross inside/outside Predicate <ChartAlertValue> arcPredicate = v => { if (v.Time == Core.Globals.MinDate || v.Time == Core.Globals.MaxDate) { return(false); } if (v.Value == double.MinValue) { return(false); } double bX = chartControl.GetXByTime(v.Time); double bY = chartScale.GetYByValue(v.Value); Point bp = new Point(bX, bY); bool isInGeo = arcGeometry.FillContainsPoint(bp.ToVector2()); return(condition == Condition.CrossInside ? isInGeo : !isInGeo); }; return(MathHelper.DidPredicateCross(values, arcPredicate)); }
public sealed override Point[] GetSelectionPoints(ChartControl chartControl, ChartScale chartScale) { ChartPanel chartPanel = chartControl.ChartPanels[chartScale.PanelIndex]; Point startPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale); Point endPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale); if (!ShouldDrawText) { return new[] { startPoint, endPoint } } ; Point textPoint = TextAnchor.GetPoint(chartControl, chartPanel, chartScale); return(new[] { startPoint, textPoint, endPoint }); }
public override Point[] GetSelectionPoints(ChartControl chartControl, ChartScale chartScale) { if (!IsVisible) { return(new Point[0]); } ChartPanel chartPanel = chartControl.ChartPanels[PanelIndex]; Point startPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale); Point endPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale); Point midPoint = new Point((startPoint.X + endPoint.X) / 2, (startPoint.Y + endPoint.Y) / 2); Point extPoint = ExtensionAnchor.GetPoint(chartControl, chartPanel, chartScale); return(new[] { startPoint, midPoint, endPoint, extPoint }); }
public override Cursor GetCursor(ChartControl chartControl, ChartPanel chartPanel, ChartScale chartScale, Point point) { switch (DrawingState) { case DrawingState.Building: return(Cursors.Pen); case DrawingState.Editing: return(IsLocked ? Cursors.No : Mode == RegionHighlightMode.Time ? Cursors.SizeWE : Cursors.SizeNS); case DrawingState.Moving: return(IsLocked ? Cursors.No : Cursors.SizeAll); default: Point startAnchorPixelPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale); ChartAnchor closest = GetClosestAnchor(chartControl, chartPanel, chartScale, cursorSensitivity, point); if (closest != null) { if (IsLocked) { return(Cursors.Arrow); } return(Mode == RegionHighlightMode.Time ? Cursors.SizeWE : Cursors.SizeNS); } Point endAnchorPixelPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale); Vector totalVector = endAnchorPixelPoint - startAnchorPixelPoint; if (MathHelper.IsPointAlongVector(point, startAnchorPixelPoint, totalVector, cursorSensitivity)) { return(IsLocked ? Cursors.Arrow : Cursors.SizeAll); } // check if cursor is along region edges foreach (Point anchorPoint in new[] { startAnchorPixelPoint, endAnchorPixelPoint }) { if (Mode == RegionHighlightMode.Price && Math.Abs(anchorPoint.Y - point.Y) <= cursorSensitivity) { return(IsLocked ? Cursors.Arrow : Cursors.SizeAll); } if (Mode == RegionHighlightMode.Time && Math.Abs(anchorPoint.X - point.X) <= cursorSensitivity) { return(IsLocked ? Cursors.Arrow : Cursors.SizeAll); } } return(null); } }
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: if (IsLocked) { return(Cursors.No); } return(editingAnchor == StartAnchor ? Cursors.SizeNESW : Cursors.SizeNWSE); default: // draw move cursor if cursor is near line path anywhere Point startPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale); ChartAnchor closest = GetClosestAnchor(chartControl, chartPanel, chartScale, cursorSensitivity, point); if (closest != null) { if (IsLocked) { return(Cursors.Arrow); } return(closest == StartAnchor ? Cursors.SizeNESW : Cursors.SizeNWSE); } Point endPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale); Point minPoint = startPoint; Point maxPoint = endPoint; maxPoint = GetExtendedPoint(startPoint, endPoint); Vector totalVector = maxPoint - minPoint; return(MathHelper.IsPointAlongVector(point, minPoint, totalVector, cursorSensitivity) ? IsLocked ? Cursors.Arrow : Cursors.SizeAll : null); } }
public override bool IsVisibleOnChart(ChartControl chartControl, ChartScale chartScale, DateTime firstTimeOnChart, DateTime lastTimeOnChart) { if (DrawingState == DrawingState.Building) { return(true); } DateTime minTime = Core.Globals.MaxDate; DateTime maxTime = Core.Globals.MinDate; Point minPoint; Point maxPoint; // here we'll get extended point and see if they're on scale ChartPanel panel = chartControl.ChartPanels[PanelIndex]; Point startPoint = StartAnchor.GetPoint(chartControl, panel, chartScale); Point endPoint = EndAnchor.GetPoint(chartControl, panel, chartScale); minPoint = startPoint; maxPoint = GetExtendedPoint(chartControl, panel, chartScale, StartAnchor, EndAnchor); foreach (Point pt in new[] { minPoint, maxPoint }) { DateTime time = chartControl.GetTimeByX((int)pt.X); if (time > maxTime) { maxTime = time; } if (time < minTime) { minTime = time; } } if ((minTime >= firstTimeOnChart && minTime <= maxTime) || (maxTime >= firstTimeOnChart && maxTime <= lastTimeOnChart)) { return(true); } return(true); }
public override void OnRender(ChartControl chartControl, ChartScale chartScale) { Stroke.RenderTarget = RenderTarget; // first of all, turn on anti-aliasing to smooth out our line RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive; ChartPanel panel = chartControl.ChartPanels[chartScale.PanelIndex]; Point startPoint = StartAnchor.GetPoint(chartControl, panel, chartScale); // align to full pixel to avoid unneeded aliasing double strokePixAdj = Stroke.Width % 2 == 0 ? 0.5d : 0d; Vector pixelAdjustVec = new Vector(strokePixAdj, strokePixAdj); Point endPoint = EndAnchor.GetPoint(chartControl, panel, chartScale); // convert our start / end pixel points to directx 2d vectors Point startPointAdjusted = startPoint + pixelAdjustVec; Point endPointAdjusted = endPoint + pixelAdjustVec; SharpDX.Vector2 startVec = startPointAdjusted.ToVector2(); SharpDX.Vector2 endVec = endPointAdjusted.ToVector2(); SharpDX.Direct2D1.Brush tmpBrush = IsInHitTest ? chartControl.SelectionBrush : Stroke.BrushDX; // if a plain ol' line, then we're all done // if we're an arrow line, make sure to draw the actual line. for extended lines, only a single // line to extended points is drawn below, to avoid unneeded multiple DrawLine calls RenderTarget.DrawLine(startVec, endVec, tmpBrush, Stroke.Width, Stroke.StrokeStyle); // we have a line type with extensions (ray / extended line) or additional drawing needed // create a line vector to easily calculate total length Vector lineVector = endPoint - startPoint; lineVector.Normalize(); Point minPoint = startPointAdjusted; Point maxPoint = GetExtendedPoint(chartControl, panel, chartScale, StartAnchor, EndAnchor); //GetExtendedPoint(startPoint, endPoint); // RenderTarget.DrawLine(endPointAdjusted.ToVector2(), maxPoint.ToVector2(), tmpBrush, Stroke.Width, Stroke.StrokeStyle); }
private void UpdateArcGeometry(ChartControl chartControl, ChartPanel chartPanel, ChartScale chartScale) { Point startPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale); Point endPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale); if (arcGeometry != null && startPoint == cachedStartPoint && endPoint == cachedEndPoint) { return; } cachedEndPoint = endPoint; cachedStartPoint = startPoint; if (arcGeometry != null && !arcGeometry.IsDisposed) { arcGeometry.Dispose(); } Vector lineVec = endPoint - startPoint; float width = Math.Abs((float)lineVec.X); float height = Math.Abs((float)lineVec.Y); SharpDX.Direct2D1.ArcSegment arcSegment = new SharpDX.Direct2D1.ArcSegment { ArcSize = SharpDX.Direct2D1.ArcSize.Small, Point = new SharpDX.Vector2((float)endPoint.X, (float)endPoint.Y), SweepDirection = SharpDX.Direct2D1.SweepDirection.CounterClockwise, Size = new SharpDX.Size2F(width, height) }; // Create the arc between the line two end points arcGeometry = new SharpDX.Direct2D1.PathGeometry(Core.Globals.D2DFactory); SharpDX.Direct2D1.GeometrySink geometrySink = arcGeometry.Open(); geometrySink.BeginFigure(new SharpDX.Vector2((float)startPoint.X, (float)startPoint.Y), SharpDX.Direct2D1.FigureBegin.Filled); geometrySink.AddArc(arcSegment); geometrySink.EndFigure(SharpDX.Direct2D1.FigureEnd.Open); geometrySink.Close(); }
private IEnumerable <Tuple <Point, Point> > GetAndrewsEndPoints(ChartControl chartControl, ChartScale chartScale) { ChartPanel panel = chartControl.ChartPanels[PanelIndex]; double totalPriceRange = EndAnchor.Price - ExtensionAnchor.Price; double startPrice = ExtensionAnchor.Price; Point anchorExtensionPoint = ExtensionAnchor.GetPoint(chartControl, panel, chartScale); Point anchorStartPoint = StartAnchor.GetPoint(chartControl, panel, chartScale); Point anchorEndPoint = EndAnchor.GetPoint(chartControl, panel, chartScale); Point midPointExtension = new Point((anchorExtensionPoint.X + anchorEndPoint.X) / 2, (anchorExtensionPoint.Y + anchorEndPoint.Y) / 2); foreach (PriceLevel pl in PriceLevels.Where(pl => pl.IsVisible)) { double levelPrice = (startPrice + ((pl.Value / 100) * totalPriceRange)); float pixelY = chartScale.GetYByValue(levelPrice); float pixelX = anchorExtensionPoint.X > anchorEndPoint.X ? (float)(anchorExtensionPoint.X - (Math.Abs((anchorEndPoint.X - anchorExtensionPoint.X) * (pl.Value / 100)))) : (float)(anchorExtensionPoint.X + ((anchorEndPoint.X - anchorExtensionPoint.X) * (pl.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); yield return(new Tuple <Point, Point>(new Point(Math.Max(maxLevelPoint.X, 1), Math.Max(maxLevelPoint.Y, 1)), startPoint)); } }
public override bool IsAlertConditionTrue(AlertConditionItem conditionItem, Condition condition, ChartAlertValue[] values, ChartControl chartControl, ChartScale chartScale) { if (values.Length < 1) { return(false); } ChartPanel chartPanel = chartControl.ChartPanels[PanelIndex]; // get start / end points of what is absolutely shown for our vector Point lineStartPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale); Point lineEndPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale); double minLineX = double.MaxValue; double maxLineX = double.MinValue; foreach (Point point in new[] { lineStartPoint, lineEndPoint }) { minLineX = Math.Min(minLineX, point.X); maxLineX = Math.Max(maxLineX, point.X); } // 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 = values[0].ValueType == ChartAlertValueType.StaticValue ? minLineX : chartControl.GetXByTime(values[0].Time); double firstBarY = chartScale.GetYByValue(values[0].Value); // dont have to take extension into account as its already handled in min/max line x // bars completely passed our line if (maxLineX < firstBarX) { return(false); } // bars not yet to our line if (minLineX > firstBarX) { return(false); } // NOTE: normalize line points so the leftmost is passed first. Otherwise, our vector // math could end up having the line normal vector being backwards if user drew it backwards. // but we dont care the order of anchors, we want 'up' to mean 'up'! Point leftPoint = lineStartPoint.X < lineEndPoint.X ? lineStartPoint : lineEndPoint; Point rightPoint = lineEndPoint.X > lineStartPoint.X ? lineEndPoint : lineStartPoint; 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(leftPoint, rightPoint, 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); MathHelper.PointLineLocation ptLocation = MathHelper.GetPointLineLocation(leftPoint, rightPoint, stepBarPoint); if (condition == Condition.CrossAbove) { return(ptLocation == MathHelper.PointLineLocation.LeftOrAbove); } return(ptLocation == MathHelper.PointLineLocation.RightOrBelow); }; return(MathHelper.DidPredicateCross(values, predicate)); } return(false); }
/* Steps: * 1. Project start/end points for rays and extended lines * 2. Find collitions with ChartPanel for TextBox coordinates * 3. Determine price to be appended * 4. Create message * 5. Draw TextBox */ public override void OnRender(ChartControl chartControl, ChartScale chartScale) { base.OnRender(chartControl, chartScale); Stroke.RenderTarget = RenderTarget; OutlineStroke.RenderTarget = RenderTarget; bool snap = true; bool startsOnScreen = true; bool priceOffScreen = false; double priceToUse = 0; string pricetime = String.Empty; string TextToDisplay = DisplayText; MasterInstrument masterInst = GetAttachedToChartBars().Bars.Instrument.MasterInstrument; Point startPoint = StartAnchor.GetPoint(chartControl, ChartPanel, chartScale); Point endPoint = EndAnchor.GetPoint(chartControl, ChartPanel, chartScale); double strokePixAdj = ((double)(Stroke.Width % 2)).ApproxCompare(0) == 0 ? 0.5d : 0d; Vector pixelAdjustVec = new Vector(strokePixAdj, strokePixAdj); Point startAdj = (LineType == ChartLineType.HorizontalLine ? new Point(ChartPanel.X, startPoint.Y) : new Point(startPoint.X, ChartPanel.Y)) + pixelAdjustVec; Point endAdj = (LineType == ChartLineType.HorizontalLine ? new Point(ChartPanel.X + ChartPanel.W, startPoint.Y) : new Point(startPoint.X, ChartPanel.Y + ChartPanel.H)) + pixelAdjustVec; Vector distVec = Vector.Divide(Point.Subtract(endPoint, startPoint), 100); Vector scalVec = (LineType == ChartLineType.ExtendedLine || LineType == ChartLineType.Ray || LineType == ChartLineType.HorizontalLine) ? Vector.Multiply(distVec, 10000) : Vector.Multiply(distVec, 100); Point extPoint = Vector.Add(scalVec, startPoint); // Project extended line start point if it is off screen if (LineType == ChartLineType.ExtendedLine && TextDisplayMode != TextMode.EndPoint) { startPoint = Point.Subtract(startPoint, scalVec); } // Project TextBox coordinate for extended lines and rays to get ChartPanel bounds if (LineType == ChartLineType.ExtendedLine || LineType == ChartLineType.Ray) { extPoint = Vector.Add(scalVec, extPoint); } // Find collisions with ChartPanel bounds for PriceScale bound TextBox coordinates if (LineType == ChartLineType.HorizontalLine || LineType == ChartLineType.VerticalLine) { extPoint = endAdj; startPoint = startAdj; } else if (TextDisplayMode == TextMode.EndPoint) { extPoint = endPoint; snap = false; } else { if (extPoint.X <= ChartPanel.X || extPoint.Y < ChartPanel.Y || extPoint.X > ChartPanel.W || extPoint.Y > ChartPanel.H) { switch (LineIntersectsRect(startPoint, extPoint, new SharpDX.RectangleF(ChartPanel.X, ChartPanel.Y, ChartPanel.W, ChartPanel.H))) { case RectSide.Top: extPoint = FindIntersection(startPoint, extPoint, new Point(ChartPanel.X, ChartPanel.Y), new Point(ChartPanel.W, ChartPanel.Y)); break; case RectSide.Bottom: extPoint = FindIntersection(startPoint, extPoint, new Point(ChartPanel.W, ChartPanel.H), new Point(ChartPanel.X, ChartPanel.H)); break; case RectSide.Left: extPoint = FindIntersection(startPoint, extPoint, new Point(ChartPanel.X, ChartPanel.H), new Point(ChartPanel.X, ChartPanel.Y)); break; case RectSide.Right: extPoint = FindIntersection(startPoint, extPoint, new Point(ChartPanel.W, ChartPanel.Y), new Point(ChartPanel.W, ChartPanel.H)); break; default: return; } } if (startPoint.X <= ChartPanel.X || startPoint.Y < ChartPanel.Y || startPoint.X > ChartPanel.W || startPoint.Y > ChartPanel.H) { switch (LineIntersectsRect(extPoint, startPoint, new SharpDX.RectangleF(ChartPanel.X, ChartPanel.Y, ChartPanel.W, ChartPanel.H))) { case RectSide.Top: startPoint = FindIntersection(extPoint, startPoint, new Point(ChartPanel.X, ChartPanel.Y), new Point(ChartPanel.W, ChartPanel.Y)); break; case RectSide.Bottom: startPoint = FindIntersection(extPoint, startPoint, new Point(ChartPanel.W, ChartPanel.H), new Point(ChartPanel.X, ChartPanel.H)); break; case RectSide.Left: startPoint = FindIntersection(extPoint, startPoint, new Point(ChartPanel.X, ChartPanel.H), new Point(ChartPanel.X, ChartPanel.Y)); break; case RectSide.Right: startPoint = FindIntersection(extPoint, startPoint, new Point(ChartPanel.W, ChartPanel.Y), new Point(ChartPanel.W, ChartPanel.H)); break; default: return; } } if (endPoint.X <= ChartPanel.X || endPoint.Y < ChartPanel.Y || endPoint.X > ChartPanel.W || endPoint.Y > ChartPanel.H) { priceOffScreen = true; } } // Scale coordinates by HorizontalOffset/VerticalOffset distVec = Point.Subtract(extPoint, startPoint); scalVec = Vector.Multiply(Vector.Divide(distVec, 100), HorizontalOffset); extPoint = Point.Subtract(extPoint, scalVec); extPoint.Y -= VerticalOffset; // Get a Price or a Timestamp to append to the label switch (LineType) { case ChartLineType.VerticalLine: pricetime = StartAnchor.Time.ToString(); break; case ChartLineType.HorizontalLine: priceToUse = StartAnchor.Price; break; case ChartLineType.ExtendedLine: case ChartLineType.Ray: priceToUse = TextDisplayMode == TextMode.PriceScale ? chartScale.GetValueByY(endPoint.X >= startPoint.X ? (float)FindIntersection(startPoint, endPoint, new Point(ChartPanel.W, ChartPanel.Y), new Point(ChartPanel.W, ChartPanel.H)).Y : (float)FindIntersection(startPoint, endPoint, new Point(ChartPanel.X, ChartPanel.Y), new Point(ChartPanel.X, ChartPanel.H)).Y) : EndAnchor.Price; break; default: priceToUse = priceOffScreen && TextDisplayMode == TextMode.PriceScale ? chartScale.GetValueByY(endPoint.X >= startPoint.X ? (float)FindIntersection(startPoint, endPoint, new Point(ChartPanel.W, ChartPanel.Y), new Point(ChartPanel.W, ChartPanel.H)).Y : (float)FindIntersection(startPoint, endPoint, new Point(ChartPanel.X, ChartPanel.Y), new Point(ChartPanel.X, ChartPanel.H)).Y) : EndAnchor.Price; break; } // Round the price if (LineType != ChartLineType.VerticalLine) { pricetime = priceToUse <= masterInst.RoundDownToTickSize(priceToUse) + masterInst.TickSize * 0.5 ? pricetime = masterInst.RoundDownToTickSize(priceToUse).ToString("0.00") : pricetime = masterInst.RoundToTickSize(priceToUse).ToString("0.00"); } // Check if we need to append price or time if (AppendPriceTime && DisplayText.Length > 0) { TextToDisplay = String.Format("{0} {1}", DisplayText, pricetime); } else if (AppendPriceTime) { TextToDisplay = pricetime; } // Use Label Font if one is not specified by template if (Font == null) { Font = new NinjaTrader.Gui.Tools.SimpleFont(chartControl.Properties.LabelFont.Family.ToString(), 16); } // Update DX Brushes if (offScreenDXBrushNeedsUpdate) { offScreenDXBrush.Dispose(); offScreenDXBrush = offScreenMediaBrush.ToDxBrush(RenderTarget); offScreenDXBrushNeedsUpdate = false; } if (backgroundDXBrushNeedsUpdate) { backgroundDXBrush.Dispose(); backgroundDXBrush = backgroundMediaBrush.ToDxBrush(RenderTarget); backgroundDXBrush.Opacity = (float)AreaOpacity / 100f; backgroundDXBrushNeedsUpdate = false; } // Draw TextBoxes switch (LineType) { case ChartLineType.VerticalLine: DrawTextBox(snap, TextToDisplay, extPoint.X, extPoint.Y, Stroke.BrushDX, backgroundDXBrush, OutlineStroke, 1.5708f); break; case ChartLineType.HorizontalLine: DrawTextBox(snap, TextToDisplay, extPoint.X, extPoint.Y, Stroke.BrushDX, backgroundDXBrush, OutlineStroke, 0); break; default: DrawTextBox(snap, TextToDisplay, extPoint.X, extPoint.Y, priceOffScreen && TextDisplayMode == TextMode.EndPointAtPriceScale ? offScreenDXBrush : Stroke.BrushDX, backgroundDXBrush, OutlineStroke, 0); break; } }
public override void OnRender(ChartControl chartControl, ChartScale chartScale) { if (firstTime && DrawingState == DrawingState.Normal) { firstTime = false; Cbi.License.Log("TimeCycles"); } ChartPanel chartPanel = chartControl.ChartPanels[PanelIndex]; int startX = Convert.ToInt32(StartAnchor.GetPoint(chartControl, chartPanel, chartScale).X); diameter = Math.Abs(startX - Convert.ToInt32(EndAnchor.GetPoint(chartControl, chartPanel, chartScale).X)); radius = Convert.ToInt32(diameter / 2.0); if (radius <= 0) { return; } UpdateAnchors(chartControl, startX); if (anchorBars.Count <= 2) { return; } RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive; Stroke outlineStroke = OutlineStroke; outlineStroke.RenderTarget = RenderTarget; // dont bother with an area brush if we're doing a hit test (software) render pass. we do not render area then. // this allows us to select something behind our area brush (like NT7) bool renderArea = false; if (!IsInHitTest && AreaBrush != null) { if (areaBrushDevice.Brush == null) { Brush brushCopy = areaBrush.Clone(); brushCopy.Opacity = areaOpacity / 100d; areaBrushDevice.Brush = brushCopy; } areaBrushDevice.RenderTarget = RenderTarget; renderArea = true; } else { areaBrushDevice.RenderTarget = null; areaBrushDevice.Brush = null; } for (int i = 0; i < anchorBars.Count - 1; i++) { SharpDX.Direct2D1.Ellipse ellipse = new SharpDX.Direct2D1.Ellipse(new SharpDX.Vector2(anchorBars[i] + radius, chartPanel.Y + chartPanel.H), radius, radius); if (renderArea) { RenderTarget.FillEllipse(ellipse, areaBrushDevice.BrushDX); } SharpDX.Direct2D1.Brush tmpBrush = IsInHitTest ? chartControl.SelectionBrush : outlineStroke.BrushDX; RenderTarget.DrawEllipse(ellipse, tmpBrush); } }
public override bool IsAlertConditionTrue(AlertConditionItem conditionItem, Condition condition, ChartAlertValue[] values, ChartControl chartControl, ChartScale chartScale) { PriceLevel priceLevel = conditionItem.Tag as PriceLevel; if (priceLevel == null) { return(false); } 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); } double totalPriceRange = EndAnchor.Price - ExtensionAnchor.Price; double startPrice = ExtensionAnchor.Price; double levelPrice = (startPrice + ((priceLevel.Value / 100) * totalPriceRange)); float pixelY = chartScale.GetYByValue(levelPrice); float pixelX = anchorExtensionPoint.X > anchorEndPoint.X ? (float)(anchorExtensionPoint.X - (Math.Abs((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100)))) : (float)(anchorExtensionPoint.X + ((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100))); Point alertStartPoint = new Point(pixelX, pixelY); Point endPoint = new Point(alertStartPoint.X + (midPointExtension.X - anchorStartPoint.X), alertStartPoint.Y + (midPointExtension.Y - anchorStartPoint.Y)); Point alertEndPoint = GetExtendedPoint(alertStartPoint, endPoint); double firstBarX = values[0].ValueType == ChartAlertValueType.StaticValue ? pixelX : chartControl.GetXByTime(values[0].Time); double firstBarY = chartScale.GetYByValue(values[0].Value); Point barPoint = new Point(firstBarX, firstBarY); // Check bars are not yet to our drawing tool if (firstBarX < alertStartPoint.X || firstBarX > alertEndPoint.X) { return(false); } // NOTE: 'left / right' is relative to if line was vertical. It can end up backwards too MathHelper.PointLineLocation pointLocation = MathHelper.GetPointLineLocation(alertStartPoint, alertEndPoint, 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(alertStartPoint, alertEndPoint, stepBarPoint); if (condition == Condition.CrossAbove) { return(ptLocation == MathHelper.PointLineLocation.LeftOrAbove); } return(ptLocation == MathHelper.PointLineLocation.RightOrBelow); }; return(MathHelper.DidPredicateCross(values, predicate)); } return(false); }
public override void OnRender(ChartControl chartControl, ChartScale chartScale) { try { if (model != null) { SharpDX.Direct2D1.AntialiasMode oldAntialiasMode = RenderTarget.AntialiasMode; RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive; ChartPanel panel = chartControl.ChartPanels[chartScale.PanelIndex]; Point startPoint = StartAnchor.GetPoint(chartControl, panel, chartScale); // align to full pixel to avoid unneeded aliasing double strokePixAdj = ((double)(1 % 2)).ApproxCompare(0) == 0 ? 0.5d : 0d; Vector pixelAdjustVec = new Vector(strokePixAdj, strokePixAdj); Point endPoint = EndAnchor.GetPoint(chartControl, panel, chartScale); // convert our start / end pixel points to directx 2d vectors Point startPointAdjusted = startPoint + pixelAdjustVec; Point endPointAdjusted = endPoint + pixelAdjustVec; SharpDX.Vector2 startVec = startPointAdjusted.ToVector2(); SharpDX.Vector2 endVec = endPointAdjusted.ToVector2(); //SharpDX.Direct2D1.Brush tmpBrush = chartControl.SelectionBrush; SharpDX.Vector2 tmpVect = startVec - endVec; brush0DX = new SharpDX.Direct2D1.SolidColorBrush(RenderTarget, SharpDX.Color.Black); brush0DX.Opacity = (float)0.01; brush1DX = model.Input_ProfileRange_Border_Color.ToDxBrush(RenderTarget); brush2DX = model.Input_ProfileRange_Inside_Color.ToDxBrush(RenderTarget); brush2DX.Opacity = model.Profile_Opacity / (float)100d; brush3DX = model.Input_ProfileRange_POC_Color.ToDxBrush(RenderTarget); brush3DX.Opacity = model.Profile_Opacity / (float)100d; brush4DX = model.Range_Profile_Text_Color.ToDxBrush(RenderTarget); brush4DX.Opacity = model.Profile_Text_Opacity / (float)100d; brush5DX = model.Input_ProfileRange_Inside_Bid_Color.ToDxBrush(RenderTarget); brush5DX.Opacity = model.Profile_Opacity / (float)100d; brush6DX = model.Input_ProfileRange_Inside_Ask_Color.ToDxBrush(RenderTarget); brush6DX.Opacity = model.Profile_Opacity / (float)100d; brush7DX = new SharpDX.Direct2D1.SolidColorBrush(RenderTarget, SharpDX.Color.WhiteSmoke); brush8DX = new SharpDX.Direct2D1.SolidColorBrush(RenderTarget, SharpDX.Color.Gray); brush9DX = new SharpDX.Direct2D1.SolidColorBrush(RenderTarget, SharpDX.Color.Gray); brush9DX.Opacity = (float)0.5; brush10DX = model.Input_ProfileRange_POC_Color.ToDxBrush(RenderTarget); brush10DX.Opacity = model.Profile_Text_Opacity / (float)100d; // if a plain ol' line, then we're all done // if we're an arrow line, make sure to draw the actual line. for extended lines, only a single // line to extended points is drawn below, to avoid unneeded multiple DrawLine calls //RenderTarget.DrawLine(startVec, endVec, model.Input_ProfileRange_Inside_Color.ToDxBrush(RenderTarget), 2); RenderTarget.DrawRectangle(new SharpDX.RectangleF(endVec.X, endVec.Y, tmpVect.X, tmpVect.Y), brush1DX, (float)1); RenderTarget.FillRectangle(new SharpDX.RectangleF(endVec.X, endVec.Y, tmpVect.X, tmpVect.Y), brush0DX); //int firstindex = ((int)model.parent.ChartControl.GetSlotIndexByTime(StartAnchor.Time)); //int lastIndex = ((int)model.parent.ChartControl.GetSlotIndexByTime(EndAnchor.Time)); int firstindex = model.parent.ChartBars.GetBarIdxByTime(chartControl, StartAnchor.Time); //Edited by PD int lastIndex = model.parent.ChartBars.GetBarIdxByTime(chartControl, EndAnchor.Time); //Edited by PD Model.HistogrammClass profile = new Model.HistogrammClass(); int count = 0; IEnumerable <Model.Bar> bars; if (firstindex <= lastIndex) { bars = model.GetBarRange(firstindex, lastIndex); } else { bars = model.GetBarRange(lastIndex, firstindex); } int leftPosition = 0; int topPosition = 0; if (startVec.X < endVec.X) { leftPosition = (int)startVec.X; } else { leftPosition = (int)endVec.X; } if (startVec.Y < endVec.Y) { topPosition = (int)startVec.Y; } else { topPosition = (int)endVec.Y; } foreach (Model.Bar bar in bars) { IEnumerable <KeyValuePair <double, Model.Claster> > clasters; if (StartAnchor.Price >= EndAnchor.Price) { clasters = bar.ListOfClasters.Where(c => c.Key <= StartAnchor.Price && c.Key >= EndAnchor.Price); } else { clasters = bar.ListOfClasters.Where(c => c.Key >= StartAnchor.Price && c.Key <= EndAnchor.Price); } foreach (KeyValuePair <double, Model.Claster> claster in clasters) { profile.AddPrintToHistogramm(claster.Key, claster.Value.Volume_Ask_sum, PrintType.ASK); profile.AddPrintToHistogramm(claster.Key, claster.Value.Volume_Bid_sum, PrintType.BID); } } //textToRender+=" : "+profile.ListOfCurrentBar.Count.ToString(); Dictionary <double, int> deltaProfile = new Dictionary <double, int>(); double maxDeltaPrice = int.MinValue; int prevdelta = 0; int volumeSum = 0; foreach (KeyValuePair <double, Model.CurrentClaster> claster in profile.ListOfCurrentBar) { volumeSum += claster.Value.Volume_sum; int delta = Math.Abs(claster.Value.Volume_Bid_sum - claster.Value.Volume_Ask_sum); deltaProfile.Add(claster.Key, delta); if (prevdelta <= delta) { prevdelta = delta; maxDeltaPrice = claster.Key; } } SharpDX.DirectWrite.TextFormat Claster_textFormat = chartControl.Properties.LabelFont.ToDirectWriteTextFormat(); Claster_textFormat.ParagraphAlignment = SharpDX.DirectWrite.ParagraphAlignment.Center; int vol1 = ProfileType != 1 ? (int)Math.Abs(tmpVect.X) : (int)Math.Abs(tmpVect.X / 2); float fontSize1 = Math.Max(7, Math.Min(vol1 / 2, Math.Min(14, model.Claster_Height - 1))); SharpDX.DirectWrite.TextFormat Claster_textFormatEach = new SharpDX.DirectWrite.TextFormat(Core.Globals.DirectWriteFactory, "Arial", SharpDX.DirectWrite.FontWeight.Normal, SharpDX.DirectWrite.FontStyle.Normal, fontSize1); Claster_textFormatEach.TextAlignment = SharpDX.DirectWrite.TextAlignment.Leading; Claster_textFormatEach.ParagraphAlignment = SharpDX.DirectWrite.ParagraphAlignment.Center; Claster_textFormatEach.WordWrapping = SharpDX.DirectWrite.WordWrapping.NoWrap; if (ProfileType == 1 || ProfileType == 0) { foreach (KeyValuePair <double, Model.CurrentClaster> claster in profile.ListOfCurrentBar) { int Y_histogramm = chartScale.GetYByValue(claster.Key) - model.Claster_Height / 2; int vol = claster.Value.Volume_sum * (int)Math.Abs(tmpVect.X) / profile.ListOfCurrentBar[profile.pocPrice].Volume_sum; if (ProfileType == 0) { if (claster.Key == profile.pocPrice) { if (ExtendedLine) { vol = (int)ChartPanel.MaxWidth - Math.Abs(leftPosition); } RenderTarget.FillRectangle(new SharpDX.RectangleF(leftPosition, Y_histogramm, vol, model.Claster_Height), brush3DX); int text_Y = chartScale.GetYByValue(profile.pocPrice) - model.Claster_Height / 2; int text_width = profile.pocPrice.ToString().Length *7; RenderTarget.DrawText(profile.pocPrice.ToString(), Claster_textFormat, new SharpDX.RectangleF(leftPosition - text_width, text_Y, text_width, model.Claster_Height), brush10DX); //RenderTarget.DrawRectangle(new SharpDX.RectangleF(leftPosition-text_width, text_Y,text_width ,model.Claster_Height), Brushes.Red.ToDxBrush(RenderTarget), 1f); // } else { RenderTarget.FillRectangle(new SharpDX.RectangleF(leftPosition, Y_histogramm, vol, model.Claster_Height), brush2DX); } if (model.Range_Profile_Text_OnOff && vol1 > 10 && model.Claster_Height > 5) { SharpDX.RectangleF rectText = new SharpDX.RectangleF(leftPosition + 2, Y_histogramm, vol1, model.Claster_Height); //RenderTarget.DrawRectangle(rectText, model.Range_Profile_Text_Color.ToDxBrush(RenderTarget), 1f); RenderTarget.DrawText(claster.Value.Volume_sum.ToString(), Claster_textFormatEach, rectText, brush4DX); } } if (ProfileType == 1) { int vol_bid = claster.Value.Volume_Bid_sum * vol / claster.Value.Volume_sum; RenderTarget.FillRectangle(new SharpDX.RectangleF(leftPosition, Y_histogramm, vol_bid, model.Claster_Height), brush5DX); RenderTarget.FillRectangle(new SharpDX.RectangleF(leftPosition + vol_bid, Y_histogramm, vol - vol_bid, model.Claster_Height), brush6DX); if (claster.Key == profile.pocPrice && ExtendedLine) { RenderTarget.FillRectangle(new SharpDX.RectangleF(leftPosition + vol, Y_histogramm, (int)ChartPanel.MaxWidth - Math.Abs(leftPosition + vol), model.Claster_Height), brush3DX); } if (claster.Key == profile.pocPrice) { int text_Y = chartScale.GetYByValue(profile.pocPrice) - model.Claster_Height / 2; int text_width = profile.pocPrice.ToString().Length *7; RenderTarget.DrawText(profile.pocPrice.ToString(), Claster_textFormat, new SharpDX.RectangleF(leftPosition - text_width, text_Y, text_width, model.Claster_Height), brush10DX); //RenderTarget.DrawRectangle(new SharpDX.RectangleF(leftPosition-text_width, text_Y,text_width ,model.Claster_Height), Brushes.Red.ToDxBrush(RenderTarget), 1f); } if (model.Range_Profile_Text_OnOff && vol1 > 10 && model.Claster_Height > 5) { SharpDX.RectangleF rectText = new SharpDX.RectangleF(leftPosition + 2, Y_histogramm, vol1, model.Claster_Height); //RenderTarget.DrawRectangle(rectText, model.Range_Profile_Text_Color.ToDxBrush(RenderTarget), 1f); RenderTarget.DrawText(claster.Value.Volume_Bid_sum.ToString() + " x " + claster.Value.Volume_Ask_sum.ToString(), Claster_textFormatEach, rectText, brush4DX); } } } } if (ProfileType == 2) { foreach (KeyValuePair <double, int> claster in deltaProfile) { int Y_histogramm = chartScale.GetYByValue(claster.Key) - model.Claster_Height / 2; int vol_delta = claster.Value * (int)Math.Abs(tmpVect.X) / (int)prevdelta; if (profile.ListOfCurrentBar[claster.Key].Volume_Bid_sum == profile.ListOfCurrentBar[claster.Key].Volume_Ask_sum) { vol_delta = 0; } else if (profile.ListOfCurrentBar[claster.Key].Volume_Bid_sum > profile.ListOfCurrentBar[claster.Key].Volume_Ask_sum) { RenderTarget.FillRectangle(new SharpDX.RectangleF(leftPosition, Y_histogramm, vol_delta, model.Claster_Height), brush5DX); } else if (profile.ListOfCurrentBar[claster.Key].Volume_Bid_sum < profile.ListOfCurrentBar[claster.Key].Volume_Ask_sum) { RenderTarget.FillRectangle(new SharpDX.RectangleF(leftPosition, Y_histogramm, vol_delta, model.Claster_Height), brush6DX); } if (model.Range_Profile_Text_OnOff && vol1 > 10 && model.Claster_Height > 5) { SharpDX.RectangleF rectText = new SharpDX.RectangleF(leftPosition + 2, Y_histogramm, vol1, model.Claster_Height); //RenderTarget.DrawRectangle(rectText, model.Range_Profile_Text_Color.ToDxBrush(RenderTarget), 1f); RenderTarget.DrawText((profile.ListOfCurrentBar[claster.Key].Volume_Ask_sum - profile.ListOfCurrentBar[claster.Key].Volume_Bid_sum).ToString(), Claster_textFormatEach, rectText, brush4DX); } } int text_Y = chartScale.GetYByValue(maxDeltaPrice) - model.Claster_Height / 2; int text_width = maxDeltaPrice.ToString().Length *7; RenderTarget.DrawText(maxDeltaPrice.ToString(), Claster_textFormat, new SharpDX.RectangleF(leftPosition - text_width, text_Y, text_width, model.Claster_Height), brush10DX); } RenderTarget.DrawText("Σ " + volumeSum.ToString(), Claster_textFormat, new SharpDX.RectangleF(leftPosition, topPosition + Math.Abs(tmpVect.Y) + 3, volumeSum.ToString().Length *8 + 10, 10), brush10DX); if (Claster_textFormat != null) { Claster_textFormat.Dispose(); } if (Claster_textFormatEach != null) { Claster_textFormatEach.Dispose(); } if (IsSelected) { SharpDX.Vector2 tempVector1 = new Point(leftPosition + 2, topPosition + 2 - 20).ToVector2(); SharpDX.Vector2 tempVector2 = new Point(leftPosition - 2 + 15, topPosition - 2 - 20 + 15).ToVector2(); RenderTarget.DrawLine(tempVector1, tempVector2, brush8DX, 2); tempVector1.X += 11; tempVector2.X -= 11; RenderTarget.DrawLine(tempVector1, tempVector2, brush8DX, 2); RenderTarget.DrawRectangle(new SharpDX.RectangleF(leftPosition, topPosition - 20, 15, 15), brush8DX, (float)1); RenderTarget.DrawRectangle(new SharpDX.RectangleF(leftPosition + 20, topPosition - 20, 15, 15), brush8DX, (float)1); string str = ""; switch (ProfileType) { case 0: str = "V"; break; case 1: str = "P"; break; case 2: str = "D"; break; } SharpDX.DirectWrite.Factory fontFactory = new SharpDX.DirectWrite.Factory(); SharpDX.DirectWrite.TextFormat textFormat = new SharpDX.DirectWrite.TextFormat(fontFactory, "Segoe UI", 15); RenderTarget.DrawText(str, textFormat, new SharpDX.RectangleF(leftPosition + 23, topPosition - 23, 15, 15), brush7DX); fontFactory.Dispose(); textFormat.Dispose(); if (ExtendedLine) { RenderTarget.FillRectangle(new SharpDX.RectangleF(leftPosition + 42, topPosition - 18, 11, 11), brush9DX); } RenderTarget.DrawRectangle(new SharpDX.RectangleF(leftPosition + 40, topPosition - 20, 15, 15), brush8DX, (float)1); } RenderTarget.AntialiasMode = oldAntialiasMode; if (brush0DX != null) { brush0DX.Dispose(); } if (brush1DX != null) { brush1DX.Dispose(); } if (brush2DX != null) { brush2DX.Dispose(); } if (brush3DX != null) { brush3DX.Dispose(); } if (brush4DX != null) { brush4DX.Dispose(); } if (brush5DX != null) { brush5DX.Dispose(); } if (brush6DX != null) { brush6DX.Dispose(); } if (brush7DX != null) { brush7DX.Dispose(); } if (brush8DX != null) { brush8DX.Dispose(); } if (brush9DX != null) { brush9DX.Dispose(); } if (brush10DX != null) { brush10DX.Dispose(); } } } catch (Exception ex) { Print("Range Profile2 OnRender 663: " + ex); } return; }
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); } } }
private void UpdateTextLayout(ChartControl chartControl, ChartPanel chartPanel, ChartScale chartScale) { if (isTextCreated && textLayout != null && !textLayout.IsDisposed) { return; } if (textFormat != null && !textFormat.IsDisposed) { textFormat.Dispose(); } if (textLayout != null && !textLayout.IsDisposed) { textLayout.Dispose(); } ChartBars chartBars = GetAttachedToChartBars(); // bars can be null while chart is initializing if (chartBars == null) { return; } double yDiffPrice = AttachedTo.Instrument.MasterInstrument.RoundToTickSize(EndAnchor.Price - StartAnchor.Price); double yDiffTicks = yDiffPrice / AttachedTo.Instrument.MasterInstrument.TickSize; switch (YValueDisplayUnit) { case ValueUnit.Price: yValueString = chartBars.Bars.Instrument.MasterInstrument.FormatPrice(yDiffPrice); break; case ValueUnit.Currency: yValueString = AttachedTo.Instrument.MasterInstrument.InstrumentType == InstrumentType.Forex ? Core.Globals.FormatCurrency((int)Math.Abs(yDiffTicks) * Account.All[0].ForexLotSize * (AttachedTo.Instrument.MasterInstrument.TickSize * AttachedTo.Instrument.MasterInstrument.PointValue)) : Core.Globals.FormatCurrency((int)Math.Abs(yDiffTicks) * (AttachedTo.Instrument.MasterInstrument.TickSize * AttachedTo.Instrument.MasterInstrument.PointValue)); break; case ValueUnit.Percent: yValueString = (yDiffPrice / AttachedTo.Instrument.MasterInstrument.RoundToTickSize(StartAnchor.Price)).ToString("P", Core.Globals.GeneralOptions.CurrentCulture); break; case ValueUnit.Ticks: yValueString = yDiffTicks.ToString("F0"); break; case ValueUnit.Pips: // show tenth pips (if available) double pips = Math.Abs(yDiffTicks / 10); char decimalChar = Char.Parse(Core.Globals.GeneralOptions.CurrentCulture.NumberFormat.NumberDecimalSeparator); yValueString = Int32.Parse(pips.ToString("F1").Split(decimalChar)[1]) > 0 ? pips.ToString("F1").Replace(decimalChar, '\'') : pips.ToString("F0"); break; } TimeSpan timeDiff = EndAnchor.Time - StartAnchor.Time; // trim off millis/ticks, match NT7 time formatting timeDiff = new TimeSpan(timeDiff.Days, timeDiff.Hours, timeDiff.Minutes, timeDiff.Seconds); bool isMultiDay = Math.Abs(timeDiff.TotalHours) >= 24; if (chartBars.Bars.BarsPeriod.BarsPeriodType == BarsPeriodType.Day) { int timeDiffDay = Math.Abs(timeDiff.Days); timeText = timeDiffDay > 1 ? Math.Abs(timeDiff.Days) + " " + Custom.Resource.Days : Math.Abs(timeDiff.Days) + " " + Custom.Resource.Day; } else { timeText = isMultiDay ? string.Format("{0}\n{1,25}", string.Format(Custom.Resource.NinjaScriptDrawingToolRulerDaysFormat, Math.Abs(timeDiff.Days)), timeDiff.Subtract(new TimeSpan(timeDiff.Days, 0, 0, 0)).Duration().ToString()) : timeDiff.Duration().ToString(); } Point startPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale); Point endPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale); int startIdx = chartBars.GetBarIdxByX(chartControl, (int)startPoint.X); int endIdx = chartBars.GetBarIdxByX(chartControl, (int)endPoint.X); int numBars = endIdx - startIdx; SimpleFont wpfFont = chartControl.Properties.LabelFont ?? new SimpleFont(); textFormat = wpfFont.ToDirectWriteTextFormat(); textFormat.TextAlignment = SharpDX.DirectWrite.TextAlignment.Leading; textFormat.WordWrapping = SharpDX.DirectWrite.WordWrapping.NoWrap; // format text to our text rectangle bounds (it will wrap to these constraints), nt7 format // NOTE: Environment.NewLine doesnt work right here string text = string.Format("{0}\n{1,-11}{2,-11}\n{3,-11}{4,-11}\n{5,-10}{6,-10}", AttachedTo.DisplayName, Custom.Resource.NinjaScriptDrawingToolRulerNumberBarsText, numBars, Custom.Resource.NinjaScriptDrawingToolRulerTimeText, timeText, Custom.Resource.NinjaScriptDrawingToolRulerYValueText, yValueString); // give big values for max width/height, we will trim to actual used textLayout = new SharpDX.DirectWrite.TextLayout(Core.Globals.DirectWriteFactory, text, textFormat, 600, 600); // use measured max width/height textLayout.MaxWidth = textLayout.Metrics.Width; textLayout.MaxHeight = textLayout.Metrics.Height; isTextCreated = true; }
public override void OnRender(ChartControl chartControl, ChartScale chartScale) { //Allow user to change ZOrder when manually drawn on chart if (!hasSetZOrder && !StartAnchor.IsNinjaScriptDrawn) { ZOrderType = DrawingToolZOrder.Normal; ZOrder = ChartPanel.ChartObjects.Min(z => z.ZOrder) - 1; hasSetZOrder = true; } RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive; OutlineStroke.RenderTarget = RenderTarget; ChartPanel chartPanel = chartControl.ChartPanels[PanelIndex]; // recenter region anchors to always be onscreen/centered double middleX = chartPanel.X + chartPanel.W / 2d; double middleY = chartPanel.Y + chartPanel.H / 2d; if (Mode == RegionHighlightMode.Price) { StartAnchor.UpdateXFromPoint(new Point(middleX, 0), chartControl, chartScale); EndAnchor.UpdateXFromPoint(new Point(middleX, 0), chartControl, chartScale); } else { StartAnchor.UpdateYFromDevicePoint(new Point(0, middleY), chartScale); EndAnchor.UpdateYFromDevicePoint(new Point(0, middleY), chartScale); } Point startPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale); Point endPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale); double width = endPoint.X - startPoint.X; AnchorLineStroke.RenderTarget = RenderTarget; OutlineStroke.RenderTarget = RenderTarget; if (!IsInHitTest && AreaBrush != null) { if (areaBrushDevice.Brush == null) { Brush brushCopy = areaBrush.Clone(); brushCopy.Opacity = areaOpacity / 100d; areaBrushDevice.Brush = brushCopy; } areaBrushDevice.RenderTarget = RenderTarget; } else { areaBrushDevice.RenderTarget = null; areaBrushDevice.Brush = null; } // align to full pixel to avoid unneeded aliasing float strokePixAdjust = Math.Abs(OutlineStroke.Width % 2d).ApproxCompare(0) == 0 ? 0.5f : 0f; SharpDX.RectangleF rect = Mode == RegionHighlightMode.Time ? new SharpDX.RectangleF((float)startPoint.X + strokePixAdjust, ChartPanel.Y - OutlineStroke.Width + strokePixAdjust, (float)width, chartPanel.Y + chartPanel.H + OutlineStroke.Width * 2) : new SharpDX.RectangleF(chartPanel.X - OutlineStroke.Width + strokePixAdjust, (float)startPoint.Y + strokePixAdjust, chartPanel.X + chartPanel.W + OutlineStroke.Width * 2, (float)(endPoint.Y - startPoint.Y)); if (!IsInHitTest && areaBrushDevice.BrushDX != null) { RenderTarget.FillRectangle(rect, areaBrushDevice.BrushDX); } SharpDX.Direct2D1.Brush tmpBrush = IsInHitTest ? chartControl.SelectionBrush : OutlineStroke.BrushDX; RenderTarget.DrawRectangle(rect, tmpBrush, OutlineStroke.Width, OutlineStroke.StrokeStyle); if (IsSelected) { tmpBrush = IsInHitTest ? chartControl.SelectionBrush : AnchorLineStroke.BrushDX; RenderTarget.DrawLine(startPoint.ToVector2(), endPoint.ToVector2(), tmpBrush, AnchorLineStroke.Width, AnchorLineStroke.StrokeStyle); } }
public override void OnRender(ChartControl chartControl, ChartScale chartScale) { if (model == null) { return; } try { // first of all, turn on anti-aliasing to smooth out our line RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive; ChartPanel panel = chartControl.ChartPanels[chartScale.PanelIndex]; Point startPoint = StartAnchor.GetPoint(chartControl, panel, chartScale); Point endPoint = EndAnchor.GetPoint(chartControl, panel, chartScale); // convert our start / end pixel points to directx 2d vectors Point startPointAdjusted = startPoint /*+ pixelAdjustVec*/; Point endPointAdjusted = endPoint /*+ pixelAdjustVec*/; SharpDX.Vector2 startVec = startPointAdjusted.ToVector2(); SharpDX.Vector2 endVec = endPointAdjusted.ToVector2(); //SharpDX.Direct2D1.Brush tmpBrush = IsInHitTest ? chartControl.SelectionBrush : LineStroke.BrushDX; SharpDX.Vector2 tmpVect = startVec - endVec; SharpDX.Direct2D1.Brush brush = Brushes.Red.ToDxBrush(RenderTarget); brush.Opacity = IsSelected ? (float)0.3 : 0; RenderTarget.DrawRectangle(new SharpDX.RectangleF(endVec.X, endVec.Y, tmpVect.X, tmpVect.Y), model.Input_ProfileRange_Border_Color.ToDxBrush(RenderTarget), (float)1); //RenderTarget.FillRectangle(new SharpDX.RectangleF(endVec.X, endVec.Y, tmpVect.X, tmpVect.Y),brush); int firstindex = ((int)model.parent.ChartControl.GetSlotIndexByTime(StartAnchor.Time)); int lastIndex = ((int)model.parent.ChartControl.GetSlotIndexByTime(EndAnchor.Time)); IEnumerable <Model.Bar> bars; if (firstindex <= lastIndex) { bars = model.GetBarRange(firstindex, lastIndex); } else { bars = model.GetBarRange(lastIndex, firstindex); } int leftPosition = 0; int topPosition = 0; if (startVec.X < endVec.X) { leftPosition = (int)startVec.X; } else { leftPosition = (int)endVec.X; } if (startVec.Y < endVec.Y) { topPosition = (int)startVec.Y; } else { topPosition = (int)endVec.Y; } Model.HistogrammClass profile = new Model.HistogrammClass(); int count = 0; foreach (Model.Bar bar in bars) { IEnumerable <KeyValuePair <double, Model.Claster> > clasters; if (StartAnchor.Price >= EndAnchor.Price) { clasters = bar.ListOfClasters.Where(c => c.Key <= StartAnchor.Price && c.Key >= EndAnchor.Price); } else { clasters = bar.ListOfClasters.Where(c => c.Key >= StartAnchor.Price && c.Key <= EndAnchor.Price); } foreach (KeyValuePair <double, Model.Claster> claster in clasters) { profile.AddPrintToHistogramm(claster.Key, claster.Value.Volume_Ask_sum, PrintType.ASK); profile.AddPrintToHistogramm(claster.Key, claster.Value.Volume_Bid_sum, PrintType.BID); } } //textToRender+=" : "+profile.ListOfCurrentBar.Count.ToString(); SharpDX.Direct2D1.Brush profile_Claster_Color = model.Input_ProfileRange_Inside_Color.ToDxBrush(RenderTarget); profile_Claster_Color.Opacity = (float)0.5; int volumeSum = 0; foreach (KeyValuePair <double, Model.CurrentClaster> claster in profile.ListOfCurrentBar) { int Y_histogramm = chartScale.GetYByValue(claster.Key) - model.Claster_Height / 2; int vol = claster.Value.Volume_sum * (int)Math.Abs(tmpVect.X) / profile.ListOfCurrentBar[profile.pocPrice].Volume_sum; volumeSum += claster.Value.Volume_sum; if (claster.Key == profile.pocPrice) { RenderTarget.FillRectangle(new SharpDX.RectangleF(leftPosition, Y_histogramm, vol, model.Claster_Height), model.Input_ProfileRange_POC_Color.ToDxBrush(RenderTarget)); } else { RenderTarget.FillRectangle(new SharpDX.RectangleF(leftPosition, Y_histogramm, vol, model.Claster_Height), profile_Claster_Color); } } SharpDX.DirectWrite.TextFormat Claster_textFormat = chartControl.Properties.LabelFont.ToDirectWriteTextFormat(); RenderTarget.DrawText("Σ " + volumeSum.ToString(), Claster_textFormat, new SharpDX.RectangleF(leftPosition, topPosition + Math.Abs(tmpVect.Y) + 3, volumeSum.ToString().Length *8 + 10, 10), Brushes.WhiteSmoke.ToDxBrush(RenderTarget)); int text_Y = chartScale.GetYByValue(profile.pocPrice) - model.Claster_Height / 2; int text_width = profile.pocPrice.ToString().Length *7; RenderTarget.DrawText(profile.pocPrice.ToString(), Claster_textFormat, new SharpDX.RectangleF(leftPosition - text_width, text_Y, text_width, 10), model.Input_ProfileRange_POC_Color.ToDxBrush(RenderTarget)); if (false) { RenderTarget.DrawRectangle(new SharpDX.RectangleF(leftPosition, topPosition - 20, 15, 15), Brushes.Gray.ToDxBrush(RenderTarget), (float)1); } return; } catch (Exception ex) { Print("MR CustomProfile 414: " + ex); } }