S-JIS[2013-08-25/2014-04-24] 変更履歴

Xtext設定ページ

Xtextの設定ページ(preferences)およびプロパティーページのメモ。


概要

Xtextで生成されたエディターでは、自動的に設定ページプロパティーページが作られる。

デフォルトでは、設定ページは以下のようなツリー構成になっている。


言語ルート設定ページ

設定ページ(およびプロパティーページ)のツリーの“独自DSLとしてのルート要素”はLanguageRootPreferencePageクラスで作られている。
といってもタイトル(DSL名)を表示しているだけだが。

このタイトル(DSL名)はuiプロジェクトのplugin.xmlに書かれているので、変えたければplugin.xmlを修正する。

uiプロジェクト/plugin.xml:

    <extension
            point="org.eclipse.ui.preferencePages">
        <page
            class="org.xtext.example.mydsl.ui.MyDslExecutableExtensionFactory:org.eclipse.xtext.ui.editor.preferences.LanguageRootPreferencePage"
            id="org.xtext.example.mydsl.MyDsl"
            name="MyDsl">
            <keywordReference id="org.xtext.example.mydsl.ui.keyword_MyDsl"/>
        </page>
〜
    </extension>
    <extension
            point="org.eclipse.ui.propertyPages">
        <page
            class="org.xtext.example.mydsl.ui.MyDslExecutableExtensionFactory:org.eclipse.xtext.ui.editor.preferences.LanguageRootPreferencePage"
            id="org.xtext.example.mydsl.MyDsl"
            name="MyDsl">
            <keywordReference id="org.xtext.example.mydsl.ui.keyword_MyDsl"/>
            <enabledWhen>
                <adapt type="org.eclipse.core.resources.IProject"/>
            </enabledWhen>
            <filter name="projectNature" value="org.eclipse.xtext.ui.shared.xtextNature"/>
        </page>
    </extension>

自作ルート設定ページ

デフォルトのルート設定ページにはタイトル以外何も表示されない。[2014-04-24]
カスタマイズすれば独自の設定を行える。

このとき、プロジェクト用のプロパティーページと、Eclipse全体の設定(Preferences)ページを共通のクラスで作ることが出来る。
そうしておくと、プロパティーページの「Enable project specific settings(プロジェクト固有の設定を可能にする)」にチェックを入れた際のプロジェクト独自設定と、「Configure Workspace Settings(ワークスペース設定の構成)」によるEclipse全体設定との切り替えも自動的に行ってくれる。


ルート設定ページを自作するには、LanguageRootPreferencePageを継承したクラスを用意する。

uiプロジェクト/src/〜/MyRootPreferencePage.java:

import org.eclipse.jface.preference.BooleanFieldEditor;
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.Group;
import org.eclipse.xtext.ui.editor.preferences.LanguageRootPreferencePage;
public class MyRootPreferencePage extends LanguageRootPreferencePage {
	// @see org.eclipse.xtext.ui.refactoring.ui.RefactoringPreferencePage

	public static final String FORMAT_ON_SAVE = "formatOnSave";
	@Override
	protected void createFieldEditors() {
		Composite parent = getFieldEditorParent();
		Group group = new Group(parent, SWT.SHADOW_IN);
		group.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));

		group.setText("actions on save");
		GridLayout layout = new GridLayout(1, false);
		group.setLayout(layout);
		final Composite composite = new Composite(group, SWT.NONE);
		addField(new BooleanFieldEditor(FORMAT_ON_SAVE, "format source", composite) {
			@Override
			protected void checkParent(Control control, Composite parent) {
				if (isPropertyPage()) {
					parent = composite;
				}
				super.checkParent(control, parent);
			}
		});
		group.pack();
	}
}

LanguageRootPreferencePageの実装方法はorg.eclipse.xtext.ui.refactoring.ui.RefactoringPreferencePageが参考になる。

ただし、RefactoringPreferencePageは設定ページ専用らしい。プロパティーページで使うと、エラーが発生する。(Xtext2.4.3)
エラー内容は、「Could Not Accept Changes」というタイトルで「The currently displayed page contains invalid values.」という内容のダイアログ。
ログを見ると「org.eclipse.core.runtime.AssertionFailedException: assertion failed: Different parents」という例外が発生している。
発生箇所はBooleanFieldEditor(FieldEditor)のcheckParentメソッド。
RefactoringPreferencePageのままだと、フィールドをグループの中に作っているのだが、そのせいで親コンポーネントが(一番大元の)FieldEditorParentとは異なっていると判断され、例外が発生してしまう。
回避策としては、(グループを作ったりせずに)FieldEditorParent直下に直接フィールドを作るか、上記のソースの様にcheckParentをオーバーライドして、プロパティーページのときだけparentを差し替えてやる


作成したルート設定ページをplugin.xmlに登録する。
(デフォルトでorg.eclipse.xtext.ui.editor.preferences.LanguageRootPreferencePageだった箇所(2箇所)を独自クラスに差し替える)

uiプロジェクト/plugin.xml:

    <extension
            point="org.eclipse.ui.preferencePages">
        <page
            class="org.xtext.example.mydsl.ui.MyDslExecutableExtensionFactory:com.example.xtext.ui.editor.preferences.MyLRootPreferencePage"
            id="org.xtext.example.mydsl.MyDsl"
            name="MyDsl">
            <keywordReference id="org.xtext.example.mydsl.ui.keyword_MyDsl"/>
        </page>
〜
    </extension>
    <extension
            point="org.eclipse.ui.propertyPages">
        <page
            class="org.xtext.example.mydsl.ui.MyDslExecutableExtensionFactory:com.example.xtext.ui.editor.preferences.MyLRootPreferencePage"
            id="org.xtext.example.mydsl.MyDsl"
            name="MyDsl">
            <keywordReference id="org.xtext.example.mydsl.ui.keyword_MyDsl"/>
            <enabledWhen>
                <adapt type="org.eclipse.core.resources.IProject"/>
            </enabledWhen>
            <filter name="projectNature" value="org.eclipse.xtext.ui.shared.xtextNature"/>
        </page>
    </extension>

プロパティーページや設定ページで設定された内容は、以下のようにして取得できる。
(設定によってファイル保存時のソース整形を行うかどうかを判断する例)

uiプロジェクト/〜/MyDocumentProvider.java:

import org.eclipse.jface.preference.IPreferenceStore;

import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;

import com.google.inject.Inject;
public class MyDocumentProvider extends XtextDocumentProvider {
〜
	@Inject
	private IPreferenceStoreAccess preferenceStoreAccess;
	@Override
	protected void doSaveDocument(IProgressMonitor monitor, Object element, IDocument document, boolean overwrite) throws CoreException {
		IPreferenceStore store = preferenceStoreAccess.getPreferenceStore();
		boolean formatOnSave = store.getBoolean(MyRootPreferencePage.FORMAT_ON_SAVE);
		if (formatOnSave) {
			〜
		}
		super.doSaveDocument(monitor, element, document, overwrite);
	}
}

IPreferenceStoreAccessのフィールドを@Inject付きで定義しておくと、インスタンス生成時に値をセットしてくれる。
それを使ってIPreferenceStoreを取得すればよい。
(getPreferenceStore()は読み取り専用の設定ストアを取得する。書き込みたい場合はgetWritablePreferenceStore()を使う)


色設定ページ

キーワードのハイライト(色付け)の為の色やスタイルを設定するページ。
HighlightingConfigurationで定義したものが自動的に表示され、値を変更することが出来る。


Xtext目次へ戻る / Eclipseへ戻る / 技術メモへ戻る
メールの送信先:ひしだま