5 var _CPAnimationContextStack = nil,
6 _animationFlushingObserver = nil;
12 Function _completionHandlerAgent;
13 Map _animationsByObject;
26 [
self _scheduleAnimationContextStackFlush];
32 + (CPArray)contextStack
34 if (!_CPAnimationContextStack)
35 _CPAnimationContextStack = [CPArray array];
37 return _CPAnimationContextStack;
40 + (void)runAnimationGroup:(Function)animationsBlock completionHandler:(Function)aCompletionHandler
45 [context setCompletionHandler:aCompletionHandler];
47 animationsBlock(context);
58 _completionHandlerAgent = nil;
59 _animationsByObject =
new Map();
64 + (void)_scheduleAnimationContextStackFlush
66 if (!_animationFlushingObserver)
69 CPLog.debug(
"create new observer");
80 if ([_CPAnimationContextStack count])
82 var currentContext = [_CPAnimationContextStack lastObject];
83 [newContext setDuration:[currentContext duration]];
84 [newContext setTimingFunction:[currentContext timingFunction]];
87 [_CPAnimationContextStack addObject:newContext];
92 if (![_CPAnimationContextStack count])
95 var context = [_CPAnimationContextStack lastObject];
96 [context _flushAnimations];
97 [_CPAnimationContextStack removeLastObject];
100 CPLog.debug(_cmd +
"context stack =" + _CPAnimationContextStack);
105 - (void)_enqueueActionForObject:(
id)anObject keyPath:(
id)aKeyPath targetValue:(
id)aTargetValue animationCompletion:(
id)animationCompletion
107 var resolvedAction = [
self _actionForObject:anObject keyPath:aKeyPath targetValue:aTargetValue animationCompletion:animationCompletion];
112 var animByKeyPath = _animationsByObject.get(anObject);
116 var newAnimByKeyPath = @{aKeyPath:resolvedAction};
117 _animationsByObject.set(anObject, newAnimByKeyPath);
120 [animByKeyPath setObject:resolvedAction forKey:aKeyPath];
123 - (Object)_actionForObject:(
id)anObject keyPath:(
CPString)aKeyPath targetValue:(
id)aTargetValue animationCompletion:(Function)animationCompletion
131 needsPeriodicFrameUpdates,
132 objectId = [anObject UID];
134 if (!aKeyPath || !anObject || !(animation = [anObject animationForKey:aKeyPath]) || ![animation isKindOfClass:[
CAAnimation class]])
137 duration = [animation duration] || [
self duration];
138 needsPeriodicFrameUpdates = [[anObject animator] needsPeriodicFrameUpdatesForKeyPath:aKeyPath];
140 var animatorClass = [[anObject class] animatorClass];
142 var completionFunction =
function()
144 if (needsPeriodicFrameUpdates)
145 [animatorClass stopUpdaterWithIdentifier:objectId];
147 if (animationCompletion)
148 animationCompletion();
150 if (needsPeriodicFrameUpdates || animationCompletion)
153 if (_completionHandlerAgent)
154 _completionHandlerAgent.decrement();
157 if (![animation isKindOfClass:[
CAPropertyAnimation class]] || !(animatedKeyPath = [animation keyPath]))
158 animatedKeyPath = aKeyPath;
162 values = [animation values];
163 keyTimes = [animation keyTimes];
164 timingFunctions = [animation timingFunctionsControlPoints];
172 if (!isBasicAnimation || (fromValue = [animation fromValue]) == nil)
173 fromValue = [anObject valueForKey:animatedKeyPath];
175 if (!isBasicAnimation || (toValue = [animation toValue]) == nil)
176 toValue = aTargetValue;
178 values = [fromValue, toValue];
180 timingFunctions = isBasicAnimation ? [animation timingFunctionControlPoints] : [_timingFunction controlPoints];
186 keypath:animatedKeyPath,
190 timingfunctions:timingFunctions,
191 completion:completionFunction
195 - (void)_flushAnimations
197 if (![_CPAnimationContextStack count])
200 if (_animationsByObject.size == 0)
202 if (_completionHandlerAgent)
205 CPLog.debug(
"No animations are scheduled. Firing completion handler");
207 _completionHandlerAgent.fire();
211 [
self _startAnimations];
214 - (void)_startAnimations
216 var cssAnimations = [],
219 _animationsByObject.forEach(
function(animByKeyPath, targetView)
221 [animByKeyPath enumerateKeysAndObjectsUsingBlock:function(aKey, anAction, stop)
223 [
self getAnimations:cssAnimations getTimers:timers usingAction:anAction cssAnimate:YES];
227 _animationsByObject.clear();
229 var k = timers.length,
230 n = cssAnimations.length;
232 if (_completionHandlerAgent)
237 CPLog.debug(
"Animations are not needed. Firing completion handler");
239 _completionHandlerAgent.fire();
242 _completionHandlerAgent.increment(n);
249 CPLog.debug(
"START TIMER " + timers[k].
description());
258 CPLog.debug(
"START ANIMATION " + cssAnimations[n].
description());
260 cssAnimations[n].start();
264 - (void)getAnimations:(CPArray)cssAnimations getTimers:(CPArray)timers usingAction:(Object)anAction cssAnimate:(BOOL)needsCSSAnimation
266 var values = anAction.values;
268 if (values.length == 2)
270 var
start = values[0],
273 if (anAction.keypath ==
@"frame" && CGRectEqualToRect(
start, end)
274 || anAction.keypath ==
@"frameSize" && CGSizeEqualToSize(
start, end)
275 || anAction.keypath ==
@"frameOrigin" && CGPointEqualToPoint(
start, end))
279 var targetView = anAction.object,
280 keyPath = anAction.keypath,
281 isFrameKeyPath = (keyPath ==
@"frame" || keyPath ==
@"frameSize"),
282 customLayout = [targetView hasCustomLayoutSubviews],
283 customDrawing = [targetView hasCustomDrawRect],
284 declarative_subviews_layout = (!customLayout || [targetView implementsSelector:
@selector(frameRectOfView:inSuperviewSize:)]),
285 needsPeriodicFrameUpdates = [[targetView animator] needsPeriodicFrameUpdatesForKeyPath:keyPath],
287 animatorClass = [[targetView
class] animatorClass];
289 if (needsCSSAnimation)
291 [animatorClass addAnimations:cssAnimations forAction:anAction];
294 if (needsPeriodicFrameUpdates)
296 [animatorClass addFrameUpdaters:timers forAction:anAction];
299 var subviews = [targetView subviews],
300 count = [subviews count];
302 if (count && isFrameKeyPath)
304 [subviews enumerateObjectsUsingBlock:function(aSubview, idx, stop)
306 if (!declarative_subviews_layout && [aSubview autoresizingMask] == 0)
310 targetFrame = [action.values lastObject];
312 if (CGRectEqualToRect([aSubview frame], targetFrame))
315 if ([aSubview hasCustomDrawRect])
317 action.completion = function()
319 [aSubview setFrame:targetFrame];
321 CPLog.debug(aSubview + " setFrame: " + CPStringFromRect(targetFrame));
323 if (idx == count - 1)
324 [animatorClass stopUpdaterWithIdentifier:[anAction.root UID]];
328 var animate = !needsPeriodicFrameUpdates;
334 - (Object)actionFromAction:(Object)anAction forAnimatedSubview:(
CPView)aView
336 var targetValue = [anAction.values lastObject],
337 startFrame = [aView
frame],
341 if (anAction.keypath ==
"frame")
342 targetValue = targetValue.size;
345 values = [startFrame, endFrame];
353 duration:anAction.duration,
354 timingfunctions:anAction.timingfunctions
358 - (void)setCompletionHandler:(Function)aCompletionHandler
360 if (_completionHandlerAgent)
362 if (aCompletionHandler === _completionHandlerAgent._completionHandler)
365 _completionHandlerAgent.invalidate();
368 if (aCompletionHandler)
372 CPLog.debug(
"created a new completion Agent with id " + _completionHandlerAgent.id);
377 _completionHandlerAgent = nil;
383 if (!_completionHandlerAgent)
386 return _completionHandlerAgent.completionHandler();
393 - (CGRect)frameRectOfView:(
CPView)aView inSuperviewSize:(CGSize)aSize
398 - (CGRect)frameWithNewSuperviewSize:(CGSize)newSize
405 var oldSize = _superview._frame.size,
406 newFrame = CGRectMakeCopy(_frame),
407 dX = newSize.width - oldSize.width,
408 dY = newSize.height - oldSize.height,
413 (mask &
CPViewMaxXMargin ? oldSize.width - _frame.size.width - _frame.origin.x : 0),
416 (mask &
CPViewMaxYMargin ? oldSize.height - _frame.size.height - _frame.origin.y : 0);
420 newFrame.origin.x += dX * (baseX > 0 ? _frame.origin.x / baseX : evenFractionX);
422 newFrame.size.width += dX * (baseX > 0 ? _frame.size.width / baseX : evenFractionX);
425 newFrame.origin.y += dY * (baseY > 0 ? _frame.origin.y / baseY : evenFractionY);
427 newFrame.size.height += dY * (baseY > 0 ? _frame.size.height / baseY : evenFractionY);
432 - (BOOL)hasCustomDrawRect
434 return self._viewClassFlags & 1;
437 - (BOOL)hasCustomLayoutSubviews
439 return self._viewClassFlags & 2;
446 - (CPArray)controlPoints
448 return [_c1x, _c1y, _c2x, _c2y];
455 - (CPArray)timingFunctionControlPoints
458 return [_timingFunction controlPoints];
467 - (CPArray)timingFunctionsControlPoints
469 var result = [CPArray array];
471 [_timingFunctions enumerateObjectsUsingBlock:function(timingFunction, idx)
485 this._completionHandler = aCompletionHandler;
488 this.
id = COMPLETION_AGENT_ID++;
493 return this._completionHandler;
500 this._completionHandler();
518 if (this.valid && this.total == 0)
524 CompletionHandlerAgent.prototype.invalidate =
function()
528 this._completionHandler = null;
531 var _animationFlushingObserverCallback =
function()
534 CPLog.debug(
"_animationFlushingObserverCallback");
536 if ([_CPAnimationContextStack count] == 1)
538 var context = [_CPAnimationContextStack lastObject];
539 [context _flushAnimations];
540 [_CPAnimationContextStack removeLastObject];
544 CPLog.debug(
"_animationFlushingObserver "+_animationFlushingObserver+
" stack:" + [_CPAnimationContextStack count]);
547 if (_animationFlushingObserver && ![_CPAnimationContextStack count])
550 CPLog.debug(
"removeObserver");
553 _animationFlushingObserver = nil;
570 - (void)setDuration:(
double)aValue
580 return _timingFunction;
588 _timingFunction = aValue;
function CFRunLoopAddObserver(runloop, observer, mode)
function CFRunLoopObserverInvalidate(runloop, observer, mode)
var CompletionHandlerAgent
The main run loop for the application.
CPRunLoop currentRunLoop()
void getAnimations:getTimers:usingAction:cssAnimate:(CPArray cssAnimations, [getTimers] CPArray timers, [usingAction] Object anAction, [cssAnimate] BOOL needsCSSAnimation)
An immutable string (collection of characters).
CGRect frameRectOfView:inSuperviewSize:(CPView aView, [inSuperviewSize] CGSize aSize)
global appkit_tag_dom_elements typedef _CPViewFullScreenModeState CPViewNotSizable
CAMediaTimingFunction timingFunction()
CGRect frameWithNewSuperviewSize:(CGSize newSize)
CompletionHandlerAgent prototype completionHandler
FrameUpdater prototype start
Object actionFromAction:forAnimatedSubview:(Object anAction, [forAnimatedSubview] CPView aView)
unsigned autoresizingMask()
CompletionHandlerAgent prototype fire
function CFRunLoopObserverCreate(activities, repeats, order, callout, context)
FrameUpdater prototype description