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
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.
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; }
Any update on this ?