/// <summary> /// Removes all the connections from this shape to others. Also removes /// connections from substroke endpoints, if there are any. /// /// Preconditions: /// - For every shape "s" in ConnectedShapes, s.ConnectedShapes /// contains this shape. /// /// Postconditions: /// - For every shape "s" in the old ConnectedShapes, s.ConnectedShapes /// does not contain this shape and there is no endpoint in /// s.Endpoints connected to this shape. /// - ConnectedShapes is empty /// - for every endpoint of every substroke, ConnectedShape is null /// </summary> public void ClearConnections() { foreach (Shape s in ConnectedShapes) { /* NOTE: shapes are allowed to be connected to themselves. * If this is the case, then the connection will be removed * below when we call ConnectedShapes.Clear(). Removing this * if-check can cause the ConnectedShapes collection to be * modified in the middle of this loop when s == this, * causing an InvalidOperationException. */ if (s != this) { s.ConnectedShapes.Remove(this); } // Remove endpoint connections referencing this shape foreach (EndPoint endpoint in s.Endpoints) { if (endpoint.ConnectedShape == this) { endpoint.ConnectedShape = null; } } } ConnectedShapes.Clear(); foreach (Substroke substroke in Substrokes) { foreach (EndPoint endpoint in substroke.Endpoints) { endpoint.ConnectedShape = null; } } }
/// <summary> /// Called when a substroke is added to this shape, and before it is added /// to the list of substrokes. By default this does the following: /// - updates the substroke's parent shape /// - connects this shape to everything the substroke is connected to /// </summary> /// <param name="substroke">the substroke to acquire</param> protected virtual void AcquireSubstroke(Substroke substroke) { if (substroke.ParentShape != null && substroke.ParentShape != this) { throw new ArgumentException("Cannot add a substroke belonging to a different shape!"); } substroke.ParentShape = this; foreach (EndPoint endpoint in substroke.Endpoints) { Shape connected = endpoint.ConnectedShape; if (connected != null) { ConnectedShapes.Add(connected); connected.ConnectedShapes.Add(this); } } }
/// <summary> /// Disconnect two shapes. /// /// Note that this.disconnectFrom(shape) should be equivalent to /// shape.disconnectFrom(this). /// </summary> /// <param name="other"></param> public void disconnectFrom(Shape other) { ConnectedShapes.Remove(other); other.ConnectedShapes.Remove(this); foreach (EndPoint endpoint in Endpoints) { if (endpoint.ConnectedShape == other) { endpoint.ConnectedShape = null; } } foreach (EndPoint endpoint in other.Endpoints) { if (endpoint.ConnectedShape == this) { endpoint.ConnectedShape = null; } } }