AppMenuHandler.java revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file. 4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)package org.chromium.chrome.browser.appmenu; 6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.app.Activity; 823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import android.content.res.TypedArray; 923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import android.graphics.Rect; 10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.view.ContextThemeWrapper; 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.view.Menu; 1223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import android.view.MenuItem; 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.view.View; 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.widget.PopupMenu; 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import com.google.common.annotations.VisibleForTesting; 1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import org.chromium.chrome.browser.UmaBridge; 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import java.util.ArrayList; 21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/** 23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Object responsible for handling the creation, showing, hiding of the AppMenu and notifying the 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * AppMenuObservers about these actions. 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) */ 26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)public class AppMenuHandler { 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private AppMenu mAppMenu; 2823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) private AppMenuDragHelper mAppMenuDragHelper; 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private Menu mMenu; 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private final ArrayList<AppMenuObserver> mObservers; 31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private final int mMenuResourceId; 32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private final AppMenuPropertiesDelegate mDelegate; 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private final Activity mActivity; 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) /** 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Constructs an AppMenuHandler object. 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @param activity Activity that is using the AppMenu. 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @param delegate Delegate used to check the desired AppMenu properties on show. 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @param menuResourceId Resource Id that should be used as the source for the menu items. 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * It is assumed to have back_menu_id, forward_menu_id, bookmark_this_page_id. 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) */ 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public AppMenuHandler(Activity activity, AppMenuPropertiesDelegate delegate, 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int menuResourceId) { 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mActivity = activity; 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mDelegate = delegate; 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mObservers = new ArrayList<AppMenuObserver>(); 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mMenuResourceId = menuResourceId; 49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) /** 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Show the app menu. 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @param anchorView Anchor view (usually a menu button) to be used for the popup. 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @param isByHardwareButton True if hardware button triggered it. (oppose to software 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * button) 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @param startDragging Whether dragging is started. For example, if the app menu is 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * showed by tapping on a button, this should be false. If it is 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * showed by start dragging down on the menu button, this should 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * be true. Note that if isByHardwareButton is true, this is 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * ignored. 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @return True, if the menu is shown, false, if menu is not shown, example reasons: 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * the menu is not yet available to be shown, or the menu is already showing. 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) */ 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public boolean showAppMenu(View anchorView, boolean isByHardwareButton, boolean startDragging) { 65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!mDelegate.shouldShowAppMenu() || isAppMenuShowing()) return false; 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (mMenu == null) { 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Use a PopupMenu to create the Menu object. Note this is not the same as the 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // AppMenu (mAppMenu) created below. 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PopupMenu tempMenu = new PopupMenu(mActivity, anchorView); 71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) tempMenu.inflate(mMenuResourceId); 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mMenu = tempMenu.getMenu(); 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mDelegate.prepareMenu(mMenu); 75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (mAppMenu == null) { 7723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) TypedArray a = mActivity.obtainStyledAttributes( 7823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) new int[] {android.R.attr.listPreferredItemHeightSmall}); 7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int itemRowHeight = a.getDimensionPixelSize(0, 0); 8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) a.recycle(); 8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) mAppMenu = new AppMenu(mMenu, itemRowHeight, this, mActivity.getResources()); 8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) mAppMenuDragHelper = new AppMenuDragHelper(mActivity, mAppMenu, itemRowHeight); 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ContextThemeWrapper wrapper = new ContextThemeWrapper(mActivity, 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mDelegate.getMenuThemeResourceId()); 8723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Get the height and width of the display. 8823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) Rect appRect = new Rect(); 8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) mActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(appRect); 9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation(); 9123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) mAppMenu.show(wrapper, anchorView, isByHardwareButton, rotation, appRect); 9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) mAppMenuDragHelper.onShow(isByHardwareButton, startDragging); 93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) UmaBridge.menuShow(); 94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 9723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) void appMenuDismissed() { 9823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) mAppMenuDragHelper.onDismiss(); 9923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 10023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) /** 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @return Whether the App Menu is currently showing. 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) */ 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public boolean isAppMenuShowing() { 105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return mAppMenu != null && mAppMenu.isShowing(); 106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) /** 109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @return The App Menu that the menu handler is interacting with. 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) */ 11123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @VisibleForTesting 112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) AppMenu getAppMenu() { 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return mAppMenu; 114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 11623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) AppMenuDragHelper getAppMenuDragHelper() { 11723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return mAppMenuDragHelper; 11823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 11923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) /** 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Requests to hide the App Menu. 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) */ 123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public void hideAppMenu() { 124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (mAppMenu != null && mAppMenu.isShowing()) mAppMenu.dismiss(); 125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) /** 128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Adds the observer to App Menu. 129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @param observer Observer that should be notified about App Menu changes. 130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) */ 131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public void addObserver(AppMenuObserver observer) { 132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mObservers.add(observer); 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) /** 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Removes the observer from the App Menu. 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @param observer Observer that should no longer be notified about App Menu changes. 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) */ 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public void removeObserver(AppMenuObserver observer) { 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mObservers.remove(observer); 141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 14323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) void onOptionsItemSelected(MenuItem item) { 14423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) mActivity.onOptionsItemSelected(item); 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) /** 14823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * Called by AppMenu to report that the App Menu visibility has changed. 14923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * @param isVisible Whether the App Menu is showing. 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) */ 15123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) void onMenuVisibilityChanged(boolean isVisible) { 152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (int i = 0; i < mObservers.size(); ++i) { 15323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) mObservers.get(i).onMenuVisibilityChanged(isVisible); 154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) /** 158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * TODO(kkimlabs) remove this call. 159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) */ 160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public void hardwareMenuButtonUp() { 16123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (mAppMenuDragHelper != null) mAppMenuDragHelper.hardwareMenuButtonUp(); 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 164