Controllerと たわむれる6

前回のつづき

今回はIKImageBrowserViewです。


まず、IKImageBrowserViewを使うために必要なFrameworkを追加します。
Quartzフレームワークです。


つぎに、IKImageBrowserViewで使うためにモデルを変更します。
モデル担当はControllersAppDelegateですね。

ControllersAppDelegate.mの一部。

- (IBAction)openRandomFolder:(id)sender
{
    NSString *folder = [self randomFolder];
    
    ControllersWindowController *windowController = [windowControllers objectForKey:folder];
    if(windowController) {
        [windowController showWindow:self];
        return;
    }
    
    NSMutableArray *array = [NSMutableArray array];
    NSFileManager *fm = [NSFileManager defaultManager];
    NSWorkspace *ws = [NSWorkspace sharedWorkspace];
    NSArray *files = [fm contentsOfDirectoryAtPath:folder error:NULL];
    for(NSString *name in files) {
        NSString *path = [folder stringByAppendingPathComponent:name];
        NSString *filename = [fm displayNameAtPath:path];
        NSImage *icon = [[[NSImage alloc] initWithContentsOfFile:path] autorelease];
        if(!icon) {
            icon = [ws iconForFile:path];
        }
        NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
                              filename, @"filename",
                              icon, @"icon",
                              path, @"fullpath",    // 追加
                              nil];
        [array addObject:dict];
    }
    
    windowController = [[[ControllersWindowController alloc] init] autorelease];
    [windowControllers setObject:windowController forKey:folder];
    windowController.window.representedFilename = folder;
    windowController.contents = array;
    [windowController showWindow:self];
}

変更したのは追加一行。辞書にfullpathを持たせました。


では、IKImageBrowserViewを管理するNSViewControllerのサブクラスを作ります。
前回、ControllersListViewControllerを作った時と同じ要領で作ってください。
ヘッダはこんな感じにします。

ControllersIconViewController.h

#import <Cocoa/Cocoa.h>

@interface ControllersIconViewController : NSViewController
- (id)init;
@end

今回も-initをオーバーライドします。
実装は後回しにして、IBでの作業に移ります。


簡単にすませるために、TableView.xibを開きます。
開いたら「File」「Decompose Interface」です。
TableView.xibはもう不要ですので閉じます。
新しく出来たXibはいきなり保存しましょう。名前はIconView.xibです。プロジェクトに追加するのをお忘れなく。


まず、File's OwnerのクラスをControllersIconViewControllerに変更します。


NSScrollViewは削除して代わりに「Custom View」を追加します。そこにIKImageBrowserViewを配置します。

IKImageBrowserViewの属性でtitledをonにします。


IKImageBrowserViewを選択して「Layout」メニューから「Enbed Objects In」「Scroll View」を選択します。
IKImageBrowserViewがスクロールビューの中に収まりました。


スクロールビューのオートリサイズフラグは次のようにしてください。



ではコネクション関係。
File's OwnerのviewをIKImageBrowserViewを包むスクロールビューに接続します。
以上。


続いてBind関係。
Bindを行うのはIKImageBrowserViewだけです。説明は面倒くさいので下の通りに!


IBでの作業は以上です。


では実装に移りましょう。

ControllersIconViewController.m

#import "ControllersIconViewController.h"
#import <Quartz/Quartz.h>

@implementation ControllersIconViewController
- (id)init
{
    return [super initWithNibName:@"IconView" bundle:nil];
}
@end

@implementation NSDictionary (ControllersIconViewController_IKImageBrowserItem)
- (NSString *)imageUID
{
    return [self objectForKey:@"fullpath"];
}
- (NSString *)imageRepresentationType
{
    return IKImageBrowserQuickLookPathRepresentationType;
}
- (id)imageRepresentation
{
    return [self objectForKey:@"fullpath"];
}
- (NSString *)imageTitle
{
    return [self objectForKey:@"filename"];
}
@end

何か混ざってます(w


ControllersIconViewControllerは前回のControllersListViewControllerと変わりありません。ロードすべきnib(xib)の名前が変わっただけです。


では、混ざった物ですが、これはIKImageBrowserViewに表示されるアイテムが実装すべきメソッド群です。IKImageBrowserView.hに非形式プロトコルとして宣言されてます。
本来なら、これ用のクラスを作るべきですが、今回はカテゴリで逃げてみました。
-(NSString *)imageUID は画像にユニークなIDです。(説明でもなんでもない。)フルパスがその役目としてぴったりでしたので使ってみました。
- (NSString *)imageRepresentationType は何をどのように表示するかを示すタイプを返します。NSImageをすでに持っているのでIKImageBrowserNSImageRepresentationTypeでも良かったんですが、今回はIKImageBrowserQuickLookPathRepresentationTypeにしてみました。これにしておくとダブルクリックでそれを開けるみたいです。
- (id)imageRepresentation は表示用データを返します。IKImageBrowserQuickLookPathRepresentationTypeを選びましたので返す物はフルパスです。
- (NSString *)imageTitle はそのまま表示されるタイトルです。


このままではIKImageBrowserViewは表示されませんのでControllersWindowControllerを変更します。
ただし、今回はNSTableViewとの切り替えではなく、単にIKImageBrowserViewを表示するだけです。

ControllersWindowController.m

#import "ControllersWindowController.h"
#import "ControllersListViewController.h"
#import "ControllersIconViewController.h"    //追加

@implementation ControllersWindowController
@synthesize contents;
@synthesize viewController;

- (id)init
{
    return [super initWithWindowNibName:@"MainWindow"];
}
- (void)dealloc
{
    self.contents = nil;
    [super dealloc];
}
- (void)awakeFromNib
{
    self.viewController = [[[ControllersIconViewController alloc] init] autorelease];  //変更
    self.viewController.representedObject = controller;
    
    NSView *listView = self.viewController.view;
    listView.frame = placeholder.frame;
    [listView setFrameOrigin:NSZeroPoint];
    
    [placeholder addSubview:listView];
}
@end

ControllersIconViewController.hをインポートして、生成するViewControllerのクラス名を書き換えるだけです。-(id)initのオーバーライドがじわじわ効いてきました。


では実行してみましょう。



次回はビューを切り替える、です。


つづきControllerと たわむれる7 - masakihの日記