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
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            if (keyCode == shortcut) {
172                return item;
173            }
174        }
175        return null;
176    }
177
178    public boolean isShortcutKey(int keyCode, KeyEvent event) {
179        return findItemWithShortcut(keyCode, event) != null;
180    }
181
182    public boolean performIdentifierAction(int id, int flags) {
183        final int index = findItemIndex(id);
184        if (index < 0) {
185            return false;
186        }
187
188        return mItems.get(index).invoke();
189    }
190
191    public boolean performShortcut(int keyCode, KeyEvent event, int flags) {
192        ActionMenuItem item = findItemWithShortcut(keyCode, event);
193        if (item == null) {
194            return false;
195        }
196
197        return item.invoke();
198    }
199
200    public void removeGroup(int groupId) {
201        final ArrayList<ActionMenuItem> items = mItems;
202        int itemCount = items.size();
203        int i = 0;
204        while (i < itemCount) {
205            if (items.get(i).getGroupId() == groupId) {
206                items.remove(i);
207                itemCount--;
208            } else {
209                i++;
210            }
211        }
212    }
213
214    public void removeItem(int id) {
215        mItems.remove(findItemIndex(id));
216    }
217
218    public void setGroupCheckable(int group, boolean checkable,
219            boolean exclusive) {
220        final ArrayList<ActionMenuItem> items = mItems;
221        final int itemCount = items.size();
222
223        for (int i = 0; i < itemCount; i++) {
224            ActionMenuItem item = items.get(i);
225            if (item.getGroupId() == group) {
226                item.setCheckable(checkable);
227                item.setExclusiveCheckable(exclusive);
228            }
229        }
230    }
231
232    public void setGroupEnabled(int group, boolean enabled) {
233        final ArrayList<ActionMenuItem> items = mItems;
234        final int itemCount = items.size();
235
236        for (int i = 0; i < itemCount; i++) {
237            ActionMenuItem item = items.get(i);
238            if (item.getGroupId() == group) {
239                item.setEnabled(enabled);
240            }
241        }
242    }
243
244    public void setGroupVisible(int group, boolean visible) {
245        final ArrayList<ActionMenuItem> items = mItems;
246        final int itemCount = items.size();
247
248        for (int i = 0; i < itemCount; i++) {
249            ActionMenuItem item = items.get(i);
250            if (item.getGroupId() == group) {
251                item.setVisible(visible);
252            }
253        }
254    }
255
256    public void setQwertyMode(boolean isQwerty) {
257        mIsQwerty = isQwerty;
258    }
259
260    public int size() {
261        return mItems.size();
262    }
263}
264