UndoManager.cs
上传用户:hbhltzc
上传日期:2022-06-04
资源大小:1925k
文件大小:7k
源码类别:

xml/soap/webservice

开发平台:

Visual C++

  1. using System;
  2. using System.Collections;
  3. namespace XmlNotepad
  4. {
  5.     public class CommandEventArgs : EventArgs {
  6.         Command cmd;
  7.         public CommandEventArgs(Command cmd) {
  8.             this.cmd = cmd;
  9.         }
  10.         public Command Command { get { return this.cmd; } }
  11.     }
  12. public class UndoManager
  13. {        
  14.         ArrayList stack = new ArrayList();
  15.         int pos;
  16.         int max;
  17.         Command exec = null;
  18.         CompoundCommand compound;
  19.         public event EventHandler StateChanged;
  20.         public event EventHandler<CommandEventArgs> CommandDone;
  21.         public event EventHandler<CommandEventArgs> CommandUndone;
  22.         public event EventHandler<CommandEventArgs> CommandRedone;
  23. public UndoManager(int maxHistory)
  24. {
  25.             this.stack = new ArrayList();            
  26.             this.max = maxHistory;
  27.         }
  28.         public void Clear(){
  29.             if (stack.Count>0){
  30.                 pos = 0;
  31.                 stack.Clear();
  32.                 if (StateChanged != null){
  33.                     StateChanged(this, EventArgs.Empty);
  34.                 }
  35.             }
  36.         }
  37.         public Command Executing {
  38.             get { return this.exec; }
  39.         }
  40.         public bool CanUndo{
  41.             get {
  42.                 return pos>0;
  43.             }
  44.         }
  45.         public bool CanRedo{
  46.             get {
  47.                 return pos < stack.Count;
  48.             }
  49.         }
  50.         public Command Current {
  51.             get { 
  52.                 if (pos>=0 && pos < stack.Count){
  53.                     return (Command)stack[pos];
  54.                 }
  55.                 return null;
  56.             }
  57.         }
  58.         void Add(Command cmd) {
  59.             if (pos < stack.Count) {
  60.                 stack.RemoveRange(pos, stack.Count - pos);
  61.             }
  62.             System.Diagnostics.Trace.WriteLine(cmd.Name);
  63.             stack.Add(cmd);
  64.             if (stack.Count > this.max) {
  65.                 stack.RemoveAt(0);
  66.             } else {
  67.                 pos++;
  68.             }
  69.         }
  70.         public void Push(Command cmd) {
  71.             if (cmd.IsNoop) return; // do nothing!
  72.             if (this.compound != null) {
  73.                 this.compound.Add(cmd);
  74.             } else {
  75.                 Add(cmd);
  76.             }
  77.             // Must do command after adding it to the command stack!
  78.             Command saved = this.exec;
  79.             try {
  80.                 this.exec = cmd;
  81.                 cmd.Do();
  82.                 
  83.             } finally {
  84.                 this.exec = saved;
  85.             }
  86.             if (StateChanged != null) {
  87.                 StateChanged(this, EventArgs.Empty);
  88.             }
  89.             if (CommandDone != null) {
  90.                 CommandDone(this, new CommandEventArgs(cmd));
  91.             }
  92.         }
  93.         public Command Undo(){
  94.             if (pos>0){
  95.                 pos--;                
  96.                 Command cmd = this.Current;
  97.                 if (cmd != null && !cmd.IsNoop){
  98.                     Command saved = this.exec;
  99.                     try {
  100.                         this.exec = cmd;
  101.                         cmd.Undo();
  102.                     } finally {
  103.                         this.exec = saved;
  104.                     }
  105.                     if (StateChanged != null) {
  106.                         StateChanged(this, EventArgs.Empty);
  107.                     }
  108.                     if (CommandUndone != null) {
  109.                         CommandUndone(this, new CommandEventArgs(cmd));
  110.                     }
  111.                 }
  112.                 return cmd;
  113.             }
  114.             return null;
  115.         }
  116.         public Command Redo(){
  117.             if (pos < stack.Count){
  118.                 Command cmd = this.Current;
  119.                 if (cmd != null && !cmd.IsNoop){
  120.                     Command saved = this.exec;
  121.                     try {
  122.                         this.exec = cmd;
  123.                         cmd.Redo();
  124.                     } finally {
  125.                         this.exec = saved;
  126.                     }
  127.                     if (StateChanged != null) {
  128.                         StateChanged(this, new CommandEventArgs(cmd));
  129.                     }
  130.                     if (CommandRedone != null) {
  131.                         CommandRedone(this, new CommandEventArgs(cmd));
  132.                     }
  133.                 }
  134.                 pos++;
  135.                 return cmd;
  136.             }
  137.             return null;
  138.         }
  139.         public Command Peek(){
  140.             if (pos>0 && pos-1 < stack.Count){
  141.                 return (Command)stack[pos-1];
  142.             }
  143.             return null;
  144.         }
  145.         public Command Pop(){
  146.             // remove command without undoing it.
  147.             if (pos > 0) {
  148.                 pos--;
  149.                 if (pos < stack.Count) {
  150.                     stack.RemoveAt(pos);
  151.                 }
  152.                 if (StateChanged != null) {
  153.                     StateChanged(this, EventArgs.Empty);
  154.                 }
  155.             }
  156.             return this.Current;
  157.         }
  158.         public void Merge(CompoundCommand cmd) {
  159.             // Replace the current command without upsetting rest of the redo stack
  160.             // and insert the current command into this compound command.
  161.             Command current = Peek();
  162.             if (current != null) {
  163.                 stack.Insert(pos-1, cmd);
  164.                 stack.RemoveAt(pos);
  165.                 cmd.Do();
  166.                 cmd.Insert(current);
  167.             } else {
  168.                 Push(cmd);
  169.             }
  170.         }
  171.         public CompoundCommand OpenCompoundAction(string name) {
  172.             this.compound = new CompoundCommand(name);
  173.             Add(this.compound);
  174.             return this.compound;
  175.         }
  176.         public void CloseCompoundAction() {
  177.             this.compound = null;
  178.         }
  179.     }
  180.     public abstract class Command {
  181.         public abstract string Name { get; }
  182.         public abstract void Do();
  183.         public abstract void Undo();
  184.         public abstract void Redo();
  185.         public abstract bool IsNoop { get; }
  186.     }
  187.     public class CompoundCommand : Command {
  188.         ArrayList commands = new ArrayList();
  189.         string name;
  190.         public CompoundCommand(string name) {
  191.             this.name = name;
  192.         }
  193.         public override string Name {
  194.             get { return name; }
  195.         }
  196.         public void Add(Command cmd) {
  197.             commands.Add(cmd);
  198.         }
  199.         public int Count { get { return commands.Count; } }
  200.         public override void Do() {
  201.             if (this.IsNoop) return;
  202.             foreach (Command cmd in this.commands) {
  203.                 cmd.Do();
  204.             }
  205.         }
  206.         public override void Undo() {
  207.             // Must undo in reverse order!
  208.             for (int i = this.commands.Count - 1; i >= 0; i--) {
  209.                 Command cmd = (Command)this.commands[i];
  210.                 cmd.Undo();
  211.             }
  212.         }
  213.         public override void Redo() {
  214.             foreach (Command cmd in this.commands) {
  215.                 cmd.Redo();
  216.             }
  217.         }
  218.         public override bool IsNoop {
  219.             get {
  220.                 foreach (Command cmd in this.commands) {
  221.                     if (!cmd.IsNoop) return false;
  222.                 }
  223.                 return true;
  224.             }
  225.         }
  226.         public void Insert(Command cmd) {
  227.             commands.Insert(0, cmd);
  228.         }
  229.     }
  230. }