NSWindow (UKFlipWindow)
Language: Objective-C, Author: Uli Kusterer
License: MIT/X11
An NSWindow category which replicates Dashboard's "flip over a window to see its back side" effect. I'm doing all of this manually (NSAffineTransform seems to only let you rotate and scale stuff), so it isn't blazingly fast, but maybe it's of use to someone.
NSWindow (UKFlipWindow) source preview
// // NSWindow_UKFlipWindow.m // WindowFlipper // // Created by Uli Kusterer on 29.03.05. // Copyright 2005 M. Uli Kusterer. All rights reserved. // MIT Licensed #import "NSWindow+UKFlipWindow.h" #import <math.h> #define NUM_FRAMES 8 #define SLICE_WIDTH 4 #define FRAME_INTERVAL 0.05 @implementation NSWindow (UKFlipWindow) NSImage* gVirginImage = nil; NSImageView* gAnimationImageView = nil; NSTimer* gAnimationTimer = nil; int gCurrAnimationFrame = 0; SEL gHalfwayMessage = 0; id gHalfwayMsgTarget = nil; -(void) flipWindowTransitionWithHalfwayMessage: (SEL)sel target: (id)targ { NSRect cRect = [self contentRectForFrameRect: [self frame]]; NSWindow* overlay = [[NSWindow alloc] initWithContentRect: cRect styleMask: NSBorderlessWindowMask backing: NSBackingStoreBuffered defer: YES]; [overlay setHasShadow: NO]; [overlay setOpaque: NO]; [overlay setBackgroundColor: [NSColor clearColor]]; gHalfwayMsgTarget = targ; gHalfwayMessage = sel; cRect.origin = NSZeroPoint; gAnimationImageView = [[[NSImageView alloc] initWithFrame: cRect] autorelease]; [gAnimationImageView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable]; [[overlay contentView] addSubview: gAnimationImageView]; [self takeSnapshot]; gAnimationTimer = [[NSTimer scheduledTimerWithTimeInterval: FRAME_INTERVAL target: self selector:@selector(nextFlipAnimationFrame:) userInfo: nil repeats: YES] retain]; } -(void) takeSnapshot { NSView* borderView = [[self contentView] superview]; NSData* pdfData = [borderView dataWithPDFInsideRect: [borderView frame]]; gVirginImage = [[NSImage alloc] initWithData: pdfData]; [gAnimationImageView setImage: gVirginImage]; NSRect box = NSInsetRect([self frame], -18, -18 ); [[gAnimationImageView window] setFrame: box display: NO]; [[gAnimationImageView window] orderFront: nil]; [self orderOut: nil]; } -(void) nextFlipAnimationFrame: (NSTimer*)sender { NSImage* destImg = gVirginImage; NSRect vSrcStrip = { { 0, 0 }, { 0, 0 } }, vDstStrip, vFillStrip; NSSize wdSize = [gVirginImage size]; float x = 0; float stepSize = wdSize.height / wdSize.width; if( gCurrAnimationFrame < NUM_FRAMES ) { destImg = [[[NSImage alloc] initWithSize: wdSize] autorelease]; stepSize -= stepSize / 20 * (20 -gCurrAnimationFrame); [destImg lockFocus]; for( x = 0; x < wdSize.width; x += SLICE_WIDTH ) { vSrcStrip.origin.x = x; vSrcStrip.size.height = wdSize.height; vSrcStrip.size.width = SLICE_WIDTH; vDstStrip = vSrcStrip; vDstStrip.origin.x = x; vDstStrip.size.height -= (wdSize.width -x) * stepSize; vDstStrip.origin.y += (wdSize.height -vDstStrip.size.height) / 2; [gVirginImage drawInRect: vDstStrip fromRect: vSrcStrip operation: NSCompositeCopy fraction:1.0]; } [destImg unlockFocus]; [destImg setScalesWhenResized: YES]; [destImg setSize: NSMakeSize( fmaxf(1,(wdSize.width / NUM_FRAMES) * (NUM_FRAMES -1 -gCurrAnimationFrame)), wdSize.height)]; gCurrAnimationFrame++; } else if( gCurrAnimationFrame < (NUM_FRAMES *2) ) { float cf = gCurrAnimationFrame -NUM_FRAMES; destImg = [[[NSImage alloc] initWithSize: wdSize] autorelease]; if( gCurrAnimationFrame == NUM_FRAMES ) { [gHalfwayMsgTarget performSelector: gHalfwayMessage withObject: self]; [self takeSnapshot]; } stepSize -= stepSize / NUM_FRAMES * (cf +1); [destImg lockFocus]; for( x = 0; x < wdSize.width; x += SLICE_WIDTH ) { vSrcStrip.origin.x = (wdSize.width) -x; vSrcStrip.size.height = wdSize.height; vSrcStrip.size.width = SLICE_WIDTH; vDstStrip = vSrcStrip; vDstStrip.origin.x = (wdSize.width) -x; vDstStrip.size.height -= (wdSize.width -x) * stepSize; vDstStrip.origin.y += (wdSize.height -vDstStrip.size.height) / 2; [gVirginImage drawInRect: vDstStrip fromRect: vSrcStrip operation: NSCompositeCopy fraction:1.0]; } [destImg unlockFocus]; [destImg setScalesWhenResized: YES]; [destImg setSize: NSMakeSize( fmaxf(1,(wdSize.width / NUM_FRAMES) * cf), wdSize.height)]; gCurrAnimationFrame++; } else if( gCurrAnimationFrame == (NUM_FRAMES *2) ) { [gAnimationImageView setImage: gVirginImage]; [self makeKeyAndOrderFront: nil]; [[gAnimationImageView window] orderOut: nil]; [gAnimationTimer autorelease]; [gAnimationTimer invalidate]; gAnimationTimer = nil; [gVirginImage release]; gVirginImage = nil; [[gAnimationImageView window] release]; gAnimationImageView = nil; gCurrAnimationFrame = 0; } if( destImg != gVirginImage && gAnimationImageView != nil ) { wdSize = [destImg size]; wdSize.height += 32; wdSize.width += 32; NSImage* shadedImg = [[[NSImage alloc] initWithSize: wdSize] autorelease]; NSShadow* shad = [[[NSShadow alloc] init] autorelease]; NSPoint paintPoint = { 16, 16 }; [shadedImg lockFocus]; [NSGraphicsContext saveGraphicsState]; [shad setShadowOffset: NSMakeSize(0,-8)]; [shad setShadowBlurRadius: 16]; [shad setShadowColor: [NSColor colorWithCalibratedWhite: 0 alpha: 0.8]]; [shad set]; [destImg compositeToPoint: paintPoint operation: NSCompositeSourceOver]; [NSGraphicsContext restoreGraphicsState]; [destImg compositeToPoint: paintPoint operation: NSCompositeSourceOver]; [shadedImg unlockFocus]; [gAnimationImageView setImage: shadedImg]; } } @end
NSWindow (UKFlipWindow) header preview
// // NSWindow_UKFlipWindow.h // WindowFlipper // // Created by Uli Kusterer on 29.03.05. // Copyright 2005 M. Uli Kusterer. All rights reserved. // MIT Licensed #import <Cocoa/Cocoa.h> @interface NSWindow (UKFlipWindow) -(void) flipWindowTransitionWithHalfwayMessage: (SEL)sel target: (id)targ; // private: -(void) takeSnapshot; -(void) nextFlipAnimationFrame: (NSTimer*)sender; @endDownload Archive
Compatible with:
- Mac OS X 10.4 PPC
- Mac OS X 10.4 Intel
- Mac OS X 10.5 PPC
- Mac OS X 10.5 Intel
Comments
Comment feed
