void DoDeleteItems(List <ModelItem> itemsToDelete, bool removeIncomingConnectors)
        {
            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);
                allStateModelItemsToDelete.AddRange(GetAllChildStateModelItems(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((UIElement)modelItem.View);
                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));
            }
        }
Ejemplo n.º 2
0
 public TransitionDesigner()
 {
     InitializeComponent();
     this.Loaded += (sender, e) =>
     {
         this.ModelItem.PropertyChanged += OnModelItemPropertyChanged;
         this.transitionsSharingTrigger.Clear();
         ModelItem parentStateModelItem = StateContainerEditor.GetParentStateModelItemForTransition(this.ModelItem);
         ModelItem triggerModelItem     = this.ModelItem.Properties[TriggerPropertyName].Value;
         if (triggerModelItem != null)
         {
             foreach (ModelItem transitionModelItem in parentStateModelItem.Properties[StateDesigner.TransitionsPropertyName].Collection)
             {
                 if (transitionModelItem != this.ModelItem)
                 {
                     if (triggerModelItem == transitionModelItem.Properties[TriggerPropertyName].Value)
                     {
                         this.transitionsSharingTrigger.Add(transitionModelItem);
                     }
                 }
             }
         }
         // Connectors starting from the same point should share the same trigger
         else
         {
             PointCollection thisPointCollection = this.ViewStateService.RetrieveViewState(this.ModelItem, StateContainerEditor.ConnectorLocationViewStateKey) as PointCollection;
             if (thisPointCollection != null && thisPointCollection.Count > 1)
             {
                 foreach (ModelItem transitionModelItem in parentStateModelItem.Properties[StateDesigner.TransitionsPropertyName].Collection)
                 {
                     if (transitionModelItem != this.ModelItem)
                     {
                         PointCollection pointCollection = this.ViewStateService.RetrieveViewState(transitionModelItem, StateContainerEditor.ConnectorLocationViewStateKey) as PointCollection;
                         if (pointCollection != null && pointCollection.Count > 1)
                         {
                             if (pointCollection[0].IsEqualTo(thisPointCollection[0]))
                             {
                                 Debug.Assert(transitionModelItem.Properties[TriggerPropertyName].Value == null, "Transition trigger should be null.");
                                 this.transitionsSharingTrigger.Add(transitionModelItem);
                             }
                         }
                     }
                 }
             }
         }
         if (this.transitionsSharingTrigger.Count > 0)
         {
             this.IsTriggerShared = true;
         }
     };
     this.Unloaded += (sender, e) =>
     {
         this.ModelItem.PropertyChanged -= OnModelItemPropertyChanged;
         this.transitionsSharingTrigger.Clear();
     };
 }
        internal void DeleteConnectorModelItem(Connector connector)
        {
            ModelItem connectorModelItem = StateContainerEditor.GetConnectorModelItem(connector);

            if (connectorModelItem.ItemType == typeof(Transition))
            {
                StateContainerEditor.GetParentStateModelItemForTransition(connectorModelItem).Properties[StateDesigner.TransitionsPropertyName].Collection.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);
                    es.Complete();
                }
            }
        }
Ejemplo n.º 4
0
        // All the connectors are directly contained by the outmost editor. This is because connectors can go across states.
        void OnEditingScopeCompleted(object sender, EditingScopeEventArgs e)
        {
            Debug.Assert(this.IsOutmostStateContainerEditor(), "Only the outmost editor should listen to the EditingScopeCompleted events of the model tree.");
            if (this.transitionModelItemsAdded.Count > 0)
            {
                // We need to wait until after the state visuals are updated
                this.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>
                {
                    foreach (ModelItem transition in this.transitionModelItemsAdded)
                    {
                        ModelItem srcStateModelItem = StateContainerEditor.GetParentStateModelItemForTransition(transition);
                        this.AddTransitionVisual(transition);
                    }
                    this.transitionModelItemsAdded.Clear();
                }));
            }
            if (this.initialStateChanged)
            {
                Debug.Assert(this.ModelItem.ItemType == typeof(StateMachine), "Only StateMachine should have initial state");
                Debug.Assert(this.initialNode != null, "Initial node should not be null");

                // Remove the old link
                if (GetAttachedConnectors(this.initialNode).Count > 0)
                {
                    this.RemoveConnectorOnOutmostEditor(GetAttachedConnectors(this.initialNode)[0]);
                }
                // Add the new link if the new initial state is not null
                ModelItem initialStateModelItem = this.ModelItem.Properties[StateMachineDesigner.InitialStatePropertyName].Value;
                if (initialStateModelItem != null)
                {
                    // We need to wait until after the state visuals are updated
                    this.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>
                    {
                        this.AddInitialNodeConnector();
                    }));
                }
                this.initialStateChanged = false;
            }
        }