Eclipseプラグインを作ってみよう!

第6回画面の作成(1)

前回は実際にPDE(Plug-in Development Environment)のソースコードを読んで、マニフェストエディターがMaster/Detailsパターンで実装されていることがわかりました。今回からマニフェストエディターの実装を参考にしながら、フォームデザイナーの画面を作っていきます。

マニフェストエディターのクラスと画面の関係

最初にマニフェストエディターのクラスと画面の関係をまとめて、各クラスが画面のどの部分を担当しているいかを見てみましょう。

マニフェストエディターのクラスと画像の関係
マニフェストエディターのクラスと画像の関係

まずエディターとしてManifestEditorクラスがあります。ManifestEditorクラスは複数のページを持っており、その中のひとつのページである「拡張」ページをExtensionsPageクラスが管理しています。ExtensionsPageクラスはMasterDetailsBlockクラスを継承したExtensionsBlockクラスをコンテンツとして生成します。ExtensionsBlockクラスはMaster(一覧)を担当するExtensionsSectionクラス、 Details(詳細)を担当するExtensionDetailsクラスを生成・管理しています。

次にこれらのクラスの継承関係を参照し、Eclipse Formsのクラスで表してみましょう。

クラスと画面の関係
Eclipse Formsのクラスと画面の関係

クラスと画面の関係をまとめることで、各クラスが画面のどの部分を担当しているか、ご理解いただけると思います。これらのクラスをそれぞれ実装していけば、マニフェストエディターのような機能を実現することができそうです。第4回でFormEditorクラスを継承したFormDesignerEditorクラスを実装しましたので、残りのFormPage、MasterDetailsBlock、AbstractFormPartクラスをそれぞれ実装していくことにします。

FormPageクラスを継承したクラスの実装

まずFormPageクラスを継承したFieldsPageクラスを作成します。

FieldsPageクラスの作成
FieldsPageクラスの作成

FormPageクラスはデフォルト・コンストラクターを定義していないため、明示的にコンストラクターを定義する必要があります。ここではExtensionsPageクラスを参考に、FormEditorクラスを引数に持つコンストラクターを定義します。

FieldsPageクラスのコンストラクター
public FieldsPage(FormEditor editor) {
    super(editor, null, "フィールド");
}

FormPageクラスのコンストラクターが持つ引数は、それぞれeditor、id、titleです。editorは定義したコンストラクターの引数をそのまま渡します。次のidはページの識別子です。今のところ1ページしか作成する予定がないので、とりあえずnullを渡すことにします。最後にページタイトルを⁠フィールド⁠とします。

次にFieldsPageクラスをFormDesignerEditorクラスのページとして追加するために、FormDesignerEditorクラスのaddPages()メソッドを修正します。

FieldsPageクラスをFormDesignerEditorクラスのページとして追加する
protected void addPages() {
    try {
        addPage(new FieldsPage(this));
    } catch (PartInitException e) {
        e.printStackTrace();            
    }
}

ここまでできたら、実行してみましょう。無名クラスで実装したFormPageクラスを削除したので⁠Hello World!⁠は表示されなくなりましたが、ページのタイトルがコンストラクターで引数として渡した⁠フィールド⁠になっているのがわかります。

ManagedFormクラスとFormToolkitクラス

次にMasterDetailsBlockクラスを継承したクラスを実装するわけですが、その前にウィジェットを生成して画面に表示されるか確認することにします。ここではラベルとテキストボックスを表示してみます。FieldsPageクラスでウィジェットを生成するのに適したメソッドを探してみると、それらしいふたつのメソッドcreatePartControl()、createFormContent()が見つかりました。APIリファレンスを参照するとFormPageクラスのサブクラスはcreateFormContent()メソッドをオーバーライドするように記述されているので、このメソッドを使用します。

次にラベルとテキストボックスを生成します。Eclipse Formsではウィジェットの生成にFormToolkitクラスを使用します。このクラスは、ラベルやテキストボックスといったウィジェットの生成、フォントや色の変更といったプレゼンテーションに関する処理を行います。今回はラベルとテキストボックスを生成しますので、それぞれ createLabel()、createText()メソッドを使用します。このようにFormToolkitクラスで提供されているメソッドのうち、 ⁠create⁠で始まるメソッドはすべてウィジェットのファクトリーメソッドとなっています。

FormToolkitクラスはnewキーワードでインスタンス化することもできますが、今回の場合は引数で渡されているManagedFormクラスが保持しています。 ManagedFormクラスはFormクラスをラップし、フォーム内のコントロールの初期化・破棄といったライフサイクルメソッドを追加します。またフォームパート間の変更通知機能も提供しています。この機能を利用して、Master(一覧)で選択したデータをDetails(詳細)に表示します。

それでは、ManagedForm, FormToolkitクラスを使用し、ラベルとテキストボックスを表示してみましょう。

createFormContent()メソッドをオーバーライドし、ラベルとテキストボックスを生成する
protected void createFormContent(IManagedForm managedForm) {
    ScrolledForm form = managedForm.getForm();
    form.setText("ラベルとテキストボックス");
    form.getBody().setLayout(new GridLayout(2, false));
        
    FormToolkit toolkit = managedForm.getToolkit();
    toolkit.createLabel(form.getBody(), "ラベル:");
    toolkit.createText(form.getBody(), "テキストボックス");
}

最初にgetForm()メソッドでManagedFormクラスが管理しているフォームを取得し、タイトルとレイアウトの設定を行います。次に getToolkit()メソッドでFormToolkitクラスのインスタンスを取得し、ラベルとテキストボックスを生成します。それでは実行してみましょう。

ラベルとテキストボックスの表示
ラベルとテキストボックスの表示

MasterDetailsBlockクラスを継承したクラスの実装

ページの準備はひととおり完了しましたので、MasterDetailsBlockクラスを継承したクラスを実装してみましょう。ExtensionsPageクラスを見てみると、これをインナークラスとして実装しているのでFieldsPageクラスでも同様に実装します。クラス名はFieldsBlockクラスとします。

FieldsBlockクラスをインナークラスとして実装する
public class FieldsPage extends FormPage {
    
    private class FieldsBlock extends MasterDetailsBlock {
        protected void createMasterPart(
                        IManagedForm managedForm,
                        Composite parent) {
        }

        protected void createToolBarActions(IManagedForm managedForm) {
        }

        protected void registerPages(DetailsPart detailsPart) {
        }
    }

...

次にFieldsPageクラスのコンストラクタでFieldsBlockクラスのインスタンスを生成し、createFormContent()メソッドでコントロールを生成するようにします。

FieldsBlockクラスを使用するように変更する
public class FieldsPage extends FormPage {
    private FieldsBlock fBlock;

    private class FieldsBlock extends MasterDetailsBlock {
        ...
    }

    public FieldsPage(FormEditor editor) {
        super(editor, null, "フィールド");
        fBlock = new FieldsBlock();
    }

    protected void createFormContent(IManagedForm managedForm) {
        fBlock.createContent(managedForm);
    }
}

最後に確認のためにMaster(一覧)に先ほどと同様にラベルとテキストボックスを表示します。MasterDetailsBlockクラスで抽象メソッドとして提供されているcreateMasterPart()メソッドに実装します。

Master(一覧)にラベルとテキストボックスを表示する
protected void createMasterPart(
                IManagedForm managedForm,
                Composite parent) {
    FormToolkit toolkit = managedForm.getToolkit();

    Section section = toolkit.createSection(parent, 
            Section.TITLE_BAR | Section.DESCRIPTION);
    section.setText("ラベルとテキストボックス");
    section.setDescription("ラベルとテキストボックスを表示します。");
    
    Composite composite = toolkit.createComposite(section);
    composite.setLayout(new GridLayout(2, false));
    toolkit.createLabel(composite, "ラベル:");
    toolkit.createText(composite, "テキストボックス");

    section.setClient(composite);
}

まずMaster(一覧)のSectionを生成し、タイトルと説明文を設定します。次にコンテナとなるCompositeを生成し、それにラベルとテキストボックスを作成します。それでは実行してみましょう。

Master(一覧)にラベルとテキストボックスを表示する
Master(一覧)にラベルとテキストボックスを表示する

「ラベルとテキストボックス」セクションの右側にマウスカーソルを移動してみてください。Master(一覧)とDetails(詳細)の幅を調整できることがわかります。これはMasterDetailsBlockクラスがSashFormクラスを利用して実装している機能です。このように単にウィジェットを生成・配置するのではなく、MasterDetailsBlockクラスを利用することによって、さまざまな恩恵を受けることができます。

おわりに

今回はEclipse Formsのクラスと画面の関係を明確にし、FormPage, MasterDetailsBlockクラスの実装を行いました。

createFormContent()メソッドの実装部分に関しては、ヘルプやマニフェストエディターの実装を参考に説明するつもりだったのですが、ヘルプには適切な説明がなく、マニフェストエディターは抽象化が進んでおり説明するには複雑すぎるため割愛しました。第2回でEclipse Formsについて説明したときに参照したEclipse Corner Articlesのドキュメントの最後のセクションからサンプルプログラムがダウンロードできます。こちらのプログラムは比較的読みやすくなっていますので、ご参考ください。

次回はMaster(一覧)とDetails(詳細)を実装し、これらが連動するようにします。

おすすめ記事

記事・ニュース一覧