Temporary Core Animation
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!
NSCollectionView scroll to origin fix
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 :)