Here's an example I threw together that lets you swap one view for another after animatedly resizing a window. The most obvious use of this would be in a preference window, when switching between multiple tabs. For the example names, I'm using Wolf Rentzsch's 'NSX' naming convention.
// Define custom objects and keys
#define NSXViewAnimationSwapAtEndEffect @"NSXViewAnimationSwapAtEndEffect"
#define NSXViewAnimationSwapOldKey @"NSXViewAnimationSwapOldKey"
#define NSXViewAnimationSwapNewKey @"NSXViewAnimationSwapNewKey"
Then somewhere in your controller class:
NSRect newWindowFrame = someCalculatedRect;
// Build a dictionary...
NSMutableDictionary* windowDict =
[NSMutableDictionary dictionaryWithCapacity: 5];
// ...with standard keys...
[windowDict setObject: myWindow
forKey: NSViewAnimationTargetKey];
[windowDict setObject: [NSValue valueWithRect: newWindowFrame]
forKey: NSViewAnimationEndFrameKey];
// ...and custom keys.
[windowDict setObject: NSXViewAnimationSwapAtEndEffect
forKey: NSViewAnimationEffectKey];
[windowDict setObject: someViewToHide
forKey: NSXViewAnimationSwapOldKey];
[windowDict setObject: someViewToShow
forKey: NSXViewAnimationSwapNewKey];
// Create the animation.
NSViewAnimation* windowAnim = [[NSViewAnimation alloc]
initWithViewAnimations: [NSArray arrayWithObjects:
windowDict, nil]];
// Go.
[windowAnim setDelegate: self];
[windowAnim startAnimation];
[windowAnim autorelease];
And finally, the delegate method:
- (void)animationDidEnd: (NSAnimation*)animation
{
// Standard sanity checks.
if (![animation isKindOfClass: [NSViewAnimation class]])
return;
NSArray* animatedViews =
[(NSViewAnimation*)animation viewAnimations];
if (!animatedViews)
return;
// Grab the window from the first animation.
NSWindow* animatingWindow = [[animatedViews objectAtIndex: 0]
objectForKey: NSViewAnimationTargetKey];
if (animatingWindow != myWindow)
return;
// Iterate through possibly multiple animations.
UInt32 i;
UInt32 numAnimations = [animatedViews count];
id animObject = nil;
id keyObject = nil;
for (i = 0; i < numAnimations; i++)
{
animObject = [animatedViews objectAtIndex: i];
if (!animObject)
continue;
// Grab our custom effect key.
keyObject = [animObject objectForKey: NSViewAnimationEffectKey];
if (!keyObject)
continue;
// Execute the custom effect.
if ([keyObject isEqualToString: NSXViewAnimationSwapAtEndEffect])
{
NSView* oldView = [animObject
objectForKey: NSXViewAnimationSwapOldKey];
NSView* newView = [animObject
objectForKey: NSXViewAnimationSwapNewKey];
if (oldView)
[oldView setHidden: YES];
if (newView)
[newView setHidden: NO];
}
}
}
A trivial example, no doubt, but there are countless possibilities. Imagine calling setDuration: from the animation:didReachProgressMark: delegate to implement some crazy animation curve. Or overriding setCurrentProgress: in a subclass to link several animations more intuitively than with startWhenAnimation:reachesProgress:. Of course, all this is possible without using custom dictionary keys, but this way is a lot more fun.
I'd love to hear any more uses you can think of, and other classes that use dictionaries in a similar way.
*I originally said 'it was just xml', and Peter Hosey pointed out that while the key/object relationship evoked feelings of xml in me, it's not really xml until it's saved to disk. I've updated the text to more correctly describe data in memory.
6 comments:
Technically, it's only XML if you write it out as such. In memory, it's just an associative array.
ah, thanks for the correction, I'll update the text.
It's not even xml if you write it out as a bplist, which most of the apps do nowadays... you'll need plist-editor to edit these, though.
just my 2ct ;-)
nice read!! really interesting
- great tips - thanks!
Quick question, how are you doing your formated code with blogger?
I imagine there's a better way using CSS, but what I did for this post was copy it into BBEdit, detab everything, then replace all spaces with It's ugly but it worked I guess. I also surrounded the code parts with <font face="Monaco" size=1>.
Thanks!
I will give that a try for the short and dirty and look for something else for the long term.
Cheers,
k
Post a Comment