private void Merge(XmlModelCommand newCommand) { // Some commands have to be merged (for example if the name or value of the same // node is changed twice) because the SourceModifier is not designed to update // stuff it just inserted into the buffer during the same transaction. List<XmlModelCommand> toRemove = null; foreach (var cmd in txCommands) { if (newCommand != cmd && newCommand.Merge(cmd)) { if (toRemove == null) { toRemove = new List<XmlModelCommand>(); } toRemove.Add(cmd); } } RemoveRange(txCommands, toRemove); // And remove this from undo list also, since we have edited the same command objects! RemoveRange(undoCommands, toRemove); }
internal void AddCommand(XmlModelCommand cmd) { var change = cmd.Change; var node = change.Node; if (change.Action == XObjectChange.Remove) { // If we are removing a node, then all changes to any descendent of this node // can be discarded since the whole thing will be ripped out of the buffer anyway. var rs = RemoveAllDescendentChanges(change); if (rs == RemoveStatus.FoundSelfAdd) { /* * 9/21/2007 - not sure what to do about the stuff below. Seems specific to the editor * so commenting it out. * // then this remove is a no-op, unless the Add operation is one of those // special ones where the buffer already contained the value - in this case // the Remove operation is real, and the add operation is a no-op, otherwise // they both cancel each other out. string bufferValue = XmlEditorNoPushToBuffer(change.Node); if (bufferValue == null) { return; } */ } } if (IsAncestorAdded(node, change.Parent)) { // If the ancestor was added by this transaction, then we can ignore the child // command because the XLink insert will insert the entire thing into the buffer // including all changes already made by the child transaction. return; } switch (change.Action) { case XObjectChange.Add: AddNode(node); // record the add operation. break; case XObjectChange.Name: Merge(cmd); // Name changes must be done first, because an Add operation might // cause a short end tag <A/> to be converted to <A></A>, and then // a rename after that of the same node would result in two edit // operations on the same end tag which is not supported by SourceModifier. undoCommands.Insert(0, cmd); txCommands.Insert(0, cmd); return; case XObjectChange.Value: Merge(cmd); break; case XObjectChange.Remove: break; } txCommands.Add(cmd); }