Commit 3c6f36d9 authored by Matthew Jones's avatar Matthew Jones Committed by Commit Bot

Replace instances of ChromeAnimation in StripLayoutHelper

This change replaces the usages of ChromeAnimation in the tablet tab
strip. Several properties have been added to facilitate animation and
much of the logic has been simplified. Particularly, onUpdateAnimation
has been removed since most of the logic depending on its param
'jumpToEnd' (which was always false) was unused.

BUG=750381

Change-Id: If5c2346545254917cf690f4e5ddbb76a7dde3239
Reviewed-on: https://chromium-review.googlesource.com/791471Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Commit-Queue: Matthew Jones <mdjones@chromium.org>
Cr-Commit-Position: refs/heads/master@{#519853}
parent 1f93c87b
......@@ -4,8 +4,9 @@
package org.chromium.chrome.browser.compositor.overlays.strip;
import static org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.AnimatableAnimation.createAnimation;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
......@@ -24,9 +25,7 @@ import android.widget.ListPopupWindow;
import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation;
import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Animatable;
import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Animation;
import org.chromium.chrome.browser.compositor.animation.CompositorAnimator;
import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost;
import org.chromium.chrome.browser.compositor.layouts.components.CompositorButton;
......@@ -110,7 +109,7 @@ public class StripLayoutHelper implements StripLayoutTab.StripLayoutTabDelegate
private StripLayoutTab[] mStripTabsToRender = new StripLayoutTab[0];
private final StripTabEventHandler mStripTabEventHandler = new StripTabEventHandler();
private final TabLoadTrackerCallback mTabLoadTrackerHost = new TabLoadTrackerCallbackImpl();
private ChromeAnimation<Animatable<?>> mLayoutAnimations;
private Animator mRunningAnimator;
private final CompositorButton mNewTabButton;
......@@ -440,7 +439,16 @@ public class StripLayoutHelper implements StripLayoutTab.StripLayoutTabDelegate
* @return Whether or not animations are done.
*/
public boolean updateLayout(long time, long dt) {
final boolean doneAnimating = onUpdateAnimation(time, false);
// 1. Handle any Scroller movements (flings).
updateScrollOffset(time);
// 2. Handle reordering automatically scrolling the tab strip.
handleReorderAutoScrolling(time);
// 3. Update tab spinners.
updateSpinners(time);
final boolean doneAnimating = mRunningAnimator == null || !mRunningAnimator.isRunning();
updateStrip();
// If this is the first layout pass, scroll to the selected tab so that it is visible.
......@@ -548,7 +556,12 @@ public class StripLayoutHelper implements StripLayoutTab.StripLayoutTabDelegate
// 2. Start an animation for the newly created tab.
StripLayoutTab tab = findTabById(id);
if (tab != null) startAnimation(buildTabCreatedAnimation(tab), true);
if (tab != null) {
finishAnimation();
mRunningAnimator = CompositorAnimator.ofFloatProperty(mUpdateHost.getAnimationHandler(),
tab, StripLayoutTab.Y_OFFSET, tab.getHeight(), 0f, ANIM_TAB_CREATED_MS);
mRunningAnimator.start();
}
// 3. Figure out which tab needs to be visible.
StripLayoutTab fastExpandTab = findTabById(prevId);
......@@ -818,11 +831,29 @@ public class StripLayoutHelper implements StripLayoutTab.StripLayoutTabDelegate
}
@Override
public void handleCloseButtonClick(StripLayoutTab tab, long time) {
public void handleCloseButtonClick(final StripLayoutTab tab, long time) {
if (tab == null || tab.isDying()) return;
// 1. Start the close animation.
startAnimation(buildTabClosedAnimation(tab), true);
finishAnimation();
mRunningAnimator = CompositorAnimator.ofFloatProperty(mUpdateHost.getAnimationHandler(),
tab, StripLayoutTab.Y_OFFSET, tab.getOffsetY(), tab.getHeight(),
ANIM_TAB_CLOSED_MS);
mRunningAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// Find out if we're closing the last tab. This determines if we resize
// immediately.
boolean lastTab = mStripTabs.length == 0
|| mStripTabs[mStripTabs.length - 1].getId() == tab.getId();
// Resize the tabs appropriately.
resizeTabStrip(!lastTab);
}
});
mRunningAnimator.start();
// 2. Set the dying state of the tab.
tab.setIsDying(true);
......@@ -830,13 +861,6 @@ public class StripLayoutHelper implements StripLayoutTab.StripLayoutTabDelegate
// 3. Fake a selection on the next tab now.
Tab nextTab = mModel.getNextTabIfClosed(tab.getId());
if (nextTab != null) tabSelected(time, nextTab.getId(), tab.getId());
// 4. Find out if we're closing the last tab. This determines if we resize immediately.
boolean lastTab =
mStripTabs.length == 0 || mStripTabs[mStripTabs.length - 1].getId() == tab.getId();
// 5. Resize the tabs appropriately.
resizeTabStrip(!lastTab);
}
@Override
......@@ -894,50 +918,13 @@ public class StripLayoutHelper implements StripLayoutTab.StripLayoutTabDelegate
}
}
private boolean onUpdateAnimation(long time, boolean jumpToEnd) {
// 1. Handle any Scroller movements (flings).
if (!jumpToEnd) updateScrollOffset(time);
// 2. Handle reordering automatically scrolling the tab strip.
handleReorderAutoScrolling(time);
// 3. Handle layout-wide animations.
boolean update = false;
boolean finished = true;
if (mLayoutAnimations != null) {
if (jumpToEnd) {
finished = mLayoutAnimations.finished();
} else {
finished = mLayoutAnimations.update(time);
}
if (jumpToEnd || finished) finishAnimation();
update = true;
}
// 4. Handle tab-specific content animations.
for (int i = 0; i < mStripTabs.length; i++) {
if (jumpToEnd) mStripTabs[i].finishAnimation();
}
// 5. Update tab spinners.
updateSpinners(time);
// 6. Stop any flings if we're trying to stop animations.
if (jumpToEnd) mScroller.forceFinished(true);
// 7. Request another update if anything requires it.
if (update) mUpdateHost.requestUpdate();
return finished;
}
/**
* @return Whether or not the tabs are moving.
*/
@VisibleForTesting
public boolean isAnimating() {
return mLayoutAnimations != null || !mScroller.isFinished();
return (mRunningAnimator != null && mRunningAnimator.isRunning())
|| !mScroller.isFinished();
}
/**
......@@ -945,11 +932,11 @@ public class StripLayoutHelper implements StripLayoutTab.StripLayoutTabDelegate
* {@link TabModel}.
*/
public void finishAnimation() {
if (mLayoutAnimations == null) return;
if (mRunningAnimator == null) return;
// 1. Force any outstanding animations to finish.
mLayoutAnimations.updateAndFinish();
mLayoutAnimations = null;
mRunningAnimator.end();
mRunningAnimator = null;
// 2. Figure out which tabs need to be closed.
ArrayList<StripLayoutTab> tabsToRemove = new ArrayList<StripLayoutTab>();
......@@ -966,23 +953,6 @@ public class StripLayoutHelper implements StripLayoutTab.StripLayoutTabDelegate
if (!tabsToRemove.isEmpty()) mUpdateHost.requestUpdate();
}
private void startAnimation(Animation<Animatable<?>> animation, boolean finishPrevious) {
if (finishPrevious) finishAnimation();
if (mLayoutAnimations == null) {
mLayoutAnimations = new ChromeAnimation<ChromeAnimation.Animatable<?>>();
}
mLayoutAnimations.add(animation);
mUpdateHost.requestUpdate();
}
private void cancelAnimation(StripLayoutTab tab, StripLayoutTab.Property property) {
if (mLayoutAnimations == null) return;
mLayoutAnimations.cancel(tab, property);
}
private void updateSpinners(long time) {
long diff = time - mLastSpinnerUpdate;
float degrees = diff * SPINNER_DPMS;
......@@ -1138,20 +1108,31 @@ public class StripLayoutHelper implements StripLayoutTab.StripLayoutTabDelegate
// 4. Calculate the realistic tab width.
mCachedTabWidth = MathUtils.clamp(optimalTabWidth, mMinTabWidth, mMaxTabWidth);
// 5. Propagate the tab width to all tabs.
// 5. Prepare animations and propagate width to all tabs.
finishAnimation();
ArrayList<Animator> resizeAnimationList = null;
if (animate && !mAnimationsDisabledForTesting) resizeAnimationList = new ArrayList<>();
for (int i = 0; i < mStripTabs.length; i++) {
StripLayoutTab tab = mStripTabs[i];
if (tab.isDying()) continue;
// 5.a. Cancel any outstanding tab width animations.
cancelAnimation(mStripTabs[i], StripLayoutTab.Property.WIDTH);
if (animate && !mAnimationsDisabledForTesting) {
startAnimation(buildTabResizeAnimation(tab, mCachedTabWidth), false);
if (resizeAnimationList != null) {
CompositorAnimator animator = CompositorAnimator.ofFloatProperty(
mUpdateHost.getAnimationHandler(), tab, StripLayoutTab.WIDTH,
tab.getWidth(), mCachedTabWidth, ANIM_TAB_RESIZE_MS);
resizeAnimationList.add(animator);
} else {
mStripTabs[i].setWidth(mCachedTabWidth);
}
}
if (resizeAnimationList != null) {
AnimatorSet set = new AnimatorSet();
set.playTogether(resizeAnimationList);
mRunningAnimator = set;
mRunningAnimator.start();
}
}
private void updateStrip() {
......@@ -1377,7 +1358,11 @@ public class StripLayoutHelper implements StripLayoutTab.StripLayoutTabDelegate
mInReorderMode = false;
// 2. Clear any drag offset.
startAnimation(buildTabMoveAnimation(mInteractingTab, mInteractingTab.getOffsetX()), true);
finishAnimation();
mRunningAnimator = CompositorAnimator.ofFloatProperty(mUpdateHost.getAnimationHandler(),
mInteractingTab, StripLayoutTab.X_OFFSET, mInteractingTab.getOffsetX(), 0f,
ANIM_TAB_MOVE_MS);
mRunningAnimator.start();
// 3. Request an update.
mUpdateHost.requestUpdate();
......@@ -1471,7 +1456,11 @@ public class StripLayoutHelper implements StripLayoutTab.StripLayoutTabDelegate
final float animationLength =
MathUtils.flipSignIf(direction * flipWidth, LocalizationUtils.isLayoutRtl());
StripLayoutTab slideTab = mStripTabs[newIndex - direction];
startAnimation(buildTabMoveAnimation(slideTab, animationLength), true);
finishAnimation();
mRunningAnimator = CompositorAnimator.ofFloatProperty(mUpdateHost.getAnimationHandler(),
slideTab, StripLayoutTab.X_OFFSET, animationLength, 0f, ANIM_TAB_MOVE_MS);
mRunningAnimator.start();
}
}
......@@ -1555,29 +1544,6 @@ public class StripLayoutHelper implements StripLayoutTab.StripLayoutTabDelegate
}
}
private static Animation<Animatable<?>> buildTabCreatedAnimation(StripLayoutTab tab) {
return createAnimation(tab, StripLayoutTab.Property.Y_OFFSET, tab.getHeight(), 0.f,
ANIM_TAB_CREATED_MS, 0, false, ChromeAnimation.getLinearInterpolator());
}
private static Animation<Animatable<?>> buildTabClosedAnimation(StripLayoutTab tab) {
return createAnimation(tab, StripLayoutTab.Property.Y_OFFSET, tab.getOffsetY(),
tab.getHeight(), ANIM_TAB_CLOSED_MS, 0, false,
ChromeAnimation.getLinearInterpolator());
}
private static Animation<Animatable<?>> buildTabResizeAnimation(
StripLayoutTab tab, float width) {
return createAnimation(tab, StripLayoutTab.Property.WIDTH, tab.getWidth(), width,
ANIM_TAB_RESIZE_MS, 0, false, ChromeAnimation.getLinearInterpolator());
}
private static Animation<Animatable<?>> buildTabMoveAnimation(
StripLayoutTab tab, float startX) {
return createAnimation(tab, StripLayoutTab.Property.X_OFFSET, startX, 0.f, ANIM_TAB_MOVE_MS,
0, false, ChromeAnimation.getLinearInterpolator());
}
private static <T> void moveElement(T[] array, int oldIndex, int newIndex) {
if (oldIndex <= newIndex) {
moveElementUp(array, oldIndex, newIndex);
......
......@@ -14,7 +14,7 @@ import org.chromium.base.ObserverList;
import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.compositor.animation.CompositorAnimator;
import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation;
import org.chromium.chrome.browser.compositor.animation.FloatProperty;
import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost;
import org.chromium.chrome.browser.compositor.layouts.components.CompositorButton;
......@@ -34,9 +34,7 @@ import java.util.List;
* {@link StripLayoutTab} is used to keep track of the strip position and rendering information for
* a particular tab so it can draw itself onto the GL canvas.
*/
public class StripLayoutTab
implements ChromeAnimation.Animatable<StripLayoutTab.Property>, VirtualView {
public class StripLayoutTab implements VirtualView {
/** An observer interface for StripLayoutTab. */
public interface Observer {
/** @param visible Whether the StripLayoutTab is visible. */
......@@ -61,15 +59,47 @@ public class StripLayoutTab
void handleCloseButtonClick(StripLayoutTab tab, long time);
}
/**
* Animatable properties that can be used with a {@link ChromeAnimation.Animatable} on a
* {@link StripLayoutTab}.
*/
enum Property {
X_OFFSET,
Y_OFFSET,
WIDTH,
}
/** A property for animations to use for changing the X offset of the tab. */
public static final FloatProperty<StripLayoutTab> X_OFFSET =
new FloatProperty<StripLayoutTab>("offsetX") {
@Override
public void setValue(StripLayoutTab object, float value) {
object.setOffsetX(value);
}
@Override
public Float get(StripLayoutTab object) {
return object.getOffsetX();
}
};
/** A property for animations to use for changing the Y offset of the tab. */
public static final FloatProperty<StripLayoutTab> Y_OFFSET =
new FloatProperty<StripLayoutTab>("offsetY") {
@Override
public void setValue(StripLayoutTab object, float value) {
object.setOffsetY(value);
}
@Override
public Float get(StripLayoutTab object) {
return object.getOffsetY();
}
};
/** A property for animations to use for changing the width of the tab. */
public static final FloatProperty<StripLayoutTab> WIDTH =
new FloatProperty<StripLayoutTab>("width") {
@Override
public void setValue(StripLayoutTab object, float value) {
object.setWidth(value);
}
@Override
public Float get(StripLayoutTab object) {
return object.getHeight();
}
};
// Behavior Constants
private static final float VISIBILITY_FADE_CLOSE_BUTTON_PERCENTAGE = 0.99f;
......@@ -514,24 +544,6 @@ public class StripLayoutTab
if (mButtonOpacityAnimation != null) mButtonOpacityAnimation.end();
}
@Override
public void setProperty(Property prop, float val) {
switch (prop) {
case X_OFFSET:
setOffsetX(val);
break;
case Y_OFFSET:
setOffsetY(val);
break;
case WIDTH:
setWidth(val);
break;
}
}
@Override
public void onPropertyAnimationFinished(Property prop) {}
private void resetCloseRect() {
RectF closeRect = getCloseRect();
mCloseButton.setWidth(closeRect.width());
......
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