不足気味でしたので、たまにはC#分を補充しておきます。 ↓ ↑ もう1年近く前になるんですね。以前、下記のエントリが注目を浴びていて、 わたしも楽しく読ませてもらいました。 Undo,Redoの実装って何十回もやってる気がする - あしあと日記 http://d.hatena.ne.jp/Youchan/20081110/1226282911 Undo,Redoの実装つづき - あしあと日記 http://d.hatena.ne.jp/Youchan/20081111/1226388917 久々にUndo,Redoを実装する機会があったので、せっかくなのでチラ裏に残しておきます。 いわゆるGoFデザインパターンでいうところのCommandパターンとMementoパターンの応用です。 そしてジェネリック対応することで、Undo,Redoの実装をある程度抽象化することができます。 今回はこの
undo,redoの実装って何十回もやってる気がする。毎回同じパターンだ。undo,redoが登場するような編集ソフトは大体同じパターンに落とせる。フレームワークも作った。ブログにそういう内容を書きたいが面倒くさい。需要があれば面倒でも書くんだけどなあ http://twitter.com/youpychan/status/994486992 という発言をしたら何人か反応を頂いたので書いてみることにする。 需要があるなら書こう。undo,redoだけじゃなくてグラフィカルな編集ソフト全般の話をいつかまとめたいと思っていたので、ちょいとシリーズで書いてみようかとおもう http://twitter.com/youpychan/status/994636764 書こうと思う。 まずUndo,Redoについて。 Unod,Redoってみなさんどういう風に実装しているでしょうか? 私はコマンドパタ
いや、悪い反応では無いのでむしろ喜ぶべきことなんだけど、意外と好評なエントリーなので続きを書きます。 タイトルだけは前回同様釣りっぽいタイトルで^^ 前回のエントリーが思ったより反響が大きくてびっくりしてます。なんか炎上してるのか?って思っちゃいましたw 炎上っていうのはさすがにネガティブだし、内容とかけ離れすぎてるのでタイトル変えました。 さて前回はコマンドパターンとコマンドの実装について書きましたが、今回は予告どおり実行部の実装についてです。 といっても、今回はとっても単純な話です。Undo用にスタックにコマンドを積んで、Undoするよって呼ばれたら、スタックからコマンドをpopしてきてundoの処理を実行するだけです。 ただし、Redoも出来ないと行けないので、実行したコマンドは今度はRedo用のスタックに積んでいきます。 実装は次のようになります。 まず前回の二番目のパターンに則っ
常に行いたい操作とその操作を元に戻すための操作をセットにして履歴を保持することで、 行った操作を元に戻す機能、元に戻した操作をやり直す機能を提供するクラス。 using System; using System.Collections.Generic; /// <summary> /// 実行、元に戻す(undo)、やり直す(redo)の各動作を定義するインターフェース /// </summary> public interface ICommand { /// <summary> /// 操作を実行するメソッド /// </summary> void Do(); /// <summary> /// 操作を元に戻すメソッド /// </summary> void Undo(); /// <summary> /// 操作をやり直すメソッド /// </summary> void Redo()
例えば移動したディレクトリを記録しているときに、履歴に残っているディレクトリが途中で削除されてしまった場合には、そのディレクトリへ移動できないようにしたり、そのディレクトリを表す項目を淡色表示したい、というようなこともあるでしょう そこで、登録されているコマンドが途中で無効になってしまったような場合には、そのコマンドを無視することができるようにしてみましょう Undo コマンドの基底クラスの実装 #define UNDOREDO_DETACHED 0 #define UNDOREDO_ATTACHED 1 #define UNDOREDO_UNDO 2 #define UNDOREDO_REDO 3 #define UNDOREDO_UNDO_BEGIN 4 #define UNDOREDO_UNDO_END 5 #define UNDOREDO_REDO_BEGIN 6 #define
Undo/Redoの履歴を表示したいときなどがあります このようなときコマンドのグループに名前が付いていると便利です コマンドチェインに名前を付けられるようにしてみましょう Undo コマンド管理クラスの実装 #define INVALID_COMMAND_ID (( uint32_t )-1) #define INVALID_CHAIN_ID (( uint32_t )-1) #define MAXIMUM_CHAIN_LEVEL (( uint32_t )-1) class cundoredoitem { uint32_t m_chain_id; uint32_t m_chain_level; uint32_t m_id; IRestoreObj* m_pRestoreObj; bool dispatch( uint32_t uMsg ); public: void detach();
コマンドのグループ化に対応できるようになりましたが、途中でエラーが発生したときなどに、キャンセルするということができませんでした コマンドチェインを途中でキャンセルできるようにしてみましょう Undo コマンド管理クラスの実装 #define INVALID_COMMAND_ID (( uint32_t )-1) #define INVALID_CHAIN_ID (( uint32_t )-1) #define MAXIMUM_CHAIN_LEVEL (( uint32_t )-1) class cundoredoitem { uint32_t m_chain_id; uint32_t m_chain_level; uint32_t m_id; IRestoreObj* m_pRestoreObj; bool dispatch( uint32_t uMsg ); public: void
一度の操作で複数のコマンドを一括して Undo/Redo したいというときがありますが、前回のコードでは対応していませんでした コマンドのグループ化、コマンドチェインに対応しましょう Undo コマンド管理クラスの実装 #define INVALID_COMMAND_ID (( uint32_t )-1) #define INVALID_CHAIN_ID (( uint32_t )-1) #define MAXIMUM_CHAIN_LEVEL (( uint32_t )-1) class cundoredoitem { uint32_t m_chain_id; uint32_t m_id; IRestoreObj* m_pRestoreObj; bool dispatch( uint32_t uMsg ); public: void detach(); bool attach( uint3
Undo/Redo の際、コマンドチェインの最初と最後のタイミングがわかると便利なときがあります コマンドチェインを実行するときに、最初と最後のタイミングも通知するようにしてみましょう Undo コマンドの基底クラスの実装 最初と最後のタイミングを通知するメッセージを追加します #define UNDOREDO_DETACHED 0 #define UNDOREDO_ATTACHED 1 #define UNDOREDO_UNDO 2 #define UNDOREDO_REDO 3 #define UNDOREDO_UNDO_BEGIN 4 #define UNDOREDO_UNDO_END 5 #define UNDOREDO_REDO_BEGIN 6 #define UNDOREDO_REDO_END 7 class CRestoreObj : public IRestoreObj {
はじめに どのようなアプリケーションでも Undo 機能はぜひとも欲しい機能の一つだと思いますが、残念ながら Undo を実現するための標準的なフレームワークというようなものは存在しません ですからアプリケーションに Undo の機能を追加しようとすれば一から自分で書く必要があります ここではコマンドリスト形式の Undo の実装について説明しましょう Undo の仕組み Undo の仕組み自体は実はとても簡単です Undo マネージャはコマンドの中身は関知せず、ただコマンドのリストを管理しているだけです コマンドのリストで現在注目しているところを前に戻すのが Undo、先へ進めるのが Redo です 注目している位置より前に変わったコマンドには Redo の通知を送り、先に変わったコマンドには Undo の通知を送ります ただそれだけです コマンドのリストとその注目位置が Undo/Re
リリース、障害情報などのサービスのお知らせ
最新の人気エントリーの配信
処理を実行中です
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く