NSTableView でテキストの上から行を選択可能にする

Cocoa プログラミング

View ベースの NSTableView で、View の上に NSTextField を置いてそこのテキストを選択できるようにしてみたところ、NSTextField 上をクリックしても行が選択されなくなりました。

そこでテキストの選択もできつつ行の選択もできるようにしてみます。


View ベースの NSTableView を使ってみたのですけど、View の上に NSTextField を配置して、そこに表示されているテキストを選択できるようにしたくなりました。

ただ、そのように作ってみたところ、その NSTextField 上をクリックした時にテーブルが選択されてくれず、テキスト以外の部分をクリックしないといけなくなってしまいました。

行の上ならどこでもクリックして行を選択できるようにしたいので、その実現方法を考えてみることにします。

表示中のテキストを選択可能にするには

NSTextField で表示中のテキストをドラッグアンドドロップで選択できるようにするには、それが持つ selectableプロパティtrue に設定する必要があります。

ただ、この設定を true にしている時は、NSTextField 上をクリックしてもそれが置かれている NSTableView の行は選択されない様子なので、たとえば今回においては単純に Interface Builder で選択可能にしておく訳には行かなそうです。

行選択時にテキストを選択可能にしてみる

そこで、行が選択されるまでは selectablefalse に設定しておいて、行が選択された時にだけそれを true に設定することにしてみます。

この時、選択解除されたものは selectablefalse にしないと、再びそのセルを選択しようとした時に NSTextField 上を選択できなくなるので注意します。

extension ViewController : NSTableViewDelegate {
	
	func tableViewSelectionDidChange(notification: NSNotification) {
		
		let tableView = notification.object as! NSTableView
		let selectedIndexes = tableView.selectedRowIndexes
		
		for row in 0 ..< tableView.numberOfRows {
		
			if let cell = tableView.viewAtColumn(0, row: row, makeIfNecessary: false) as? NSTableCellView {
				
				cell.textField!.selectable = selectedIndexes.containsIndex(row)
			}
		}
	}
}

View ベースの NSTableView で行が選択されると、NSTableViewDelegatetableViewSelectionDidChange: が呼び出されるので、その中で、存在する全ての行 (cell) 上の NSTextFieldselectable を調整しています。

この時、選択済みの行であれば true を設定してテキスト選択可能にして、未選択の行については false を設定してテキストを選択できないようにしています。

動き的には大丈夫そう

このようにすることで、未選択の状態から NSTextField 上のテキストをクリックして行を選択できるようになりました。その上で改めて表示されているテキスト上をドラッグアンドドロップすると、そこのテキストを選択できるようになりました。

動き的にはこれで期待通りになっているように思えますけど、頑張って作った感も否めないので、もしもっと適切な方法をご存知でしたら、ぜひツイートなどで教えてください。