Fixed: CPViewAnimator was not giving correct frame information (#2502)

Fixed: When only animating frameSize, there’s no matrix defined. This is now
correctly handled.
New: The animator can explicitly request frames updates when the frameOrigin 
keyPath changes with the new method [animator setWantsPeriodicFramesUpdates:YES]
This commit is contained in:
Didier Korthoudt authored and cacaodev committed 2016-11-07 22:20:55 +01:00
1 parent ef1d6c78ac
commit eeea21c882
3 files changed
+114 -64

No files matched your search

+13 -5
View File
@@ -252,6 +252,8 @@ var CPViewHighDPIDrawingEnabled = YES;
id _animator;
CPDictionary _animationsDictionary;
BOOL _inhibitDOMUpdates @accessors(setter=_setInhibitDOMUpdates);
BOOL _forceUpdates @accessors(setter=_setForceUpdates);
}
/*
@@ -404,6 +406,9 @@ var CPViewHighDPIDrawingEnabled = YES;
[self _setupViewFlags];
[self _loadThemeAttributes];
_inhibitDOMUpdates = NO;
_forceUpdates = NO;
}
return self;
@@ -1013,7 +1018,7 @@ var CPViewHighDPIDrawingEnabled = YES;
*/
- (void)setFrame:(CGRect)aFrame
{
if (CGRectEqualToRect(_frame, aFrame))
if (CGRectEqualToRect(_frame, aFrame) && !_forceUpdates)
return;
_inhibitFrameAndBoundsChangedNotifications = YES;
@@ -1084,7 +1089,7 @@ var CPViewHighDPIDrawingEnabled = YES;
{
var origin = _frame.origin;
if (!aPoint || CGPointEqualToPoint(origin, aPoint))
if (!aPoint || (CGPointEqualToPoint(origin, aPoint) && !_forceUpdates))
return;
origin.x = aPoint.x;
@@ -1097,9 +1102,12 @@ var CPViewHighDPIDrawingEnabled = YES;
[[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]];
#if PLATFORM(DOM)
var transform = _superview ? _superview._boundsTransform : NULL;
if (!_inhibitDOMUpdates)
{
var transform = _superview ? _superview._boundsTransform : NULL;
CPDOMDisplayServerSetStyleLeftTop(_DOMElement, transform, origin.x, origin.y);
CPDOMDisplayServerSetStyleLeftTop(_DOMElement, transform, origin.x, origin.y);
}
#endif
if (!_inhibitUpdateTrackingAreas && !_inhibitFrameAndBoundsChangedNotifications)
@@ -1116,7 +1124,7 @@ var CPViewHighDPIDrawingEnabled = YES;
{
var size = _frame.size;
if (!aSize || CGSizeEqualToSize(size, aSize))
if (!aSize || (CGSizeEqualToSize(size, aSize) && !_forceUpdates))
return;
var oldSize = CGSizeMakeCopy(size);
+62 -40
View File
@@ -152,24 +152,32 @@ CPLog.debug(_cmd + "context stack =" + _CPAnimationContextStack);
duration = [animation duration] || [self duration];
var needsFrameTimer = (aKeyPath == @"frame" || aKeyPath == @"frameSize") &&
([anObject hasCustomLayoutSubviews] || [anObject hasCustomDrawRect]) &&
(objectId = [anObject UID]);
var needsPeriodicFrameUpdates = (((aKeyPath == @"frame" || aKeyPath == @"frameSize") &&
([anObject hasCustomLayoutSubviews] || [anObject hasCustomDrawRect])) || [[anObject animator] wantsPeriodicFrameUpdates]) &&
(objectId = [anObject UID]);
if (_completionHandlerAgent)
_completionHandlerAgent.increment();
var completionFunction = function()
{
if (needsFrameTimer)
if (needsPeriodicFrameUpdates)
{
[self stopFrameUpdaterWithIdentifier:objectId];
if ([anObject respondsToSelector:@selector(_setForceUpdates:)])
[anObject _setForceUpdates:YES];
}
if (animationCompletion)
animationCompletion();
if (needsFrameTimer || animationCompletion)
if (needsPeriodicFrameUpdates || animationCompletion)
[[CPRunLoop currentRunLoop] performSelectors];
if (needsPeriodicFrameUpdates && [anObject respondsToSelector:@selector(_setForceUpdates:)])
[anObject _setForceUpdates:NO];
if (_completionHandlerAgent)
_completionHandlerAgent.decrement();
};
@@ -266,7 +274,7 @@ CPLog.debug(_cmd + "context stack =" + _CPAnimationContextStack);
isFrameKeyPath = (keyPath == @"frame" || keyPath == @"frameSize"),
customLayout = [aTargetView hasCustomLayoutSubviews],
customDrawing = [aTargetView hasCustomDrawRect],
needsFrameTimer = isFrameKeyPath && (customLayout || customDrawing);
needsPeriodicFrameUpdates = ((isFrameKeyPath && (customLayout || customDrawing)) || [[aTargetView animator] wantsPeriodicFrameUpdates]);
if (needsCSSAnimation)
{
@@ -305,7 +313,7 @@ CPLog.debug(_cmd + "context stack =" + _CPAnimationContextStack);
}];
}
if (needsFrameTimer)
if (needsPeriodicFrameUpdates)
{
var timer = [self addFrameUpdaterWithIdentifier:[rootView UID] forView:aTargetView keyPath:keyPath duration:anAction.duration];
@@ -314,35 +322,36 @@ CPLog.debug(_cmd + "context stack =" + _CPAnimationContextStack);
}
var subviews = [aTargetView subviews],
count = [subviews count];
count = [subviews count],
customLayout = [aTargetView hasCustomLayoutSubviews];
if (count && isFrameKeyPath)
{
var frameTimerId = [rootView UID],
lastIndex = count - 1;
lastIndex = count - 1;
[subviews enumerateObjectsUsingBlock:function(aSubview, idx, stop)
{
var action = [self actionFromAction:anAction forAnimatedSubview:aSubview],
{
var action = [self actionFromAction:anAction forAnimatedSubview:aSubview],
targetFrame = [action.values lastObject];
if (CGRectEqualToRect([aSubview frame], targetFrame))
return;
if (CGRectEqualToRect([aSubview frame], targetFrame))
return;
if ([aSubview hasCustomDrawRect])
{
action.completion = function()
{
[aSubview setFrame:targetFrame];
CPLog.debug(aSubview + " setFrame: ");
if ([aSubview hasCustomDrawRect])
{
action.completion = function()
{
[aSubview setFrame:targetFrame];
CPLog.debug(aSubview + " setFrame: ");
if (idx == lastIndex)
[self stopFrameUpdaterWithIdentifier:frameTimerId];
};
}
if (idx == lastIndex)
[self stopFrameUpdaterWithIdentifier:frameTimerId];
};
}
[self getAnimations:cssAnimations getTimers:timers forView:aSubview usingAction:action rootView:rootView cssAnimate:!customLayout];
}];
[self getAnimations:cssAnimations getTimers:timers forView:aSubview usingAction:action rootView:rootView cssAnimate:!customLayout];
}];
}
}
@@ -422,6 +431,7 @@ CPLog.debug(_cmd + "context stack =" + _CPAnimationContextStack);
{
var mask = [self autoresizingMask];
if (mask == CPViewNotSizable)
return _frame;
@@ -674,31 +684,43 @@ FrameUpdater.prototype.addTarget = function(target, keyPath, duration)
var createUpdateFrame = function(aView, aKeyPath)
{
if (aKeyPath !== "frame" && aKeyPath !== "frameSize")
if (aKeyPath !== "frame" && aKeyPath !== "frameSize" && aKeyPath !== "frameOrigin")
return nil;
var style = getComputedStyle(aView._DOMElement),
getCSSPropertyValue = function(prop) {
return ROUND(parseFloat(style.getPropertyValue(prop)));
};
var updateFrame = function(timestamp)
getCSSPropertyValue = function(prop) {
return ROUND(parseFloat(style.getPropertyValue(prop)));
},
initialOrigin = CGPointMakeCopy([aView frameOrigin]),
transformProperty = CPBrowserCSSProperty("transform"),
updateFrame = function(timestamp)
{
var width = getCSSPropertyValue("width"),
height = getCSSPropertyValue("height");
if (aKeyPath == "frame")
{
var left = getCSSPropertyValue("left"),
top = getCSSPropertyValue("top"),
frame = CGRectMake(left, top, width, height);
[aView setFrame:frame];
}
else if (aKeyPath == "frameSize")
if (aKeyPath === "frameSize")
{
[aView setFrameSize:CGSizeMake(width, height)];
}
else
{
[aView _setInhibitDOMUpdates:YES];
var matrix = style[transformProperty].split('(')[1].split(')')[0].split(','),
x = ROUND(initialOrigin.x + parseFloat(matrix[4])),
y = ROUND(initialOrigin.y + parseFloat(matrix[5]));
if (aKeyPath === "frame")
{
[aView setFrame:CGRectMake(x, y, width, height)];
}
else
{
[aView setFrameOrigin:CGPointMake(x, y)];
}
[aView _setInhibitDOMUpdates:NO];
}
[[CPRunLoop currentRunLoop] performSelectors];
};
+39 -19
View File
@@ -1,9 +1,20 @@
@import "_CPObjectAnimator.j"
@import "CPView.j"
@import "CPCompatibility.j"
@implementation CPViewAnimator : _CPObjectAnimator
{
BOOL _wantsPeriodicFrameUpdates @accessors(property=wantsPeriodicFrameUpdates);
}
- (id)initWithTarget:(id)aTarget
{
self = [super initWithTarget:aTarget];
_wantsPeriodicFrameUpdates = NO;
return self;
}
- (void)removeFromSuperview
@@ -76,16 +87,6 @@
@end
var transformOrigin = function(start, current)
{
return "translate(" + (current.x - start.x) + "px," + (current.y - start.y) + "px)";
};
var transformFrameToTranslate = function(start, current)
{
return transformOrigin(start.origin, current.origin);
};
var transformFrameToWidth = function(start, current)
{
return current.size.width + "px";
@@ -106,6 +107,25 @@ var transformSizeToHeight = function(start, current)
return current.height + "px";
};
var CSSStringFromCGAffineTransform = function(anAffineTransform)
{
return "matrix(" + anAffineTransform.a + ", " + anAffineTransform.b + ", " + anAffineTransform.c + ", " + anAffineTransform.d + ", " + anAffineTransform.tx + (CPBrowserIsEngine(CPGeckoBrowserEngine) ? "px, " : ", ") + anAffineTransform.ty + (CPBrowserIsEngine(CPGeckoBrowserEngine) ? "px)" : ")");
};
var frameOriginToCSSTransformMatrix = function(start, current)
{
var affine = CGAffineTransformMakeTranslation(current.x - start.x, current.y - start.y);
return CSSStringFromCGAffineTransform(affine);
};
var frameToCSSTranslationTransformMatrix = function(start, current)
{
var affine = CGAffineTransformMakeTranslation(current.origin.x - start.origin.x, current.origin.y - start.origin.y);
return CSSStringFromCGAffineTransform(affine);
};
var DEFAULT_CSS_PROPERTIES = nil;
@implementation CPView (CPAnimatablePropertyContainer)
@@ -117,15 +137,15 @@ var DEFAULT_CSS_PROPERTIES = nil;
var transformProperty = CPBrowserCSSProperty("transform");
DEFAULT_CSS_PROPERTIES = @{
"backgroundColor" : [@{"property":"background", "value":function(sv, val){return [val cssString];}}],
"alphaValue" : [@{"property":"opacity"}],
"frame" : [@{"property":transformProperty, "value":transformFrameToTranslate},
@{"property":"width", "value":transformFrameToWidth},
@{"property":"height", "value":transformFrameToHeight}],
"frameOrigin" : [@{"property":transformProperty, "value":transformOrigin}],
"frameSize" : [@{"property":"width", "value":transformSizeToWidth},
@{"property":"height", "value":transformSizeToHeight}]
};
"backgroundColor" : [@{"property":"background", "value":function(sv, val){return [val cssString];}}],
"alphaValue" : [@{"property":"opacity"}],
"frame" : [@{"property":transformProperty, "value":frameToCSSTranslationTransformMatrix},
@{"property":"width", "value":transformFrameToWidth},
@{"property":"height", "value":transformFrameToHeight}],
"frameOrigin" : [@{"property":transformProperty, "value":frameOriginToCSSTransformMatrix}],
"frameSize" : [@{"property":"width", "value":transformSizeToWidth},
@{"property":"height", "value":transformSizeToHeight}]
};
}
return DEFAULT_CSS_PROPERTIES;