7 Comments

Summary:

This will be a new thread where I’ll show a tip or trick for Cocoa programmers, and why it’s imporant to everyone. These articles will be geared towards everyone – not just programmers. I’ll hide the code so you don’t have to look at it if […]

This will be a new thread where I’ll show a tip or trick for Cocoa programmers, and why it’s imporant to everyone. These articles will be geared towards everyone – not just programmers. I’ll hide the code so you don’t have to look at it if you don’t want to see it.

Cocoa Label NSTableView

Labels

More and more applications these days are utilizing labels in list views, tables, and other data rich layouts. Now in OS X (as with OS 9) we have finder labels.
finder labels
Labels are a great way to keep your ever-increasing data organized. They can be used in various ways, and are usually fully customizable. Much like gmail filters, these allow you to avoid creating countless folders for organization and use search instead. Really, these labels are quite simple to add into most applications, and probably should be. If an application you use everyday has lots of data, and could be helped by labels, suggest to the developer to take this code and pop it in for instant labels!

One thing many implementations of labels leave out is sorting (see my review of SOHO Notes). I’ve included code to do the nice little circles seen in the first screenshot for selection, and code to sort by labels. Although not in this example, I also think there is no reason why an entry should not be able to have more than one label. In reality, there are many times when your data belongs to two or more different sets.

A good example of an application that I think might benefit from labels is NetNewsWire. For those who keep posts for a long time, it would be nice to label some occasionally. This would set them apart more than simply flagging. An example of an app you wouldn’t think of adding labels to is iTunes. Imagine being able to color label songs into groups, instead of creating huge playlists. Sure, it’s probably not any more useful than playlists (though I am sure you could make an argument for it) but it sure would be fun. Or, even assign a label to smart playlist songs. For instance, I want all my music not listened to in the last 30 days to be green. Fun!

I am sure everyone reading this can come up with better examples, so go for it in the comments. What apps do you wish had labels???

The Code:

// In NSTableView subclass
– (void)drawRow:(int)rowIndex clipRect:(NSRect)clipRect
{
// Implement tableView:labelColorForRow in the table delegate
// It will just return the color, if there is one. Otherwise nil
NSColor * rowColor = [[self delegate] tableView:self labelColorForRow:rowIndex];
if ( ![[self selectedRowIndexes] containsIndex:rowIndex] && rowColor ) {
NSRect rect = [self rectOfRow:rowIndex];
rect.origin.x += 1.0;
rect.size.width -=2.0;
rect.size.height -=1.0;
rect.origin.y +=1.0;
[rowColor set];
// You can find this on CocoaDev.com
[[NSBezierPath bezierPathWithRoundRectInRect:rect radius:10.0] fill];
}
[super drawRow:rowIndex clipRect:clipRect];
}

// In the object class for sorting – in this case a “note” class
// If someone knows a better way to do this, please post
// Assume the color is not in the correct colorspace to begin with
– (NSComparisonResult)compareLabel:(note *)n
{
NSColor *rgb1 = [labelColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
NSColor *rgb2 = [[n labelColor] colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
float blue1 = [rgb1 blueComponent];
float red1 = [rgb1 redComponent];
float green1 = [rgb1 greenComponent];

float blue2 = [rgb2 blueComponent];
float red2 = [rgb2 redComponent];
float green2 = [rgb2 greenComponent];

int color1 = ((int)(blue1*8) << 16) + ((int)(red1*8) << 8 ) + green1*8;
int color2 = ((int)(blue2*8) << 16) + ((int)(red2*8) << 8 ) + green2*8;

if (color1 – color2 == 0)
return NSOrderedSame;
if (color1 – color2 > 0)
return NSOrderedAscending;
return NSOrderedDescending;
}

// In tableView delegate
– (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell
forTableColumn:(NSTableColumn *)aTableColumn
row:(int)rowIndex
{


if ([ident isEqualToString:@"colorLabel"]) {
if ([n labelColor] != [NSColor clearColor]) {
NSRect r = NSMakeRect(0,0,16,16);
NSImage *label = [[NSImage alloc] initWithSize:r.size];
[label lockFocus];
NSBezierPath *bp = [NSBezierPath bezierPathWithOvalInRect:NSInsetRect(r,1.0,1.0)];
[[n labelColor] set];
[bp fill];
[bp setLineWidth:2.0];
[[NSColor whiteColor] set];
[bp stroke];
[label unlockFocus];
[aCell setImage:label];
}

}

Enjoy!

  1. oh my god, this is the best post of the month.

    i’ve been wishing so many times that Mail (highlight specific emails beyond Flags and Rules backgrounds), iTunes (secondary rating) and iPhoto (alternative grouping / checking) had a label functionality.

    Linotype did it for their amazing Font Explorer, so if they can, Apple can surely follow them!

    Share
  2. Dude,

    This is an answer to prayer for me!!!! I’ve been looking for some code like this forever!
    I didn’t think it would be easy, since Apple doesn’t do it very often.

    Thanks!

    Share
  3. OK, so this sounds awsome enough, but, for all those out there who are boggled about code, including myself, how is this applied? And to what programs, and how?
    ANdy

    Share
  4. Michael Marmarou Tuesday, October 24, 2006

    For those of you who are not coders, this is call for you to email the developers of the apps you like, and send them here. Let them see how easy it is to add.

    Share
  5. Damn I thought this could be a sort of copy and paste sort of deal…

    Share
  6. Michael Marmarou Wednesday, October 25, 2006

    It is…sort of. If you don’t have a subclass of the tableview, just make one quickly. Completely empty except for that method.

    You’ll need to add a NSColor *labelColor to your object class, and some accessors. Then just paste the code into the delagate method. Shouldn’t take more than about 5 minutes.

    Feel free to email me if you have questions- marmarou at g mail dot com

    Share
  7. Mail.app

    This is what I miss from Thunderbird.

    Share

Comments have been disabled for this post