예제 #1
0
        private void DrawString(string text, SimpleFont font, DXMediaBrush brush, double pointX, double pointY, DXMediaBrush areaBrush)
        {
            SharpDX.DirectWrite.TextFormat textFormat = font.ToDirectWriteTextFormat();
            SharpDX.DirectWrite.TextLayout textLayout =
                new SharpDX.DirectWrite.TextLayout(NinjaTrader.Core.Globals.DirectWriteFactory,
                                                   text, textFormat, ChartPanel.X + ChartPanel.W,
                                                   textFormat.FontSize);

            float newW = textLayout.Metrics.Width;
            float newH = textLayout.Metrics.Height;

            SharpDX.Vector2 TextPlotPoint = new System.Windows.Point(pointX - newW, pointY - textLayout.Metrics.Height / 2 - 1).ToVector2();

            SharpDX.RectangleF PLBoundRect = new SharpDX.RectangleF((float)pointX - newW - 4, (float)pointY - textLayout.Metrics.Height / 2 - 1, newW + 6, newH + 2);

            SharpDX.Direct2D1.RoundedRectangle PLRoundedRect = new SharpDX.Direct2D1.RoundedRectangle();

            PLRoundedRect.RadiusX = newW / 4;
            PLRoundedRect.RadiusY = newH / 4;
            PLRoundedRect.Rect    = PLBoundRect;

            RenderTarget.FillRoundedRectangle(PLRoundedRect, areaBrush.DxBrush);

            RenderTarget.DrawTextLayout(TextPlotPoint, textLayout, brush.DxBrush, SharpDX.Direct2D1.DrawTextOptions.NoSnap);

            textLayout.Dispose();
            textLayout = null;
            textFormat.Dispose();
            textFormat = null;
        }
예제 #2
0
        private void DrawString(string text, SimpleFont font, string brushName, double pointX, double pointY, string areaBrushName)
        {
            SharpDX.DirectWrite.TextFormat textFormat = font.ToDirectWriteTextFormat();
            SharpDX.Vector2 TextPlotPoint             = new System.Windows.Point(pointX, pointY).ToVector2();
            SharpDX.DirectWrite.TextLayout textLayout =
                new SharpDX.DirectWrite.TextLayout(NinjaTrader.Core.Globals.DirectWriteFactory,
                                                   text, textFormat, ChartPanel.X + ChartPanel.W,
                                                   textFormat.FontSize);

            float newW = textLayout.Metrics.Width;
            float newH = textLayout.Metrics.Height;

            SharpDX.RectangleF PLBoundRect = new SharpDX.RectangleF((float)pointX + 2, (float)pointY, newW + 5, newH + 2);
            RenderTarget.FillRectangle(PLBoundRect, dxmBrushes[areaBrushName].DxBrush);

            RenderTarget.DrawTextLayout(TextPlotPoint, textLayout, dxmBrushes[brushName].DxBrush, SharpDX.Direct2D1.DrawTextOptions.NoSnap);
            textLayout.Dispose();
            textFormat.Dispose();
        }
예제 #3
0
        public override void OnRender(ChartControl chartControl, ChartScale chartScale)
        {
            if (firstTime && DrawingState == DrawingState.Normal)
            {
                firstTime = false;
                Cbi.License.Log("Path");
            }

            RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive;
            Stroke outlineStroke = OutlineStroke;

            outlineStroke.RenderTarget = RenderTarget;
            ChartPanel chartPanel      = chartControl.ChartPanels[PanelIndex];
            double     strokePixAdjust = outlineStroke.Width % 2 == 0 ? 0.5d : 0d;
            Vector     pixelAdjustVec  = new Vector(strokePixAdjust, strokePixAdjust);

            SharpDX.Direct2D1.PathGeometry polyGeo  = CreatePathGeometry(chartControl, chartPanel, chartScale, strokePixAdjust);
            SharpDX.Direct2D1.Brush        tmpBrush = IsInHitTest ? chartControl.SelectionBrush : outlineStroke.BrushDX;

            RenderTarget.DrawGeometry(polyGeo, tmpBrush, outlineStroke.Width, outlineStroke.StrokeStyle);
            polyGeo.Dispose();

            if (PathBegin == PathToolCapMode.Arrow || PathEnd == PathToolCapMode.Arrow)
            {
                Point[] points = GetPathAnchorPoints(chartControl, chartScale);

                if (points.Length > 1)
                {
                    if (arrowPathGeometry == null)
                    {
                        arrowPathGeometry = new SharpDX.Direct2D1.PathGeometry(Core.Globals.D2DFactory);
                        SharpDX.Direct2D1.GeometrySink geometrySink = arrowPathGeometry.Open();
                        float           arrowWidth = 6f;
                        SharpDX.Vector2 top        = new SharpDX.Vector2(0, outlineStroke.Width * 0.5f);

                        geometrySink.BeginFigure(top, SharpDX.Direct2D1.FigureBegin.Filled);
                        geometrySink.AddLine(new SharpDX.Vector2(arrowWidth, -arrowWidth));
                        geometrySink.AddLine(new SharpDX.Vector2(-arrowWidth, -arrowWidth));
                        geometrySink.AddLine(top);                        // cap off figure
                        geometrySink.EndFigure(SharpDX.Direct2D1.FigureEnd.Closed);
                        geometrySink.Close();
                    }

                    if (PathBegin == PathToolCapMode.Arrow)
                    {
                        Vector lineVector = points[0] - points[1];

                        lineVector.Normalize();

                        Point             pointAdjusted    = points[0] + pixelAdjustVec;
                        SharpDX.Vector2   pointVec         = pointAdjusted.ToVector2();
                        float             vectorAngle      = -(float)Math.Atan2(lineVector.X, lineVector.Y);
                        Vector            adjustVector     = lineVector * 5;
                        SharpDX.Vector2   arrowPointVec    = new SharpDX.Vector2((float)(pointVec.X + adjustVector.X), (float)(pointVec.Y + adjustVector.Y));
                        SharpDX.Matrix3x2 transformMatrix2 = SharpDX.Matrix3x2.Rotation(vectorAngle, SharpDX.Vector2.Zero) * SharpDX.Matrix3x2.Scaling((float)Math.Max(1.0f, outlineStroke.Width * .45) + 0.25f) * SharpDX.Matrix3x2.Translation(arrowPointVec);
                        RenderTarget.Transform = transformMatrix2;

                        RenderTarget.FillGeometry(arrowPathGeometry, tmpBrush);
                        RenderTarget.Transform = SharpDX.Matrix3x2.Identity;
                    }

                    if (PathEnd == PathToolCapMode.Arrow)
                    {
                        Vector lineVector = points[points.Length - 1] - points[points.Length - 2];

                        lineVector.Normalize();

                        Point             pointAdjusted    = points[points.Length - 1] + pixelAdjustVec;
                        SharpDX.Vector2   pointVec         = pointAdjusted.ToVector2();
                        float             vectorAngle      = -(float)Math.Atan2(lineVector.X, lineVector.Y);
                        Vector            adjustVector     = lineVector * 5;
                        SharpDX.Vector2   arrowPointVec    = new SharpDX.Vector2((float)(pointVec.X + adjustVector.X), (float)(pointVec.Y + adjustVector.Y));
                        SharpDX.Matrix3x2 transformMatrix2 = SharpDX.Matrix3x2.Rotation(vectorAngle, SharpDX.Vector2.Zero) * SharpDX.Matrix3x2.Scaling((float)Math.Max(1.0f, outlineStroke.Width * .45) + 0.25f) * SharpDX.Matrix3x2.Translation(arrowPointVec);
                        RenderTarget.Transform = transformMatrix2;

                        RenderTarget.FillGeometry(arrowPathGeometry, tmpBrush);

                        RenderTarget.Transform = SharpDX.Matrix3x2.Identity;
                    }
                }
            }

            if (ShowCount)
            {
                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;

                for (int i = 1; i < ChartAnchors.Count; i++)
                {
                    Point p  = ChartAnchors[i - 1].GetPoint(chartControl, chartPanel, chartScale);
                    Point p1 = ChartAnchors[i].GetPoint(chartControl, chartPanel, chartScale);

                    if (i + 1 < ChartAnchors.Count)
                    {
                        Point  p2 = ChartAnchors[i + 1].GetPoint(chartControl, chartPanel, chartScale);
                        Vector v1 = p - p1;

                        v1.Normalize();

                        Vector v2 = p2 - p1;

                        v2.Normalize();

                        Vector vector = v1 + v2;

                        vector.Normalize();

                        SharpDX.DirectWrite.TextLayout textLayout = new SharpDX.DirectWrite.TextLayout(Core.Globals.DirectWriteFactory, i.ToString(), textFormat, 250, textFormat.FontSize);
                        Point textPoint = p1 - vector * textFormat.FontSize;
                        textPoint.X -= textLayout.Metrics.Width / 2f;
                        textPoint.Y -= textLayout.Metrics.Height / 2f;

                        RenderTarget.DrawTextLayout((textPoint + pixelAdjustVec).ToVector2(), textLayout, outlineStroke.BrushDX, SharpDX.Direct2D1.DrawTextOptions.NoSnap);
                        textLayout.Dispose();
                    }
                    else
                    {
                        SharpDX.DirectWrite.TextLayout textLayout = new SharpDX.DirectWrite.TextLayout(Core.Globals.DirectWriteFactory, i.ToString(), textFormat, 250, textFormat.FontSize);
                        Vector vector = (p - p1);

                        vector.Normalize();

                        Point textPoint = p1 - vector * textFormat.FontSize;
                        textPoint.X -= textLayout.Metrics.Width / 2f;
                        textPoint.Y -= textLayout.Metrics.Height / 2f;

                        RenderTarget.DrawTextLayout((textPoint + pixelAdjustVec).ToVector2(), textLayout, outlineStroke.BrushDX, SharpDX.Direct2D1.DrawTextOptions.NoSnap);
                        textLayout.Dispose();
                    }
                }

                textFormat.Dispose();
            }
        }
예제 #4
0
        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);
        }
예제 #5
0
        public override void OnRender(ChartControl chartControl, ChartScale chartScale)
        {
            RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive;

            ChartPanel panel       = chartControl.ChartPanels[PanelIndex];
            Point      anchorPoint = Anchor.GetPoint(chartControl, panel, chartScale);

            Point lastEndPoint = new Point(0, 0);

            SharpDX.Direct2D1.Brush lastBrush = null;
            foreach (GannAngle gannAngle in GannAngles.Where(ga => ga.IsVisible && ga.Stroke != null).OrderBy(ga => (ga.RatioX / ga.RatioY)))
            {
                gannAngle.Stroke.RenderTarget = RenderTarget;

                double dx               = gannAngle.RatioX * chartControl.Properties.BarDistance;
                double dVal             = gannAngle.RatioY * PointsPerBar;                                //NT7, just multiple directly this is price not pixels //chartScale.GetPixelsForDistance(gannAngle.RatioY * PointsPerBar);
                Vector gannDataVector   = GetGannStepDataVector(dx, dVal);
                Point  extendedEndPoint = CalculateExtendedDataPoint(panel, chartScale, Convert.ToInt32(anchorPoint.X), Anchor.Price, gannDataVector);

                // align to full pixel to avoid unneeded aliasing
                double strokePixAdj   = ((double)(gannAngle.Stroke.Width % 2)).ApproxCompare(0) == 0 ? 0.5d : 0d;
                Vector pixelAdjustVec = new Vector(0, strokePixAdj);

                SharpDX.Direct2D1.Brush tmpBrush = IsInHitTest ? chartControl.SelectionBrush : gannAngle.Stroke.BrushDX;
                RenderTarget.DrawLine((anchorPoint + pixelAdjustVec).ToVector2(), (extendedEndPoint + pixelAdjustVec).ToVector2(), tmpBrush, gannAngle.Stroke.Width, gannAngle.Stroke.StrokeStyle);

                if (lastBrush != null)
                {
                    float oldOpacity = lastBrush.Opacity;
                    lastBrush.Opacity = PriceLevelOpacity / 100f;

                    // create geometry
                    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 (Math.Abs(lastEndPoint.Y - extendedEndPoint.Y) > 0.1 && Math.Abs(lastEndPoint.X - extendedEndPoint.X) > 0.1)
                    {
                        double boundaryX;
                        double boundaryY;

                        if (lastEndPoint.Y <= ChartPanel.Y || lastEndPoint.Y >= ChartPanel.Y + ChartPanel.H)
                        {
                            if (FanDirection == GannFanDirection.UpLeft || FanDirection == GannFanDirection.UpRight)
                            {
                                boundaryY = extendedEndPoint.Y;
                                boundaryX = lastEndPoint.X;
                            }
                            else
                            {
                                boundaryY = lastEndPoint.Y;
                                boundaryX = extendedEndPoint.X;
                            }
                        }
                        else
                        {
                            if (FanDirection == GannFanDirection.UpLeft || FanDirection == GannFanDirection.UpRight)
                            {
                                boundaryY = lastEndPoint.Y;
                                boundaryX = extendedEndPoint.X;
                            }
                            else
                            {
                                boundaryY = extendedEndPoint.Y;
                                boundaryX = lastEndPoint.X;
                            }
                        }
                        sink.AddLine(new SharpDX.Vector2((float)boundaryX, (float)boundaryY));
                    }

                    sink.AddLine(extendedEndPoint.ToVector2());
                    sink.AddLine((anchorPoint + pixelAdjustVec).ToVector2());
                    sink.AddLine((lastEndPoint).ToVector2());
                    sink.EndFigure(SharpDX.Direct2D1.FigureEnd.Closed);
                    sink.Close();
                    RenderTarget.FillGeometry(lineGeometry, lastBrush);
                    lineGeometry.Dispose();

                    lastBrush.Opacity = oldOpacity;
                }
                lastEndPoint = extendedEndPoint + pixelAdjustVec;
                lastBrush    = tmpBrush;
            }

            if (!IsTextDisplayed || IsInHitTest)
            {
                return;
            }

            foreach (GannAngle gannAngle in GannAngles.Where(ga => ga.IsVisible && ga.Stroke != null).OrderBy(ga => (ga.RatioX / ga.RatioY)))
            {
                gannAngle.Stroke.RenderTarget = RenderTarget;
                double dx               = gannAngle.RatioX * chartControl.Properties.BarDistance;
                double dVal             = gannAngle.RatioY * PointsPerBar;                                //NT7, just multiple directly this is price not pixels //chartScale.GetPixelsForDistance(gannAngle.RatioY * PointsPerBar);
                Vector gannDataVector   = GetGannStepDataVector(dx, dVal);
                Point  extendedEndPoint = CalculateExtendedDataPoint(panel, chartScale, Convert.ToInt32(anchorPoint.X), Anchor.Price, gannDataVector);

                if (!IsTextDisplayed || IsInHitTest)
                {
                    continue;
                }

                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, gannAngle.Name, textFormat, 100, textFormat.FontSize);

                // once text is laid out, update used width to calcuated space required
                float fontHeight = textLayout.Metrics.Height;

                Point textEndPoint = new Point(extendedEndPoint.X, extendedEndPoint.Y);

                if (textEndPoint.X > panel.X + panel.W - textLayout.Metrics.Width)
                {
                    textEndPoint.X  = panel.X + panel.W - textLayout.Metrics.Width;
                    textEndPoint.Y += textLayout.Metrics.Width;
                }

                if (gannDataVector.Y > 0)
                {
                    if (textEndPoint.Y < panel.Y + (fontHeight * 0.5))
                    {
                        textEndPoint.Y = panel.Y + (fontHeight * 0.5);
                    }
                }
                else
                {
                    if (textEndPoint.Y > panel.Y + panel.H - (fontHeight * 1.5))
                    {
                        textEndPoint.Y = panel.Y + panel.H - (fontHeight * 1.5);
                    }
                }

                float?marginResource = Application.Current.FindResource("FontModalTitleMargin") as float?;
                float margin         = 2f + (marginResource.HasValue ? marginResource.Value : 3f);
                // Allow for changes in X position based on whether text is aligned to left or right edge of screen
                float marginX = FanDirection == GannFanDirection.DownLeft || FanDirection == GannFanDirection.UpLeft ? margin : -2 * margin;

                SharpDX.Vector2   endVec          = new SharpDX.Vector2((float)textEndPoint.X, (float)textEndPoint.Y);
                SharpDX.Matrix3x2 transformMatrix = SharpDX.Matrix3x2.Translation(endVec);

                RenderTarget.Transform = transformMatrix;

                RenderTarget.DrawTextLayout(new SharpDX.Vector2(marginX + margin, margin), textLayout, gannAngle.Stroke.BrushDX, SharpDX.Direct2D1.DrawTextOptions.NoSnap);

                RenderTarget.Transform = SharpDX.Matrix3x2.Identity;
                textFormat.Dispose();
                textLayout.Dispose();
            }
        }
예제 #6
0
        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;
        }