Eclipseのプラグイン開発のPreference(設定の保存)について。
|
|
Eclipseでは、メニューバーの「Windows(W)」→「設定(P)」で設定(Preference)ダイアログを開き、各プラグインの設定を変更・保存する事が出来る。
これはPreferenceStore(設定保存)クラスで実現する。
→プロジェクト毎の設定はPropertyPageで行う。
メッセージを表示するアクションの例に対し、表示するダイアログのタイトルとメッセージを設定できるように改造してみる。
まず、設定のデフォルト値(初期値)を管理するクラスを作成する。
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>
次に、設定ダイアログで表示されるページを作成する。
これには、EclipseのSWT(GUIの為のクラス群)を使う。
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属性が、設定ダイアログのツリーに表示される文言となる。
今回の例の対象であるアクションクラスを修正し、設定ストアから値を読み込むようにする。
@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);
}
単純なグリッド(表形式)の設定ページなら、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()をオーバーライドする)
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を指定すると、そのページの子ページとなる。
カテゴリーを指定しない場合は全体(親)の子ページとなる。
<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を使っている場合、テスト実行して起動されるEclipseも日本語化される。
なんと、自分で作った設定ページ(のラベルの内容)も自動的に日本語化される。
例えば上記の例だと「title」は「タイトル」、「message」は「メッセージ」と表示される。
問題は、この変換内容がキャッシュされてしまうということ。
一度テスト実行したら、設定ページのソースを変えてコンパイルし直しても、次回以降のテスト実行では反映されない。
Eclipseをインストールしたディレクトリーの下のconfiguration\jp.sourceforge.mergedoc.pleiadesの中にある「transformed-class.cache」というファイルを削除すると、キャッシュが無いので最新のクラスが使われる。
※このファイルを一度削除すると再生成はされない(キャッシュされなくなる)っぽい。
テスト実行用の実行構成にPleiadesの設定があるので、無効化してやる。
(当然、起動されるEclipseは英語版になる)
-Dosgi.requiredJavaVersion=1.5 -Xms40m -Xmx512m -javaagent:dropins/MergeDoc/eclipse/plugins/jp.sourceforge.mergedoc.pleiades/pleiades.jar ↓ -Dosgi.requiredJavaVersion=1.5 -Xms40m -Xmx512m