« | Home | »

NSBrowser, NSTreeController, bindings, and displaying images

After much searching in Google, I found that there was no obvious solution to displaying images along with text in an NSBrowser when you are using NSTreeController and bindings to populate the browser.

Part of the problem is that you cannot easily use an NSBrowser delegate if you are also using bindings and an NSTreeController to drive the browser (at least on Mac OS X 10.6). For instance, you are prevented from using the -[NSBrowser browser:willDisplayCell:atRow:row column:column] delegate method to customize the cell presentation as you might do in an NSTableView or NSOutlineView.

I worked around this problem using a custome cell approach. When you bind the Browser’s Content Values binding to the NSTreeController, NSTreeController calls the browser cell’s setObjectValue: method. If you subclass NSBrowserCell and override setObjectValue:, you can assign the cell’s text and image. Here’s my NSBrowserCell subclass:

@interface MyBrowserCell : NSBrowserCell { }

- (void) setObjectValue:(id) value;

@end

@implementation MyBrowserCell

- (void) setObjectValue:(id) value {
    if ([value isKindOfClass:[NSDictionary class]]) {
        [self setStringValue:[value valueForKey:@"name"]];
        [self setImage:[value valueForKey:@"image"]];
    }
    else
        [super setObjectValue:value];
}

@end

Next, you need to configure the NSBrowser to use this cell. The simplest way to accomplish this is with NSBrowser’s setCellClass: method:

[browserView setCellClass:[MyBrowserCell class]];

Finally, you need to make your bindings model return a value that’s appropriate for MyBrowserCell. Here’s my nodel’s value getter method which is bound to the NSBrowser Content Values binding:

- (id) browserValue {
    return [NSDictionary dictionaryWithObjectsAndKeys:
                            [self browserName], @"name",
                            [self browserImage], @"image",
                            nil];
}

Note that you’ll need to make sure that will/didChangeValueForKey messages are sent for browserValue when browserName or browserImage change.

Here’s the result in my application:

SD5 Object Chooser Panel


About this entry