ページ

2009年12月11日金曜日

NSTableView にカスタムセルを表示する (11) ボタンをつける〜NSCellのマウスイベントの扱い

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

※タイトルが実体とそぐわなくなったので変えました(「カスタムビュー」⇒「カスタムセル」)。

(前回)Cocoaの日々: NSTableView にカスタムビューを表示する (10) カスタムセル+CoreData のメモリ利用状況

今度はカスタムセルの中にボタンを作ることにする。

アプローチ

画像や文字は表示するだけなので描画するだけなのだが、ボタンの場合はマウスイベントを処理する必要がある。カスタムセルの中の場合、単純に NSButton(や NSButtonCell)を貼付けるといった方法がとれない為、少しやっかいだ。試していないのであるいはそっちの方が楽かもしれないが、ボタンの挙動をカスタマイズしたいので自前で作ることにする。ボタンの挙動は Cocoaのそれではなく、Webアプリのボタンのそれに近いものにする。

次のような3つの状態を持たせる。

 (1)通常状態
 (2)マウスオーバ(目立たせる)
 (3)マウスクリック(押された感じ)


NSTableView 内のセルでマウスイベントを扱う

この場合、セル上のマウスイベントを拾う必要がある。どうするか。
NSCell のリファレンスを眺めているとマウスイベントを扱うメソッドがあった。

Mac Dev Center: NSCell Class Reference

引用すると:


Tracking the Mouse


挙動をみてみることにする。前回までのプログラムのカスタムセルでいくつかメソッドをオーバーライドしてみる。

CustomCell.m

- (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView
{
 NSLog(@"startTrackingAt:%@ inView:%@",
 NSStringFromPoint(startPoint), controlView);
 return YES;
}

- (BOOL)continueTracking:(NSPoint)lastPoint at:(NSPoint)currentPoint inView:(NSView *)controlView
{
 NSLog(@"continueTracking:%@ at:%@ inView:%@",
 NSStringFromPoint(lastPoint), NSStringFromPoint(currentPoint), controlView);
 return YES;
}
- (void)stopTracking:(NSPoint)lastPoint at:(NSPoint)stopPoint inView:(NSView *)controlView mouseIsUp:(BOOL)flag
{
 NSLog(@"sopTracking:%@lastPoint at:%@ inView:%@ mouseIsUp:%d",
 NSStringFromPoint(lastPoint), NSStringFromPoint(stopPoint),
 controlView, flag);
}


実行する。

セルの上をクリックし、マウスを少し動かした後離す。
結果のログはこんな感じ。

startTrackingAt:{240, 278} inView:
continueTracking:{240, 278} at:{239, 278} inView:
continueTracking:{239, 278} at:{238, 278} inView:
continueTracking:{238, 278} at:{237, 278} inView:
continueTracking:{237, 278} at:{236, 278} inView:
sopTracking:{236, 278}lastPoint at:{236, 278} inView: mouseIsUp:1



最初に startTrackingAt:inView: が呼び出され、続いてマウスを押している間 continueTracking:at:inView: が呼ばれ続ける。マウスボタンを離すと最後に stopTracking:at:inView:mouseIsUp: が呼ばれる。なおstart..とcontinue..の戻り値で YES を返さないとそれに続くメソッドは呼び出されない。

これを使えば、マウスの「押し」と「離し」はハンドリングできそうだ。
ただマウスオーバーは無理そうだ。こればっかりは NSTableView(のサブクラス)でハンドリングするしかないのか。さてどうしたものか。


(続く)