protected void UpdateConnections(GraphicElement el) { el.Connections.ForEach(c => { // Connection point on shape. ConnectionPoint cp = el.GetConnectionPoints().Single(cp2 => cp2.Type == c.ElementConnectionPoint.Type); c.ToElement.MoveAnchor(cp, c.ToConnectionPoint); }); }
public void UpdateConnections(GraphicElement el) { el.Connections.ForEach(c => { // Connection point on shape. var cps = el.GetConnectionPoints().Where(cp2 => cp2.Type == c.ElementConnectionPoint.Type); cps.ForEach(cp => c.ToElement.MoveAnchor(cp, c.ToConnectionPoint)); }); }
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); }
protected SnapAction Snap(GripType type, Point delta, bool isByKeyPress) { SnapAction action = null; // Snapping permitted only when one and only one element is selected. if (controller.SelectedElements.Count != 1) { return(null); } if (controller.IsSnapToBeIgnored) { return(null); } // bool snapped = false; GraphicElement selectedElement = controller.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? // Keyboard overrides the velocity check so we immediately detach if moving away. if (neardxsign == 0 && neardxsign == 0 && ((delta.X.Abs() >= SNAP_DETACH_VELOCITY || delta.Y.Abs() >= SNAP_DETACH_VELOCITY) || (isByKeyPress && (neardxsign != deltaxsign || neardysign != deltaysign)))) { // Detach: action = new SnapAction(SnapAction.Action.Detach, selectedElement, type, si.NearElement, si.LineConnectionPoint, nearConnectionPoint, delta); break; } else { // Not already connected? if (neardxsign != 0 || neardysign != 0) { // Attach: action = new SnapAction(SnapAction.Action.Attach, selectedElement, type, si.NearElement, si.LineConnectionPoint, nearConnectionPoint, new Point(neardx, neardy)); } else { action = new SnapAction(); break; } // delta = new Point(neardx, neardy); // snapped = true; break; } } } } return(action); }