//Calls the Line routing algorithm and populates the points collection of the connector. void RoutePolyLine(Connector connector) { Point[] pts = ConnectorRouter.Route(this, FreeFormPanel.GetSourceConnectionPoint(connector), FreeFormPanel.GetDestinationConnectionPoint(connector)); List <Point> points = new List <Point>(pts); if (pts != null) { UpdateConnectorPoints(connector, points); } }
// referenceConnector is used when we are re-linking the connector. internal ConnectorCreationResult CreateConnectorGesture(ConnectionPoint sourceConnectionPoint, ConnectionPoint destConnectionPoint, Connector referenceConnector, bool isConnectorStartMoved) { Fx.Assert(sourceConnectionPoint != null, "sourceConnectionPoint is null."); Fx.Assert(destConnectionPoint != null, "destConnectionPoint is null."); ConnectorCreationResult result = ConnectorCreationResult.OtherFailure; if (destConnectionPoint.PointType != ConnectionPointKind.Outgoing && sourceConnectionPoint.PointType != ConnectionPointKind.Incoming) { if (sourceConnectionPoint.ParentDesigner is VirtualizedContainerService.VirtualizingContainer) { //bool sameDestination = false; ModelItem refTransitionModelItem = null; if (referenceConnector != null) { refTransitionModelItem = StateContainerEditor.GetConnectorModelItem(referenceConnector); } using (EditingScope es = (EditingScope)this.ModelItem.BeginEdit(SR.CreateTransition)) { if (refTransitionModelItem != null) { this.CreateTransition(sourceConnectionPoint, destConnectionPoint, refTransitionModelItem, isConnectorStartMoved); } else { this.CreateTransition(sourceConnectionPoint, destConnectionPoint, null, false); } result = ConnectorCreationResult.Success; es.Complete(); } } else if (sourceConnectionPoint.ParentDesigner is StartSymbol) { ModelItem stateModelItem = ((VirtualizedContainerService.VirtualizingContainer)destConnectionPoint.ParentDesigner).ModelItem; if (IsFinalState(stateModelItem)) { result = ConnectorCreationResult.CannotSetFinalStateAsInitialState; } else { using (EditingScope es = (EditingScope)this.ModelItem.BeginEdit(SR.SetInitialState)) { this.StateMachineModelItem.Properties[StateMachineDesigner.InitialStatePropertyName].SetValue(stateModelItem); PointCollection connectorViewState = new PointCollection(ConnectorRouter.Route(this.panel, sourceConnectionPoint, destConnectionPoint)); this.StoreConnectorLocationViewState(this.StateMachineModelItem, connectorViewState, true); result = ConnectorCreationResult.Success; es.Complete(); } } } } return(result); }
void RerouteIfInvalid(Connector connector, ModelItem linkModelItem) { if (connector.Points != null) { Point[] points = new Point[connector.Points.Count]; connector.Points.CopyTo(points, 0); if (!ConnectorRouter.AreSegmentsValid(points)) { Reroute(connector, false); } } }
void UpdateEditPoints(Point newPoint) { if (this.editPoints.Count < 2 || this.editPoints[0].Type != EditPoint.EditPointTypes.ConnectionEditPoint || this.editPoints[this.editPoints.Count - 1].Type != EditPoint.EditPointTypes.ConnectionEditPoint) { Debug.Assert(false, "EditPoints are invalid"); return; } if (this.activeEditPoint != null) { int activeEditPointIndex = this.editPoints.IndexOf(this.activeEditPoint); EditPoint previous = (activeEditPointIndex > 0) ? this.editPoints[activeEditPointIndex - 1] : null; EditPoint next = (activeEditPointIndex < this.editPoints.Count - 1) ? this.editPoints[activeEditPointIndex + 1] : null; //Note that extra edit points are only added if we are connected to connection point if (previous != null && previous.Type == EditPoint.EditPointTypes.ConnectionEditPoint) { double slopeOfLine = DesignerGeometryHelper.SlopeOfLineSegment(previous.Location, this.activeEditPoint.Location); Orientation orientation = (Math.Abs(slopeOfLine) < 1) ? Orientation.Horizontal : Orientation.Vertical; int editPointOffset = Convert.ToInt32(DesignerGeometryHelper.DistanceBetweenPoints(previous.Location, (next != null) ? next.Location : this.activeEditPoint.Location)) / 4; if (orientation == Orientation.Horizontal) { editPointOffset *= (previous.Location.X < this.activeEditPoint.Location.X) ? 1 : -1; } else { editPointOffset *= (previous.Location.Y < this.activeEditPoint.Location.Y) ? 1 : -1; } activeEditPointIndex = this.editPoints.IndexOf(this.activeEditPoint); Point editPointLocation = (orientation == Orientation.Horizontal) ? new Point(previous.Location.X + editPointOffset, previous.Location.Y) : new Point(previous.Location.X, previous.Location.Y + editPointOffset); previous = new EditPoint(EditPoint.EditPointTypes.MultiSegmentEditPoint, editPointLocation); this.editPoints.InsertRange(activeEditPointIndex, new EditPoint[] { new EditPoint(EditPoint.EditPointTypes.MultiSegmentEditPoint, editPointLocation), previous }); } if (next != null && next.Type == EditPoint.EditPointTypes.ConnectionEditPoint) { double slopeOfLine = DesignerGeometryHelper.SlopeOfLineSegment(this.activeEditPoint.Location, next.Location); Orientation orientation = (Math.Abs(slopeOfLine) < 1) ? Orientation.Horizontal : Orientation.Vertical; int editPointOffset = Convert.ToInt32(DesignerGeometryHelper.DistanceBetweenPoints((previous != null) ? previous.Location : this.activeEditPoint.Location, next.Location)) / 4; if (orientation == Orientation.Horizontal) { editPointOffset *= (this.activeEditPoint.Location.X < next.Location.X) ? -1 : 1; } else { editPointOffset *= (this.activeEditPoint.Location.Y < next.Location.Y) ? -1 : 1; } activeEditPointIndex = this.editPoints.IndexOf(this.activeEditPoint); Point editPointLocation = (orientation == Orientation.Horizontal) ? new Point(next.Location.X + editPointOffset, next.Location.Y) : new Point(next.Location.X, next.Location.Y + editPointOffset); next = new EditPoint(EditPoint.EditPointTypes.MultiSegmentEditPoint, editPointLocation); this.editPoints.InsertRange(activeEditPointIndex + 1, new EditPoint[] { next, new EditPoint(EditPoint.EditPointTypes.MultiSegmentEditPoint, editPointLocation) }); } if (this.activeEditPoint.Type == EditPoint.EditPointTypes.ConnectionEditPoint) { Debug.Assert(this.editPoints[0].Type == EditPoint.EditPointTypes.ConnectionEditPoint, "EditPoint type is wrong."); Debug.Assert(this.editPoints[editPoints.Count - 1].Type == EditPoint.EditPointTypes.ConnectionEditPoint, "EditPoint type is wrong."); this.activeEditPoint.Location = newPoint; Point begin, end; Debug.Assert(this.editPoints.Count > 0, "Some edit point should exist"); begin = this.editPoints[0].Location; end = this.editPoints[this.editPoints.Count - 1].Location; //When we start editing the end point we need to clear the slate and start over List <EditPoint> newEditPoints = new List <EditPoint>(); Point[] points = ConnectorRouter.Route(parentPanel, begin, end); if (points != null && points.Length > 1) { RemoveEditPoints(EditPoint.EditPointTypes.MultiSegmentEditPoint); for (int i = 1; i < points.Length - 1; ++i) { newEditPoints.Add(new EditPoint(EditPoint.EditPointTypes.MultiSegmentEditPoint, points[i])); } this.editPoints.InsertRange(1, newEditPoints.ToArray()); } } else if (this.activeEditPoint.Type == EditPoint.EditPointTypes.MultiSegmentEditPoint) { if (previous != null && previous.Type != EditPoint.EditPointTypes.ConnectionEditPoint && next != null && next.Type != EditPoint.EditPointTypes.ConnectionEditPoint) { //Update the previous point double slopeOfLine = DesignerGeometryHelper.SlopeOfLineSegment(previous.Location, this.activeEditPoint.Location); Orientation orientation = (Math.Abs(slopeOfLine) < 1) ? Orientation.Horizontal : Orientation.Vertical; previous.Location = (orientation == Orientation.Horizontal) ? new Point(previous.Location.X, newPoint.Y) : new Point(newPoint.X, previous.Location.Y); //Update the next point slopeOfLine = DesignerGeometryHelper.SlopeOfLineSegment(this.activeEditPoint.Location, next.Location); orientation = (Math.Abs(slopeOfLine) < 1) ? Orientation.Horizontal : Orientation.Vertical; next.Location = (orientation == Orientation.Horizontal) ? new Point(next.Location.X, newPoint.Y) : new Point(newPoint.X, next.Location.Y); //Update the current point this.activeEditPoint.Location = newPoint; } else { Debug.Assert(false, "Should not be here. UpdateEditPoints failed."); } } } // Remove all the redundant edit points RemoveCoincidingEditPoints(); bool validEditPoints = ValidateEditPoints(); Debug.Assert(validEditPoints, "Validating EditPoints failed."); }
// referenceTransitionModelItem is used when a connector is re-linked. void CreateTransition(ConnectionPoint sourceConnPoint, ConnectionPoint destConnPoint, ModelItem referenceTransitionModelItem, bool isSourceMoved) { VirtualizedContainerService.VirtualizingContainer srcDesigner = sourceConnPoint.ParentDesigner as VirtualizedContainerService.VirtualizingContainer; Fx.Assert(srcDesigner != null, "srcDesigner should not be null."); VirtualizedContainerService.VirtualizingContainer destDesigner = destConnPoint.ParentDesigner as VirtualizedContainerService.VirtualizingContainer; Fx.Assert(destDesigner != null, "destDesigner should not be null."); ModelItem srcModelItem = srcDesigner.ModelItem; ModelItem destModelItem = destDesigner.ModelItem; ModelItem transitionModelItem = null; // We are moving the connector. if (referenceTransitionModelItem != null && referenceTransitionModelItem.ItemType == typeof(Transition)) { transitionModelItem = referenceTransitionModelItem; // We are moving the start of the connector. We only preserve the trigger if it is not shared. if (isSourceMoved) { Transition referenceTransition = referenceTransitionModelItem.GetCurrentValue() as Transition; ModelItem stateModelItem = GetParentStateModelItemForTransition(referenceTransitionModelItem); State state = stateModelItem.GetCurrentValue() as State; bool isTriggerShared = false; foreach (Transition transition in state.Transitions) { if (transition != referenceTransition && transition.Trigger == referenceTransition.Trigger) { isTriggerShared = true; break; } } if (isTriggerShared) { transitionModelItem.Properties[TransitionDesigner.TriggerPropertyName].SetValue(null); } } transitionModelItem.Properties[TransitionDesigner.ToPropertyName].SetValue(destModelItem); srcModelItem.Properties[StateDesigner.TransitionsPropertyName].Collection.Add(transitionModelItem); } // We are creating a new connector. else { ModelItem stateMachineModelItem = GetStateMachineModelItem(srcModelItem); Transition newTransition = new Transition() { DisplayName = StateContainerEditor.GenerateTransitionName(stateMachineModelItem) }; newTransition.To = destModelItem.GetCurrentValue() as State; // Assign the shared trigger. if (sourceConnPoint.AttachedConnectors.Count > 0) { Connector connector = sourceConnPoint.AttachedConnectors[0]; Transition existingTransition = StateContainerEditor.GetConnectorModelItem(connector).GetCurrentValue() as Transition; newTransition.Trigger = existingTransition.Trigger; } transitionModelItem = srcModelItem.Properties[StateDesigner.TransitionsPropertyName].Collection.Add(newTransition); } if (transitionModelItem != null) { // if the transition connection is re-routed, the SrcConnPointIndex needs to be updated. PointCollection connectorViewState = new PointCollection(ConnectorRouter.Route(this.panel, sourceConnPoint, destConnPoint)); int srcConnectionPointIndex = StateContainerEditor.GetConnectionPoints(sourceConnPoint.ParentDesigner).IndexOf(sourceConnPoint); int destConnectionPointIndex = StateContainerEditor.GetConnectionPoints(destConnPoint.ParentDesigner).IndexOf(destConnPoint); this.StoreConnectorLocationViewState(transitionModelItem, connectorViewState, true); this.ViewStateService.StoreViewStateWithUndo(transitionModelItem, SrcConnectionPointIndexStateKey, srcConnectionPointIndex); this.ViewStateService.StoreViewStateWithUndo(transitionModelItem, DestConnectionPointIndexStateKey, destConnectionPointIndex); } }
// referenceTransitionModelItem is used when a connector is re-linked. void CreateTransition(ConnectionPoint sourceConnPoint, ConnectionPoint destConnPoint, ModelItem referenceTransitionModelItem, bool isSourceMoved) { Debug.Assert(this.IsOutmostStateContainerEditor(), "Should only be called by the outmost editor."); WorkflowViewElement srcDesigner = sourceConnPoint.ParentDesigner as WorkflowViewElement; WorkflowViewElement destDesigner = destConnPoint.ParentDesigner as WorkflowViewElement; Debug.Assert(srcDesigner is StateDesigner && destDesigner is StateDesigner, "The source and destination designers should both be StateDesigner"); ModelItem srcModelItem = srcDesigner.ModelItem; ModelItem destModelItem = destDesigner.ModelItem; ModelItem transitionModelItem = null; // We are moving the connector. if (referenceTransitionModelItem != null && referenceTransitionModelItem.ItemType == typeof(Transition)) { transitionModelItem = referenceTransitionModelItem; // We are moving the start of the connector. We only preserve the trigger if it is not shared. if (isSourceMoved) { Transition referenceTransition = referenceTransitionModelItem.GetCurrentValue() as Transition; ModelItem stateModelItem = GetParentStateModelItemForTransition(referenceTransitionModelItem); State state = stateModelItem.GetCurrentValue() as State; bool isTriggerShared = false; foreach (Transition transition in state.Transitions) { if (transition != referenceTransition && transition.Trigger == referenceTransition.Trigger) { isTriggerShared = true; break; } } if (isTriggerShared) { transitionModelItem.Properties[TransitionDesigner.TriggerPropertyName].SetValue(null); } } transitionModelItem.Properties[TransitionDesigner.ToPropertyName].SetValue(destModelItem); srcModelItem.Properties[StateDesigner.TransitionsPropertyName].Collection.Add(transitionModelItem); } // We are creating a new connector. else { Transition newTransition = new Transition() { DisplayName = string.Empty }; newTransition.To = destModelItem.GetCurrentValue() as State; // Assign the shared trigger. if (sourceConnPoint.AttachedConnectors.Count > 0) { Connector connector = sourceConnPoint.AttachedConnectors[0]; Transition existingTransition = StateContainerEditor.GetConnectorModelItem(connector).GetCurrentValue() as Transition; newTransition.Trigger = existingTransition.Trigger; } transitionModelItem = srcModelItem.Properties[StateDesigner.TransitionsPropertyName].Collection.Add(newTransition); } if (transitionModelItem != null) { PointCollection connectorViewState = new PointCollection(ConnectorRouter.Route(this.panel, sourceConnPoint, destConnPoint)); this.StoreConnectorLocationViewState(transitionModelItem, connectorViewState, true); } }
// referenceConnector is used when we are re-linking the connector. internal ConnectorCreationResult CreateConnectorGesture(ConnectionPoint sourceConnectionPoint, ConnectionPoint destConnectionPoint, Connector referenceConnector, bool isConnectorStartMoved) { Debug.Assert(this.IsOutmostStateContainerEditor(), "Should only be called by the outmost editor."); Debug.Assert(sourceConnectionPoint != null, "sourceConnectionPoint is null."); Debug.Assert(destConnectionPoint != null, "destConnectionPoint is null."); ConnectorCreationResult result = ConnectorCreationResult.OtherFailure; if (destConnectionPoint.PointType != ConnectionPointType.Outgoing && sourceConnectionPoint.PointType != ConnectionPointType.Incoming) { if (sourceConnectionPoint.ParentDesigner is StateDesigner) { bool sameDestination = false; ModelItem refTransitionModelItem = null; if (referenceConnector != null) { refTransitionModelItem = StateContainerEditor.GetConnectorModelItem(referenceConnector); ModelItem destStateModelItem = ((StateDesigner)destConnectionPoint.ParentDesigner).ModelItem; if (refTransitionModelItem != null && refTransitionModelItem.Properties[TransitionDesigner.ToPropertyName].Value == destStateModelItem) { sameDestination = true; } } // We do not allow transitions to composite states unless we don't change the transition destination // (e.g., we are moving the start of a connector). if (!sameDestination && !((StateDesigner)destConnectionPoint.ParentDesigner).IsSimpleState()) { result = ConnectorCreationResult.CannotCreateTransitionToCompositeState; } // We do not allow transitions from an ancestor to its descendant else if (StateContainerEditor.IsDescendantStateOf(((StateDesigner)destConnectionPoint.ParentDesigner).ModelItem, ((StateDesigner)sourceConnectionPoint.ParentDesigner).ModelItem)) { result = ConnectorCreationResult.CannotCreateTransitionFromAncestorToDescendant; } else { using (EditingScope es = (EditingScope)this.ModelItem.BeginEdit(SR.CreateTransition)) { if (refTransitionModelItem != null) { this.CreateTransition(sourceConnectionPoint, destConnectionPoint, refTransitionModelItem, isConnectorStartMoved); } else { this.CreateTransition(sourceConnectionPoint, destConnectionPoint, null, false); } result = ConnectorCreationResult.Success; es.Complete(); } } } else if (sourceConnectionPoint.ParentDesigner is InitialNode) { StateDesigner destDesigner = (StateDesigner)destConnectionPoint.ParentDesigner; // We only allow simple states to be set as the initial state if (!destDesigner.IsSimpleState()) { result = ConnectorCreationResult.CannotSetCompositeStateAsInitialState; } else if (destDesigner.IsFinalState()) { result = ConnectorCreationResult.CannotSetFinalStateAsInitialState; } else { ModelItem destModelItem = destDesigner.ModelItem; using (EditingScope es = (EditingScope)this.ModelItem.BeginEdit(SR.SetInitialState)) { this.StateMachineModelItem.Properties[StateMachineDesigner.InitialStatePropertyName].SetValue(destModelItem); PointCollection connectorViewState = new PointCollection(ConnectorRouter.Route(this.panel, sourceConnectionPoint, destConnectionPoint)); this.StoreConnectorLocationViewState(this.StateMachineModelItem, connectorViewState, true); result = ConnectorCreationResult.Success; es.Complete(); } } } } return(result); }
bool UpdateFlowChartObject(ConnectionPoint sourceConnPoint, ConnectionPoint destConnPoint, out string errorMessage, bool isLinkValidDueToLinkMove, IFlowSwitchLink caseKey) { //srcDesigner will be null for the case where source designer is StartSymbol. VirtualizedContainerService.VirtualizingContainer srcDesigner = sourceConnPoint.ParentDesigner as VirtualizedContainerService.VirtualizingContainer; VirtualizedContainerService.VirtualizingContainer destDesigner = destConnPoint.ParentDesigner as VirtualizedContainerService.VirtualizingContainer; ModelItem linkSource; ModelItem linkDest = destDesigner.ModelItem; ModelItem destFlowElementMI = GetFlowElementMI(linkDest); PointCollection connectorViewState = new PointCollection(ConnectorRouter.Route(this.panel, sourceConnPoint, destConnPoint)); errorMessage = string.Empty; if (sourceConnPoint.ParentDesigner is StartSymbol) { linkSource = this.ModelItem; if (linkSource.Properties["StartNode"].Value == null || isLinkValidDueToLinkMove) { this.StoreConnectorViewState(linkSource, connectorViewState, sourceConnPoint); linkSource.Properties["StartNode"].SetValue(destFlowElementMI); } else { errorMessage = SR.FCNextLinkDefined; } } else { linkSource = srcDesigner.ModelItem; ModelItem srcFlowElementMI = GetFlowElementMI(linkSource); if (typeof(FlowStep).IsAssignableFrom(srcFlowElementMI.ItemType)) { if (srcFlowElementMI.Properties["Next"].Value == null || isLinkValidDueToLinkMove) { this.StoreConnectorViewState(srcFlowElementMI, connectorViewState, sourceConnPoint); srcFlowElementMI.Properties["Next"].SetValue(destFlowElementMI); } else { errorMessage = SR.FCNextLinkDefined; } } else if (typeof(FlowDecision).IsAssignableFrom(srcFlowElementMI.ItemType)) { if (sourceConnPoint.Equals(FlowchartDesigner.GetTrueConnectionPoint(this.modelElement[linkSource]))) { if (linkSource.Properties["True"].Value == null || isLinkValidDueToLinkMove) { this.StoreConnectorViewState(srcFlowElementMI, connectorViewState, sourceConnPoint); linkSource.Properties["True"].SetValue(destFlowElementMI); } else { errorMessage = SR.FCTrueBranchExists; } } else if (sourceConnPoint.Equals(FlowchartDesigner.GetFalseConnectionPoint(this.modelElement[linkSource]))) { if (linkSource.Properties["False"].Value == null || isLinkValidDueToLinkMove) { this.StoreConnectorViewState(srcFlowElementMI, connectorViewState, sourceConnPoint); linkSource.Properties["False"].SetValue(destFlowElementMI); } else { errorMessage = SR.FCFalseBranchExists; } } else { errorMessage = SR.FCFlowConditionLinkError; } } else //FlowSwitch { if (!CreateFlowSwitchLink(sourceConnPoint, srcFlowElementMI, destFlowElementMI, caseKey, connectorViewState, ref errorMessage)) { return(false); } } } return(errorMessage.Equals(string.Empty)); }