Collapsible Views by Seth Willits
09-05-04




Collapsible Views
In Mac OS X, Apple has been paying nearly as much attention to how things look as to how they work and what they can do. Small animation such as the plusating blue default button, close button rollovers, the genie minimizing effect, and the Dock. One useful feature with that extra "Apple" touch is the Mixer view for Tracks in GarageBand. While other programs may simply allow the feature to make it visible or hidden instantaneously, Apple chose to do a bit of sliding animation, to hide it, very much like a drawer. Well, thinking this would be a cool effect to see in REALbasic applications I set out to see how to do it with individual controls, and as it turns out, it's incredibly simple.



The Design
This is quite a simple project since all it revolves around is having three canvases, a distinct control order, and a loop. Rather than use one canvas to draw the entire view, I decided it might be more efficient to simply use three separate canvases, one for the far left "tracks" column, one for the "mixer" column, and the last for the resizable area which in GarageBand would be the music editing space. By using the control order of the canvases, we make the mixer column appear below/under the tracks column. This conveniently gives us a place to hide our control under.



Now this is just a short example, so the project and code isn't production level, but it does show one method of accomplishing this. Here we see the routine to collapse the mixer column. When the mixer column is entirely hidden, the Left value of the canvas should be 40, which is what the kMixerLeftContracted constant represents. The dx constant is the number of pixels the column moves on each loop iteration. This is not time-based at all so it'll look different on your machine than it does on mine. 9 pixels per iteration happened to be the perfect speed for my machine.

What the code does is simply move the mixer canvas, and the expandable space on its right, to the left. The expandable canvas is also resized so that it fills the bounds the mixer canvas once used to fill. The if statement inside of the loop just does a simple check to see if the mixer column was moved too far past the left bound (kMixerLeftContracted) and moves it back accordingly. At the end of each iteration we have to have some way to make the interface update to reflect the position changes, so we simply redraw the mixer column. As it turns out, redrawing the mixer column also causes the expandable space canvas to redraw also.

So the collapse code is simply:



And the expansion code is just the opposite.


Finished
A simple but demonstrative way to accomplish the same effect as in GarageBand. Now to make this production-level code, you might consider making it time-based and maybe finding some ways to optimize the interface updating to make it smooth on as many computers as possible. Also, maybe wrapping the behavior in a canvas subclass and using notifications to give the controls around the one being expanded/contracted a chance to react would be a good idea. As always, you can download the project here.