minimize

TableViewerColumn は、Eclipse 3.3で導入されたテーブル関連クラスです。

従来の TableViewer を使った流れでは、

  1. viewer.setContentProvider でモデル→ビューアへの変換(テーブル単位)

  2. TableColumn でテーブルヘッダを生成(列単位)

  3. viewer.setLabelProvider でテーブルセルの表示方法を定義(テーブル単位)

  4. viewer.setCellModifier でテーブルセルの編集方法を定義(テーブル単位)

  5. viewer.setCellEditors でテーブルセルのエディタを定義(列単位)

こんな感じでした。TableViewerColumnを使うと、

  1. viewer.setContentProvider でモデル→ビューアへの変換(テーブル単位)

  2. TableViewerColumn でテーブルヘッダおよび列定義を生成(列単位)

  3. viewerColumn.setLabelProvider でテーブルセルの表示方法を定義(列単位)

  4. viewerColumn.setEditingSupport でテーブルセルの編集方法およびエディタを定義(列単位)

のようになります。
ContentProvider を除いて全てが列単位になりました。
ある列のテーブルヘッダ、セル表示方法、セル編集方法は全て
TableViewerColumn という一つのクラスに統一されて管理されます。

使い方

まずは TableViewer を作成します。
そして従来通り ContentProvider を設定します。

TableViewer viewer = new TableViewer(table);
viewer.setContentProvider(new ArrayContentProvider());

テーブルビューアでは通常この ArrayContentProvider で事足りるはずです。
そしたら、列ごとに以下の作業を繰り返します。

TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.LEFT);
viewerColumn.setLabelProvider(new MyCellLabelProvider());
TableColumn tableColumn = viewerColumn.getColumn();
tableColumn.setText("name");
tableColumn.setWidth(100); // もしくは pack()
viewerColumn.setEditingSupport(new MyEditingSupport(viewer));

2行目の setLabelProvider は常に必要です。
テーブルヘッダを表示しない場合は3~5行目は不要です。
同様にセルを編集しない場合は6行目は不要です。

CellLabelProvider

setLabelProvider には、CellLabelProvider の実装クラスを設定します。
上の例で定義した MyCellLabelProvider を見てみましょう。

public class MyCellLabelProvider extends CellLabelProvider {
    public void update(ViewerCell cell) {
        TableObject tableObject = (TableObject)cell.getElement();
        cell.setText(tableObject.getName());
    }
}

実装するメソッドは一つです。
このメソッドは、セルの内容が変更された時および初期表示時にCallされます。
ViewerCell というのが、セルオブジェクトです。
cell.getElement() で、そのセルを含む行の行オブジェクトを返します。
行オブジェクトとは、テーブルの1行を表すオブジェクトのことです(造語)。
cell.setText() によって設定した文字列が、実際にセルとして表示されます。

従来の(テーブル単位の)LabelProvider では、

public String getColumnText(Object element, int columnIndex) {
    TableObject tableObject = (TableObject)element;
    switch (columnIndex) {
    case 0:
        return tableObject.getName();
    case 1:
        return tableObject.getAddress();
    case 2:
        return tableObject.getUrl();
    }
    throw new IllegalArgumentException("Invalid columnIndex : " + columnIndex);
}

このように、列番号が増えてくるとコードの複雑度が増加してしまいます。
TableViewerColumn を使うと列ごとに LabelProvider を定義できるので
コード量は増えるかもしれませんがシンプルになります。

EditingSupport

setEditingSupport には、EditingSupport の実装クラスを設定します。
いくつかのメソッドを実装する必要があるので一つずつ見ていきましょう。

canEdit

これは従来の CellModifier と同じです。
セルが編集可能かどうかを返します。
element には行オブジェクトが入っています。

protected boolean canEdit(Object element) {
    return true;
}

getCellEditor

セルエディタを返します。
同様に element には行オブジェクトが入っています。
editor はコンストラクタ内で予め作っておくのが良いでしょう。

protected CellEditor getCellEditor(Object element) {
    return editor;
}

getValue

エディタがアクティブになったときに呼ばれます。
ここで返した値が、エディタ内の初期表示文字列になります。

protected Object getValue(Object element) {
    TableObject tableObject = (TableObject)element;
    return tableObject.getName();
}

setValue

エディタで編集して確定(RETURNキー押下など)したときに呼ばれます。
value には確定した文字列が格納されているので、
通常はこれを行オブジェクトに反映させます。

protected void setValue(Object element, Object value) {
    TableObject tableObject = (TableObject)element;
    tableObject.setName(value.toString());
}
[コメント(0)]