Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / android / java / src / org / chromium / chrome / browser / appmenu / AppMenuHandler.java
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.
4
5 package org.chromium.chrome.browser.appmenu;
6
7 import android.app.Activity;
8 import android.content.res.TypedArray;
9 import android.graphics.Rect;
10 import android.graphics.drawable.Drawable;
11 import android.view.ContextThemeWrapper;
12 import android.view.Menu;
13 import android.view.MenuItem;
14 import android.view.View;
15 import android.widget.PopupMenu;
16
17 import com.google.common.annotations.VisibleForTesting;
18
19 import org.chromium.chrome.browser.UmaBridge;
20
21 import java.util.ArrayList;
22
23 /**
24  * Object responsible for handling the creation, showing, hiding of the AppMenu and notifying the
25  * AppMenuObservers about these actions.
26  */
27 public class AppMenuHandler {
28     private AppMenu mAppMenu;
29     private AppMenuDragHelper mAppMenuDragHelper;
30     private Menu mMenu;
31     private final ArrayList<AppMenuObserver> mObservers;
32     private final int mMenuResourceId;
33
34     private final AppMenuPropertiesDelegate mDelegate;
35     private final Activity mActivity;
36
37     /**
38      * Constructs an AppMenuHandler object.
39      * @param activity Activity that is using the AppMenu.
40      * @param delegate Delegate used to check the desired AppMenu properties on show.
41      * @param menuResourceId Resource Id that should be used as the source for the menu items.
42      *            It is assumed to have back_menu_id, forward_menu_id, bookmark_this_page_id.
43      */
44     public AppMenuHandler(Activity activity, AppMenuPropertiesDelegate delegate,
45             int menuResourceId) {
46         mActivity = activity;
47         mDelegate = delegate;
48         mObservers = new ArrayList<AppMenuObserver>();
49         mMenuResourceId = menuResourceId;
50     }
51
52     /**
53      * Show the app menu.
54      * @param anchorView         Anchor view (usually a menu button) to be used for the popup.
55      * @param isByHardwareButton True if hardware button triggered it. (oppose to software
56      *                           button)
57      * @param startDragging      Whether dragging is started. For example, if the app menu is
58      *                           showed by tapping on a button, this should be false. If it is
59      *                           showed by start dragging down on the menu button, this should
60      *                           be true. Note that if isByHardwareButton is true, this is
61      *                           ignored.
62      * @return True, if the menu is shown, false, if menu is not shown, example reasons:
63      *         the menu is not yet available to be shown, or the menu is already showing.
64      */
65     public boolean showAppMenu(View anchorView, boolean isByHardwareButton, boolean startDragging) {
66         if (!mDelegate.shouldShowAppMenu() || isAppMenuShowing()) return false;
67
68         if (mMenu == null) {
69             // Use a PopupMenu to create the Menu object. Note this is not the same as the
70             // AppMenu (mAppMenu) created below.
71             PopupMenu tempMenu = new PopupMenu(mActivity, anchorView);
72             tempMenu.inflate(mMenuResourceId);
73             mMenu = tempMenu.getMenu();
74         }
75         mDelegate.prepareMenu(mMenu);
76
77         if (mAppMenu == null) {
78             TypedArray a = mActivity.obtainStyledAttributes(new int[]
79                     {android.R.attr.listPreferredItemHeightSmall, android.R.attr.listDivider});
80             int itemRowHeight = a.getDimensionPixelSize(0, 0);
81             Drawable itemDivider = a.getDrawable(1);
82             int itemDividerHeight = itemDivider.getIntrinsicHeight();
83             a.recycle();
84             mAppMenu = new AppMenu(mMenu, itemRowHeight, itemDividerHeight, this,
85                     mActivity.getResources());
86             mAppMenuDragHelper = new AppMenuDragHelper(mActivity, mAppMenu, itemRowHeight);
87         }
88
89         ContextThemeWrapper wrapper = new ContextThemeWrapper(mActivity,
90                 mDelegate.getMenuThemeResourceId());
91         // Get the height and width of the display.
92         Rect appRect = new Rect();
93         mActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(appRect);
94         int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
95         mAppMenu.show(wrapper, anchorView, isByHardwareButton, rotation, appRect);
96         mAppMenuDragHelper.onShow(isByHardwareButton, startDragging);
97         UmaBridge.menuShow();
98         return true;
99     }
100
101     void appMenuDismissed() {
102         mAppMenuDragHelper.onDismiss();
103     }
104
105     /**
106      * @return Whether the App Menu is currently showing.
107      */
108     public boolean isAppMenuShowing() {
109         return mAppMenu != null && mAppMenu.isShowing();
110     }
111
112     /**
113      * @return The App Menu that the menu handler is interacting with.
114      */
115     @VisibleForTesting
116     AppMenu getAppMenu() {
117         return mAppMenu;
118     }
119
120     AppMenuDragHelper getAppMenuDragHelper() {
121         return mAppMenuDragHelper;
122     }
123
124     /**
125      * Requests to hide the App Menu.
126      */
127     public void hideAppMenu() {
128         if (mAppMenu != null && mAppMenu.isShowing()) mAppMenu.dismiss();
129     }
130
131     /**
132      * Adds the observer to App Menu.
133      * @param observer Observer that should be notified about App Menu changes.
134      */
135     public void addObserver(AppMenuObserver observer) {
136         mObservers.add(observer);
137     }
138
139     /**
140      * Removes the observer from the App Menu.
141      * @param observer Observer that should no longer be notified about App Menu changes.
142      */
143     public void removeObserver(AppMenuObserver observer) {
144         mObservers.remove(observer);
145     }
146
147     void onOptionsItemSelected(MenuItem item) {
148         mActivity.onOptionsItemSelected(item);
149     }
150
151     /**
152      * Called by AppMenu to report that the App Menu visibility has changed.
153      * @param isVisible Whether the App Menu is showing.
154      */
155     void onMenuVisibilityChanged(boolean isVisible) {
156         for (int i = 0; i < mObservers.size(); ++i) {
157             mObservers.get(i).onMenuVisibilityChanged(isVisible);
158         }
159     }
160
161     /**
162      * TODO(kkimlabs) remove this call.
163      */
164     public void hardwareMenuButtonUp() {
165         if (mAppMenuDragHelper != null) mAppMenuDragHelper.hardwareMenuButtonUp();
166     }
167 }