FC2ブログ

C#で元に戻すとやり直しの機能を実装する

  • Day:2011.12.11 11:32
  • Cat:C#
操作を元に戻す、やり直す機能は、
命令を1つのオブジェクトで表すCommandパターンを使用します。


/// <summary>
/// 実行、元に戻す、やり直すの各動作を定義するインターフェイス
/// </summary>
public interface ICommand
{
/// <summary>
/// 操作を実行する
/// </summary>
void Action();

/// <summary>
/// 操作を元に戻す
/// </summary>
void Undo();

/// <summary>
/// 操作をやり直す
/// </summary>
void Redo();
}

命令を表すICommandというインターフェイスを作っておいて


using System.Drawing;

/// <summary>
/// ペンツールのコマンドを管理するクラス
/// </summary>
public class PenCommand : ICommand
{
private Map map; // 編集するマップ
private Point position; // 編集する位置
private int prevPart; // 編集前のパーツ
private int nextPart; // 編集後のパーツ

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="map">編集するマップ</param>
/// <param name="position">編集する位置</param>
/// <param name="nextPart">編集後のパーツ</param>
public PenCommand(Map map, Point position, int nextPart)
{
this.map = map;
this.position = position;
this.nextPart = nextPart;
}

/// <summary>
/// 操作を実行する
/// </summary>
public void Action()
{
this.prevPart = this.map.GetPart(this.position);
this.map.SetPart(this.position, this.nextPart);
}

/// <summary>
/// 操作を元に戻す
/// </summary>
public void Undo()
{
this.map.SetPart(this.position, this.prevPart);
}

/// <summary>
/// 操作をやり直す
/// </summary>
public void Redo()
{
this.map.SetPart(this.position, this.nextPart);
}
}

それを実装する形で、個々の命令を表すPenCommandクラスなどを定義します。


using System.Collections.Generic;

/// <summary>
/// 実行、元に戻す、やり直すの各動作を管理するクラス
/// </summary>
public class CommandManager
{
private Stack<ICommand> undo = new Stack<ICommand>(); // 元に戻すための履歴
private Stack<ICommand> redo = new Stack<ICommand>(); // やり直すための履歴

/// <summary>
/// 操作を実行して内容を履歴に追加する
/// </summary>
/// <param name="command">コマンド</param>
public void Action(ICommand command)
{
this.undo.Push(command);
command.Action();
this.redo.Clear();
}

/// <summary>
/// 操作を元に戻す
/// </summary>
public void Undo()
{
if (!this.CanUndo())
{
return;
}

ICommand command = this.undo.Pop();
command.Undo();
this.redo.Push(command);
}

/// <summary>
/// 操作をやり直す
/// </summary>
public void Redo()
{
if (!this.CanRedo())
{
return;
}

ICommand command = this.redo.Pop();
command.Redo();
this.undo.Push(command);
}

/// <summary>
/// 元に戻せるかどうかを確認する
/// </summary>
/// <returns>元に戻せるかどうか</returns>
public bool CanUndo()
{
return 0 < this.undo.Count;
}

/// <summary>
/// やり直せるかどうかを確認する
/// </summary>
/// <returns>やり直せるかどうか</returns>
public bool CanRedo()
{
return 0 < this.redo.Count;
}
}

そして、CommandManagerクラスで命令を管理します。

マップエディタで塗りつぶしや直線の機能を実装する場合は
ICommandインターフェイスを継承してFillCommandクラスやLineCommandクラスを定義します。


C#|Undo,Redo機能を実装する
矢沢久雄の早わかりGoFデザインパターン(10) - 矢沢久雄の早わかりGoFデザインパターン:ITpro

Comment

Comment Form
公開設定

Trackback


→ この記事にトラックバックする(FC2ブログユーザー)
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。