Apple introduced new scrollers in iTunes 7 and then moved on to give us the HUD, which many developers want their own scrollers for too. In Leopard, many of us thought that these would come in a nice, shiny box; but as they didn’t we’re all forced to roll our own. The common method is to draw all the components in Photoshop and then make a composite image when subclassing, but now with NSGradient and some nice additions to NSBezierPath all these have become quite easy to do, even for those with little artistic ability.
My first attempt was to do all of this using NSAffineTransforms, but without being able to mirror a bezier path, or define the the centre of rotation of a path or NSRect it becomes a loathsome task of tweaking and it just never quite works. So all the elements are drawn separately in this example, which is more code, but turned out to be far easier to code.
The important point to realise when subclassing NSScroller is that Apple’s documentation is out of date and some of the methods that we immediately assume we can subclass aren’t called. You can read the details in this thread on the cocoa-dev mailing list. You end up having to also implement -drawRect: and calling these documented (but unused) methods yourself.
The NSScroller consists first of the NSScrollerKnobSlot, the track on which the NSScrollerKnob itself lies. There are 2 (normally) buttons: in the vertical case the up arrow defined as the NSScrollerDecrementLine and the down arrow is the NSScrollerIncrementLine. I’ve implemented a method that checks to see which configuration the user has the scrollbars in, whether they are at the top and bottom or both together at the bottom. It does this by examining the AppleScrollBarVariant key in the global user defaults. If this (AFAICT undocumented) key changes then it calculated which configuration the user has selected. So when using these scrollers, the user can switch the configuration in System Preferences and the change can be seen. In the mode with both together at the bottom of the bar, there is also a top ‘socket’ that’s drawn.
The scrollbars also support horizontal scrolling, and I found that instantiating the vertical scroller without a frame works fine, but the only way to get a horizontal scroller is by using -initWithFrame:. I can only assume that apple are doing something under-the-hood for horizontal ones.
The final hiccup comes when you can to support the last 20% of users that use the scrollbar variant with both buttons at both ends. This is done in terminal and thankfully requires a restart of any program in which you want it to take effect. Problems come when trying to support this case when you want to know which button has been hit so you can draw it highlighted. The documented stuff from apple returns the same value whether the decrement line one end or the other is clicked! Making this impossible without tracking the mouse yourself, and I haven’t had the time to fix that. If I were using a program that didn’t respect my settings (I’m looking at you General Electric), then I’d get angry, so I included an NSScrollView subclass that checks for this case and just uses Apple’s scrollers if the user has selected it.
I think they’re pretty close to the iTunes ones, but mine are resoution-independent, but only Apple can give the perfect solution. You can download the XCode (3.1) project and sample app (10.5-only) here.



September 4, 2008 at 18:14 pm
Hi Jonathan,
Interesting post and project. It was funny to run it, because it looks like it’s out by a pixel, but then, looking at iTunes, that now looks wrong to me. Thanks for ruining iTunes for me!
Anyway, Scribbler sounds like a great idea. I use a really cut down selection of styles to give my documents some regularity in OpenOffice. When using other peoples documents in Word, the generally messed up styles drives me nuts. Will Scribbler have a set of predefined document templates? It seems like the nice TeX output would be great for people who like documents to be formatted in a standard way.
How are you planning to ensure that a TeX stack exists and is valid on the destination Mac?
Good luck with being an ISV!
September 5, 2008 at 20:34 pm
Hi Jonathan,
I *think* I know what you mean about it being out by a pixel, is it on the right-hand side of the vertical scroller? If it is then you see it in apps that don’t have a 1-pixel border around their scroll views, so the edge of the scroller is exactly aligned with the edge of the window. You can then see the effect this has when you move the window so it is directly above the desktop after being above another application’s window (if that makes sense). If that’s not what you mean then et me know and I’ll take a look.
As for Scribbler, I’m working on a set of project templates and document templates to help get people started, but these will grow as they’re added by users. If you have your own, you won’t have to send it to me for inclusion in the app either, just put it in the Scribbler directory in ~/Library/Application Support and Scribbler will find it. If you have any really good templates then please send them along!
As for the TeX stack, the only part that doesn’t work if there’s no valid distro on the system is typesetting itself. For those that download the app without TeX installed, I’m going to point them to the most current MacTeX distro for simplicity, possibly downloading it and mounting the disk image it for them so all they have to do is install. If I’ve misunderstood your question then please forgive me!