1/*
2 * Copyright (C) 2012 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 android.support.v7.internal.view.menu;
18
19import android.annotation.TargetApi;
20import android.content.Context;
21import android.content.Intent;
22import android.graphics.drawable.Drawable;
23import android.os.Build;
24import android.support.v4.internal.view.SupportMenuItem;
25import android.support.v4.view.ActionProvider;
26import android.support.v4.view.MenuItemCompat;
27import android.support.v7.view.CollapsibleActionView;
28import android.util.Log;
29import android.view.ContextMenu;
30import android.view.MenuItem;
31import android.view.SubMenu;
32import android.view.View;
33import android.widget.FrameLayout;
34
35import java.lang.reflect.Method;
36
37/**
38 * Wraps a support {@link SupportMenuItem} as a framework {@link android.view.MenuItem}
39 * @hide
40 */
41@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
42public class MenuItemWrapperICS extends BaseMenuWrapper<SupportMenuItem> implements MenuItem {
43    static final String LOG_TAG = "MenuItemWrapper";
44
45    // Reflection Method to call setExclusiveCheckable
46    private Method mSetExclusiveCheckableMethod;
47
48    MenuItemWrapperICS(Context context, SupportMenuItem object) {
49        super(context, object);
50    }
51
52    @Override
53    public int getItemId() {
54        return mWrappedObject.getItemId();
55    }
56
57    @Override
58    public int getGroupId() {
59        return mWrappedObject.getGroupId();
60    }
61
62    @Override
63    public int getOrder() {
64        return mWrappedObject.getOrder();
65    }
66
67    @Override
68    public MenuItem setTitle(CharSequence title) {
69        mWrappedObject.setTitle(title);
70        return this;
71    }
72
73    @Override
74    public MenuItem setTitle(int title) {
75        mWrappedObject.setTitle(title);
76        return this;
77    }
78
79    @Override
80    public CharSequence getTitle() {
81        return mWrappedObject.getTitle();
82    }
83
84    @Override
85    public MenuItem setTitleCondensed(CharSequence title) {
86        mWrappedObject.setTitleCondensed(title);
87        return this;
88    }
89
90    @Override
91    public CharSequence getTitleCondensed() {
92        return mWrappedObject.getTitleCondensed();
93    }
94
95    @Override
96    public MenuItem setIcon(Drawable icon) {
97        mWrappedObject.setIcon(icon);
98        return this;
99    }
100
101    @Override
102    public MenuItem setIcon(int iconRes) {
103        mWrappedObject.setIcon(iconRes);
104        return this;
105    }
106
107    @Override
108    public Drawable getIcon() {
109        return mWrappedObject.getIcon();
110    }
111
112    @Override
113    public MenuItem setIntent(Intent intent) {
114        mWrappedObject.setIntent(intent);
115        return this;
116    }
117
118    @Override
119    public Intent getIntent() {
120        return mWrappedObject.getIntent();
121    }
122
123    @Override
124    public MenuItem setShortcut(char numericChar, char alphaChar) {
125        mWrappedObject.setShortcut(numericChar, alphaChar);
126        return this;
127    }
128
129    @Override
130    public MenuItem setNumericShortcut(char numericChar) {
131        mWrappedObject.setNumericShortcut(numericChar);
132        return this;
133    }
134
135    @Override
136    public char getNumericShortcut() {
137        return mWrappedObject.getNumericShortcut();
138    }
139
140    @Override
141    public MenuItem setAlphabeticShortcut(char alphaChar) {
142        mWrappedObject.setAlphabeticShortcut(alphaChar);
143        return this;
144    }
145
146    @Override
147    public char getAlphabeticShortcut() {
148        return mWrappedObject.getAlphabeticShortcut();
149    }
150
151    @Override
152    public MenuItem setCheckable(boolean checkable) {
153        mWrappedObject.setCheckable(checkable);
154        return this;
155    }
156
157    @Override
158    public boolean isCheckable() {
159        return mWrappedObject.isCheckable();
160    }
161
162    @Override
163    public MenuItem setChecked(boolean checked) {
164        mWrappedObject.setChecked(checked);
165        return this;
166    }
167
168    @Override
169    public boolean isChecked() {
170        return mWrappedObject.isChecked();
171    }
172
173    @Override
174    public MenuItem setVisible(boolean visible) {
175        return mWrappedObject.setVisible(visible);
176    }
177
178    @Override
179    public boolean isVisible() {
180        return mWrappedObject.isVisible();
181    }
182
183    @Override
184    public MenuItem setEnabled(boolean enabled) {
185        mWrappedObject.setEnabled(enabled);
186        return this;
187    }
188
189    @Override
190    public boolean isEnabled() {
191        return mWrappedObject.isEnabled();
192    }
193
194    @Override
195    public boolean hasSubMenu() {
196        return mWrappedObject.hasSubMenu();
197    }
198
199    @Override
200    public SubMenu getSubMenu() {
201        return getSubMenuWrapper(mWrappedObject.getSubMenu());
202    }
203
204    @Override
205    public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener menuItemClickListener) {
206        mWrappedObject.setOnMenuItemClickListener(menuItemClickListener != null ?
207                new OnMenuItemClickListenerWrapper(menuItemClickListener) : null);
208        return this;
209    }
210
211    @Override
212    public ContextMenu.ContextMenuInfo getMenuInfo() {
213        return mWrappedObject.getMenuInfo();
214    }
215
216    @Override
217    public void setShowAsAction(int actionEnum) {
218        mWrappedObject.setShowAsAction(actionEnum);
219    }
220
221    @Override
222    public MenuItem setShowAsActionFlags(int actionEnum) {
223        mWrappedObject.setShowAsActionFlags(actionEnum);
224        return this;
225    }
226
227    @Override
228    public MenuItem setActionView(View view) {
229        if (view instanceof android.view.CollapsibleActionView) {
230            view = new CollapsibleActionViewWrapper(view);
231        }
232        mWrappedObject.setActionView(view);
233        return this;
234    }
235
236    @Override
237    public MenuItem setActionView(int resId) {
238        // Make framework menu item inflate the view
239        mWrappedObject.setActionView(resId);
240
241        View actionView = mWrappedObject.getActionView();
242        if (actionView instanceof android.view.CollapsibleActionView) {
243            // If the inflated Action View is support-collapsible, wrap it
244            mWrappedObject.setActionView(new CollapsibleActionViewWrapper(actionView));
245        }
246        return this;
247    }
248
249    @Override
250    public View getActionView() {
251        View actionView = mWrappedObject.getActionView();
252        if (actionView instanceof CollapsibleActionViewWrapper) {
253            return ((CollapsibleActionViewWrapper) actionView).getWrappedView();
254        }
255        return actionView;
256    }
257
258    @Override
259    public MenuItem setActionProvider(android.view.ActionProvider provider) {
260        mWrappedObject.setSupportActionProvider(
261                provider != null ? createActionProviderWrapper(provider) : null);
262        return this;
263    }
264
265    @Override
266    public android.view.ActionProvider getActionProvider() {
267        ActionProvider provider = mWrappedObject.getSupportActionProvider();
268        if (provider instanceof ActionProviderWrapper) {
269            return ((ActionProviderWrapper) provider).mInner;
270        }
271        return null;
272    }
273
274    @Override
275    public boolean expandActionView() {
276        return mWrappedObject.expandActionView();
277    }
278
279    @Override
280    public boolean collapseActionView() {
281        return mWrappedObject.collapseActionView();
282    }
283
284    @Override
285    public boolean isActionViewExpanded() {
286        return mWrappedObject.isActionViewExpanded();
287    }
288
289    @Override
290    public MenuItem setOnActionExpandListener(MenuItem.OnActionExpandListener listener) {
291        mWrappedObject.setSupportOnActionExpandListener(listener != null ?
292                new OnActionExpandListenerWrapper(listener) : null);
293        return this;
294    }
295
296    public void setExclusiveCheckable(boolean checkable) {
297        try {
298            if (mSetExclusiveCheckableMethod == null) {
299                mSetExclusiveCheckableMethod = mWrappedObject.getClass()
300                        .getDeclaredMethod("setExclusiveCheckable", Boolean.TYPE);
301            }
302            mSetExclusiveCheckableMethod.invoke(mWrappedObject, checkable);
303        } catch (Exception e) {
304            Log.w(LOG_TAG, "Error while calling setExclusiveCheckable", e);
305        }
306    }
307
308    ActionProviderWrapper createActionProviderWrapper(android.view.ActionProvider provider) {
309        return new ActionProviderWrapper(mContext, provider);
310    }
311
312    private class OnMenuItemClickListenerWrapper extends BaseWrapper<OnMenuItemClickListener>
313            implements android.view.MenuItem.OnMenuItemClickListener {
314
315        OnMenuItemClickListenerWrapper(OnMenuItemClickListener object) {
316            super(object);
317        }
318
319        @Override
320        public boolean onMenuItemClick(android.view.MenuItem item) {
321            return mWrappedObject.onMenuItemClick(getMenuItemWrapper(item));
322        }
323    }
324
325    private class OnActionExpandListenerWrapper extends BaseWrapper<MenuItem.OnActionExpandListener>
326            implements MenuItemCompat.OnActionExpandListener {
327
328        OnActionExpandListenerWrapper(MenuItem.OnActionExpandListener object) {
329            super(object);
330        }
331
332        @Override
333        public boolean onMenuItemActionExpand(android.view.MenuItem item) {
334            return mWrappedObject.onMenuItemActionExpand(getMenuItemWrapper(item));
335        }
336
337        @Override
338        public boolean onMenuItemActionCollapse(android.view.MenuItem item) {
339            return mWrappedObject.onMenuItemActionCollapse(getMenuItemWrapper(item));
340        }
341    }
342
343    class ActionProviderWrapper extends android.support.v4.view.ActionProvider {
344        final android.view.ActionProvider mInner;
345
346        public ActionProviderWrapper(Context context, android.view.ActionProvider inner) {
347            super(context);
348            mInner = inner;
349        }
350
351        @Override
352        public View onCreateActionView() {
353            return mInner.onCreateActionView();
354        }
355
356        @Override
357        public boolean onPerformDefaultAction() {
358            return mInner.onPerformDefaultAction();
359        }
360
361        @Override
362        public boolean hasSubMenu() {
363            return mInner.hasSubMenu();
364        }
365
366        @Override
367        public void onPrepareSubMenu(android.view.SubMenu subMenu) {
368            mInner.onPrepareSubMenu(getSubMenuWrapper(subMenu));
369        }
370    }
371
372    /**
373     * Wrap a support {@link android.support.v7.view.CollapsibleActionView} into a framework
374     * {@link android.view.CollapsibleActionView}.
375     */
376    static class CollapsibleActionViewWrapper extends FrameLayout
377            implements CollapsibleActionView {
378
379        final android.view.CollapsibleActionView mWrappedView;
380
381        CollapsibleActionViewWrapper(View actionView) {
382            super(actionView.getContext());
383            mWrappedView = (android.view.CollapsibleActionView) actionView;
384            addView(actionView);
385        }
386
387        @Override
388        public void onActionViewExpanded() {
389            mWrappedView.onActionViewExpanded();
390        }
391
392        @Override
393        public void onActionViewCollapsed() {
394            mWrappedView.onActionViewCollapsed();
395        }
396
397        View getWrappedView() {
398            return (View) mWrappedView;
399        }
400    }
401}
402