//---------------------------------------------------------------------------------------------------------------------------------------
        protected override void OnRender(DrawingContext drawingContext)
        {
            if (CandlesMaxVolume == long.MinValue)
            {
                return;
            }

            Pen    pen                       = new Pen(Brushes.Black, 1);
            double textHeight                = (new FormattedText("123", CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, new Typeface("Verdana"), PriceTickFontSize, Brushes.Black, VisualTreeHelper.GetDpi(this).PixelsPerDip)).Height;
            double halfTextHeight            = textHeight / 2.0;
            double volumeHistogramPanelWidth = ActualWidth - PriceAxisWidth;
            double tick_text_X               = volumeHistogramPanelWidth + TICK_LINE_WIDTH + TICK_LEFT_MARGIN;
            double tick_line_endX            = volumeHistogramPanelWidth + TICK_LINE_WIDTH;

            double chartHeight = ActualHeight - ChartBottomMargin - ChartTopMargin;

            if (chartHeight <= 0)
            {
                return;
            }
            long stepInVolumeLots          = (long)(CandlesMaxVolume * ((textHeight + GapBetweenTickLabels) / chartHeight)) + 1;
            long stepInVolumeLots_maxDigit = MyWpfMath.MaxDigit(stepInVolumeLots);

            stepInVolumeLots = (stepInVolumeLots % stepInVolumeLots_maxDigit) == 0 ? stepInVolumeLots : (stepInVolumeLots / stepInVolumeLots_maxDigit + 1) * stepInVolumeLots_maxDigit;
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            double chartHeight_candlesLHRange_Ratio = chartHeight / CandlesMaxVolume;

            void DrawPriceTick(long volume)
            {
                FormattedText priceTickFormattedText = new FormattedText(volume.ToString(), CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, new Typeface("Verdana"), PriceTickFontSize, Brushes.Black, VisualTreeHelper.GetDpi(this).PixelsPerDip);
                double        y = ChartTopMargin + (CandlesMaxVolume - volume) * chartHeight_candlesLHRange_Ratio;

                drawingContext.DrawText(priceTickFormattedText, new Point(tick_text_X, y - halfTextHeight));
                drawingContext.DrawLine(pen, new Point(volumeHistogramPanelWidth, y), new Point(tick_line_endX, y));

                if (IsGridlinesEnabled && GridlinesPen != null)
                {
                    drawingContext.DrawLine(GridlinesPen, new Point(0, y), new Point(volumeHistogramPanelWidth, y));
                }
            }

            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            long theMostRoundVolume = MyWpfMath.MaxDigit(CandlesMaxVolume);

            DrawPriceTick(theMostRoundVolume);

            long maxVolumeThreshold = (long)(CandlesMaxVolume + (ChartTopMargin - halfTextHeight) / chartHeight_candlesLHRange_Ratio);
            long minVolumeThreshold = (long)(CandlesMaxVolume + (ChartTopMargin - ActualHeight + halfTextHeight) / chartHeight_candlesLHRange_Ratio);

            int  step_i    = 1;
            long next_tick = theMostRoundVolume + step_i * stepInVolumeLots;

            while (next_tick < maxVolumeThreshold)
            {
                DrawPriceTick(next_tick);
                step_i++;
                next_tick = theMostRoundVolume + step_i * stepInVolumeLots;
            }

            step_i    = 1;
            next_tick = theMostRoundVolume - step_i * stepInVolumeLots;
            while (next_tick > minVolumeThreshold)
            {
                DrawPriceTick(next_tick);
                step_i++;
                next_tick = theMostRoundVolume - step_i * stepInVolumeLots;
            }
        }
Example #2
0
        //---------------------------------------------------------------------------------------------------------------------------------------
        protected override void OnRender(DrawingContext drawingContext)
        {
            Pen    pen              = new Pen(Brushes.Black, 1);
            double textHeight       = (new FormattedText("123", CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, new Typeface("Verdana"), PriceTickFontSize, Brushes.Black, VisualTreeHelper.GetDpi(this).PixelsPerDip)).Height;
            double halfTextHeight   = textHeight / 2.0;
            double candlePanelWidth = ActualWidth - PriceAxisWidth;
            double tick_text_X      = candlePanelWidth + TICK_LINE_WIDTH + TICK_LEFT_MARGIN;
            double tick_line_endX   = candlePanelWidth + TICK_LINE_WIDTH;

            double chartHeight           = ActualHeight - ChartBottomMargin - ChartTopMargin;
            double stepInRubles          = (CandlesLH.Y - CandlesLH.X) / chartHeight * (textHeight + GapBetweenTickLabels);
            double stepInRubles_maxDigit = MyWpfMath.MaxDigit(stepInRubles);

            stepInRubles = Math.Ceiling(stepInRubles / stepInRubles_maxDigit) * stepInRubles_maxDigit;
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            double chartHeight_candlesLHRange_Ratio = chartHeight / (CandlesLH.Y - CandlesLH.X);

            void DrawPriceTick(double price)
            {
                FormattedText priceTickFormattedText = new FormattedText(price.ToString(), CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, new Typeface("Verdana"), PriceTickFontSize, Brushes.Black, VisualTreeHelper.GetDpi(this).PixelsPerDip);
                double        y = ChartTopMargin + (CandlesLH.Y - price) * chartHeight_candlesLHRange_Ratio;

                drawingContext.DrawText(priceTickFormattedText, new Point(tick_text_X, y - halfTextHeight));
                drawingContext.DrawLine(pen, new Point(candlePanelWidth, y), new Point(tick_line_endX, y));

                if (IsGridlinesEnabled && GridlinesPen != null)
                {
                    drawingContext.DrawLine(GridlinesPen, new Point(0, y), new Point(candlePanelWidth, y));
                }
            }

            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            double theMostRoundPrice = MyWpfMath.TheMostRoundValueInsideRange(CandlesLH.X, CandlesLH.Y);

            DrawPriceTick(theMostRoundPrice);

            double maxPriceThreshold = CandlesLH.Y + (ChartTopMargin - halfTextHeight) / chartHeight_candlesLHRange_Ratio;
            double minPriceThreshold = CandlesLH.Y + (ChartTopMargin - ActualHeight + halfTextHeight) / chartHeight_candlesLHRange_Ratio;

            int    step_i    = 1;
            double next_tick = theMostRoundPrice + step_i * stepInRubles;

            while (next_tick < maxPriceThreshold)
            {
                DrawPriceTick(next_tick);
                step_i++;
                next_tick = theMostRoundPrice + step_i * stepInRubles;
            }

            step_i    = 1;
            next_tick = theMostRoundPrice - step_i * stepInRubles;
            while (next_tick > minPriceThreshold)
            {
                DrawPriceTick(next_tick);
                step_i++;
                next_tick = theMostRoundPrice - step_i * stepInRubles;
            }

            // Горизонтальные линии на всю ширину разделяющая и окаймляющая панели времени и даты:
            //drawingContext.DrawLine(pen, new Point(0, 0), new Point(RenderSize.Width, 0));
            //drawingContext.DrawLine(pen, new Point(0, halfRenderSizeHeight), new Point(RenderSize.Width, halfRenderSizeHeight));
            //drawingContext.DrawLine(pen, new Point(0, RenderSize.Height), new Point(RenderSize.Width, RenderSize.Height));
        }
        //---------------------------------------------------------------------------------------------------------------------------------------
        protected override void OnRender(DrawingContext drawingContext)
        {
            double textHeight      = (new FormattedText("123", Culture, FlowDirection.LeftToRight, currentTypeFace, TickLabelFontSize, Brushes.Black, VisualTreeHelper.GetDpi(this).PixelsPerDip)).Height;
            double halfTextHeight  = textHeight / 2.0;
            double chartPanelWidth = ActualWidth - PriceAxisWidth;
            double tickLabelX      = chartPanelWidth + TICK_LINE_WIDTH + TICK_HORIZ_MARGIN;
            double tickLineEndX    = chartPanelWidth + TICK_LINE_WIDTH;
            double chartHeight     = ActualHeight - ChartBottomMargin - ChartTopMargin;

            double stepInRubles        = (VisibleCandlesExtremums.PriceHigh - VisibleCandlesExtremums.PriceLow) / chartHeight * (textHeight + GapBetweenTickLabels);
            double stepInRubles_HPlace = MyWpfMath.HighestDecimalPlace(stepInRubles, out int stepInRubles_HPow);

            stepInRubles = Math.Ceiling(stepInRubles / stepInRubles_HPlace) * stepInRubles_HPlace;
            MyWpfMath.HighestDecimalPlace(stepInRubles, out int stepInRublesHighestDecimalPow);
            string priceTickLabelNumberFormat    = (stepInRubles_HPow >= 0) ? "N0" : $"N{-stepInRubles_HPow}";
            string currentPriceLabelNumberFormat = $"N{MaxNumberOfFractionalDigitsInPrice}";

            double chartHeight_candlesLHRange_Ratio = chartHeight / (VisibleCandlesExtremums.PriceHigh - VisibleCandlesExtremums.PriceLow);

            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            string decimalSeparator = Culture.NumberFormat.NumberDecimalSeparator;

            char[] decimalSeparatorArray = decimalSeparator.ToCharArray();

            void DrawPriceTickLabel(double price, int priceStepHighestDecimalPow)
            {
                string        s = MyNumberFormatting.PriceToString(price, priceTickLabelNumberFormat, Culture, decimalSeparator, decimalSeparatorArray);
                FormattedText priceTickFormattedText = new FormattedText(s, Culture, FlowDirection.LeftToRight, currentTypeFace, TickLabelFontSize, TickColor, VisualTreeHelper.GetDpi(this).PixelsPerDip);
                double        y = ChartTopMargin + (VisibleCandlesExtremums.PriceHigh - price) * chartHeight_candlesLHRange_Ratio;

                drawingContext.DrawText(priceTickFormattedText, new Point(tickLabelX, y - halfTextHeight));
                drawingContext.DrawLine(tickPen, new Point(chartPanelWidth, y), new Point(tickLineEndX, y));

                if (IsGridlinesEnabled && GridlinesPen != null)
                {
                    drawingContext.DrawLine(GridlinesPen, new Point(0, y), new Point(chartPanelWidth, y));
                }
            }

            void DrawCurrentPriceLabel()
            {
                string        currentPriceString = MyNumberFormatting.PriceToString(CurrentPrice, currentPriceLabelNumberFormat, Culture, decimalSeparator, decimalSeparatorArray);
                FormattedText formattedText      = new FormattedText(currentPriceString, Culture, FlowDirection.LeftToRight, currentTypeFace, TickLabelFontSize, CurrentPriceLabelForeground, VisualTreeHelper.GetDpi(this).PixelsPerDip);
                double        formattedTextWidth = formattedText.Width;
                double        y = ChartTopMargin + (VisibleCandlesExtremums.PriceHigh - CurrentPrice) * chartHeight_candlesLHRange_Ratio;

                drawingContext.DrawRectangle(CurrentPriceLabelBackground, currentPriceLabelForegroundPen,
                                             new Rect(chartPanelWidth, y - halfTextHeight, formattedTextWidth + TICK_LINE_WIDTH + 2 * TICK_HORIZ_MARGIN, textHeight + 1.0));
                drawingContext.DrawLine(currentPriceLabelForegroundPen, new Point(chartPanelWidth, y), new Point(tickLineEndX, y));
                drawingContext.DrawText(formattedText, new Point(tickLabelX, y - halfTextHeight));
            }

            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            double theMostRoundPrice = MyWpfMath.TheMostRoundValueInsideRange(VisibleCandlesExtremums.PriceLow, VisibleCandlesExtremums.PriceHigh);

            DrawPriceTickLabel(theMostRoundPrice, stepInRublesHighestDecimalPow);

            double maxPriceThreshold = VisibleCandlesExtremums.PriceHigh + (ChartTopMargin - halfTextHeight) / chartHeight_candlesLHRange_Ratio;
            double minPriceThreshold = VisibleCandlesExtremums.PriceHigh + (ChartTopMargin - ActualHeight + halfTextHeight) / chartHeight_candlesLHRange_Ratio;

            int    step_i = 1;
            double next_tick;

            while ((next_tick = theMostRoundPrice + step_i * stepInRubles) < maxPriceThreshold)
            {
                DrawPriceTickLabel(next_tick, stepInRublesHighestDecimalPow);
                step_i++;
            }

            step_i = 1;
            while ((next_tick = theMostRoundPrice - step_i * stepInRubles) > minPriceThreshold)
            {
                DrawPriceTickLabel(next_tick, stepInRublesHighestDecimalPow);
                step_i++;
            }

            if (IsCurrentPriceLabelVisible && CurrentPrice >= VisibleCandlesExtremums.PriceLow && CurrentPrice <= VisibleCandlesExtremums.PriceHigh)
            {
                DrawCurrentPriceLabel();
            }

            // Горизонтальные линии на всю ширину разделяющая и окаймляющая панели времени и даты:
            //drawingContext.DrawLine(pen, new Point(0, 0), new Point(RenderSize.Width, 0));
            //drawingContext.DrawLine(pen, new Point(0, halfRenderSizeHeight), new Point(RenderSize.Width, halfRenderSizeHeight));
            //drawingContext.DrawLine(pen, new Point(0, RenderSize.Height), new Point(RenderSize.Width, RenderSize.Height));
        }
        //---------------------------------------------------------------------------------------------------------------------------------------
        protected override void OnRender(DrawingContext drawingContext)
        {
            //if (VisibleCandlesExtremums.VolumeHigh == long.MinValue) return;

            double textHeight      = (new FormattedText("1,23", Culture, FlowDirection.LeftToRight, currentTypeFace, TickLabelFontSize, Brushes.Black, VisualTreeHelper.GetDpi(this).PixelsPerDip)).Height;
            double halfTextHeight  = textHeight / 2.0;
            double chartPanelWidth = ActualWidth - PriceAxisWidth;
            double tickLabelX      = chartPanelWidth + TICK_LINE_WIDTH + TICK_LEFT_MARGIN;
            double tickLineEndX    = chartPanelWidth + TICK_LINE_WIDTH;
            double chartHeight     = ActualHeight - ChartBottomMargin - ChartTopMargin;

            if (chartHeight <= 0)
            {
                return;
            }

            double stepInVolumeUnits        = VisibleCandlesExtremums.VolumeHigh * ((textHeight + GapBetweenTickLabels) / chartHeight);
            double stepInVolumeUnits_HPlace = MyWpfMath.HighestDecimalPlace(stepInVolumeUnits, out _);

            stepInVolumeUnits = Math.Ceiling(stepInVolumeUnits / stepInVolumeUnits_HPlace) * stepInVolumeUnits_HPlace;
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            double chartHeight_candlesLHRange_Ratio = chartHeight / VisibleCandlesExtremums.VolumeHigh;

            string decimalSeparator = Culture.NumberFormat.NumberDecimalSeparator;

            char[] decimalSeparatorArray = decimalSeparator.ToCharArray();

            void DrawVolumeTick(double volume)
            {
                string        s = MyNumberFormatting.VolumeToLimitedLengthString(volume, Culture, decimalSeparator, decimalSeparatorArray);
                FormattedText priceTickFormattedText = new FormattedText(s, Culture, FlowDirection.LeftToRight, currentTypeFace, TickLabelFontSize, TickColor, VisualTreeHelper.GetDpi(this).PixelsPerDip);
                double        y = ChartTopMargin + (VisibleCandlesExtremums.VolumeHigh - volume) * chartHeight_candlesLHRange_Ratio;

                drawingContext.DrawText(priceTickFormattedText, new Point(tickLabelX, y - halfTextHeight));
                drawingContext.DrawLine(tickPen, new Point(chartPanelWidth, y), new Point(tickLineEndX, y));

                if (IsGridlinesEnabled && GridlinesPen != null)
                {
                    drawingContext.DrawLine(GridlinesPen, new Point(0, y), new Point(chartPanelWidth, y));
                }
            }

            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            double theMostRoundVolume = MyWpfMath.HighestDecimalPlace(VisibleCandlesExtremums.VolumeHigh, out _);

            DrawVolumeTick(theMostRoundVolume);

            double maxVolumeThreshold = (VisibleCandlesExtremums.VolumeHigh + (ChartTopMargin - halfTextHeight) / chartHeight_candlesLHRange_Ratio);
            double minVolumeThreshold = (VisibleCandlesExtremums.VolumeHigh + (ChartTopMargin - ActualHeight + halfTextHeight) / chartHeight_candlesLHRange_Ratio);

            int    step_i = 1;
            double next_tick;

            while ((next_tick = theMostRoundVolume + step_i * stepInVolumeUnits) < maxVolumeThreshold)
            {
                DrawVolumeTick(next_tick);
                step_i++;
            }

            step_i = 1;
            while ((next_tick = theMostRoundVolume - step_i * stepInVolumeUnits) > minVolumeThreshold)
            {
                DrawVolumeTick(next_tick);
                step_i++;
            }
        }