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

第8回 画面の作成(3)

この記事を読むのに必要な時間:およそ 5.5 分

前回まででフィールドの一覧を表示できるようになりました。今回はMaster(一覧)のボタンの表示と,Master(一覧)のテーブルで選択されたフィールドの詳細がDetails(詳細)に表示されるようにします。

ボタンの表示

それでは,前回表示したテーブルの右横に[追加],[削除],[上へ],[下へ]ボタンを表示します。まず,テーブルの親コンポジットに新たなコンポジットbuttonsを作成し,これに対して各ボタンを作成していきます。さらに作成する各ボタンを水平方向いっぱいに広げるようにGridDataオブジェクトを設定します。GridLayoutクラスはレイアウト時に各ウィジェットごとに設定されたGridDataオブジェクトを取得し,配置位置を計算するので,同じ設定内容であってもウィジェットごとにインスタンスを設定しなければなりません。

FieldBlockクラスのcreateMasterPart()メソッドでボタンを生成する

protected void createMasterPart(
                IManagedForm managedForm,
                Composite parent) {
    ...

    TableViewer viewer = new TableViewer(table);
    viewer.setContentProvider(new ArrayContentProvider());
    viewer.setLabelProvider(new ITableLabelProvider() {
        ...
    });
    
    Composite buttons = toolkit.createComposite(composite);
    layoutData = new GridData();
    layoutData.verticalAlignment = GridData.FILL;
    buttons.setLayoutData(layoutData);

    buttons.setLayout(new GridLayout());

    Button addButton = toolkit.createButton(buttons, "追加(&A)...", SWT.PUSH);
    layoutData = new GridData();
    layoutData.horizontalAlignment = GridData.FILL;
    addButton.setLayoutData(layoutData);
    
    Button delButton = toolkit.createButton(buttons, "削除(&D)...", SWT.PUSH);
    layoutData = new GridData();
    layoutData.horizontalAlignment = GridData.FILL;
    delButton.setLayoutData(layoutData);

    Button upButton = toolkit.createButton(buttons, "上へ", SWT.PUSH);
    layoutData = new GridData();
    layoutData.horizontalAlignment = GridData.FILL;
    upButton.setLayoutData(layoutData);

    Button downButton = toolkit.createButton(buttons, "下へ", SWT.PUSH);
    layoutData = new GridData();
    layoutData.horizontalAlignment = GridData.FILL;
    downButton.setLayoutData(layoutData);

    section.setClient(composite);
    
    viewer.setInput(createSample());
}

それでは実行してボタンが表示されることを確認しましょう。

各ボタンが表示されました

各ボタンが表示されました

入力項目定義フォームの表示

ボタンが配置できましたので,続いて入力項目定義フォームを表示してみましょう。第3回で行った画面設計のラフスケッチを元に実装していきます。

入力項目定義フォームのラフスケッチ

入力項目定義フォームのラフスケッチ

Master(一覧)はFieldsBlockクラスのcreateMasterPart()メソッドで実装しましたが,Details(詳細)はどこに実装すればよいのでしょうか。ここで,マニフェストエディターの実装を参照してみましょう。フォームデザイナーが参考にした「拡張」ページの実装を見てみます。「拡張」ページはExtensionsPageクラスで実装されており,Master/DetailsパターンはMasterDetailsBlockクラスを継承したExtensionsBlockクラスで実装されていました。このExtensionsBlockクラスのregisterPages()メソッドでExtensionsDetailsクラスのインスタンスを生成しています。

ExtensionsBlockクラスのregisterPages()メソッドの実装

protected void registerPages(DetailsPart detailsPart) {
    detailsPart.setPageLimit(10);
    // register static page for the extensions
    detailsPart.registerPage(IPluginExtension.class, 
            new ExtensionDetails(fSection));
    // Register a static page for the extension elements that contain 
    // only body text (no child elements or attributes)
    // (e.g. schema simple type)
    fBodyTextDetails = new ExtensionElementBodyTextDetails(fSection);
    detailsPart.registerPage(ExtensionElementBodyTextDetails.class,
            fBodyTextDetails);
    // register a dynamic provider for elements
    detailsPart.setPageProvider(this);
}

ExtensionsDetailsクラスの実装を見てみると,名前のとおりDetails(詳細)の実装を行っています。以上のことから,registerPages()メソッドでDetails(詳細)を実装したクラスのインスタンスをdetailsPartに登録すればよいということがわかります。ここでMasterDetailsBlockクラスのregisterPages()メソッドのAPIリファレンスを見てみましょう。それによると,このメソッドはモデルとDetails(詳細)を一対一でマッピングを実装するものであると記述されています。さらにregisterPages()メソッドの引数であるDetailsPartクラスのregisterPage()メソッドを調べると第二引数はIDetailsPageインタフェースを実装すればよいことがわかります。

以上の点を踏まえて,FieldsBlockクラスのregisterPages()メソッドを実装してみましょう。

FieldsBlockクラスのregisterPages()メソッドの実装

protected void registerPages(DetailsPart detailsPart) {
    IDetailsPage detailsPage = new IDetailsPage() {
        private IManagedForm fForm;
        
        private Text fNameText;
        private Text fDescriptionText;
        private Button fRequiredYesButton;
        private Button fRequiredNoButton;
        private Text fMessageText;

        public void createContents(Composite parent) {
            GridLayout layout = new GridLayout(1, false);
            layout.marginHeight = 0;
            layout.marginWidth = 0;
            parent.setLayout(layout);

            FormToolkit toolkit = fForm.getToolkit();

            Section section = toolkit.createSection(parent, Section.TITLE_BAR);
            section.setText("フィールド詳細");

            GridData layoutData = new GridData();
            layoutData.grabExcessHorizontalSpace = true;
            layoutData.horizontalAlignment = GridData.FILL;
            section.setLayoutData(layoutData);
            
            Composite composite = toolkit.createComposite(section);
            composite.setLayout(new GridLayout(2, false));

            layoutData = new GridData();
            layoutData.grabExcessHorizontalSpace = true;
            layoutData.horizontalAlignment = GridData.FILL;
            composite.setLayoutData(layoutData);
            
            toolkit.createLabel(composite, "フィールド名");
            fNameText = toolkit.createText(composite, "");
            layoutData.grabExcessHorizontalSpace = true;
            layoutData.horizontalAlignment = GridData.FILL;
            fNameText.setLayoutData(layoutData);

            toolkit.createLabel(composite, "概要");
            fDescriptionText = toolkit.createText(composite, "");
            layoutData.grabExcessHorizontalSpace = true;
            layoutData.horizontalAlignment = GridData.FILL;
            fDescriptionText.setLayoutData(layoutData);

            toolkit.createLabel(composite, "必須");
            Composite requiredComposite = toolkit.createComposite(composite);
            requiredComposite.setLayout(new RowLayout(SWT.HORIZONTAL));
            fRequiredYesButton = toolkit.createButton(requiredComposite, "はい", SWT.RADIO);
            fRequiredNoButton = toolkit.createButton(requiredComposite, "いいえ", SWT.RADIO);

            toolkit.createLabel(composite, "メッセージ");
            fMessageText = toolkit.createText(composite, "");
            layoutData.grabExcessHorizontalSpace = true;
            layoutData.horizontalAlignment = GridData.FILL;
            fMessageText.setLayoutData(layoutData);

            section.setClient(composite);
        }
        ...
        public void initialize(IManagedForm form) {
            fForm = form;
        }
        ...
    };
    detailsPart.registerPage(Field.class, detailsPage);
}

IDetailsPageインタフェースの実装には,無名クラスを使用します。このインタフェースにはメソッドがいくつか定義されていますが,今のところ実装するべきメソッドはcreateContents()メソッドメソッドとinitialize()メソッドのふたつです。 createContents()メソッドではウィジェットの生成と配置を行います。initialize()メソッドでは引数の IManagedFormオブジェクトを無名クラスのプロパティーとして保持します。

これで入力項目定義フォームのウィジェットの生成と配置の実装は完成です。しかし,実際にフィールドの詳細を表示するには以下の実装を行う必要があります。

  1. テーブルで選択されたFieldオブジェクトを取得する
  2. 取得したFieldオブジェクトをDetails(詳細)に通知する
  3. 通知されたFieldオブジェクトの情報をDetails(詳細)に表示する

これらを順番に実装していきます。

著者プロフィール

松藤秀治(まつふじひではる)

Piece Frameworkのプログラマー。担当はEclipseのプラグインとして開発されているPiece Frameworkの統合開発環境Piece_IDE。2007年5月に株式会社アイテマンを設立。

コメント

コメントの記入