eclipse3.6(Helios)でのプラグイン開発 - メニュー

仕事で eclipseプラグインを作ることになったので、そのために調べたことのまとめです。
今回は、メニュー及びポップアップメニューの出し方になります。
Help - Eclipse Platform

メニューは、eclipse3.3から IHandler*1を実装したクラスを使うことになったようで、調べていると Actionクラスを使っているものが多くてややこしいことになってました。そのため、自分のために Heliosでのやり方をまとめておきたいと思います。

まずは、今回の関連する拡張ポイント。

org.eclipse.ui.commands
以下で使用する commandIdを定義するためのもの
org.eclipse.ui.handlers
上記の IHandlerを実装したクラスと commandIdを結びつける定義
org.eclipse.ui.bindings
commandIdに対して、キーのバインディングを結びつける定義
org.eclipse.ui.menus
どこにどんなメニューを表示して、そのメニューと commandIdを結びつける定義

org.eclipse.ui.commands

この拡張ポイントの定義は簡単で、commandId(XML上は command/@id) を定義するためのものです。
実際には以下のように categoryの定義も必要になってきます。

<extension
     point="org.eclipse.ui.commands">
   <category
         name="SampleCategory"
         id="SamplePluginGUI.commands.category">
   </category>
   <command
         name="SampleCommand"
         categoryId="SamplePluginGUI.commands.category"
         id="SamplePluginGUI.commands.sampleCommand">
   </command>
</extension>

org.eclipse.ui.handlers

Handlerの定義も単純で、以下のように handlerタグで上記で定義した commandIdと実際の IHandlerを実装したクラスを結び付けます。

<extension
      point="org.eclipse.ui.handlers">
   <handler
         commandId="SamplePluginGUI.commands.sampleCommand"
         class="ch.jpn.taoe.eclipse.sampleplugingui.handlers.SampleHandler">
   </handler>
</extension>

org.eclipse.ui.bindings

キーバインディングの定義は必須でないので、必要がなければ不要です。定義自体は、以下のように commandIdに対してsequence(これがショートカットキーの定義)を決めます。
contextIdは、「org.eclipse.ui.contexts.window」を設定しておくと決まっているようです。将来的に拡張予定だそうだそうですが、今のところ選択肢はないので気にしないでいいかと。
schemeIdは、eclipseの設定画面の「一般>キー」を開くと一番上にあるschemeに対応しています。基本的には「org.eclipse.ui.defaultAcceleratorConfiguration」を選んでおけばいいかと思います。

<extension
      point="org.eclipse.ui.bindings">
   <key
         commandId="SamplePluginGUI.commands.sampleCommand"
         contextId="org.eclipse.ui.contexts.window"
         sequence="M3+6"
         schemeId="org.eclipse.ui.defaultAcceleratorConfiguration">
   </key>
</extension>

sequenceには、キー名を記述することになります。特殊キーの対応は以下の通り。
修飾キーは、M1=ALT, M2=COMMAND, M3=CTRL, M4=SHIFT になります。
その他に以下の特殊名が定義されています。ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, BREAK, BS, CAPS_LOCK, CR, ENTER, RETURN, DEL, END, ESC, ESCAPE, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, FF, HOME, INSERT, LF, NUL, NUM_LOCK, NUMPAD_0, NUMPAD_1, NUMPAD_2, NUMPAD_3, NUMPAD_4, NUMPAD_5, NUMPAD_6, NUMPAD_7, NUMPAD_8, NUMPAD_9, NUMPAD_ADD, NUMPAD_DECIMAL, NUMPAD_DIVIDE, NUMPAD_ENTER, NUMPAD_EQUAL, NUMPAD_MULTIPLY, NUMPAD_SUBTRACT, PAGE_UP, PAGE_DOWN, PAUSE, PRINT_SCREEN, SCROLL_LOCK, SPACE, TAB, VT *2

org.eclipse.ui.menus

ようやく真打の登場です。ここでどのメニューにどういう項目を表示するかを定義します。定義のxmlは、以下のようにmenuContribution タグの locationURIでメニューの追加場所を定義し、その下に commandタグで 実行するcommandIdを登録したり、サブメニューのために menuタグを追加したりできます。さらに、menuタグやcommandタグに visibleWhenタグを付けることで表示する条件を指定できます。
しかし、メニューと言われているものは具体的には3つあり、メニュー・ツールバー・ポップアップメニューに分かれます。さらに、windowに対するメニューやらviewのメニューなどがあり、何がどこに対応しているかわかり辛いですので下の画像を参考にしてください。

<extension
      point="org.eclipse.ui.menus">
   <!-- windowのメニューに追加 -->
   <menuContribution
         locationURI="menu:org.eclipse.ui.main.menu?after=additions">
      <menu
            label="サンプル・メニュー"
            mnemonic="M"
            id="SamplePluginGUI.menus.sampleMenu">
         <command
               commandId="SamplePluginGUI.commands.sampleCommand"
               mnemonic="S"
               id="SamplePluginGUI.menus.sampleCommand">
         </command>
      </menu>
      <command
            commandId="SamplePluginGUI.commands.sampleCommand"
            mnemonic="S"
            id="SamplePluginGUI.menus.sampleCommand">
      </command>
   </menuContribution>
   <!-- 右クリックの全ポップアップメニューに追加 -->
   <menuContribution
         locationURI="popup:org.eclipse.ui.popup.any?after=additions">
      <menu
            label="サンプル・メニュー"
            mnemonic="M"
            id="SamplePluginGUI.menus.sampleMenu">
         <command
               commandId="SamplePluginGUI.commands.sampleCommand"
               mnemonic="S"
               id="SamplePluginGUI.menus.sampleCommand">
         </command>
      </menu>
   </menuContribution>
   <!-- windowのツールバーに追加 -->
   <menuContribution
         locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
      <toolbar
            id="SamplePluginGUI.toolbars.sampleToolbar">
         <command
               commandId="SamplePluginGUI.commands.sampleCommand"
               icon="icons/sample.gif"
               tooltip="Say hello world"
               id="SamplePluginGUI.toolbars.sampleCommand">
         </command>
      </toolbar>
   </menuContribution>
</extension>

結局、locationURI によって様々な場所に表示されることになるので、その値が重要になります。locationURI の値は、以下のような書式で指定します。

"[Scheme]:[ID]?[ArgList]"

Scheme
"menu", "popup", "toolbar" のいずれかを指定します。
ID
表示する対象のIDを指定します。Viewのメニューやツールバーの場合は ViewのIDを指定します。windowのメニューの場合は "org.eclipse.ui.main.menu"、windowsツールバーは "org.eclipse.ui.main.toolbar"、全Viewのポップアップを対象とする場合は "org.eclipse.ui.popup.any" を指定します。
ArgList
対象のメニューのどこに追加するのかを指定します。さらに "[placement]=[id]" と分かれます。placementには "after", "before", "endof" を指定します。id にはメニューの中にある、menuタグの id、もしくは commandタグの idを指定することになります。ただし、"additions"というIDは常に存在するので、場所を気にしない場合にはこのIDを指定することになります。

*1:基本は org.eclipse.core.commands.IHandler インターフェイスが必要ですが、実際には org.eclipse.core.commands.AbstractHandler クラスを継承することになります。

*2:ESCとESCAPE、CRとENTERとRETURNは、それぞれ同じキーを表します。