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

第9回 画面の作成(4)

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

前回はMaster(一覧)で選択したフィールドをDetails(詳細)で表示できるようにしました。今回は最初にパッケージとクラスの構造を整理します。そのあとで,各ボタンが動作するようにし,Details(詳細)で変更された内容が反映されるようにします。

パッケージ・クラスの構造の整理

今までは「とりあえず実装して動作させる」ことに重点を置いてきたので,FieldsPageクラスにすべて詰め込んだかなり見にくいソースコードになっています。そこで新しい機能を実装する前に,パッケージとクラスの構造を整理することにします。

パッケージの分割

まず,パッケージの構成を見直すことにします。現在は,com.piece_framework.piece_ide.form_designerにすべてのクラスが配置されています。これらのパッケージ構成を以下のように変更します(パッケージ名にはプリフィックスとしてcom.piece_framework.piece_ide.form_designerを付けます)。

パッケージ名説明所属するファイル
pluginプラグイン全体で使用するクラスを配置するActivator.java
modelモデルクラスを配置するField.java
uiユーザーインタフェースに関係するクラスを配置するFormDesignerEditor.java, FieldsPage.java

変更後のパッケージ構成

変更後のパッケージ構成

インターナルパッケージ

Eclipseのプラグイン開発では慣習として外部に公開しないパッケージはパッケージ名にinternalを付けることになっています。例えば,今まで参考にしてきたManifestEditorクラスが属するパッケージ名は org.eclipse.pde.internal.ui.editor.pluginとなっており,外部に公開しないものであることが分かります。

本来,外部からは利用しないことを想定しているインターナルパッケージですが,中にはそれを利用した方が実装が容易になる場合もあります。その反面,インターナルパッケージの開発者は公開することを意図していないため,そのAPIを変更してしまうかもしれないということも考えられます。こういったメリット・デメリットを考慮した上で各自がインターナルパッケージの利用を検討すれば良いのですが,開発者の意図やバージョンアップ時の互換性を考慮すると,私は可能な限り公開されているパッケージを利用することを考えるべきではないかと思います。インターナルパッケージは,どうしてもほかに方法がない場合の最後の「砦」と考えるのが適当なのではないでしょうか。

Master(一覧)のクラス化

現在のフォームデザイナーのソースコードの中で一番複雑なのは,なんといってもFieldsPageクラスでしょう。そこで,まずMaster(一覧)の部分を別クラスに抽出することにします。

マニフェストエディターの「拡張」ページではMaster(一覧)をSectionPartクラスを継承したクラスで実装しているので,同じように継承したFieldsMasterSectionPartクラスを作成します。Compositeオブジェクトと ManagedFormオブジェクトを引数として受け取るコンストラクターを作成し,その中で初期化とウィジェットの生成・配置を行います。

FieldsMasterSectionPartクラスでウィジェットの生成・配置を行うcreateContents()メソッドはFieldsBlockクラスのcreateMasterPart()メソッドをほぼそのまま移動します。この移動に伴い,サンプルデータを生成するcreateSample()メソッドもFieldsMasterSectionPartクラスに移動します。

FieldsMasterSectionPartクラス

public class FieldsMasterSectionPart extends SectionPart {
    public FieldsMasterSectionPart(Composite parent, IManagedForm managedForm) {
        super(parent, 
              managedForm.getToolkit(), 
              Section.TITLE_BAR | Section.DESCRIPTION);
        initialize(managedForm);
        createContents(getSection(), managedForm.getToolkit());
    }

    private void createContents(Section section, FormToolkit toolkit) {
        section.setText("フィールド一覧");
        section.setDescription("編集するフィールドを選択してください。");

        Composite composite = toolkit.createComposite(section);
        composite.setLayout(new GridLayout(2, false));
       
        Table table = toolkit.createTable(
                        composite, 
                        SWT.SINGLE | SWT.FULL_SELECTION);
        table.setHeaderVisible(true);
        table.setLinesVisible(true);

        GridData layoutData = new GridData();
        layoutData.horizontalAlignment = GridData.FILL;
        layoutData.verticalAlignment = GridData.FILL;
        layoutData.grabExcessHorizontalSpace = true;
        layoutData.grabExcessVerticalSpace = true;
        table.setLayoutData(layoutData);
       
        TableColumn column1 = new TableColumn(table, SWT.NULL);
        column1.setText("フィールド名");
        column1.setWidth(100);

        TableColumn column2 = new TableColumn(table, SWT.NULL);
        column2.setText("説明");
        column2.setWidth(100);

        TableViewer viewer = new TableViewer(table);
        viewer.setContentProvider(new ArrayContentProvider());
        viewer.setLabelProvider(new ITableLabelProvider() {

            public Image getColumnImage(Object element, int columnIndex) {
                return null;
            }

            public String getColumnText(Object element, int columnIndex) {
                if (element == null) {
                    return "";
                }
                if (!(element instanceof Field)) {
                    return "";
                }
                
                Field field = (Field) element;
                if (columnIndex == 0) {
                    return field.getName();
                } else if (columnIndex == 1) {
                    return field.getDescription();
                }
                return "";
            }

            public void addListener(ILabelProviderListener listener) {
            }

            public void dispose() {
            }

            public boolean isLabelProperty(Object element, String property) {
                return false;
            }

            public void removeListener(ILabelProviderListener listener) {
            }
        });
        final SectionPart part = new SectionPart(section);
        viewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                FieldsMasterSectionPart.this.getManagedForm().fireSelectionChanged(
                                part,  
                                event.getSelection());
            }
        });

        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());
    }

    private List createSample() {
        List fields = new ArrayList();
        
        Field field1 = new Field("name");
        field1.setDescription("名前");
        field1.setRequired(true);
        field1.setMessage("名前は必須です。");
        
        fields.add(field1);

        Field field2 = new Field("phone");
        field2.setDescription("電話番号");
        field2.setRequired(true);
        field2.setMessage("電話番号は必須です。");
        
        fields.add(field2);
        
        Field field3 = new Field("address");
        field3.setDescription("住所");
        field3.setRequired(false);
        
        fields.add(field3);
        
        return fields;
    }
}

FieldsBlockクラス

private class FieldsBlock extends MasterDetailsBlock {
    @Override
    protected void createMasterPart(
                    final IManagedForm managedForm,
                    final Composite parent) {
        new FieldsMasterSectionPart(parent, managedForm);
    }

    @Override
    protected void createToolBarActions(IManagedForm managedForm) {
    }

    @Override
    protected void registerPages(DetailsPart detailsPart) {
        ...
    }
}

ここまで実装できたら,実行して動作に影響がないことを確認します。

著者プロフィール

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

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

コメント

コメントの記入