public void Attach() { // action = new SnapAction(selectedElement, type, si.NearElement, si.LineConnectionPoint, nearConnectionPoint); //si.NearElement.Connections.Add(new Connection() { ToElement = selectedElement, ToConnectionPoint = si.LineConnectionPoint, ElementConnectionPoint = nearConnectionPoint }); //selectedElement.SetConnection(si.LineConnectionPoint.Type, si.NearElement); targetShape.Connections.Add(new Connection() { ToElement = connector, ToConnectionPoint = lineConnectionPoint, ElementConnectionPoint = shapeConnectionPoint }); connector.SetConnection(lineConnectionPoint.Type, targetShape); }
public override bool Snap(GripType type, ref Point delta) { // Snapping permitted only when one and only one element is selected. if (selectedElements.Count != 1) { return(false); } bool snapped = false; GraphicElement selectedElement = selectedElements[0]; // Look for connection points on nearby elements. // If a connection point is nearby, and the delta is moving toward that connection point, then snap to that connection point. // So, it seems odd that we're using the connection points of the line, rather than the anchors. // However, this is actually simpler, and a line's connection points should at least include the endpoint anchors. IEnumerable <ConnectionPoint> connectionPoints = selectedElement.GetConnectionPoints().Where(p => type == GripType.None || p.Type == type); nearElements = GetNearbyElements(connectionPoints); ShowConnectionPoints(nearElements.Select(e => e.NearElement), true); ShowConnectionPoints(currentlyNear.Where(e => !nearElements.Any(e2 => e.NearElement == e2.NearElement)).Select(e => e.NearElement), false); currentlyNear = nearElements; // Issue #6 // TODO: Again, sort of kludgy. UpdateWithNearElementConnectionPoints(nearElements); nearElements = nearElements.OrderBy(si => si.AbsDx + si.AbsDy).ToList(); // abs(dx) + abs(dy) as a fast "distance" sorter, no need for sqrt(dx^2 + dy^2) foreach (SnapInfo si in nearElements) { ConnectionPoint nearConnectionPoint = si.NearElement.GetConnectionPoints().FirstOrDefault(cp => cp.Point.IsNear(si.LineConnectionPoint.Point, SNAP_CONNECTION_POINT_RANGE)); if (nearConnectionPoint != null) { Point sourceConnectionPoint = si.LineConnectionPoint.Point; int neardx = nearConnectionPoint.Point.X - sourceConnectionPoint.X; // calculate to match possible delta sign int neardy = nearConnectionPoint.Point.Y - sourceConnectionPoint.Y; int neardxsign = neardx.Sign(); int neardysign = neardy.Sign(); int deltaxsign = delta.X.Sign(); int deltaysign = delta.Y.Sign(); // Are we attached already or moving toward the shape's connection point? if ((neardxsign == 0 || deltaxsign == 0 || neardxsign == deltaxsign) && (neardysign == 0 || deltaysign == 0 || neardysign == deltaysign)) { // If attached, are we moving away from the connection point to detach it? if (neardxsign == 0 && neardxsign == 0 && (delta.X.Abs() >= SNAP_DETACH_VELOCITY || delta.Y.Abs() >= SNAP_DETACH_VELOCITY)) { Disconnect(selectedElement, type); } else { // Not already connected? if (neardxsign != 0 || neardysign != 0) { // Remove any current connections. See issue #41 Disconnect(selectedElement, type); si.NearElement.Connections.Add(new Connection() { ToElement = selectedElement, ToConnectionPoint = si.LineConnectionPoint, ElementConnectionPoint = nearConnectionPoint }); selectedElement.SetConnection(si.LineConnectionPoint.Type, si.NearElement); } delta = new Point(neardx, neardy); snapped = true; break; } } } } return(snapped); }