/// <summary>
 /// Creates and adds <see cref="SnapLine"/>s for the free <see cref="AdditionalSnapLineVisualCreator"/>
 /// to a <see cref="GraphSnapContext"/>.
 /// </summary>
 /// <remarks>
 /// While the <see cref="AdditionalSnapLineVisualCreator"/>s are used to visualize and represent free snap lines,
 /// according <see cref="OrthogonalSnapLine"/>s have to be added to the snapping mechanism to describe their snapping behavior.
 /// </remarks>
 /// <param name="sender">The snap context sending this event.</param>
 /// <param name="e">The event arguments to add the snap lines to.</param>
 protected virtual void CollectAdditionalGraphSnapLines(object sender, CollectGraphSnapLinesEventArgs e)
 {
     foreach (var creator in AdditionalSnapLineVisualCreators)
     {
         foreach (var snapLine in creator.CreateSnapLines())
         {
             e.AddAdditionalSnapLine(snapLine);
         }
     }
 }
        /// <summary>
        /// Calls <see cref="ISnapLineProvider.AddSnapLines"/> of the wrapped provider and adds custom <see cref="OrthogonalSnapLine"/>s
        /// for the <paramref name="item"/>.
        /// </summary>
        /// <param name="context">The context which holds the settings for the snap lines. </param>
        /// <param name="args">The argument to use for adding snap lines.</param>
        /// <param name="item">The item to add snaplines for.</param>
        public void AddSnapLines(GraphSnapContext context, CollectGraphSnapLinesEventArgs args, IModelItem item)
        {
            wrapped.AddSnapLines(context, args, item);

            // add snaplines for orthogonal labels
            ILabelOwner labelOwner = item as ILabelOwner;

            if (labelOwner != null)
            {
                foreach (ILabel label in labelOwner.Labels)
                {
                    var    layout = label.GetLayout();
                    double upX    = Math.Round(layout.UpX, 6); // round UpX to it's first 6 digits
                    if (upX == 0 || upX == 1 || upX == -1)     // check if it's orthogonal
                    // label is orthogonal
                    {
                        RectD bounds = layout.GetBounds();

                        // add snaplines to the top, bottom, left and right border of the label
                        PointD topCenter = bounds.TopLeft + new PointD(layout.Width / 2, 0);
                        var    snapLine  = new OrthogonalSnapLine(SnapLineOrientation.Horizontal, SnapLineSnapTypes.Bottom,
                                                                  SnapLine.SnapLineFixedLineKey, topCenter, bounds.MinX - 10, bounds.MaxX + 10, label, 100);
                        args.AddAdditionalSnapLine(snapLine);

                        PointD bottomCenter = bounds.BottomLeft + new PointD(layout.Width / 2, 0);
                        snapLine = new OrthogonalSnapLine(SnapLineOrientation.Horizontal, SnapLineSnapTypes.Top,
                                                          SnapLine.SnapLineFixedLineKey, bottomCenter, bounds.MinX - 10, bounds.MaxX + 10, label, 100);
                        args.AddAdditionalSnapLine(snapLine);

                        PointD leftCenter = bounds.TopLeft + new PointD(0, layout.Height / 2);
                        snapLine = new OrthogonalSnapLine(SnapLineOrientation.Vertical, SnapLineSnapTypes.Right,
                                                          SnapLine.SnapLineFixedLineKey, leftCenter, bounds.MinY - 10, bounds.MaxY + 10, label, 100);
                        args.AddAdditionalSnapLine(snapLine);

                        PointD rightCenter = bounds.TopRight + new PointD(0, layout.Height / 2);
                        snapLine = new OrthogonalSnapLine(SnapLineOrientation.Vertical, SnapLineSnapTypes.Left,
                                                          SnapLine.SnapLineFixedLineKey, rightCenter, bounds.MinY - 10, bounds.MaxY + 10, label, 100);
                        args.AddAdditionalSnapLine(snapLine);
                    }
                }
            }
        }