summaryrefslogtreecommitdiffstats
path: root/actionbarsherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java
diff options
context:
space:
mode:
Diffstat (limited to 'actionbarsherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java')
-rw-r--r--actionbarsherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java572
1 files changed, 0 insertions, 572 deletions
diff --git a/actionbarsherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java b/actionbarsherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java
deleted file mode 100644
index e090677a1..000000000
--- a/actionbarsherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java
+++ /dev/null
@@ -1,572 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-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;
-
-/**
- * @hide
- */
-public class ActionMenuView extends IcsLinearLayout implements MenuBuilder.ItemInvoker, MenuView {
- //UNUSED private static final String TAG = "ActionMenuView";
- private static final boolean IS_FROYO = Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO;
-
- static final int MIN_CELL_SIZE = 56; // dips
- static final int GENERATED_ITEM_PADDING = 4; // dips
-
- private MenuBuilder mMenu;
-
- private boolean mReserveOverflow;
- private ActionMenuPresenter mPresenter;
- private boolean mFormatItems;
- private int mFormatItemsWidth;
- private int mMinCellSize;
- private int mGeneratedItemPadding;
- //UNUSED private int mMeasuredExtraWidth;
-
- private boolean mFirst = true;
-
- public ActionMenuView(Context context) {
- this(context, null);
- }
-
- public ActionMenuView(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 setPresenter(ActionMenuPresenter presenter) {
- mPresenter = presenter;
- }
-
- public boolean isExpandedFormat() {
- return mFormatItems;
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- if (IS_FROYO) {
- super.onConfigurationChanged(newConfig);
- }
- mPresenter.updateMenuView(false);
-
- if (mPresenter != null && mPresenter.isOverflowMenuShowing()) {
- mPresenter.hideOverflowMenu();
- mPresenter.showOverflowMenu();
- }
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- //Need to trigger a relayout since we may have been added extremely
- //late in the initial rendering (e.g., when contained in a ViewPager).
- //See: https://github.com/JakeWharton/ActionBarSherlock/issues/272
- if (!IS_FROYO && mFirst) {
- mFirst = false;
- requestLayout();
- return;
- }
- super.onDraw(canvas);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- // If we've been given an exact size to match, apply special formatting during layout.
- final boolean wasFormatted = mFormatItems;
- mFormatItems = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY;
-
- if (wasFormatted != mFormatItems) {
- mFormatItemsWidth = 0; // Reset this when switching modes
- }
-
- // Special formatting can change whether items can fit as action buttons.
- // Kick the menu and update presenters when this changes.
- 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);
- }
- }
-
- private void onMeasureExactFormat(int widthMeasureSpec, int heightMeasureSpec) {
- // We already know the width mode is EXACTLY if we're here.
- 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;
-
- // Divide the view into cells.
- final int cellCount = widthSize / mMinCellSize;
- final int cellSizeRemaining = widthSize % mMinCellSize;
-
- if (cellCount == 0) {
- // Give up, nothing fits.
- 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;
-
- // This is used as a bitfield to locate the smallest items present. Assumes childCount < 64.
- 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) {
- // Reset padding for generated menu item views; it may change below
- // and views are recycled.
- 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();
-
- // Overflow always gets 1 cell. No more, no less.
- 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);
- }
-
- // When we have overflow and a single expanded (text) item, we want to try centering it
- // visually in the available space even though overflow consumes some of it.
- final boolean centerSingleExpandedItem = hasOverflow && visibleItemCount == 2;
-
- // Divide space for remaining cells if we have items that can expand.
- // Try distributing whole leftover cells to smaller items first.
-
- boolean needsExpansion = false;
- while (expandableItemCount > 0 && cellsRemaining > 0) {
- int minCells = Integer.MAX_VALUE;
- long minCellsAt = 0; // Bit locations are indices of relevant child views
- int minCellsItemCount = 0;
- for (int i = 0; i < childCount; i++) {
- final View child = getChildAt(i);
- final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-
- // Don't try to expand items that shouldn't.
- if (!lp.expandable) continue;
-
- // Mark indices of children that can receive an extra cell.
- if (lp.cellsUsed < minCells) {
- minCells = lp.cellsUsed;
- minCellsAt = 1 << i;
- minCellsItemCount = 1;
- } else if (lp.cellsUsed == minCells) {
- minCellsAt |= 1 << i;
- minCellsItemCount++;
- }
- }
-
- // Items that get expanded will always be in the set of smallest items when we're done.
- smallestItemsAt |= minCellsAt;
-
- if (minCellsItemCount > cellsRemaining) break; // Couldn't expand anything evenly. Stop.
-
- // We have enough cells, all minimum size items will be incremented.
- 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 this item is already at our small item count, mark it for later.
- if (lp.cellsUsed == minCells) smallestItemsAt |= 1 << i;
- continue;
- }
-
- if (centerSingleExpandedItem && lp.preventEdgeOffset && cellsRemaining == 1) {
- // Add padding to this item such that it centers.
- child.setPadding(mGeneratedItemPadding + cellSize, 0, mGeneratedItemPadding, 0);
- }
- lp.cellsUsed++;
- lp.expanded = true;
- cellsRemaining--;
- }
-
- needsExpansion = true;
- }
-
- // Divide any space left that wouldn't divide along cell boundaries
- // evenly among the smallest items
-
- final boolean singleItem = !hasOverflow && visibleItemCount == 1;
- if (cellsRemaining > 0 && smallestItemsAt != 0 &&
- (cellsRemaining < visibleItemCount - 1 || singleItem || maxCellsUsed > 1)) {
- float expandCount = Long.bitCount(smallestItemsAt);
-
- if (!singleItem) {
- // The items at the far edges may only expand by half in order to pin to either side.
- 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) {
- // If this is one of our views, expand and measure at the larger size.
- lp.extraPixels = extraPixels;
- lp.expanded = true;
- if (i == 0 && !lp.preventEdgeOffset) {
- // First item gets part of its new padding pushed out of sight.
- // The last item will get this implicitly from layout.
- lp.leftMargin = -extraPixels / 2;
- }
- needsExpansion = true;
- } else if (lp.isOverflowButton) {
- lp.extraPixels = extraPixels;
- lp.expanded = true;
- lp.rightMargin = -extraPixels / 2;
- needsExpansion = true;
- } else {
- // If we don't know what it is, give it some margins instead
- // and let it center within its space. We still want to pin
- // against the edges.
- if (i != 0) {
- lp.leftMargin = extraPixels / 2;
- }
- if (i != childCount - 1) {
- lp.rightMargin = extraPixels / 2;
- }
- }
- }
-
- cellsRemaining = 0;
- }
-
- // Remeasure any items that have had extra space allocated to them.
- 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);
- //UNUSED mMeasuredExtraWidth = cellsRemaining * cellSize;
- }
-
- /**
- * Measure a child view to fit within cell-based formatting. The child's width
- * will be measured to a whole multiple of cellSize.
- *
- * <p>Sets the expandable and cellsUsed fields of LayoutParams.
- *
- * @param child Child to measure
- * @param cellSize Size of one cell
- * @param cellsRemaining Number of cells remaining that this view can expand to fill
- * @param parentHeightMeasureSpec MeasureSpec used by the parent view
- * @param parentHeightPadding Padding present in the parent view
- * @return Number of cells this child was measured to occupy
- */
- static int measureChildForCells(View child, int cellSize, int cellsRemaining,
- 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;//getDividerWidth();
- int overflowWidth = 0;
- //UNUSED int nonOverflowWidth = 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;
- //UNUSED nonOverflowWidth += size;
- widthRemaining -= size;
- //if (hasDividerBeforeChildAt(i)) {
- //UNUSED nonOverflowWidth += dividerWidth;
- //}
- nonOverflowCount++;
- }
- }
-
- if (childCount == 1 && !hasOverflow) {
- // Center a single child
- 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
- public void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- mPresenter.dismissPopupMenus();
- }
-
- public boolean isOverflowReserved() {
- return mReserveOverflow;
- }
-
- public void setOverflowReserved(boolean reserveOverflow) {
- mReserveOverflow = reserveOverflow;
- }
-
- @Override
- protected LayoutParams generateDefaultLayoutParams() {
- LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
- LayoutParams.WRAP_CONTENT);
- params.gravity = Gravity.CENTER_VERTICAL;
- return params;
- }
-
- @Override
- public LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new LayoutParams(getContext(), attrs);
- }
-
- @Override
- protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- 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
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
- return p != null && p instanceof LayoutParams;
- }
-
- public LayoutParams generateOverflowButtonLayoutParams() {
- LayoutParams result = generateDefaultLayoutParams();
- result.isOverflowButton = true;
- return result;
- }
-
- public boolean invokeItem(MenuItemImpl item) {
- return mMenu.performItemAction(item, 0);
- }
-
- public int getWindowAnimations() {
- return 0;
- }
-
- public void initialize(MenuBuilder menu) {
- mMenu = menu;
- }
-
- //@Override
- protected boolean hasDividerBeforeChildAt(int childIndex) {
- 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;
- }
-
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- return false;
- }
-
- public interface ActionMenuChildView {
- public boolean needsDividerBefore();
- public boolean needsDividerAfter();
- }
-
- public static class LayoutParams extends LinearLayout.LayoutParams {
- public boolean isOverflowButton;
- public int cellsUsed;
- public int extraPixels;
- public boolean expandable;
- public boolean preventEdgeOffset;
-
- public boolean expanded;
-
- public LayoutParams(Context c, AttributeSet attrs) {
- super(c, attrs);
- }
-
- public LayoutParams(LayoutParams other) {
- super((LinearLayout.LayoutParams) other);
- isOverflowButton = other.isOverflowButton;
- }
-
- public LayoutParams(int width, int height) {
- super(width, height);
- isOverflowButton = false;
- }
-
- public LayoutParams(int width, int height, boolean isOverflowButton) {
- super(width, height);
- this.isOverflowButton = isOverflowButton;
- }
- }
-}