スクリプトで Table Column を追加する

スクリプトを使ってテーブルにコラムを追加する方法を試したので、ちょっとメモ。

NSTableColumn オブジェクトを作るときには、Header Cell と Data Cell を指定して作ることができる。

まずは、NSTableColumninitWithIdentifier(identifier) というメソッドで、NSTableColumn のオブジェクトを作る。ここでは、Identifier に test という名前を付けてみた。

column = NSTableColumn.alloc.initWithIdentifier("test")

ここで作った、コラムに対して設定をするんだけど、とりあえずは幅の設定と編集の不許可だけにしておく。

column.setWidth(120)

column.setEditable(false)

これで、コラムの設定はできたんだけど、ヘッダーのところにタイトルなんかを表示させたい。まあ、そのタイトルも Test としておく。

テーブルのヘッダーには、NSTableColumnsetHeaderCell(cell) というメソッドを使う。それで、そこに入れる NSCell のオブジェクトを作るんだけど、テーブルのヘッダーに入れる NSTableHeaderCell というクラスがあるので、そのオブジェクトを作る。NSCell のクラスのメッソッドを継承しているので、initTextCell(string) で作る。

headerCell = NSTableHeaderCell.alloc.initTextCell("Test")

そしたら、setHeaderCell(cell) で上で作ったコラムに追加する。

column.setHeaderCell(headerCell)

次に、データを表示するセルを作る。文字や数値を表示するには、NSTextFieldCell を使う。

textCell = NSTextFieldCell.alloc.init

これを右揃えにしてみる。setAlignment(alignment) というメソッドを使う。

textCell.setAlignment(NSRightTextAlignment)

文字列を表示するにはこれでいいけど、数字を表示させるときに、少数が含まれる場合、float だと、小数点以下が表示できるだけされるので、フォーマットを決めておく。ここでは、正の少数だけを扱うということで進める。数値のフォーマットを指定するには NSNumberFormatter というクラスを使う。

formatter = NSNumberFormatter.alloc.init

これで、setPositiveFormat(format) というメソッドで正の少数のフォーマットを決める。負の場合だけのときは、setNegativeFormat(format) を使う。setFormat(format) を使うと、正と負の場合を同時に指定できる(ゼロのときも?)。その際は、セミコロンで区切る。

ここでは、小数点以下2桁の表示にしたいので、0.00 と指定する。

formatter.setPositiveFormat("0.00")

準備ができたら、NSCellsetFormatter(formatter) というメソッドで、つくった NSNumberFormatter オブジェクトを設定する。

textCell.setFormatter(formatter)

そして、この NSTextFieldCell を setDataCell(cell) というメソッドを使って、NSTableColumn オブジェクトに追加する。

column.setDataCell(textCell)

最後にこの NSTableColumn のオブジェクトを NSTableView に追加する。

@table.addTableColumn(column)

ちょっとおまけで、NSTableView の表示に NSArrayController を使っていて、Array Controller にバインドしたい場合の方法。NSObject の bind_toObject_withKeyPath_options(bind,object,keyPath,options) というメソッドを使う。bind は、Array Controller の値を入れたいので、"value" にする。これは、小文字で始めないとエラーがでる。object は Array Controller にバインドするので、@aryCtl に、keyPath は、表示したい値の key を arrangedObjects につける。ここでは key は test にしておくので、arrangedObjects.test になる。さいごに、options はいろいろ指定できるみたいなんだけど(ValueTransformer など)まだよくわかっていないので、とりあえず、nil にしておく。

column.bind_toObject_withKeyPath_options("value",@aryCtl,"arrangedObjects.test",nil)

あと、ヘッダーをクリックしたときの並べ替えの指定もできる。それには、setSortDescriptorPrototype(sortDescriptor) を使う。ここでは、NSSortDescriptorsortDescriptorWithKey_ascending_selector(key,true/false,selector) を使って selectorcaseInsensitiveCompare を指定してみる。これは大文字小文字を無視した並べ替え。

column.setSortDescriptorPrototype(NSSortDescriptor.sortDescriptorWithKey_ascending_selector('test',true,"caseInsensitiveCompare:"))

ここまでのをまとめると、こんな感じ。

column = NSTableColumn.alloc.initWithIdentifier('test')

column.setWidth(120)

column.setEditable(false)

column.bind_toObject_withKeyPath_options("value",@aryCtl,"arrangedObjects.test",nil)

headerCell = NSTableHeaderCell.alloc.initTextCell('Test')

column.setHeaderCell(headerCell)

textCell = NSTextFieldCell.alloc.init

textCell.setAlignment(NSRightTextAlignment)

formatter = NSNumberFormatter.alloc.init

formatter.setPositiveFormat("0.00")

textCell.setFormatter(formatter)

column.setDataCell(textCell)

column.setSortDescriptorPrototype(NSSortDescriptor.sortDescriptorWithKey_ascending_selector('test',true,"caseInsensitiveCompare:"))

@table.addTableColumn(column)

これで、@table という Table View に test という identifier を持ったコラムが追加される。

削除もしてみる

で、追加したはいいが、削除もしたい。その場合は、NSTableView の removeTableColumn(column) というメソッドを使う。この column には、削除したい NSTableColumn オブジェクトを指定するんだけど、NSTableView の tableColumns というメソッドでコラムの配列を取り出して何らかの処理をするか、tableColumnWithIdentifier(identifier) というメソッドで、identifier を指定してコラムを得る(指定した identifier を持った最初のコラム)。

例えば、上の test という identifier を持ったコラムを消す場合は次のようにする。

@table.removeTableColumn(@table.tableColumnWithIdentifier('test'))

全部のコラムを消したい場合、全部削除、というメソッドがないようなので、ブロックにして地道に消してみる。

@table.tableColumns.each do |col|

@table.removeTableColumn(col)

end

他に、コラムの一番最初と最後は消さないで、その間のだけを消したければ、こんな風にしたらできる(もっといい方法はあるかも)。

while @table.tableColumns.length > 2

@table.removeTableColumn(@table.TableColumns[1])

end

コラムを追加するときに identifier をインスタンス変数としてどこかに記憶させておくとか、連番でつけておくとかすると、消すときも楽。例えば、col1、col2 という感じで identifier をつけていった場合、消すときはこんな感じで行けるはず。

i = 1

while @table.tableColumnWithIdentifier("col#{i}")

@table.removeTableColumn(@table.tableColumnWithIdentifier("col#{i}"))

i += 1

end

これなら、残しておきたいコラムは別で名前を付けておけば間違って消してしまうこともない。