Declined
Last Updated: 29 Dec 2016 11:05 by ADMIN
ADMIN
Petar Mladenov
Created on: 06 Dec 2013 15:34
Category: Diagram
Type: Feature Request
1
Diagram: Implement Item to Item Snapping during Resize.
Implement "Item to Item Snapping" during item resize operation.

DECLINED: Duplicate with https://feedback.telerik.com/Project/143/Feedback/Details/101276-diagram-implement-item-to-item-snapping-during-resize
(Total attached files size should be smaller than 20mb. Allowed extensions: .zip, .rar, .jpg, .png, .gif)
3 comments
Bruno
Posted on: 11 Aug 2016 17:44
Any update on this ?
Bruno
Posted on: 11 Aug 2016 17:49
I did an implementation of snapping for resizing but the issue is when resizing we should just try to snap based on the resizing point not all sides of the SelectedShapes. But currently snapping engine doesn't support this way. and suggestion ?

public class XResizingService : ResizingService
    {
        private bool ShiftModifierAlreadyConsidered { get; set; }

        private Point StartPoint { get; set; }

        private double SizeRatio { get; set; }

        private Rect AdornerBound { get; set; }

        private RadDiagram Diagram { get; set; }

        private bool KeepAspectRatio { get; set; }

        private IEnumerable<IDiagramItem> Items { get; set; }

        private SnappingLinesCalculatedEventArgs SnappingLines { get; set; }

        private ISnappingService SnappingService { get { return Diagram.ServiceLocator.GetService<ISnappingService>(); } }

        public XResizingService(RadDiagram graph)
            : base(graph)
        {
            Diagram = graph;
        }

        public override void InitializeResize(IEnumerable<IDiagramItem> newSelectedItems, double adornerAngle, Rect adornerBounds, ResizeDirection resisingDirection, Point startPoint)
        {
            StartPoint = startPoint;
            this.AdornerBound = adornerBounds;
            Items = newSelectedItems;
            Diagram.IsSnapToGridEnabled = false;
            base.InitializeResize(newSelectedItems, adornerAngle, adornerBounds, resisingDirection, startPoint);

            if (Diagram.IsSnapToItemsEnabled)
            {
                SnappingService.InitializeSnap(this.Diagram.Items.OfType<IShape>().Where(i => Items.Contains(i) == false), Items.First(), true, false, startPoint);
                SnappingService.SnappingLinesCalculated -= SnappingService_SnappingLinesCalculated;
                SnappingService.SnappingLinesCalculated += SnappingService_SnappingLinesCalculated;
            }
         
            if (Keyboard.Modifiers == ModifierKeys.Shift || KeepAspectRatio)
            {
                ShiftModifierAlreadyConsidered = true;
                this.AdornerBound = adornerBounds;
                this.SizeRatio = this.AdornerBound.Width / this.AdornerBound.Height;
            }
            else
            {
                ShiftModifierAlreadyConsidered = false;
            }
        }

        public override void CompleteResize(Rect finalBounds, Point mousePosition)
        {
            base.CompleteResize(finalBounds, mousePosition);
            Diagram.IsSnapToGridEnabled = true;
            if (Diagram.IsSnapToItemsEnabled)
            {
                SnappingLines = null;
                SnappingService.SnappingLinesCalculated -= SnappingService_SnappingLinesCalculated;
                SnappingService.ClearSnap();
            }
        }

        protected override Point CalculateNewDelta(Point newPoint)
        {
            if (Keyboard.Modifiers == ModifierKeys.Shift || KeepAspectRatio)
            {
                if (ShiftModifierAlreadyConsidered == false)
                {
                    this.SizeRatio = this.AdornerBound.Width / this.AdornerBound.Height;
                }

                if (Diagram.IsSnapToItemsEnabled)
                {
                    SnappingService.SnapItems(Items, newPoint);

                    if (SnappingLines != null)
                    {
                        double minX = 0;
                        double minY = 0;

                        if (SnappingLines.VerticalSnappingLines.Any())
                        {
                            minX = SnappingLines.VerticalSnappingLines.Min(l => Math.Abs(newPoint.X - l.Start.Value.X));
                            
                        }

                        if (SnappingLines.HorizontalSnappingLines.Any())
                        {
                            minY = SnappingLines.HorizontalSnappingLines.Min(l => Math.Abs(newPoint.Y - l.Start.Value.Y));
                        }

                        bool shouldKeepX=false;
                        bool shouldKeepY=false;

                        var verticalSnapLine = SnappingLines.VerticalSnappingLines.FirstOrDefault(l => Math.Abs(l.Start.Value.X - newPoint.X)==minX);
                        var horizontalSnapLine = SnappingLines.HorizontalSnappingLines.FirstOrDefault(l => Math.Abs(l.Start.Value.Y - newPoint.Y)==minY);

                        if (verticalSnapLine != null || horizontalSnapLine != null)
                        {
                            if (verticalSnapLine == null)
                            {
                                shouldKeepY = true;
                            }
                            else if (horizontalSnapLine == null)
                            {
                                shouldKeepX = true;
                            }
                            else
                            {
                                if (minX < minY)
                                {
                                    shouldKeepY = true;
                                }
                                else
                                {
                                    shouldKeepX = true;
                                }
                            }
                        }

                        if (shouldKeepY || shouldKeepX)
                        {
                            if (shouldKeepX)
                            {
                                double newY = ((verticalSnapLine.Start.Value.X - StartPoint.X) / SizeRatio) + StartPoint.Y;
                                newPoint = new Point(verticalSnapLine.Start.Value.X, newY);
                            }
                            if (shouldKeepY)
                            {
                                double newX = (SizeRatio * (horizontalSnapLine.Start.Value.Y - StartPoint.Y)) + StartPoint.X;
                                newPoint = new Point(newX, horizontalSnapLine.Start.Value.Y);
                            }

                            return base.CalculateNewDelta(newPoint);
                        }
                    }
                }


                double y = ((newPoint.X - StartPoint.X) / SizeRatio) + StartPoint.Y;
                double x = (SizeRatio * (newPoint.Y - StartPoint.Y)) + StartPoint.X;

                if (Math.Abs(x - newPoint.X) < Math.Abs(y - newPoint.Y))
                {
                    newPoint = new Point(newPoint.X, y);
                }
                else
                {
                    newPoint = new Point(x, newPoint.Y);
                }

                return base.CalculateNewDelta(newPoint);
            }

            if (Diagram.IsSnapToItemsEnabled)
            {
                newPoint = SnappingService.SnapItems(Items, newPoint);
            }

            return base.CalculateNewDelta(newPoint);
        }

        private void SnappingService_SnappingLinesCalculated(object sender, SnappingLinesCalculatedEventArgs e)
        {
            SnappingLines = e;
        }
ADMIN
Petar Mladenov
Posted on: 16 Aug 2016 07:38
It seems a little strange to snap a group of shapes on resize only on some / one of them.
However, you can try to pass only subset of the selected shapes to the function SnappingService.SnapItems.