XtextのNatureAddingEditorCallbackクラス(IXtextEditorCallbackインターフェース)のメモ。
|
Xtextで生成されたエディターを起動すると、初回に「Do you want to add the Xtext nature to the project 'プロジェクト名'?」というダイアログが表示される。
このダイアログはNatureAddingEditorCallbackクラスで表示しているので、 ダイアログを出さないようにする為にはNatureAddingEditorCallbackクラスを独自クラスに差し替えればよい。
ただし、NatureAddingEditorCallbackは(Eclipseプラグイン機構の仕組みにより)外部に公開されていないクラスなので、直接継承しようとすると警告が出る。
したがって、(他の処理も特に無いので)NatureAddingEditorCallbackの親クラスを継承して独自クラスを作ればよい。
Xtext2.4ではNatureAddingEditorCallbackはAbstractDirtyStateAwareEditorCallbackを継承しているので、独自クラスもAbstractDirtyStateAwareEditorCallbackを継承すれば(このクラスは公開されているクラスなので)警告も出ない。
と思っていた。
しかし、Xtext2.7でAbstractDirtyStateAwareEditorCallbackが非推奨となり、NatureAddingEditorCallbackもIXtextEditorCallback.NullImplを継承するよう修正された。
AbstractDirtyStateAwareEditorCallbackを継承した独自クラスを使っていると、Xtext2.7環境では、エディターで文字を入力する度に
『Resource was edited concurrently.』「The resource is concurrently edited in
another editor. Do you want to continue?」というダイアログが出て、非常に鬱陶しい。
「Yes」を押せば一時的に出なくなるが、ファイルを保存してから修正しようとするとまた出てくる(苦笑)
Xtext2.7では、NatureAddingEditorCallbackを差し替えるには(AbstractDirtyStateAwareEditorCallbackでなく)IXtextEditorCallback.NullImplを継承するようにするべき。
とは言え、過去のバージョンでも使えるようにするなら、警告が出るのはあきらめて、NatureAddingEditorCallbackを直接継承しておくのが良さそうだ。
→ネイチャーの自動登録
Xtext2.4で(NatureAddingEditorCallbackを差し替えて)自動的にネイチャーを登録する例。
import java.util.Arrays; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.xtext.ui.XtextProjectHelper; import org.eclipse.xtext.ui.editor.AbstractDirtyStateAwareEditorCallback; import org.eclipse.xtext.ui.editor.XtextEditor;
public class MyEditorCallback extends AbstractDirtyStateAwareEditorCallback { @Override public void afterCreatePartControl(XtextEditor editor) { super.afterCreatePartControl(editor); IResource resource = editor.getResource(); if (resource == null) { return; } IProject project = resource.getProject(); if (!XtextProjectHelper.hasNature(project) && project.isAccessible() && !project.isHidden()) { addNature(project); } }
private void addNature(IProject project) { try { IProjectDescription description = project.getDescription(); String[] natures = description.getNatureIds(); String[] newNatures = Arrays.copyOf(natures, natures.length + 1); newNatures[natures.length] = XtextProjectHelper.NATURE_ID; description.setNatureIds(newNatures); project.setDescription(description, null); } catch (CoreException e) { MyActivator.getInstance().getLog().log(e.getStatus()); } } }
作成したCallbackクラスをUiModuleで指定する。
public class MyUiModule extends com.example.ui.AbstractMyUiModule { 〜
@Override public Class<? extends org.eclipse.xtext.ui.editor.IXtextEditorCallback> bindIXtextEditorCallback() { return MyEditorCallback.class; } }
Xtext2.7で(NatureAddingEditorCallbackを差し替えて)自動的にネイチャーを登録する例。
(Xtext2.4版との違いは、親クラスだけ)
import java.util.Arrays; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.xtext.ui.XtextProjectHelper; import org.eclipse.xtext.ui.editor.IXtextEditorCallback; import org.eclipse.xtext.ui.editor.XtextEditor;
public class MyEditorCallback extends IXtextEditorCallback.NullImpl { @Override public void afterCreatePartControl(XtextEditor editor) { super.afterCreatePartControl(editor); IResource resource = editor.getResource(); if (resource == null) { return; } IProject project = resource.getProject(); if (!XtextProjectHelper.hasNature(project) && project.isAccessible() && !project.isHidden()) { addNature(project); } }
private void addNature(IProject project) { try { IProjectDescription description = project.getDescription(); String[] natures = description.getNatureIds(); String[] newNatures = Arrays.copyOf(natures, natures.length + 1); newNatures[natures.length] = XtextProjectHelper.NATURE_ID; description.setNatureIds(newNatures); project.setDescription(description, null); } catch (CoreException e) { MyActivator.getInstance().getLog().log(e.getStatus()); } } }
作成したCallbackクラスをUiModuleで指定する。
public class MyUiModule extends com.example.ui.AbstractMyUiModule { 〜
@Override public Class<? extends org.eclipse.xtext.ui.editor.IXtextEditorCallback> bindIXtextEditorCallback() { return MyEditorCallback.class; } }