« エディタを閉じる | トップページ | ファイルの作成 »

2004.05.26

アクション起動時の要素選択でのIAdaptableの利用

Package Explorerビューの各要素について,コンテキストメニューに追加したアクションの起動を,ファイルに対してのみ行いたいと考えたとする。例えば,

package-explorer.gif

という感じだった場合に,「class-icon.gifEmployee.java」「,「class-icon.gifEmployeeTest.java」「class-icon.giftest.exclusion」という3つのファイルに対してアクションを実行したいというシチュエーションを想像して欲しい。

コンテキストメニューへのアクションの追加」で取り上げた方法を参考にして,Eclipse内でファイルリソースはIFileオブジェクトで表現されていることを踏まえると,以下のようなアクションの定義が考えられる。

  <extension point="org.eclipse.ui.popupMenus">
    <objectContribution
        id="yoichiro.myPlugin"
        objectClass="org.eclipse.core.resources.IFile">
      <action
          id="yoichiro.myPlugin.MyAction"
          name="My action"
          class="yoichiro.myPlugin.MyAction">
      </action>
    </objectContribution>
  </extension>

実際に上記をプラグイン・マニフェストに記載して実行してみると,「class-icon.giftest.exclusion」ファイルしかアクションの対象にならない。ビューの見かけ上はファイルなのに,なんで!?ってことになってしまう。

実はclass-icon.gifEmployee.java」と「class-icon.gifEmployeeTest.java」という要素は,ICompilationUnitオブジェクトであって,IFileオブジェクトではない。同時に,2つのファイルが持つクラスのノード(class-icon.gifアイコンの要素)に関しても,「コンテキストメニューへのアクションの追加」で紹介したように,ITypeオブジェクトであってIFileオブジェクトではない。よって,上記の記述ではこれらの要素はIFileオブジェクトではないと判断され,アクションが有効にならないのである。「Package Explorerに表示されるあらゆる要素の種別を予測して,個別に定義していかなくちゃいけないの?」となると,とっても面倒だし柔軟性という点でとても良いとはいえない。

Eclipseでは,このような問題に対して,IAdaptableインタフェースを使うことで解決している。上記のプラグイン・マニフェストで記述されているobjectContribution要素のobjectClass属性で指定された型について,仮にICompilationUnitオブジェクトやITypeオブジェクトであっても,「おまえホントはIFileオブジェクトちゃうんか!?」という問い合わせを各要素に対して行わせるための指定をすることができる

  <extension point="org.eclipse.ui.popupMenus">
    <objectContribution
        id="yoichiro.myPlugin"
        objectClass="org.eclipse.core.resources.IFile"
        adaptable="true">
      <action
          id="yoichiro.myPlugin.MyAction"
          name="My action"
          class="yoichiro.myPlugin.MyAction">
      </action>
    </objectContribution>
  </extension>

Package Explorer上に表示されている要素は,IAdaptableインタフェースを実装したオブジェクトである。上記のようにadaptable属性にtrueを渡すことにより,Eclipseプラットフォームは各要素に対して,getAdapterメソッドにIResourceクラスオブジェクトを渡して呼び出し,その戻り値がobjectClass属性で指定した型かどうかをチェックする。そして,もしgetAdapterメソッドの戻り値のオブジェクトがobjectClass属性で指定したクラスの型であれば,その要素はアクションを有効にして良いと判断され,アクションがコンテキストメニューに表示されるようになる。

ITypeインタフェースの実装クラスでは,getAdapterメソッドにIResourceクラスオブジェクトが渡されると,そのクラスが定義されたファイルを表すIFileオブジェクトを返却するようになっている。もちろんICompilationUnitオブジェクトやIMethodオブジェクトなども同様である。つまり上記の例ではclass-icon.gifEmployee」の要素はITypeオブジェクトだけど,getAdapterメソッドが利用されることによりEmployee.javaファイルのIFileオブジェクトが取り出され,結果としてアクションが有効になる,という動きになる。

上記のアクションを処理するIObjectActionDelegateインタフェースの実装クラスの中では,例えば,

  public void selectionChanged(IAction action, ISelection selection) {
    IStructuredSelection structured = (IStructuredSelection)selection;
    IAdaptable adaptable = (IAdaptable)structured.getFirstElement();
    IFile file = (IFile)adaptable.getAdapter(IResource.class);
  }

というようにして,IFileオブジェクトを取得することができる。

|

« エディタを閉じる | トップページ | ファイルの作成 »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/12631/657473

この記事へのトラックバック一覧です: アクション起動時の要素選択でのIAdaptableの利用:

« エディタを閉じる | トップページ | ファイルの作成 »