Exemplo n.º 1
0
        private static FormattedText GetFormattedText(
            double value,
            Brush textBrush,
            Typeface textTypeface,
            IDoubleToStringConverter valueConverter,
            object valueConverterParameter)
        {
            string text = (valueConverter == null) ?
                          value.ToString(CultureInfo.CurrentCulture.NumberFormat) :
                          valueConverter.Convert(value, valueConverterParameter);
            var formattedText = new FormattedText(
                text,
                CultureInfo.CurrentCulture,
                CultureInfo.CurrentCulture.TextInfo.IsRightToLeft ? FlowDirection.RightToLeft : FlowDirection.LeftToRight,
                textTypeface,
                8,
                textBrush);

            return(formattedText);
        }
Exemplo n.º 2
0
        protected override void OnRender(DrawingContext dc)
        {
            bool   eliminateOverlapping = EliminateOverlapping;
            double controlActualWidth = ActualWidth, controlActualHeight = ActualHeight;

            Contract.Assert(ActualWidth >= 0);
            var    size = new Size(controlActualWidth, controlActualHeight);
            double min = Minimum, max = Maximum;
            double range = max - min;
            double logicalToPhysical       = 1.0;
            double textPointShiftDirection = 0.0d;
            var    startPoint = new Point(0d, 0d);
            var    endPoint   = new Point(0d, 0d);

            // Take Thumb size in to account
            double halfReservedSpace = ReservedSpace * 0.5;

            switch (Placement)
            {
            case TickBarPlacement.Top:
                if (DoubleUtil.GreaterThanOrClose(ReservedSpace, size.Width))
                {
                    return;
                }
                size.Width -= ReservedSpace;
                textPointShiftDirection = -1.0d;
                startPoint        = new Point(halfReservedSpace, size.Height);
                endPoint          = new Point(halfReservedSpace + size.Width, size.Height);
                logicalToPhysical = size.Width / range;
                break;

            case TickBarPlacement.Bottom:
                if (DoubleUtil.GreaterThanOrClose(ReservedSpace, size.Width))
                {
                    return;
                }
                size.Width -= ReservedSpace;
                textPointShiftDirection = 0.0d;
                startPoint        = new Point(halfReservedSpace, 0d);
                endPoint          = new Point(halfReservedSpace + size.Width, 0d);
                logicalToPhysical = size.Width / range;
                break;

            case TickBarPlacement.Left:
                if (DoubleUtil.GreaterThanOrClose(ReservedSpace, size.Height))
                {
                    return;
                }
                size.Height            -= ReservedSpace;
                textPointShiftDirection = 1.0d;
                startPoint        = new Point(size.Width, size.Height + halfReservedSpace);
                endPoint          = new Point(size.Width, halfReservedSpace);
                logicalToPhysical = size.Height / range * -1;
                break;

            case TickBarPlacement.Right:
                if (DoubleUtil.GreaterThanOrClose(ReservedSpace, size.Height))
                {
                    return;
                }
                size.Height            -= ReservedSpace;
                textPointShiftDirection = 0.0d;
                startPoint        = new Point(0d, size.Height + halfReservedSpace);
                endPoint          = new Point(0d, halfReservedSpace);
                logicalToPhysical = size.Height / range * -1;
                break;
            }

            // Invert direciton of the ticks
            bool isDirectionReversed = IsDirectionReversed;

            if (isDirectionReversed)
            {
                logicalToPhysical *= -1;

                // swap startPoint & endPoint
                Point pt = startPoint;
                startPoint = endPoint;
                endPoint   = pt;
            }

            Brush                    textBrush               = Fill;
            var                      pen                     = new Pen(textBrush, 1.0d);
            DoubleCollection         ticks                   = Ticks;
            const double             pointRadius             = 1.0d;
            IDoubleToStringConverter valueConverter          = ValueConverter;
            object                   valueConverterParameter = ValueConverterParameter;
            var                      textTypeface            = new Typeface("Verdana");

            double startSpace = StartLabelSpace, endSpace = EndLabelSpace;

            Contract.Assume(startSpace >= 0.0);
            Contract.Assume(endSpace >= 0.0);

            // Is it Vertical?
            if ((Placement == TickBarPlacement.Left) || (Placement == TickBarPlacement.Right))
            {
                double prevTextEdge = isDirectionReversed ? (0.0 - startSpace) : (controlActualHeight + startSpace);
                double maxTextEdge  = isDirectionReversed ? (controlActualHeight + endSpace) : (0.0 - endSpace);

                // Reduce tick interval if it is more than would be visible on the screen
                double interval = TickFrequency;
                if (interval > 0.0)
                {
                    double minInterval = range / size.Height;
                    if (interval < minInterval)
                    {
                        interval = minInterval;
                    }
                }

                Action <double, double> drawer = (tick, y) =>
                {
                    var formattedText = GetFormattedText(tick, textBrush, textTypeface, valueConverter, valueConverterParameter);
                    var textPoint     = new Point(startPoint.X - formattedText.Width / 2,
                                                  y - (textPointShiftDirection * formattedText.Height));
                    double newTextEdge = y + (isDirectionReversed ? 1 : -1) * formattedText.Width / 2;

                    bool drawThisText = true;
                    if (eliminateOverlapping)
                    {
                        if (isDirectionReversed)
                        {
                            drawThisText = DoubleUtil.GreaterThanOrClose(y - formattedText.Width / 2, prevTextEdge) &&
                                           DoubleUtil.LessThanOrClose(y + formattedText.Width / 2, maxTextEdge);
                        }
                        else
                        {
                            drawThisText = DoubleUtil.LessThanOrClose(y + formattedText.Width / 2, prevTextEdge) &&
                                           DoubleUtil.GreaterThanOrClose(y - formattedText.Width / 2, maxTextEdge);
                        }
                    }

                    if (drawThisText)
                    {
                        var rotateTransform = new RotateTransform(270,
                                                                  textPoint.X + formattedText.Width / 2,
                                                                  textPoint.Y + textPointShiftDirection * formattedText.Height);
                        dc.DrawEllipse(textBrush, pen, new Point(startPoint.X, y), pointRadius, pointRadius);
                        dc.PushTransform(rotateTransform);
                        dc.DrawText(formattedText, textPoint);
                        dc.Pop();
                        prevTextEdge = newTextEdge;
                    }
                };
                // Draw Min tick
                drawer(min, startPoint.Y);

                // Draw ticks using specified Ticks collection
                if ((ticks != null) && (ticks.Count > 0))
                {
                    foreach (double tick in ticks)
                    {
                        if (DoubleUtil.LessThanOrClose(tick, min) || DoubleUtil.GreaterThanOrClose(tick, max))
                        {
                            continue;
                        }

                        double adjustedTick = tick - min;
                        double y            = adjustedTick * logicalToPhysical + startPoint.Y;

                        drawer(tick, y);
                    }
                }
                // Draw ticks using specified TickFrequency
                else if (interval > 0.0)
                {
                    for (double i = interval; i < range; i += interval)
                    {
                        double y = i * logicalToPhysical + startPoint.Y;

                        drawer(i + min, y);
                    }
                }

                // Draw Max tick
                drawer(max, endPoint.Y);
            }
            else  // Placement == Top || Placement == Bottom
            {
                double prevTextEdge = isDirectionReversed ? (controlActualWidth + startSpace) : (0.0 - startSpace);
                double maxTextEdge  = isDirectionReversed ? (0.0 - endSpace) : (controlActualWidth + endSpace);

                // Reduce tick interval if it is more than would be visible on the screen
                double interval = TickFrequency;
                if (interval > 0.0)
                {
                    double minInterval = range / size.Width;
                    if (interval < minInterval)
                    {
                        interval = minInterval;
                    }
                }

                Action <double, double> drawer = (tick, x) =>
                {
                    var formattedText = GetFormattedText(tick, textBrush, textTypeface, valueConverter, valueConverterParameter);
                    var textPoint     = new Point(x - (formattedText.Width / 2),
                                                  startPoint.Y + textPointShiftDirection * formattedText.Height);
                    double newTextEdge = textPoint.X + (isDirectionReversed ? 0.0 : formattedText.Width);

                    bool drawThisText = true;
                    if (eliminateOverlapping)
                    {
                        if (isDirectionReversed)
                        {
                            drawThisText = DoubleUtil.LessThanOrClose(textPoint.X + formattedText.Width, prevTextEdge) &&
                                           DoubleUtil.GreaterThanOrClose(textPoint.X, maxTextEdge);
                        }
                        else
                        {
                            drawThisText = DoubleUtil.GreaterThanOrClose(textPoint.X, prevTextEdge) &&
                                           DoubleUtil.LessThanOrClose(textPoint.X + formattedText.Width, maxTextEdge);
                        }
                    }

                    if (drawThisText)
                    {
                        dc.DrawEllipse(textBrush, pen, new Point(x, startPoint.Y), pointRadius, pointRadius);
                        dc.DrawText(formattedText, textPoint);
                        prevTextEdge = newTextEdge;
                    }
                };
                // Draw Min tick
                drawer(min, startPoint.X);

                // Draw ticks using specified Ticks collection
                if ((ticks != null) && (ticks.Count > 0))
                {
                    foreach (double tick in ticks)
                    {
                        if (DoubleUtil.LessThanOrClose(tick, min) || DoubleUtil.GreaterThanOrClose(tick, max))
                        {
                            continue;
                        }
                        double adjustedTick = tick - min;
                        double x            = adjustedTick * logicalToPhysical + startPoint.X;

                        drawer(tick, x);
                    }
                }
                // Draw ticks using specified TickFrequency
                else if (interval > 0.0)
                {
                    for (double i = interval; i < range; i += interval)
                    {
                        double x = i * logicalToPhysical + startPoint.X;

                        drawer(i + min, x);
                    }
                }

                // Draw Max tick
                drawer(max, endPoint.X);
            }
        }