This source file includes following definitions.
- notifyAnimationFinished
- setAnimationListener
- getAnimationListener
- areInfoBarsOnTop
- onInterceptTouchEvent
- onTouchEvent
- addToParentView
- determineGravity
- createLayoutParams
- removeFromParentView
- onParentViewChanged
- drawChild
- onAttachedToWindow
- onDetachedFromWindow
- findInfoBar
- addInfoBar
- findLastTransitionForInfoBar
- swapInfoBarViews
- removeInfoBar
- enqueueInfoBarAnimation
- onLayout
- hasBeenDestroyed
- processPendingInfoBars
- onPageStarted
- getTabId
- destroy
- getInfoBars
- processAutoLogin
- dismissAutoLoginInfoBars
- prepareTransition
- startTransition
- finishTransition
- childViewOf
- getNative
- nativeInit
- nativeDestroy
package org.chromium.chrome.browser.infobar;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.graphics.Canvas;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.google.common.annotations.VisibleForTesting;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.CalledByNative;
import org.chromium.content.browser.DeviceUtils;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.UiUtils;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
public class InfoBarContainer extends LinearLayout {
private static final String TAG = "InfoBarContainer";
private static final long REATTACH_FADE_IN_MS = 250;
public interface InfoBarAnimationListener {
void notifyAnimationFinished(int animationType);
}
private static class InfoBarTransitionInfo {
public InfoBar target;
public View toShow;
public int animationType;
public InfoBarTransitionInfo(InfoBar bar, View view, int type) {
assert type >= AnimationHelper.ANIMATION_TYPE_SHOW;
assert type < AnimationHelper.ANIMATION_TYPE_BOUNDARY;
target = bar;
toShow = view;
animationType = type;
}
}
private InfoBarAnimationListener mAnimationListener;
private long mNativeInfoBarContainer;
private final Activity mActivity;
private final AutoLoginDelegate mAutoLoginDelegate;
private final boolean mInfoBarsOnTop;
private final ArrayList<InfoBar> mInfoBars = new ArrayList<InfoBar>();
private final ArrayDeque<InfoBarTransitionInfo> mInfoBarTransitions;
private AnimationHelper mAnimation;
private final FrameLayout mAnimationSizer;
private boolean mDestroyed = false;
private int mTabId;
private ViewGroup mParentView;
public InfoBarContainer(Activity activity, AutoLoginProcessor autoLoginProcessor,
int tabId, ViewGroup parentView, WebContents webContents) {
super(activity);
setOrientation(LinearLayout.VERTICAL);
mAnimationListener = null;
mInfoBarTransitions = new ArrayDeque<InfoBarTransitionInfo>();
mAutoLoginDelegate = new AutoLoginDelegate(autoLoginProcessor, activity);
mActivity = activity;
mTabId = tabId;
mParentView = parentView;
mAnimationSizer = new FrameLayout(activity);
mAnimationSizer.setVisibility(INVISIBLE);
mInfoBarsOnTop = DeviceUtils.isTablet(activity);
setGravity(determineGravity());
mNativeInfoBarContainer = nativeInit(webContents, mAutoLoginDelegate);
}
public void setAnimationListener(InfoBarAnimationListener listener) {
mAnimationListener = listener;
}
@VisibleForTesting
public InfoBarAnimationListener getAnimationListener() {
return mAnimationListener;
}
public boolean areInfoBarsOnTop() {
return mInfoBarsOnTop;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mAnimation != null;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return true;
}
private void addToParentView() {
if (mParentView != null && mParentView.indexOfChild(this) == -1) {
mParentView.addView(this, createLayoutParams());
}
}
private int determineGravity() {
return mInfoBarsOnTop ? Gravity.TOP : Gravity.BOTTOM;
}
private FrameLayout.LayoutParams createLayoutParams() {
return new FrameLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, determineGravity());
}
public void removeFromParentView() {
if (getParent() != null) {
((ViewGroup) getParent()).removeView(this);
}
}
public void onParentViewChanged(int tabId, ViewGroup parentView) {
mTabId = tabId;
mParentView = parentView;
removeFromParentView();
addToParentView();
}
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (mAnimation == null || child != mAnimation.getTarget()) {
return super.drawChild(canvas, child, drawingTime);
}
boolean retVal;
canvas.save();
canvas.clipRect(mAnimation.getTarget().getClippingRect());
retVal = super.drawChild(canvas, child, drawingTime);
canvas.restore();
return retVal;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
ObjectAnimator.ofFloat(this, "alpha", 0.f, 1.f).setDuration(REATTACH_FADE_IN_MS).start();
setVisibility(VISIBLE);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
setVisibility(INVISIBLE);
}
public InfoBar findInfoBar(int nativeInfoBar) {
for (InfoBar infoBar : mInfoBars) {
if (infoBar.ownsNativeInfoBar(nativeInfoBar)) {
return infoBar;
}
}
return null;
}
@CalledByNative
public void addInfoBar(InfoBar infoBar) {
assert !mDestroyed;
if (infoBar == null) {
return;
}
if (mInfoBars.contains(infoBar)) {
assert false : "Trying to add an info bar that has already been added.";
return;
}
mInfoBars.add(infoBar);
infoBar.setContext(mActivity);
infoBar.setInfoBarContainer(this);
enqueueInfoBarAnimation(infoBar, null, AnimationHelper.ANIMATION_TYPE_SHOW);
}
public InfoBarTransitionInfo findLastTransitionForInfoBar(InfoBar toFind) {
Iterator<InfoBarTransitionInfo> iterator = mInfoBarTransitions.descendingIterator();
while (iterator.hasNext()) {
InfoBarTransitionInfo info = iterator.next();
if (info.target == toFind) return info;
}
return null;
}
public void swapInfoBarViews(InfoBar infoBar, View toShow) {
assert !mDestroyed;
if (!mInfoBars.contains(infoBar)) {
assert false : "Trying to swap an InfoBar that is not in this container.";
return;
}
InfoBarTransitionInfo transition = findLastTransitionForInfoBar(infoBar);
if (transition != null && transition.toShow == toShow) {
assert false : "Tried to enqueue the same swap twice in a row.";
return;
}
enqueueInfoBarAnimation(infoBar, toShow, AnimationHelper.ANIMATION_TYPE_SWAP);
}
public void removeInfoBar(InfoBar infoBar) {
assert !mDestroyed;
if (!mInfoBars.remove(infoBar)) {
assert false : "Trying to remove an InfoBar that is not in this container.";
return;
}
boolean collapseAnimations = false;
ArrayDeque<InfoBarTransitionInfo> transitionCopy =
new ArrayDeque<InfoBarTransitionInfo>(mInfoBarTransitions);
for (InfoBarTransitionInfo info : transitionCopy) {
if (info.target == infoBar) {
if (info.animationType == AnimationHelper.ANIMATION_TYPE_SHOW) {
assert !collapseAnimations;
collapseAnimations = true;
}
if (collapseAnimations) {
mInfoBarTransitions.remove(info);
}
}
}
if (!collapseAnimations) {
enqueueInfoBarAnimation(infoBar, null, AnimationHelper.ANIMATION_TYPE_HIDE);
}
}
private void enqueueInfoBarAnimation(InfoBar infoBar, View toShow, int animationType) {
InfoBarTransitionInfo info = new InfoBarTransitionInfo(infoBar, toShow, animationType);
mInfoBarTransitions.add(info);
processPendingInfoBars();
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
boolean isShowing = (getVisibility() == View.VISIBLE);
if (UiUtils.isKeyboardShowing(mActivity, this)) {
if (isShowing) {
setVisibility(View.INVISIBLE);
}
} else {
if (!isShowing) {
setVisibility(View.VISIBLE);
}
}
super.onLayout(changed, l, t, r, b);
}
public boolean hasBeenDestroyed() {
return mDestroyed;
}
private void processPendingInfoBars() {
if (mAnimation != null || mInfoBarTransitions.isEmpty()) return;
InfoBarTransitionInfo info = mInfoBarTransitions.remove();
View toShow = info.toShow;
ContentWrapperView targetView;
addToParentView();
if (info.animationType == AnimationHelper.ANIMATION_TYPE_SHOW) {
targetView = info.target.getContentWrapper(true);
assert mInfoBars.contains(info.target);
toShow = targetView.detachCurrentView();
addView(targetView, mInfoBarsOnTop ? getChildCount() : 0,
new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
} else {
targetView = info.target.getContentWrapper(false);
}
mAnimation = new AnimationHelper(this, targetView, info.target, toShow, info.animationType);
mAnimation.start();
}
public void onPageStarted(String url) {
LinkedList<InfoBar> barsToRemove = new LinkedList<InfoBar>();
for (InfoBar infoBar : mInfoBars) {
if (infoBar.shouldExpire(url)) {
barsToRemove.add(infoBar);
}
}
for (InfoBar infoBar : barsToRemove) {
infoBar.dismissJavaOnlyInfoBar();
}
}
public int getTabId() {
return mTabId;
}
public void destroy() {
mDestroyed = true;
removeAllViews();
if (mNativeInfoBarContainer != 0) {
nativeDestroy(mNativeInfoBarContainer);
}
mInfoBarTransitions.clear();
}
@VisibleForTesting
public ArrayList<InfoBar> getInfoBars() {
return mInfoBars;
}
public void processAutoLogin(String accountName, String authToken, boolean success,
String result) {
mAutoLoginDelegate.dismissAutoLogins(accountName, authToken, success, result);
}
public void dismissAutoLoginInfoBars() {
mAutoLoginDelegate.dismissAutoLogins("", "", false, "");
}
public void prepareTransition(View toShow) {
if (toShow != null) {
ViewGroup parent = (ViewGroup) toShow.getParent();
if (parent != null) parent.removeView(toShow);
assert mAnimationSizer.getParent() == null;
mParentView.addView(mAnimationSizer, createLayoutParams());
mAnimationSizer.addView(toShow, 0,
new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
mAnimationSizer.requestLayout();
}
}
public void startTransition() {
if (mInfoBarsOnTop) {
ApiCompatibilityUtils.postInvalidateOnAnimation(this);
}
}
public void finishTransition() {
assert mAnimation != null;
if (mAnimation.getAnimationType() == AnimationHelper.ANIMATION_TYPE_HIDE) {
removeView(mAnimation.getTarget());
}
for (int i = 0; i < getChildCount(); ++i) {
View view = getChildAt(i);
view.setTranslationY(0);
}
requestLayout();
if (getChildCount() == 0) {
removeFromParentView();
}
if (mAnimationSizer.getParent() != null) {
((ViewGroup) mAnimationSizer.getParent()).removeView(mAnimationSizer);
}
if (mAnimationListener != null) {
mAnimationListener.notifyAnimationFinished(mAnimation.getAnimationType());
}
mAnimation = null;
processPendingInfoBars();
}
public static InfoBarContainer childViewOf(ViewGroup parentView) {
for (int i = 0; i < parentView.getChildCount(); i++) {
if (parentView.getChildAt(i) instanceof InfoBarContainer) {
return (InfoBarContainer) parentView.getChildAt(i);
}
}
return null;
}
public long getNative() {
return mNativeInfoBarContainer;
}
private native long nativeInit(WebContents webContents, AutoLoginDelegate autoLoginDelegate);
private native void nativeDestroy(long nativeInfoBarContainerAndroid);
}