pigoz

stuff that no one cares about

Temporary Core Animation

with 2 comments

Working on my project I used Core Animation for the first time. Unfortunately layer-backed views don’t work well with some Cocoa controls (such as NSTextField and NSButton with check style). Luckyly I only need Core Animation to set up some NSView replacing and NSWindow scaling transitions.

For this reason I started to research a way to turn on layer backing before the animation starts and turn it off as soon as it ends. Since I didn’t find much information about it I wrote this post to sum it up. Here is some source code:

-(IBAction) trigger:(id) sender
{
	[[mainWindow contentView] setWantsLayer:YES];
	[NSTimer scheduledTimerWithTimeInterval:.2 target:self
                       selector:@selector(doAnimation) userInfo:nil repeats:NO];

}
-(void)doAnimation
{
	[NSAnimationContext beginGrouping];
	// do your transition here
	[NSAnimationContext endGrouping];
	[NSTimer scheduledTimerWithTimeInterval:.1 target:self
                       selector:@selector(finishAnimation) userInfo:nil repeats:NO];

}
-(void)finishAnimation
{
	[[mainWindow contentView] setWantsLayer:NO];
}

Have fun with Core Animation!

Written by pigoz

9 February 2009 at 10:24 am

Posted in Cocoa

NSCollectionView scroll to origin fix

leave a comment »

As you know Leopard has this new amazing facility to present complex data on screen. NSCollectionView allows you to lay out some NSViews each representing your data, whereas NSTableView supports only NSCells out of the box.

Anyway if you are thinking about using a NSCollectionView you will be disappointed to discover that in its current implementation is very buggy. As pointed out in the linked posts whenever you resize a containing NSWindow the contained NSCollectionView will scroll to its origins (provided that you actually have springed the NSCollectionView to the window).

Fortunately, fixing the “scroll to origin” misbehavior is pretty easy. Al you need to do is a NSWindow subclass implementing two delegate methods.

In the definition define an outlet that you will bind to the NSScrollView containing the NSCollectionView you want to resize properly. Moreover define an NSPoint to store the original position of the NSCollectionView in the NSScrollView.

@interface PGZWindow : NSWindow {

	IBOutlet NSScrollView * scrollView;
	NSPoint pos;

}

@property (retain) IBOutlet NSScrollView * scrollView;
- (void)windowDidResize:(NSNotification *)notification;
- (NSSize)windowWillResize:(NSWindow *) window toSize:(NSSize)newSize;

@end

In the implementation you just store the position before the resize, and set it after the resize is completed. Note that you need to set the delegate to self or windowDidResize: will not be called (the mysteries of cocoa…).

@implementation PGZWindow
@synthesize scrollView;

- (void) awakeFromNib
{
	[self setDelegate:self];
}

- (NSSize)windowWillResize:(NSWindow *) window toSize:(NSSize)newSize
{
	NSPoint new_pos = [[scrollView contentView] bounds].origin;
	if(new_pos.x > 0.0 || new_pos.y > 0.0){
		self->pos = new_pos;
	}
}

- (void)windowDidResize:(NSNotification *)notification
{
	NSPoint new_pos = [[scrollView contentView] bounds].origin;
	if(new_pos.x > 0.0 || new_pos.y > 0.0){
		self->pos = new_pos;
	} else {
		[[scrollView contentView] scrollToPoint:self->pos];
		[scrollView reflectScrolledClipView: [scrollView contentView]];
	}
	self->pos = NSMakePoint(0.0, 0.0);
}

@end

Thank you for reading and enjoy your resizing NSCollectionView. Cheers :)

Written by pigoz

6 February 2009 at 11:44 am

Posted in Cocoa

Tagged with