示例#1
0
 bool ValidateCaseKey(object obj, out string reason)
 {
     return(GenericFlowSwitchHelper.ValidateCaseKey(obj,
                                                    this.ModelItem.Properties["Cases"],
                                                    this.genericType,
                                                    out reason));
 }
示例#2
0
        bool CreateFlowSwitchLink(ConnectionPoint sourceConnPoint, ModelItem srcFlowElementMI, ModelItem destFlowElementMI, IFlowSwitchLink caseKey, PointCollection connectorViewState, ref string errorMessage)
        {
            IModelTreeItem modelTreeItem = this.ModelItem as IModelTreeItem;

            if ((caseKey != null && caseKey.IsDefaultCase) || (caseKey == null && srcFlowElementMI.Properties["Default"].Value == null))
            {
                IFlowSwitchLink link          = GenericFlowSwitchHelper.CreateFlowSwitchLink(srcFlowElementMI.ItemType, srcFlowElementMI, null, true);
                ModelItem       linkModelItem = new FakeModelItemImpl(modelTreeItem.ModelTreeManager, link.GetType(), link, null);
                link.ModelItem = linkModelItem;
                if (connectorViewState != null)
                {
                    this.StoreConnectorViewState(linkModelItem, connectorViewState, sourceConnPoint);
                }
                srcFlowElementMI.Properties["Default"].SetValue(destFlowElementMI);
            }
            else
            {
                ModelProperty casesProp = srcFlowElementMI.Properties["Cases"];

                string uniqueCaseName = null;

                if (caseKey == null)
                {
                    Type typeArgument = srcFlowElementMI.ItemType.GetGenericArguments()[0];
                    if (GenericFlowSwitchHelper.CanBeGeneratedUniquely(typeArgument))
                    {
                        uniqueCaseName = GenericFlowSwitchHelper.GetCaseName(casesProp, typeArgument, out errorMessage);
                    }
                    else
                    {
                        FlowSwitchCaseEditorDialog editor = new FlowSwitchCaseEditorDialog(srcFlowElementMI, this.Context, this, SR.AddNewCase, typeArgument);
                        editor.WindowSizeToContent = SizeToContent.WidthAndHeight;
                        if (!editor.ShowOkCancel())
                        {
                            return(false);
                        }
                        uniqueCaseName = editor.CaseName;
                    }
                }
                else
                {
                    uniqueCaseName = caseKey.CaseName;
                }

                if (string.IsNullOrEmpty(errorMessage))
                {
                    IFlowSwitchLink link          = GenericFlowSwitchHelper.CreateFlowSwitchLink(srcFlowElementMI.ItemType, srcFlowElementMI, uniqueCaseName, false);
                    ModelItem       linkModelItem = new FakeModelItemImpl(modelTreeItem.ModelTreeManager, link.GetType(), link, null);
                    link.ModelItem = linkModelItem;
                    if (connectorViewState != null)
                    {
                        this.StoreConnectorViewState(linkModelItem, connectorViewState, sourceConnPoint);
                    }
                    GenericFlowSwitchHelper.AddCase(srcFlowElementMI.Properties["Cases"], link.CaseObject, destFlowElementMI.GetCurrentValue());
                }
            }
            return(true);
        }
        //This method updates the clone of currentFlowElement to reference cloned FlowElements.
        void UpdateCloneReferences(FlowNode currentFlowElement, Dictionary <FlowNode, FlowNode> clonedFlowElements)
        {
            if (typeof(FlowStep).IsAssignableFrom(currentFlowElement.GetType()))
            {
                FlowStep currentFlowStep = (FlowStep)currentFlowElement;
                FlowStep clonedFlowStep  = (FlowStep)clonedFlowElements[currentFlowElement];
                FlowNode nextFlowElement = currentFlowStep.Next;
                if (nextFlowElement != null && clonedFlowElements.ContainsKey(nextFlowElement))
                {
                    clonedFlowStep.Next = clonedFlowElements[nextFlowElement];
                }
                else
                {
                    clonedFlowStep.Next = null;
                }
            }
            else if (typeof(FlowDecision).IsAssignableFrom(currentFlowElement.GetType()))
            {
                FlowDecision currentFlowDecision = (FlowDecision)currentFlowElement;
                FlowDecision clonedFlowDecision  = (FlowDecision)clonedFlowElements[currentFlowElement];
                FlowNode     trueElement         = currentFlowDecision.True;
                FlowNode     falseElement        = currentFlowDecision.False;

                if (trueElement != null && clonedFlowElements.ContainsKey(trueElement))
                {
                    clonedFlowDecision.True = clonedFlowElements[trueElement];
                }
                else
                {
                    clonedFlowDecision.True = null;
                }

                if (falseElement != null && clonedFlowElements.ContainsKey(falseElement))
                {
                    clonedFlowDecision.False = clonedFlowElements[falseElement];
                }
                else
                {
                    clonedFlowDecision.False = null;
                }
            }
            else if (GenericFlowSwitchHelper.IsGenericFlowSwitch(currentFlowElement.GetType()))
            {
                GenericFlowSwitchHelper.Copy(currentFlowElement.GetType().GetGenericArguments()[0], currentFlowElement, clonedFlowElements);
            }
            else
            {
                Debug.Fail("Unknown FlowNode");
            }
        }
        Connector CreatePropertyLink(ModelItem srcModelItem, ModelItem propertyValue, string propertyName)
        {
            Connector newConnector = null;

            if (typeof(FlowStep).IsAssignableFrom(srcModelItem.ItemType))
            {
                ModelItem src  = GetCorrespondingElementOnCanvas(srcModelItem);
                ModelItem dest = GetCorrespondingElementOnCanvas(propertyValue);
                newConnector = CreateLink(modelElement[src], modelElement[dest], srcModelItem);
            }
            else if (typeof(FlowDecision).IsAssignableFrom(srcModelItem.ItemType))
            {
                ModelItem       dest = GetCorrespondingElementOnCanvas(propertyValue);
                ConnectionPoint srcConnPoint;
                if (propertyName.Equals("True"))
                {
                    srcConnPoint = FlowchartDesigner.GetTrueConnectionPoint(modelElement[srcModelItem]);
                }
                else
                {
                    srcConnPoint = FlowchartDesigner.GetFalseConnectionPoint(modelElement[srcModelItem]);
                }
                newConnector = CreateLink(srcConnPoint, modelElement[dest], srcModelItem);
            }
            else if (GenericFlowSwitchHelper.IsGenericFlowSwitch(srcModelItem.ItemType))
            {
                ModelItem       dest = GetCorrespondingElementOnCanvas(propertyValue);
                IFlowSwitchLink link;
                if (propertyName.Equals("Default"))
                {
                    link = GenericFlowSwitchHelper.CreateFlowSwitchLink(srcModelItem.ItemType, srcModelItem, null, true);
                }
                else
                {
                    Fx.Assert(propertyName.Length >= GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier.Length, "Case property names should be prepended by the string GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier");
                    link = GenericFlowSwitchHelper.CreateFlowSwitchLink(srcModelItem.ItemType, srcModelItem, propertyName.Substring(GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier.Length), false);
                }
                IModelTreeItem modelTreeItem = (IModelTreeItem)this.ModelItem;
                ModelItem      linkModelItem = new FakeModelItemImpl(modelTreeItem.ModelTreeManager, link.GetType(), link, null);
                link.ModelItem = linkModelItem;
                newConnector   = CreateLink(modelElement[srcModelItem], modelElement[dest], linkModelItem);
            }
            else // FlowStart
            {
                ModelItem dest = GetCorrespondingElementOnCanvas(propertyValue);
                newConnector = CreateLink(this.StartSymbol, modelElement[dest], this.ModelItem);
            }
            return(newConnector);
        }
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            bool isDefaultCase = (bool)values[1];

            if (isDefaultCase)
            {
                // Fx.Assert(values.Length == 3, "The multi-binding must have been constructed by FlowSwitchLink.");
                // For default case, we should have got three bindings. Two binding is possible when the linkModelItem is replaced but the view is not completely re-constructed yet.
                return(values.Length == 3 ? values[2] : null);
            }
            else
            {
                return(GenericFlowSwitchHelper.GetString(values[0], (Type)parameter));
            }
        }
示例#6
0
        void OnCasePropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            bool isUndoRedoInProgress = this.IsUndoRedoInProgress();

            if (!this.internalChange && !isUndoRedoInProgress)
            {
                T oldValue = (T)e.OldValue;
                T newValue = (T)e.NewValue;

                if (newValue is string && newValue != null)
                {
                    newValue = (T)((object)((string)((object)newValue)).Trim());
                }

                string oldViewStateKey = string.Empty;
                if (!this.ContainsKey(newValue))
                {
                    using (EditingScope es = (EditingScope)this.flowSwitchModelItem.BeginEdit(SR.FlowSwitchCaseRenameEditingScopeDesc))
                    {
                        ModelItem flowElementMI = null;

                        flowElementMI = GenericFlowSwitchHelper.GetCaseModelItem(this.flowSwitchModelItem.Properties["Cases"], oldValue);
                        GenericFlowSwitchHelper.RemoveCase(this.flowSwitchModelItem.Properties["Cases"], oldValue);
                        oldViewStateKey = GenericFlowSwitchHelper.GetString(oldValue, typeof(T)) + CaseViewStateKeyAppendString;
                        //Add the new value
                        GenericFlowSwitchHelper.AddCase(this.flowSwitchModelItem.Properties["Cases"], newValue, flowElementMI.GetCurrentValue());
                        //Update the viewstate for the flowswitch.
                        this.UpdateViewState(oldViewStateKey, GenericFlowSwitchHelper.GetString(newValue, typeof(T)) + CaseViewStateKeyAppendString);
                        //Making sure the value for Case is always trimmed.
                        this.internalChange = true;
                        this.ModelItem.Properties["Case"].SetValue(newValue);
                        es.Complete();
                    }
                }
                else
                {
                    this.internalChange = true;
                    this.CaseObject     = oldValue;
                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR.InvalidFlowSwitchCaseMessage));
                }
            }
            this.internalChange = false;
        }
示例#7
0
        // oldNewFlowNodeMap: <OldFlowNode, NewFlowNode>
        //    sometimes, OldFlowNode == NewFlowNode, say, FlowNode is a FlowDecesion.
        //    if FlowNode is FlowStep, OldFlowNode != NewFlowNode
        public static void GenericRemapFlowSwitch <T>(FlowNode currentFlowElement,
                                                      ModelItem modelItem, Dictionary <FlowNode, FlowNode> oldNewFlowNodeMap)
        {
            FlowSwitch <T> currentFlowSwitch = (FlowSwitch <T>)currentFlowElement;

            //Update the default case.
            FlowNode defaultCase = currentFlowSwitch.Default;

            if (defaultCase != null && oldNewFlowNodeMap.ContainsKey(defaultCase))
            {
                modelItem.Properties["Default"].SetValue(oldNewFlowNodeMap[defaultCase]);
            }
            else
            {
                modelItem.Properties["Default"].SetValue(null);
            }


            // collect all the cases that should be update
            Dictionary <object, object> keyValueMap = new Dictionary <object, object>();

            foreach (T key in currentFlowSwitch.Cases.Keys)
            {
                if (oldNewFlowNodeMap.ContainsKey(currentFlowSwitch.Cases[key]))
                {
                    keyValueMap.Add(key, oldNewFlowNodeMap[currentFlowSwitch.Cases[key]]);
                }
            }
            // Update the Cases dictionary.
            ModelProperty casesProperty = modelItem.Properties["Cases"];

            // remove all key
            foreach (ModelItem key in GenericFlowSwitchHelper.GetCaseKeys(casesProperty))
            {
                GenericFlowSwitchHelper.RemoveCase(casesProperty, key.GetCurrentValue());
            }

            // add back keys
            foreach (T key in keyValueMap.Keys)
            {
                GenericFlowSwitchHelper.AddCase(casesProperty, key, keyValueMap[key]);
            }
        }
示例#8
0
        public static bool ValidateCaseKey(object obj, ModelProperty casesProp, Type genericType, out string reason)
        {
            reason = string.Empty;
            string key = GenericFlowSwitchHelper.GetString(obj, genericType);

            if (GenericFlowSwitchHelper.CheckEquality(obj, genericType))
            {
                if (GenericFlowSwitchHelper.ContainsCaseKey(casesProp, obj))
                {
                    reason = string.Format(CultureInfo.CurrentCulture, SR.DuplicateCaseKey, key);
                    return(false);
                }
                return(true);
            }
            else
            {
                reason = string.Format(CultureInfo.CurrentUICulture, SR.EqualityError, genericType.Name);
                return(false);
            }
        }
        void RefreshFlowSwitchLinkModelItem(ModelItem flowSwitchModelItem, Connector connector, bool isDefault)
        {
            ModelItem oldLinkModelItem = FlowchartDesigner.GetLinkModelItem(connector);

            IModelTreeItem  modelTreeItem = flowSwitchModelItem as IModelTreeItem;
            IFlowSwitchLink link          = GenericFlowSwitchHelper.CreateFlowSwitchLink(flowSwitchModelItem.ItemType, flowSwitchModelItem, ((IFlowSwitchLink)oldLinkModelItem.GetCurrentValue()).CaseObject, isDefault);
            ModelItem       linkModelItem = new FakeModelItemImpl(modelTreeItem.ModelTreeManager, link.GetType(), link, null);

            link.ModelItem = linkModelItem;

            FlowchartDesigner.SetLinkModelItem(connector, linkModelItem);
            connector.SetBinding(Connector.LabelTextProperty, link.CreateConnectorLabelTextBinding());

            Selection currentSelection = this.Context.Items.GetValue <Selection>();

            if (currentSelection.SelectedObjects.Contains(oldLinkModelItem))
            {
                Selection.Toggle(this.Context, oldLinkModelItem);
                Selection.Select(this.Context, linkModelItem);
            }
        }
示例#10
0
        void OnIsDefaultPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            bool isUndoRedoInProgress = this.IsUndoRedoInProgress();

            if (!this.internalDefaultCaseChange && !isUndoRedoInProgress)
            {
                bool value    = (bool)e.NewValue;
                bool oldValue = (bool)e.OldValue;

                if (value)
                {
                    if (object.Equals(this.flowSwitchModelItem.Properties["Default"].Value, null))
                    {
                        using (EditingScope es = (EditingScope)this.flowSwitchModelItem.BeginEdit(SR.FlowSwitchCaseRenameEditingScopeDesc))
                        {
                            ModelItem flowNodeMI = GenericFlowSwitchHelper.GetCaseModelItem(this.flowSwitchModelItem.Properties["Cases"], this.CaseObject);
                            GenericFlowSwitchHelper.RemoveCase(this.flowSwitchModelItem.Properties["Cases"], this.CaseObject);
                            this.flowSwitchModelItem.Properties["Default"].SetValue(flowNodeMI);
                            this.UpdateViewState(this.CaseName + CaseViewStateKeyAppendString, DefaultConnectorViewStateKey);
                            this.internalChange = true;
                            es.Complete();
                        }
                    }
                    else
                    {
                        this.internalDefaultCaseChange = true;
                        this.IsDefaultCase             = oldValue;
                        throw FxTrace.Exception.AsError(new InvalidOperationException(SR.DefaultCaseExists));
                    }
                }
                else
                {
                    if (oldValue)
                    {
                        using (EditingScope es = (EditingScope)this.flowSwitchModelItem.BeginEdit(SR.FlowSwitchCaseRenameEditingScopeDesc))
                        {
                            ModelItem defaultCase  = this.flowSwitchModelItem.Properties["Default"].Value;
                            object    uniqueCase   = null;
                            string    errorMessage = string.Empty;
                            Type      typeArgument = typeof(T);
                            if (GenericFlowSwitchHelper.CanBeGeneratedUniquely(typeArgument))
                            {
                                string caseName = GenericFlowSwitchHelper.GetCaseName(this.flowSwitchModelItem.Properties["Cases"], typeArgument, out errorMessage);
                                if (!string.IsNullOrEmpty(errorMessage))
                                {
                                    this.internalDefaultCaseChange = true;
                                    this.IsDefaultCase             = oldValue;
                                    throw FxTrace.Exception.AsError(new InvalidOperationException(errorMessage));
                                }
                                uniqueCase = GenericFlowSwitchHelper.GetObject(caseName, typeArgument);
                            }
                            else
                            {
                                FlowSwitchCaseEditorDialog editor = new FlowSwitchCaseEditorDialog(this.flowSwitchModelItem, ((WorkflowViewElement)this.flowSwitchModelItem.View).Context, this.flowSwitchModelItem.View, SR.ChangeCaseValue, this.flowSwitchModelItem.ItemType.GetGenericArguments()[0]);
                                editor.WindowSizeToContent = SizeToContent.WidthAndHeight;

                                if (!editor.ShowOkCancel())
                                {
                                    this.internalDefaultCaseChange = true;
                                    this.IsDefaultCase             = oldValue;
                                    return;
                                }
                                uniqueCase = editor.Case;
                                if (GenericFlowSwitchHelper.ContainsCaseKey(this.flowSwitchModelItem.Properties["Cases"], uniqueCase))
                                {
                                    this.internalDefaultCaseChange = true;
                                    this.IsDefaultCase             = oldValue;
                                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR.InvalidFlowSwitchCaseMessage));
                                }
                            }

                            this.flowSwitchModelItem.Properties["Default"].SetValue(null);
                            this.flowSwitchModelItem.Properties[FlowSwitchLabelFeature.DefaultCaseDisplayNamePropertyName].SetValue(FlowSwitchLabelFeature.DefaultCaseDisplayNameDefaultValue);

                            this.internalChange = true;
                            if (typeof(string) != typeof(T))
                            {
                                this.ModelItem.Properties["Case"].SetValue(uniqueCase);
                                GenericFlowSwitchHelper.AddCase(this.flowSwitchModelItem.Properties["Cases"], uniqueCase, defaultCase.GetCurrentValue());
                            }
                            else
                            {
                                this.ModelItem.Properties["Case"].SetValue(uniqueCase);
                                GenericFlowSwitchHelper.AddCase(this.flowSwitchModelItem.Properties["Cases"], uniqueCase, defaultCase.GetCurrentValue());
                            }
                            this.UpdateViewState(DefaultConnectorViewStateKey, GenericFlowSwitchHelper.GetString(uniqueCase, typeof(T)) + CaseViewStateKeyAppendString);
                            es.Complete();
                            this.internalChange = false;
                        }
                        this.internalDefaultCaseChange = false;
                    }
                }
            }
            this.internalDefaultCaseChange = false;
        }
示例#11
0
        private IFlowSwitchLink DeleteLinkImpl(Connector link, bool isMoveOrAutoSplit         = false,
                                               HashSet <ModelItem> referenceUpdatedModelItems = null)
        {
            IFlowSwitchLink caseKey       = null;
            ModelItem       linkModelItem = FlowchartDesigner.GetLinkModelItem(link);

            if (referenceUpdatedModelItems != null &&
                referenceUpdatedModelItems.Contains(linkModelItem))
            {
                return(caseKey);
            }
            ConnectionPoint srcConnectionPoint  = FreeFormPanel.GetSourceConnectionPoint(link);
            ConnectionPoint destConnectionPoint = FreeFormPanel.GetDestinationConnectionPoint(link);

            if (typeof(FlowStep).IsAssignableFrom(linkModelItem.ItemType))
            {
                linkModelItem.Properties["Next"].SetValue(null);
            }
            else if (typeof(FlowDecision).IsAssignableFrom(linkModelItem.ItemType))
            {
                //Determine if it is True or False branch.
                if (srcConnectionPoint.Equals(FlowchartDesigner.GetTrueConnectionPoint(srcConnectionPoint.ParentDesigner)))
                {
                    //True branch
                    linkModelItem.Properties["True"].SetValue(null);
                }
                else
                {
                    linkModelItem.Properties["False"].SetValue(null);
                }
            }
            else if (typeof(IFlowSwitchLink).IsAssignableFrom(linkModelItem.ItemType))
            {
                IFlowSwitchLink flowSwitchLink = (IFlowSwitchLink)linkModelItem.GetCurrentValue();
                caseKey = flowSwitchLink;
                //Transitioning from the fakeModelItem world to the real ModelItem world.
                FlowNode  fs = flowSwitchLink.ParentFlowSwitch;
                ModelItem realFlowSwitchMI = (this.ModelItem as IModelTreeItem).ModelTreeManager.WrapAsModelItem(fs);
                if (referenceUpdatedModelItems != null &&
                    referenceUpdatedModelItems.Contains(realFlowSwitchMI))
                {
                    return(caseKey);
                }

                if (flowSwitchLink.IsDefaultCase)
                {
                    realFlowSwitchMI.Properties["Default"].SetValue(null);

                    if (!isMoveOrAutoSplit)
                    {
                        realFlowSwitchMI.Properties[FlowSwitchLabelFeature.DefaultCaseDisplayNamePropertyName].SetValue(FlowSwitchLabelFeature.DefaultCaseDisplayNameDefaultValue);
                    }
                }
                else
                {
                    GenericFlowSwitchHelper.RemoveCase(realFlowSwitchMI.Properties["Cases"], flowSwitchLink.CaseObject);
                }
            }
            else // StartNode
            {
                this.ModelItem.Properties["StartNode"].SetValue(null);
            }

            this.StoreConnectorViewState(linkModelItem, null, srcConnectionPoint, true);
            return(caseKey);
        }
示例#12
0
        public static ModelItem GetCaseModelItem(ModelProperty casesProp, object key)
        {
            ModelItemCollection itemsCollection = casesProp.Value.Properties["ItemsCollection"].Collection;

            return(GenericFlowSwitchHelper.GetCaseModelItem(itemsCollection, key));
        }
        public void OnItemsPasted(List <object> itemsToPaste, List <object> metaData, Point pastePoint, WorkflowViewElement pastePointReference)
        {
            Fx.Assert(this.panel != null, "This code shouldn't be hit if panel is null");
            HashSet <Activity> workflowElementsPasted = new HashSet <Activity>();
            List <ModelItem>   modelItemsToSelect     = new List <ModelItem>();
            bool shouldStoreCurrentSizeViewState      = true;

            Fx.Assert(this.ModelItem is IModelTreeItem, "this.ModelItem must implement IModelTreeItem");
            using (EditingScope editingScope = ((IModelTreeItem)this.ModelItem).ModelTreeManager.CreateEditingScope(System.Activities.Presentation.SR.CollectionAddEditingScopeDescription))
            {
                if (metaData != null)
                {
                    List <ModelItem> modelItemsPerMetaData = new List <ModelItem>();
                    foreach (object designerMetaData in metaData)
                    {
                        if (designerMetaData is List <FlowNode> )
                        {
                            //This is flowchart metadata.
                            foreach (FlowNode element in designerMetaData as List <FlowNode> )
                            {
                                FlowStep step = element as FlowStep;
                                if (step != null)
                                {
                                    workflowElementsPasted.Add(step.Action);
                                }

                                if (shouldStoreCurrentSizeViewState)
                                {
                                    // Pasting may change the size of flowchart; need this to undo the size change.
                                    this.StoreCurrentSizeViewStateWithUndo();
                                    shouldStoreCurrentSizeViewState = false;
                                }

                                ModelItem item = this.ModelItem.Properties["Nodes"].Collection.Add(element);

                                // if the pasted item is a flowswitch but the default target is not in the pasted selection,
                                // reset the DefaultCaseDisplayName to "Default".
                                if (GenericFlowSwitchHelper.IsGenericFlowSwitch(item.ItemType) &&
                                    item.Properties["Default"].Value == null)
                                {
                                    item.Properties[FlowSwitchLabelFeature.DefaultCaseDisplayNamePropertyName].SetValue(FlowSwitchLabelFeature.DefaultCaseDisplayNameDefaultValue);
                                }

                                modelItemsPerMetaData.Add(item);
                                if (item != null)
                                {
                                    if (item.ItemType.Equals(typeof(FlowStep)))
                                    {
                                        modelItemsToSelect.Add(item.Properties["Action"].Value);
                                    }
                                    else
                                    {
                                        modelItemsToSelect.Add(item);
                                    }
                                }
                            }
                            if (pastePoint.X > 0 && pastePoint.Y > 0)
                            {
                                Point panelPoint = this.TranslatePoint(pastePoint, this.panel);
                                if (pastePointReference != null && !pastePointReference.Equals(this))
                                {
                                    if (pastePointReference.ModelItem != null && this.modelElement.ContainsKey(pastePointReference.ModelItem))
                                    {
                                        panelPoint = pastePointReference.TranslatePoint(pastePoint, this.panel);
                                    }
                                }
                                panelPoint.X = panelPoint.X < 0 ? 0 : panelPoint.X;
                                panelPoint.Y = panelPoint.Y < 0 ? 0 : panelPoint.Y;
                                UpdateViewStateOnPastePoint(modelItemsPerMetaData, panelPoint);
                            }
                            else
                            {
                                UpdateViewStateToAvoidOverlapOnPaste(modelItemsPerMetaData);
                            }
                            modelItemsPerMetaData.Clear();
                        }
                    }
                }

                foreach (object itemToPaste in itemsToPaste)
                {
                    Activity workflowElementToPaste = itemToPaste as Activity;
                    if (workflowElementToPaste != null && !workflowElementsPasted.Contains(workflowElementToPaste))
                    {
                        FlowStep flowStep = new FlowStep {
                            Action = workflowElementToPaste, Next = null
                        };
                        if (shouldStoreCurrentSizeViewState)
                        {
                            // Pasting may change the size of flowchart; need this to undo the size change.
                            this.StoreCurrentSizeViewStateWithUndo();
                            shouldStoreCurrentSizeViewState = false;
                        }

                        // When paste a non-flowstep object to flowchart, the existing hintsize of the object
                        // should be removed, and let flowchart panel to compute the right size.
                        VirtualizedContainerService.SetHintSize(workflowElementToPaste, null);
                        ModelItem flowStepItem = this.ModelItem.Properties["Nodes"].Collection.Add(flowStep);

                        if (flowStepItem != null)
                        {
                            modelItemsToSelect.Add(flowStepItem.Properties["Action"].Value);
                        }
                    }
                }

                editingScope.Complete();
            }

            this.Dispatcher.BeginInvoke(() =>
            {
                if (modelItemsToSelect.Count > 0 && modelItemsToSelect[0] != null)
                {
                    Keyboard.Focus(modelItemsToSelect[0].View as IInputElement);
                }
                this.Context.Items.SetValue(new Selection(modelItemsToSelect));
            },
                                        DispatcherPriority.ApplicationIdle
                                        );
        }
        // The logic is similar to UpdateCloneReferences.
        // the difference is in this function, we need to set reference by Property.
        void UpdateCloneReferenceByModelItem(FlowNode currentFlowElement,
                                             Dictionary <FlowNode, ModelItem> modelItems, Dictionary <FlowNode, FlowNode> clonedFlowElements)
        {
            if (typeof(FlowStep).IsAssignableFrom(currentFlowElement.GetType()))
            {
                FlowStep  currentFlowStep = (FlowStep)currentFlowElement;
                FlowStep  clonedFlowStep  = (FlowStep)clonedFlowElements[currentFlowElement];
                ModelItem modelItem       = modelItems[clonedFlowStep];
                FlowNode  nextFlowElement = currentFlowStep.Next;
                if (nextFlowElement != null && clonedFlowElements.ContainsKey(nextFlowElement))
                {
                    modelItem.Properties["Next"].SetValue(clonedFlowElements[nextFlowElement]);
                }
                else
                {
                    modelItem.Properties["Next"].SetValue(null);
                }
            }
            else if (typeof(FlowDecision).IsAssignableFrom(currentFlowElement.GetType()))
            {
                if (!modelItems.ContainsKey(currentFlowElement))
                {
                    Fx.Assert("Should not happen.");
                }
                FlowDecision currentFlowDecision = (FlowDecision)currentFlowElement;
                FlowDecision clonedFlowDecision  = (FlowDecision)clonedFlowElements[currentFlowElement];
                Fx.Assert(currentFlowDecision == clonedFlowDecision, "should not happen");
                ModelItem modelItem = modelItems[currentFlowElement];
                Fx.Assert(modelItem != null, "should not happen");
                FlowNode trueElement  = currentFlowDecision.True;
                FlowNode falseElement = currentFlowDecision.False;

                if (trueElement != null && clonedFlowElements.ContainsKey(trueElement))
                {
                    modelItem.Properties["True"].SetValue(clonedFlowElements[trueElement]);
                }
                else
                {
                    modelItem.Properties["True"].SetValue(null);
                }

                if (falseElement != null && clonedFlowElements.ContainsKey(falseElement))
                {
                    modelItem.Properties["False"].SetValue(clonedFlowElements[falseElement]);
                }
                else
                {
                    modelItem.Properties["False"].SetValue(null);
                }
            }
            else if (GenericFlowSwitchHelper.IsGenericFlowSwitch(currentFlowElement.GetType()))
            {
                GenericFlowSwitchHelper.ReferenceCopy(currentFlowElement.GetType().GetGenericArguments()[0],
                                                      currentFlowElement,
                                                      modelItems,
                                                      clonedFlowElements);
            }
            else
            {
                Debug.Fail("Unknown FlowNode");
            }
        }
示例#15
0
 public static object GetCase(ModelItemCollection itemsCollection, object key)
 {
     return(GenericFlowSwitchHelper.GetCaseModelItem(itemsCollection, key).GetCurrentValue());
 }
        internal Connector GetLinkOnCanvas(ModelItem srcFlowElementModelItem, ModelItem destflowElementModelItem, string propertyName)
        {
            Connector        linkOnCanvas       = null;
            ModelItem        shapeModelItem     = null;
            List <Connector> outGoingConnectors = null;

            if (!srcFlowElementModelItem.Equals(this.ModelItem))
            {
                shapeModelItem     = this.GetCorrespondingElementOnCanvas(srcFlowElementModelItem);
                outGoingConnectors = GetOutGoingConnectors(this.modelElement[shapeModelItem]);
            }
            else // Must be startNode
            {
                outGoingConnectors = GetOutGoingConnectors(this.StartSymbol);
            }

            foreach (Connector connector in outGoingConnectors)
            {
                ModelItem connectorDestModelItem     = ((VirtualizedContainerService.VirtualizingContainer)FreeFormPanel.GetDestinationConnectionPoint(connector).ParentDesigner).ModelItem;
                ModelItem connectorDestFlowElementMI = this.GetFlowElementMI(connectorDestModelItem);
                //Following condition checks if the destination for current connector is equal to the destination passed in.
                if (destflowElementModelItem != null && destflowElementModelItem.Equals(connectorDestFlowElementMI))
                {
                    if (GenericFlowSwitchHelper.IsGenericFlowSwitch(srcFlowElementModelItem.ItemType))
                    {
                        ModelItem linkModelItem = FlowchartDesigner.GetLinkModelItem(connector);
                        if (linkModelItem.Properties["IsDefaultCase"].Value.GetCurrentValue().Equals(true) && propertyName.Equals("Default"))
                        {
                            linkOnCanvas = connector;
                            break;
                        }
                        else
                        {
                            ModelItem connectorCaseMI = linkModelItem.Properties["Case"].Value;
                            if (linkModelItem.Properties["IsDefaultCase"].Value.GetCurrentValue().Equals(false))
                            {
                                string caseName = connectorCaseMI == null ? null : GenericFlowSwitchHelper.GetString(connectorCaseMI.GetCurrentValue(), connectorCaseMI.ItemType);
                                if (connectorCaseMI != null && caseName.Equals(propertyName.Substring(GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier.Length)))
                                {
                                    linkOnCanvas = connector;
                                    break;
                                }
                                else if (connectorCaseMI == null)
                                {
                                    if (GenericFlowSwitchHelper.FlowSwitchNullCaseKeyIdentifier.Equals(propertyName.Substring(GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier.Length)))
                                    {
                                        linkOnCanvas = connector;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    else if (typeof(FlowDecision).IsAssignableFrom(srcFlowElementModelItem.ItemType))
                    {
                        ConnectionPoint trueConnPoint         = FlowchartDesigner.GetTrueConnectionPoint(this.modelElement[shapeModelItem]);
                        ConnectionPoint falseConnPoint        = FlowchartDesigner.GetFalseConnectionPoint(this.modelElement[shapeModelItem]);
                        ConnectionPoint connectorSrcConnPoint = FreeFormPanel.GetSourceConnectionPoint(connector);
                        if ((propertyName.Equals("True") && connectorSrcConnPoint.Equals(trueConnPoint)) ||
                            (propertyName.Equals("False") && connectorSrcConnPoint.Equals(falseConnPoint)))
                        {
                            linkOnCanvas = connector;
                            break;
                        }
                    }
                    else    //FlowStep case.
                    {
                        linkOnCanvas = connector;
                        break;
                    }
                }
            }
            return(linkOnCanvas);
        }
示例#17
0
        public static string GenericGetCaseName <T>(ModelItemCollection collection, out string errorMessage)
        {
            int  maxName = 100000;
            Type type    = typeof(T);

            errorMessage = string.Empty;
            if (typeof(string).IsAssignableFrom(type))
            {
                string caseName = "caseN";
                for (int i = 1; i <= maxName; i++)
                {
                    caseName = string.Format(CultureInfo.InvariantCulture, SR.CaseFormat, i);
                    if (!GenericFlowSwitchHelper.ContainsCaseKey(collection, caseName))
                    {
                        break;
                    }
                }
                return(caseName);
            }
            else if (GenericFlowSwitchHelper.IsIntegralType(type))
            {
                if (type == typeof(sbyte))
                {
                    sbyte maxCount = (sbyte.MaxValue < maxName) ? sbyte.MaxValue : (sbyte)maxName;
                    for (sbyte i = 0; i <= maxCount; i++)
                    {
                        if (!GenericFlowSwitchHelper.ContainsCaseKey(collection, i))
                        {
                            return(GenericFlowSwitchHelper.GetString(i, type));
                        }
                    }
                }
                else if (type == typeof(byte))
                {
                    byte maxCount = (byte.MaxValue < maxName) ? byte.MaxValue : (byte)maxName;
                    for (byte i = 0; i <= maxCount; i++)
                    {
                        if (!GenericFlowSwitchHelper.ContainsCaseKey(collection, i))
                        {
                            return(GenericFlowSwitchHelper.GetString(i, type));
                        }
                    }
                }
                else if (type == typeof(char))
                {
                    char maxCount = unchecked ((char)maxName);
                    for (char i = (char)48; i <= maxCount; i++)
                    {
                        if (!GenericFlowSwitchHelper.ContainsCaseKey(collection, i))
                        {
                            return(GenericFlowSwitchHelper.GetString(i, type));
                        }
                    }
                }
                else if (type == typeof(short))
                {
                    short maxCount = (short)maxName;
                    for (short i = 0; i <= maxCount; i++)
                    {
                        if (!GenericFlowSwitchHelper.ContainsCaseKey(collection, i))
                        {
                            return(GenericFlowSwitchHelper.GetString(i, type));
                        }
                    }
                }
                else if (type == typeof(ushort))
                {
                    ushort maxCount = (ushort)maxName;
                    for (ushort i = 0; i <= maxCount; i++)
                    {
                        if (!GenericFlowSwitchHelper.ContainsCaseKey(collection, i))
                        {
                            return(GenericFlowSwitchHelper.GetString(i, type));
                        }
                    }
                }
                else if (type == typeof(int))
                {
                    for (int i = 0; i <= maxName; i++)
                    {
                        if (!GenericFlowSwitchHelper.ContainsCaseKey(collection, i))
                        {
                            return(GenericFlowSwitchHelper.GetString(i, type));
                        }
                    }
                }
                else if (type == typeof(uint))
                {
                    for (uint i = 0; i <= (uint)maxName; i++)
                    {
                        if (!GenericFlowSwitchHelper.ContainsCaseKey(collection, i))
                        {
                            return(GenericFlowSwitchHelper.GetString(i, type));
                        }
                    }
                }
                else if (type == typeof(long))
                {
                    for (long i = 0; i <= (long)maxName; i++)
                    {
                        if (!GenericFlowSwitchHelper.ContainsCaseKey(collection, i))
                        {
                            return(GenericFlowSwitchHelper.GetString(i, type));
                        }
                    }
                }
                else if (type == typeof(ulong))
                {
                    for (ulong i = 0; i <= (ulong)maxName; i++)
                    {
                        if (!GenericFlowSwitchHelper.ContainsCaseKey(collection, i))
                        {
                            return(GenericFlowSwitchHelper.GetString(i, type));
                        }
                    }
                }
                errorMessage = SR.InvalidFlowSwitchCaseMessage;
                return(string.Empty);
            }
            else if (type.IsEnum)
            {
                Array array = type.GetEnumValues();
                foreach (object value in array)
                {
                    if (!GenericFlowSwitchHelper.ContainsCaseKey(collection, value))
                    {
                        return(GenericFlowSwitchHelper.GetString(value, type));
                    }
                }
                errorMessage = SR.InvalidFlowSwitchCaseMessage;
                return(string.Empty);
            }
            else if (type == typeof(bool))
            {
                if (!GenericFlowSwitchHelper.ContainsCaseKey(collection, true))
                {
                    return(GenericFlowSwitchHelper.GetString(true, type));
                }
                else if (!GenericFlowSwitchHelper.ContainsCaseKey(collection, false))
                {
                    return(GenericFlowSwitchHelper.GetString(false, type));
                }
                errorMessage = SR.InvalidFlowSwitchCaseMessage;
                return(string.Empty);
            }
            return(string.Empty);
        }
        void AddFlowElementsToDesigner(IList <ModelItem> flowElementMICollection, bool addConnectorAfterLoaded = false)
        {
            Queue <ModelItem> flowElementsToProcess = new Queue <ModelItem>();
            List <UIElement>  viewsAdded            = new List <UIElement>();

            foreach (ModelItem model in flowElementMICollection)
            {
                ModelItem itemOnCanvas = GetCorrespondingElementOnCanvas(model);
                if (!this.modelElement.ContainsKey(itemOnCanvas))
                {
                    flowElementsToProcess.Enqueue(model);
                    viewsAdded.Add(ProcessAndGetModelView(itemOnCanvas));
                }
                else if (!this.panel.Children.Contains(this.modelElement[itemOnCanvas]))
                {
                    flowElementsToProcess.Enqueue(model);
                    viewsAdded.Add(this.modelElement[itemOnCanvas]);
                }
            }

            ModelItem startNodeModelItem = null;
            List <Tuple <UIElement, UIElement, ModelItem> >       elem2elemConnections  = new List <Tuple <UIElement, UIElement, ModelItem> >();
            List <Tuple <ConnectionPoint, UIElement, ModelItem> > point2elemConnections = new List <Tuple <ConnectionPoint, UIElement, ModelItem> >();

            while (flowElementsToProcess.Count > 0)
            {
                ModelItem currentMI = flowElementsToProcess.Dequeue();
                //Create links for the current FlowNode.
                //First of all check if this is connected to the start node.
                if (this.ModelItem.Properties["StartNode"].Value != null &&
                    this.ModelItem.Properties["StartNode"].Value.Equals(currentMI))
                {
                    startNodeModelItem = currentMI;
                }
                if (typeof(FlowStep).IsAssignableFrom(currentMI.ItemType))
                {
                    ModelItem linkDest = currentMI.Properties["Next"].Value;
                    if (linkDest != null)
                    {
                        ModelItem src  = GetCorrespondingElementOnCanvas(currentMI);
                        ModelItem dest = GetCorrespondingElementOnCanvas(linkDest);
                        if (!modelElement.ContainsKey(dest))
                        {
                            viewsAdded.Add(ProcessAndGetModelView(dest));
                            flowElementsToProcess.Enqueue(linkDest);
                        }
                        elem2elemConnections.Add(Tuple.Create(modelElement[src], modelElement[dest], currentMI));
                    }
                }
                else if (typeof(FlowDecision).IsAssignableFrom(currentMI.ItemType))
                {
                    ModelItem trueDest  = currentMI.Properties["True"].Value;
                    ModelItem falseDest = currentMI.Properties["False"].Value;
                    if (trueDest != null)
                    {
                        ConnectionPoint srcConnectionPoint = FlowchartDesigner.GetTrueConnectionPoint(modelElement[currentMI]);
                        ModelItem       trueDestOnCanvas   = GetCorrespondingElementOnCanvas(trueDest);
                        if (!modelElement.ContainsKey(trueDestOnCanvas))
                        {
                            viewsAdded.Add(ProcessAndGetModelView(trueDestOnCanvas));
                            flowElementsToProcess.Enqueue(trueDest);
                        }
                        point2elemConnections.Add(Tuple.Create(srcConnectionPoint, modelElement[trueDestOnCanvas], currentMI));
                    }
                    if (falseDest != null)
                    {
                        ConnectionPoint srcConnectionPoint = FlowchartDesigner.GetFalseConnectionPoint(modelElement[currentMI]);
                        ModelItem       falseDestOnCanvas  = GetCorrespondingElementOnCanvas(falseDest);
                        if (!modelElement.ContainsKey(falseDestOnCanvas))
                        {
                            viewsAdded.Add(ProcessAndGetModelView(falseDestOnCanvas));
                            flowElementsToProcess.Enqueue(falseDest);
                        }
                        point2elemConnections.Add(Tuple.Create(srcConnectionPoint, modelElement[falseDestOnCanvas], currentMI));
                    }
                }
                else if (GenericFlowSwitchHelper.IsGenericFlowSwitch(currentMI.ItemType))
                {
                    IModelTreeItem modelTreeItem = this.ModelItem as IModelTreeItem;
                    ModelItem      defaultCase   = currentMI.Properties["Default"].Value;

                    if (defaultCase != null)
                    {
                        ModelItem defaultCaseOnCanvas = GetCorrespondingElementOnCanvas(defaultCase);
                        if (!modelElement.ContainsKey(defaultCaseOnCanvas))
                        {
                            viewsAdded.Add(ProcessAndGetModelView(defaultCaseOnCanvas));
                            flowElementsToProcess.Enqueue(defaultCase);
                        }
                        IFlowSwitchLink link          = GenericFlowSwitchHelper.CreateFlowSwitchLink(currentMI.ItemType, currentMI, null, true);
                        ModelItem       linkModelItem = new FakeModelItemImpl(modelTreeItem.ModelTreeManager, link.GetType(), link, null);
                        link.ModelItem = linkModelItem;

                        elem2elemConnections.Add(Tuple.Create(modelElement[currentMI], modelElement[defaultCaseOnCanvas], linkModelItem));
                    }
                    Type genericType = currentMI.ItemType.GetGenericArguments()[0];

                    foreach (ModelItem key in GenericFlowSwitchHelper.GetCaseKeys(currentMI.Properties["Cases"]))
                    {
                        ModelItem       destFlowElementMI = GenericFlowSwitchHelper.GetCaseModelItem(currentMI.Properties["Cases"], (key == null) ? null : key.GetCurrentValue());
                        IFlowSwitchLink link          = GenericFlowSwitchHelper.CreateFlowSwitchLink(currentMI.ItemType, currentMI, (key == null) ? null : key.GetCurrentValue(), false);
                        ModelItem       linkModelItem = new FakeModelItemImpl(modelTreeItem.ModelTreeManager, link.GetType(), link, null);
                        link.ModelItem = linkModelItem;
                        ModelItem destModelItem = GetCorrespondingElementOnCanvas(destFlowElementMI);
                        if (!modelElement.ContainsKey(destModelItem))
                        {
                            viewsAdded.Add(ProcessAndGetModelView(destModelItem));
                            flowElementsToProcess.Enqueue(destFlowElementMI);
                        }

                        elem2elemConnections.Add(Tuple.Create(modelElement[currentMI], modelElement[destModelItem], linkModelItem));
                    }
                }
                else
                {
                    Fx.Assert(false, "Unknown type of FlowNode");
                }
            }

            if (!this.startNodeAdded)
            {
                panel.Children.Add(this.StartSymbol);
                this.startNodeAdded = true;
            }
            foreach (UIElement view in viewsAdded)
            {
                panel.Children.Add(view);
            }

            // connection between flownode should be create only after all flownodes have been loaded on the canvas
            if (addConnectorAfterLoaded)
            {
                this.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>
                {
                    if (this.isLoaded)
                    {
                        AddConnectorsToPanel(startNodeModelItem, elem2elemConnections, point2elemConnections);
                    }
                }));
            }
            else
            {
                AddConnectorsToPanel(startNodeModelItem, elem2elemConnections, point2elemConnections);
            }
        }
        //For flowchart reacting to ModelItem changes we are concerned of the following scenarios:
        //1. FlowElements being deleted from the Flowchart.Nodes collection or Flowswitch cases being deleted from ItemsCollection
        //2. FlowElements being added to the Flowchart.Nodes collection or Flowswitch cases being added from ItemsCollection
        //3. Properties being changed in FlowStep(Next), FlowDecision(True, false), FlowSwitch(Default) (Any of the flowelemnet should be present in the elements collection).
        //4. Flowswitch cases being added/remove via Cases.Dicitionary
        void ModelTreeManager_EditingScopeCompleted(object sender, EditingScopeEventArgs e)
        {
            Fx.Assert(this.panel != null, "This code should not be hit if panel is null");
            foreach (Change change in e.EditingScope.Changes)
            {
                //Case 1, 2.
                if (change is CollectionChange)
                {
                    CollectionChange collectionChange = change as CollectionChange;
                    if (collectionChange.Collection.Equals(this.ModelItem.Properties["Nodes"].Collection))
                    {
                        if (collectionChange.Operation == CollectionChange.OperationType.Delete)
                        {
                            this.DeleteShapeVisual(this.flowNodeToUIElement[collectionChange.Item]);
                        }
                        else
                        {
                            this.AddFlowElementsToDesigner(new List <ModelItem> {
                                collectionChange.Item
                            });
                            //An editing scope change references the ModelItem.
                            //Hence in case of multiple changes to the same modelItem within the same EditingScope, we will see all the changes on the ModelItem for each change.
                            //Eg. Suppose following two changes are in the same editing scope: 1. Add ModelItem item1 to Collection, 2. Change a property on this MI, item1.Prop1
                            //In this case, EditingScope.Changes.Count will be 2.
                            //Since an EditingScope change keeps a reference to the ModelItem changed, when we process the first change, the second change would already be reflected on the ModelItem.
                            //Hence, while processing CollectionChange for item1, item1.Prop1 will already reflect the new value.
                            //Also there will be another change notifying the change in item1.Prop1.
                            //AddFlowElementsToDesigner() method, walks through the properties of a newly added item and creates any links if required.
                            //This is necessary for Paste scenario where we want to create links between Items added to the Nodes Collection.
                            //Because of this behavior of AddFlowElementsToDesigner(), before reacting to a property change for adding a link, we will always verify that the link does not already exists.
                        }
                    }
                    if (collectionChange.Collection.Parent != null && collectionChange.Collection.Parent.Parent != null &&
                        this.ModelItem.Properties["Nodes"].Collection.Contains(collectionChange.Collection.Parent.Parent) &&
                        collectionChange.Collection.Parent.Parent.ItemType.IsGenericType &&
                        collectionChange.Collection.Parent.Parent.ItemType.GetGenericTypeDefinition() == typeof(FlowSwitch <>))
                    {
                        ModelItem item     = collectionChange.Item;
                        string    caseName = GenericFlowSwitchHelper.GetString(item.Properties["Key"].ComputedValue, item.Properties["Key"].PropertyType);

                        Connector connector = this.GetLinkOnCanvas(collectionChange.Collection.Parent.Parent,
                                                                   item.Properties["Value"].Value, GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier + caseName);
                        if (collectionChange.Operation == CollectionChange.OperationType.Delete)
                        {
                            if (connector != null)
                            {
                                this.DeleteLinkVisual(connector);
                            }
                        }
                        else if (collectionChange.Operation == CollectionChange.OperationType.Insert)
                        {
                            if (connector == null)
                            {
                                //Prepending GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier to differentiate between the FlowSwitch's Property Default and key Default.
                                connector = this.CreatePropertyLink(collectionChange.Collection.Parent.Parent,
                                                                    item.Properties["Value"].Value,
                                                                    GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier + caseName);
                                Fx.Assert(connector != null, "Link not created");
                                this.panel.Children.Add(connector);
                            }
                            else
                            {
                                RefreshFlowSwitchLinkModelItem(/* flowSwitchModelItem = */ collectionChange.Collection.Parent.Parent, connector, false);
                            }
                        }
                    }
                }
                else if (change is DictionaryChange)
                {
                    // case 4
                    DictionaryChange dictionaryChange = change as DictionaryChange;

                    if (dictionaryChange.Dictionary.Parent != null &&
                        this.ModelItem.Properties["Nodes"].Collection.Contains(dictionaryChange.Dictionary.Parent) &&
                        dictionaryChange.Dictionary.Parent.ItemType.IsGenericType &&
                        dictionaryChange.Dictionary.Parent.ItemType.GetGenericTypeDefinition() == typeof(FlowSwitch <>))
                    {
                        ModelItem flowSwitchModelItem = dictionaryChange.Dictionary.Parent;
                        ModelItem caseTargetModelItem = dictionaryChange.Value;
                        string    caseName            = GenericFlowSwitchHelper.GetString(dictionaryChange.Key == null ? null : dictionaryChange.Key.GetCurrentValue(), dictionaryChange.Key == null ? null : dictionaryChange.Key.ItemType);
                        string    caseNameInModelItem = GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier + caseName;

                        Connector connector = this.GetLinkOnCanvas(
                            flowSwitchModelItem,
                            caseTargetModelItem,
                            caseNameInModelItem);

                        if (dictionaryChange.Operation == DictionaryChange.OperationType.Delete)
                        {
                            if (connector != null)
                            {
                                this.DeleteLinkVisual(connector);
                            }
                        }
                        else if (dictionaryChange.Operation == DictionaryChange.OperationType.Insert)
                        {
                            if (connector == null)
                            {
                                connector = this.CreatePropertyLink(
                                    flowSwitchModelItem,
                                    caseTargetModelItem,
                                    caseNameInModelItem);
                                this.panel.Children.Add(connector);
                            }
                        }
                    }
                }
                //Case 3.
                else if (change is PropertyChange)
                {
                    PropertyChange propertyChange = change as PropertyChange;

                    if (this.ModelItem.Properties["Nodes"].Collection.Contains(propertyChange.Owner) ||
                        (propertyChange.PropertyName == "StartNode" && propertyChange.Owner == this.ModelItem))
                    {
                        if (propertyChange.OldValue != null &&
                            IsFlowNode(propertyChange.OldValue))
                        {
                            Connector link = GetLinkOnCanvas(propertyChange.Owner, propertyChange.OldValue, propertyChange.PropertyName);
                            //Debug.Assert(link != null, "Link not found on designer");
                            if (link != null)
                            {
                                this.DeleteLinkVisual(link);
                            }
                        }
                        if (propertyChange.NewValue != null &&
                            IsFlowNode(propertyChange.NewValue))
                        {
                            Connector oldLink = GetLinkOnCanvas(propertyChange.Owner, propertyChange.NewValue, propertyChange.PropertyName);
                            //If this connector has already been added don't add again.
                            if (oldLink == null)
                            {
                                Connector link = CreatePropertyLink(propertyChange.Owner, propertyChange.NewValue, propertyChange.PropertyName);
                                Fx.Assert(link != null, "Link not created");
                                this.panel.Children.Add(link);
                            }
                            else
                            {
                                if (GenericFlowSwitchHelper.IsGenericFlowSwitch(propertyChange.Owner.ItemType))
                                {
                                    this.RefreshFlowSwitchLinkModelItem(/* flowSwitchModelItem = */ propertyChange.Owner, oldLink, true);
                                }
                            }
                        }

                        //handling for the case where the FlowStep.Action changes:
                        //Explicitly adding a check for FlowStep, because other FlowNodes have properties of type Activity, which we don't want to react to.
                        //AddFlowElementsToDesigner() will add the links originating out of the shape that is changing.
                        //We have to take care of refreshing the links coming into the shape that is changing.
                        if (typeof(FlowStep).IsAssignableFrom(propertyChange.Owner.ItemType))
                        {
                            List <Connector> oldIncomingConnectors = new List <Connector>();
                            if (propertyChange.OldValue != null && IsFlowStepAction(propertyChange.OldValue))
                            {
                                UIElement oldShape = this.flowNodeToUIElement[propertyChange.Owner];
                                oldIncomingConnectors = this.GetInComingConnectors(oldShape);
                                this.DeleteShapeVisual(oldShape);
                            }
                            if (propertyChange.NewValue != null && IsFlowStepAction(propertyChange.NewValue))
                            {
                                this.AddFlowElementsToDesigner(new List <ModelItem> {
                                    propertyChange.Owner
                                });
                                foreach (Connector oldConnector in oldIncomingConnectors)
                                {
                                    Connector newConnector = CreateLink(FreeFormPanel.GetSourceConnectionPoint(oldConnector),
                                                                        this.flowNodeToUIElement[propertyChange.Owner], FlowchartDesigner.GetLinkModelItem(oldConnector));
                                    this.panel.Children.Add(newConnector);
                                }
                            }
                        }
                    }
                }
            }
        }
        void OnViewStateChanged(object sender, ViewStateChangedEventArgs e)
        {
            Fx.Assert(this.panel != null, "This code should not be hit if panel is null");
            Fx.Assert(e.ParentModelItem != null, "ViewState should be associated with some modelItem");
            Connector changedConnector = null;

            if (e.ParentModelItem == this.ModelItem)
            {
                if (string.Equals(e.Key, FlowchartSizeFeature.WidthPropertyName, StringComparison.Ordinal))
                {
                    this.FlowchartWidth = (double)TypeDescriptor.GetProperties(this.ModelItem)[FlowchartSizeFeature.WidthPropertyName].GetValue(this.ModelItem);
                }
                else if (string.Equals(e.Key, FlowchartSizeFeature.HeightPropertyName, StringComparison.Ordinal))
                {
                    this.FlowchartHeight = (double)TypeDescriptor.GetProperties(this.ModelItem)[FlowchartSizeFeature.HeightPropertyName].GetValue(this.ModelItem);
                }
            }
            if ((IsFlowNode(e.ParentModelItem) || this.ModelItem.Equals(e.ParentModelItem)) && !this.internalViewStateChange)
            {
                ModelItem itemOnCanvas = this.GetCorrespondingElementOnCanvas(e.ParentModelItem);
                if (this.modelElement.ContainsKey(itemOnCanvas))
                {
                    if (e.Key.Equals(shapeLocation))
                    {
                        if (e.NewValue != null)
                        {
                            FreeFormPanel.SetLocation(this.modelElement[itemOnCanvas], (Point)e.NewValue);
                            this.panel.InvalidateMeasure();
                            if (e.OldValue != null)
                            {
                                this.shapeLocations.Remove((Point)e.OldValue);
                            }
                            this.shapeLocations.Add((Point)e.NewValue);
                        }
                    }
                    else
                    {
                        if (this.ModelItem.Equals(e.ParentModelItem) &&
                            e.Key.Equals(ConnectorViewStateKey))
                        {
                            changedConnector = this.GetLinkOnCanvas(e.ParentModelItem, e.ParentModelItem.Properties["StartNode"].Value, "StartNode");
                        }
                        else if (typeof(FlowStep).IsAssignableFrom(e.ParentModelItem.ItemType) &&
                                 e.Key.Equals(ConnectorViewStateKey))
                        {
                            changedConnector = this.GetLinkOnCanvas(e.ParentModelItem, e.ParentModelItem.Properties["Next"].Value, "Next");
                        }
                        else if (typeof(FlowDecision).IsAssignableFrom(e.ParentModelItem.ItemType))
                        {
                            if (e.Key.Equals(TrueConnectorViewStateKey))
                            {
                                changedConnector = this.GetLinkOnCanvas(e.ParentModelItem, e.ParentModelItem.Properties["True"].Value, "True");
                            }
                            else if (e.Key.Equals(FalseConnectorViewStateKey))
                            {
                                changedConnector = this.GetLinkOnCanvas(e.ParentModelItem, e.ParentModelItem.Properties["False"].Value, "False");
                            }
                        }
                        else if (GenericFlowSwitchHelper.IsGenericFlowSwitch(e.ParentModelItem.ItemType))
                        {
                            if (e.Key.Equals(FlowchartDesigner.FlowSwitchDefaultViewStateKey, StringComparison.CurrentCulture))
                            {
                                changedConnector = this.GetLinkOnCanvas(e.ParentModelItem, e.ParentModelItem.Properties["Default"].Value, e.Key);
                            }
                            else if (e.Key.EndsWith(CaseViewStateKeyAppendString, StringComparison.CurrentCulture))
                            {
                                string switchCaseName = e.Key.Substring(0, e.Key.Length - CaseViewStateKeyAppendString.Length);
                                object switchCase     = switchCaseName;
                                Type   genericType    = e.ParentModelItem.ItemType.GetGenericArguments()[0];
                                switchCase = GenericFlowSwitchHelper.GetObject(switchCaseName, genericType);

                                if (GenericFlowSwitchHelper.ContainsCaseKey(e.ParentModelItem.Properties["Cases"], switchCase))
                                {
                                    //Prepending with GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier to differentiate between the property Default and the key Default.
                                    changedConnector = this.GetLinkOnCanvas(e.ParentModelItem, GenericFlowSwitchHelper.GetCaseModelItem(e.ParentModelItem.Properties["Cases"], switchCase), GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier + switchCase);
                                }
                            }
                        }
                    }
                }
            }
            if (changedConnector != null)
            {
                if (e.NewValue != null)
                {
                    Fx.Assert(e.NewValue is PointCollection, "e.NewValue is not PointCollection");
                    changedConnector.Points = e.NewValue as PointCollection;
                    this.panel.RemoveConnectorEditor();
                    this.panel.InvalidateMeasure();
                }
            }
        }
示例#21
0
 public static bool CanBeGeneratedUniquely(Type typeArgument)
 {
     return(typeArgument.IsEnum || typeof(string).IsAssignableFrom(typeArgument) ||
            GenericFlowSwitchHelper.IsIntegralType(typeArgument) || typeof(bool) == typeArgument);
 }