/// <summary> /// This is called by AddUndo, so that primitives are always in a fully merged state as we go. /// </summary> protected void MergeMostRecentUndoPrimitive() { // no merging unless there are at least two items if (_primitives.Count < 2) { return; } ITextUndoPrimitive top = _primitives[_primitives.Count - 1]; ITextUndoPrimitive victim = null; int victimIndex = -1; for (int i = _primitives.Count - 2; i >= 0; --i) { if (top.GetType() == _primitives[i].GetType() && top.CanMerge(_primitives[i])) { victim = _primitives[i]; victimIndex = i; break; } } if (victim != null) { ITextUndoPrimitive newPrimitive = top.Merge(victim); _primitives.RemoveRange(_primitives.Count - 1, 1); _primitives.RemoveRange(victimIndex, 1); _primitives.Add(newPrimitive); } }
public bool CanMerge(ITextUndoTransaction newTransaction, ITextUndoTransaction oldTransaction) { MergeUndoActionPolicy oldPolicy = oldTransaction.MergePolicy as MergeUndoActionPolicy; MergeUndoActionPolicy newPolicy = newTransaction.MergePolicy as MergeUndoActionPolicy; if (oldPolicy != null && oldPolicy._mergeNext && newPolicy != null && newPolicy._mergePrevious && oldPolicy._actionName == newPolicy._actionName) { // If one of the transactions is empty, than it is safe to merge if (newTransaction.UndoPrimitives.Count == 0 || oldTransaction.UndoPrimitives.Count == 0) { return(true); } // Make sure that we only merge consecutive edits ITextUndoPrimitive newPrimitive = newTransaction.UndoPrimitives[0]; ITextUndoPrimitive oldPrimitive = oldTransaction.UndoPrimitives[oldTransaction.UndoPrimitives.Count - 1]; return(newPrimitive.CanMerge(oldPrimitive)); } return(false); }
public bool CanMerge(ITextUndoTransaction newTransaction, ITextUndoTransaction oldTransaction) { // Validate if (newTransaction == null) { throw new ArgumentNullException(nameof(newTransaction)); } if (oldTransaction == null) { throw new ArgumentNullException(nameof(oldTransaction)); } TextTransactionMergePolicy oldPolicy = oldTransaction.MergePolicy as TextTransactionMergePolicy; TextTransactionMergePolicy newPolicy = newTransaction.MergePolicy as TextTransactionMergePolicy; if (oldPolicy == null || newPolicy == null) { throw new InvalidOperationException("The MergePolicy for both transactions should be a TextTransactionMergePolicy."); } // Make sure the merge policy directions permit merging these two transactions. if ((oldPolicy._allowableMergeDirections & TextTransactionMergeDirections.Forward) == 0 || (newPolicy._allowableMergeDirections & TextTransactionMergeDirections.Backward) == 0) { return(false); } // Only merge text transactions that have the same description if (!string.Equals(newTransaction.Description, oldTransaction.Description, StringComparison.Ordinal)) { return(false); } // If one of the transactions is empty, than it is safe to merge if ((newTransaction.UndoPrimitives.Count == 0) || (oldTransaction.UndoPrimitives.Count == 0)) { return(true); } // Make sure that we only merge consecutive edits ITextUndoPrimitive newerBeforeTextChangePrimitive = newTransaction.UndoPrimitives[0]; ITextUndoPrimitive olderAfterTextChangePrimitive = oldTransaction.UndoPrimitives[oldTransaction.UndoPrimitives.Count - 1]; return(newerBeforeTextChangePrimitive.CanMerge(olderAfterTextChangePrimitive)); }