前回 でEclipse Formsを利用して“ Hello World!” を表示することに成功しました。さっそくフォームデザイナーを実装していきたいところですが、どのように実装すればPDE(Plug-in Development Environment)のマニフェストエディターような機能を実現することができるのでしょうか? 今回は実際にマニフェストエディターのソースコードを見て、その実装方法を調べてみることにします。
PDEのチェックアウト
「Eclipse for RCP/Plug-in Developers」でインストールした場合、あらかじめPDEのソースコードが含まれています。プラグインをプロジェクトとしてインポートすることも可能ですが、ここではCVSを利用してPDEのプロジェクトをチェックアウトすることにします。それではEclipseのCVSの利用方法 のページを参照しながらチェックアウトしてみましょう。
最初に「CVSリポジトリー・エクスプローラー」パースペクティブに切り替えます。「 ウィンドウ」 →「 パースペクティブを開く」 →「 その他」をクリックし「パースペクティブを開く」ダイアログを表示します。「 CVSリポジトリー・エクスプローラー」をクリックし、[ OK]ボタンをクリックします。
続いて、新しいCVSリポジトリーを作成します。「 CVSリポジトリー」のツールバーにある[CVSリポジトリーの追加]ボタンをクリックします。
[CVSリポジトリーの追加]ボタン
「CVSリポジトリーの追加」ダイアログが表示されますので、EclipseのCVSの利用方法 に従って設定し、[ 終了]ボタンをクリックします。
「CVSリポジトリーの追加」ダイアログ
「CVSリポジトリー」の作成したCVSリポジトリー下の“ HEAD” をクリックすると、Eclipse platform projectで開発されているプロジェクトの一覧が表示されます。
Eclipse platform projectで開発されているプロジェクトの一覧が表示されます
今回はPDEに関するソースコードを参照したいので、PDEに関するプロジェクトをすべてダウンロードします。具体的には下記のプロジェクトをダウンロードします。
org.eclipse.pde
org.eclipse.pde.build
org.eclipse.pde.build.tests
org.eclipse.pde.core
org.eclipse.pde.doc.user
org.eclipse.pde.junit
org.eclipse.pde.junit.runtime
org.eclipse.pde.source
org.eclipse.pde.ui
org.eclipse.pde.ui.templates
org.eclipse.pde.ui.tests
org.eclipse.pde-feature
一覧から上記プロジェクトを右クリックし「チェックアウト」をクリックすると、チェックアウトされます。依存関係の問題でエラーが出ますが、ビルドするわけではないので今回は無視します。
前回のコードのおさらい
無事PDEのプロジェクトをチェックアウトすることができましたが、どこから見ていけばよいのでしょうか?まず、PDEについて調べる前に前回 のFormEditorクラスのaddPages()メソッドを見てみましょう。
addPages()メソッドの実装
protected void addPages() {
FormPage page = new FormPage(this, null, null) {
protected void createFormContent(IManagedForm managedForm) {
managedForm.getForm().setText("Hello World!");
}
};
try {
addPage(page);
} catch (PartInitException e) {
e.printStackTrace();
}
}
FormPageクラスのインスタンスを生成し、それをFormEditorクラスのaddPage()メソッドを使って追加しています。つまり、FormEditorクラスはFormPageクラスのみ管理しており、各ページの内容はFormPageクラスに任せていると言えます。この構造はEclipse Formsでエディターを実装する場合に共通するはずです。そこでFormEditorクラス、FormPageクラスを継承しているクラスを足掛かりに見ていくことにします。
FormEditorクラスを実装しているクラスの検索
それではPDEの中でFomrEditorクラスを継承しているクラスをEclipseのJava検索機能を使って検索してみましょう。「 検索」 →「 検索」をクリックし、「 検索」ダイアログを表示します。次に「Java 検索」タブをクリックし、各項目を入力します。検索したいのは“ FormEditorを継承しているクラス” ですので、「 ストリングの検索」に “ FormEditor” と入力し、「 制限」グループの「実装」を選択し、[ 検索]ボタンをクリックします。
FormEditorクラスを実装しているクラスを検索する
検索の結果、PDEにはFomrEditorクラスを継承しているクラスがふたつあることがわかります。
FormEditorクラスを実装しているクラスがふたつ見つかりました
アイコンの横に“ A” が付いていることから、これらのクラスは抽象クラスだとわかります。それではこれらのクラスの型階層を見てみましょう。PDEFormEditorクラス、SharedHeaderFormEditorクラスをそれぞれ選択し、F4キーを押すと型階層が表示されます。SharedHeaderFormEditorクラスを継承しているクラスはありませんでしたが、PDEFormEditorクラスにはサブクラスが多数あることがわかります。さらに辿っていくと、ManifestEditorクラスを発見しました。設計時に参考にしていたのはまさにマニフェストエディターだったので、名前からこのクラスがマニフェストエディターの実装であることは一目瞭然です。
PDEFormEditorクラスのサブクラスにManifestEditorクラスを発見しました
addPages()メソッドの検索
それではManifestEditorクラスを開いて、addPages()メソッドの実装を探します。しかし、ManifestEditorクラスにはaddPages()メソッドがありません。そこで、スーパークラスを順番に辿っていったところ、PDEFormEditorクラスで下記の実装がありました。
PDEFormEditorクラスのaddPages()メソッドの実装
protected final void addPages() {
fError = getAggregateModel() == null;
if (fError) {
try {
addPage(new MissingResourcePage(this));
} catch (PartInitException e) {
PDEPlugin.logException(e);
}
} else
addEditorPages();
}
protected abstract void addEditorPages();
この実装から、実際のページの追加はaddEditorPages()メソッドで行われていることがわかります。このメソッドは抽象メソッドとして定義されているので、ManifestEditorクラスに戻って、addEditorPages()メソッドを探したところ、下記の実装を見つけました。
マニフェストエディターにページを追加しているaddEditorPages()メソッドの実装
protected void addEditorPages() {
try {
addPage(new OverviewPage(this));
addPage(new DependenciesPage(this));
addPage(new RuntimePage(this));
if (showExtensionTabs()) {
addExtensionTabs();
}
if (fInputContextManager.hasContext(BuildInputContext.CONTEXT_ID))
addPage(new BuildPage(this));
} catch (PartInitException e) {
PDEPlugin.logException(e);
}
addSourcePage(BundleInputContext.CONTEXT_ID);
addSourcePage(PluginInputContext.CONTEXT_ID);
addSourcePage(BuildInputContext.CONTEXT_ID);
}
第3回 で設計の参考にしたのはマニフェストエディターの「拡張」タブでしたので、その実装を参照することにします。addExtensionTabs()メソッドの中でExtensionPointsPageクラスとExtensionsPageクラスが追加されています。名前からそれぞれ「拡張ポイント」タブ、「 拡張」タブに対応していることがわかります。
ExtensionsPageクラス
それでは「拡張」タブの実装であるExtensionsPageクラスを見てみましょう。ExtensionsPageクラスのcreateFormContent()メソッドがコントロールの生成と配置を行っているので、このメソッドを参照します。
ExtensionsPageクラスのcreateFormContent()メソッド
protected void createFormContent(IManagedForm managedForm) {
ScrolledForm form = managedForm.getForm();
form.setText(PDEUIMessages.ExtensionsPage_title);
form.setImage(PDEPlugin.getDefault().getLabelProvider().get(PDEPluginImages.DESC_EXTENSIONS_OBJ));
fBlock.createContent(managedForm);
//refire selection
fSection.fireSelection();
PlatformUI.getWorkbench().getHelpSystem().setHelp(form.getBody(), IHelpContextIds.MANIFEST_PLUGIN_EXTENSIONS);
super.createFormContent(managedForm);
}
このメソッドではfBlockのcreateContent()メソッドを呼び出しています。fBlockは内部クラスのExtensionsBlockクラスのインスタンスです。前述したようにcreateFormContent()メソッドはコントロールの生成と配置を行うメソッドですので、ExtentionsBlockクラスもなんらかのコントロールのはずです。そこでExtensionsBlockクラスの型階層を表示するとMasterDetailsBlockクラスのサブクラスであることがわかります。
Master/Detailsパターン
MasterDetailsBlockクラスはEclipse Formsのクラスですので、ヘルプからAPIリファレンスを参照してみましょう。このクラスはMaster/Detailsと呼ばれるユーザーインタフェースパターンを実装するためのクラスであることがわかります。Master/DetailsパターンはMaster(一覧)とDetails(詳細)のふたつのパートに分かれており、Master(一覧)で選択されたデータの詳細がDetails(詳細)に表示されるパターンで、ユーザーインタフェースにおいてもっともよく使用されるパターンのひとつです。
マニフェストエディターはMaster(一覧)とDetails(詳細)を独自の方法で実装していたのではなく、MasterDetailsBlockクラスを使って実装していたことがわかりました。フォームデザイナーでもこのクラスを利用して実装していくことにします。
おわりに
今回はPDEのプロジェクトのチェックアウトからマニフェストエディターの実装方法を調べるところまでを説明しました。Eclipseプラグインの開発に限ったことではありませんが、ほかの人のソースコードを読むことは大変勉強になります。今回、CVSリポジトリーの設定を行ったことで、Eclipseのさまざまなプロジェクトをチェックアウトできるようになりましたので、ぜひ興味のあるプラグインのソースコードを読んでみてください。
次回はPDEのソースを参考にしながら、フォームデザイナーの実装を行っていきます。