Eclipseプラグインを作ってみよう!

第11回 YAMLファイルの読み書き

この記事を読むのに必要な時間:およそ 4.5 分

前回まででGUIの実装は完了しましたので,今回はYAMLファイルの読み書きを実装し,フィールドのデータを永続化できるようにします。前回と同様にプラグインプロジェクトを用意いましたので,ダウンロードするところからはじめます。

プラグインプロジェクトのダウンロード

YAMLファイルの読み書きを実装したプラグインプロジェクトを下記のリンクからダウンロードし,お使いのワークスペースにインポートしてください。前回の連載までで実装されたプラグインプロジェクトはインポート前にリネームすることで残しておくことができます。

変更の判定

マニフェストエディターで内容を変更すると,タイトルタブのファイル名の先頭に「*」が付加され,「保管」コマンドが有効になります。これはどのように実装すればよいのでしょうか。第4回で拡張の設定を行いましたが,このときエディタークラスはIEditorPartインタフェースを実装していなければならないことを解説しました。このインタフェースは保管に関するメソッドを定義しているISaveablePartインタフェースを継承しています。ISaveablePartインタフェースで定義されているメソッドにはisDirty()メソッドがあります。

ISaveablePartインタフェースのisDirty()メソッド

public interface ISaveablePart {
    ...
    /**
     * Returns whether the contents of this part have changed since the last save
     * operation. If this value changes the part must fire a property listener 
     * event with <code>PROP_DIRTY</code>.
     * <p>
     * <b>Note:</b> this method is called often on a part open or part
     * activation switch, for example by actions to determine their 
     * enabled status.
     * </p>
     *
     * @return <code>true</code> if the contents have been modified and need
     *   saving, and <code>false</code> if they have not changed since the last
     *   save
     */
    public boolean isDirty();
    ...
}

JavaDocの説明を読むと,isDirty()メソッドの役割はパートのコンテンツが最後に保存されてから変更されているかどうかを返すことにあります。そこでFormDesignerEditorクラスのスーパークラスであるFormEditorクラスでisDirty()メソッドがどのように実装されているか見てみましょう。

FormEditorクラスのisDirty()メソッド

public abstract class FormEditor extends MultiPageEditorPart implements IPageChangeProvider {
    ...
    public boolean isDirty() {
        if (pages != null) {
            for (int i = 0; i < pages.size(); i++) {
                Object page = pages.get(i);
                if (page instanceof IFormPage) {
                    IFormPage fpage = (IFormPage) page;
                    if (fpage.isDirty())
                        return true;
                }
            }
        }
        return super.isDirty();
    }
    ...
}

FormEditorクラスのisDirty()メソッドではaddPage()メソッドで追加されたIFormPageクラスのisDirty()メソッドを確認していることがわかります。このように,それぞれが保持するパートやフォームを順番にチェックして,変更されたかどうかを判定していきます。

Eclipseのエディターでどのように変更の判定が行われているかを理解したところで,フォームデザイナーではどのタイミングで変更が発生したと判定するのが適切かを考えてみましょう。フォームデザイナーではフィールドの情報はテーブルビューアーが保持しています。従ってテーブルビューアーに対して変更があったときを捕捉することができればよさそうです。しかし,TableViewerクラスにはこういった用途のリスナーを登録することができないので,内容が変更される以下の場合に対して変更を通知することにしました。

  1. フィールドが追加されたとき
  2. フィールドが削除されたとき
  3. フィールドが上下に移動されたとき
  4. フィールドの詳細が変更されたとき

1~3についてはそれぞれ対応するボタンが実行されたときに,4についてはDetails(詳細)での変更通知を受け取るselectionChanged()メソッドで捕捉します。具体的にはこれらの場所でmarkDirty()メソッドを呼び出します。

変更の状態は保管されたときにリセットされる必要があります。そこでFormDeisgnerEditorクラスのdoSave()メソッドを実装します。

FormDesignerEditorクラスのdoSave()メソッド

public class FormDesignerEditor extends FormEditor {
    ...
    @Override
    public void doSave(IProgressMonitor monitor) {
        commitPages(true);
        editorDirtyStateChanged();
    }
    ...
}
}

commitPages()メソッドはisDirty()メソッドと同じように保持しているIFormPageオブジェクトやIManagedFormオブジェクトに対してcommit()メソッドを呼び出し,変更状態をリセットしていきます。これで「保管」コマンドを実行すると,変更中であることを示す「*」が消えるようになります。

著者プロフィール

松藤秀治(まつふじひではる)

Piece Frameworkのプログラマー。担当はEclipseのプラグインとして開発されているPiece Frameworkの統合開発環境Piece_IDE。2007年5月に株式会社アイテマンを設立。

コメント

コメントの記入