17

私のプロジェクトの一部は、いくつかのルールの入力、アプリケーションのコンパイル、および実行に使用されるテキストエディターを作成することです。コンパイラの作成は終了し、ベータ版をリリースしました。最終バージョンでは、元に戻るとやり直しをテキストエディタに追加する必要があります。私はファイルを使用して、テキストエディタ用に定期的に保存します。テキストエディタで元に戻すとやり直しを設計するにはどうすればよいですか?ファイルの永続性の構造は何が変わったのですか?

4

8 に答える 8

16

アクションをコマンドとしてモデル化でき、2つのスタックに保持します。1つは元に戻すため、もう1つはやり直し用です。たとえば、マクロのアクションを元に戻したい場合など、コマンドを作成して、より高レベルのコマンドを作成できます。または、1つの単語またはフレーズの個々のキーストロークを1つのアクションにグループ化する場合。

エディターの各アクション(またはREDOアクション)は、UNDOスタックに入る(またREDOスタックをクリアする)新しいUNDOコマンドを生成します。各undoアクションは、REDOスタックに入る対応するREDOコマンドを生成します。

また、 derekerdmannのコメントで述べられているように、元に戻すコマンドとやり直しコマンドの両方を1つのタイプのコマンドに組み合わせて、そのアクションを元に戻したりやり直したりする方法を知っていることもできます。

于 2010-08-27T12:27:33.320 に答える
8

基本的に2つの良い方法があります。

  • 「コマンド」デザインパターン

  • 不変オブジェクトに対してOOのみを使用します。ここでは、すべてが不変オブジェクトで構成された不変オブジェクトであり、不変オブジェクトで構成されています(これはあまり一般的ではありませんが、正しく実行すると非常にエレガントになります)

素朴なコマンドや素朴な元に/やり直しよりも不変オブジェクトよりもOOを使用する利点は、それについてあまり考える必要がないことです。アクションの効果を「元に戻す」必要も、すべてを「再生」する必要もありません。コマンド。必要なのは、不変オブジェクトの膨大なリストへのポインタだけです。

オブジェクトは不変であるため、ほとんどのオブジェクトを任意の状態でキャッシュ/再利用できるため、すべての「状態」を非常に軽量にすることができます。

「不変オブジェクト上のOO」は純粋な宝石です。おそらく、次の10年前に主流になることはないでしょう。)。

PS:不変オブジェクトに対してOOを実行すると、並行プログラミングも驚くほど簡素化されます。

于 2010-08-27T12:42:03.683 に答える
6

特別なことをしたくない場合は、UndoManagerを追加するだけです。テキストを追加または削除DocumentするUndoableEditたびに起動します。それぞれの変更を元に戻したりやり直したりするには、UndoManagerでそれらのメソッドを呼び出すだけです。

これの欠点は、ユーザーが何かを入力するたびにUndoManagerが新しい編集を追加することです。したがって、「apple」と入力すると、一度に1つずつ元に戻すことができる5つの編集が残ります。私のテキストエディタでは、テキストの変更とオフセットに加えて、編集のラッパーを作成しました。また、UndoableEditListener編集の間に短い期間(0.5)しかない場合は、新しい編集を以前の編集に連結します。秒は私にとってうまくいきます)。

これは一般的な編集には適していますが、大規模な置換が行われると問題が発生します。「apple」のインスタンスが5000個あるドキュメントがあり、これを「orange」に置き換えたい場合は、5000個の編集で、すべて「apple」、「orange」、およびオフセットが格納されます。使用するメモリの量を減らすために、これを通常の編集とは別のケースとして扱い、代わりに「リンゴ」、「オレンジ」、および5000オフセットの配列を格納しています。これを適用することはまだできていませんが、複数の文字列が検索条件に一致すると(大文字と小文字を区別しない検索、正規表現検索など)、頭痛の種になることはわかっています。

于 2010-08-27T12:55:16.243 に答える
4

あなたは2つの方法でそれを行うことができます:

  • エディターの状態のリストとリスト内のポインターを保持します。undoはポインターを後ろに移動し、そこで状態を復元します。redoは代わりに前に移動します。何かを行うと、ポインター以外のすべてが破棄され、状態が新しい最上位要素として挿入されます。
  • 状態を保持するのではなく、アクションを保持します。これには、すべてのアクションに対して、そのアクションの効果を元に戻すための反作用が必要です。

私の(図)エディターには、4つのレベルの状態変化があります。

  • アクションフラグメント:これらはより大きなアクションの一部であり、個別に元に戻すこともやり直すこともできません(たとえば、マウスを動かす)
  • アクション:元に戻すこともやり直すこともできる意味のある変更を形成するが、ディスク上で変更されたときに編集されたドキュメントに反映されない1つ以上のアクションフラグメント(要素の選択など)
  • ドキュメントの変更:ディスクに保存されるときに編集されたドキュメントを変更する1つ以上のアクション(要素の変更、追加、削除など)
  • ドキュメントの保存:ドキュメントの現在の状態が明示的にディスクに保存されます-この時点で、私のエディターは元に戻す履歴を破棄するため、保存を過ぎて元に戻すことはできません
于 2010-08-27T12:17:38.317 に答える
4

うわー、なんて不思議なことだ-私は文字通りこの1時間で、WYSIWYGテキストエディタに元に戻る/やり直しを実装しました。

基本的な考え方は、テキストエディタの内容全体を配列に保存するか、最後の編集との違いを保存することです。

重要なポイント、つまり数文字ごとにこの配列を更新します(キーを押すたびにコンテンツの長さを確認し、20文字を超える場合は、セーブポイントを作成します)。また、スタイルの変更(リッチテキストの場合)、画像の追加(許可されている場合)、テキストの貼り付けなど。配列内のどの項目が現在の状態であるかを示すポインター(int変数のみ)も必要です。編集者)

配列の長さを設定します。保存ポイントを追加するたびに、それを配列の先頭に追加し、他のすべてのデータポイントを1つ下に移動します。(保存ポイントが非常に多いと、配列の最後の項目は忘れられます)

ユーザーが元に戻すボタンを押したら、エディターの現在の内容が最新の保存と同じかどうかを確認します(そうでない場合は、ユーザーは最後の保存ポイント以降に変更を加えたため、現在の内容を保存します。エディター(やり直し可能)、エディターを最後の保存ポイントと等しくし、ポインター変数= 1(配列の2番目の項目)にします。それらが同じである場合、最後から変更は加えられていません。ポイントを保存するので、その前のポイントに戻す必要があります。これを行うには、ポインター値+ 1をインクリメントし、エディターの内容をポインターの値にします。

やり直すには、ポインタ値を1減らして、配列の内容をロードします(配列の最後に到達したかどうかを確認してください)。

ユーザーが元に戻した後に編集を行った場合は、ポイントされた値の配列セルをセル0に移動し、残りを同じ量だけ上に移動します(別の編集を行った後は、他のものにやり直したくありません)。

もう1つの主要なキャッチポイント-テキストエディタの内容が実際に変更された場合にのみ保存ポイントを追加するようにしてください(そうしないと、保存ポイントが重複し、元にたりがユーザーに何もしていないように見えます。

Javaの詳細についてはお役に立てませんが、他にご不明な点がございましたら、お気軽にお問い合わせください。

ニコ

于 2010-08-27T12:23:16.573 に答える
3

これはコマンドパターンの仕事です。

于 2010-08-27T12:23:09.197 に答える
3

これは、SWTがUndo/Redo操作をサポートする方法を示すスニペットです。実用的な例として取り上げます(または、エディターがSWTに基づいている場合は、直接使用します)。

SWT元に戻るやり直し

于 2010-08-27T12:50:49.373 に答える
2

本を読むデザインパターン:再利用可能なオブジェクト指向ソフトウェアの要素。私が覚えている限り、かなり良い例があります。

于 2010-08-27T12:21:16.157 に答える