pascalabcnet/ICSharpCode.TextEditor/Src/Undo/UndoStack.cs
miks1965 e862ff8cd4 Новый TextEditor.dll, в котором предположительно исправлена ошибка Ctrl-Z
Улучшенная генерация документации для всех новых модулей - модуль GenDocUnit.pas

Модуль WPFObjects со всеми расставленными комментариями для автогенерации документации

Сгенерированная автодокументация по модулю WPFObjects
2018-08-25 12:25:03 +03:00

224 lines
5.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
// <version>$Revision: 2659 $</version>
// </file>
using System;
using System.Collections.Generic;
using System.Drawing;
namespace ICSharpCode.TextEditor.Undo
{
/// <summary>
/// This class implements an undo stack
/// </summary>
public class UndoStack
{
Stack<IUndoableOperation> undostack = new Stack<IUndoableOperation>();
Stack<IUndoableOperation> redostack = new Stack<IUndoableOperation>();
public TextEditorControlBase TextEditorControl = null;
/// <summary>
/// </summary>
public event EventHandler ActionUndone;
/// <summary>
/// </summary>
public event EventHandler ActionRedone;
/// <summary>
/// Gets/Sets if changes to the document are protocolled by the undo stack.
/// Used internally to disable the undo stack temporarily while undoing an action.
/// </summary>
internal bool AcceptChanges = true;
/// <summary>
/// Gets if there are actions on the undo stack.
/// </summary>
public bool CanUndo {
get {
return undostack.Count > 0;
}
}
/// <summary>
/// Gets if there are actions on the redo stack.
/// </summary>
public bool CanRedo {
get {
return redostack.Count > 0;
}
}
/// <summary>
/// Gets the number of actions on the undo stack.
/// </summary>
public int UndoItemCount {
get {
return undostack.Count;
}
}
/// <summary>
/// Gets the number of actions on the redo stack.
/// </summary>
public int RedoItemCount {
get {
return redostack.Count;
}
}
// /// <summary>
// /// You call this method to pool the last x operations from the undo stack
// /// to make 1 operation from it.
// /// </summary>
// public void CombineLast(int actionCount)
// {
// undostack.Push(new UndoQueue(undostack, actionCount));
// }
int undoGroupDepth;
int actionCountInUndoGroup;
public void StartUndoGroup()
{
if (undoGroupDepth == 0) {
actionCountInUndoGroup = 0;
}
undoGroupDepth++;
}
public void EndUndoGroup()
{
if (undoGroupDepth == 0)
return;
//throw new InvalidOperationException("There are no open undo groups");
undoGroupDepth--;
if (undoGroupDepth == 0 && actionCountInUndoGroup > 1) {
undostack.Push(new UndoQueue(undostack, actionCountInUndoGroup));
}
}
/// <summary>
/// Call this method to undo the last operation on the stack
/// </summary>
public void Undo()
{
while (undoGroupDepth != 0) // SSM 24.08.18 - грязный хак в попытке исправления ошибки с Ctrl-Z
{
EndUndoGroup();
}
if (undoGroupDepth != 0) {
throw new InvalidOperationException("cannot perform Undo/Redo while undo group is open");
}
if (undostack.Count > 0) {
IUndoableOperation uedit = (IUndoableOperation)undostack.Pop();
redostack.Push(uedit);
uedit.Undo();
OnActionUndone();
}
}
/// <summary>
/// Call this method to redo the last undone operation
/// </summary>
public void Redo()
{
if (undoGroupDepth != 0) {
throw new InvalidOperationException("cannot perform Undo/Redo while undo group is open");
}
if (redostack.Count > 0) {
IUndoableOperation uedit = (IUndoableOperation)redostack.Pop();
undostack.Push(uedit);
uedit.Redo();
OnActionRedone();
}
}
/// <summary>
/// Call this method to push an UndoableOperation on the undostack, the redostack
/// will be cleared, if you use this method.
/// </summary>
public void Push(IUndoableOperation operation)
{
if (operation == null) {
throw new ArgumentNullException("UndoStack.Push(UndoableOperation operation) : operation can't be null");
}
if (AcceptChanges) {
StartUndoGroup();
undostack.Push(operation);
actionCountInUndoGroup++;
if (TextEditorControl != null) {
undostack.Push(new UndoableSetCaretPosition(this, TextEditorControl.ActiveTextAreaControl.Caret.Position));
actionCountInUndoGroup++;
}
EndUndoGroup();
ClearRedoStack();
}
}
/// <summary>
/// Call this method, if you want to clear the redo stack
/// </summary>
public void ClearRedoStack()
{
redostack.Clear();
}
/// <summary>
/// Clears both the undo and redo stack.
/// </summary>
public void ClearAll()
{
undostack.Clear();
redostack.Clear();
actionCountInUndoGroup = 0;
}
/// <summary>
/// </summary>
protected void OnActionUndone()
{
if (ActionUndone != null) {
ActionUndone(null, null);
}
}
/// <summary>
/// </summary>
protected void OnActionRedone()
{
if (ActionRedone != null) {
ActionRedone(null, null);
}
}
class UndoableSetCaretPosition : IUndoableOperation
{
UndoStack stack;
TextLocation pos;
TextLocation redoPos;
public UndoableSetCaretPosition(UndoStack stack, TextLocation pos)
{
this.stack = stack;
this.pos = pos;
}
public void Undo()
{
redoPos = stack.TextEditorControl.ActiveTextAreaControl.Caret.Position;
stack.TextEditorControl.ActiveTextAreaControl.Caret.Position = pos;
}
public void Redo()
{
stack.TextEditorControl.ActiveTextAreaControl.Caret.Position = redoPos;
}
}
}
}