1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.chromium.chrome.browser.appmenu;
7 import android.app.Activity;
8 import android.content.res.TypedArray;
9 import android.graphics.Rect;
10 import android.view.ContextThemeWrapper;
11 import android.view.Menu;
12 import android.view.MenuItem;
13 import android.view.View;
14 import android.widget.PopupMenu;
16 import com.google.common.annotations.VisibleForTesting;
18 import org.chromium.chrome.browser.UmaBridge;
20 import java.util.ArrayList;
23 * Object responsible for handling the creation, showing, hiding of the AppMenu and notifying the
24 * AppMenuObservers about these actions.
26 public class AppMenuHandler {
27 private AppMenu mAppMenu;
28 private AppMenuDragHelper mAppMenuDragHelper;
30 private final ArrayList<AppMenuObserver> mObservers;
31 private final int mMenuResourceId;
33 private final AppMenuPropertiesDelegate mDelegate;
34 private final Activity mActivity;
37 * Constructs an AppMenuHandler object.
38 * @param activity Activity that is using the AppMenu.
39 * @param delegate Delegate used to check the desired AppMenu properties on show.
40 * @param menuResourceId Resource Id that should be used as the source for the menu items.
41 * It is assumed to have back_menu_id, forward_menu_id, bookmark_this_page_id.
43 public AppMenuHandler(Activity activity, AppMenuPropertiesDelegate delegate,
47 mObservers = new ArrayList<AppMenuObserver>();
48 mMenuResourceId = menuResourceId;
53 * @param anchorView Anchor view (usually a menu button) to be used for the popup.
54 * @param isByHardwareButton True if hardware button triggered it. (oppose to software
56 * @param startDragging Whether dragging is started. For example, if the app menu is
57 * showed by tapping on a button, this should be false. If it is
58 * showed by start dragging down on the menu button, this should
59 * be true. Note that if isByHardwareButton is true, this is
61 * @return True, if the menu is shown, false, if menu is not shown, example reasons:
62 * the menu is not yet available to be shown, or the menu is already showing.
64 public boolean showAppMenu(View anchorView, boolean isByHardwareButton, boolean startDragging) {
65 if (!mDelegate.shouldShowAppMenu()) return false;
68 // Use a PopupMenu to create the Menu object. Note this is not the same as the
69 // AppMenu (mAppMenu) created below.
70 PopupMenu tempMenu = new PopupMenu(mActivity, anchorView);
71 tempMenu.inflate(mMenuResourceId);
72 mMenu = tempMenu.getMenu();
74 mDelegate.prepareMenu(mMenu);
76 if (mAppMenu == null) {
77 TypedArray a = mActivity.obtainStyledAttributes(
78 new int[] {android.R.attr.listPreferredItemHeightSmall});
79 int itemRowHeight = a.getDimensionPixelSize(0, 0);
81 mAppMenu = new AppMenu(mMenu, itemRowHeight, this, mActivity.getResources());
82 mAppMenuDragHelper = new AppMenuDragHelper(mActivity, mAppMenu, itemRowHeight);
85 ContextThemeWrapper wrapper = new ContextThemeWrapper(mActivity,
86 mDelegate.getMenuThemeResourceId());
87 // Get the height and width of the display.
88 Rect appRect = new Rect();
89 mActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(appRect);
90 int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
91 mAppMenu.show(wrapper, anchorView, isByHardwareButton, rotation, appRect);
92 mAppMenuDragHelper.onShow(isByHardwareButton, startDragging);
97 void appMenuDismissed() {
98 mAppMenuDragHelper.onDismiss();
102 * @return Whether the App Menu is currently showing.
104 public boolean isAppMenuShowing() {
105 return mAppMenu != null && mAppMenu.isShowing();
109 * @return The App Menu that the menu handler is interacting with.
112 AppMenu getAppMenu() {
116 AppMenuDragHelper getAppMenuDragHelper() {
117 return mAppMenuDragHelper;
121 * Requests to hide the App Menu.
123 public void hideAppMenu() {
124 if (mAppMenu != null && mAppMenu.isShowing()) mAppMenu.dismiss();
128 * Adds the observer to App Menu.
129 * @param observer Observer that should be notified about App Menu changes.
131 public void addObserver(AppMenuObserver observer) {
132 mObservers.add(observer);
136 * Removes the observer from the App Menu.
137 * @param observer Observer that should no longer be notified about App Menu changes.
139 public void removeObserver(AppMenuObserver observer) {
140 mObservers.remove(observer);
143 void onOptionsItemSelected(MenuItem item) {
144 mActivity.onOptionsItemSelected(item);
148 * Called by AppMenu to report that the App Menu visibility has changed.
149 * @param isVisible Whether the App Menu is showing.
151 void onMenuVisibilityChanged(boolean isVisible) {
152 for (int i = 0; i < mObservers.size(); ++i) {
153 mObservers.get(i).onMenuVisibilityChanged(isVisible);
158 * TODO(kkimlabs) remove this call.
160 public void hardwareMenuButtonUp() {
161 if (mAppMenuDragHelper != null) mAppMenuDragHelper.hardwareMenuButtonUp();