I Love Outline Views - Here’s Mine

October 24, 2008

Apps like Coda are the de-facto standard for good user-interface design nowadays. You can do a lot with the standard Cocoa controls provided by Apple, but you can’t always get exactly what you want out-of-the-box. For example, the CSS edit section of Coda has a fantastic way of dividing tasks: the animated outline view.

Rather than having a monolithic view that has all the controls grouped with dividing lines; each section, “Text”, “Colors and Background”, “Dimensions”, all exist in their own collapsible view. Clicking the separating bar animatedly expands or collapses the view.


To make one of these views isn’t quite as easy as you first think, and you can quickly go down the wrong road in the design. The super-secret trick is to *not* use Core Animation, or more precisely: ignore the lure of NSViews conformance to the NSAnimatablePropertyContainer protocol. As of Mac OS X 10.5, a few of the properties of a view or window can be animated simply be replacing calls like [view setFrame:newFrame]; with [[view animator] setFrame:newFrame];. This is fine when you have one or two views that you want to move but it’s impossible to coordinate the movements of multiple view using this API. After using Core Animation, one would expect that after a call such as [[view animator] setFrame:newFrame]; requesting the frame from the view would return newFrame. Unfortunatley it returns the original frame of the view. Only when the animation is done, do you get newFrame. Furthermore, just try setting the delegate of the CABasicAnimation object that handles the implicit animation and getting any form of useful information back. You can’t. You’re in for a world of pain if you try.

The solution: use good-ol’ NSViewAnimation. That way you can create all the dictionaries containing the animations for all the views you want to, then instantiate one NSViewAnimation object to handle the lot and set them off at the same time. Simple.

The Animating Outline View

The outline view is made up of a few classes, the TLDisclosureBar, a subclass of the highly-configurable TLGradientView; the TLCollapsibleView which has a TLDisclosureBar and any NSView you like as its subviews. A TLCollapsibleView itself can be used alone, and will animate the collapse/expansion of the NSView subview (which I term the “detail view”).

The fun part comes when TLCollapsibleViews are subviews of a TLAnimatingOutlineView. In this case, the TLAnimatingOutlineView takes over all the animations, simply asking the TLCollapsibleView that the user has selected for the NSDictionary object that describes the collapse/expansion animation. With this information, it constructs the movement animations for all the subviews below the collapsing/expanding view and handles the required change of frame size to accommodate the changing content size. It’s all quite elegant, if I do say so myself.

Not being content with example code, I’ve made sure these classes are real-world useful. This view is integral to BibTeX management in Scribbler so it needs to be good. Some of the relevant parts of the NSOutlineView API are replicated and the delegate of the TLAnimatingOutlineView gets will/did/expand/collapse notifications, along with allowing the delegate to deny/allow animations, too. Each of the TLCollapsibleViews will also ask their detail views if the collapse/expansion is allowed if the TLCollapsibleDetailView protocol is implemented. The TLAnimatingOutlineView itself works when in an NSScrollView.

The code, along with an example project, is hosted on Google Code here. It is distributed under the new BSD license.

So why is is not ESAnimatingOutlineView, why the TL namespace? Well, I’m working on something big, at the same time as writing Scribbler. Start guessing.

Update

I’ve fixed a few bugs in the code, the current version can be checked out of the repository. Fixes include: proper support for hiding subviews of the TLDisclosureBars when the outline view is resized small, a correction to the autoresizing mask of the TLAnimatingOutlineView itself, declaration of keys that the TLCollapsibleView supplies with the animation dictionaries, the delegate of the outline view and subclasses of TLGradientView are no longer unregistered for notifications that client code specifies (i.e. no longer uses [[NSNotifcationCenter defaultCenter] removeObserver:_delegate];).


Creating iTunes Scrollers

June 18, 2008

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.
Read the rest of this entry »


How-to: Install MCNP4C2 on Mac OS X 10.4.10 (Intel)

October 8, 2007

MCNP (Monte Carlo N-Particle) is a transport code that is used throughout the physics community to model how particles interact as they travel through a system. The code is quite old, and therefore requires tweaking to get it running on newer systems like Mac OS X 10.4.10. There are programs and compilers it needs to use when installing that aren’t included in Mac OS X anymore due to their age, and a few that are on the Mac OS X CD that came with your computer, but aren’t installed by default. The first things we need are:

A FORTRAN-77 compiler and a ‘C’ compiler of the same version.
The ‘fsplit’ program.
X11 installed.
The XCode tools.
Read the rest of this entry »