さて、Eclipse/プラグイン開発のTIPS集/org.eclipse.core.runtime.IAdaptable の続きです。 さっきのように、ContactクラスがPlatformObject?を拡張している場合は、 org.eclipse.core.runtime.IAdaptable インタフェース org.eclipse.core.runtime.PlatformObject オブジェクト org.eclipse.core.runtime.IAdapterFactory ファクトリ を使ってViewに表示ができました。今度はModelオブジェクトがIAdaptableやPlatformObject?を実装していない場合はどうするか、です。。通常このような場合が多いですよね。モデルをEclipse依存にしたくないですしね。 モデル †モデルは先のクラス構成で、ContactがPlatformObject?を拡張していない、一般的なクラスであると仮定します。 org.eclipse.core.runtime.adapters拡張ポイント †こたえはやはりorg.eclipse.core.runtime.adapters拡張ポイントみたいです。 <extension point="org.eclipse.core.runtime.adapters"> <factory adaptableType="org.eclipsercp.hyperbola.model.Contact" class="org.eclipsercp.hyperbola.model.HyperbolaAdapterFactory"> <adapter type="org.eclipse.ui.model.IWorkbenchAdapter"/> </factory> </extension> このように定義しておくと、Contactのインスタンスelementに対して、 Platform.getAdapterManager().loadAdapter (element, IWorkbenchAdapter.class.getName()); ↑adaptableType ↑<adapter type="org.eclipse.ui.model.IWorkbenchAdapter"/> というメソッドがよばれたときに、 IAdapterFactory adapterFactory = new HyperbolaAdapterFactory(); Platform.getAdapterManager().registerAdapters(adapterFactory,Contact.class); が自動的に行われます。でメソッドの返り値が IAdapterFactory#getAdapter(element, IWorkbenchAdapter.class); になります。 つまりContactがPlatformObject?ではないにもかかわらず、IAdapterFactory?を用いて IWorkbenchAdapter adapter=(IWorkbenchAdapter) Contact.getAdapter(IWorkbenchAdapter.class); の様なことができるわけですね。これと IAdapterFactory adapterFactory = new HyperbolaAdapterFactory(); Platform.getAdapterManager().registerAdapters(adapterFactory,Contact.class); IWorkbenchAdapter adapter = (IWorkbenchAdapter)adapterFactory.getAdapter(IWorkbenchAdapter.class); は等価でしたね。 ちょっとまとめ †まとめると
となるわけです。つまり、ある一般的なクラスに対して、IAdaptableでないにも関わらず動的にgetAdapterが呼べる仕組みということですね。まだ、あたまがまとまってませんが、ものすごい事のような気がしてきました。 さて、つづき †さて、Viewerの続きです。ContactはもはやPlatformObject?ではないため当然IAdaptableでもありません。これだけだとBaseWorkbenchContentProvider?の protected IWorkbenchAdapter getAdapter(Object element) { if (!(element instanceof IAdaptable)) { return null; } return (IWorkbenchAdapter) ((IAdaptable) element) .getAdapter(IWorkbenchAdapter.class); } は当然nullになってしまうので、拡張クラスを作ってOverrideします。 public class HogeContentProvider extends BaseWorkbenchContentProvider { protected IWorkbenchAdapter getAdapter(Object element) { ↑この引数elementはモデル要素: Contact,ContactEntry,ContactGroupでした IWorkbenchAdapter adapter = null; // モデルが、IAdaptableならばそのまま使う if (element instanceof IAdaptable) { adapter = getAdapter(element); } // モデルが、一般的なオブジェクトならば、さっきの動的ローディングをつかう。 if (element != null && adapter == null) { adapter = (IWorkbenchAdapter) Platform.getAdapterManager() .loadAdapter(element, IWorkbenchAdapter.class.getName()); } // この返り値adapterは、org.eclipsercp.hyperbola.model.HyperbolaAdapterFactory // のgetAdapter(element,IWorkbenchAdapter.class);になるんでしたね。 return adapter; } } Viewerにはこのコンテンツプロバイダをセットすることで、先と同じ結果が得られます。 当然、Viewでorg.eclipsercp.hyperbola.model.HyperbolaAdapterFactory?をnewする必要もないし、当然register,unregisterも必要ないです。モデルオブジェクトもPlatformObject?を拡張している必要もありません。 、、、、ここまでやって、コンテンツプロバイダやラベルプロバイダはIWorkbenchAdapter?を使わない一般的なやり方の方がいいような気がしますね。よくわかってないだけかも知れないけど。。 あ、当然ラベルプロバイダも書き換える必要があります。この書きかえ方が...またようわからん。。WorkbenchLabelProvider?#getAdapterはfinalだし。。。。じぶんで書くしかないのかなぁ。。 関連リンク †
この記事は
現在のアクセス:13401 |