S-JIS[2013-01-13/2014-05-11] 変更履歴

EclipseプラグインCommandサンプル

Eclipseプラグイン開発のCommandのサンプル。


サンプル

Eclipseのメニューバー(およびツールバー)にメニューを表示し、そのメニューをクリックしたらメッセージダイアログが表示されるプラグインを作ってみる。
対象はWindows7上のEclipse3.7。

Eclipse3.3以降では、メニューを実行するには「コマンド」を使う。

Eclipse3.2以前の「アクション」を使う例


プラグインプロジェクトの作成

最初に、Eclipseプラグインを開発する為のプロジェクトを作成する。
※余計なプラグイン(Scalaプラグインとか)の入っていない初期状態のEclipseを使った方が良さそう

  1. メニューバーの「ファイル(F)」→「新規(N)」→「プロジェクト(R)」で「新規プロジェクト」ダイアログを開く。
  2. 「プラグイン・プロジェクト」(プラグイン開発の下にある)を選択して、次へ。
  3. プロジェクト名に適当な名前を入力して、次へ。
    内容 説明
    プロジェクト名 プロジェクト(ディレクトリー)名。 plugin-example2
    ソース・フォルダー   src
    出力フォルダー   classes
    Eclipseバージョン プラグインの実行対象となるEclipseのバージョン。 3.7
  4. IDやアクティベーターのクラス名を変更し、次へ。
    内容 説明
    ID プラグインのID。
    Javaのパッケージ名の様に世界でユニーク(単一)になるような名前を付ける。
    com.example.eclipse.plugin.hello2
    アクティベーター プラグインの各種情報にアクセスする為のクラス。
    このクラスは自分で用意する必要があるが、ここで指定しておくと自動生成してくれる。
    Hello Worldくらいのサンプルでは使わないが、一応用意しておく。
    com.example.eclipse.plugin.hello2.Activator
  5. テンプレートを選択して、次へ。
    今回は「Hello, World Command」を選択する。
  6. 「Hello, World」テンプレートで生成するパッケージ名やクラス名を指定して、完了。
    内容 説明
    Javaパッケージ名 生成するパッケージ名。 com.example.eclipse.plugin.hello2.handlers
    アクション・クラス名 生成クラス名。 HelloHandler
    メッセージ・ボックス・テキスト 今回のサンプルでメッセージダイアログに表示される内容。 Hello, Eclipse world

これで、plugin-example2というプロジェクトが作られる。
内容は以下のようになっている。

内容 説明
src HelloHandler.java
Activator.java
ソースディレクトリー。
生成されたJavaソースファイルが置かれている。
icons sample.gif アイコンのディレクトリー。
ツールバーにはこのアイコンが表示される。
META-INF MANIFEST.MF プラグインの情報
プラグインのバージョンや依存ライブラリーが記述されている。
build.properties プラグインのビルド情報
plugin.xml プラグインの設定内容。
ここにextension(拡張内容)を記述して、自分のクラスを実行させるようにする。

プラグインの実行方法

「Hello, World」テンプレートで生成されたプロジェクトは、そのままで実行させることが出来る。

  1. パッケージエクスプローラーからMANIFEST.MFをダブルクリックし、エディターを開く。
  2. 「概要」タブを選択する。
  3. 「テスト」という段落の「Eclipseアプリケーションの起動」をクリックする。

これで、作成したプラグインの含まれた新しいEclipseが起動する。
(この方法によって一度起動すれば、以降はメニューバーやツールバーの「実行」メニューから再実行することが出来る)

今回は、新しいEclipseのメニューバーに「サンプル・メニュー」が追加されているはず。
この「サンプル・メニュー」→「サンプル・コマンド Ctrl+6」を実行すると、メッセージダイアログが表示される。
あるいは、ツールバーの「Say hello world (Ctrl+6)」アイコンをクリックすることでも実行される。
あるいは、Ctrl+6を押しても実行される。


Eclipseプラグインを実行中に「java.lang.OutOfMemoryError: PermGen space」が発生することがある。[2013-09-06]
この場合、Run/Debugの起動オプションのVM引数に「-XX:MaxPermSize=256m」を付けると直る。


plugin.xml

プラグインにどういう拡張を行うか(自分独自の動作をさせるか)は、plugin.xmlに記述されている。

パッケージエクスプローラーでplugin.xmlをダブルクリックすると、拡張エディターが開く。
設定内容の確認や修正はこのエディターで行うのが楽そうだが、
右クリックしてテキストエディターで開くと、XMLとして内容を表示できる。

plugin.xml:

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>

   <extension
         point="org.eclipse.ui.commands">
      <category
            name="サンプル・カテゴリー"
            id="com.example.eclipse.plugin.hello2.commands.category">
      </category>
      <command
            name="サンプル・コマンド"
            categoryId="com.example.eclipse.plugin.hello2.commands.category"
            id="com.example.eclipse.plugin.hello2.commands.sampleCommand">
      </command>
   </extension>
   <extension
         point="org.eclipse.ui.handlers">
      <handler
            commandId="com.example.eclipse.plugin.hello2.commands.sampleCommand"
            class="com.example.eclipse.plugin.hello2.handlers.HelloHandler">
      </handler>
   </extension>
   <extension
         point="org.eclipse.ui.bindings">
      <key
            commandId="com.example.eclipse.plugin.hello2.commands.sampleCommand"
            contextId="org.eclipse.ui.contexts.window"
            sequence="M1+6"
            schemeId="org.eclipse.ui.defaultAcceleratorConfiguration">
      </key>
   </extension>
   <extension
         point="org.eclipse.ui.menus">
      <menuContribution
            locationURI="menu:org.eclipse.ui.main.menu?after=additions">
         <menu
               label="サンプル・メニュー"
               mnemonic="M"
               id="com.example.eclipse.plugin.hello2.menus.sampleMenu">
            <command
                  commandId="com.example.eclipse.plugin.hello2.commands.sampleCommand"
                  mnemonic="S"
                  id="com.example.eclipse.plugin.hello2.menus.sampleCommand">
            </command>
         </menu>
      </menuContribution>
      <menuContribution
            locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
         <toolbar
               id="com.example.eclipse.plugin.hello2.toolbars.sampleToolbar">
            <command
                  commandId="com.example.eclipse.plugin.hello2.commands.sampleCommand"
                  icon="icons/sample.gif"
                  tooltip="Say hello world"
                  id="com.example.eclipse.plugin.hello2.toolbars.sampleCommand">
            </command>
         </toolbar>
      </menuContribution>
   </extension>

</plugin>

今回はコマンドを追加しているので、複数のextensionが定義されている。
commandsで(カテゴリーIDと)コマンドIDを定義し、handlersで (コマンドIDに対して)どのクラスを呼び出すかを設定する。
bindingsではショートカットキー(どのキーを押したらどのコマンドIDを実行するか)を割り当てている。
menusではメニューバーとツールバーにコマンドIDを割り当てている。

独自のcontextIdを定義する例


bindingsのkey/sequenceで「M1+6」と記述しているが、これがWindowsやUNIXでの「Ctrl+6」を意味する。
MacOS Xではキーの使途が異なるらしいので、キーを抽象化して記述する。

抽象キー Windows・UNIXのキー
M1 Ctrl キー
M2 Shift キー
M3 Alt キー

menusではmenuContribution要素を2つ入れ、メニューバーとツールバーを設定している。

locationURI
  スキーム 備考
メニューバー menu menu:org.eclipse.ui.main.menu?after=additions  
ツールバー toolbar toolbar:org.eclipse.ui.main.toolbar?after=additions  
ポップアップ popup popup:org.eclipse.ui.popup.any?after=additions 全てのポップアップ
popup:org.eclipse.jdt.ui.PackageExplorer?after=additions パッケージエクスプローラーのポップアップ[2013-08-31]

menuタグやtoolbarタグ内にcommand要素を複数入れると複数のメニューになる。


ハンドラークラス

実行される内容はハンドラークラスに記述されている。

src/com/example/eclipse/plugin/hello2/handlers/HelloHandler.java:

package com.example.eclipse.plugin.hello2.handlers;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.jface.dialogs.MessageDialog;
/**
 * Our sample handler extends AbstractHandler, an IHandler base class.
 * @see org.eclipse.core.commands.IHandler
 * @see org.eclipse.core.commands.AbstractHandler
 */
public class HelloHandler extends AbstractHandler {
	/**
	 * The constructor.
	 */
	public HelloHandler() {
	}
	/**
	 * the command has been executed, so extract extract the needed information
	 * from the application context.
	 */
	public Object execute(ExecutionEvent event) throws ExecutionException {
		IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
		MessageDialog.openInformation(
			window.getShell(),
			"Plugin-example2",
			"Hello, Eclipse world");
		return null;
	}
}

メニューやツールバーのアイコンがクリックされたりショートカットキーが押されたりすると、execute()が実行される。
今回はこの中でMessageDialogクラスを使ってダイアログを表示している。
openInformation()の第1引数は親ウィンドウ(シェル)、第2引数はダイアログのタイトル、第3引数はメッセージ本体。


ポップアップメニューの例

右クリックで開くポップアップメニューにコマンドを追加してみる。

menusエクステンションに新しいmenuContribution要素を追加し、locationURIにポップアップを指定すればよい。

plugin.xml:

<plugin>
〜
   <extension
         point="org.eclipse.ui.menus">
〜
      <menuContribution
            locationURI="popup:org.eclipse.ui.popup.any?after=additions">
         <command
               commandId="com.example.eclipse.plugin.hello2.commands.sampleCommand"
               id="com.example.eclipse.plugin.hello2.popup.sampleCommand">
         </command>
      </menuContribution>
   </extension>

</plugin>

ただ、これだと全てのポップアップメニューでコマンドが出てしまう…。


visibleWhen

一部のポップアップメニューのみにコマンドを出すよう、条件を付けることが出来る。

プロジェクトが選択されているときのポップアップメニューにだけコマンドを出す例(plugin.xml):

<plugin>
〜
   <extension
         point="org.eclipse.ui.menus">
〜
      <menuContribution
            locationURI="popup:org.eclipse.ui.popup.any?after=additions">
         <command
               commandId="com.example.eclipse.plugin.hello2.commands.sampleCommand"
               id="com.example.eclipse.plugin.hello2.popup.sampleCommand">
            <visibleWhen>
               <with variable="selection">
                  <iterate>
                     <adapt type="org.eclipse.core.resources.IProject" />
                  </iterate>
               </with>
            </visibleWhen>
         </command>
      </menuContribution>
   </extension>

</plugin>

commandタグにvisibleWhen要素を追加する。
withタグのvariable属性で、実行中の状態(変数)を取得することが出来る。
withタグのボディー部に、その状態と比較する条件を記述する。

参考:『Eclipse プラグイン開発 徹底攻略』p.198


visibleWhenによる条件付けは、ポップアップメニュー以外(コマンドを使うメニューバーやツールバー)でも指定できる。
ただ、そうするとあちこちに同じ条件(with要素)を記述する事になりかねないので、条件判定だけ別の場所に記述して、それを参照するようにする事が出来る。

plugin.xml:

<plugin>
〜
   <extension
         point="org.eclipse.ui.menus">
〜
      <menuContribution
            locationURI="popup:org.eclipse.ui.popup.any?after=additions">
         <command
               commandId="com.example.eclipse.plugin.hello2.commands.sampleCommand"
               id="com.example.eclipse.plugin.hello2.popup.sampleCommand">
            <visibleWhen>
               <reference definitionId="com.example.eclipse.plugin.hello2.commands.sampleCommand.visibleWhen" />
            </visibleWhen>
         </command>
      </menuContribution>
   </extension>

   <extension
         point="org.eclipse.core.expressions.definitions">
      <definition
            id="com.example.eclipse.plugin.hello2.commands.sampleCommand.visibleWhen">
         <with variable="selection">
            <iterate>
               <adapt type="org.eclipse.core.resources.IProject" />
            </iterate>
         </with>
      </definition>
   </extension>

</plugin>

また、visibleWhenはcommandの下だけでなくmenuの下に置くことも出来る。[2013-05-06]

   <extension
         point="org.eclipse.ui.menus">
〜
      <menuContribution
            locationURI="popup:org.eclipse.ui.popup.any?after=additions">
         <menu
               label = "my context menu">
            <command
                  commandId="com.example.eclipse.plugin.hello2.commands.sampleCommand"
                  id="com.example.eclipse.plugin.hello2.popup.sampleCommand">
            </command>
            <visibleWhen>
               <reference definitionId="com.example.eclipse.plugin.hello2.commands.sampleCommand.visibleWhen" />
            </visibleWhen>
         </menu>
      </menuContribution>
   </extension>

条件 記述例 更新日
プロジェクト
(パッケージエクスプローラー)
<with
      variable="selection">
   <iterate>
      <adapt
            type="org.eclipse.core.resources.IProject" />
   </iterate>
</with>
 
特定の拡張子のファイル
(パッケージエクスプローラー)
<with
      variable="selection">
   <iterate
         ifEmpty="false">
      <adapt
            type="org.eclipse.core.resources.IFile">
         <test
               property="org.eclipse.core.resources.extension"
               value="txt">
         </test>
      </adapt>
   </iterate>
</with>
2013-03-21
クラスファイル
(パッケージエクスプローラー)
<with
      variable="selection">
   <iterate
         ifEmpty="false">
      <adapt
            type="org.eclipse.jdt.core.ICompilationUnit">
      </adapt>
   </iterate>
</with>
2013-03-21
特定のエディター
<with
      variable="activeEditorId">
   <equals
      value="dmdl_editor.editors.DMDLEditor">
   </equals>
</with>
2013-05-06
<!-- Javaエディター -->
<with
      variable="activeEditorId">
   <equals
      value="org.eclipse.jdt.ui.CompilationUnitEditor">
   </equals>
</with>
2014-05-11
特定の拡張子のファイル
(エディター)
<with
      variable="activeEditorInput">
   <adapt
         type="org.eclipse.core.resources.IFile">
      <test
            property="org.eclipse.core.resources.extension"
            value="txt">
      </test>
   </adapt>
</with>
2013-06-05
独自の条件
PropertyTester
<test
      forcePluginActivation="true"
      property="my.jdt.isTargetClass" />
2014-05-11

別プラグインのメニューへの追加

あるプラグインでメニューを定義し、別のプラグインでそのメニューに追加する形でメニューを定義することが出来る。
locationURIで別プラグインのIDを指定すればよい。

  plugin.xml 備考
先行メニュー
<extension
      point="org.eclipse.ui.menus">
   <menuContribution
         locationURI="popup:org.eclipse.ui.popup.any?after=additions">
      <menu
            id="example.popup.menu"
            label="example">
         <command
               commandId="example-command1"
               label="command1">
         </command>
         <separator
               name="additions"
               visible="true">
         </separator>
      </menu>
   </menuContribution>
</extension>
menuContributionの下にmenuを置き、
その下にcommandを書く。
separatorでnameを定義しておくと
他のプラグインからその位置を指定できる。
後続メニュー
<extension
      point="org.eclipse.ui.menus">
   <menuContribution
         locationURI="popup:example.popup.menu?after=additions">
      <command
            commandId="example-command2"
            label="command2">
      </command>
   </menuContribution>
</extension>
locationURIで他のプラグインのIDと位置を指定する。
そして、menuContributionの下にmenuを置かず、
直接commandを書く。

ツールバーのプルダウンメニュー

ツールバーのボタンをプルダウン化して複数のメニューをまとめ、そのうち1つを選択して実行するように出来る。[2014-04-27]

ツールバー上のボタンとしては、スタイルをpulldownにするだけで、普通のボタンの様に定義する。
プルダウンにまとめるメニュー群は、1つのメニューとして別途定義する。その際に、locationURIとして「ツールバー上のボタンのコマンドID」を指定する。

plugin.xml:

   <extension
         point="org.eclipse.ui.menus">

      <!-- ツールバー上のボタンをpulldownで定義 -->
      <menuContribution
            locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
         <toolbar
               id="com.example.eclipse.plugin.hello.toolbars.exmpleToolbar">
            <command
         id="com.example.hello.toolbar.pulldownExample"
                  commandId="com.example.eclipse.plugin.hello.commands.exampleCommand1"
                  style="pulldown">
            </command>
         </toolbar>
      </menuContribution>

      <!-- プルダウンされるメニューを定義 -->
      <menuContribution
            locationURI="menu:com.example.hello.toolbar.pulldownExample">
         <command
               commandId="com.example.eclipse.plugin.hello.commands.exampleCommand1"
               style="push">
         </command>
         <command
               commandId="com.example.eclipse.plugin.hello.commands.exampleCommand2"
               style="push">
         </command>
         <command
               commandId="com.example.eclipse.plugin.hello.commands.exampleCommand3"
               style="push">
         </command>
      </menuContribution>
   </extension>

ツールバー上にデフォルトで表示されているボタンのコマンドと、プルダウンリスト内のコマンドは別なので、同じものを重複して定義している。

参考: Eclipse TipsのContributing Workbench Wizards thru Commands


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