Exemple #1
0
        /// <summary>
        /// Paints the annotation object on the specified graphics.
        /// </summary>
        /// <param name="graphics">
        /// A <see cref="ChartGraphics"/>
        /// </param>
        /// <param name="chart">
        /// Reference to the <see cref="ChartService"/> control that owns the annotation.
        /// </param>
        override internal void Paint(ChartService chart, ChartGraphics graphics)
        {
            // Get annotation position in relative coordinates
            GetRelativePosition(out SKPoint firstPoint, out SKSize size, out _);
            SKPoint secondPoint = new(firstPoint.X + size.Width, firstPoint.Y + size.Height);

            // Create selection rectangle
            SKRect selectionRect = new(firstPoint.X, firstPoint.Y, secondPoint.X, secondPoint.Y);

            // Get text position
            SKRect rectanglePosition = new(selectionRect.Left, selectionRect.Top, selectionRect.Right, selectionRect.Bottom);

            if (rectanglePosition.Width < 0 || rectanglePosition.Height < 0)
            {
                rectanglePosition = rectanglePosition.Standardized;
            }

            // Check if position is valid
            if (float.IsNaN(rectanglePosition.Left) ||
                float.IsNaN(rectanglePosition.Top) ||
                float.IsNaN(rectanglePosition.Right) ||
                float.IsNaN(rectanglePosition.Bottom))
            {
                return;
            }

            if (Common.ProcessModePaint)
            {
                // Do not draw border if size is less that 10 pixels
                SKRect absRectanglePosition = graphics.GetAbsoluteRectangle(rectanglePosition);
                if (absRectanglePosition.Width > 30f &&
                    absRectanglePosition.Height > 30f)
                {
                    // Draw rectangle
                    graphics.Draw3DBorderRel(
                        _borderSkin,
                        rectanglePosition,
                        BackColor,
                        BackHatchStyle,
                        String.Empty,
                        ChartImageWrapMode.Scaled,
                        SKColor.Empty,
                        ChartImageAlignmentStyle.Center,
                        BackGradientStyle,
                        BackSecondaryColor,
                        LineColor,
                        LineWidth,
                        LineDashStyle);
                }
            }

            // Call base class to paint text, selection handles and process hot regions
            base.Paint(chart, graphics);
        }
        /// <summary>
        /// Get arrow path for the specified annotation position
        /// </summary>
        /// <param name="graphics"></param>
        /// <param name="position"></param>
        /// <returns></returns>
        private SKPath GetArrowPath(
            ChartGraphics graphics,
            SKRect position)
        {
            // Get absolute position
            SKRect  positionAbs = graphics.GetAbsoluteRectangle(position);
            SKPoint firstPoint  = positionAbs.Location;
            SKPoint secondPoint = new(positionAbs.Right, positionAbs.Bottom);

            // Calculate arrow length
            float deltaX      = secondPoint.X - firstPoint.X;
            float deltaY      = secondPoint.Y - firstPoint.Y;
            float arrowLength = (float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY);

            // Create unrotated graphics path for the arrow started at the annotation location
            // and going to the right for the length of the rotated arrow.
            SKPath path         = new();
            float  pointerRatio = 2.1f;

            SKPoint[] points;
            if (ArrowStyle == ArrowStyle.Simple)
            {
                points = new SKPoint[] {
                    firstPoint,
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize * pointerRatio),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize),
                    new SKPoint(firstPoint.X + arrowLength, firstPoint.Y - ArrowSize),
                    new SKPoint(firstPoint.X + arrowLength, firstPoint.Y + ArrowSize),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize * pointerRatio)
                };
            }
            else if (ArrowStyle == ArrowStyle.DoubleArrow)
            {
                points = new SKPoint[] {
                    firstPoint,
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize * pointerRatio),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize),
                    new SKPoint(firstPoint.X + arrowLength - ArrowSize * pointerRatio, firstPoint.Y - ArrowSize),
                    new SKPoint(firstPoint.X + arrowLength - ArrowSize * pointerRatio, firstPoint.Y - ArrowSize * pointerRatio),
                    new SKPoint(firstPoint.X + arrowLength, firstPoint.Y),
                    new SKPoint(firstPoint.X + arrowLength - ArrowSize * pointerRatio, firstPoint.Y + ArrowSize * pointerRatio),
                    new SKPoint(firstPoint.X + arrowLength - ArrowSize * pointerRatio, firstPoint.Y + ArrowSize),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize * pointerRatio)
                };
            }
            else if (ArrowStyle == ArrowStyle.Tailed)
            {
                float tailRatio = 2.1f;
                points = new SKPoint[] {
                    firstPoint,
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize * pointerRatio),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize),
                    new SKPoint(firstPoint.X + arrowLength, firstPoint.Y - ArrowSize * tailRatio),
                    new SKPoint(firstPoint.X + arrowLength - ArrowSize * tailRatio, firstPoint.Y),
                    new SKPoint(firstPoint.X + arrowLength, firstPoint.Y + ArrowSize * tailRatio),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize * pointerRatio)
                };
            }
            else
            {
                throw (new InvalidOperationException(SR.ExceptionAnnotationArrowStyleUnknown));
            }

            path.AddLines(points);
            path.Close();

            // Calculate arrow angle
            float angle = (float)(Math.Atan(deltaY / deltaX) * 180f / Math.PI);

            if (deltaX < 0)
            {
                angle += 180f;
            }

            // Rotate arrow path around the first point
            SKMatrix matrix = SKMatrix.CreateRotationDegrees(angle, firstPoint.X, firstPoint.Y);

            path.Transform(matrix);

            return(path);
        }
        /// <summary>
        /// Draws 3D button in the scroll bar
        /// </summary>
        /// <param name="graph">Chart graphics.</param>
        /// <param name="buttonRect">Button position.</param>
        /// <param name="pressedState">Indicates that button is pressed.</param>
        /// <param name="buttonType">Button type to draw.</param>
        internal void PaintScrollBar3DButton(
            ChartGraphics graph,
            SKRect buttonRect,
            bool pressedState,
            ScrollBarButtonType buttonType)
        {
            // Page Up/Down buttons do not require drawing
            if (buttonType == ScrollBarButtonType.LargeIncrement || buttonType == ScrollBarButtonType.LargeDecrement)
            {
                return;
            }

            // Get 3 levels of colors for button drawing
            var darkerColor  = ChartGraphics.GetGradientColor(_buttonCurrentColor, SKColors.Black, 0.5);
            var darkestColor = ChartGraphics.GetGradientColor(_buttonCurrentColor, SKColors.Black, 0.8);
            var lighterColor = ChartGraphics.GetGradientColor(_buttonCurrentColor, SKColors.White, 0.5);

            // Fill button rectangle background
            graph.FillRectangleRel(
                buttonRect,
                _buttonCurrentColor,
                ChartHatchStyle.None,
                "",
                ChartImageWrapMode.Tile,
                SKColor.Empty,
                ChartImageAlignmentStyle.Center,
                GradientStyle.None,
                SKColor.Empty,
                darkerColor,
                (pressedState) ? 1 : 0,
                ChartDashStyle.Solid,
                SKColor.Empty,
                0,
                PenAlignment.Outset);

            // Check if 2 or 1 pixel border will be drawn (if size too small)
            bool singlePixelBorder = Size <= 12;

            // Draw 3D effect around the button when not pressed
            if (!pressedState)
            {
                // Get relative size of 1 pixel
                SKSize pixelRelativeSize = new(1, 1);
                pixelRelativeSize = graph.GetRelativeSize(pixelRelativeSize);

                // Draw top/left border with button color
                graph.DrawLineRel(
                    (singlePixelBorder) ? lighterColor : _buttonCurrentColor, 1, ChartDashStyle.Solid,
                    new SKPoint(buttonRect.Left, buttonRect.Bottom),
                    new SKPoint(buttonRect.Left, buttonRect.Top));
                graph.DrawLineRel(
                    (singlePixelBorder) ? lighterColor : _buttonCurrentColor, 1, ChartDashStyle.Solid,
                    new SKPoint(buttonRect.Left, buttonRect.Top),
                    new SKPoint(buttonRect.Right, buttonRect.Top));

                // Draw right/bottom border with the darkest color
                graph.DrawLineRel(
                    (singlePixelBorder) ? darkerColor : darkestColor, 1, ChartDashStyle.Solid,
                    new SKPoint(buttonRect.Right, buttonRect.Bottom),
                    new SKPoint(buttonRect.Right, buttonRect.Top));
                graph.DrawLineRel(
                    (singlePixelBorder) ? darkerColor : darkestColor, 1, ChartDashStyle.Solid,
                    new SKPoint(buttonRect.Left, buttonRect.Bottom),
                    new SKPoint(buttonRect.Right, buttonRect.Bottom));

                if (!singlePixelBorder)
                {
                    // Draw right/bottom border (offset 1) with the dark color
                    graph.DrawLineRel(
                        darkerColor, 1, ChartDashStyle.Solid,
                        new SKPoint(buttonRect.Right - pixelRelativeSize.Width, buttonRect.Bottom - pixelRelativeSize.Height),
                        new SKPoint(buttonRect.Right - pixelRelativeSize.Width, buttonRect.Top + pixelRelativeSize.Height));
                    graph.DrawLineRel(
                        darkerColor, 1, ChartDashStyle.Solid,
                        new SKPoint(buttonRect.Left + pixelRelativeSize.Width, buttonRect.Bottom - pixelRelativeSize.Height),
                        new SKPoint(buttonRect.Right - pixelRelativeSize.Width, buttonRect.Bottom - pixelRelativeSize.Height));

                    // Draw top/left border (offset 1) with lighter color
                    graph.DrawLineRel(
                        lighterColor, 1, ChartDashStyle.Solid,
                        new SKPoint(buttonRect.Left + pixelRelativeSize.Width, buttonRect.Bottom - pixelRelativeSize.Height),
                        new SKPoint(buttonRect.Left + pixelRelativeSize.Width, buttonRect.Top + pixelRelativeSize.Height));
                    graph.DrawLineRel(
                        lighterColor, 1, ChartDashStyle.Solid,
                        new SKPoint(buttonRect.Left + pixelRelativeSize.Width, buttonRect.Left + pixelRelativeSize.Height),
                        new SKPoint(buttonRect.Right - pixelRelativeSize.Width, buttonRect.Left + pixelRelativeSize.Height));
                }
            }

            // Check axis orientation
            bool verticalAxis = (axis.AxisPosition == AxisPosition.Left ||
                                 axis.AxisPosition == AxisPosition.Right);

            // Set graphics transformation for button pressed mode
            float pressedShifting = (singlePixelBorder) ? 0.5f : 1f;

            if (pressedState)
            {
                graph.TranslateTransform(pressedShifting, pressedShifting);
            }

            // Draw button image
            SKRect buttonAbsRect = graph.GetAbsoluteRectangle(buttonRect);
            float  imageOffset   = (singlePixelBorder) ? 2 : 3;

            switch (buttonType)
            {
            case (ScrollBarButtonType.SmallDecrement):
            {
                // Calculate triangal points position
                SKPoint[] points = new SKPoint[3];
                if (verticalAxis)
                {
                    points[0].X = buttonAbsRect.Left + imageOffset;
                    points[0].Y = buttonAbsRect.Top + (imageOffset + 1f);
                    points[1].X = buttonAbsRect.Left + buttonAbsRect.Width / 2f;
                    points[1].Y = buttonAbsRect.Bottom - imageOffset;
                    points[2].X = buttonAbsRect.Right - imageOffset;
                    points[2].Y = buttonAbsRect.Top + (imageOffset + 1f);
                }
                else
                {
                    points[0].X = buttonAbsRect.Left + imageOffset;
                    points[0].Y = buttonAbsRect.Top + buttonAbsRect.Height / 2f;
                    points[1].X = buttonAbsRect.Right - (imageOffset + 1f);
                    points[1].Y = buttonAbsRect.Top + imageOffset;
                    points[2].X = buttonAbsRect.Right - (imageOffset + 1f);
                    points[2].Y = buttonAbsRect.Bottom - imageOffset;
                }

                using var brush = new SKPaint { Style = SKPaintStyle.Fill, Color = _lineCurrentColor };

                graph.FillPolygon(brush, points);

                break;
            }

            case (ScrollBarButtonType.SmallIncrement):
            {
                // Calculate triangal points position
                SKPoint[] points = new SKPoint[3];
                if (verticalAxis)
                {
                    points[0].X = buttonAbsRect.Left + imageOffset;
                    points[0].Y = buttonAbsRect.Bottom - (imageOffset + 1f);
                    points[1].X = buttonAbsRect.Left + buttonAbsRect.Width / 2f;
                    points[1].Y = buttonAbsRect.Top + imageOffset;
                    points[2].X = buttonAbsRect.Right - imageOffset;
                    points[2].Y = buttonAbsRect.Bottom - (imageOffset + 1f);
                }
                else
                {
                    points[0].X = buttonAbsRect.Right - imageOffset;
                    points[0].Y = buttonAbsRect.Top + buttonAbsRect.Height / 2f;
                    points[1].X = buttonAbsRect.Left + (imageOffset + 1f);
                    points[1].Y = buttonAbsRect.Top + imageOffset;
                    points[2].X = buttonAbsRect.Left + (imageOffset + 1f);
                    points[2].Y = buttonAbsRect.Bottom - imageOffset;
                }

                using var brush = new SKPaint { Style = SKPaintStyle.Fill, Color = _lineCurrentColor };
                graph.FillPolygon(brush, points);

                break;
            }

            case (ScrollBarButtonType.ZoomReset):
            {
                // Draw circule with a minus sign

                using var pen = new SKPaint { Style = SKPaintStyle.Fill, Color = _lineCurrentColor };

                graph.DrawEllipse(pen, buttonAbsRect.Left + imageOffset - 0.5f, buttonAbsRect.Top + imageOffset - 0.5f, buttonAbsRect.Width - 2f * imageOffset, buttonAbsRect.Height - 2f * imageOffset);
                graph.DrawLine(pen, buttonAbsRect.Left + imageOffset + 1.5f, buttonAbsRect.Top + buttonAbsRect.Height / 2f - 0.5f, buttonAbsRect.Right - imageOffset - 2.5f, buttonAbsRect.Top + buttonAbsRect.Height / 2f - 0.5f);

                break;
            }
            }

            // Reset graphics transformation for button pressed mode
            if (pressedState)
            {
                graph.TranslateTransform(-pressedShifting, -pressedShifting);
            }
        }