blob: 20939ab481dd65ad8bd5775fc56a9bb1cabcc45c [file] [log] [blame]
/*
* 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.android.internal.view.menu;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import java.util.ArrayList;
/**
* @hide
*/
public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvoker, MenuView {
private static final String TAG = "ActionMenuView";
private MenuBuilder mMenu;
private int mItemPadding;
private int mItemMargin;
private int mMaxItems;
private boolean mReserveOverflow;
private OverflowMenuButton mOverflowButton;
private MenuPopupHelper mOverflowPopup;
private Runnable mShowOverflow = new Runnable() {
public void run() {
showOverflowMenu();
}
};
public ActionMenuView(Context context) {
this(context, null);
}
public ActionMenuView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.Theme);
mItemPadding = a.getDimensionPixelOffset(
com.android.internal.R.styleable.Theme_actionButtonPadding, 0);
mItemMargin = mItemPadding / 2;
a.recycle();
// Measure for initial configuration
mMaxItems = measureMaxActionButtons();
// TODO There has to be a better way to indicate that we don't have a hard menu key.
final int screen = getResources().getConfiguration().screenLayout;
mReserveOverflow = (screen & Configuration.SCREENLAYOUT_SIZE_MASK) ==
Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
final int screen = newConfig.screenLayout;
mReserveOverflow = (screen & Configuration.SCREENLAYOUT_SIZE_MASK) ==
Configuration.SCREENLAYOUT_SIZE_XLARGE;
mMaxItems = measureMaxActionButtons();
if (mMenu != null) {
mMenu.setMaxActionItems(mMaxItems);
updateChildren(false);
}
if (mOverflowPopup != null && mOverflowPopup.isShowing()) {
mOverflowPopup.dismiss();
post(mShowOverflow);
}
}
private int measureMaxActionButtons() {
final Resources res = getResources();
final int size = res.getDimensionPixelSize(com.android.internal.R.dimen.action_icon_size);
final int spaceAvailable = res.getDisplayMetrics().widthPixels / 2;
final int itemSpace = size + mItemPadding;
return spaceAvailable / (itemSpace > 0 ? itemSpace : 1);
}
public boolean isOverflowReserved() {
return mReserveOverflow;
}
public void setOverflowReserved(boolean reserveOverflow) {
mReserveOverflow = reserveOverflow;
}
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
if (p instanceof LayoutParams) {
LayoutParams lp = (LayoutParams) p;
return lp.leftMargin == mItemMargin && lp.rightMargin == mItemMargin &&
lp.gravity == Gravity.CENTER_VERTICAL &&
lp.width == LayoutParams.WRAP_CONTENT && lp.height == LayoutParams.WRAP_CONTENT;
}
return false;
}
@Override
protected LayoutParams generateDefaultLayoutParams() {
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
params.leftMargin = mItemMargin;
params.rightMargin = mItemMargin;
params.gravity = Gravity.CENTER_VERTICAL;
return params;
}
@Override
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return generateDefaultLayoutParams();
}
public int getItemMargin() {
return mItemMargin;
}
public boolean invokeItem(MenuItemImpl item) {
return mMenu.performItemAction(item, 0);
}
public int getWindowAnimations() {
return 0;
}
public void initialize(MenuBuilder menu, int menuType) {
menu.setMaxActionItems(mMaxItems);
mMenu = menu;
updateChildren(true);
}
public void updateChildren(boolean cleared) {
final boolean reserveOverflow = mReserveOverflow;
removeAllViews();
final ArrayList<MenuItemImpl> itemsToShow = mMenu.getActionItems(reserveOverflow);
final int itemCount = itemsToShow.size();
for (int i = 0; i < itemCount; i++) {
final MenuItemImpl itemData = itemsToShow.get(i);
final View actionView = itemData.getActionView();
if (actionView != null) {
addView(actionView);
} else {
addItemView((ActionMenuItemView) itemData.getItemView(
MenuBuilder.TYPE_ACTION_BUTTON, this));
}
}
if (reserveOverflow) {
if (mMenu.getNonActionItems(true).size() > 0) {
OverflowMenuButton button = new OverflowMenuButton(mContext);
addView(button);
mOverflowButton = button;
} else {
mOverflowButton = null;
}
}
}
public boolean showOverflowMenu() {
if (mOverflowButton != null) {
final MenuPopupHelper popup =
new MenuPopupHelper(getContext(), mMenu, mOverflowButton, true);
// Post this for later; we might still need a layout for the anchor to be right.
post(new Runnable() {
public void run() {
popup.show();
}
});
mOverflowPopup = popup;
return true;
}
return false;
}
public boolean isOverflowMenuShowing() {
MenuPopupHelper popup = mOverflowPopup;
if (popup != null) {
return popup.isShowing();
}
return false;
}
public boolean hideOverflowMenu() {
MenuPopupHelper popup = mOverflowPopup;
if (popup != null) {
popup.dismiss();
return true;
}
return false;
}
private void addItemView(ActionMenuItemView view) {
view.setItemInvoker(this);
addView(view);
}
private class OverflowMenuButton extends ImageButton {
public OverflowMenuButton(Context context) {
super(context, null, com.android.internal.R.attr.actionOverflowButtonStyle);
final Resources res = context.getResources();
setClickable(true);
setFocusable(true);
setVisibility(VISIBLE);
setEnabled(true);
}
@Override
public boolean performClick() {
if (super.performClick()) {
return true;
}
// Change to overflow mode
mMenu.getCallback().onMenuModeChange(mMenu);
return true;
}
}
}