// Be sure to call the base class constructor.
        public DottedPathAdorner(UIElement adornedElement, LinkStroke stroke, CustomInkCanvas canvas)
            : base(adornedElement)
        {
            adornedStroke = stroke;

            linkStroke     = stroke;
            this.canvas    = canvas;
            visualChildren = new VisualCollection(this);
            strokeBounds   = stroke.GetCustomBound();

            linkPath                 = new Path();
            linkPath.Stroke          = (Brush) new BrushConverter().ConvertFromString(stroke.style.color);
            linkPath.StrokeThickness = stroke.DrawingAttributes.Height;
            linkPath.StrokeDashArray = new DoubleCollection {
                1, 0.5
            };
            linkPath.IsHitTestVisible = false;
            linkPath.Fill             = Brushes.Black;

            arrowGeom = new PathGeometry();
            lineGeom  = new LineGeometry();

            for (int i = 1; i < linkStroke.path.Count - 1; i++)
            {
                lineGeom.StartPoint = linkStroke.path[i - 1].ToPoint();
                lineGeom.EndPoint   = linkStroke.path[i].ToPoint();
                arrowGeom.AddGeometry(lineGeom);
            }

            AddRelationArrows1();

            linkPath.Data = arrowGeom;

            arrowGeom = new PathGeometry();

            AddRelationArrows();

            arrow                 = new Path();
            arrow.Data            = arrowGeom;
            arrow.Stroke          = (Brush) new BrushConverter().ConvertFromString(stroke.style.color);
            arrow.StrokeThickness = 2;
            if (linkStroke.linkType == 1 || linkStroke.linkType == 2 && linkStroke.style?.thickness != 0)
            {
                arrow.StrokeThickness = 3;
            }
            arrow.IsHitTestVisible = false;
            arrow.Fill             = Brushes.Black;

            visualChildren.Add(linkPath);
            visualChildren.Add(arrow);
        }
        public LinkRotateAdorner(UIElement adornedElement, LinkStroke strokeToRotate, CustomInkCanvas actualCanvas)
            : base(adornedElement)
        {
            adornedStroke = strokeToRotate;

            linkStroke = strokeToRotate;
            canvas     = actualCanvas;
            // rotation initiale de la stroke (pour dessiner le rectangle)
            // Bug. Cheat, but the geometry, the selection Rectangle (newRect) should be the right one.. geom of the stroke?
            strokeBounds = strokeToRotate.GetCustomBound();
            center       = linkStroke.GetCenter();
            lastAngle    = linkStroke.rotation;

            rotation = new RotateTransform(linkStroke.rotation, center.X, center.Y);

            visualChildren          = new VisualCollection(this);
            rotateHandle            = new Thumb();
            rotateHandle.Cursor     = Cursors.Hand;
            rotateHandle.Width      = 10;
            rotateHandle.Height     = 10;
            rotateHandle.Background = new LinearGradientBrush((Color)ColorConverter.ConvertFromString("#FFc8d4ea"),
                                                              (Color)ColorConverter.ConvertFromString("#FF809dce"), 45);

            rotateHandle.DragDelta     += new DragDeltaEventHandler(rotateHandle_DragDelta);
            rotateHandle.DragCompleted += new DragCompletedEventHandler(rotateHandle_DragCompleted);

            TransformGroup transform = new TransformGroup();

            transform.Children.Add(new RotateTransform(rotation.Angle, rotateHandle.Width / 2, rotateHandle.Height / 2));
            transform.Children.Add(new TranslateTransform(-canvas.ActualWidth / 2 + strokeBounds.X + strokeBounds.Width / 2,
                                                          -canvas.ActualHeight / 2 + strokeBounds.Y - HANDLEMARGIN));

            rotateHandle.RenderTransform = transform;

            line                 = new Path();
            line.Stroke          = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF809dce"));
            line.StrokeThickness = 1;

            line.RenderTransform = rotation;

            visualChildren.Add(line);
            visualChildren.Add(rotateHandle);

            pathPreview.IsClosed          = false;
            rotatePreview                 = new Path();
            rotatePreview.Data            = new PathGeometry();
            rotatePreview.Stroke          = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFBBBBBB"));
            rotatePreview.StrokeThickness = 2;
            visualChildren.Add(rotatePreview);
        }
        /// <summary>
        /// Rotates the rectangle representing the
        /// strokes' bounds as the user drags the
        /// Thumb.
        /// </summary>
        void rotateHandle_DragDelta(object sender, DragDeltaEventArgs e)
        {
            // Find the angle of which to rotate the shape.  Use the right
            // triangle that uses the center and the mouse's position
            // as vertices for the hypotenuse.

            Point pos = Mouse.GetPosition(this);

            double deltaX = pos.X - center.X;
            double deltaY = pos.Y - center.Y;

            if (deltaY.Equals(0))
            {
                return;
            }

            double tan   = deltaX / deltaY;
            double angle = Math.Atan(tan);

            // Convert to degrees.
            angle = angle * 180 / Math.PI;

            // If the mouse crosses the vertical center,
            // find the complementary angle.
            if (deltaY > 0)
            {
                angle = 180 - Math.Abs(angle);
            }

            // Rotate left if the mouse moves left and right
            // if the mouse moves right.
            if (deltaX < 0)
            {
                angle = -Math.Abs(angle);
            }
            else
            {
                angle = Math.Abs(angle);
            }

            if (Double.IsNaN(angle))
            {
                return;
            }

            // Apply the rotation to the strokes' outline.
            rotation = new RotateTransform(angle, center.X, center.Y);
            pathPreview.Segments.Clear();
            bool isFirst = true;

            foreach (Coordinates coordinates in linkStroke.path)
            {
                if (isFirst)
                {
                    pathPreview.StartPoint = rotation.Transform(coordinates.ToPoint());
                    isFirst = false;
                }
                else
                {
                    pathPreview.Segments.Add(new LineSegment(rotation.Transform(coordinates.ToPoint()), true));
                }
            }
            rotatePreview.Data = new PathGeometry(new PathFigureCollection {
                pathPreview
            });
            rotatePreview.Arrange(new Rect(new Size(canvas.ActualWidth, canvas.ActualHeight)));

            line.RenderTransform = rotation;

            TransformGroup transform = new TransformGroup();

            transform.Children.Add(new RotateTransform(rotation.Angle, rotateHandle.Width / 2, rotateHandle.Height / 2 + HANDLEMARGIN + linkStroke.GetCustomBound().Height / 2));
            transform.Children.Add(new TranslateTransform(-canvas.ActualWidth / 2 + strokeBounds.X + strokeBounds.Width / 2,
                                                          -canvas.ActualHeight / 2 + strokeBounds.Y - HANDLEMARGIN));

            rotateHandle.RenderTransform = transform;
        }