2 * Copyright (C) 2013 FooProject
3 * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
6 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
9 You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
12 using System.Collections.Generic;
15 namespace FooEditEngine
30 /// <param name="a"></param>
31 /// <returns>マージできた場合は真、そうでない場合は偽を返す</returns>
32 bool marge(ICommand a);
34 /// コマンドを結合した結果が空なら真。そうでないなら偽を返す
36 /// <returns></returns>
41 sealed class BeginActionCommand : ICommand
53 public bool marge(ICommand a)
65 sealed class EndActionCommand : ICommand
77 public bool marge(ICommand a)
92 public sealed class UndoManager
94 private bool locked = false;
95 private Stack<ICommand> UndoStack = new Stack<ICommand>();
96 private Stack<ICommand> RedoStack = new Stack<ICommand>();
97 private int groupLevel = 0;
102 internal UndoManager()
104 this.Grouping = false;
110 /// <param name="cmd">ICommandインターフェイス</param>
111 internal void push(ICommand cmd)
113 if (this.locked == true)
115 ICommand last = null;
116 if (this.AutoMerge && UndoStack.Count() > 0)
117 last = UndoStack.First();
118 if(last == null || last.marge(cmd) == false)
120 if (last != null && last.isempty())
122 if (this.RedoStack.Count > 0)
127 /// 履歴として残される操作が一連のグループとして追加されるなら真を返し、そうでなければ偽を返す
129 internal bool Grouping
137 /// アクションを結合するなら真。そうでないなら偽
139 internal bool AutoMerge
146 /// 一連のアンドゥアクションの開始を宣言します
148 public void BeginUndoGroup()
156 this.push(new BeginActionCommand());
157 this.Grouping = true;
158 this.AutoMerge = true;
163 /// 一連のアンドゥアクションの終了を宣言します
165 public void EndUndoGroup()
167 if (this.Grouping == false)
168 throw new InvalidOperationException("BeginUndoGroup()を呼び出してください");
169 if (this.groupLevel > 0)
175 ICommand last = UndoStack.First();
176 if (last != null && last is BeginActionCommand)
177 this.UndoStack.Pop();
179 this.push(new EndActionCommand());
180 this.Grouping = false;
181 this.AutoMerge = false;
190 if (this.UndoStack.Count == 0 || this.locked == true)
194 bool isGrouped = false;
198 cmd = this.UndoStack.Pop();
199 this.RedoStack.Push(cmd);
203 //アンドゥスタック上ではEndActionCommand,...,BeginActionCommandの順番になる
204 if (cmd is EndActionCommand)
206 else if (cmd is BeginActionCommand)
217 if (this.RedoStack.Count == 0 || this.locked == true)
220 bool isGrouped = false;
224 cmd = this.RedoStack.Pop();
225 this.UndoStack.Push(cmd);
229 //リドゥスタック上ではBeginActionCommand,...,EndActionCommandの順番になる
230 if (cmd is BeginActionCommand)
232 else if (cmd is EndActionCommand)
242 if (this.locked == true)
244 this.UndoStack.Clear();
245 this.RedoStack.Clear();
250 public void BeginLock()
258 public void EndLock()