NSSliderCell overriding drawBarInside:flipped: doesn’t remove default track
| Originator: | douglas | ||
| Number: | rdar://11002025 | Date Originated: | 07-Mar-2012 |
| Status: | Open | Resolved: | |
| Product: | Mac OS SDK | Product Version: | Tested 10.6-10.8 |
| Classification: | Other Bug | Reproducible: | Always |
07-Mar-2012 11:06 AM Douglas Heriot: NSSliderCell bug report Summary: In an NSSliderCell subclass, overriding drawBarInside:flipped: doesn’t prevent the default track image from being drawn. Overriding drawWithFrame:inView: instead correctly prevents it from being drawn, but causes issue as the private _trackRect ivar is not set (as described in Notes below) Steps to Reproduce: Create an NSSliderCell subclass. Override drawBarInside:flipped: (and optionally drawKnob: to complete the custom visual style) Where the custom design of drawBarInside:flipped: uses a transparent background, the default track image shows through. See example project, file NormalCustomSliderCell.m, first group on left of screenshot. Expected Results: Overriding drawBarInside:flipped: should prevent the default track image from being drawn. Actual Results: Overriding drawBarInside:flipped: has no effect on whether the default track image is drawn Regression: not sure, but appears to have been this way for a while Observed in 10.6, 10.7 and 10.8 Notes: This only applies where the custom design requires a transparent background. One workaround is to simply draw over the default image in the custom drawBarInside:flipped:, but this doesn’t work for my transparent design (eg. for HUD windows, or within a view with an image texture background) There are a number of other workarounds. An obvious possible way is to instead override drawWithFrame:inView:, and call simply call drawBarInside:flipped: and drawKnob from there. This correctly prevents the default track image from being drawn, however, by not calling the superclass’s method the private _trackRect ivar is not set. This causes issues when the slider is resized, (ie. when the window is resized). (See the second group of sliders in the demo project, PublicAPISliderCell.m) The two other workarounds I’ve discovered both rely on private APIs. We can set _trackRect from our overridden drawWithFrame:inView: through a category. However, this isn’t very nice, and my app was eventually rejected from the Mac App Store for doing this. (See third group of sliders in example, TrackRectSliderCell.m) My last workaround, which I currently implement in my shipping app, is to override the private _usesCustomTrackImage method to return NO. (Because I really needed to get a bugdix release out, and I wanted to be extra sure using the private _usesCustomTrackImage wouldn’t be caught by the private API police, I used the class_addMethod() function from objc/runtime.h to add it in at runtime!) (See the fourth group of sliders, CustomTrackSliderCell.m) By correctly solving this drawBarInside:flipped: issue, the private API hacks should no longer be needed. Sample project zip: http://cl.ly/1v0T3T1o3s2I3N3k3S1n Screenshot: http://cl.ly/1m0L2f233X1M373h301i
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!