|
1 /* |
|
2 * Copyright (C) 2009 Apple Inc. All rights reserved. |
|
3 * |
|
4 * Redistribution and use in source and binary forms, with or without |
|
5 * modification, are permitted provided that the following conditions |
|
6 * are met: |
|
7 * 1. Redistributions of source code must retain the above copyright |
|
8 * notice, this list of conditions and the following disclaimer. |
|
9 * 2. Redistributions in binary form must reproduce the above copyright |
|
10 * notice, this list of conditions and the following disclaimer in the |
|
11 * documentation and/or other materials provided with the distribution. |
|
12 * |
|
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
|
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
|
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
|
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
|
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
|
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
|
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
24 */ |
|
25 |
|
26 #import "WebWindowAnimation.h" |
|
27 #import "WebKitSystemInterface.h" |
|
28 #import <wtf/Assertions.h> |
|
29 |
|
30 static const CGFloat slowMotionFactor = 10.; |
|
31 |
|
32 static NSTimeInterval WebWindowAnimationDurationFromDuration(NSTimeInterval duration) |
|
33 { |
|
34 return ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask) ? duration * slowMotionFactor : duration; |
|
35 } |
|
36 |
|
37 static NSRect scaledRect(NSRect _initialFrame, NSRect _finalFrame, double factor) |
|
38 { |
|
39 NSRect currentRect = _initialFrame; |
|
40 currentRect.origin.x += (NSMinX(_finalFrame) - NSMinX(_initialFrame)) * factor; |
|
41 currentRect.origin.y += (NSMinY(_finalFrame) - NSMinY(_initialFrame)) * factor; |
|
42 currentRect.size.width += (NSWidth(_finalFrame) - NSWidth(_initialFrame)) * factor; |
|
43 currentRect.size.height += (NSHeight(_finalFrame) - NSHeight(_initialFrame)) * factor; |
|
44 return currentRect; |
|
45 } |
|
46 |
|
47 static CGFloat squaredDistance(NSPoint point1, NSPoint point2) |
|
48 { |
|
49 CGFloat deltaX = point1.x - point2.x; |
|
50 CGFloat deltaY = point1.y - point2.y; |
|
51 return deltaX * deltaX + deltaY * deltaY; |
|
52 } |
|
53 |
|
54 @implementation WebWindowScaleAnimation |
|
55 |
|
56 - (id)init |
|
57 { |
|
58 self = [super init]; |
|
59 if (!self) |
|
60 return nil; |
|
61 #ifndef BUILDING_ON_TIGER |
|
62 [self setAnimationBlockingMode:NSAnimationNonblockingThreaded]; |
|
63 #endif |
|
64 [self setFrameRate:60.]; |
|
65 return self; |
|
66 } |
|
67 |
|
68 - (id)initWithHintedDuration:(NSTimeInterval)duration window:(NSWindow *)window initalFrame:(NSRect)initialFrame finalFrame:(NSRect)finalFrame |
|
69 { |
|
70 self = [self init]; |
|
71 if (!self) |
|
72 return nil; |
|
73 _hintedDuration = duration; |
|
74 _window = window; |
|
75 _initialFrame = initialFrame; |
|
76 _finalFrame = finalFrame; |
|
77 _realFrame = [window frame]; |
|
78 return self; |
|
79 } |
|
80 |
|
81 - (void) dealloc |
|
82 { |
|
83 [_subAnimation release]; |
|
84 [super dealloc]; |
|
85 } |
|
86 |
|
87 - (void)setDuration:(NSTimeInterval)duration |
|
88 { |
|
89 [super setDuration:WebWindowAnimationDurationFromDuration(duration)]; |
|
90 } |
|
91 |
|
92 - (void)setWindow:(NSWindow *)window |
|
93 { |
|
94 _window = window; |
|
95 } |
|
96 |
|
97 - (float)currentValue |
|
98 { |
|
99 return 0.5 - 0.5 * cos(M_PI * (1 - [self currentProgress])); |
|
100 } |
|
101 |
|
102 - (NSRect)currentFrame |
|
103 { |
|
104 return scaledRect(_finalFrame, _initialFrame, [self currentValue]); |
|
105 } |
|
106 |
|
107 - (void)setCurrentProgress:(NSAnimationProgress)progress |
|
108 { |
|
109 if (!_window) |
|
110 return; |
|
111 |
|
112 [super setCurrentProgress:progress]; |
|
113 |
|
114 NSRect currentRect = [self currentFrame]; |
|
115 #ifndef BUILDING_ON_TIGER |
|
116 WKWindowSetScaledFrame(_window, currentRect, _realFrame); |
|
117 #else |
|
118 [_window setFrame:currentRect display:YES]; |
|
119 #endif |
|
120 [_subAnimation setCurrentProgress:progress]; |
|
121 } |
|
122 |
|
123 - (void)setSubAnimation:(NSAnimation *)animation |
|
124 { |
|
125 id oldAnimation = _subAnimation; |
|
126 _subAnimation = [animation retain]; |
|
127 [oldAnimation release]; |
|
128 } |
|
129 |
|
130 - (NSTimeInterval)additionalDurationNeededToReachFinalFrame |
|
131 { |
|
132 static const CGFloat maxAdditionalDuration = 1.0; |
|
133 static const CGFloat speedFactor = 0.0001; |
|
134 |
|
135 CGFloat maxDist = squaredDistance(_initialFrame.origin, _finalFrame.origin); |
|
136 CGFloat dist; |
|
137 |
|
138 dist = squaredDistance(NSMakePoint(NSMaxX(_initialFrame), NSMinY(_initialFrame)), NSMakePoint(NSMaxX(_finalFrame), NSMinY(_finalFrame))); |
|
139 if (dist > maxDist) |
|
140 maxDist = dist; |
|
141 |
|
142 dist = squaredDistance(NSMakePoint(NSMaxX(_initialFrame), NSMaxY(_initialFrame)), NSMakePoint(NSMaxX(_finalFrame), NSMaxY(_finalFrame))); |
|
143 if (dist > maxDist) |
|
144 maxDist = dist; |
|
145 |
|
146 dist = squaredDistance(NSMakePoint(NSMinX(_initialFrame), NSMinY(_initialFrame)), NSMakePoint(NSMinX(_finalFrame), NSMinY(_finalFrame))); |
|
147 if (dist > maxDist) |
|
148 maxDist = dist; |
|
149 |
|
150 return MIN(sqrt(maxDist) * speedFactor, maxAdditionalDuration); |
|
151 } |
|
152 |
|
153 - (void)startAnimation |
|
154 { |
|
155 // Compute extra time |
|
156 if (_hintedDuration) |
|
157 [self setDuration:_hintedDuration + [self additionalDurationNeededToReachFinalFrame]]; |
|
158 [super startAnimation]; |
|
159 } |
|
160 |
|
161 - (void)stopAnimation |
|
162 { |
|
163 _window = nil; |
|
164 [super stopAnimation]; |
|
165 [_subAnimation stopAnimation]; |
|
166 } |
|
167 |
|
168 @end |
|
169 |
|
170 @implementation WebWindowFadeAnimation |
|
171 |
|
172 - (id)init |
|
173 { |
|
174 self = [super init]; |
|
175 if (!self) |
|
176 return nil; |
|
177 #ifndef BUILDING_ON_TIGER |
|
178 [self setAnimationBlockingMode:NSAnimationNonblockingThreaded]; |
|
179 #endif |
|
180 [self setFrameRate:60]; |
|
181 [self setAnimationCurve:NSAnimationEaseInOut]; |
|
182 return self; |
|
183 } |
|
184 |
|
185 - (id)initWithDuration:(NSTimeInterval)duration window:(NSWindow *)window initialAlpha:(CGFloat)initialAlpha finalAlpha:(CGFloat)finalAlpha |
|
186 { |
|
187 self = [self init]; |
|
188 if (!self) |
|
189 return nil; |
|
190 _window = window; |
|
191 _initialAlpha = initialAlpha; |
|
192 _finalAlpha = finalAlpha; |
|
193 return self; |
|
194 } |
|
195 |
|
196 - (void)setDuration:(NSTimeInterval)duration |
|
197 { |
|
198 [super setDuration:WebWindowAnimationDurationFromDuration(duration)]; |
|
199 } |
|
200 |
|
201 - (CGFloat)currentAlpha |
|
202 { |
|
203 return MAX(0.0, MIN(1.0, _initialAlpha + [self currentValue] * (_finalAlpha - _initialAlpha))); |
|
204 } |
|
205 |
|
206 - (void)setCurrentProgress:(NSAnimationProgress)progress |
|
207 { |
|
208 if (_isStopped) |
|
209 return; |
|
210 |
|
211 ASSERT(_window); |
|
212 [super setCurrentProgress:progress]; |
|
213 |
|
214 #ifndef BUILDING_ON_TIGER |
|
215 WKWindowSetAlpha(_window, [self currentAlpha]); |
|
216 #else |
|
217 [_window setAlphaValue:[self currentAlpha]]; |
|
218 #endif |
|
219 } |
|
220 |
|
221 - (void)setWindow:(NSWindow*)window |
|
222 { |
|
223 _window = window; |
|
224 } |
|
225 |
|
226 - (void)stopAnimation |
|
227 { |
|
228 // This is relevant when we are a sub animation of a scale animation. |
|
229 // In this case we are hosted in the animated thread of the parent |
|
230 // and even after [super stopAnimation], the parent might call |
|
231 // setCurrrentProgress. |
|
232 _isStopped = YES; |
|
233 |
|
234 [super stopAnimation]; |
|
235 } |
|
236 |
|
237 @end |
|
238 |