Commit a340744f authored by Marcin Wiacek's avatar Marcin Wiacek Committed by Commit Bot

Migrate StackLayoutBase (migration to CompositorAnimator, part 3)

This is part of changes which put as goal removing redundant ChromeAnimation API by moving everything into CompositorAnimator.

Public doc with proposal: https://docs.google.com/document/d/1VL5ntE7vn267IFjE4Zke0GkhVVTHz1bEP672Apj_E2k/edit

This concrete patch is migrating StackLayoutBase.

BUG=890643

Change-Id: I66668b9373c54fc9573de8d797990b6e291f2b54
Reviewed-on: https://chromium-review.googlesource.com/c/1376851Reviewed-by: default avatarChangwan Ryu <changwan@chromium.org>
Commit-Queue: Marcin Wiącek <marcin@mwiacek.com>
Cr-Commit-Position: refs/heads/master@{#619739}
parent a75f00e5
......@@ -45,6 +45,8 @@ public class CompositorAnimator extends Animator {
/** The list of frame update listeners for this animation. */
private final ArrayList<AnimatorUpdateListener> mAnimatorUpdateListeners = new ArrayList<>();
private FloatProperty mFloatProperty;
/**
* A cached copy of the list of {@link AnimatorUpdateListener}s to prevent allocating a new list
* every update.
......@@ -135,6 +137,7 @@ public class CompositorAnimator extends Animator {
animator.setDuration(durationMs);
animator.addUpdateListener(
(CompositorAnimator a) -> property.setValue(target, a.getAnimatedValue()));
animator.setFloatProperty(property);
animator.setInterpolator(interpolator);
return animator;
}
......@@ -229,6 +232,17 @@ public class CompositorAnimator extends Animator {
mAnimatorUpdateListeners.add(listener);
}
private void setFloatProperty(FloatProperty property) {
mFloatProperty = property;
}
/**
* @return Whether this animation is of the given FloatProperty.
*/
public boolean isOfFloatProperty(FloatProperty property) {
return mFloatProperty == property;
}
/**
* @return Whether or not the animation has ended after being started. If the animation is
* started after ending, this value will be reset to true.
......@@ -270,6 +284,7 @@ public class CompositorAnimator extends Animator {
public void removeAllListeners() {
mListeners.clear();
mAnimatorUpdateListeners.clear();
mFloatProperty = null;
}
@Override
......
......@@ -4,8 +4,8 @@
package org.chromium.chrome.browser.compositor.layouts.phone;
import static org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.AnimatableAnimation.createAnimation;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.RectF;
......@@ -22,8 +22,7 @@ import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.compositor.LayerTitleCache;
import org.chromium.chrome.browser.compositor.animation.CompositorAnimator;
import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation;
import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Animatable;
import org.chromium.chrome.browser.compositor.animation.FloatProperty;
import org.chromium.chrome.browser.compositor.layouts.Layout;
import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
......@@ -63,14 +62,45 @@ import java.util.List;
/**
* Base class for layouts that show one or more stacks of tabs.
*/
public abstract class StackLayoutBase extends Layout implements Animatable {
@IntDef({Property.INNER_MARGIN_PERCENT, Property.STACK_SNAP, Property.STACK_OFFSET_Y_PERCENT})
@Retention(RetentionPolicy.SOURCE)
public @interface Property {
int INNER_MARGIN_PERCENT = 0;
int STACK_SNAP = 1;
int STACK_OFFSET_Y_PERCENT = 2;
}
public abstract class StackLayoutBase extends Layout {
private static final FloatProperty<StackLayoutBase> INNER_MARGIN_PERCENT =
new FloatProperty<StackLayoutBase>("") {
@Override
public void setValue(StackLayoutBase layoutBase, float v) {
layoutBase.setInnerMarginPercent(v);
}
@Override
public Float get(StackLayoutBase layoutTab) {
return null;
}
};
private static final FloatProperty<StackLayoutBase> STACK_OFFSET_Y_PERCENT =
new FloatProperty<StackLayoutBase>("") {
@Override
public void setValue(StackLayoutBase layoutBase, float v) {
layoutBase.setStackOffsetYPercent(v);
}
@Override
public Float get(StackLayoutBase layoutTab) {
return null;
}
};
private static final FloatProperty<StackLayoutBase> STACK_SNAP =
new FloatProperty<StackLayoutBase>("") {
@Override
public void setValue(StackLayoutBase layoutBase, float v) {
layoutBase.setStackSnap(v);
}
@Override
public Float get(StackLayoutBase layoutTab) {
return null;
}
};
@IntDef({DragDirection.NONE, DragDirection.HORIZONTAL, DragDirection.VERTICAL})
@Retention(RetentionPolicy.SOURCE)
......@@ -194,7 +224,7 @@ public abstract class StackLayoutBase extends Layout implements Animatable {
private StackLayoutGestureHandler mGestureHandler;
private ChromeAnimation<Animatable> mLayoutAnimations;
private AnimatorSet mLayoutAnimations;
private class StackLayoutGestureHandler implements GestureHandler {
@Override
......@@ -348,6 +378,34 @@ public abstract class StackLayoutBase extends Layout implements Animatable {
mSceneLayer = new TabListSceneLayer();
}
/**
* Sets the stack offset percent for vertical axis.
*
* @param v Value to set.
*/
public void setStackOffsetYPercent(float v) {
mStackOffsetYPercent = v;
}
/**
* Sets the inner margin percent.
*
* @param v Value to set.
*/
public void setInnerMarginPercent(float v) {
mInnerMarginPercent = v;
}
/**
* Sets the stack stap value.
*
* @param v Value to set.
*/
public void setStackSnap(float v) {
mRenderedScrollOffset = v;
mScrollIndexOffset = v;
}
/**
* Whether or not the HorizontalTabSwitcherAndroid flag (which enables the new horizontal tab
* switcher in both portrait and landscape mode) is enabled.
......@@ -648,10 +706,9 @@ public abstract class StackLayoutBase extends Layout implements Animatable {
boolean animationsWasDone = true;
if (mLayoutAnimations != null) {
if (jumpToEnd) {
animationsWasDone = mLayoutAnimations.finished();
mLayoutAnimations.updateAndFinish();
mLayoutAnimations.end();
} else {
animationsWasDone = mLayoutAnimations.update(time);
animationsWasDone = !mLayoutAnimations.isRunning();
}
if (animationsWasDone || jumpToEnd) {
......@@ -775,23 +832,23 @@ public abstract class StackLayoutBase extends Layout implements Animatable {
protected void startMarginAnimation(boolean enter, boolean showMargin) {
// Any outstanding animations must be cancelled to avoid race condition.
cancelAnimation(this, Property.INNER_MARGIN_PERCENT);
cancelAnimation(INNER_MARGIN_PERCENT);
float start = mInnerMarginPercent;
float end = enter && showMargin ? 1.0f : 0.0f;
if (start != end) {
addToAnimation(this, Property.INNER_MARGIN_PERCENT, start, end, 200, 0);
addToAnimation(INNER_MARGIN_PERCENT, start, end, 200, 0);
}
}
private void startYOffsetAnimation(boolean enter) {
// Any outstanding animations must be cancelled to avoid race condition.
cancelAnimation(this, Property.STACK_OFFSET_Y_PERCENT);
cancelAnimation(STACK_OFFSET_Y_PERCENT);
float start = mStackOffsetYPercent;
float end = enter ? 1.f : 0.f;
if (start != end) {
addToAnimation(this, Property.STACK_OFFSET_Y_PERCENT, start, end, 300, 0);
addToAnimation(STACK_OFFSET_Y_PERCENT, start, end, 300, 0);
}
}
......@@ -1132,7 +1189,7 @@ public abstract class StackLayoutBase extends Layout implements Animatable {
* @param delta The amount to scroll by.
*/
private void scrollStacks(float delta) {
cancelAnimation(this, Property.STACK_SNAP);
cancelAnimation(STACK_SNAP);
float fullDistance = getFullScrollDistance();
mScrollIndexOffset += MathUtils.flipSignIf(delta / fullDistance,
!isUsingHorizontalLayout() && LocalizationUtils.isLayoutRtl());
......@@ -1160,16 +1217,16 @@ public abstract class StackLayoutBase extends Layout implements Animatable {
* incognito to non-incognito, which leaves the up event in the incognito side.
*/
private void finishScrollStacks() {
cancelAnimation(this, Property.STACK_SNAP);
cancelAnimation(STACK_SNAP);
final int currentModelIndex = getTabStackIndex();
float delta = Math.abs(currentModelIndex + mRenderedScrollOffset);
float target = -currentModelIndex;
if (delta != 0) {
long duration = FLING_MIN_DURATION
+ (long) Math.abs(delta * getFullScrollDistance() / mFlingSpeed);
addToAnimation(this, Property.STACK_SNAP, mRenderedScrollOffset, target, duration, 0);
addToAnimation(STACK_SNAP, mRenderedScrollOffset, target, duration, 0);
} else {
setProperty(Property.STACK_SNAP, target);
setStackSnap(target);
onAnimationFinished();
}
}
......@@ -1487,30 +1544,6 @@ public abstract class StackLayoutBase extends Layout implements Animatable {
return false;
}
/**
* Sets properties for animations.
* @param prop The property to update
* @param p New value of the property
*/
@Override
public void setProperty(@Property int prop, float p) {
switch (prop) {
case Property.STACK_SNAP:
mRenderedScrollOffset = p;
mScrollIndexOffset = p;
break;
case Property.INNER_MARGIN_PERCENT:
mInnerMarginPercent = p;
break;
case Property.STACK_OFFSET_Y_PERCENT:
mStackOffsetYPercent = p;
break;
}
}
@Override
public void onPropertyAnimationFinished(@Property int prop) {}
/**
* Called by the stacks whenever they start an animation.
*/
......@@ -1548,20 +1581,20 @@ public abstract class StackLayoutBase extends Layout implements Animatable {
}
/**
* Creates an {@link org.chromium.chrome.browser.compositor.layouts.ChromeAnimation
* .AnimatableAnimation} and adds it to the animation.
* Creates an {@link CompositorAnimator} and adds it to the animation.
* Automatically sets the start value at the beginning of the animation.
*/
protected void addToAnimation(
Animatable object, int prop, float start, float end, long duration, long startTime) {
ChromeAnimation.Animation<Animatable> component = createAnimation(object, prop, start, end,
duration, startTime, false, CompositorAnimator.DECELERATE_INTERPOLATOR);
if (mLayoutAnimations == null || mLayoutAnimations.finished()) {
mLayoutAnimations = new ChromeAnimation<Animatable>();
mLayoutAnimations.start();
}
component.start();
mLayoutAnimations.add(component);
protected void addToAnimation(FloatProperty<StackLayoutBase> property, float start, float end,
long duration, long startTime) {
if (mLayoutAnimations == null) mLayoutAnimations = new AnimatorSet();
CompositorAnimator compositorAnimator = CompositorAnimator.ofFloatProperty(
getAnimationHandler(), this, property, start, end, duration);
compositorAnimator.setStartDelay(startTime);
mLayoutAnimations.playTogether(compositorAnimator);
mLayoutAnimations.start();
requestUpdate();
}
......@@ -1569,7 +1602,7 @@ public abstract class StackLayoutBase extends Layout implements Animatable {
protected void forceAnimationToFinish() {
super.forceAnimationToFinish();
if (mLayoutAnimations != null) {
mLayoutAnimations.updateAndFinish();
mLayoutAnimations.end();
mLayoutAnimations = null;
}
}
......@@ -1579,13 +1612,18 @@ public abstract class StackLayoutBase extends Layout implements Animatable {
* @param object The object being animated.
* @param prop The property to search for.
*/
protected void cancelAnimation(Animatable object, int prop) {
if (mLayoutAnimations != null) mLayoutAnimations.cancel(object, prop);
protected void cancelAnimation(FloatProperty<StackLayoutBase> property) {
if (mLayoutAnimations == null) return;
for (Animator animator : mLayoutAnimations.getChildAnimations()) {
CompositorAnimator a = (CompositorAnimator) animator;
if (a.isOfFloatProperty(property)) a.cancel();
}
}
@Override
@VisibleForTesting
public boolean isLayoutAnimating() {
return mLayoutAnimations != null && !mLayoutAnimations.finished();
return mLayoutAnimations != null && mLayoutAnimations.isRunning();
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment