static ConnectionPoint ConnectionPointHitTest(UIElement element, Point hitPoint)
        {
            FreeFormPanel          panel            = VisualTreeUtils.FindVisualAncestor <FreeFormPanel>(element);
            List <ConnectionPoint> connectionPoints = StateContainerEditor.GetConnectionPoints(element);

            return(FreeFormPanel.ConnectionPointHitTest(hitPoint, connectionPoints, panel));
        }
Example #2
0
        private void AddNewTransition(string stateName)
        {
            ModelItem stateMachineModelItem = StateContainerEditor.GetStateMachineModelItem(this.parentStateModelItem);
            ModelItem toStateModelItem      = null;

            foreach (ModelItem stateModelItem in stateMachineModelItem.Properties[StateMachineDesigner.StatesPropertyName].Collection)
            {
                if (string.Equals(stateName, stateModelItem.Properties[StateDesigner.DisplayNamePropertyName].ComputedValue as string, StringComparison.Ordinal))
                {
                    toStateModelItem = stateModelItem;
                }
            }

            if (null == toStateModelItem)
            {
                return;
            }

            Fx.Assert(toStateModelItem != null, "To state cannot be null.");

            using (EditingScope editingScope = (EditingScope)this.ModelItem.BeginEdit(SR.CreateTransition))
            {
                ModelItem triggerModelItem = this.ModelItem.Properties[TriggerPropertyName].Value;
                State     toState          = toStateModelItem.GetCurrentValue() as State;

                ModelItem newTransitionItem = this.parentStateModelItem.Properties[StateDesigner.TransitionsPropertyName].Collection.Add(new Transition()
                {
                    Trigger     = null == triggerModelItem ? null : triggerModelItem.GetCurrentValue() as Activity,
                    DisplayName = StateContainerEditor.GenerateTransitionName(stateMachineModelItem),
                    To          = toState
                });

                this.ViewStateService.StoreViewState(newTransitionItem, ExpandViewStateKey, true);

                if (null == triggerModelItem)
                {
                    PointCollection thisPointCollection = this.ViewStateService.RetrieveViewState(this.ModelItem, StateContainerEditor.ConnectorLocationViewStateKey) as PointCollection;
                    if (null != thisPointCollection && thisPointCollection.Any())
                    {
                        PointCollection newTransitionViewState = new PointCollection
                        {
                            thisPointCollection[0]     // start point
                        };

                        if (toState == this.parentStateModelItem.GetCurrentValue())
                        {
                            // add an invalid destination point for self-transition, to force a reroute of the connection point
                            newTransitionViewState.Add(new Point(0, 0));
                        }

                        this.ViewStateService.StoreViewState(newTransitionItem, StateContainerEditor.ConnectorLocationViewStateKey, newTransitionViewState);
                    }
                }

                editingScope.Complete();
            }

            this.UpdateTransitionsSharingTrigger();
        }
 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;
 }
Example #4
0
        private void OnSourceStateClicked(object sender, RoutedEventArgs e)
        {
            ModelItem sourceState = StateContainerEditor.GetParentStateModelItemForTransition(this.ModelItem);

            if (sourceState != null)
            {
                this.Designer.MakeRootDesigner(sourceState);
            }
        }
        void OnSetAsInitialCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            ModelItem stateMachineModelItem = StateContainerEditor.GetStateMachineModelItem(this.ModelItem);

            e.CanExecute = (!this.IsReadOnly && stateMachineModelItem != null && this.ModelItem != stateMachineModelItem.Properties[StateMachineDesigner.InitialStatePropertyName].Value &&
                            !this.IsFinalState() &&
                            !this.IsRootDesigner && StateContainerEditor.GetEmptyConnectionPoints(this).Count > 0);
            e.Handled = true;
        }
        // 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 static List <ConnectionPoint> GetEmptyConnectionPoints(UIElement designer)
        {
            List <ConnectionPoint> connectionPoints = StateContainerEditor.GetConnectionPoints(designer);

            if (connectionPoints != null)
            {
                return(new List <ConnectionPoint>(connectionPoints.Where <ConnectionPoint>(
                                                      (p) => { return p.AttachedConnectors == null || p.AttachedConnectors.Count == 0; })));
            }
            return(new List <ConnectionPoint>());
        }
        void OnSetAsInitialExecute(object sender, ExecutedRoutedEventArgs e)
        {
            ModelItem stateMachineModelItem = StateContainerEditor.GetStateMachineModelItem(this.ModelItem);

            using (EditingScope es = (EditingScope)this.ModelItem.BeginEdit(SR.SetInitialState))
            {
                this.ViewStateService.RemoveViewState(stateMachineModelItem, StateContainerEditor.ConnectorLocationViewStateKey);
                stateMachineModelItem.Properties[StateMachineDesigner.InitialStatePropertyName].SetValue(this.ModelItem.GetCurrentValue());
                es.Complete();
            }
            e.Handled = true;
        }
        static ConnectionPoint GetConnectionPoint(UIElement element, Point location)
        {
            List <ConnectionPoint> connectionPoints = StateContainerEditor.GetConnectionPoints(element);

            foreach (ConnectionPoint connectionPoint in connectionPoints)
            {
                if (DesignerGeometryHelper.ManhattanDistanceBetweenPoints(location, connectionPoint.Location) <= ConnectorRouter.EndPointTolerance)
                {
                    return(connectionPoint);
                }
            }
            return(null);
        }
Example #10
0
        private IEnumerable <ModelItem> GetAvailableStates()
        {
            List <ModelItem> availableStates       = new List <ModelItem>();
            ModelItem        stateMachineModelItem = StateContainerEditor.GetStateMachineModelItem(this.parentStateModelItem);

            Fx.Assert(null != stateMachineModelItem, "StateMachine must be the ancestor.");
            Dictionary <ModelItem, int> stateToConnectionMap = new Dictionary <ModelItem, int>();

            foreach (ModelItem stateModelItem in stateMachineModelItem.Properties[StateMachineDesigner.StatesPropertyName].Collection)
            {
                if (!stateToConnectionMap.ContainsKey(stateModelItem))
                {
                    stateToConnectionMap[stateModelItem] = 0;
                }

                foreach (ModelItem transitionModelItem in stateModelItem.Properties[StateDesigner.TransitionsPropertyName].Collection)
                {
                    // to simplify the model, count a source connection as one, regardless of whether it is shared Trigger or not.
                    stateToConnectionMap[stateModelItem]++;

                    ModelItem toStateModelItem = transitionModelItem.Properties[TransitionDesigner.ToPropertyName].Value;
                    Fx.Assert(toStateModelItem != null, "To state of a transition cannot be null.");

                    if (stateToConnectionMap.ContainsKey(toStateModelItem))
                    {
                        stateToConnectionMap[toStateModelItem]++;
                    }
                    else
                    {
                        stateToConnectionMap[toStateModelItem] = 1;
                    }
                }
            }

            foreach (ModelItem stateModelItem in stateToConnectionMap.Keys)
            {
                if (stateToConnectionMap[stateModelItem] < TotalFreeConnectionPointNum)
                {
                    // only allow connection to state that have available connection points
                    availableStates.Add(stateModelItem);
                }
            }

            return(availableStates.OrderBy(modelItem => modelItem.Properties[StateDesigner.DisplayNamePropertyName].Value == null ?
                                           SR.EmptyName :
                                           modelItem.Properties[StateDesigner.DisplayNamePropertyName].Value.GetCurrentValue()));
        }
        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);
        }
        public static void RegisterMetadata(AttributeTableBuilder builder)
        {
            Type stateType = typeof(State);

            builder.AddCustomAttributes(stateType, new DesignerAttribute(typeof(StateDesigner)));
            builder.AddCustomAttributes(stateType, stateType.GetProperty(StateDesigner.EntryPropertyName), BrowsableAttribute.No);
            builder.AddCustomAttributes(stateType, stateType.GetProperty(StateDesigner.ExitPropertyName), BrowsableAttribute.No);
            builder.AddCustomAttributes(stateType, stateType.GetProperty(StateDesigner.TransitionsPropertyName), BrowsableAttribute.No);
            builder.AddCustomAttributes(stateType, stateType.GetProperty(StateDesigner.IsFinalPropertyName), BrowsableAttribute.No);
            builder.AddCustomAttributes(stateType, stateType.GetProperty(StateDesigner.VariablesPropertyName), BrowsableAttribute.No);

            builder.AddCustomAttributes(stateType, new ShowInOutlineViewAttribute());
            builder.AddCustomAttributes(stateType, new AllowBreakpointAttribute());
            builder.AddCustomAttributes(stateType, stateType.GetProperty(StateDesigner.TransitionsPropertyName), new ShowPropertyInOutlineViewAttribute()
            {
                CurrentPropertyVisible = false
            });
            builder.AddCustomAttributes(stateType, new ActivityDesignerOptionsAttribute
            {
                OutlineViewIconProvider = (modelItem) =>
                {
                    ResourceDictionary icons = EditorResources.GetIcons();

                    if (modelItem != null)
                    {
                        object icon = null;

                        if (StateContainerEditor.IsFinalState(modelItem) && icons.Contains("FinalStateIcon"))
                        {
                            icon = icons["FinalStateIcon"];
                        }
                        else if (icons.Contains("StateIcon"))
                        {
                            icon = icons["StateIcon"];
                        }

                        if (icon != null && icon is DrawingBrush)
                        {
                            return((DrawingBrush)icon);
                        }
                    }

                    return(null);
                }
            });
        }
        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);
        }
 protected override void OnMouseMove(MouseEventArgs args)
 {
     base.OnMouseMove(args);
     if (args != null && !this.Disabled)
     {
         if (args.LeftButton == MouseButtonState.Pressed && this.IsMouseCaptured && this.scope != null)
         {
             StateContainerEditor stateContainerEditor = this.ParentStateContainerEditor;
             FreeFormPanel        panel = stateContainerEditor.Panel;
             Grid  stateContainerGrid   = stateContainerEditor.stateContainerGrid;
             Point currentPosition      = Mouse.GetPosition(stateContainerGrid);
             currentPosition.Offset(this.offset.X, this.offset.Y);
             stateContainerEditor.StateContainerWidth  = Math.Min(Math.Max(panel.RequiredWidth, currentPosition.X), stateContainerGrid.MaxWidth);
             stateContainerEditor.StateContainerHeight = Math.Min(Math.Max(panel.RequiredHeight, currentPosition.Y), stateContainerGrid.MaxHeight);
             args.Handled = true;
         }
     }
 }
        private void StateDesignerToolTipOpening(object sender, ToolTipEventArgs e)
        {
            StateContainerEditor stateContainerEditor = (StateContainerEditor)sender;

            if (StateContainerEditor.CopiedTransitionDestinationState != null)
            {
                WorkflowViewElement view = VisualTreeUtils.FindVisualAncestor <WorkflowViewElement>(stateContainerEditor);
                if (view != null)
                {
                    StateContainerEditor container = (StateContainerEditor)DragDropHelper.GetCompositeView(view);
                    string errorMessage;
                    if (container != null && container.CanPasteTransition(StateContainerEditor.CopiedTransitionDestinationState, out errorMessage, view.ModelItem))
                    {
                        stateContainerEditor.ToolTip = SR.EditStateToolTip + Environment.NewLine + SR.PasteTransitionToolTip;
                        return;
                    }
                }
            }

            stateContainerEditor.ToolTip = SR.EditStateToolTip;
        }
        public object OnItemsCopied(List <ModelItem> itemsToCopy)
        {
            itemsToCopy.Remove(this.initialModelItem);

            // If the item copied is Transition, save its destination state guid to find the destination state when pasting.
            if (itemsToCopy.Count == 1)
            {
                ModelItem item = itemsToCopy.First();
                if (item != null && item.ItemType == typeof(Transition))
                {
                    ModelItem destinationState = item.Properties[TransitionDesigner.ToPropertyName].Value;

                    if (!modelItemToGuid.ContainsKey(destinationState))
                    {
                        modelItemToGuid.Add(destinationState, Guid.NewGuid().ToString());
                    }

                    CopiedTransitionDestinationState = destinationState;
                    return(modelItemToGuid[destinationState]);
                }
            }

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

            // Save the locations of copied items relative to the statemachine editor to the metadata.
            // The metadata will be used to translate the location view states of pasted items to the pasting target.
            PointCollection metaData = new PointCollection();

            foreach (ModelItem modelItem in itemsToCopy)
            {
                object viewState = this.ViewStateService.RetrieveViewState(modelItem, ShapeLocationViewStateKey);
                Point  location  = (Point)viewState;
                StateContainerEditor parentDesigner = VisualTreeUtils.FindVisualAncestor <StateContainerEditor>(GetStateView(modelItem));
                location = parentDesigner.panel.GetLocationRelativeToOutmostPanel(location);
                metaData.Add(location);
            }

            CopiedTransitionDestinationState = null;
            return(metaData);
        }
Example #17
0
        public TransitionDesigner()
        {
            InitializeComponent();
            this.TransitionsSharingTrigger = new ObservableCollection <ExpandableItemWrapper>();

            this.Loaded += (sender, e) =>
            {
                if (!this.isPopulated)
                {
                    this.isPopulated = true;
                    this.TransitionsSharingTrigger.CollectionChanged += OnTransitionsCollectionChanged;
                    this.ModelItem.PropertyChanged += OnModelItemPropertyChanged;
                    this.parentStateModelItem       = StateContainerEditor.GetParentStateModelItemForTransition(this.ModelItem);
                    this.parentStateModelItem.Properties[StateDesigner.TransitionsPropertyName].Collection.CollectionChanged += OnTransitionsModelItemCollectionChanged;
                    ExpandableItemWrapper selectedItem = this.UpdateTransitionsSharingTrigger();
                    if (null != selectedItem)
                    {
                        this.SelectedTransition = selectedItem;
                    }
                }
            };

            this.Unloaded += (sender, e) =>
            {
                if (this.isPopulated)
                {
                    this.isPopulated = false;
                    this.TransitionsSharingTrigger.Clear();
                    this.TransitionsSharingTrigger.CollectionChanged -= OnTransitionsCollectionChanged;
                    this.ModelItem.PropertyChanged -= OnModelItemPropertyChanged;
                    this.parentStateModelItem.Properties[StateDesigner.TransitionsPropertyName].Collection.CollectionChanged -= OnTransitionsModelItemCollectionChanged;
                    this.SelectedTransition   = null;
                    this.parentStateModelItem = null;
                }
            };
        }
        // 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);
            }
        }
        //This returns the closest non-incoming connectionPoint on source. Return value will be different than destConnectionPoint.
        static ConnectionPoint GetClosestSrcConnectionPoint(UIElement src, ConnectionPoint destConnectionPoint)
        {
            ConnectionPoint srcConnectionPoint = null;

            if (destConnectionPoint.PointType != ConnectionPointKind.Outgoing)
            {
                srcConnectionPoint = GetClosestConnectionPointNotOfType(destConnectionPoint, StateContainerEditor.GetConnectionPoints(src), ConnectionPointKind.Incoming);
            }
            return(srcConnectionPoint);
        }
 void UpdateLocationViewStatesByMetaData(List <ModelItem> itemsPasted, List <object> metaData, StateContainerEditor container)
 {
     Fx.Assert(container != null, "The view states must be calculated related to a parent StateContainerEditor.");
     // If the states are not copied from state machine view (e.g., when the State designer is the breadcrumb root),
     // there is no meta data
     if (metaData != null && metaData.Count > 0)
     {
         int ii = 0;
         foreach (object data in metaData)
         {
             PointCollection points = (PointCollection)data;
             foreach (Point point in points)
             {
                 // translate location view states to be in the coordinate system of the pasting target
                 this.ViewStateService.StoreViewState(itemsPasted[ii], ShapeLocationViewStateKey, container.panel.TranslatePoint(point, container.panel));
                 ++ii;
             }
         }
         Fx.Assert(itemsPasted.Count == ii, "itemsCopied does not match the metaData.");
     }
 }
        //This returns the closest non-outgoing connectionPoint on dest. Return value will be different than sourceConnectionPoint.
        static ConnectionPoint GetClosestDestConnectionPoint(ConnectionPoint sourceConnectionPoint, UIElement dest)
        {
            ConnectionPoint destConnectionPoint = null;

            if (sourceConnectionPoint.PointType != ConnectionPointKind.Incoming)
            {
                destConnectionPoint = GetClosestConnectionPointNotOfType(sourceConnectionPoint, StateContainerEditor.GetConnectionPoints(dest), ConnectionPointKind.Outgoing);
            }
            return(destConnectionPoint);
        }
        void Cleanup()
        {
            this.panel.Children.Clear();
            // Cleaning up the designers as they might be re-used.
            foreach (UIElement element in this.modelItemToUIElement.Values)
            {
                element.MouseEnter -= new MouseEventHandler(OnChildElementMouseEnter);
                element.MouseLeave -= new MouseEventHandler(OnChildElementMouseLeave);
                ((FrameworkElement)element).SizeChanged -= new SizeChangedEventHandler(OnChildElementSizeChanged);
            }
            this.modelItemToUIElement.Clear();
            this.panel.LocationChanged -= new LocationChangedEventHandler(OnFreeFormPanelLocationChanged);
            this.panel.ConnectorMoved -= new ConnectorMovedEventHandler(OnFreeFormPanelConnectorMoved);
            this.panel.LayoutUpdated -= new EventHandler(OnFreeFormPanelLayoutUpdated);
            this.panel.RequiredSizeChanged -= new RequiredSizeChangedEventHandler(OnFreeFormPanelRequiredSizeChanged);
            this.ViewStateService.ViewStateChanged -= new ViewStateChangedEventHandler(OnViewStateChanged);

            if (this.ModelItem.ItemType == typeof(StateMachine))
            {
                // Only StateMachine supports "States" collection
                this.ModelItem.Properties[StateMachineDesigner.StatesPropertyName].Collection.CollectionChanged -= new NotifyCollectionChangedEventHandler(OnStateCollectionChanged);
                this.ModelItem.PropertyChanged -= new PropertyChangedEventHandler(this.OnModelPropertyChanged);
                ModelTreeManager modelTreeManager = this.Context.Services.GetService<ModelTreeManager>();
                modelTreeManager.EditingScopeCompleted -= new EventHandler<EditingScopeEventArgs>(this.OnEditingScopeCompleted);

                foreach (ModelItem modelItem in this.ModelItem.Properties[StateMachineDesigner.StatesPropertyName].Collection)
                {
                    if (modelItem.ItemType == typeof(State))
                    {
                        ModelItemCollection transitions = modelItem.Properties[StateDesigner.TransitionsPropertyName].Collection;
                        if (this.listenedTransitionCollections.Contains(transitions))
                        {
                            transitions.CollectionChanged -= new NotifyCollectionChangedEventHandler(this.OnTransitionCollectionChanged);
                            this.listenedTransitionCollections.Remove(transitions);
                        }
                    }
                }
            }

            // stateMachineContainerEditor will be null when dropping a State into a WorkflowItemPresenter.
            if (this.ModelItem.ItemType == typeof(State) && this.stateMachineContainerEditor != null)
            {
                this.stateMachineContainerEditor = null;
            }
        }
        void Populate()
        {
            // Keep track of the outmost editor, which may not be accessible by traversing the visual tree when the designer is deleted.
            this.stateMachineContainerEditor = this.GetStateMachineContainerEditor();

            this.panel.LocationChanged += new LocationChangedEventHandler(OnFreeFormPanelLocationChanged);
            this.panel.ConnectorMoved += new ConnectorMovedEventHandler(OnFreeFormPanelConnectorMoved);
            this.panel.LayoutUpdated += new EventHandler(OnFreeFormPanelLayoutUpdated);
            this.panel.RequiredSizeChanged += new RequiredSizeChangedEventHandler(OnFreeFormPanelRequiredSizeChanged);

            this.ViewStateService.ViewStateChanged += new ViewStateChangedEventHandler(OnViewStateChanged);

            if (this.ModelItem.ItemType == typeof(StateMachine))
            {
                // Only StateMachine supports "States" collection
                IsStateMachineContainer = true;
                this.ModelItem.Properties[StateMachineDesigner.StatesPropertyName].Collection.CollectionChanged += new NotifyCollectionChangedEventHandler(OnStateCollectionChanged);
                this.ModelItem.PropertyChanged += new PropertyChangedEventHandler(this.OnModelPropertyChanged);
                ModelTreeManager modelTreeManager = this.Context.Services.GetService<ModelTreeManager>();
                modelTreeManager.EditingScopeCompleted += new EventHandler<EditingScopeEventArgs>(this.OnEditingScopeCompleted);

                foreach (ModelItem modelItem in this.ModelItem.Properties[StateMachineDesigner.StatesPropertyName].Collection)
                {
                    if (modelItem.ItemType == typeof(State))
                    {
                        ModelItemCollection transitions = modelItem.Properties[StateDesigner.TransitionsPropertyName].Collection;
                        if (!this.listenedTransitionCollections.Contains(transitions))
                        {
                            transitions.CollectionChanged += new NotifyCollectionChangedEventHandler(this.OnTransitionCollectionChanged);
                            this.listenedTransitionCollections.Add(transitions);
                        }
                    }
                }
            }


            object widthViewState = this.ViewStateService.RetrieveViewState(this.ModelItem, StateContainerWidthViewStateKey);
            if (widthViewState != null)
            {
                this.StateContainerWidth = (double)widthViewState;
            }

            object heightViewState = this.ViewStateService.RetrieveViewState(this.ModelItem, StateContainerHeightViewStateKey);
            if (heightViewState != null)
            {
                this.StateContainerHeight = (double)heightViewState;
            }

            this.panel.Children.Clear();
            this.modelItemToUIElement.Clear();
            this.shapeLocations.Clear();

            if (this.ModelItem.ItemType == typeof(StateMachine))
            {
                this.AddInitialNode();
                this.AddStateVisuals(this.ModelItem.Properties[StateMachineDesigner.StatesPropertyName].Collection);
            }
        }
        public void OnItemsPasted(List <object> itemsToPaste, List <object> metaData, Point pastePoint, WorkflowViewElement pastePointReference)
        {
            if (this.ModelItem.ItemType == typeof(State))
            {
                WorkflowViewElement view = VisualTreeUtils.FindVisualAncestor <WorkflowViewElement>(this);
                if (view != null)
                {
                    StateContainerEditor container = (StateContainerEditor)DragDropHelper.GetCompositeView(view);
                    container.OnItemsPasted(itemsToPaste, metaData, pastePoint, pastePointReference);
                }

                return;
            }

            if (itemsToPaste.Count == 1 && itemsToPaste.First() is Transition)
            {
                if (metaData == null || metaData.Count != 1 || !(metaData.First() is string))
                {
                    ShowMessageBox(SR.PasteTransitionWithoutDestinationState);
                    return;
                }

                ModelItem destinationState = FindState(metaData.First() as string);

                if (destinationState == null)
                {
                    ShowMessageBox(SR.PasteTransitionWithoutDestinationState);
                    return;
                }

                this.PopulateVirtualizingContainer(destinationState);

                ModelItem[] selectedItems = this.Context.Items.GetValue <Selection>().SelectedObjects.ToArray();
                string      errorMessage;
                if (!CanPasteTransition(destinationState, out errorMessage, selectedItems))
                {
                    ShowMessageBox(errorMessage);
                    return;
                }

                Transition pastedTransition = itemsToPaste.First() as Transition;
                Fx.Assert(pastedTransition != null, "Copied Transition should not be null.");

                using (EditingScope es = (EditingScope)this.ModelItem.BeginEdit(System.Activities.Presentation.SR.PropertyChangeEditingScopeDescription))
                {
                    string displayName = pastedTransition.DisplayName;
                    bool   isFirst     = true;
                    foreach (ModelItem selectedItem in selectedItems)
                    {
                        if (!isFirst)
                        {
                            StringReader reader = new StringReader(XamlServices.Save(pastedTransition));
                            pastedTransition = (Transition)XamlServices.Load(reader);
                        }

                        ModelItem transitionModelItem = this.Context.Services.GetRequiredService <ModelTreeManager>().WrapAsModelItem(pastedTransition);
                        ModelItem sourceState         = selectedItem;
                        sourceState.Properties[StateDesigner.TransitionsPropertyName].Collection.Add(transitionModelItem);
                        transitionModelItem.Properties[TransitionDesigner.ToPropertyName].SetValue(destinationState);

                        if (isFirst)
                        {
                            this.ViewStateService.RemoveViewState(transitionModelItem, ConnectorLocationViewStateKey);
                            this.ViewStateService.RemoveViewState(transitionModelItem, SrcConnectionPointIndexStateKey);
                            this.ViewStateService.RemoveViewState(transitionModelItem, DestConnectionPointIndexStateKey);
                            isFirst = false;
                        }
                    }

                    es.Complete();
                }
            }
            else
            {
                List <ModelItem> modelItemsPasted = new List <ModelItem>();
                List <State>     states           = new List <State>();

                foreach (object obj in itemsToPaste)
                {
                    State state;
                    if (obj is FinalState)
                    {
                        state = new State()
                        {
                            DisplayName = DefaultFinalStateDisplayName, IsFinal = true
                        };
                    }
                    else
                    {
                        state = (State)obj;
                        if (state.DisplayName == null)
                        {
                            state.DisplayName = DefaultStateDisplayName;
                        }
                    }
                    states.Add(state);
                }

                RemoveDanglingTransitions(states);

                using (EditingScope es = (EditingScope)this.ModelItem.BeginEdit(
                           System.Activities.Presentation.SR.CollectionAddEditingScopeDescription))
                {
                    // Fix 157591 by storing the height and width of the container "before" the new states are added to the
                    // panel, and group the insertion inside one editing scope - such that Undo will also restore the
                    // size of the StateMachineContainer to pre-insert size.
                    StoreShapeSizeWithUndoRecursively(this.ModelItem);

                    foreach (State state in states)
                    {
                        ModelItem stateModelItem =
                            (this.ModelItem.ItemType == typeof(StateMachine)) ?
                            this.ModelItem.Properties[StateMachineDesigner.StatesPropertyName].Collection.Add(state) :
                            GetStateMachineModelItem(this.ModelItem).Properties[StateMachineDesigner.StatesPropertyName].Collection.Add(state);
                        modelItemsPasted.Add(stateModelItem);
                    }

                    es.Complete();
                }

                if (modelItemsPasted.Count > 0)
                {
                    // translate location view states to be in the coordinate system of the pasting target
                    Fx.Assert(this.ModelItem.ItemType == typeof(StateMachine), "Only StateMachine contain the StateContainerEditor.");

                    this.UpdateLocationViewStatesByMetaData(modelItemsPasted, metaData, this);

                    if (pastePoint.X > 0 && pastePoint.Y > 0)
                    {
                        if (pastePointReference != null)
                        {
                            pastePoint   = pastePointReference.TranslatePoint(pastePoint, this.panel);
                            pastePoint.X = pastePoint.X < 0 ? 0 : pastePoint.X;
                            pastePoint.Y = pastePoint.Y < 0 ? 0 : pastePoint.Y;
                        }
                        this.UpdateLocationViewStatesByPoint(modelItemsPasted, pastePoint);
                    }
                    // If paste point is not available, paste the items to the top left corner.
                    else
                    {
                        this.UpdateLocationViewStatesToAvoidOverlap(modelItemsPasted);
                    }
                }

                this.Dispatcher.BeginInvoke(() =>
                {
                    if (modelItemsPasted.Count > 0 && modelItemsPasted[0] != null)
                    {
                        Keyboard.Focus(modelItemsPasted[0].View as IInputElement);
                    }
                    this.Context.Items.SetValue(new Selection(modelItemsPasted));
                },
                                            DispatcherPriority.ApplicationIdle
                                            );
            }
        }
Example #25
0
 void OnStateContainerUnloaded(object sender, RoutedEventArgs e)
 {
     this.stateContainerEditor = null;
 }
 internal bool IsFinalState()
 {
     return(StateContainerEditor.IsFinalState(this.ModelItem));
 }
 void OnStateContainerUnloaded(object sender, RoutedEventArgs e)
 {
     this.stateContainerEditor = null;
 }
        void UpdateLocationViewStatesToAvoidOverlap(List <ModelItem> itemsPasted)
        {
            int offset = 0;

            if (itemsPasted.Count > 0)
            {
                //Check to see if the first element in the input list needs offset. Generalize that information for all ModelItems in the input list.
                object          location = this.ViewStateService.RetrieveViewState(itemsPasted[0], ShapeLocationViewStateKey);
                HashSet <Point> targetOccupiedLocations = null;

                if (this.ModelItem.ItemType == typeof(StateMachine))
                {
                    targetOccupiedLocations = this.shapeLocations;
                }
                else
                {
                    ModelItem            stateMachineModelItem = StateContainerEditor.GetStateMachineModelItem(this.ModelItem);
                    StateMachineDesigner designer = stateMachineModelItem.View as StateMachineDesigner;

                    if (designer != null)
                    {
                        targetOccupiedLocations = designer.StateContainerEditor.shapeLocations;
                    }
                }

                if (location != null && targetOccupiedLocations != null)
                {
                    Point locationOfShape = (Point)location;

                    bool isOverlapped;

                    do
                    {
                        isOverlapped = false;
                        // need to check for each point on the canvas
                        foreach (var point in targetOccupiedLocations)
                        {
                            // When the pasting occurs, the pasted point may not be exactly the same
                            // as the copied point (with a slight margin of offset).  Therefore,
                            // we need to detect if the pasted point is within the boundary of the copied
                            // object.  If so, offset the pasted position such that the overlap is not observable.
                            if ((locationOfShape.X < point.X + FreeFormPanel.GridSize &&
                                 locationOfShape.X > point.X - FreeFormPanel.GridSize) &&
                                (locationOfShape.Y < point.Y + FreeFormPanel.GridSize &&
                                 locationOfShape.Y > point.Y - FreeFormPanel.GridSize))
                            {
                                offset++;
                                locationOfShape.Offset(FreeFormPanel.GridSize, FreeFormPanel.GridSize);
                                isOverlapped = true;
                                break;
                            }
                        }
                    } while (isOverlapped);
                }
            }
            //Update ViewState according to calculated offset.
            if (offset > 0)
            {
                double offsetValue = FreeFormPanel.GridSize * offset;
                OffsetLocationViewStates(new Vector(offsetValue, offsetValue), itemsPasted, GetTransitionModelItems(itemsPasted), false);
            }
        }
Example #29
0
 void OnStateContainerLoaded(object sender, RoutedEventArgs e)
 {
     this.stateContainerEditor = sender as StateContainerEditor;
 }
 void UpdateLocationViewStatesByMetaData(List<ModelItem> itemsPasted, List<object> metaData, StateContainerEditor container)
 {
     Fx.Assert(container != null, "The view states must be calculated related to a parent StateContainerEditor.");
     // If the states are not copied from state machine view (e.g., when the State designer is the breadcrumb root), 
     // there is no meta data
     if (metaData != null && metaData.Count > 0)
     {
         int ii = 0;
         foreach (object data in metaData)
         {
             PointCollection points = (PointCollection)data;
             foreach (Point point in points)
             {
                 // translate location view states to be in the coordinate system of the pasting target
                 this.ViewStateService.StoreViewState(itemsPasted[ii], ShapeLocationViewStateKey, container.panel.TranslatePoint(point, container.panel));
                 ++ii;
             }
         }
         Fx.Assert(itemsPasted.Count == ii, "itemsCopied does not match the metaData.");
     }
 }
 void OnStateContainerLoaded(object sender, RoutedEventArgs e)
 {
     this.stateContainerEditor = sender as StateContainerEditor;
 }
        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));
            }
        }