Eclipseのプラグイン開発のJDTのコンテキストメニューの実装方法について。
|
Javaエディター上で右クリックして開くコンテキストメニュー(ポップアップメニュー)に独自のメニューを追加できる。
と言っても、追加先のlocationURIをJavaエディターのものにするだけで、通常のコンテキストメニューの追加方法と全く同じ。
locationURI | 説明 | 参考 |
---|---|---|
popup:org.eclipse.jdt.ui.CompilationUnitEditor.EditorContext?after=additions |
コンテキストメニュー | Christoffer HolmstedtさんのLocationURI for context menu in the Eclipse java editor view |
popup:org.eclipse.jdt.ui.source.menu?after=additions |
「ソース」メニュー | MICHAELさんのExtend the ‘Source’ context menu of the JDT |
コンテキストメニューの各メニューID(メニューの位置を表す文字列)。[2014-05-17]
位置名 | 説明 | 備考 (位置名を見つけた場所) |
更新日 |
---|---|---|---|
additions |
メニュー追加用の場所 | ||
OpenEditor |
「Open Declaration」メニュー | OpenEditorActionGroupクラス | |
OpenTypeHierarchy |
「Open Type Hierarchy」メニュー | OpenViewActionGroupクラス | |
OpenCallHierarchy |
「Open Call Hierarch」メニュー | OpenViewActionGroupクラス | |
copy |
「Copy」メニュー | Xtextの「Copy Qualified Name」メニュー | 2014-06-14 |
copyQualifiedName |
「Copy Qualified Name」メニュー | IJavaEditorActionConstantsクラス | 2014-06-14 |
例えばlocationURIを「popup:org.eclipse.jdt.ui.CompilationUnitEditor.EditorContext?after=OpenEditor
」にすると、「Open
Declaration」の下にメニューを追加できる。
Javaエディターのコンテキストメニューの「ソース」にメニューを追加する例。
まず、処理を行うハンドラークラスを用意する。
import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.jface.viewers.ISelection; import org.eclipse.ui.handlers.HandlerUtil;
public class MySourceHandler extends AbstractHandler { @Override public Object execute(ExecutionEvent event) throws ExecutionException { ISelection selection = HandlerUtil.getCurrentSelection(event); 〜 return null; } }
次に、plugin.xmlを定義する。
<extension point="org.eclipse.ui.commands"> <command categoryId="jp.hishidama.example.jdt.category" id="jp.hishidama.example.mySourceCommand" name="My Source Menu"> </command> </extension>
<extension point="org.eclipse.ui.handlers"> <handler class="jp.hishidama.example.MySourceHandler" commandId="jp.hishidama.example.mySourceCommand"> </handler> </extension>
<extension point="org.eclipse.ui.menus"> <menuContribution allPopups="true" locationURI="popup:org.eclipse.jdt.ui.source.menu?after=additions"> <separator name="jp.hishidama.example.jdt.separator.editorSourceMenu" visible="true"> </separator> <command commandId="jp.hishidama.example.mySourceCommand" icon="icons/example.gif" style="push"> <!-- <visibleWhen> <with variable="activeEditorId"> <equals value="org.eclipse.jdt.ui.CompilationUnitEditor" /> </with> </visibleWhen> --> </command> </menuContribution> </extension>
要するに、「org.eclipse.jdt.ui.source.menu」に対してコマンド(メニュー)を追加すると、コンテキストメニューの「ソース」にメニューが追加される。
対象のJavaエディターで開いているクラスが条件を満たしている場合だけメニューを有効化するといったことが出来る。[2014-05-11]
menu(command)のextensionではvisibleWhenやenabledWhenが指定できるが、これに独自のクラスを追加できる。
このクラスはPropertyTesterクラスを継承して作成する。
PropertyTesterを使うには、「依存関係」の「必須プラグイン」で「org.eclipse.core.expressions
」を追加する必要がある。
Javaエディター上のクラスが特定のクラスの場合だけメニューを有効にする例。
import org.eclipse.core.expressions.PropertyTester; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; import org.eclipse.ui.texteditor.ITextEditor;
@SuppressWarnings("restriction") public class MyJdtPropertyTester extends PropertyTester {
@Override public boolean test(Object receiver, String property, Object[] args, Object expectedValue) { ITextEditor editor = (ITextEditor) receiver; ITypeRoot element = EditorUtility.getEditorInputJavaElement(editor, true); if (element != null) { if ("isTargetClass".equals(property)) { IType type = root.findPrimaryType(); if (type != null) { return 〜; // 何らかの判定を行い、対象ならばtrueを返す } } } return false; } }
receiverには条件判定対象のオブジェクトが渡ってくる。
propertyにはplugin.xml上で指定したプロパティー名(接頭辞を除いたもの)が入っている。
receiverをいきなりITextEditorにキャストしても大丈夫な理由は、PropertyTesterのextensionで「type="org.eclipse.ui.texteditor.ITextEditor"
」を指定して、ITextEditorのときだけ呼ばれるようにしている為。
ちなみに、EditorUtility.getEditorInputJavaElement()
でIJavaElementが取得できれば、判定対象はたぶんJavaエディターだろうから、「判定対象オブジェクトがJavaエディターかどうか」は明示的には判定していない。
plugin.xmlには、最初に、作成したPropertyTesterを呼び出すための拡張ポイントを定義する。
<extension point="org.eclipse.core.expressions.propertyTesters"> <propertyTester class="com.example.jdt.MyJdtPropertyTester" id="com.example.myJdtPropertyTester" namespace="my.jdt" properties="isTargetClass" type="org.eclipse.ui.texteditor.ITextEditor"> </propertyTester> </extension>
classには、作成したPropertyTesterクラスを指定する。
typeには、条件判定対象オブジェクトがどういうクラスのときにこのPropertyTesterが呼ばれるかを指定する。とりあえずjava.lang.Objectにしておくと、どういうオブジェクトのときでも呼ばれるようになる。
namespaceは、enabledWhen(test)でプロパティー名を指定するときの接頭辞。
propertiesは、接頭辞を除いたプロパティー名。カンマ区切りで複数定義できる。
使う側は以下のようになる。
<extension point="org.eclipse.ui.handlers"> <handler class="jp.hishidama.example.MySourceHandler" commandId="jp.hishidama.example.mySourceCommand"> <enabledWhen> <and> <with variable="activeEditorId"> <equals value="org.eclipse.jdt.ui.CompilationUnitEditor" /> </with> <with variable="activeEditor"> <test forcePluginActivation="true" property="my.jdt.isTargetClass" /> </with> </and> </enabledWhen> </handler> </extension>
この例では、PropertyTesterのextensionではITextEditorを受け付けるようになっているので、
enabledWhenの側でも「with variable="activeEditor"
」を使って、
条件判定対象オブジェクトをエディターにしている。
testのforcePluginActivationをtrueにしておかないと、条件判定が有効にならないっぽい。
testのpropertyには、PropertyTesterのextensionのnamespaceおよびpropertiesで定義されたプロパティー名を指定する。