I’ve got a NSArrayController dynamically populating a table with a bunch of columns, one of them has a popup button. The content of the popup button cell needs to use NSAttributedString as I need to display a scientific variable with subscript (X1 with lowered 1, for example).
Binding the pop up cell’s content values to an array of NSAttributedString yields gibberish in the UI as it only understands plain NSString objects.
The menu of the popup button isn’t bindable (i.e. not possible to assign dynamically via bindings).
The contents of the popup button menu can’t be bound dynamically either.
Can anybody suggest a way (sticking with bindings for at least the rest of the table content) to dynamically populate the NSPopUpButtonCell menu with NSAttributedString objects?
For displaying attributed strings in the menu when it’s popped up, I suggest setting the table column containing the pop-up cell to have it’s
Contentbinding pointing to anNSArrayControllerwhich itself is bound to anNSArrayofNSAttributedStringscontaining all the options, and then putting a delegate on theNSMenucontained by the pop-up cell, and then doing something like this in the delegate:The binding will have put the un-molested
NSAttributedStringinto therepresentedObjectproperty of theNSMenuItem. You can find it there and put it into theattributedTitleproperty, which will make it show the attributed string in the menu. In sum, a menu item, being drawn in a menu, with it’sattributedTitleproperty appropriately set, will draw the the styled text.What’s a bit more complicated is making the attributed string draw as intended in the pop-up cell when the menu is not popped-up.
NSPopUpButtonCellappears to render by having anNSMenuItemthat draws for it. Unfortunately, the creation of that particularNSMenuItemdoesn’t appear to include pushing the un-molested value into it. Instead the title seems to be sent in as a plain, non-attributed string. I’ve not been able to devise an elegant solution for this, but I did come up with an inelegant workaround:First add an
NSTextFieldcolumn to yourNSTableViewthat draws the currently selected attributed string correctly (i.e. with attributes). Make that column hidden. SubclassNSPopUpButtonCellor use a category and associated storage to add a new, private property toNSPopUpButtonCell. This property will hold a block that you can use at draw time to fetch the corresponding cell from the hidden column. Add anNSTableViewDelegate, and implement-tableView:dataCellForTableColumn:row:. When that gets called for the pop-up column, create the block to fetch the cell from the hidden column and shove it into the property on your subclass. Then at draw time, if you have a cell fetcher block, clear out thetitleon themenuItemthat it would normally use for rendering, call super (to get the little arrows for the pop-up), then fetch the surrogate cell, and have it draw too. Here’s what the code looks like:I must admit this makes me feel a little dirty, but it seems to get the job done. I’ve posted all the code, including the xib with all the associated bindings over on github:
Example Project
Hope that helps.