Dealing with the triangles in a NSOutlineView

Monday, April 03, 2006

Since the solutions for "Cocoa(R) Programming for Mac(R) OS X (2nd Edition)" don't seem to generate that much interest and they take a pretty good amount of time to make a decent blog entry, I'm taking a little different direction on this blog. I'm going to post small snippets of code that I've found rather tricky to develop.

The first of which is a quick way to hide the little triangles in an outline view. I've searched many sites for an answer to this question and didn't really get an example of doing this. So here it is.

The first thing to make you aware of is that a NSOutlineView has a delegate method which allows you to override the display of the outline column's cell.

Here's the method...
- (void)outlineView:(NSOutlineView *)outlineView willDisplayOutlineCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item

Approach 1

Just replace the triangle images with other images. (This requires the image to be the same size as the triangle)
- (void)outlineView:(NSOutlineView *)theOutlineView willDisplayOutlineCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item {
if (item) {
[cell setImage:[NSImage imageNamed:@"down"]];
[cell setAlternateImage:[NSImage imageNamed:@"up"]];

Approach 2

First, hide the triangle completely.

- (void)outlineView:(NSOutlineView *)theOutlineView willDisplayOutlineCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item {
if (item) {
[cell setTransparent:YES];

Now we use the non-outline delegate method to set up a button cell to do the expand and collapse for the row.
- (void)outlineView:(NSOutlineView *)theOutlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item {
if ([[tableColumn identifier] isEqualToString:@"outline"]) { //use the appropriate identifier for you column
if ([self childCountOfItem:item] > 0) {
if ([theOutlineView isItemExpanded:item]) {
[cell setImage:[NSImage imageNamed:@"up"]];
} else {
[cell setImage:[NSImage imageNamed:@"down"]];

//set up an action to emulate the clicking you would normally do on the triangle

[cell setAction:@selector(toggleItem:)];
[cell setTarget:self];
} else {
[cell setImage:[NSImage imageNamed:@"unexpandable"]];

- (void)toggleItem:(id)sender {
id item = [outlineView itemAtRow:[outlineView selectedRow]];
if ([outlineView isItemExpanded:item]) {
[outlineView collapseItem:item];
} else {
[outlineView expandItem:item];

As always feedback is encouraged...

The Cocoa challenge tutorials were awesome. Don't get rid of them.
Ditto. I hope you'll continue doing the Cocoa challenge tutorials as I've been looking for the solutions for quite some time. I'm glad I finally found you!

Also, if you have the time, maybe you could explain how to set the background color of the NSTableView when it doesn't seem possible to set the outlet from the Document to it (pg 192-193). Even his sample code from the site doesn't do it correctly. Obviously some things in XCode have changed.

Thanks for the help.
Ditto. Please bring back the cocoa challenge tutorials! We need them!
The AppKit release notes for 10.5 make a different recommendation: override frameOfOutlineCellAtRow: and return the empty rect.
as others have stated, the answers would be nice. i have been struggling with chapter 13 for a bit. finally found it.

to post it here just for anyone else, to reset the user defaults you have to get the defaults and them simply removeObjectFromKey:someObject as below:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults removeObjectForKey:BNREmptyDocKey];

the next phase was to get the UI to update, and that can be done by simply the following:

[checkBox setState:[self emptyDoc]];

since the user default has been reset, when you read whats there, you get the default and then set the state of the checkbox accordingly.

i would be happy to help anyone that needs info on any of the excersizes that i have completed. feel free to email me
Thank you for posting some of the challange solutions. It saved me a few hairs when trying to figure these out!
Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?