1 //----------------------------------------------------------------
2 // <copyright company="Microsoft Corporation">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //----------------------------------------------------------------
7 namespace System.Activities.Presentation.FreeFormEditing
9 using System.Collections.Generic;
12 internal static class AutoSplitHelper
14 private const double ShapeMargin = 40;
16 public static void CalculateEntryExitEdges(Point mousePosition, Connector connector, out EdgeLocation entryEdge, out EdgeLocation exitEdge)
18 UIElement srcShape = FreeFormPanel.GetSourceConnectionPoint(connector).ParentDesigner;
19 UIElement destShape = FreeFormPanel.GetDestinationConnectionPoint(connector).ParentDesigner;
20 Point srcLocation = FreeFormPanel.GetLocation(srcShape);
21 Point destLocation = FreeFormPanel.GetLocation(destShape);
22 Size srcSize = FreeFormPanel.GetChildSize(srcShape);
23 Size destSize = FreeFormPanel.GetChildSize(destShape);
25 Point srcCenter = new Point(srcLocation.X + (srcSize.Width / 2), srcLocation.Y + (srcSize.Height / 2));
26 Point destCenter = new Point(destLocation.X + (destSize.Width / 2), destLocation.Y + (destSize.Height / 2));
28 entryEdge = CalculateEdgeLocation(mousePosition, srcCenter);
29 exitEdge = CalculateEdgeLocation(mousePosition, destCenter);
31 if (exitEdge == entryEdge)
35 case EdgeLocation.Top:
36 exitEdge = EdgeLocation.Bottom;
39 case EdgeLocation.Bottom:
40 exitEdge = EdgeLocation.Top;
43 case EdgeLocation.Left:
44 exitEdge = EdgeLocation.Right;
47 case EdgeLocation.Right:
48 exitEdge = EdgeLocation.Left;
54 public static Point CalculateDropLocation(Point mousePosition, Point originalDropLocation, Connector connector, Size droppedSize, HashSet<Point> shapeLocations)
56 UIElement srcShape = FreeFormPanel.GetSourceConnectionPoint(connector).ParentDesigner;
57 UIElement destShape = FreeFormPanel.GetDestinationConnectionPoint(connector).ParentDesigner;
58 Point srcLocation = FreeFormPanel.GetLocation(srcShape);
59 Point destLocation = FreeFormPanel.GetLocation(destShape);
60 Size srcSize = FreeFormPanel.GetChildSize(srcShape);
61 Size destSize = FreeFormPanel.GetChildSize(destShape);
63 return CalculateDropLocation(mousePosition, originalDropLocation, droppedSize, srcLocation, destLocation, srcSize, destSize, shapeLocations);
66 internal static Point CalculateDropLocation(Point mousePosition, Point originalDropLocation, Size droppedSize, Point srcLocation, Point destLocation, Size srcSize, Size destSize, HashSet<Point> shapeLocations)
68 Point dropLocation = originalDropLocation;
70 double distToSrc = DesignerGeometryHelper.ManhattanDistanceBetweenPoints(mousePosition, new Point(srcLocation.X + (srcSize.Width / 2), srcLocation.Y + (srcSize.Height / 2)));
71 double distToDest = DesignerGeometryHelper.ManhattanDistanceBetweenPoints(mousePosition, new Point(destLocation.X + (destSize.Width / 2), destLocation.Y + (destSize.Height / 2)));
73 AutoSplitAlignment srcAlignment = GetAlignment(mousePosition, srcLocation, srcSize);
74 AutoSplitAlignment destAlignment = GetAlignment(mousePosition, destLocation, destSize);
76 if ((distToSrc <= distToDest || destAlignment == AutoSplitAlignment.None) && srcAlignment == AutoSplitAlignment.Vertical)
78 dropLocation = CalculateDropLocationToAlignVertically(dropLocation, droppedSize, srcLocation, srcSize);
80 else if ((distToSrc <= distToDest || destAlignment == AutoSplitAlignment.None) && srcAlignment == AutoSplitAlignment.Horizontal)
82 dropLocation = CalculateDropLocationToAlignHorizontally(dropLocation, droppedSize, srcLocation, srcSize);
84 else if ((distToSrc >= distToDest || srcAlignment == AutoSplitAlignment.None) && destAlignment == AutoSplitAlignment.Vertical)
86 dropLocation = CalculateDropLocationToAlignVertically(dropLocation, droppedSize, destLocation, destSize);
88 else if ((distToSrc >= distToDest || srcAlignment == AutoSplitAlignment.None) && destAlignment == AutoSplitAlignment.Horizontal)
90 dropLocation = CalculateDropLocationToAlignHorizontally(dropLocation, droppedSize, destLocation, destSize);
93 dropLocation.X = dropLocation.X < 0 ? 0 : dropLocation.X;
94 dropLocation.Y = dropLocation.Y < 0 ? 0 : dropLocation.Y;
96 // To avoid overlaps with existing shapes
97 if (shapeLocations != null)
99 while (shapeLocations.Contains(dropLocation))
101 dropLocation.Offset(FreeFormPanel.GridSize, FreeFormPanel.GridSize);
108 internal static AutoSplitAlignment GetAlignment(Point mousePosition, Point targetLocation, Size targetSize)
110 AutoSplitAlignment alignment = AutoSplitAlignment.None;
111 if (mousePosition.X >= targetLocation.X && mousePosition.X <= targetLocation.X + targetSize.Width)
113 alignment = AutoSplitAlignment.Vertical;
115 else if (mousePosition.Y >= targetLocation.Y && mousePosition.Y <= targetLocation.Y + targetSize.Height)
117 alignment = AutoSplitAlignment.Horizontal;
123 internal static Point CalculateDropLocationToAlignVertically(Point originalDropLocation, Size droppedSize, Point targetLocation, Size targetSize)
125 Point dropLocation = originalDropLocation;
126 dropLocation.X = targetLocation.X + ((targetSize.Width - droppedSize.Width) / 2);
127 if (dropLocation.Y >= targetLocation.Y && dropLocation.Y <= targetLocation.Y + targetSize.Height + ShapeMargin)
129 dropLocation.Y = targetLocation.Y + targetSize.Height + ShapeMargin;
131 else if (dropLocation.Y + droppedSize.Height + ShapeMargin >= targetLocation.Y && dropLocation.Y <= targetLocation.Y)
133 dropLocation.Y = targetLocation.Y - droppedSize.Height - ShapeMargin;
139 internal static Point CalculateDropLocationToAlignHorizontally(Point originalDropLocation, Size droppedSize, Point targetLocation, Size targetSize)
141 Point dropLocation = originalDropLocation;
142 dropLocation.Y = targetLocation.Y + ((targetSize.Height - droppedSize.Height) / 2);
143 if (dropLocation.X >= targetLocation.X && dropLocation.X <= targetLocation.X + targetSize.Width + ShapeMargin)
145 dropLocation.X = targetLocation.X + targetSize.Width + ShapeMargin;
147 else if (dropLocation.X + droppedSize.Width + ShapeMargin >= targetLocation.X && dropLocation.X <= targetLocation.X)
149 dropLocation.X = targetLocation.X - droppedSize.Width - ShapeMargin;
155 internal static EdgeLocation CalculateEdgeLocation(Point mousePosition, Point shapeCenter)
157 double distX = Math.Abs(shapeCenter.X - mousePosition.X);
158 double distY = Math.Abs(shapeCenter.Y - mousePosition.Y);
161 return shapeCenter.X < mousePosition.X ? EdgeLocation.Left : EdgeLocation.Right;
165 return shapeCenter.Y < mousePosition.Y ? EdgeLocation.Top : EdgeLocation.Bottom;