1/*
2 * Copyright (C) 2010 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 */
16
17package com.android.internal.view.menu;
18
19import java.util.ArrayList;
20import java.util.List;
21
22import android.content.ComponentName;
23import android.content.Context;
24import android.content.Intent;
25import android.content.pm.PackageManager;
26import android.content.pm.ResolveInfo;
27import android.view.KeyEvent;
28import android.view.Menu;
29import android.view.MenuItem;
30import android.view.SubMenu;
31
32/**
33 * @hide
34 */
35public class ActionMenu implements Menu {
36    private Context mContext;
37
38    private boolean mIsQwerty;
39
40    private ArrayList<ActionMenuItem> mItems;
41
42    public ActionMenu(Context context) {
43        mContext = context;
44        mItems = new ArrayList<ActionMenuItem>();
45    }
46
47    public Context getContext() {
48        return mContext;
49    }
50
51    public MenuItem add(CharSequence title) {
52        return add(0, 0, 0, title);
53    }
54
55    public MenuItem add(int titleRes) {
56        return add(0, 0, 0, titleRes);
57    }
58
59    public MenuItem add(int groupId, int itemId, int order, int titleRes) {
60        return add(groupId, itemId, order, mContext.getResources().getString(titleRes));
61    }
62
63    public MenuItem add(int groupId, int itemId, int order, CharSequence title) {
64        ActionMenuItem item = new ActionMenuItem(getContext(),
65                groupId, itemId, 0, order, title);
66        mItems.add(order, item);
67        return item;
68    }
69
70    public int addIntentOptions(int groupId, int itemId, int order,
71            ComponentName caller, Intent[] specifics, Intent intent, int flags,
72            MenuItem[] outSpecificItems) {
73        PackageManager pm = mContext.getPackageManager();
74        final List<ResolveInfo> lri =
75                pm.queryIntentActivityOptions(caller, specifics, intent, 0);
76        final int N = lri != null ? lri.size() : 0;
77
78        if ((flags & FLAG_APPEND_TO_GROUP) == 0) {
79            removeGroup(groupId);
80        }
81
82        for (int i=0; i<N; i++) {
83            final ResolveInfo ri = lri.get(i);
84            Intent rintent = new Intent(
85                ri.specificIndex < 0 ? intent : specifics[ri.specificIndex]);
86            rintent.setComponent(new ComponentName(
87                    ri.activityInfo.applicationInfo.packageName,
88                    ri.activityInfo.name));
89            final MenuItem item = add(groupId, itemId, order, ri.loadLabel(pm))
90                    .setIcon(ri.loadIcon(pm))
91                    .setIntent(rintent);
92            if (outSpecificItems != null && ri.specificIndex >= 0) {
93                outSpecificItems[ri.specificIndex] = item;
94            }
95        }
96
97        return N;
98    }
99
100    public SubMenu addSubMenu(CharSequence title) {
101        // TODO Implement submenus
102        return null;
103    }
104
105    public SubMenu addSubMenu(int titleRes) {
106        // TODO Implement submenus
107        return null;
108    }
109
110    public SubMenu addSubMenu(int groupId, int itemId, int order,
111            CharSequence title) {
112        // TODO Implement submenus
113        return null;
114    }
115
116    public SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes) {
117        // TODO Implement submenus
118        return null;
119    }
120
121    public void clear() {
122        mItems.clear();
123    }
124
125    public void close() {
126    }
127
128    private int findItemIndex(int id) {
129        final ArrayList<ActionMenuItem> items = mItems;
130        final int itemCount = items.size();
131        for (int i = 0; i < itemCount; i++) {
132            if (items.get(i).getItemId() == id) {
133                return i;
134            }
135        }
136
137        return -1;
138    }
139
140    public MenuItem findItem(int id) {
141        return mItems.get(findItemIndex(id));
142    }
143
144    public MenuItem getItem(int index) {
145        return mItems.get(index);
146    }
147
148    public boolean hasVisibleItems() {
149        final ArrayList<ActionMenuItem> items = mItems;
150        final int itemCount = items.size();
151
152        for (int i = 0; i < itemCount; i++) {
153            if (items.get(i).isVisible()) {
154                return true;
155            }
156        }
157
158        return false;
159    }
160
161    private ActionMenuItem findItemWithShortcut(int keyCode, KeyEvent event) {
162        // TODO Make this smarter.
163        final boolean qwerty = mIsQwerty;
164        final ArrayList<ActionMenuItem> items = mItems;
165        final int itemCount = items.size();
166        final int modifierState = event.getModifiers();
167        for (int i = 0; i < itemCount; i++) {
168            ActionMenuItem item = items.get(i);
169            final char shortcut = qwerty ? item.getAlphabeticShortcut() :
170                    item.getNumericShortcut();
171            final int shortcutModifiers =
172                    qwerty ? item.getAlphabeticModifiers() : item.getNumericModifiers();
173            final boolean is_modifiers_exact_match = (modifierState & SUPPORTED_MODIFIERS_MASK)
174                    == (shortcutModifiers & SUPPORTED_MODIFIERS_MASK);
175            if ((keyCode == shortcut) && is_modifiers_exact_match) {
176                return item;
177            }
178        }
179        return null;
180    }
181
182    public boolean isShortcutKey(int keyCode, KeyEvent event) {
183        return findItemWithShortcut(keyCode, event) != null;
184    }
185
186    public boolean performIdentifierAction(int id, int flags) {
187        final int index = findItemIndex(id);
188        if (index < 0) {
189            return false;
190        }
191
192        return mItems.get(index).invoke();
193    }
194
195    public boolean performShortcut(int keyCode, KeyEvent event, int flags) {
196        ActionMenuItem item = findItemWithShortcut(keyCode, event);
197        if (item == null) {
198            return false;
199        }
200
201        return item.invoke();
202    }
203
204    public void removeGroup(int groupId) {
205        final ArrayList<ActionMenuItem> items = mItems;
206        int itemCount = items.size();
207        int i = 0;
208        while (i < itemCount) {
209            if (items.get(i).getGroupId() == groupId) {
210                items.remove(i);
211                itemCount--;
212            } else {
213                i++;
214            }
215        }
216    }
217
218    public void removeItem(int id) {
219        mItems.remove(findItemIndex(id));
220    }
221
222    public void setGroupCheckable(int group, boolean checkable,
223            boolean exclusive) {
224        final ArrayList<ActionMenuItem> items = mItems;
225        final int itemCount = items.size();
226
227        for (int i = 0; i < itemCount; i++) {
228            ActionMenuItem item = items.get(i);
229            if (item.getGroupId() == group) {
230                item.setCheckable(checkable);
231                item.setExclusiveCheckable(exclusive);
232            }
233        }
234    }
235
236    public void setGroupEnabled(int group, boolean enabled) {
237        final ArrayList<ActionMenuItem> items = mItems;
238        final int itemCount = items.size();
239
240        for (int i = 0; i < itemCount; i++) {
241            ActionMenuItem item = items.get(i);
242            if (item.getGroupId() == group) {
243                item.setEnabled(enabled);
244            }
245        }
246    }
247
248    public void setGroupVisible(int group, boolean visible) {
249        final ArrayList<ActionMenuItem> items = mItems;
250        final int itemCount = items.size();
251
252        for (int i = 0; i < itemCount; i++) {
253            ActionMenuItem item = items.get(i);
254            if (item.getGroupId() == group) {
255                item.setVisible(visible);
256            }
257        }
258    }
259
260    public void setQwertyMode(boolean isQwerty) {
261        mIsQwerty = isQwerty;
262    }
263
264    public int size() {
265        return mItems.size();
266    }
267}
268