|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
// Description: Helper class for TextContainer, handles all undo operations.
//
using MS.Internal.Documents;
namespace System.Windows.Documents
{
// This static class is logically an extension of TextContainer. It contains
// TextContainer undo related helpers.
internal static class TextTreeUndo
{
//------------------------------------------------------
//
// Internal Methods
//
//------------------------------------------------------
#region Internal Methods
// Adds a TextTreeInsertUndoUnit to the open parent undo unit, if any.
// Called from TextContainer.InsertText and TextContainer.InsertEmbeddedObject.
internal static void CreateInsertUndoUnit(TextContainer tree, int symbolOffset, int symbolCount)
{
UndoManager undoManager;
undoManager = GetOrClearUndoManager(tree);
if (undoManager == null)
return;
undoManager.Add(new TextTreeInsertUndoUnit(tree, symbolOffset, symbolCount));
}
// Adds a TextTreeInsertElementUndoUnit to the open parent undo unit, if any.
// Called from TextContainer.InsertElement.
internal static void CreateInsertElementUndoUnit(TextContainer tree, int symbolOffset, bool deep)
{
UndoManager undoManager;
undoManager = GetOrClearUndoManager(tree);
if (undoManager == null)
return;
undoManager.Add(new TextTreeInsertElementUndoUnit(tree, symbolOffset, deep));
}
// Adds a TextTreePropertyUndoUnit to the open parent undo unit, if any.
// Called by TextElement's property change listener.
internal static void CreatePropertyUndoUnit(TextElement element, DependencyPropertyChangedEventArgs e)
{
UndoManager undoManager;
PropertyRecord record;
TextContainer textContainer = element.TextContainer;
undoManager = GetOrClearUndoManager(textContainer);
if (undoManager == null)
return;
record = new PropertyRecord();
record.Property = e.Property;
record.Value = e.OldValueSource == BaseValueSourceInternal.Local ? e.OldValue : DependencyProperty.UnsetValue;
undoManager.Add(new TextTreePropertyUndoUnit(textContainer, element.TextElementNode.GetSymbolOffset(textContainer.Generation) + 1, record));
}
// Adds a DeleteContentUndoUnit to the open parent undo unit, if any.
// Called by TextContainer.DeleteContent.
internal static TextTreeDeleteContentUndoUnit CreateDeleteContentUndoUnit(TextContainer tree, TextPointer start, TextPointer end)
{
UndoManager undoManager;
TextTreeDeleteContentUndoUnit undoUnit;
if (start.CompareTo(end) == 0)
return null;
undoManager = GetOrClearUndoManager(tree);
if (undoManager == null)
return null;
undoUnit = new TextTreeDeleteContentUndoUnit(tree, start, end);
undoManager.Add(undoUnit);
return undoUnit;
}
// Adds a TextTreeExtractElementUndoUnit to the open parent undo unit, if any.
// Called by TextContainer.ExtractElement.
internal static TextTreeExtractElementUndoUnit CreateExtractElementUndoUnit(TextContainer tree, TextTreeTextElementNode elementNode)
{
UndoManager undoManager;
TextTreeExtractElementUndoUnit undoUnit;
undoManager = GetOrClearUndoManager(tree);
if (undoManager == null)
return null;
undoUnit = new TextTreeExtractElementUndoUnit(tree, elementNode);
undoManager.Add(undoUnit);
return undoUnit;
}
// Returns the local UndoManager.
// Returns null if there is no undo service or if the service exists
// but is disabled or if there is no open parent undo unit.
internal static UndoManager GetOrClearUndoManager(ITextContainer textContainer)
{
UndoManager undoManager;
undoManager = textContainer.UndoManager;
if (undoManager == null)
return null;
if (!undoManager.IsEnabled)
return null;
if (undoManager.OpenedUnit == null)
{
// There's no parent undo unit, so we can't open a child.
//
// Clear the undo stack -- since we depend on symbol offsets
// matching the original document state when an undo unit is
// executed, any of our units currently in the stack will be
// corrupted after we finished the operation in progress.
undoManager.Clear();
return null;
}
return undoManager;
}
#endregion Internal methods
}
}
|