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で定義されたプロパティー名を指定する。