(前回)Cocoaの日々: Application List (2) ファイルパスからアプリ名に変換して表示 - LSCopyDisplayNameForURL
前回はアプリ名を表示した。今回はアイコンを表示してみよう。
まずアイコン画像の用意から。ファイルのアイコン画像は -[NSWorkspace iconForFile:] で取得できる。
NSWorkspace Class Reference - iconForFile:
パスから決めることができるので前回同様 -[ApplicationEntry initWithPath:] 内に仕込む。
ApplicationEntry.m
-(id)initWithPath:(NSString*)aPath
{
self = [super init];
if (self != nil) {
self.path = aPath;
:
:
self.icon = [[NSWorkspace sharedWorkspace] iconForFile:path];
[icon setSize:NSMakeSize(16, 16)];
}
return self;
}
取得後に表示用のサイズ(16x16)を設定しておく。
次にこの画像を表示する実装。
NSTableView で画像を表示するには NSImageCell を使うのが簡単だが、これでは同じセル内でアプリ名が表示できない。カスタムセルを作って自前で描画する必要がある。この辺り iPhone では標準のセルで簡単にできるので AppKit の方にも用意して欲しい。
自前描画は以前扱ったことがある。
Cocoaの日々: NSTableView にカスタムビューを表示する (6)カスタムセルにモデルオブジェクトの内容を描画する
関連:
Cocoaの日々: NSTableView にカスタムビューを表示する (5)カスタムセルへ bindings経由でモデルオブジェクトを渡す
描画方法について改めてまとめてみる。
1. NSCell のサブクラスを作る(カスタムセルと呼ぶことにする)
2. 表示したい NSTableColumn にカスタムセルのインスタンスを設定する。
3. NSTableColumn の Value に モデルを bindする
4. カスタムセルに2つのメソッドを実装する
-(void) drawInteriorWithFrame:inView:
-(id)copyWithZone:
詳しく見ていこう。
1. NSCell のサブクラスを作る。
ApplicationCell という名のクラスを作る。
@interface ApplicationCell : NSCell {
}
@end
2. 表示したい NSTableColumn にカスタムセルのインスタンスを設定する。
今回は AppListAppDelegate に NSTableColumn へのアウトレットを用意し、アプリ起動時に -[NSTableColumn setDataCell:] で設定してやる。
今回は AppListAppDelegate に NSTableColumn へのアウトレットを用意し、アプリ起動時に -[NSTableColumn setDataCell:] で設定してやる。
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
:
[tableColumn_ setDataCell:
[[[ApplicationCell alloc] init] autorelease]];
}
3. NSTableColumn の Value に モデルを bindする
今回は ArrayController を介してモデルとつながっている。
AppListAppDelegate.appList ← Array Controller ← NSTableColumn
Interface Builder で NSTableColumn の Bindings設定を開き、Bind to を Array Controller へ、Key は arrangedObjects、Model Key Path を空にしておく。
Model Key Path を空にしておくのがポイントで、これによって ArrayController が扱う ApplicationEntry のインスタンスを直接セルへ渡せる。
4. カスタムセルに2つのメソッドを実装する
ApplicationCell.m
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
ApplicationEntry* entry = [self objectValue];
[controlView lockFocus];
NSPoint p1 = cellFrame.origin;
p1.x += 0;
p1.y += 0 + [entry.icon size].height;
[entry.icon compositeToPoint:p1 operation:NSCompositeSourceOver];
NSPoint p2 = cellFrame.origin;
p2.x += 20;
p2.y += 0;
NSDictionary* attrs = [NSDictionary dictionary];
[entry.name drawAtPoint:p2 withAttributes:attrs];
[controlView unlockFocus];
}
- (id)copyWithZone:(NSZone *)zone
{
ApplicationCell* cell = (ApplicationCell*)[super copyWithZone:zone];
return cell;
}
-[NSCell objectValue] でArrayController から渡される ApplicationEntry のインスタンスを取得することができる。
copyWithZone: は必須。これが実装さていないと実行時にエラーとなる(NSTableColumn が使う)。
これで、できあがり。
動かしてみよう。
出た。いい感じだ。
ソースコードは GitHub からどうぞ
AppList at 2010-04-15c from xcatsan's SampleCode - GitHub
(参考)セルに画像とテキストを描く情報はHMDT でも紹介されている。参考まで。
この中の「セルに画像とテキストを描く」の箇所。カスタムセルを用意して drawInteriorWithFrame:inView: をオーバーライドすれば良い。
----
次はドラッグ&ドロップによる並び替え。