-
Notifications
You must be signed in to change notification settings - Fork 1
/
NSWindow+ThumbAnimation.m
186 lines (151 loc) · 4.72 KB
/
NSWindow+ThumbAnimation.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// COMMON FILE: Common
//
// NSWindow+ThumbAnimation.m
// ThumbAnim
//
// Created by Uncle MiF on 4/12/10.
// Copyright 2010 Deep IT. All rights reserved.
//
#import "NSWindow+ThumbAnimation.h"
#import <QuartzCore/QuartzCore.h>
NSString* NSWindowAnimationFromFrameDidFinished = @"NSWindowAnimationFromFrameDidFinished";
static NSMutableDictionary * _storage = nil;
@implementation NSWindow (ThumbAnimation)
-(NSMutableDictionary*)_ta_storage
{
if (!_storage)
@synchronized(@"ta_storage")
{
if (!_storage)
_storage = [NSMutableDictionary new];
}
return _storage;
}
-(id)_ta_storageObjectForKey:(NSString*)key
{
NSMutableDictionary* storage = [self _ta_storage];
id obj = nil;
@synchronized(storage)
{
obj = [[[storage objectForKey:key] retain] autorelease];
}
return obj;
}
-(void)_ta_setStorageObject:(id)object forKey:(NSString*)key
{
NSMutableDictionary* storage = [self _ta_storage];
@synchronized(storage)
{
if (!object)
[storage removeObjectForKey:key];
else
[storage setObject:object forKey:key];
}
}
#define TACachedView @"cachedView"
-(NSView*)_ta_cachedView
{
return [self _ta_storageObjectForKey:TACachedView];
}
#define TAOldContent @"oldContent"
-(NSView*)_ta_oldContent
{
return [self _ta_storageObjectForKey:TAOldContent];
}
-(void)_ta_setCachedView:(NSView*)view
{
[self _ta_setStorageObject:view forKey:TACachedView];
}
-(void)_ta_setOldContent:(NSView*)view
{
[self _ta_setStorageObject:view forKey:TAOldContent];
}
-(void)animateFromFrame:(NSRect)fromRect toFrame:(NSRect)toRect
{
NSView* windowView = [[self contentView] opaqueAncestor];
NSBitmapImageRep* bitmap = nil;
NSRect windowRect = [windowView frame];
@try
{
if ([self isVisible])
[self orderOut:self];
[self setFrame:toRect display:NO];
[self display];
[windowView lockFocus];
@try
{
bitmap = [[[NSBitmapImageRep alloc] initWithFocusedViewRect: windowRect] autorelease];
}
@catch(id universal){}
[windowView unlockFocus];
if (!bitmap)
@throw(@"No bitmap");
}
@catch(id universal)
{
[self makeKeyAndOrderFront:self];
return;
}
NSImage* image = [[[NSImage alloc] initWithSize: [bitmap size]] autorelease];
NSImageView * imageView = nil;
if (image)
{
[image addRepresentation: bitmap];
imageView = [[[NSImageView alloc] initWithFrame: windowRect] autorelease];
[imageView setAutoresizingMask:
NSViewMinYMargin | NSViewMaxYMargin | NSViewMinXMargin | NSViewMaxXMargin |
NSViewHeightSizable | NSViewWidthSizable];
[imageView setImage: image];
[imageView setImageScaling:NSScaleToFit];
}
if (imageView)
{
[self _ta_setOldContent:[self contentView]];
NSView * emptyView = [[[NSView alloc] initWithFrame:[[self contentView] frame]] autorelease];
[emptyView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[self setContentView:emptyView];
[windowView addSubview:imageView];
[self _ta_setCachedView:imageView];
if ([self isVisible])
[self orderOut:self];
[self setFrame:fromRect display:NO];
[self setAlphaValue:0.4];
[self orderFront:self];
CABasicAnimation * frameAnimation = [CABasicAnimation animationWithKeyPath:@"frame"];
frameAnimation.delegate = self;
frameAnimation.duration = .5;
frameAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
CABasicAnimation * alphaValueAnimation = [CABasicAnimation animationWithKeyPath:@"alphaValue"];
alphaValueAnimation.duration = .5;
alphaValueAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[self setAnimations:[NSDictionary dictionaryWithObjectsAndKeys:
frameAnimation,@"frame",
alphaValueAnimation,@"alphaValue",
nil]];
[NSAnimationContext beginGrouping];
[[self animator] setFrame:toRect display:NO];
[[self animator] setAlphaValue:1.0];
[NSAnimationContext endGrouping];
}
else
[self makeKeyAndOrderFront:self];
}
- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag
{
#pragma unused(flag)
[animation setDelegate:nil];
[self setContentView:[self _ta_oldContent]];
[self _ta_setOldContent:nil];
[[self _ta_cachedView] removeFromSuperview];
[self _ta_setCachedView:nil];
[self setToolbar:[self toolbar]];
[self makeKeyAndOrderFront:self];
[self flushWindow];
[self display];
if ([self respondsToSelector:@selector(animationFromFrameDidFinished)])
[self performSelector:@selector(animationFromFrameDidFinished)];
if ([[self windowController] respondsToSelector:@selector(animationFromFrameDidFinished)])
[[self windowController] performSelector:@selector(animationFromFrameDidFinished)];
[[NSNotificationCenter defaultCenter] postNotificationName:NSWindowAnimationFromFrameDidFinished object:self];
}
@end