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へ戻る / 技術メモへ戻る
メールの送信先:ひしだま