views:

296

answers:

2

I'm experimenting with creating a custom scope bar that uses recessed-style NSButtonCell objects. However, I'm having trouble drawing the bezel when the mouse is hovering. I can make it work by creating tracking areas and setting showsBorderOnlyWhileMouseInside to NO while the mouse is inside, and YES when it moves outside, but this feels like a hack to me, especially since NSButtonCell will do the tracking on its own.

If I use the control's setCell method, the button cell will call the control's addTrackingRect:owner:userData:assumeInside: and set up its own tracking to draw the bezel when the mouse is hovering. However, if I want to use multiple button cells in the same control, I try to set each cell's controlView to the custom control using the button cell's setControlView method, but it doesn't prompt the cell to set up tracking areas like setCell does.

The technique must be possible since NSMatrix does this, but after reading every API and forum available, I haven't found a way to initiate NSButtonCell's tracking behavior without using its control's setCell method. My forehead is bloody from beating against the desk - help would be appreciated.

A: 

First off, a band-aid might be the first thing that could help. ;)

Have you tried using NSButtonCell's -updateTrackingAreaWithFrame:inView: method?  It's not documented, but shows up in the NSButtonCell header that class-dump generates on Leopard.  I'm not sure what the official word or general consensus is regarding usage of non-documented methods that don't start with underscores, so caveat emptor.

On another note: You might want to – instead of using multiple buttonCells – look at using multiple buttons in a view for this task.  Modeling your own class after an existing class like NSMatrix is admirable, but for complex behaviors like what you're looking for, it's often more fruitful to deviate a little.  The concept that using many views instead of using a single view with a bunch of cells is expensive still has some merit, but if going that route requires a hacky implementation, I'd go the other way.

Dirk Stoop
Thanks, Dirk - I completely agree. I think the documentation's praise of NSCell made me feel guilty for using buttons. I thought I'd chase the rat hole for a while, but there doesn't seem to be a satisfactory solution for implementing this.I tried the updateTrackingAreaWithFrame:inView: method, but it didn't do the trick. Looking at the stack when Cocoa does this with an NSButton shows a bunch of private APIs getting passed around, so it doesn't look like we're meant to do this ourselves.
Sean Rich
+1  A: 

I came back to this one later and discovered that if you change the custom subclass to NSControl instead of NSView, the addTrackingRect method is taken care of automatically by the cell. Just call the cell's mouseEntered/mouseExited methods as necessary to implement the hovered mode of the cell. Hope this helps someone.

Sean Rich