package com.actionbarsherlock.internal.view.menu;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.os.Build;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.LinearLayout;
import com.actionbarsherlock.internal.widget.IcsLinearLayout;
public class extends IcsLinearLayout implements MenuBuilder.ItemInvoker, MenuView {
private static final boolean IS_FROYO = Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO;
static final int MIN_CELL_SIZE = 56;
static final int GENERATED_ITEM_PADDING = 4;
private MenuBuilder mMenu;
private boolean mReserveOverflow;
private ActionMenuPresenter mPresenter;
private boolean mFormatItems;
private int mFormatItemsWidth;
private int mMinCellSize;
private int mGeneratedItemPadding;
private boolean mFirst = true;
public (Context context) {
this(context, null);
}
public (Context context, AttributeSet attrs) {
super(context, attrs);
setBaselineAligned(false);
final float density = context.getResources().getDisplayMetrics().density;
mMinCellSize = (int) (MIN_CELL_SIZE * density);
mGeneratedItemPadding = (int) (GENERATED_ITEM_PADDING * density);
}
public void (ActionMenuPresenter presenter) {
mPresenter = presenter;
}
return mFormatItems;
}
@Override
if (IS_FROYO) {
super.onConfigurationChanged(newConfig);
}
mPresenter.updateMenuView(false);
if (mPresenter != null && mPresenter.isOverflowMenuShowing()) {
mPresenter.hideOverflowMenu();
mPresenter.showOverflowMenu();
}
}
@Override
protected void onDraw(Canvas canvas) {
if (!IS_FROYO && mFirst) {
mFirst = false;
requestLayout();
return;
}
super.onDraw(canvas);
}
@Override
protected void onMeasure(
int widthMeasureSpec,
int heightMeasureSpec) {
final boolean wasFormatted = mFormatItems;
mFormatItems = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY;
if (wasFormatted != mFormatItems) {
mFormatItemsWidth = 0;
}
final int widthSize = MeasureSpec.getMode(widthMeasureSpec);
if (mFormatItems && mMenu != null && widthSize != mFormatItemsWidth) {
mFormatItemsWidth = widthSize;
mMenu.onItemsChanged(true);
}
if (mFormatItems) {
onMeasureExactFormat(widthMeasureSpec, heightMeasureSpec);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
final int widthPadding = getPaddingLeft() + getPaddingRight();
final int heightPadding = getPaddingTop() + getPaddingBottom();
widthSize -= widthPadding;
final int cellCount = widthSize / mMinCellSize;
final int cellSizeRemaining = widthSize % mMinCellSize;
if (cellCount == 0) {
setMeasuredDimension(widthSize, 0);
return;
}
final int cellSize = mMinCellSize + cellSizeRemaining / cellCount;
int cellsRemaining = cellCount;
int maxChildHeight = 0;
int maxCellsUsed = 0;
int expandableItemCount = 0;
int visibleItemCount = 0;
boolean hasOverflow = false;
long smallestItemsAt = 0;
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE) continue;
final boolean isGeneratedItem = child instanceof ActionMenuItemView;
visibleItemCount++;
if (isGeneratedItem) {
child.setPadding(mGeneratedItemPadding, 0, mGeneratedItemPadding, 0);
}
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
lp.expanded = false;
lp.extraPixels = 0;
lp.cellsUsed = 0;
lp.expandable = false;
lp.leftMargin = 0;
lp.rightMargin = 0;
lp.preventEdgeOffset = isGeneratedItem && ((ActionMenuItemView) child).hasText();
final int cellsAvailable = lp.isOverflowButton ? 1 : cellsRemaining;
final int cellsUsed = measureChildForCells(child, cellSize, cellsAvailable,
heightMeasureSpec, heightPadding);
maxCellsUsed = Math.max(maxCellsUsed, cellsUsed);
if (lp.expandable) expandableItemCount++;
if (lp.isOverflowButton) hasOverflow = true;
cellsRemaining -= cellsUsed;
maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight());
if (cellsUsed == 1) smallestItemsAt |= (1 << i);
}
final boolean centerSingleExpandedItem = hasOverflow && visibleItemCount == 2;
boolean needsExpansion = false;
while (expandableItemCount > 0 && cellsRemaining > 0) {
int minCells = Integer.MAX_VALUE;
long minCellsAt = 0;
int minCellsItemCount = 0;
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (!lp.expandable) continue;
if (lp.cellsUsed < minCells) {
minCells = lp.cellsUsed;
minCellsAt = 1 << i;
minCellsItemCount = 1;
} else if (lp.cellsUsed == minCells) {
minCellsAt |= 1 << i;
minCellsItemCount++;
}
}
smallestItemsAt |= minCellsAt;
if (minCellsItemCount > cellsRemaining) break;
minCells++;
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if ((minCellsAt & (1 << i)) == 0) {
if (lp.cellsUsed == minCells) smallestItemsAt |= 1 << i;
continue;
}
if (centerSingleExpandedItem && lp.preventEdgeOffset && cellsRemaining == 1) {
child.setPadding(mGeneratedItemPadding + cellSize, 0, mGeneratedItemPadding, 0);
}
lp.cellsUsed++;
lp.expanded = true;
cellsRemaining--;
}
needsExpansion = true;
}
final boolean singleItem = !hasOverflow && visibleItemCount == 1;
if (cellsRemaining > 0 && smallestItemsAt != 0 &&
(cellsRemaining < visibleItemCount - 1 || singleItem || maxCellsUsed > 1)) {
float expandCount = Long.bitCount(smallestItemsAt);
if (!singleItem) {
if ((smallestItemsAt & 1) != 0) {
LayoutParams lp = (LayoutParams) getChildAt(0).getLayoutParams();
if (!lp.preventEdgeOffset) expandCount -= 0.5f;
}
if ((smallestItemsAt & (1 << (childCount - 1))) != 0) {
LayoutParams lp = ((LayoutParams) getChildAt(childCount - 1).getLayoutParams());
if (!lp.preventEdgeOffset) expandCount -= 0.5f;
}
}
final int extraPixels = expandCount > 0 ?
(int) (cellsRemaining * cellSize / expandCount) : 0;
for (int i = 0; i < childCount; i++) {
if ((smallestItemsAt & (1 << i)) == 0) continue;
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (child instanceof ActionMenuItemView) {
lp.extraPixels = extraPixels;
lp.expanded = true;
if (i == 0 && !lp.preventEdgeOffset) {
lp.leftMargin = -extraPixels / 2;
}
needsExpansion = true;
} else if (lp.isOverflowButton) {
lp.extraPixels = extraPixels;
lp.expanded = true;
lp.rightMargin = -extraPixels / 2;
needsExpansion = true;
} else {
if (i != 0) {
lp.leftMargin = extraPixels / 2;
}
if (i != childCount - 1) {
lp.rightMargin = extraPixels / 2;
}
}
}
cellsRemaining = 0;
}
if (needsExpansion) {
int heightSpec = MeasureSpec.makeMeasureSpec(heightSize - heightPadding, heightMode);
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (!lp.expanded) continue;
final int width = lp.cellsUsed * cellSize + lp.extraPixels;
child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), heightSpec);
}
}
if (heightMode != MeasureSpec.EXACTLY) {
heightSize = maxChildHeight;
}
setMeasuredDimension(widthSize, heightSize);
}
int parentHeightMeasureSpec, int parentHeightPadding) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
final int childHeightSize = MeasureSpec.getSize(parentHeightMeasureSpec) -
parentHeightPadding;
final int childHeightMode = MeasureSpec.getMode(parentHeightMeasureSpec);
final int childHeightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, childHeightMode);
int cellsUsed = 0;
if (cellsRemaining > 0) {
final int childWidthSpec = MeasureSpec.makeMeasureSpec(
cellSize * cellsRemaining, MeasureSpec.AT_MOST);
child.measure(childWidthSpec, childHeightSpec);
final int measuredWidth = child.getMeasuredWidth();
cellsUsed = measuredWidth / cellSize;
if (measuredWidth % cellSize != 0) cellsUsed++;
}
final ActionMenuItemView itemView = child instanceof ActionMenuItemView ?
(ActionMenuItemView) child : null;
final boolean expandable = !lp.isOverflowButton && itemView != null && itemView.hasText();
lp.expandable = expandable;
lp.cellsUsed = cellsUsed;
final int targetWidth = cellsUsed * cellSize;
child.measure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY),
childHeightSpec);
return cellsUsed;
}
@Override
protected void onLayout(
boolean changed,
int left,
int top,
int right,
int bottom) {
if (!mFormatItems) {
super.onLayout(changed, left, top, right, bottom);
return;
}
final int childCount = getChildCount();
final int midVertical = (top + bottom) / 2;
final int dividerWidth = 0;
int overflowWidth = 0;
int nonOverflowCount = 0;
int widthRemaining = right - left - getPaddingRight() - getPaddingLeft();
boolean hasOverflow = false;
for (int i = 0; i < childCount; i++) {
final View v = getChildAt(i);
if (v.getVisibility() == GONE) {
continue;
}
LayoutParams p = (LayoutParams) v.getLayoutParams();
if (p.isOverflowButton) {
overflowWidth = v.getMeasuredWidth();
if (hasDividerBeforeChildAt(i)) {
overflowWidth += dividerWidth;
}
int height = v.getMeasuredHeight();
int r = getWidth() - getPaddingRight() - p.rightMargin;
int l = r - overflowWidth;
int t = midVertical - (height / 2);
int b = t + height;
v.layout(l, t, r, b);
widthRemaining -= overflowWidth;
hasOverflow = true;
} else {
final int size = v.getMeasuredWidth() + p.leftMargin + p.rightMargin;
widthRemaining -= size;
nonOverflowCount++;
}
}
if (childCount == 1 && !hasOverflow) {
final View v = getChildAt(0);
final int width = v.getMeasuredWidth();
final int height = v.getMeasuredHeight();
final int midHorizontal = (right - left) / 2;
final int l = midHorizontal - width / 2;
final int t = midVertical - height / 2;
v.layout(l, t, l + width, t + height);
return;
}
final int spacerCount = nonOverflowCount - (hasOverflow ? 0 : 1);
final int spacerSize = Math.max(0, spacerCount > 0 ? widthRemaining / spacerCount : 0);
int startLeft = getPaddingLeft();
for (int i = 0; i < childCount; i++) {
final View v = getChildAt(i);
final LayoutParams lp = (LayoutParams) v.getLayoutParams();
if (v.getVisibility() == GONE || lp.isOverflowButton) {
continue;
}
startLeft += lp.leftMargin;
int width = v.getMeasuredWidth();
int height = v.getMeasuredHeight();
int t = midVertical - height / 2;
v.layout(startLeft, t, startLeft + width, t + height);
startLeft += width + lp.rightMargin + spacerSize;
}
}
@Override
super.onDetachedFromWindow();
mPresenter.dismissPopupMenus();
}
return mReserveOverflow;
}
mReserveOverflow = reserveOverflow;
}
@Override
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER_VERTICAL;
return params;
}
@Override
return new LayoutParams(getContext(), attrs);
}
@Override
if (p instanceof LayoutParams) {
LayoutParams result = new LayoutParams((LayoutParams) p);
if (result.gravity <= Gravity.NO_GRAVITY) {
result.gravity = Gravity.CENTER_VERTICAL;
}
return result;
}
return generateDefaultLayoutParams();
}
@Override
return p != null && p instanceof LayoutParams;
}
LayoutParams result = generateDefaultLayoutParams();
result.isOverflowButton = true;
return result;
}
public boolean (MenuItemImpl item) {
return mMenu.performItemAction(item, 0);
}
return 0;
}
public void (MenuBuilder menu) {
mMenu = menu;
}
if (childIndex == 0) {
return false;
}
final View childBefore = getChildAt(childIndex - 1);
final View child = getChildAt(childIndex);
boolean result = false;
if (childIndex < getChildCount() && childBefore instanceof ActionMenuChildView) {
result |= ((ActionMenuChildView) childBefore).needsDividerAfter();
}
if (childIndex > 0 && child instanceof ActionMenuChildView) {
result |= ((ActionMenuChildView) child).needsDividerBefore();
}
return result;
}
return false;
}
public interface {
}
public static class extends LinearLayout.LayoutParams {
public boolean isOverflowButton;
public int cellsUsed;
public int extraPixels;
public boolean expandable;
public boolean preventEdgeOffset;
public boolean expanded;
super(c, attrs);
}
super((LinearLayout.LayoutParams) other);
isOverflowButton = other.isOverflowButton;
}
super(width, height);
isOverflowButton = false;
}
public LayoutParams(
int width,
int height,
boolean isOverflowButton) {
super(width, height);
this.isOverflowButton = isOverflowButton;
}
}
}