blob: 525ec229c2c859e6c08f7ec1afbb3a32a5125942 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.appmenu;
import android.app.Activity;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.ContextThemeWrapper;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.PopupMenu;
import com.google.common.annotations.VisibleForTesting;
import org.chromium.chrome.browser.UmaBridge;
import java.util.ArrayList;
/**
* Object responsible for handling the creation, showing, hiding of the AppMenu and notifying the
* AppMenuObservers about these actions.
*/
public class AppMenuHandler {
private AppMenu mAppMenu;
private AppMenuDragHelper mAppMenuDragHelper;
private Menu mMenu;
private final ArrayList<AppMenuObserver> mObservers;
private final int mMenuResourceId;
private final AppMenuPropertiesDelegate mDelegate;
private final Activity mActivity;
/**
* Constructs an AppMenuHandler object.
* @param activity Activity that is using the AppMenu.
* @param delegate Delegate used to check the desired AppMenu properties on show.
* @param menuResourceId Resource Id that should be used as the source for the menu items.
* It is assumed to have back_menu_id, forward_menu_id, bookmark_this_page_id.
*/
public AppMenuHandler(Activity activity, AppMenuPropertiesDelegate delegate,
int menuResourceId) {
mActivity = activity;
mDelegate = delegate;
mObservers = new ArrayList<AppMenuObserver>();
mMenuResourceId = menuResourceId;
}
/**
* Show the app menu.
* @param anchorView Anchor view (usually a menu button) to be used for the popup.
* @param isByHardwareButton True if hardware button triggered it. (oppose to software
* button)
* @param startDragging Whether dragging is started. For example, if the app menu is
* showed by tapping on a button, this should be false. If it is
* showed by start dragging down on the menu button, this should
* be true. Note that if isByHardwareButton is true, this must
* be false since we no longer support hardware menu button
* dragging.
* @return True, if the menu is shown, false, if menu is not shown, example reasons:
* the menu is not yet available to be shown, or the menu is already showing.
*/
public boolean showAppMenu(View anchorView, boolean isByHardwareButton, boolean startDragging) {
assert !(isByHardwareButton && startDragging);
if (!mDelegate.shouldShowAppMenu() || isAppMenuShowing()) return false;
if (mMenu == null) {
// Use a PopupMenu to create the Menu object. Note this is not the same as the
// AppMenu (mAppMenu) created below.
PopupMenu tempMenu = new PopupMenu(mActivity, anchorView);
tempMenu.inflate(mMenuResourceId);
mMenu = tempMenu.getMenu();
}
mDelegate.prepareMenu(mMenu);
ContextThemeWrapper wrapper = new ContextThemeWrapper(mActivity,
mDelegate.getMenuThemeResourceId());
if (mAppMenu == null) {
TypedArray a = wrapper.obtainStyledAttributes(new int[]
{android.R.attr.listPreferredItemHeightSmall, android.R.attr.listDivider});
int itemRowHeight = a.getDimensionPixelSize(0, 0);
Drawable itemDivider = a.getDrawable(1);
int itemDividerHeight = itemDivider != null ? itemDivider.getIntrinsicHeight() : 0;
a.recycle();
mAppMenu = new AppMenu(mMenu, itemRowHeight, itemDividerHeight, this,
mActivity.getResources());
mAppMenuDragHelper = new AppMenuDragHelper(mActivity, mAppMenu, itemRowHeight);
}
// Get the height and width of the display.
Rect appRect = new Rect();
mActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(appRect);
int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
mAppMenu.show(wrapper, anchorView, isByHardwareButton, rotation, appRect);
mAppMenuDragHelper.onShow(startDragging);
UmaBridge.menuShow();
return true;
}
void appMenuDismissed() {
mAppMenuDragHelper.onDismiss();
}
/**
* @return Whether the App Menu is currently showing.
*/
public boolean isAppMenuShowing() {
return mAppMenu != null && mAppMenu.isShowing();
}
/**
* @return The App Menu that the menu handler is interacting with.
*/
@VisibleForTesting
AppMenu getAppMenu() {
return mAppMenu;
}
AppMenuDragHelper getAppMenuDragHelper() {
return mAppMenuDragHelper;
}
/**
* Requests to hide the App Menu.
*/
public void hideAppMenu() {
if (mAppMenu != null && mAppMenu.isShowing()) mAppMenu.dismiss();
}
/**
* Adds the observer to App Menu.
* @param observer Observer that should be notified about App Menu changes.
*/
public void addObserver(AppMenuObserver observer) {
mObservers.add(observer);
}
/**
* Removes the observer from the App Menu.
* @param observer Observer that should no longer be notified about App Menu changes.
*/
public void removeObserver(AppMenuObserver observer) {
mObservers.remove(observer);
}
void onOptionsItemSelected(MenuItem item) {
mActivity.onOptionsItemSelected(item);
}
/**
* Called by AppMenu to report that the App Menu visibility has changed.
* @param isVisible Whether the App Menu is showing.
*/
void onMenuVisibilityChanged(boolean isVisible) {
for (int i = 0; i < mObservers.size(); ++i) {
mObservers.get(i).onMenuVisibilityChanged(isVisible);
}
}
}