S-JIS[2013-01-04/2013-02-09] 変更履歴

Eclipseプラグイン PreferenceStoreクラス

Eclipseプラグイン開発のPreference(設定の保存)について。


Preferenceとは

Eclipseでは、メニューバーの「Windows(W)」→「設定(P)」で設定(Preference)ダイアログを開き、各プラグインの設定を変更・保存する事が出来る。
これはPreferenceStore(設定保存)クラスで実現する。

→プロジェクト毎の設定はPropertyPageで行う。


設定の使用例

メッセージを表示するアクションの例に対し、表示するダイアログのタイトルとメッセージを設定できるように改造してみる。


イニシャライザーの作成

まず、設定のデフォルト値(初期値)を管理するクラスを作成する。

src/com/example/eclipse/plugin/hello/preference/HelloPreferenceInitializer.java

package com.example.eclipse.plugin.hello.preference;

import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
import org.eclipse.jface.preference.IPreferenceStore;

import com.example.eclipse.plugin.Activator;
public class HelloPreferenceInitializer extends AbstractPreferenceInitializer {

	public static final String KEY_TITLE   = "HELLO_TITLE";
	public static final String KEY_MESSAGE = "HELLO_MESSAGE";
	@Override
	public void initializeDefaultPreferences() {
		IPreferenceStore store = Activator.getDefault().getPreferenceStore();
		store.setDefault(KEY_TITLE,   "plugin-example1");
		store.setDefault(KEY_MESSAGE, "Hello, Eclipse world");
	}
}

Activatorから設定ストアを取得し、setDefault()でデフォルト値を設定していく。
(キー名は自分で適当に付ける)


そして、plugin.xmlにイニシャライザーを呼び出す記述を追加する。

<plugin>
〜
   <extension
         point="org.eclipse.core.runtime.preferences">
      <initializer class="com.example.eclipse.plugin.hello.preference.HelloPreferenceInitializer" />
   </extension>

</plugin>

設定ページの作成(SWT直接使用版)

次に、設定ダイアログで表示されるページを作成する。
これには、EclipseのSWT(GUIの為のクラス群)を使う。

src/com/example/eclipse/plugin/hello/preference/HelloPreferencePage1.java

package com.example.eclipse.plugin.hello.preference;

import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;

import com.example.eclipse.plugin.Activator;

SWTのラベルやテキストフィールドのクラス名はAWTやSwingと似ているが、インポートするのはSWTのクラス。

public class HelloPreferencePage1 extends PreferencePage implements IWorkbenchPreferencePage {

	private Text titleText;
	private Text messageText;
	@Override
	public void init(IWorkbench workbench) {
	}
	@Override
	protected Control createContents(Composite parent) {
		setTitle("preference-title");

		IPreferenceStore store = Activator.getDefault().getPreferenceStore();

		Composite composite = new Composite(parent, SWT.NONE);
		{
			GridLayout layout = new GridLayout();
			layout.numColumns = 2; // 列数
			composite.setLayout(layout);
		}

		{ // タイトルを入力する行
			Label label = new Label(composite, SWT.NONE);
			label.setText("title");

			titleText = new Text(composite, SWT.SINGLE | SWT.BORDER);
			titleText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
			titleText.setText(store.getString(HelloPreferenceInitializer.KEY_TITLE));
		}
		{ // メッセージを入力する行
			Label label = new Label(composite, SWT.NONE);
			label.setText("message");

			messageText = new Text(composite, SWT.SINGLE | SWT.BORDER);
			messageText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
			messageText.setText(store.getString(HelloPreferenceInitializer.KEY_MESSAGE));
		}

		return composite;
	}

createContents()でSWTを使って入力フィールドを用意していく。

	@Override
	protected void performDefaults() {
		IPreferenceStore store = Activator.getDefault().getPreferenceStore();

		titleText.  setText(store.getDefaultString(HelloPreferenceInitializer.KEY_TITLE));
		messageText.setText(store.getDefaultString(HelloPreferenceInitializer.KEY_MESSAGE));
	}

performDefaults()は「デフォルトの復元」ボタンが押されたときに実行される。
設定ストアからデフォルト値を取得してテキストフィールドに設定し直す。

	@Override
	public boolean performOk() {
		IPreferenceStore store = Activator.getDefault().getPreferenceStore();

		store.setValue(HelloPreferenceInitializer.KEY_TITLE,   titleText.getText());
		store.setValue(HelloPreferenceInitializer.KEY_MESSAGE, messageText.getText());

		return true;
	}
}

performOk()は「OK」ボタンが押されたときに実行される。
テキストフィールドに入力された値を設定ストアに保存する。

なお、設定内容の永続化(どこかのファイルに保存される)は自動的に行われる。


そして、plugin.xmlに設定ページの記述を追加する。

<plugin>
〜
   <extension
         point="org.eclipse.ui.preferencePages">
      <page
            class="com.example.eclipse.plugin.hello.preference.HelloPreferencePage1"
            id="com.example.eclipse.plugin.hello.preference.page"
            name="plugin-example1">
      </page>
   </extension>

</plugin>

pageタグのname属性が、設定ダイアログのツリーに表示される文言となる。


設定の読み込み

今回の例の対象であるアクションクラスを修正し、設定ストアから値を読み込むようにする。

src/com/example/eclipse/plugin/hello/actions/HelloAction.java:

	@Override
	public void run(IAction action) {
		IPreferenceStore store = Activator.getDefault().getPreferenceStore();
		String title   = store.getString(HelloPreferenceInitializer.KEY_TITLE);
		String message = store.getString(HelloPreferenceInitializer.KEY_MESSAGE);

		ILog log = Activator.getDefault().getLog();
		log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, String.format("action title=[%s], message=[%s]", title, message)));

		MessageDialog.openInformation(window.getShell(), title, message);
	}

設定ページの作成(FieldEditor版)

単純なグリッド(表形式)の設定ページなら、FieldEditorPreferencePageというクラスを使った方がSWTを直接使うよりも便利。

package com.example.eclipse.plugin.hello.preference;

import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;

import com.example.eclipse.plugin.hello.Activator;
public class HelloPreferencePage2 extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {

	/**
	 * コンストラクター.
	 */
	public HelloPreferencePage2() {
		super(GRID);
		setPreferenceStore(Activator.getDefault().getPreferenceStore());
	}
	@Override
	public void init(IWorkbench workbench) {
	}
	@Override
	protected void createFieldEditors() {
		Composite parent = getFieldEditorParent();

		addField(new StringFieldEditor(HelloPreferenceInitializer.KEY_TITLE,   "title",   parent));
		addField(new StringFieldEditor(HelloPreferenceInitializer.KEY_MESSAGE, "message", parent));
	}
}

createFieldEditors()の中で設定ページの定義を行う。

addField()でフィールド行を追加していく。
StringFieldEditorがString用で、他にもBooleanFieldEditorとかIntegerFieldEditorなど色々なクラスがある。


設定ストアのスコープ

Eclise3.7のプラグイン開発のデフォルトでは、設定ストアのスコープはワークスペース単位となっている。
(設定値の保存の範囲がワークスペースということ。つまり別々のワークスペースでは設定を共有しない)

Eclipse単位(Eclipse全体で設定を共有する)のスコープにするには、以下のようにする。
(全般的にActivatorオブジェクトから設定ストアを取得するコーディングになっているので、ActivatorクラスのgetPreferenceStore()をオーバーライドする)

Activator.java:

import org.eclipse.core.runtime.preferences.ConfigurationScope;
import org.eclipse.ui.preferences.ScopedPreferenceStore;
	/**
	 * Storage for preferences.
	 */
	private ScopedPreferenceStore preferenceStore;
	@Override
	public IPreferenceStore getPreferenceStore() {
		if (preferenceStore == null) {
			preferenceStore = new ScopedPreferenceStore(ConfigurationScope.INSTANCE, PLUGIN_ID);
		}
		return preferenceStore;
	}
スコープ スコープオブジェクト
Eclipse単位 ConfigurationScope.INSTANCE
ワークスペース単位 InstanceScope.INSTANCE

カテゴリー

Preferenceでは、ツリー構造で複数の画面(ページ)を持つことが出来る。[2013-02-09]

各ページの定義において、カテゴリーで別ページのIDを指定すると、そのページの子ページとなる。
カテゴリーを指定しない場合は全体(親)の子ページとなる。

plugin.xml:

   <extension
         point="org.eclipse.ui.preferencePages">
      <page
            class="com.example.preference.TopPreferencePage"
            id="example.top-preference-page"
            name="example top page">
      </page>
      <page
            category="example.top-preference-page"
            class="com.example.preference.SubPreferencePage"
            id="example.sub-preference-page"
            name="example sub page">
      </page>
   </extension>

ボタンの非表示

特に設定を行わないページ(カテゴリーで階層を作ったトップページ等)の場合、デフォルトボタンや適用ボタンは不要。[2013-02-09]

そういうページでは、コンストラクターでボタン非表示の指定をしておく。

public class TopPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
	public TopPreferencePage() {
		super("TopPreferencePage");
		noDefaultAndApplyButton(); //DefaultボタンとApplyボタンの非表示
	}
	@Override
	public void init(IWorkbench workbench) {
	}
	@Override
	protected Control createContents(Composite parent) {
		setTitle("example blank page");

		Composite composite = new Composite(parent, SWT.NONE);
		return composite;
	}
}

Pleiades版Eclipseの注意点

Pleiadesプラグインで日本語化しているEclipseを使っている場合、テスト実行して起動されるEclipseも日本語化される。
なんと、自分で作った設定ページ(のラベルの内容)も自動的に日本語化される。
例えば上記の例だと「title」は「タイトル」、「message」は「メッセージ」と表示される。

問題は、この変換内容がキャッシュされてしまうということ。
一度テスト実行したら、設定ページのソースを変えてコンパイルし直しても、次回以降のテスト実行では反映されない。

解決策1:Pleiadesのキャッシュのクリア

Eclipseをインストールしたディレクトリーの下のconfiguration\jp.sourceforge.mergedoc.pleiadesの中にある「transformed-class.cache」というファイルを削除すると、キャッシュが無いので最新のクラスが使われる。
※このファイルを一度削除すると再生成はされない(キャッシュされなくなる)っぽい。

解決策2:Pleiadesの無効化

テスト実行用の実行構成にPleiadesの設定があるので、無効化してやる。
(当然、起動されるEclipseは英語版になる)

  1. メニューバーの「実行(R)」→「実行構成(N)」で、「実行構成」ダイアログを開く。
  2. 左側のツリーから対象のEclipseアプリケーションを選択する。
  3. 右側の「引数」タブを選択する。
  4. 「VM引数(G)」にPleiadesの設定が書かれているので、削除する。
    -Dosgi.requiredJavaVersion=1.5 -Xms40m -Xmx512m -javaagent:dropins/MergeDoc/eclipse/plugins/jp.sourceforge.mergedoc.pleiades/pleiades.jar
    ↓
    -Dosgi.requiredJavaVersion=1.5 -Xms40m -Xmx512m

Eclipseプラグインへ戻る / Eclipseへ戻る / 技術メモへ戻る
メールの送信先:ひしだま