/// <summary> /// This method will reload the artifact from the XLinq tree. This *DOES NOT* do a 'deep reloading', i.e. reloading from disk. /// </summary> internal virtual void ReloadArtifact() { try { IsArtifactReloading = true; // clear out the artifact set of our information ArtifactSet.RemoveArtifact(this); ArtifactSet.Add(this); // reparse this artifact State = EFElementState.None; Parse(new List <XName>()); if (State == EFElementState.Parsed) { XmlModelHelper.NormalizeAndResolve(this); } // this will do some analysis to determine if the artifact is safe for the designer, or should be displayed in the xml editor DetermineIfArtifactIsDesignerSafe(); FireArtifactReloadedEvent(); _requiresReloading = false; IsDirty = false; } finally { IsArtifactReloading = false; } }
/// <summary> /// Reload the EntityDesignArtifact and DiagramArtifact (if available). /// </summary> internal override void ReloadArtifact() { try { IsArtifactReloading = true; // clear out the artifact set of our information ArtifactSet.RemoveArtifact(this); ArtifactSet.Add(this); // Reparse the artifact. State = EFElementState.None; Parse(new List <XName>()); if (State == EFElementState.Parsed) { XmlModelHelper.NormalizeAndResolve(this); } // NOTE: DiagramArtifact must be reloaded after EntityDesignArtifact finishes reloading but before we fire artifact reloaded event. if (DiagramArtifact != null) { DiagramArtifact.ReloadArtifact(); } // this will do some analysis to determine if the artifact is safe for the designer, or should be displayed in the xml editor DetermineIfArtifactIsDesignerSafe(); FireArtifactReloadedEvent(); RequireDelayedReload = false; IsDirty = false; } finally { IsArtifactReloading = false; } }
private void ProcessExternalAddOrUpdateChange( EfiChangeGroup changeGroup, List <EFContainer> containersToRenormalize, ExternalXMLModelChange undoModelChange) { var changedEFObject = undoModelChange.ChangedEFObject; var parentEFObject = undoModelChange.Parent; if (parentEFObject != null) { var parentEFContainer = parentEFObject as EFContainer; Debug.Assert(parentEFContainer != null, "parentEFObject was not an EFContainer!"); // if this is an "add" for an element, then the parent will parse the new child. // if this is an "add" for an attribute, then we have to directly set the XObject // if this is an "update" then we will just record it in our model if (parentEFContainer != null && undoModelChange.Action == XObjectChange.Add) { var newXElement = undoModelChange.XNode as XElement; if (newXElement != null && parentEFContainer.ReparseSingleElement(new List <XName>(), newXElement)) { var newEFObject = ModelItemAnnotation.GetModelItem(undoModelChange.XNode); Debug.Assert(newEFObject != null, "Couldn't find the ModelItemAnnotation for the newly created XLinq node"); if (newEFObject != null) { var newEFElement = newEFObject as EFElement; Debug.Assert(newEFElement != null, "If the XObject was an XElement, then we should have an EFElement as well"); if (newEFElement != null) { XmlModelHelper.NormalizeAndResolve(newEFElement); } // we need to rediscover the XLinq annotation to pick up the new EFObject that just got created changedEFObject = ModelItemAnnotation.GetModelItem(undoModelChange.XNode); } } else if (undoModelChange.XNode is XAttribute) { var staleItemBinding = changedEFObject as ItemBinding; var staleDefaultableValue = changedEFObject as DefaultableValue; // item bindings might have gotten added after their parents got added in which case the MIA will be stale. // we have to step through the new parent, set the xobject manually, rebind, and reset the annotation on the xlinq node. if (staleItemBinding != null) { foreach (var child in parentEFContainer.Children) { var updatedItemBinding = child as ItemBinding; if (updatedItemBinding != null && updatedItemBinding.EFTypeName == staleItemBinding.EFTypeName) { updatedItemBinding.SetXObject(undoModelChange.XNode); updatedItemBinding.Rebind(); changedEFObject = updatedItemBinding; } } } // for defaultable values that got added after parents were added, we have to discover the actual EFObject in the Escher tree, // set the xobject, and reset the annotation on the existing xlinq node else if (staleDefaultableValue != null) { foreach (var child in parentEFContainer.Children) { var updatedDefaultableValue = child as DefaultableValue; if (updatedDefaultableValue != null && updatedDefaultableValue.EFTypeName == staleDefaultableValue.EFTypeName) { updatedDefaultableValue.SetXObject(undoModelChange.XNode); changedEFObject = updatedDefaultableValue; } } } ModelItemAnnotation.SetModelItem(undoModelChange.XNode, changedEFObject); } } else if (undoModelChange.Action == XObjectChange.Value) { Debug.Assert(undoModelChange.XNode is XAttribute, "The only 'value' change Escher supports is to XAttributes"); if (undoModelChange.XNode is XAttribute) { var existingItemBinding = changedEFObject as ItemBinding; if (existingItemBinding != null) { existingItemBinding.Rebind(); } // we have to normalize and resolve the parents of DefaultableValues // because this change could affect the parent's RefName, affecting SingleItemBindings var defaultableValue = changedEFObject as DefaultableValue; if (defaultableValue != null) { XmlModelHelper.NormalizeAndResolve(parentEFContainer); #if DEBUG var xattr = undoModelChange.XNode as XAttribute; var defaultableValueValue = defaultableValue.ObjectValue as string; if (defaultableValueValue != null) { // verify that the defaultableValue's value & the XAttribute's value are the same Debug.Assert(xattr.Value == defaultableValueValue); } #endif } } } else { Debug.Assert(false, "Encountered a non-valid type of change to the XML: " + undoModelChange.Action.ToString()); throw new ChangeProcessingFailedException(); } // if an object's state is unresolved, then queue it for re-normalization. This occurs // for example, if itembinding changes occur before the 'add' changes for their targeted objects var itemBinding = changedEFObject as ItemBinding; if ((itemBinding != null && false == itemBinding.Resolved) || parentEFContainer.State != EFElementState.Resolved) { containersToRenormalize.Add(parentEFContainer); } CheckObjectToRenormalize(changedEFObject, ref containersToRenormalize); // now tell the views that a new item has been created; this will happen for both an 'add' and a 'change' string oldValue = null; string newValue = null; string property = null; GetOldAndNewValues(undoModelChange.XmlChange, out property, out oldValue, out newValue); changeGroup.RecordModelChange(GetChangeType(undoModelChange.XmlChange), changedEFObject, property, oldValue, newValue); } else { // we got a change event on a root-node in the document. // This will cause an NRE when looking for the model-item annotation, // so throw this exception to cause the caller to reload the doc throw new ChangeProcessingFailedException(); } }
private EfiChangeGroup ProcessUndoRedoChanges(XmlTransactionEventArgs xmlTransactionEventArgs) { using (var tx = new EfiTransaction(this, EfiTransactionOriginator.UndoRedoOriginatorId, xmlTransactionEventArgs.Transaction)) { var changeGroup = tx.ChangeGroup; var undoChanges = new List <ExternalXMLModelChange>(); var containersToRenormalize = new List <EFContainer>(); var bindingsForRebind = new List <ItemBinding>(); var namespaces = GetNamespaces(); // filter the changes received from XmlEditor and resolve changed EFObjects and their parents foreach (var xmlChange in xmlTransactionEventArgs.Transaction.Changes()) { // determine how to process this edit if (xmlChange.Node.NodeType == XmlNodeType.Element || xmlChange.Node.NodeType == XmlNodeType.Attribute || xmlChange.Node.NodeType == XmlNodeType.Document) { if (xmlChange.Node.NodeType == XmlNodeType.Element && xmlChange.Action == XObjectChange.Value) { var nodeValueChange = xmlChange as IXmlNodeValueChange; Debug.Assert( nodeValueChange != null && string.IsNullOrEmpty(nodeValueChange.OldValue) && string.IsNullOrEmpty(nodeValueChange.NewValue)); // in cases where we are undoing the addition of all children to an element A, the Xml Model // will forcibly add an empty string to the element A so that a "short" end tag "/>" is not created // in this case, the change we will receive is a set value change on an element; we ignore this } else { var emc = new ExternalXMLModelChange(xmlChange, ExpectEFObjectForXObject); if (emc.IsAnnotationChange(namespaces)) { continue; } undoChanges.Add(emc); } } } // go through the undo changes and make changes to the model foreach (var undoModelChange in undoChanges) { // Should ignore other artifact changes. if (undoModelChange.ChangedEFObject.Artifact != this) { continue; } if (undoModelChange.Action == XObjectChange.Remove) { ProcessExternalRemoveChange(changeGroup, bindingsForRebind, undoModelChange); } else { ProcessExternalAddOrUpdateChange(changeGroup, containersToRenormalize, undoModelChange); } } // because of the order in which elements were possibly added, certain ItemBindings were not resolved; // therefore we have to step through the normalized EFElements again and normalize/resolve so their child // ItemBindings will get resolved. foreach (var container in containersToRenormalize) { XmlModelHelper.NormalizeAndResolve(container); } XmlModelHelper.RebindItemBindings(bindingsForRebind); #if DEBUG var visitor = GetVerifyModelIntegrityVisitor(); visitor.Traverse(this); if (visitor.ErrorCount > 0) { Debug.WriteLine("Model Integrity Verifier found " + visitor.ErrorCount + " error(s):"); Debug.WriteLine(visitor.AllSerializedErrors); Debug.Assert( false, "Model Integrity Verifier found " + visitor.ErrorCount + " error(s). See the Debug console for details."); } #endif return(changeGroup); } }