void StoreConnectorLocationViewState(Connector connector, bool isUndoableViewState)
 {
     //This method will be called whenever the FreeFormPanel raises a location changed event on a connector.
     //Such location changed events are a result of changes already committed in the UI. Hence we do not want to react to such view state changes.
     //Using internalViewStateChange flag for that purpose.
     this.internalViewStateChange = true;
     this.StoreConnectorLocationViewState(StateContainerEditor.GetConnectorModelItem(connector), connector.Points, isUndoableViewState);
     this.internalViewStateChange = false;
 }
        // 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);
        }
        internal int DeleteConnectorModelItem(Connector connector, bool rerouting = false)
        {
            ModelItem connectorModelItem = StateContainerEditor.GetConnectorModelItem(connector);

            if (!rerouting)
            {
                if (connector is ConnectorWithStartDot)
                {
                    connector.StartDot.MouseDown -= new MouseButtonEventHandler(OnConnectorStartDotMouseDown);
                    connector.StartDot.MouseUp   -= new MouseButtonEventHandler(OnConnectorStartDotMouseUp);
                }

                connector.GotKeyboardFocus     -= new KeyboardFocusChangedEventHandler(OnConnectorGotKeyboardFocus);
                connector.RequestBringIntoView -= new RequestBringIntoViewEventHandler(OnConnectorRequestBringIntoView);
                connector.GotFocus             -= new RoutedEventHandler(OnConnectorGotFocus);
                connector.MouseDoubleClick     -= new MouseButtonEventHandler(OnConnectorMouseDoubleClick);
                connector.MouseDown            -= new MouseButtonEventHandler(OnConnectorMouseDown);
                connector.KeyDown            -= new KeyEventHandler(OnConnectorKeyDown);
                connector.ContextMenuOpening -= new ContextMenuEventHandler(OnConnectorContextMenuOpening);
                connector.Unloaded           -= new RoutedEventHandler(OnConnectorUnloaded);
            }

            int removedIndex = InvalidIndex;

            if (connectorModelItem.ItemType == typeof(Transition))
            {
                ModelItemCollection transitions = StateContainerEditor.GetParentStateModelItemForTransition(connectorModelItem).Properties[StateDesigner.TransitionsPropertyName].Collection;
                removedIndex = transitions.IndexOf(connectorModelItem);
                Fx.Assert(removedIndex >= 0, "can't find the connector ModelItem in collection");
                transitions.Remove(connectorModelItem);
            }
            // Connector from initial node
            else if (connectorModelItem.ItemType == typeof(StateMachine))
            {
                using (EditingScope es = (EditingScope)this.ModelItem.BeginEdit(SR.ClearInitialState))
                {
                    connectorModelItem.Properties[StateMachineDesigner.InitialStatePropertyName].SetValue(null);
                    if (!rerouting)
                    {
                        this.ViewStateService.StoreViewStateWithUndo(connectorModelItem, ConnectorLocationViewStateKey, null);
                    }
                    es.Complete();
                }
            }
            return(removedIndex);
        }
        static ConnectionPoint GetSrcConnectionPointForSharedTrigger(UIElement sourceDesigner, ModelItem connectorModelItem)
        {
            ConnectionPoint  sourceConnectionPoint = null;
            List <Connector> connectors            = StateContainerEditor.GetOutgoingConnectors(sourceDesigner);

            foreach (Connector connector in connectors)
            {
                ModelItem modelItem = StateContainerEditor.GetConnectorModelItem(connector);
                if (modelItem != null && modelItem.ItemType == typeof(Transition))
                {
                    if (modelItem.Properties[TransitionDesigner.TriggerPropertyName].Value == connectorModelItem.Properties[TransitionDesigner.TriggerPropertyName].Value)
                    {
                        sourceConnectionPoint = FreeFormPanel.GetSourceConnectionPoint(connector);
                    }
                }
            }
            return(sourceConnectionPoint);
        }
        // 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);
            }
        }
        void DoDeleteItems(List <ModelItem> itemsToDelete, bool removeIncomingConnectors)
        {
            itemsToDelete.Remove(this.initialModelItem);

            if (itemsToDelete.Count == 1 && itemsToDelete.First().ItemType == typeof(Transition))
            {
                this.DeleteConnectorModelItem(this.selectedConnector);
                return;
            }

            itemsToDelete.RemoveAll(item => item.ItemType == typeof(Transition));

            HashSet <Connector>     connectorsToDelete         = new HashSet <Connector>();
            List <ModelItem>        allStateModelItemsToDelete = new List <ModelItem>();
            IEnumerable <ModelItem> selectedStateModelItems    = this.Context.Items.GetValue <Selection>().SelectedObjects
                                                                 .Where <ModelItem>((p) => { return(p.ItemType == typeof(State)); });

            foreach (ModelItem stateModelItem in itemsToDelete)
            {
                allStateModelItemsToDelete.Add(stateModelItem);
            }

            foreach (ModelItem modelItem in allStateModelItemsToDelete)
            {
                // We only need to delete incoming connectors to the states to be deleted; outgoing connectors will be deleted
                // automatically when the containing state is deleted.
                List <Connector> incomingConnectors = StateContainerEditor.GetIncomingConnectors(GetStateView(modelItem));
                foreach (Connector connector in incomingConnectors)
                {
                    ModelItem transitionModelItem = StateContainerEditor.GetConnectorModelItem(connector);
                    // If the transition is contained by the states to delete, we don't bother to delete it separately.
                    if (!StateContainerEditor.IsTransitionModelItemContainedByStateModelItems(transitionModelItem, selectedStateModelItems))
                    {
                        connectorsToDelete.Add(connector);
                    }
                }
            }

            // If we don't need to remove incoming connectors, we still remove the transitions but then add them back later.
            // This is in order to create an undo unit that contains the change notifications needed to make undo/redo work correctly.
            foreach (Connector connector in connectorsToDelete)
            {
                ModelItem connectorModelItem = StateContainerEditor.GetConnectorModelItem(connector);
                if (removeIncomingConnectors || connectorModelItem.ItemType == typeof(Transition))
                {
                    this.DeleteConnectorModelItem(connector);
                }
            }
            if (!removeIncomingConnectors)
            {
                foreach (Connector connector in connectorsToDelete)
                {
                    ModelItem connectorModelItem = StateContainerEditor.GetConnectorModelItem(connector);
                    if (connectorModelItem.ItemType == typeof(Transition))
                    {
                        StateContainerEditor.GetParentStateModelItemForTransition(connectorModelItem).Properties[StateDesigner.TransitionsPropertyName].Collection.Add(connectorModelItem);
                    }
                }
            }

            if (null != itemsToDelete)
            {
                itemsToDelete.ForEach(p => this.DeleteState(p, removeIncomingConnectors));
            }
        }