1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package com.android.internal.view.menu; 17 18import com.android.internal.view.menu.MenuView.ItemView; 19 20import android.content.Context; 21import android.os.Bundle; 22import android.os.Parcelable; 23import android.util.SparseArray; 24import android.view.ContextThemeWrapper; 25import android.view.MenuItem; 26import android.view.View; 27import android.view.ViewGroup; 28 29import java.util.ArrayList; 30 31/** 32 * MenuPresenter for the classic "six-pack" icon menu. 33 */ 34public class IconMenuPresenter extends BaseMenuPresenter { 35 private IconMenuItemView mMoreView; 36 private int mMaxItems = -1; 37 38 int mOpenSubMenuId; 39 SubMenuPresenterCallback mSubMenuPresenterCallback = new SubMenuPresenterCallback(); 40 MenuDialogHelper mOpenSubMenu; 41 42 private static final String VIEWS_TAG = "android:menu:icon"; 43 private static final String OPEN_SUBMENU_KEY = "android:menu:icon:submenu"; 44 45 public IconMenuPresenter(Context context) { 46 super(new ContextThemeWrapper(context, com.android.internal.R.style.Theme_IconMenu), 47 com.android.internal.R.layout.icon_menu_layout, 48 com.android.internal.R.layout.icon_menu_item_layout); 49 } 50 51 @Override 52 public void initForMenu(Context context, MenuBuilder menu) { 53 super.initForMenu(context, menu); 54 mMaxItems = -1; 55 } 56 57 @Override 58 public void bindItemView(MenuItemImpl item, ItemView itemView) { 59 final IconMenuItemView view = (IconMenuItemView) itemView; 60 view.setItemData(item); 61 62 view.initialize(item.getTitleForItemView(view), item.getIcon()); 63 64 view.setVisibility(item.isVisible() ? View.VISIBLE : View.GONE); 65 view.setEnabled(view.isEnabled()); 66 view.setLayoutParams(view.getTextAppropriateLayoutParams()); 67 } 68 69 @Override 70 public boolean shouldIncludeItem(int childIndex, MenuItemImpl item) { 71 final ArrayList<MenuItemImpl> itemsToShow = mMenu.getNonActionItems(); 72 boolean fits = (itemsToShow.size() == mMaxItems && childIndex < mMaxItems) || 73 childIndex < mMaxItems - 1; 74 return fits && !item.isActionButton(); 75 } 76 77 @Override 78 protected void addItemView(View itemView, int childIndex) { 79 final IconMenuItemView v = (IconMenuItemView) itemView; 80 final IconMenuView parent = (IconMenuView) mMenuView; 81 82 v.setIconMenuView(parent); 83 v.setItemInvoker(parent); 84 v.setBackgroundDrawable(parent.getItemBackgroundDrawable()); 85 super.addItemView(itemView, childIndex); 86 } 87 88 @Override 89 public boolean onSubMenuSelected(SubMenuBuilder subMenu) { 90 if (!subMenu.hasVisibleItems()) return false; 91 92 // The window manager will give us a token. 93 MenuDialogHelper helper = new MenuDialogHelper(subMenu); 94 helper.setPresenterCallback(mSubMenuPresenterCallback); 95 helper.show(null); 96 mOpenSubMenu = helper; 97 mOpenSubMenuId = subMenu.getItem().getItemId(); 98 super.onSubMenuSelected(subMenu); 99 return true; 100 } 101 102 @Override 103 public void updateMenuView(boolean cleared) { 104 final IconMenuView menuView = (IconMenuView) mMenuView; 105 if (mMaxItems < 0) mMaxItems = menuView.getMaxItems(); 106 final ArrayList<MenuItemImpl> itemsToShow = mMenu.getNonActionItems(); 107 final boolean needsMore = itemsToShow.size() > mMaxItems; 108 super.updateMenuView(cleared); 109 110 if (needsMore && (mMoreView == null || mMoreView.getParent() != menuView)) { 111 if (mMoreView == null) { 112 mMoreView = menuView.createMoreItemView(); 113 mMoreView.setBackgroundDrawable(menuView.getItemBackgroundDrawable()); 114 } 115 menuView.addView(mMoreView); 116 } else if (!needsMore && mMoreView != null) { 117 menuView.removeView(mMoreView); 118 } 119 120 menuView.setNumActualItemsShown(needsMore ? mMaxItems - 1 : itemsToShow.size()); 121 } 122 123 @Override 124 protected boolean filterLeftoverView(ViewGroup parent, int childIndex) { 125 if (parent.getChildAt(childIndex) != mMoreView) { 126 return super.filterLeftoverView(parent, childIndex); 127 } 128 return false; 129 } 130 131 public int getNumActualItemsShown() { 132 return ((IconMenuView) mMenuView).getNumActualItemsShown(); 133 } 134 135 public void saveHierarchyState(Bundle outState) { 136 SparseArray<Parcelable> viewStates = new SparseArray<Parcelable>(); 137 if (mMenuView != null) { 138 ((View) mMenuView).saveHierarchyState(viewStates); 139 } 140 outState.putSparseParcelableArray(VIEWS_TAG, viewStates); 141 } 142 143 public void restoreHierarchyState(Bundle inState) { 144 SparseArray<Parcelable> viewStates = inState.getSparseParcelableArray(VIEWS_TAG); 145 if (viewStates != null) { 146 ((View) mMenuView).restoreHierarchyState(viewStates); 147 } 148 int subMenuId = inState.getInt(OPEN_SUBMENU_KEY, 0); 149 if (subMenuId > 0 && mMenu != null) { 150 MenuItem item = mMenu.findItem(subMenuId); 151 if (item != null) { 152 onSubMenuSelected((SubMenuBuilder) item.getSubMenu()); 153 } 154 } 155 } 156 157 @Override 158 public Parcelable onSaveInstanceState() { 159 if (mMenuView == null) { 160 return null; 161 } 162 163 Bundle state = new Bundle(); 164 saveHierarchyState(state); 165 if (mOpenSubMenuId > 0) { 166 state.putInt(OPEN_SUBMENU_KEY, mOpenSubMenuId); 167 } 168 return state; 169 } 170 171 @Override 172 public void onRestoreInstanceState(Parcelable state) { 173 restoreHierarchyState((Bundle) state); 174 } 175 176 class SubMenuPresenterCallback implements MenuPresenter.Callback { 177 @Override 178 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 179 mOpenSubMenuId = 0; 180 if (mOpenSubMenu != null) { 181 mOpenSubMenu.dismiss(); 182 mOpenSubMenu = null; 183 } 184 } 185 186 @Override 187 public boolean onOpenSubMenu(MenuBuilder subMenu) { 188 if (subMenu != null) { 189 mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId(); 190 } 191 return false; 192 } 193 194 } 195} 196