Archive for June 2007


Animation in the Time of Tiger: Part 1

June 30th, 2007 — 3:12pm

One of the most touted APIs in Leopard is CoreAnimation. Soon, you will be able to easily put together animations with tons of crap flying around all over the place. And with the new APIs, it’ll be a snap! Ok, ok, so there are some nice, tasteful animations that can be done and with Leopard they can be done easily. Fact is, though, there’s a good bit of animation you can do right now in Tiger (or earlier).

Why bother? Well, not all of us are dumping our Tiger users come October plus you could stand to learn something if you follow along. So, over the next couple months, I’ll be doing sporadic installments in this series. I’m not sure how many as I haven’t thought that far ahead but let’s say at least two, probably three.

Now, I feel that it’s important to lay down some guidelines. Animation in applications is subject to severe abuse. What may seem neat the first time can quickly become tedious if you are using the app on a daily basis. Too much movement in the interface can make for a visually noisy user experience or cause annoying delays. For the most part, use animation sparingly and with a purpose. Good uses would be to draw a connection between the start and end states of a transformation or to draw the eye from one part of the UI to another. A rule of thumb: if you feel the need to provide a preference to turn your animation off, maybe the animation is too intrusive. Remember, with great power comes great responsibility.

Before we delve into things, I want to point out that most of the animation techniques I’m going to talk about here pertain to NSWindows and NSViews. For various reasons, it is much easier to do animations with views than with, say, NSCells. What this means is that if you have a list of items using an NSMatrix or NSTableView and want to animate them, you may want to consider converting them into a bunch of views. While it is possible to write a control that animates its cells, you have to do a bit more work. Most of the animation hooks available operate on the view level, something that is further emphasized in CoreAnimation.

NSWindow animation

In NSWindow, you already have a powerful method at your disposal. With -setFrame:display:animate: you can set a new frame for your window and by specifying YES to the animate flag, the window will animate from its current frame to the new frame. Not too exciting? Well, try this on for size:

This effect is similar to how windows animate when you use the “Scale Effect” instead of the “Genie Effect” when minimizing windows (check your Dock preferences). You can download the project here. This is all done in an NSWindow category using documented API. While there’s a little magic of getting the window’s pixels (will probably talk about view/window caching in a future installment), the animation itself is done via the setFrame:display:animate: call. Ok, I fudge things slightly by overriding -animationResizeTime: to make it animate faster but the point is that you can do some interesting things with a basic call.

Autoresizing

When you animate, another thing you can take advantage of is the autoresizing mechanism (those springs and struts you see in IB). By setting up the autoresizing flags on your views in creative ways, you can do some neat little animations without having to muck with specifying all the different frames.

In Hazel’s (as well as in Mail’s) rule interface, when you create a new row, notice how all the rows below the new row shift down as space for the new row “grows” in. This is all done via setting the autoresizing masks (at least that’s how I do it; I can’t speak for what actually happens in Mail). Note that the autoresizing masks don’t have to be something you set once in IB and never touch again. Here, I reset them on the fly as needed. For the rows above the inserted row, the bottom margin is set to sizable. For rows below the insertion point, the top margin is set to sizable.

autoresizeanimationdiagrama.png

You need to put the new view into the hierarchy at some point. If you add it before the animation, you need to tweak with its size and autoresizing (make it height sizable). If you add it after, the view “pops” in but it happens fast enough that users will probably not notice. Now, I just resize the window (with animation) and all the views fall into place:

autoresizeanimationdiagramb.png

You do something similar when a row is deleted. Note that this is mostly effective when only one view in the window is resizing (and the others just moving) in a particular dimension as the resizing mechanism produces less than ideal results when more than one view is resizing.

So, that’s it for now. In the next installment, we’ll dig into NSViewAnimation and also have some more fun with autosizing flags.

5 comments » | Cocoa, Downloads, Programming

WWDC Wrap-Up

June 20th, 2007 — 12:09pm

Ok, I’ve painted myself into a corner here. I’m back home finally but I don’t really have anything interesting to add (at least anything that won’t break NDA). Nonetheless, since I started talking about WWDC, I might as well cap it off.

As Gus Mueller mentions here, it seems that this year was much more oriented towards those new to the platform (and there were a lot of them). As for me, I found it a bit annoying to walk into a session and find out it was Quartz 101 or somesuch. I don’t mind the existence of such sessions; I just felt that they were not as clearly marked. It was sometimes hard to tell if a session would (a) tell us something new since last time or (b) touch on something more advanced, either of which I would have been satisfied with. Personally, I’d like to see some indication of level or prerequisites (or lack thereof) on sessions.

And like everyone else, I met a bunch of people and even got re-acquainted with a couple people who I haven’t seen in a decade. Maybe next year I should just skip the conference and just crash the parties…

Comment » | WWDC

WWDC midweek report

June 13th, 2007 — 4:55pm

Typing this up between sessions so please excuse the sloppy writing.

Stacks

When Steve started talking about cleaning the Desktop, my heart stopped for a split second. I thought I was going to be Sherlocked (I was also sitting with the Karelia guys at the time). As it turns out, Stacks is just doing what I’ve been suggesting for a while on my tips and tricks page: download everything to a separate downloads folder. Hazel stores the file’s date added and ships with a sample rule to color newly added files; Finder (or maybe the filesystem, I need to check) now keeps track of the date added as well and uses it to keep your most recently added files at the top of the stack. Nonetheless, those Stacks don’t clean themselves so, I think the main adjustment I need to make is to change the marketing message from “Clean Your Desktop” to “Clean Your Stacks”.

Miscellaneous KeyNote comments

I feel like I’m missing the point of the transparent menubar. You can’t drag windows up underneath the menubar. Are the top 20 or so pixels of your wallpaper that important? What do you need to see under there? While I appreciate the tricks they pulled to maintain legibility, it’s still not as clear as an opaque menubar. So yes, add me to the list of grumpy transparent menubar haters.

Did anyone find it odd that when showing the pie charts of Safari’s current market share and their target marketshare, that they had Safari eat up Firefox’s slice of the pie while IE’s market share remained unchanged? Not sure if one should read too much into it as it probably was inadvertent, but it does give the impression that Apple is gunning for Firefox.

Parties

A big thanks for Chuck Soper and Buzz Anderson for organizing their respective parties. The edge has to go to Buzz though since he arranged for a taco truck to be parked outside. Nothing like eating a taco with meat scraped off the face of a cow to start the evening off right.

I’ll probably drop by the OmniFocus get-together later today but won’t be able to make any of the other extracurricular events because of dinner plans.

3 comments » | Hazel, WWDC

Dub Dub Dee See

June 8th, 2007 — 11:31am

It doesn’t seem that long ago that I went to my first WWDC last year. I had recently quit my fulltime job. Hazel 1.0 was in beta at that time. Since my app was to be released on Tiger, all this Leopard talk seemed somewhat irrelevant. I was a newcomer and an unknown.

It’s not quite a year later but WWDC is here again. Hazel 2.0 is now in alpha. It is still targeted for Tiger so Leopard-specific features are still just in the concept phase for me. I’m now not a total unknown. Additionally, since the last WWDC, sales have increased by ∞% so things are going great!

I’m on the road already and am trying to squeeze out another release before the conference (most likely later today). I’ll be in SF on Sunday in time for the Mac ISV dinner. If you spot me, feel free to give me copious amounts of money; it’s what they call “networking.” How do you spot me? Well, take Rodney Dangerfield in a tutu and cross him with Zombie Joseph Stalin and you’d get something that not only is hard to visualize, but also doesn’t resemble me in the least. See you there!

3 comments » | Hazel, Noodlesoft, WWDC

Tracking Hacks

June 1st, 2007 — 5:57pm

You do it more than you’d like to admit. Because of time constraints, laziness, or just plain not-knowing-what-to-do, you write an ugly hack to get around a problem. The code works for the most part but you wonder for how long. The problem isn’t so much with creating the hack; quick ‘n’ dirty code is sometimes necessary. The problem is letting it exist for longer than it should.

I thought I’d share my simple little system for dealing with this. It has worked out well for me over the years.

When writing crufty code, comment the hack. Give as much background as is necessary such that months later you will be able to understand the issue after you’ve dumped it from your short term memory.

Now, prefix the comment as follows:

  • If this hack should be removed before the next release, use PENDING.
  • If this hack is to stay for an indeterminate amount of time, such as a workaround for an Apple bug, use FUTURE.
  • If this hack is permanent (maybe for legacy reasons or it’s otherwise unavoidable), just use good ol’ HACK.

Basically, it would look like this:


// PENDING(MrHacker): I probably should not be doing this.

It also helps to include your name, as shown above. Don’t make people use svn blame.

Basically, what this does is tag your hacks for easy scouring later.

Near the end of your dev cycle, do a global search for all the PENDING comments. Decide whether you want to apply a more permanent fix now or whether to keep the hack in longer. Downgrade to FUTURE or HACK if you aren’t going to fix them for this release. Every so often, revisit FUTURE comments to see if conditions have changed to allow a better fix. If so, you can either fix them on the spot or upgrade them to PENDING for inclusion in the next release.

Also, it’s not strictly for hacked code. Maybe you’re on a roll. Code is just shooting out of your fingertips. When you got the flow, the last thing you want to do stop and figure out how to handle some error condition. Just use a PENDING comment as a placeholder. Since you will undoubtedly scour for them later, it’s a sure way to remind yourself that you need to fill in the rest. In a sense, hacks are defined not just by what you create, but what you omit and tagging them as such helps to identify them later. You could further extend this by also including ticket/issue/bug numbers if you are using such a system.

If there has been any failing to this system, it’s not being diligent about scouring through and changing the tags. But, the important thing is that it is tagged and easily identified when needed.

2 comments » | Programming

Back to top