FakeModelItemImpl WrapValue(object value)
        {
            FakeModelItemImpl wrappedValue = value as FakeModelItemImpl;

            if (null == wrappedValue && null != value)
            {
                wrappedValue = new FakeModelItemImpl(this.parentModelTreeItem.ModelTreeManager, this.PropertyType, value, (FakeModelItemImpl)this.Parent);
            }
            return(wrappedValue);
        }
        public override ModelItem SetValue(object value)
        {
            //are we already setting value? 
            if (!isSettingValue)
            {
                try
                {
                    this.isSettingValue = true;
                    //create new value
                    this.temporaryValue = this.WrapValue(value);
                    //is there a value stored already?
                    if (this.parentModelTreeItem.ModelPropertyStore.ContainsKey(this.Name))
                    {
                        //yes - cleanup references
                        IModelTreeItem item = (IModelTreeItem)this.parentModelTreeItem.ModelPropertyStore[this.Name];
                        item.RemoveSource(this);
                        item.RemoveParent(this.parentModelTreeItem.ModelItem);
                        //and remove it
                        this.parentModelTreeItem.ModelPropertyStore.Remove(this.Name);
                    }
                    //set it onto underlying object
                    this.PropertyDescriptor.SetValue(this.Parent.GetCurrentValue(), (null != this.temporaryValue ? this.temporaryValue.GetCurrentValue() : null));
                    //store it in parent's store
                    this.temporaryValue = this.StoreValue(this.temporaryValue);

                    //notify listeners - notification must be postponed until actual underlying object value is updated, otherwise, listeners might get old value
                    this.parentModelTreeItem.ModelTreeManager.AddToCurrentEditingScope(new FakeModelNotifyPropertyChange(this.parentModelTreeItem, this.Name));
                }
                catch (ValidationException e)
                {
                    Trace.WriteLine(e.ToString());
                    //it is important to rethrow exception here - otherwise, DataGrid will assume operation completed successfully
                    throw;
                }
                finally
                {
                    this.isSettingValue = false;
                }
            }

            return this.temporaryValue;
        }
        public override ModelItem SetValue(object value)
        {
            //are we already setting value?
            if (!isSettingValue)
            {
                try
                {
                    this.isSettingValue = true;
                    //create new value
                    this.temporaryValue = this.WrapValue(value);
                    //is there a value stored already?
                    if (this.parentModelTreeItem.ModelPropertyStore.ContainsKey(this.Name))
                    {
                        //yes - cleanup references
                        IModelTreeItem item = (IModelTreeItem)this.parentModelTreeItem.ModelPropertyStore[this.Name];
                        item.RemoveSource(this);
                        item.RemoveParent(this.parentModelTreeItem.ModelItem);
                        //and remove it
                        this.parentModelTreeItem.ModelPropertyStore.Remove(this.Name);
                    }
                    //set it onto underlying object
                    this.PropertyDescriptor.SetValue(this.Parent.GetCurrentValue(), (null != this.temporaryValue ? this.temporaryValue.GetCurrentValue() : null));
                    //store it in parent's store
                    this.temporaryValue = this.StoreValue(this.temporaryValue);

                    //notify listeners - notification must be postponed until actual underlying object value is updated, otherwise, listeners might get old value
                    this.parentModelTreeItem.ModelTreeManager.AddToCurrentEditingScope(new FakeModelNotifyPropertyChange(this.parentModelTreeItem, this.Name));
                }
                catch (ValidationException e)
                {
                    Trace.WriteLine(e.ToString());
                    //it is important to rethrow exception here - otherwise, DataGrid will assume operation completed successfully
                    throw;
                }
                finally
                {
                    this.isSettingValue = false;
                }
            }

            return(this.temporaryValue);
        }
        FakeModelItemImpl StoreValue(object value)
        {
            FakeModelItemImpl wrappedValue = WrapValue(value);

            if (null != wrappedValue)
            {
                this.parentModelTreeItem.ModelPropertyStore[this.Name] = wrappedValue;
                IModelTreeItem modelTreeItem = (IModelTreeItem)wrappedValue;
                modelTreeItem.SetSource(this);
            }
            else
            {
                ModelItem existing = null;
                if (this.parentModelTreeItem.ModelPropertyStore.TryGetValue(this.Name, out existing))
                {
                    IModelTreeItem modelTreeItem = (IModelTreeItem)existing;
                    modelTreeItem.RemoveSource(this);
                    modelTreeItem.RemoveParent(this.Parent);
                }
                this.parentModelTreeItem.ModelPropertyStore.Remove(this.Name);
            }
            return(wrappedValue);
        }
 public FakeModelPropertyImpl(FakeModelItemImpl parent, PropertyDescriptor propertyDescriptor)
     : base(parent, propertyDescriptor, false)
 {
     this.parentModelTreeItem = (IModelTreeItem)parent;
 }
 FakeModelItemImpl WrapValue(object value)
 {
     FakeModelItemImpl wrappedValue = value as FakeModelItemImpl;
     if (null == wrappedValue && null != value)
     {
         wrappedValue = new FakeModelItemImpl(this.parentModelTreeItem.ModelTreeManager, this.PropertyType, value, (FakeModelItemImpl)this.Parent);
     }
     return wrappedValue;
 }
        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;

        }
        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);
            }
        }
        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);
            }
        }
        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;
        }
 public FakeModelPropertyImpl(FakeModelItemImpl parent, PropertyDescriptor propertyDescriptor)
     : base(parent, propertyDescriptor, false)
 {
     this.parentModelTreeItem = (IModelTreeItem)parent;
 }