/// <summary> /// Given an obstacle and its attempted destination, determines the correct landing /// spot for an obstacle. /// </summary> /// <param name="movingObstacle">The obstacle that is moving.</param> /// <param name="newLocation">The upper-left coordinate of the obstacle's original intended destination.</param> /// <returns> /// A Point that determines where the obstacle should be placed instead. If there are no adjustments /// required to the obstacle's desintation, then the return value will be equal to newLocation. /// </returns> /// <remarks> /// movingObstacle's SnapDescription will also be updated. The caller of this method is required /// to update the SnapObstacle with the new, adjusted location. /// </remarks> public Point AdjustObstacleDestination(SnapObstacle movingObstacle, Point newLocation) { Point adjusted1 = AdjustObstacleDestination(movingObstacle, newLocation, false); Point adjusted2 = AdjustObstacleDestination(movingObstacle, adjusted1, true); return(adjusted2); }
public void ParkObstacle(SnapObstacle obstacle, SnapObstacle snappedTo, HorizontalSnapEdge hEdge, VerticalSnapEdge vEdge) { SnapDescription sd = new SnapDescription(snappedTo, hEdge, vEdge, obstacle.SnapDistance, obstacle.SnapDistance); this.obstacles[obstacle] = sd; ParkObstacle(obstacle, sd); }
public Point AdjustObstacleDestination(SnapObstacle movingObstacle, Point newLocation, bool considerStickies) { Point adjustedLocation = newLocation; SnapDescription sd = this.obstacles[movingObstacle]; SnapDescription newSD = null; foreach (SnapObstacle avoidee in this.obstacles.Keys) { if (avoidee.StickyEdges != considerStickies) { continue; } if (avoidee.Enabled && !object.ReferenceEquals(avoidee, movingObstacle)) { SnapDescription newSD2 = DetermineNewSnapDescription(movingObstacle, adjustedLocation, avoidee, newSD); if (newSD2 != null) { Point adjustedLocation2 = AdjustNewLocation(movingObstacle, adjustedLocation, newSD2); newSD = newSD2; adjustedLocation = adjustedLocation2; Rectangle newBounds = new Rectangle(adjustedLocation, movingObstacle.Bounds.Size); } } } if (sd == null || !sd.SnappedTo.StickyEdges || newSD == null || newSD.SnappedTo.StickyEdges) { this.obstacles[movingObstacle] = newSD; } return(adjustedLocation); }
private void SnapObstacle_BoundsChanged(object sender, EventArgs <Rectangle> e) { SnapObstacle senderSO = (SnapObstacle)sender; Rectangle fromRect = e.Data; Rectangle toRect = senderSO.Bounds; UpdateDependentObstacles(senderSO, fromRect, toRect); }
private static void ParkObstacle(SnapObstacle avoider, SnapDescription snapDescription) { Point newLocation = avoider.Bounds.Location; Point adjustedLocation = AdjustNewLocation(avoider, newLocation, snapDescription); Rectangle newBounds = new Rectangle(adjustedLocation, avoider.Bounds.Size); avoider.RequestBoundsChange(newBounds); }
private void LoadSnapObstacleData(ISimpleCollection <string, string> loadFrom, SnapObstacle so) { string prefix = so.Name + "."; SnapDescription sd; string isSnappedString = loadFrom.Get(prefix + isSnappedValueName); bool isSnapped = bool.Parse(isSnappedString); if (isSnapped) { string snappedToString = loadFrom.Get(prefix + snappedToValueName); SnapObstacle snappedTo = FindObstacle(snappedToString); string horizontalEdgeString = loadFrom.Get(prefix + horizontalEdgeValueName); HorizontalSnapEdge horizontalEdge = (HorizontalSnapEdge)Enum.Parse(typeof(HorizontalSnapEdge), horizontalEdgeString, true); string verticalEdgeString = loadFrom.Get(prefix + verticalEdgeValueName); VerticalSnapEdge verticalEdge = (VerticalSnapEdge)Enum.Parse(typeof(VerticalSnapEdge), verticalEdgeString, true); string xOffsetString = loadFrom.Get(prefix + xOffsetValueName); int xOffset = int.Parse(xOffsetString, CultureInfo.InvariantCulture); string yOffsetString = loadFrom.Get(prefix + yOffsetValueName); int yOffset = int.Parse(yOffsetString, CultureInfo.InvariantCulture); sd = new SnapDescription(snappedTo, horizontalEdge, verticalEdge, xOffset, yOffset); } else { sd = null; } this.obstacles[so] = sd; string leftString = loadFrom.Get(prefix + leftValueName); int left = int.Parse(leftString, CultureInfo.InvariantCulture); string topString = loadFrom.Get(prefix + topValueName); int top = int.Parse(topString, CultureInfo.InvariantCulture); string widthString = loadFrom.Get(prefix + widthValueName); int width = int.Parse(widthString, CultureInfo.InvariantCulture); string heightString = loadFrom.Get(prefix + heightValueName); int height = int.Parse(heightString, CultureInfo.InvariantCulture); Rectangle newBounds = new Rectangle(left, top, width, height); so.RequestBoundsChange(newBounds); if (sd != null) { ParkObstacle(so, sd); } }
private void LoadSnapObstacleData(ISimpleCollection<string, string> loadFrom, SnapObstacle so) { string prefix = so.Name + "."; SnapDescription sd; string isSnappedString = loadFrom.Get(prefix + isSnappedValueName); bool isSnapped = bool.Parse(isSnappedString); if (isSnapped) { string snappedToString = loadFrom.Get(prefix + snappedToValueName); SnapObstacle snappedTo = FindObstacle(snappedToString); string horizontalEdgeString = loadFrom.Get(prefix + horizontalEdgeValueName); HorizontalSnapEdge horizontalEdge = (HorizontalSnapEdge)Enum.Parse(typeof(HorizontalSnapEdge), horizontalEdgeString, true); string verticalEdgeString = loadFrom.Get(prefix + verticalEdgeValueName); VerticalSnapEdge verticalEdge = (VerticalSnapEdge)Enum.Parse(typeof(VerticalSnapEdge), verticalEdgeString, true); string xOffsetString = loadFrom.Get(prefix + xOffsetValueName); int xOffset = int.Parse(xOffsetString, CultureInfo.InvariantCulture); string yOffsetString = loadFrom.Get(prefix + yOffsetValueName); int yOffset = int.Parse(yOffsetString, CultureInfo.InvariantCulture); sd = new SnapDescription(snappedTo, horizontalEdge, verticalEdge, xOffset, yOffset); } else { sd = null; } this.obstacles[so] = sd; string leftString = loadFrom.Get(prefix + leftValueName); int left = int.Parse(leftString, CultureInfo.InvariantCulture); string topString = loadFrom.Get(prefix + topValueName); int top = int.Parse(topString, CultureInfo.InvariantCulture); string widthString = loadFrom.Get(prefix + widthValueName); int width = int.Parse(widthString, CultureInfo.InvariantCulture); string heightString = loadFrom.Get(prefix + heightValueName); int height = int.Parse(heightString, CultureInfo.InvariantCulture); Rectangle newBounds = new Rectangle(left, top, width, height); so.RequestBoundsChange(newBounds); if (sd != null) { ParkObstacle(so, sd); } }
public void ReparkObstacle(SnapObstacle obstacle) { if (this.obstacles.ContainsKey(obstacle)) { SnapDescription sd = this.obstacles[obstacle]; if (sd != null) { ParkObstacle(obstacle, sd); } } }
public void AddSnapObstacle(SnapObstacle snapObstacle) { if (!this.obstacles.ContainsKey(snapObstacle)) { this.obstacles.Add(snapObstacle, null); if (snapObstacle.StickyEdges) { snapObstacle.BoundsChanging += SnapObstacle_BoundsChanging; snapObstacle.BoundsChanged += SnapObstacle_BoundsChanged; } } }
public void RemoveSnapObstacle(SnapObstacle snapObstacle) { if (this.obstacles.ContainsKey(snapObstacle)) { this.obstacles.Remove(snapObstacle); if (snapObstacle.StickyEdges) { snapObstacle.BoundsChanging -= SnapObstacle_BoundsChanging; snapObstacle.BoundsChanged -= SnapObstacle_BoundsChanged; } } }
public void Load(ISimpleCollection <string, string> loadFrom) { SnapObstacle[] newObstacles = new SnapObstacle[this.obstacles.Count]; this.obstacles.Keys.CopyTo(newObstacles, 0); foreach (SnapObstacle obstacle in newObstacles) { if (obstacle.EnableSave) { LoadSnapObstacleData(loadFrom, obstacle); } } }
private void UpdateDependentObstacles(SnapObstacle senderSO, Rectangle fromRect, Rectangle toRect) { int leftDelta = toRect.Left - fromRect.Left; int topDelta = toRect.Top - fromRect.Top; int rightDelta = toRect.Right - fromRect.Right; int bottomDelta = toRect.Bottom - fromRect.Bottom; foreach (SnapObstacle obstacle in this.obstacles.Keys) { if (!object.ReferenceEquals(senderSO, obstacle)) { SnapDescription sd = this.obstacles[obstacle]; if (sd != null && object.ReferenceEquals(sd.SnappedTo, senderSO)) { int deltaX; if (sd.VerticalEdge == VerticalSnapEdge.Right) { deltaX = rightDelta; } else { deltaX = leftDelta; } int deltaY; if (sd.HorizontalEdge == HorizontalSnapEdge.Bottom) { deltaY = bottomDelta; } else { deltaY = topDelta; } Rectangle oldBounds = obstacle.Bounds; Point newLocation1 = new Point(oldBounds.Left + deltaX, oldBounds.Top + deltaY); Point newLocation2 = AdjustNewLocation(obstacle, newLocation1, sd); Rectangle newBounds = new Rectangle(newLocation2, oldBounds.Size); obstacle.RequestBoundsChange(newBounds); // Recursively update anything snapped to this obstacle UpdateDependentObstacles(obstacle, oldBounds, newBounds); } } } }
public SnapDescription( SnapObstacle snappedTo, HorizontalSnapEdge horizontalEdge, VerticalSnapEdge verticalEdge, int xOffset, int yOffset) { if (snappedTo == null) { throw new ArgumentNullException("snappedTo"); } this.snappedTo = snappedTo; this.horizontalEdge = horizontalEdge; this.verticalEdge = verticalEdge; this.xOffset = xOffset; this.yOffset = yOffset; }
private void SaveSnapObstacleData(ISimpleCollection<string, string> saveTo, SnapObstacle so) { string prefix = so.Name + "."; SnapDescription sd = this.obstacles[so]; bool isSnappedValue = (sd != null); saveTo.Set(prefix + isSnappedValueName, isSnappedValue.ToString(CultureInfo.InvariantCulture)); if (isSnappedValue) { saveTo.Set(prefix + snappedToValueName, sd.SnappedTo.Name); saveTo.Set(prefix + horizontalEdgeValueName, sd.HorizontalEdge.ToString()); saveTo.Set(prefix + verticalEdgeValueName, sd.VerticalEdge.ToString()); saveTo.Set(prefix + xOffsetValueName, sd.XOffset.ToString(CultureInfo.InvariantCulture)); saveTo.Set(prefix + yOffsetValueName, sd.YOffset.ToString(CultureInfo.InvariantCulture)); } saveTo.Set(prefix + leftValueName, so.Bounds.Left.ToString(CultureInfo.InvariantCulture)); saveTo.Set(prefix + topValueName, so.Bounds.Top.ToString(CultureInfo.InvariantCulture)); saveTo.Set(prefix + widthValueName, so.Bounds.Width.ToString(CultureInfo.InvariantCulture)); saveTo.Set(prefix + heightValueName, so.Bounds.Height.ToString(CultureInfo.InvariantCulture)); }
private void SaveSnapObstacleData(ISimpleCollection <string, string> saveTo, SnapObstacle so) { string prefix = so.Name + "."; SnapDescription sd = this.obstacles[so]; bool isSnappedValue = (sd != null); saveTo.Set(prefix + isSnappedValueName, isSnappedValue.ToString(CultureInfo.InvariantCulture)); if (isSnappedValue) { saveTo.Set(prefix + snappedToValueName, sd.SnappedTo.Name); saveTo.Set(prefix + horizontalEdgeValueName, sd.HorizontalEdge.ToString()); saveTo.Set(prefix + verticalEdgeValueName, sd.VerticalEdge.ToString()); saveTo.Set(prefix + xOffsetValueName, sd.XOffset.ToString(CultureInfo.InvariantCulture)); saveTo.Set(prefix + yOffsetValueName, sd.YOffset.ToString(CultureInfo.InvariantCulture)); } saveTo.Set(prefix + leftValueName, so.Bounds.Left.ToString(CultureInfo.InvariantCulture)); saveTo.Set(prefix + topValueName, so.Bounds.Top.ToString(CultureInfo.InvariantCulture)); saveTo.Set(prefix + widthValueName, so.Bounds.Width.ToString(CultureInfo.InvariantCulture)); saveTo.Set(prefix + heightValueName, so.Bounds.Height.ToString(CultureInfo.InvariantCulture)); }
public Point AdjustObstacleDestination(SnapObstacle movingObstacle, Point newLocation, bool considerStickies) { Point adjustedLocation = newLocation; SnapDescription sd = this.obstacles[movingObstacle]; SnapDescription newSD = null; foreach (SnapObstacle avoidee in this.obstacles.Keys) { if (avoidee.StickyEdges != considerStickies) { continue; } if (avoidee.Enabled && !object.ReferenceEquals(avoidee, movingObstacle)) { SnapDescription newSD2 = DetermineNewSnapDescription(movingObstacle, adjustedLocation, avoidee, newSD); if (newSD2 != null) { Point adjustedLocation2 = AdjustNewLocation(movingObstacle, adjustedLocation, newSD2); newSD = newSD2; adjustedLocation = adjustedLocation2; Rectangle newBounds = new Rectangle(adjustedLocation, movingObstacle.Bounds.Size); } } } if (sd == null || !sd.SnappedTo.StickyEdges || newSD == null || newSD.SnappedTo.StickyEdges) { this.obstacles[movingObstacle] = newSD; } return adjustedLocation; }
private static Point AdjustNewLocation(SnapObstacle obstacle, Point newLocation, SnapDescription snapDescription) { if (snapDescription == null || (snapDescription.HorizontalEdge == HorizontalSnapEdge.Neither && snapDescription.VerticalEdge == VerticalSnapEdge.Neither)) { return(obstacle.Bounds.Location); } Rectangle obstacleRect = new Rectangle(newLocation, obstacle.Bounds.Size); Rectangle snappedToRect = snapDescription.SnappedTo.Bounds; HorizontalSnapEdge hEdge = snapDescription.HorizontalEdge; VerticalSnapEdge vEdge = snapDescription.VerticalEdge; SnapRegion region = snapDescription.SnappedTo.SnapRegion; int deltaY = 0; if (hEdge == HorizontalSnapEdge.Top && region == SnapRegion.Exterior) { int newBottomEdge = snappedToRect.Top - snapDescription.YOffset; deltaY = obstacleRect.Bottom - newBottomEdge; } else if (hEdge == HorizontalSnapEdge.Bottom && region == SnapRegion.Exterior) { int newTopEdge = snappedToRect.Bottom + snapDescription.YOffset; deltaY = obstacleRect.Top - newTopEdge; } else if (hEdge == HorizontalSnapEdge.Top && region == SnapRegion.Interior) { int newTopEdge = Math.Min(snappedToRect.Bottom, snappedToRect.Top + snapDescription.YOffset); deltaY = obstacleRect.Top - newTopEdge; } else if (hEdge == HorizontalSnapEdge.Bottom && region == SnapRegion.Interior) { int newBottomEdge = Math.Max(snappedToRect.Top, snappedToRect.Bottom - snapDescription.YOffset); deltaY = obstacleRect.Bottom - newBottomEdge; } int deltaX = 0; if (vEdge == VerticalSnapEdge.Left && region == SnapRegion.Exterior) { int newRightEdge = snappedToRect.Left - snapDescription.XOffset; deltaX = obstacleRect.Right - newRightEdge; } else if (vEdge == VerticalSnapEdge.Right && region == SnapRegion.Exterior) { int newLeftEdge = snappedToRect.Right + snapDescription.XOffset; deltaX = obstacleRect.Left - newLeftEdge; } else if (vEdge == VerticalSnapEdge.Left && region == SnapRegion.Interior) { int newLeftEdge = Math.Min(snappedToRect.Right, snappedToRect.Left + snapDescription.XOffset); deltaX = obstacleRect.Left - newLeftEdge; } else if (vEdge == VerticalSnapEdge.Right && region == SnapRegion.Interior) { int newRightEdge = Math.Max(snappedToRect.Left, snappedToRect.Right - snapDescription.XOffset); deltaX = obstacleRect.Right - newRightEdge; } Point adjustedLocation = new Point(obstacleRect.Left - deltaX, obstacleRect.Top - deltaY); return(adjustedLocation); }
public bool ContainsSnapObstacle(SnapObstacle snapObstacle) { return this.obstacles.ContainsKey(snapObstacle); }
private SnapDescription DetermineNewSnapDescription( SnapObstacle avoider, Point newLocation, SnapObstacle avoidee, SnapDescription currentSnapDescription) { int ourSnapProximity; if (currentSnapDescription != null && (currentSnapDescription.HorizontalEdge != HorizontalSnapEdge.Neither || currentSnapDescription.VerticalEdge != VerticalSnapEdge.Neither)) { // the avoider is already snapped to the avoidee -- make it more difficult to un-snap ourSnapProximity = avoidee.SnapProximity * 2; } else { ourSnapProximity = avoidee.SnapProximity; } Rectangle avoiderRect = avoider.Bounds; avoiderRect.Location = newLocation; Rectangle avoideeRect = avoidee.Bounds; // Are the vertical edges close enough for snapping? bool vertProximity = AreEdgesClose(avoiderRect.Top, avoiderRect.Bottom, avoideeRect.Top, avoideeRect.Bottom); // Are the horizontal edges close enough for snapping? bool horizProximity = AreEdgesClose(avoiderRect.Left, avoiderRect.Right, avoideeRect.Left, avoideeRect.Right); // Compute distances from pertinent edges // (e.g. if SnapRegion.Interior, figure out distance from avoider's right edge to avoidee's right edge, // if SnapRegion.Exterior, figure out distance from avoider's right edge to avoidee's left edge) int leftDistance; int rightDistance; int topDistance; int bottomDistance; switch (avoidee.SnapRegion) { case SnapRegion.Interior: leftDistance = Math.Abs(avoiderRect.Left - avoideeRect.Left); rightDistance = Math.Abs(avoiderRect.Right - avoideeRect.Right); topDistance = Math.Abs(avoiderRect.Top - avoideeRect.Top); bottomDistance = Math.Abs(avoiderRect.Bottom - avoideeRect.Bottom); break; case SnapRegion.Exterior: leftDistance = Math.Abs(avoiderRect.Left - avoideeRect.Right); rightDistance = Math.Abs(avoiderRect.Right - avoideeRect.Left); topDistance = Math.Abs(avoiderRect.Top - avoideeRect.Bottom); bottomDistance = Math.Abs(avoiderRect.Bottom - avoideeRect.Top); break; default: throw new InvalidEnumArgumentException("avoidee.SnapRegion"); } bool leftClose = (leftDistance < ourSnapProximity); bool rightClose = (rightDistance < ourSnapProximity); bool topClose = (topDistance < ourSnapProximity); bool bottomClose = (bottomDistance < ourSnapProximity); VerticalSnapEdge vEdge = VerticalSnapEdge.Neither; if (vertProximity) { if ((leftClose && avoidee.SnapRegion == SnapRegion.Exterior) || (rightClose && avoidee.SnapRegion == SnapRegion.Interior)) { vEdge = VerticalSnapEdge.Right; } else if ((rightClose && avoidee.SnapRegion == SnapRegion.Exterior) || (leftClose && avoidee.SnapRegion == SnapRegion.Interior)) { vEdge = VerticalSnapEdge.Left; } } HorizontalSnapEdge hEdge = HorizontalSnapEdge.Neither; if (horizProximity) { if ((topClose && avoidee.SnapRegion == SnapRegion.Exterior) || (bottomClose && avoidee.SnapRegion == SnapRegion.Interior)) { hEdge = HorizontalSnapEdge.Bottom; } else if ((bottomClose && avoidee.SnapRegion == SnapRegion.Exterior) || (topClose && avoidee.SnapRegion == SnapRegion.Interior)) { hEdge = HorizontalSnapEdge.Top; } } SnapDescription sd; if (hEdge != HorizontalSnapEdge.Neither || vEdge != VerticalSnapEdge.Neither) { int xOffset = avoider.SnapDistance; int yOffset = avoider.SnapDistance; if (hEdge == HorizontalSnapEdge.Neither) { if (avoidee.SnapRegion == SnapRegion.Interior) { yOffset = avoiderRect.Top - avoideeRect.Top; hEdge = HorizontalSnapEdge.Top; } } if (vEdge == VerticalSnapEdge.Neither) { if (avoidee.SnapRegion == SnapRegion.Interior) { xOffset = avoiderRect.Left - avoideeRect.Left; vEdge = VerticalSnapEdge.Left; } } sd = new SnapDescription(avoidee, hEdge, vEdge, xOffset, yOffset); } else { sd = null; } return(sd); }
public bool ContainsSnapObstacle(SnapObstacle snapObstacle) { return(this.obstacles.ContainsKey(snapObstacle)); }
private static Point AdjustNewLocation(SnapObstacle obstacle, Point newLocation, SnapDescription snapDescription) { if (snapDescription == null || (snapDescription.HorizontalEdge == HorizontalSnapEdge.Neither && snapDescription.VerticalEdge == VerticalSnapEdge.Neither)) { return obstacle.Bounds.Location; } Rectangle obstacleRect = new Rectangle(newLocation, obstacle.Bounds.Size); Rectangle snappedToRect = snapDescription.SnappedTo.Bounds; HorizontalSnapEdge hEdge = snapDescription.HorizontalEdge; VerticalSnapEdge vEdge = snapDescription.VerticalEdge; SnapRegion region = snapDescription.SnappedTo.SnapRegion; int deltaY = 0; if (hEdge == HorizontalSnapEdge.Top && region == SnapRegion.Exterior) { int newBottomEdge = snappedToRect.Top - snapDescription.YOffset; deltaY = obstacleRect.Bottom - newBottomEdge; } else if (hEdge == HorizontalSnapEdge.Bottom && region == SnapRegion.Exterior) { int newTopEdge = snappedToRect.Bottom + snapDescription.YOffset; deltaY = obstacleRect.Top - newTopEdge; } else if (hEdge == HorizontalSnapEdge.Top && region == SnapRegion.Interior) { int newTopEdge = Math.Min(snappedToRect.Bottom, snappedToRect.Top + snapDescription.YOffset); deltaY = obstacleRect.Top - newTopEdge; } else if (hEdge == HorizontalSnapEdge.Bottom && region == SnapRegion.Interior) { int newBottomEdge = Math.Max(snappedToRect.Top, snappedToRect.Bottom - snapDescription.YOffset); deltaY = obstacleRect.Bottom - newBottomEdge; } int deltaX = 0; if (vEdge == VerticalSnapEdge.Left && region == SnapRegion.Exterior) { int newRightEdge = snappedToRect.Left - snapDescription.XOffset; deltaX = obstacleRect.Right - newRightEdge; } else if (vEdge == VerticalSnapEdge.Right && region == SnapRegion.Exterior) { int newLeftEdge = snappedToRect.Right + snapDescription.XOffset; deltaX = obstacleRect.Left - newLeftEdge; } else if (vEdge == VerticalSnapEdge.Left && region == SnapRegion.Interior) { int newLeftEdge = Math.Min(snappedToRect.Right, snappedToRect.Left + snapDescription.XOffset); deltaX = obstacleRect.Left - newLeftEdge; } else if (vEdge == VerticalSnapEdge.Right && region == SnapRegion.Interior) { int newRightEdge = Math.Max(snappedToRect.Left, snappedToRect.Right - snapDescription.XOffset); deltaX = obstacleRect.Right - newRightEdge; } Point adjustedLocation = new Point(obstacleRect.Left - deltaX, obstacleRect.Top - deltaY); return adjustedLocation; }
private SnapDescription DetermineNewSnapDescription( SnapObstacle avoider, Point newLocation, SnapObstacle avoidee, SnapDescription currentSnapDescription) { int ourSnapProximity; if (currentSnapDescription != null && (currentSnapDescription.HorizontalEdge != HorizontalSnapEdge.Neither || currentSnapDescription.VerticalEdge != VerticalSnapEdge.Neither)) { // the avoider is already snapped to the avoidee -- make it more difficult to un-snap ourSnapProximity = avoidee.SnapProximity * 2; } else { ourSnapProximity = avoidee.SnapProximity; } Rectangle avoiderRect = avoider.Bounds; avoiderRect.Location = newLocation; Rectangle avoideeRect = avoidee.Bounds; // Are the vertical edges close enough for snapping? bool vertProximity = AreEdgesClose(avoiderRect.Top, avoiderRect.Bottom, avoideeRect.Top, avoideeRect.Bottom); // Are the horizontal edges close enough for snapping? bool horizProximity = AreEdgesClose(avoiderRect.Left, avoiderRect.Right, avoideeRect.Left, avoideeRect.Right); // Compute distances from pertinent edges // (e.g. if SnapRegion.Interior, figure out distance from avoider's right edge to avoidee's right edge, // if SnapRegion.Exterior, figure out distance from avoider's right edge to avoidee's left edge) int leftDistance; int rightDistance; int topDistance; int bottomDistance; switch (avoidee.SnapRegion) { case SnapRegion.Interior: leftDistance = Math.Abs(avoiderRect.Left - avoideeRect.Left); rightDistance = Math.Abs(avoiderRect.Right - avoideeRect.Right); topDistance = Math.Abs(avoiderRect.Top - avoideeRect.Top); bottomDistance = Math.Abs(avoiderRect.Bottom - avoideeRect.Bottom); break; case SnapRegion.Exterior: leftDistance = Math.Abs(avoiderRect.Left - avoideeRect.Right); rightDistance = Math.Abs(avoiderRect.Right - avoideeRect.Left); topDistance = Math.Abs(avoiderRect.Top - avoideeRect.Bottom); bottomDistance = Math.Abs(avoiderRect.Bottom - avoideeRect.Top); break; default: throw new InvalidEnumArgumentException("avoidee.SnapRegion"); } bool leftClose = (leftDistance < ourSnapProximity); bool rightClose = (rightDistance < ourSnapProximity); bool topClose = (topDistance < ourSnapProximity); bool bottomClose = (bottomDistance < ourSnapProximity); VerticalSnapEdge vEdge = VerticalSnapEdge.Neither; if (vertProximity) { if ((leftClose && avoidee.SnapRegion == SnapRegion.Exterior) || (rightClose && avoidee.SnapRegion == SnapRegion.Interior)) { vEdge = VerticalSnapEdge.Right; } else if ((rightClose && avoidee.SnapRegion == SnapRegion.Exterior) || (leftClose && avoidee.SnapRegion == SnapRegion.Interior)) { vEdge = VerticalSnapEdge.Left; } } HorizontalSnapEdge hEdge = HorizontalSnapEdge.Neither; if (horizProximity) { if ((topClose && avoidee.SnapRegion == SnapRegion.Exterior) || (bottomClose && avoidee.SnapRegion == SnapRegion.Interior)) { hEdge = HorizontalSnapEdge.Bottom; } else if ((bottomClose && avoidee.SnapRegion == SnapRegion.Exterior) || (topClose && avoidee.SnapRegion == SnapRegion.Interior)) { hEdge = HorizontalSnapEdge.Top; } } SnapDescription sd; if (hEdge != HorizontalSnapEdge.Neither || vEdge != VerticalSnapEdge.Neither) { int xOffset = avoider.SnapDistance; int yOffset = avoider.SnapDistance; if (hEdge == HorizontalSnapEdge.Neither) { if (avoidee.SnapRegion == SnapRegion.Interior) { yOffset = avoiderRect.Top - avoideeRect.Top; hEdge = HorizontalSnapEdge.Top; } } if (vEdge == VerticalSnapEdge.Neither) { if (avoidee.SnapRegion == SnapRegion.Interior) { xOffset = avoiderRect.Left - avoideeRect.Left; vEdge = VerticalSnapEdge.Left; } } sd = new SnapDescription(avoidee, hEdge, vEdge, xOffset, yOffset); } else { sd = null; } return sd; }
/// <summary> /// Given an obstacle and its attempted destination, determines the correct landing /// spot for an obstacle. /// </summary> /// <param name="movingObstacle">The obstacle that is moving.</param> /// <param name="newLocation">The upper-left coordinate of the obstacle's original intended destination.</param> /// <returns> /// A Point that determines where the obstacle should be placed instead. If there are no adjustments /// required to the obstacle's desintation, then the return value will be equal to newLocation. /// </returns> /// <remarks> /// movingObstacle's SnapDescription will also be updated. The caller of this method is required /// to update the SnapObstacle with the new, adjusted location. /// </remarks> public Point AdjustObstacleDestination(SnapObstacle movingObstacle, Point newLocation) { Point adjusted1 = AdjustObstacleDestination(movingObstacle, newLocation, false); Point adjusted2 = AdjustObstacleDestination(movingObstacle, adjusted1, true); return adjusted2; }
public void Load(ISimpleCollection<string, string> loadFrom) { SnapObstacle[] newObstacles = new SnapObstacle[this.obstacles.Count]; this.obstacles.Keys.CopyTo(newObstacles, 0); foreach (SnapObstacle obstacle in newObstacles) { if (obstacle.EnableSave) { LoadSnapObstacleData(loadFrom, obstacle); } } }