S-JIS[2014-05-05/2014-06-14] 変更履歴

Eclipse JDT コンテキストメニュー

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

コンテキストメニューの各メニュー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エディターのコンテキストメニューの「ソース」にメニューを追加する例。

まず、処理を行うハンドラークラスを用意する。

MySourceHandler.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を定義する。

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エディター上のクラスが特定のクラスの場合だけメニューを有効にする例。

MyJdtPropertyTester.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を呼び出すための拡張ポイントを定義する。

plugin.xml:

   <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は、接頭辞を除いたプロパティー名。カンマ区切りで複数定義できる。


使う側は以下のようになる。

plugin.xml:

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


JDTへ戻る / Eclipseプラグインへ戻る / Eclipseへ戻る / 技術メモへ戻る
メールの送信先:ひしだま