ページ

2009年12月21日月曜日

NSTableView にカスタムセルを表示する (14) ボタンをつける〜ボタンの表示とイベント処理

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

(前回)Cocoaの日々: NSTableView にカスタムセルを表示する (13) ボタンをつける〜マウスイベントの結果をセルで使う

ようやくボタンの作成まできた。先に出来上がりのイメージを掲載しておく。

起動直後のウィンドウ


ボタンの上にマウスを載せる




ボタンを押す(分かりやすい様に目立つ色にしてある)




実装

前回からも色々手を入れたのでソースコードを見てもらうのが一番わかりやすいと思う。ここではポイントだけ解説する。

CustomCellControl.h

#import

enum CONTROL_STATE
{
CONTROL_STATE_OFF,
CONTROL_STATE_ON,
CONTROL_STATE_OVER
};
@interface CustomCellControl : NSObject {

NSRect frame;
NSString* title;

id target;
SEL action;
}
@property (retain) NSString* title;
@property (retain) id target;
@property (assign) SEL action;

- (id)initWithOrigin:(NSPoint)origin;
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView state:(NSInteger)buttonState;
- (BOOL)hitTestAtPoint:(NSPoint)testPoint inFrame:(NSRect)cellFrame;




カスタムセルに載せるコントロールクラスを定義した。ボタンクラスの親にあたりイベント処理など動作上必要な基本的な実装をここに書く。

CustomCellButton.h

@interface CustomCellButton : CustomCellControl {

}
- (id)initWithTitle:(NSString*)aTitle at:(NSPoint)aPoint;

@end


描画メソッドをオーバーライドしてボタンを描いている。


CustomCell.h

@interface CustomCell : NSCell {
 :


NSMutableArray* controls;
}



CustomCell にコントロール間利用の配列を追加した。

CustomTableView からイベントが渡ってきたら、イベント処理対象のコントロールを探し出してこれを取っておく。
CustomCell.m

-(void)handleMouseEntered:(NSEvent*)theEvent frame:(NSRect)cellFrame inView:(NSView*)controlView
{
self.handlingValue = [self objectValue];
self.handlingEvent = theEvent;
self.handlingControl = [self controlOnMouse:theEvent frame:cellFrame inView:controlView];
}


そして描画時にその情報を使ってボタンの表示を描き分ける。

- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
   :

NSInteger controlState;

for (CustomCellControl* cellControl in controls) {
if (handlingControl == cellControl) {
if (isMouseDown) {
controlState = CONTROL_STATE_ON;
} else {
controlState = CONTROL_STATE_OVER;
}
} else {
controlState = CONTROL_STATE_OFF;
}
[cellControl drawWithFrame:cellFrame
  inView:controlView
state:controlState];
}
}

見た目はたくさんあるボタンだが、インスタンスは1つだけなのでこうやって(ボタンの)外部から状態を渡して、描き分けさせる必要がある。


同様に CustomCellLabel, CustomCellImage を作り、描画はそれらにおこわなせるようにした。


ソースコード

GitHubからどうぞ。
CustomCellWithCoredata at 20091221b from xcatsan's SampleCode - GitHub


- - - - -
作っているうちに結局NSCell内に NSCellを作るような形となってしまい、一時はいっそのこと NSCellのコンテナを作ってしまった方が良い気もした。そうすれば Cocoaで提供されているすべてのコントロール(セル)が使える。ただ一方でオリジナルの実装は低機能だがしがらみが無い分好きにできる。低機能ではあるが自前のコントロールを作るのは結構楽しかった。

これでカスタムセルでどこまでできるのかが大体掴めた。汎用的に仕上げる誘惑は残るが、このままではいつまでたっても開発が進まないので後はアプリ(BlogAssistant)を作る過程で必要に応じて改良していくことにする。