This source file includes following definitions.
- generateDefaultLayoutParams
 
- addView
 
- addGroup
 
- addButtons
 
- onLayout
 
- layoutMainRow
 
- layoutRow
 
- isMainControl
 
- addRowStartIndex
 
- getNextGroup
 
- measureChild
 
- onMeasure
 
- measureMainRow
 
- measureRemainingRows
 
- computeHeight
 
- computeMainRowHeight
 
- computeRowHeight
 
- isButton
 
- updateBackgroundsForButtons
 
- onClick
 
package org.chromium.chrome.browser.infobar;
import android.content.Context;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import org.chromium.chrome.R;
import org.chromium.ui.base.LocalizationUtils;
import java.util.ArrayList;
public class InfoBarLayout extends ViewGroup implements View.OnClickListener {
    private static final String TAG = "InfoBarLayout";
    
    public static class LayoutParams extends ViewGroup.LayoutParams {
        
        public static final int ALIGN_START = 0;
        public static final int ALIGN_END = 1;
        
        public boolean isInMainRow;
        
        public boolean isGroupedWithNextView;
        
        public int align;
        
        public int background;
        public LayoutParams() {
            super(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
            align = ALIGN_END;
            isInMainRow = true;
        }
        public LayoutParams(LayoutParams other) {
            super(other);
            isGroupedWithNextView = other.isGroupedWithNextView;
            align = other.align;
            isInMainRow = other.isInMainRow;
        }
    }
    private static class GroupInfo {
        public int numViews;
        public int width;
        public int greatestMemberWidth;
        public int endIndex;
        public boolean hasButton;
    };
    private final int mDimensionMinSize;
    private final int mDimensionMargin;
    private final int mDimensionIconSize;
    private final boolean mLayoutRTL;
    private final InfoBarView mInfoBarView;
    private final ImageView mIconView;
    private final TextView mMessageView;
    private final ImageButton mCloseButton;
    
    private final int mBackgroundFloating;
    private final int mBackgroundFullLeft;
    private final int mBackgroundFullRight;
    
    private final ArrayList<Integer> mIndicesOfRows;
    
    public InfoBarLayout(Context context, InfoBarView infoBarView, int backgroundType,
            int iconResourceId) {
        super(context);
        mIndicesOfRows = new ArrayList<Integer>();
        mLayoutRTL = LocalizationUtils.isLayoutRtl();
        mInfoBarView = infoBarView;
        
        if (backgroundType == InfoBar.BACKGROUND_TYPE_INFO) {
            mBackgroundFloating = R.drawable.infobar_button_normal_floating;
            mBackgroundFullLeft = R.drawable.infobar_button_normal_full_left;
            mBackgroundFullRight = R.drawable.infobar_button_normal_full_right;
        } else {
            mBackgroundFloating = R.drawable.infobar_button_warning_floating;
            mBackgroundFullLeft = R.drawable.infobar_button_warning_full_left;
            mBackgroundFullRight = R.drawable.infobar_button_warning_full_right;
        }
        
        mDimensionMinSize =
                context.getResources().getDimensionPixelSize(R.dimen.infobar_min_size);
        mDimensionMargin =
                context.getResources().getDimensionPixelSize(R.dimen.infobar_margin);
        mDimensionIconSize =
                context.getResources().getDimensionPixelSize(R.dimen.infobar_icon_size);
        
        mCloseButton = new ImageButton(context);
        mIconView = new ImageView(context);
        mMessageView = (TextView) LayoutInflater.from(context).inflate(R.layout.infobar_text, null);
        addGroup(mCloseButton, mIconView, mMessageView);
        
        mCloseButton.setId(R.id.infobar_close_button);
        mCloseButton.setImageResource(R.drawable.dismiss);
        mCloseButton.setBackgroundResource(R.drawable.infobar_close_bg);
        mCloseButton.setOnClickListener(this);
        mCloseButton.setContentDescription(getResources().getString(R.string.infobar_close));
        
        mIconView.setFocusable(false);
        if (iconResourceId != 0) {
            mIconView.setImageResource(iconResourceId);
        } else {
            mIconView.setVisibility(View.INVISIBLE);
        }
        
        mMessageView.setMovementMethod(LinkMovementMethod.getInstance());
        mMessageView.setText(infoBarView.getMessageText(context), TextView.BufferType.SPANNABLE);
        
        ((LayoutParams) mIconView.getLayoutParams()).align = LayoutParams.ALIGN_START;
        ((LayoutParams) mMessageView.getLayoutParams()).align = LayoutParams.ALIGN_START;
        
        
        mIconView.getLayoutParams().width = mDimensionIconSize;
        mIconView.getLayoutParams().height = mDimensionIconSize;
        
        int closeButtonHeight = mCloseButton.getDrawable().getIntrinsicHeight();
        int closePadding = (mDimensionMinSize - closeButtonHeight) / 2;
        if (closePadding >= 0) {
            mCloseButton.setPadding(closePadding, closePadding, closePadding, closePadding);
        } else {
            assert closePadding >= 0 : "Assets are too large for this layout.";
        }
        
        infoBarView.createContent(this);
    }
    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams();
    }
    
    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        if (index == -1) {
            super.addView(child, index, params);
        } else {
            assert false : "Adding children at random places can break group structure.";
            super.addView(child, -1, params);
        }
    }
    
    public void addGroup(View... group) {
        for (int i = 0; i < group.length; i++) {
            final View member = group[i];
            addView(member);
            LayoutParams params = (LayoutParams) member.getLayoutParams();
            params.isGroupedWithNextView = (i != group.length - 1);
        }
    }
    
    public void addButtons(String primaryText, String secondaryText) {
        Button primaryButton = null;
        Button secondaryButton = null;
        if (!TextUtils.isEmpty(secondaryText)) {
            secondaryButton = (Button) LayoutInflater.from(getContext()).inflate(
                    R.layout.infobar_button, null);
            secondaryButton.setId(R.id.button_secondary);
            secondaryButton.setOnClickListener(this);
            secondaryButton.setText(secondaryText);
        }
        if (!TextUtils.isEmpty(primaryText)) {
            primaryButton = (Button) LayoutInflater.from(getContext()).inflate(
                    R.layout.infobar_button, null);
            primaryButton.setId(R.id.button_primary);
            primaryButton.setOnClickListener(this);
            primaryButton.setText(primaryText);
        }
        
        if (primaryButton == null && secondaryButton != null) {
            assert false : "When using only one button, make it the primary button.";
        } else if (primaryButton != null && secondaryButton != null) {
            addGroup(secondaryButton, primaryButton);
        } else if (primaryButton != null) {
            addGroup(primaryButton);
        }
    }
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        final int rowWidth = right - left;
        int rowTop = layoutMainRow(rowWidth);
        for (int row = 1; row < mIndicesOfRows.size() - 1; row++) {
            rowTop = layoutRow(row, rowTop, rowWidth);
        }
    }
    
    private int layoutMainRow(int width) {
        final int rowStart = mIndicesOfRows.get(0);
        final int rowEnd = mIndicesOfRows.get(1);
        final int rowHeight = computeMainRowHeight(rowStart, rowEnd);
        
        int closeLeft;
        int iconPadding = (mDimensionMinSize - mDimensionIconSize) / 2;
        int iconLeft = iconPadding;
        if (mLayoutRTL) {
            iconLeft += width - mDimensionMinSize;
            closeLeft = 0;
        } else {
            closeLeft = width - mCloseButton.getMeasuredWidth();
        }
        mIconView.layout(iconLeft, iconPadding, iconLeft + mDimensionIconSize,
                iconPadding + mDimensionIconSize);
        mCloseButton.layout(closeLeft, 0, closeLeft + mDimensionMinSize, mDimensionMinSize);
        
        int rowLeft = mDimensionMinSize;
        int rowRight = width - mDimensionMinSize;
        for (int i = rowStart; i < rowEnd; i++) {
            final View child = getChildAt(i);
            LayoutParams params = (LayoutParams) child.getLayoutParams();
            if (params.align != LayoutParams.ALIGN_START || child.getVisibility() == View.GONE
                    || child == mCloseButton || child == mIconView) {
                continue;
            }
            
            int childTop = (rowHeight - child.getMeasuredHeight()) / 2;
            int childLeft;
            if (mLayoutRTL) {
                if (!isMainControl(child)) rowRight -= mDimensionMargin;
                childLeft = rowRight - child.getMeasuredWidth();
                rowRight -= child.getMeasuredWidth();
            } else {
                if (!isMainControl(child)) rowLeft += mDimensionMargin;
                childLeft = rowLeft;
                rowLeft += child.getMeasuredWidth();
            }
            child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(),
                    childTop + child.getMeasuredHeight());
        }
        
        for (int i = rowEnd - 1; i >= rowStart; i--) {
            final View child = getChildAt(i);
            LayoutParams params = (LayoutParams) child.getLayoutParams();
            if (params.align != LayoutParams.ALIGN_END || child.getVisibility() == View.GONE
                    || child == mCloseButton || child == mIconView) {
                continue;
            }
            
            int childTop = (rowHeight - child.getMeasuredHeight()) / 2;
            int childLeft;
            if (!mLayoutRTL) {
                childLeft = rowRight - child.getMeasuredWidth();
                rowRight -= child.getMeasuredWidth();
                if (!isMainControl(child)) rowRight -= mDimensionMargin;
            } else {
                childLeft = rowLeft;
                rowLeft += child.getMeasuredWidth();
                if (!isMainControl(child)) rowLeft += mDimensionMargin;
            }
            child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(),
                    childTop + child.getMeasuredHeight());
        }
        return rowHeight;
    }
    
    private int layoutRow(int row, int rowTop, int width) {
        final int rowStart = mIndicesOfRows.get(row);
        final int rowEnd = mIndicesOfRows.get(row + 1);
        final boolean hasButton = isButton(getChildAt(rowStart));
        int rowLeft = hasButton ? 0 : mDimensionMargin;
        int rowRight = width - (hasButton ? 0 : mDimensionMargin);
        for (int i = rowStart; i < rowEnd; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() == View.GONE) continue;
            int childLeft;
            if (mLayoutRTL) {
                childLeft = rowRight - child.getMeasuredWidth();
                rowRight -= child.getMeasuredWidth() + (hasButton ? 0 : mDimensionMargin);
            } else {
                childLeft = rowLeft;
                rowLeft += child.getMeasuredWidth() + (hasButton ? 0 : mDimensionMargin);
            }
            child.layout(childLeft, rowTop, childLeft + child.getMeasuredWidth(),
                    rowTop + child.getMeasuredHeight());
        }
        return rowTop + computeRowHeight(rowStart, rowEnd);
    }
    
    private boolean isMainControl(View child) {
        return child == mIconView || child == mMessageView || child == mCloseButton;
    }
    
    private void addRowStartIndex(int rowStartIndex) {
        if (mIndicesOfRows.size() == 0
                || rowStartIndex != mIndicesOfRows.get(mIndicesOfRows.size() - 1)) {
            mIndicesOfRows.add(rowStartIndex);
        }
    }
    
    private GroupInfo getNextGroup(int startIndex) {
        GroupInfo groupInfo = new GroupInfo();
        groupInfo.endIndex = startIndex;
        final int childCount = getChildCount();
        int currentChildIndex = startIndex;
        while (groupInfo.endIndex < childCount) {
            final View groupChild = getChildAt(groupInfo.endIndex);
            if (groupChild.getVisibility() != View.GONE) {
                groupInfo.hasButton |= isButton(groupChild);
                groupInfo.width += groupChild.getMeasuredWidth();
                groupInfo.greatestMemberWidth =
                        Math.max(groupInfo.greatestMemberWidth, groupChild.getMeasuredWidth());
                groupInfo.numViews++;
            }
            groupInfo.endIndex++;
            LayoutParams params = (LayoutParams) groupChild.getLayoutParams();
            if (!params.isGroupedWithNextView) break;
        }
        return groupInfo;
    }
    @Override
    protected void measureChild(View child, int widthSpec, int heightSpec) {
        
        
        LayoutParams params = (LayoutParams) child.getLayoutParams();
        params.width = params.isInMainRow ? LayoutParams.WRAP_CONTENT : LayoutParams.MATCH_PARENT;
        super.measureChild(child, widthSpec, heightSpec);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        assert getLayoutParams().height == LayoutParams.WRAP_CONTENT
                : "InfoBar heights cannot be constrained.";
        final int maxWidth = MeasureSpec.getSize(widthMeasureSpec);
        mIndicesOfRows.clear();
        
        
        final int childCount = getChildCount();
        for (int numChild = 0; numChild < childCount; numChild++) {
            final View child = getChildAt(numChild);
            if (child.getVisibility() == View.GONE) continue;
            ((LayoutParams) child.getLayoutParams()).isInMainRow = true;
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
        }
        
        
        int currentChildIndex = measureMainRow(maxWidth);
        measureRemainingRows(maxWidth, currentChildIndex);
        
        
        updateBackgroundsForButtons();
        
        int layoutHeight = computeHeight();
        setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
                resolveSize(layoutHeight, heightMeasureSpec));
    }
    
    private int measureMainRow(int maxWidth) {
        final int childCount = getChildCount();
        
        
        
        GroupInfo mainControlInfo = getNextGroup(0);
        int remainingWidth = maxWidth - (mDimensionMinSize * 2) - mMessageView.getMeasuredWidth();
        addRowStartIndex(0);
        
        int currentChildIndex = mainControlInfo.endIndex;
        while (currentChildIndex < childCount && remainingWidth > 0) {
            GroupInfo groupInfo = getNextGroup(currentChildIndex);
            int widthWithMargins = groupInfo.width + mDimensionMargin * groupInfo.numViews;
            if (widthWithMargins <= remainingWidth) {
                
                currentChildIndex = groupInfo.endIndex;
                remainingWidth -= widthWithMargins;
            } else {
                
                break;
            }
        }
        addRowStartIndex(currentChildIndex);
        
        
        int specWidth = MeasureSpec.makeMeasureSpec(mDimensionMinSize, MeasureSpec.EXACTLY);
        int specHeight = MeasureSpec.makeMeasureSpec(mDimensionMinSize, MeasureSpec.EXACTLY);
        measureChild(mIconView, specWidth, specHeight);
        measureChild(mCloseButton, specWidth, specHeight);
        
        remainingWidth = maxWidth - (mDimensionMinSize * 2);
        for (int i = 0; i < currentChildIndex; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() == View.GONE || isMainControl(child)) continue;
            specWidth = MeasureSpec.makeMeasureSpec(remainingWidth, MeasureSpec.AT_MOST);
            specHeight = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
            measureChild(child, specWidth, specHeight);
            remainingWidth -= child.getMeasuredWidth() + mDimensionMargin;
        }
        
        
        specWidth = MeasureSpec.makeMeasureSpec(remainingWidth, MeasureSpec.AT_MOST);
        specHeight = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        measureChild(mMessageView, specWidth, specHeight);
        return currentChildIndex;
    }
    
    private void measureRemainingRows(int maxWidth, int currentChildIndex) {
        final int childCount = getChildCount();
        final int specHeight = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        while (currentChildIndex < childCount) {
            GroupInfo groupInfo = getNextGroup(currentChildIndex);
            int availableWidth;
            int boundaryMargins;
            if (groupInfo.hasButton) {
                
                availableWidth = maxWidth;
                boundaryMargins = 0;
            } else {
                
                availableWidth = maxWidth - mDimensionMargin * 2;
                boundaryMargins = (groupInfo.numViews - 1) * mDimensionMargin;
            }
            
            int evenWidth = (availableWidth - boundaryMargins) / groupInfo.numViews;
            if (groupInfo.greatestMemberWidth <= evenWidth) {
                
                int specWidth = MeasureSpec.makeMeasureSpec(evenWidth, MeasureSpec.EXACTLY);
                for (int i = currentChildIndex; i < groupInfo.endIndex; i++) {
                    final View child = getChildAt(i);
                    if (child.getVisibility() == View.GONE) continue;
                    ((LayoutParams) child.getLayoutParams()).isInMainRow = false;
                    measureChild(child, specWidth, specHeight);
                }
                addRowStartIndex(currentChildIndex);
            } else {
                
                int specWidth = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.EXACTLY);
                for (int i = currentChildIndex; i < groupInfo.endIndex; i++) {
                    final View child = getChildAt(i);
                    if (child.getVisibility() == View.GONE) continue;
                    ((LayoutParams) child.getLayoutParams()).isInMainRow = false;
                    measureChild(child, specWidth, specHeight);
                    addRowStartIndex(i);
                }
            }
            currentChildIndex = groupInfo.endIndex;
        }
        addRowStartIndex(childCount);
    }
    
    private int computeHeight() {
        int cumulativeHeight = 0;
        
        final int numRows = mIndicesOfRows.size() - 1;
        for (int row = 0; row < numRows; row++) {
            final int rowStart = mIndicesOfRows.get(row);
            final int rowEnd = mIndicesOfRows.get(row + 1);
            if (row == 0) {
                cumulativeHeight += computeMainRowHeight(rowStart, rowEnd);
            } else {
                cumulativeHeight += computeRowHeight(rowStart, rowEnd);
            }
        }
        return cumulativeHeight;
    }
    
    private int computeMainRowHeight(int rowStart, int rowEnd) {
        
        
        final int verticalMargins = mDimensionMargin * 2;
        int rowHeight = mDimensionMinSize;
        for (int i = rowStart; i < rowEnd; i++) {
            View child = getChildAt(i);
            if (child == mCloseButton || child == mIconView || child.getVisibility() == View.GONE) {
                continue;
            }
            rowHeight = Math.max(rowHeight, child.getMeasuredHeight() + verticalMargins);
        }
        return rowHeight;
    }
    
    private int computeRowHeight(int rowStart, int rowEnd) {
        boolean isButtonRow = isButton(getChildAt(rowStart));
        final int verticalMargins = isButtonRow ? 0 : mDimensionMargin;
        int rowHeight = 0;
        for (int i = rowStart; i < rowEnd; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() == View.GONE) continue;
            rowHeight = Math.max(rowHeight, child.getMeasuredHeight() + verticalMargins);
        }
        return rowHeight;
    }
    
    private boolean isButton(View child) {
        return child.getId() == R.id.button_secondary || child.getId() == R.id.button_primary;
    }
    
    private void updateBackgroundsForButtons() {
        boolean bothButtonsExist = findViewById(R.id.button_primary) != null
                && findViewById(R.id.button_secondary) != null;
        for (int row = 0; row < mIndicesOfRows.size() - 1; row++) {
            final int rowStart = mIndicesOfRows.get(row);
            final int rowEnd = mIndicesOfRows.get(row + 1);
            final int rowSize = rowEnd - rowStart;
            for (int i = rowStart; i < rowEnd; i++) {
                final View child = getChildAt(i);
                if (child.getVisibility() == View.GONE || !isButton(child)) continue;
                
                int background;
                if (row == 0) {
                    
                    background = mBackgroundFloating;
                } else if (rowSize == 1 || !bothButtonsExist) {
                    
                    background = mBackgroundFullRight;
                } else if (mLayoutRTL) {
                    
                    background = child.getId() == R.id.button_primary
                            ? mBackgroundFullLeft : mBackgroundFullRight;
                } else {
                    
                    background = child.getId() == R.id.button_primary
                            ? mBackgroundFullRight : mBackgroundFullLeft;
                }
                
                LayoutParams params = (LayoutParams) child.getLayoutParams();
                if (params.background != background) {
                    params.background = background;
                    
                    int paddingLeft = child.getPaddingLeft();
                    int paddingTop = child.getPaddingTop();
                    int paddingRight = child.getPaddingRight();
                    int paddingBottom = child.getPaddingBottom();
                    int buttonWidth = child.getMeasuredWidth();
                    int buttonHeight = child.getMeasuredHeight();
                    
                    child.setBackgroundResource(background);
                    child.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
                    
                    int specWidth = MeasureSpec.makeMeasureSpec(buttonWidth, MeasureSpec.EXACTLY);
                    int specHeight = MeasureSpec.makeMeasureSpec(buttonHeight, MeasureSpec.EXACTLY);
                    measureChild(child, specWidth, specHeight);
                }
            }
        }
    }
    
    @Override
    public void onClick(View view) {
        mInfoBarView.setControlsEnabled(false);
        if (view.getId() == R.id.infobar_close_button) {
            mInfoBarView.onCloseButtonClicked();
        } else if (view.getId() == R.id.button_primary) {
            mInfoBarView.onButtonClicked(true);
        } else if (view.getId() == R.id.button_secondary) {
            mInfoBarView.onButtonClicked(false);
        }
    }
}