0

EMF ベースの Eclipse アプリケーションに次の問題があります。

元に戻すは正常に機能します。検証は正常に機能します。ただし、GUI フィールドのデータに検証エラーがあると、元に戻すアクションの使用がブロックされます。たとえば、そのフィールドを有効な状態に戻すために元に戻すことはできません。

この図では、 undo を使用することはできません:

うまくいけば、質問を見るのがもう少し楽しくなる、あまり有益な画像ではありません。


アプリケーションで使用されるツール:

  • Eclipse データバインディング
  • UpdateValueStrategy検証のためのバインディングに関する
  • UndoAction元に戻すは、を呼び出す標準を使用して実装されますCommandStack.undo
  • MessageManagerSupport検証フレームワークを Eclipse Forms ベースの GUI に接続するクラス。

データ バインディングは次のようになります。

dataBindingContext.bindValue(WidgetProperties.text(...), 
    EMFEditProperties.value(...), validatingUpdateStrategy, null);

問題はこれです:

  • 元に戻すシステムは、モデルを変更するコマンドで機能します。
  • 検証システムは、検証エラーがある場合、更新がモデルに到達するのを停止します。

検証エラーが発生したときに元に戻すには、次のいずれかを実行できると思います。

  1. GUI 層で元に戻すシステムを動作させます。(これは大きな変更になるでしょう。これに EMF を使用することはおそらくまったく不可能です。)
  2. 有効なデータと同様に、モデル データを変更する GUI トリガー コマンドで無効なデータを作成します。(データがディスクに保存されない限り、これは問題ありません。しかし、これを行う方法が見つかりません。)
  3. のコンテンツ リスナーによってトリガーされる可能性がある、モデルで検証を直接機能させResourceます。(これは検証戦略の大きな変更です。この段階でソース GUI コントロールを追跡することはできないようです。)

これらの解決策は、不可能に見えるか、深刻な欠点があります。

検証エラーが発生した場合でも元に戻すにはどうすればよいですか?


:Mad Mattsの回答は、彼らの提案が私の解決策につながるため、受け入れます。しかし、私はそれで満足しているわけではなく、もっと良いものがあればいいのにと思います。

誰かがより良い解決策を見つけた場合、現在の解決策ではなく、喜んでそれを受け入れることを検討します!

4

2 に答える 2

1

Validator が Target 値を無効な値から保護することは理にかなっています。そのため、無効な値の場合、ターゲット コマンド スタックは変更されません。無効な値を強制的に設定したいのはなぜですか? ctrl + zGUI では、最後の有効な状態をリセットするのに十分ではありませんか?

これらの値を実際のターゲット モデルに設定したい場合は、UpdateValueStrategy.

更新フェーズは次のとおりです。

  1. 取得後に検証する - validateAfterGet(Object)

  2. 変換 - convert(オブジェクト)

  3. 変換後の検証 - validateAfterConvert(Object)

  4. 設定前に検証 - validateBeforeSet(Object)

  5. 値セット - doSet(IObservableValue, Object)

検証エラー ( ) が正確に発生する場所はわかりませんが、場所を確認して手動でStatus.ERROR強制することができます。それを行うために、各ステップのSetCommandカスタムを設定できます。IValidatorUpdateValueStrategy

于 2016-10-22T14:21:27.913 に答える
1

注: これは、アプリケーションで最終的に使用したソリューションです。私は本当にそれに満足していません。ちょっとしたハックだと思います。

彼らの提案が私をこの解決策に導くので、私はMad Mattsの答えを受け入れます。

誰かがより良い解決策を見つけた場合、現在の解決策ではなく、喜んでそれを受け入れることを検討します!


モデルオブジェクトに値が設定されたUpdateValueStratetyにバリデーターを実行するサブクラスを作成することになりました。これはうまく機能しているようです。

この回答を作成して、最終的に使用したコードを投稿します。ここにあります:

/**
 * An {@link UpdateValueStrategy} that can perform validation AFTER a value is set
 * in the model. This is used because undo dosen't work if no model changed in made.
 */
public class LateValidationUpdateValueStrategy extends UpdateValueStrategy {

    private IValidator afterSetValidator;

    public void setAfterSetValidator(IValidator afterSetValidator) {
        this.afterSetValidator = afterSetValidator;
    }

    @Override
    protected IStatus doSet(IObservableValue observableValue, Object value) {
        IStatus setStatus = super.doSet(observableValue, value);

        if (setStatus.getSeverity() >= IStatus.ERROR || afterSetValidator == null) {
            return setStatus;
        }

        // I used a validator here that calls the EMF generated model validator.
        // In that way I can specify validation of the model.
        IStatus validStatus = afterSetValidator.validate(value); 

        // Merge the two statuses
        if (setStatus.isOK() && validStatus.isOK()) {
            return validStatus;
        } else if (!setStatus.isOK() && validStatus.isOK()) {
            return setStatus;
        } else if (setStatus.isOK() && !validStatus.isOK()) {
            return validStatus;
        } else {
            return new MultiStatus(Activator.PLUGIN_ID, -1, 
                new IStatus[] { setStatus, validStatus },
                setStatus.getMessage() + "; " + validStatus.getMessage(), null);
        }
    }
}
于 2016-10-26T11:50:19.433 に答える