ページ

2009年12月3日木曜日

Cocoaの日々: NSTableView にカスタムビューを表示する (8) NSCollectionView で選択状態を描画する

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

(前回)Cocoaの日々: NSTableView にカスタムビューを表示する (7) NSCollectionView

前回に続き NSCollectionView が NSTableView の代わりに使えないかを検証する。


アイテムの選択

NSCollectionView には Selectable というプロパティがあるが、これにチェックを入れても実際の動作では選択できない(アイテムを押しても何も起こらない)。


NSTableView のように選択をしたい。調べてみると他の人がこの問題に取り組んでいた。

NSCollectionViewを選択可能にする - The Invisible Designer
CocoaDev: NSCollectionView

これらを参考に選択できるようにしてみよう。


コーディング
※以下、MacOSX10.5(ppc)/Xcode3.1で作成

NSCollectionViewItem と アイテムを表示する NSView のサブクラスを作成する。





中身はこんな感じ。

CollectionViewItem.h
@interface CollectionViewItem : NSCollectionViewItem {

}

@end

CollectionViewItem.m
@implementation CollectionViewItem

- (void)setSelected:(BOOL)flag
{
ItemView* itemView = (ItemView*)[self view];
itemView.selected = flag;
[itemView setNeedsDisplay:YES];
[super setSelected:flag];
}

@end

ItemView.h
@interface ItemView : NSView {

BOOL selected;
}

@property BOOL selected;

@end


ItemView.m
@implementation ItemView

@synthesize selected;

- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
    }
    return self;
}

- (void)drawRect:(NSRect)rect {

if (self.selected) {
[[NSColor lightGrayColor] set];
} else {
[[NSColor whiteColor] set];
}
NSRectFill(rect);
[super drawRect:rect];
}

@end


ファイルを作成したら InterfaceBuilder で上記クラスに切り替える。

また NSCollectionView の selectable プロパティにチェックを入れておく。



実行してみよう。


選択状態(背景が灰色)にすることができた。

Allows Multiple Selection にチェックを入れておくと複数選択もできる(範囲指定もしくは Shift+クリック)。




なお -[setSelected:] 内で親のメソッドを呼ばないと flag=NO のケースが呼び出されない。

- (void)setSelected:(BOOL)flag
{
         :
[super setSelected:flag];
}


ソースコード

githubからどうぞ
CustomCell at 20091203-2 from xcatsan's SampleCode - GitHub


参考

Mac Dev Center: NSCollectionView Class Reference

Mac Dev Center: NSCollectionViewItem Class Reference


- - - - - -
ここまでで機能的には NSTableView の代わりになりそうなことがわかった。もちろん用途によるが制作している BlogAssistant では十分そうだ。ただ気になるのはアイテムが大量にある場合。メモリを食い尽くす、なんてことになるのだろうか。