« Delphi easter eggs | Main | Drag and Drop in an NSTableView »
July 26, 2005
Dynamically populating an NSPopUpButtonCell in an NSTableView
It is quite common. You have a PopUpButton (NSPopUpButtonCell) in an NSTableView and you want to dynamically change the contents based on the selected row:
How do you do this? There are a few tricky steps. First, add a menu to the nib and set the delegate for the menu to be your Controller:
Okay. Next is the tricky part. In IB, when you have a column in a tableview selected, it has a little white triangle in the corner:
Clicking on that will allow you to modify properties of the cell (in this case, the NSPopUpButtonCell). However, we want to set the menu for the NSPopUpButtonCell, so drag from that little triangle to your menu and set the menu outlet:
Okay, good! Now, all your controller needs is a little bit of code to dynamically populate the menu:
- (void)menuNeedsUpdate:(NSMenu *)menu {
// remove all previous items
while ([menu numberOfItems] > 0) {
[menu removeItemAtIndex:0];
}
// dynamically build the menu
int i;
int selectedRow = [tableViewStuff selectedRow];
for (i = 0; i <= selectedRow; i++) {
NSMenuItem *item = [[NSMenuItem alloc]
initWithTitle:[NSString stringWithFormat:@“Menu %d”, i]
action:@selector(menuClicked:) keyEquivalent:@“”];
[item setTarget:self];
[menu addItem:item];
}
}
Okay, that should work, right? Normally, yes. But in a tableview when a cell is tracked, it is first copied. Unfortunately, a small bug in the menu code doesn't copy the delegate. Therefore, we must fix it up in the nstableview's delegate method:
- (void)tableView:(NSTableView *)tableView
willDisplayCell:(id)cell
forTableColumn:(NSTableColumn *)tableColumn
row:(int)row
{
if ([cell isKindOfClass:[NSPopUpButtonCell class]]) {
[[cell menu] setDelegate:self];
}
}
That's it! Have fun...happy coding.
Posted by corbin at July 26, 2005 04:14 PM