NSTableColumn は NSTableView や NSOutlineView で使われる、テーブルの列のセルを決定するためのクラスだ。ここでは、こいつを使って NSTableView にポップアップメニューを埋め込んでみよう。
ただし、全部のセルに埋め込むわけではない。普通のセルと、ポップアップメニューのセルを混在させるんだ。値を自由に設定したいセルには普通のセルを、すでに設定されている値の組から選びたいときはポップアップメニューのセルを使おう。具体的には、下の図みたいなイメージだ。'Normal Cell' は普通のセル。'Boolean value' のところは YES か NO かが選べる。'Type menu' のところは、クラスの名前のメニューから 1 つを選ぶんだ。

で、こいつを実現するには、NSTableColumn のサブクラスを作ってやる必要があるんだ。サブクラスで dataCellForRow: をオーバーライドしてやる。
Application Kit/NSTableColumn.h
- (id)dataCellForRow:(int)row;
これはセルを作るためのメソッド。指定した行のセルを作るんだ。この中で、必要に応じて普通のセルや、ポップアップボタンのセルを作ってやればいい。
では、次の問題。どうやってポップアップのセルを指定してやるか?これはアプリケーションによって最適な方法が異なると思う。このサンプルでは次のようにする。テーブルのデータソースで、次のような感じのデータを用意してやるんだ。
value.plist (sample)
{
"name" = "Boolean value";
"item" = {
"value" = 0;
"itemNames" = (
"YES", "NO"
);
"itemValues" = (
1, 0
);
};
}
このデータは plist 形式で、NSDictionary を表している。最初のレベルでは、'name' と 'item' っていうキーがある。'name' は、テーブルの 'name' 列に入れる文字列を表す。'item' は、ポップアップのためのデータだ。
'item' には、'value'、'itemNames'、'itemValues' の 3 つのキーがある。'itemNames' はポップアップに表示される文字列、'itemValues' はそれに対応する値、'value' は現在の値(つまりメニューで選択される値)だ。このデータでポップアップのデータを指定してやろう。
ちなみに、普通のセルを指定するときは、次のようなデータを使う。'item' がなくて 'value' があるんだ。
value.plist (sample)
{
"name" = "Normal cell";
"value" = 16;
}
これで、データの準備はできた。じゃ、次の問題。このデータをどうやって NSTableColumn に渡すか?NSOutlineView の場合は比較的簡単だ。outlineView:child:ofItem: で、上に示したデータを返してやればいい。NSTableColumn からは dataAtRow: で取り出せる。これは、NSOutlineView だと、表示する値と、データソースが返すオブジェクトが直接一致しないからできるんだ。(outlineView:child:ofItem: で得た item から、outlineView:objectValueForTableColumn:byItem: で表示する値に変える)。
NSTableView の場合はちょっと面倒。なぜなら、NSTableView のデータソースは、テーブルで表示する値を直接返してしまうから。そこで、データソースにメソッドを 1 つ追加することにした。ポップアップ用の NSTableColumn で使うデータを取得するための、tableView:itemForTableColumn:row: だ。
PopupTableColumn.h (sample)
@interface NSObject (NSTableDataSourceForPopupTableColumn)
- (id)tableView:(NSTableView*)tableView
itemForTableColumn:(NSTableColumn*)tableColumn
row:(int)row;
@end
これを NSTableView のデータソースで実装してやる。これでどうにかできるよ。じゃ、サンプルを。
PopupTableColumn.m (sample)
- (id)dataCellForRow:(int)row
{
id tableView;
id dataSource;
id item;
id itemNames;
id cell;
// row のアイテムを取得
tableView = [self tableView];
dataSource = [tableView dataSource];
if ([tableView isMemberOfClass:[NSTableView class]]) {
item = [dataSource tableView:tableView
itemForTableColumn:self
row:row];
}
else if ([tableView isMemberOfClass:[NSOutlineView class]]) {
item = [[tableView itemAtRow:row] objectForKey:@"item"];
}
// アイテムの名前を取得
if ([item respondsToSelector:@selector(objectForKey:)] &&
(itemNames = [item objectForKey:PopupTableColumeItemNamesKey]))
{
// ポップアップボタンを作る
cell = [[[NSPopUpButtonCell alloc]
initTextCell:@"" pullsDown:NO] autorelease];
[cell setBordered:NO];
[cell setFont:[[self dataCell] font]];
// タイトルを加える
[cell addItemsWithTitles:itemNames];
}
else {
// 親クラスを呼び出す
cell = [super dataCellForRow:row];
}
return cell;
}
まず、ポップアップ用の item を取得する。NSTableView と NSOutlineView で処理が異なるので注意。とれたらポップアップ用のセルを作る。NSPopUpButtonCell のインスタンスを作るんだ。setBordered: で NULL をセットしてやるのがコツ。そして、'itemNames' をタイトルとして設定してやるんだ。これでできあがり。
サンプルソースコードは、NSTableView 用と NSOutlineView 用の 2 つを用意したぜ。
■サンプルダウンロード:
PopupTableColumn.tar.gz
PopupTableColumnOutline.tar.gz