/// <summary>
        /// Draw chart line using horisontal and vertical lines.
        /// </summary>
        /// <param name="graph">Graphics object.</param>
        /// <param name="common">The Common elements object</param>
        /// <param name="point">Point to draw the line for.</param>
        /// <param name="series">Point series.</param>
        /// <param name="points">Array of points coordinates.</param>
        /// <param name="pointIndex">Index of point to draw.</param>
        /// <param name="tension">Line tension</param>
        override protected void DrawLine(
            ChartGraphics graph,
            CommonElements common,
            DataPoint point,
            Series series,
            SKPoint[] points,
            int pointIndex,
            float tension)
        {
            // Start drawing from the second point
            if (pointIndex <= 0)
            {
                return;
            }

            // Darw two lines
            SKPoint point1 = points[pointIndex - 1];
            SKPoint point2 = new(points[pointIndex].X, points[pointIndex - 1].Y);
            SKPoint point3 = points[pointIndex];

            graph.DrawLineRel(point.Color, point.BorderWidth, point.BorderDashStyle, graph.GetRelativePoint(point1), graph.GetRelativePoint(point2), series.ShadowColor, series.ShadowOffset);
            graph.DrawLineRel(point.Color, point.BorderWidth, point.BorderDashStyle, graph.GetRelativePoint(point2), graph.GetRelativePoint(point3), series.ShadowColor, series.ShadowOffset);

            if (common.ProcessModeRegions)
            {
                // Create grapics path object for the line
                // Split line into 2 segments.
                SKPath path = new();
                try
                {
                    path.AddLine(point2, point3);
                    if (!point2.Equals(point3))
                    {
                        // path.Widen(new Pen(point.Color, point.BorderWidth + 2));
                    }
                }
                catch (OutOfMemoryException)
                {
                    // SKPath.Widen incorrectly throws OutOfMemoryException
                    // catching here and reacting by not widening
                }
                catch (ArgumentException)
                {
                    // Ignore
                }

                float[]   coord      = new float[path.PointCount * 2];
                SKPoint[] pathPoints = path.Points;

                // Allocate array of floats
                SKPoint pointNew;
                for (int i = 0; i < path.PointCount; i++)
                {
                    pointNew         = graph.GetRelativePoint(pathPoints[i]);
                    coord[2 * i]     = pointNew.X;
                    coord[2 * i + 1] = pointNew.Y;
                }

                common.HotRegionsList.AddHotRegion(
                    path,
                    false,
                    coord,
                    point,
                    series.Name,
                    pointIndex);
                path.Dispose();
                // Create grapics path object for the line
                path = new SKPath();
                try
                {
                    path.AddLine(point1, point2);
                    //path.Widen(new Pen(point.Color, point.BorderWidth + 2));
                }
                catch (OutOfMemoryException)
                {
                    // SKPath.Widen incorrectly throws OutOfMemoryException
                    // catching here and reacting by not widening
                }
                catch (ArgumentException)
                {
                    // Ignore
                }

                // Allocate array of floats
                coord      = new float[path.PointCount * 2];
                pathPoints = path.Points;
                for (int i = 0; i < path.PointCount; i++)
                {
                    pointNew         = graph.GetRelativePoint(pathPoints[i]);
                    coord[2 * i]     = pointNew.X;
                    coord[2 * i + 1] = pointNew.Y;
                }

                common.HotRegionsList.AddHotRegion(
                    path,
                    false,
                    coord,
                    series.Points[pointIndex - 1],
                    series.Name,
                    pointIndex - 1);
                path.Dispose();
            }
        }
        /// <summary>
        /// Draws chart area cursor and selection.
        /// </summary>
        /// <param name="graph">Reference to the ChartGraphics object.</param>
        internal void Paint(ChartGraphics graph)
        {
            //***************************************************
            //** Prepare for drawing
            //***************************************************

            // Do not proceed with painting if cursor is not attached to the axis
            if (GetAxis() == null ||
                _chartArea == null ||
                _chartArea.Common == null ||
                _chartArea.Common.ChartPicture == null ||
                _chartArea.Common.ChartPicture.isPrinting)
            {
                return;
            }

            // Get plot area position
            SKRect plotAreaPosition = _chartArea.PlotAreaPosition.ToSKRect();

            // Detect if cursor is horizontal or vertical
            bool horizontal = true;

            if (GetAxis().AxisPosition == AxisPosition.Bottom || GetAxis().AxisPosition == AxisPosition.Top)
            {
                horizontal = false;
            }

            //***************************************************
            //** Draw selection
            //***************************************************

            // Check if selection need to be drawn
            if (_drawSelection &&
                !double.IsNaN(SelectionStart) &&
                !double.IsNaN(SelectionEnd) &&
                SelectionColor != SKColor.Empty)
            {
                // Calculate selection rectangle
                SKRect rectSelection = GetSelectionRect(plotAreaPosition);
                rectSelection.Intersect(plotAreaPosition);

                // Get opposite axis selection rectangle
                SKRect rectOppositeSelection = GetOppositeSelectionRect(plotAreaPosition);

                // Draw selection if rectangle is not empty
                if (!rectSelection.IsEmpty && rectSelection.Width > 0 && rectSelection.Height > 0)
                {
                    // Limit selection rectangle to the area of the opposite selection
                    if (!rectOppositeSelection.IsEmpty && rectOppositeSelection.Width > 0 && rectOppositeSelection.Height > 0)
                    {
                        rectSelection.Intersect(rectOppositeSelection);

                        // We do not need to draw selection in the opposite axis
                        Cursor oppositeCursor =
                            (_attachedToXAxis == AxisName.X || _attachedToXAxis == AxisName.X2) ?
                            _chartArea.CursorY : _chartArea.CursorX;
                        oppositeCursor._drawSelection = false;
                    }

                    // Make sure selection is inside plotting area
                    rectSelection.Intersect(plotAreaPosition);

                    // If selection rectangle is not empty
                    if (rectSelection.Width > 0 && rectSelection.Height > 0)
                    {
                        // Add transparency to solid colors
                        var rangeSelectionColor = SelectionColor;
                        if (rangeSelectionColor.Alpha == 255)
                        {
                            rangeSelectionColor = new(rangeSelectionColor.Red, rangeSelectionColor.Green, rangeSelectionColor.Blue, 120);
                        }

                        // Draw selection
                        graph.FillRectangleRel(rectSelection,
                                               rangeSelectionColor,
                                               ChartHatchStyle.None,
                                               "",
                                               ChartImageWrapMode.Tile,
                                               SKColor.Empty,
                                               ChartImageAlignmentStyle.Center,
                                               GradientStyle.None,
                                               SKColor.Empty,
                                               SKColor.Empty,
                                               0,
                                               ChartDashStyle.NotSet,
                                               SKColor.Empty,
                                               0,
                                               PenAlignment.Inset);
                    }
                }
            }

            //***************************************************
            //** Draw cursor
            //***************************************************

            // Check if cursor need to be drawn
            if (!double.IsNaN(Position) &&
                LineColor != SKColor.Empty &&
                LineWidth > 0 &&
                LineDashStyle != ChartDashStyle.NotSet)
            {
                // Calculate line position
                bool    insideArea = false;
                SKPoint point1     = SKPoint.Empty;
                SKPoint point2     = SKPoint.Empty;
                if (horizontal)
                {
                    // Set cursor coordinates
                    point1.X = plotAreaPosition.Left;
                    point1.Y = (float)GetAxis().GetLinearPosition(Position);
                    point2.X = plotAreaPosition.Right;
                    point2.Y = point1.Y;

                    // Check if cursor is inside plotting rect
                    if (point1.Y >= plotAreaPosition.Top && point1.Y <= plotAreaPosition.Bottom)
                    {
                        insideArea = true;
                    }
                }
                else
                {
                    // Set cursor coordinates
                    point1.X = (float)GetAxis().GetLinearPosition(Position);
                    point1.Y = plotAreaPosition.Top;
                    point2.X = point1.X;
                    point2.Y = plotAreaPosition.Bottom;

                    // Check if cursor is inside plotting rect
                    if (point1.X >= plotAreaPosition.Left && point1.X <= plotAreaPosition.Right)
                    {
                        insideArea = true;
                    }
                }

                // Draw cursor if it's inside the chart area plotting rectangle
                if (insideArea)
                {
                    graph.DrawLineRel(LineColor, LineWidth, LineDashStyle, point1, point2);
                }
            }
            // Reset draw selection flag
            _drawSelection = true;
        }
Exemple #3
0
        /// <summary>
        /// Paints an annotation object on the specified graphics.
        /// </summary>
        /// <param name="graphics">
        /// A <see cref="ChartGraphics"/> object, used to paint an annotation object.
        /// </param>
        /// <param name="chart">
        /// Reference to the <see cref="ChartService"/> owner control.
        /// </param>
        override internal void Paint(ChartService chart, ChartGraphics graphics)
        {
            // Get annotation position in relative coordinates
            GetRelativePosition(out SKPoint firstPoint, out SKSize size, out SKPoint anchorPoint);
            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);

            // Adjust coordinates
            AdjustLineCoordinates(ref firstPoint, ref secondPoint, ref selectionRect);

            // Check if text position is valid
            if (float.IsNaN(firstPoint.X) ||
                float.IsNaN(firstPoint.Y) ||
                float.IsNaN(secondPoint.X) ||
                float.IsNaN(secondPoint.Y))
            {
                return;
            }

            // TODO: this
#if false
            // Set line caps
            bool        capChanged = false;
            SKStrokeCap oldCap     = SKStrokeCap.Butt;
            if (_startCap != LineAnchorCapStyle.None ||
                _endCap != LineAnchorCapStyle.None)
            {
                capChanged = true;
                oldCap     = graphics.Pen.StrokeCap;

                // Apply anchor cap settings
                if (_startCap == LineAnchorCapStyle.Arrow)
                {
                    // Adjust arrow size for small line width
                    if (LineWidth < 4)
                    {
                        int adjustment = 3 - LineWidth;
                        graphics.Pen.StrokeCap      = LineCap.Custom;
                        graphics.Pen.CustomStartCap = new AdjustableArrowCap(
                            LineWidth + adjustment,
                            LineWidth + adjustment,
                            true);
                    }
                    else
                    {
                        graphics.Pen.StartCap = LineCap.ArrowAnchor;
                    }
                }
                else if (_startCap == LineAnchorCapStyle.Diamond)
                {
                    graphics.Pen.StartCap = LineCap.DiamondAnchor;
                }
                else if (_startCap == LineAnchorCapStyle.Round)
                {
                    graphics.Pen.StartCap = LineCap.RoundAnchor;
                }
                else if (_startCap == LineAnchorCapStyle.Square)
                {
                    graphics.Pen.StartCap = LineCap.SquareAnchor;
                }
                if (_endCap == LineAnchorCapStyle.Arrow)
                {
                    // Adjust arrow size for small line width
                    if (LineWidth < 4)
                    {
                        int adjustment = 3 - LineWidth;
                        graphics.Pen.StrokeCap = SKStrokeCap.Round;
                        //    graphics.Pen.EndCap = LineCap.Custom;
                        //    graphics.Pen.CustomEndCap = new AdjustableArrowCap(
                        //        this.LineWidth + adjustment,
                        //        this.LineWidth + adjustment,
                        //        true);
                    }
                    else
                    {
                        graphics.Pen.StrokeCap = SKStrokeCap.Round;//LineCap.ArrowAnchor;
                    }
                }
                else if (_endCap == LineAnchorCapStyle.Diamond)
                {
                    graphics.Pen.EndCap = LineCap.DiamondAnchor;
                }
                else if (_endCap == LineAnchorCapStyle.Round)
                {
                    graphics.Pen.EndCap = LineCap.RoundAnchor;
                }
                else if (_endCap == LineAnchorCapStyle.Square)
                {
                    graphics.Pen.EndCap = LineCap.SquareAnchor;
                }
            }

            if (Common.ProcessModePaint)
            {
                // Draw line
                graphics.DrawLineRel(
                    LineColor,
                    LineWidth,
                    LineDashStyle,
                    firstPoint,
                    secondPoint,
                    ShadowColor,
                    ShadowOffset);
            }

            // Restore line caps
            if (capChanged)
            {
                graphics.Pen.StartCap = oldStartCap;
                graphics.Pen.EndCap   = oldEndCap;
            }
#endif
            // Paint selection handles
            PaintSelectionHandles(graphics, selectionRect, null);
        }