18262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns/*
28262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * Copyright (C) 2013 The Android Open Source Project
38262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns *
48262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * Licensed under the Apache License, Version 2.0 (the "License");
58262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * you may not use this file except in compliance with the License.
68262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * You may obtain a copy of the License at
78262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns *
88262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns *      http://www.apache.org/licenses/LICENSE-2.0
98262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns *
108262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * Unless required by applicable law or agreed to in writing, software
118262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * distributed under the License is distributed on an "AS IS" BASIS,
128262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * See the License for the specific language governing permissions and
148262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * limitations under the License.
158262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns */
168262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.appcompat.view;
188262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
20592df2e7552ba6902c9750ab8453850fc9e30334Chris Banes
218262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.app.Activity;
228262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.content.Context;
23eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyarimport android.content.ContextWrapper;
243a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikovimport android.content.res.ColorStateList;
258262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.content.res.TypedArray;
268262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.content.res.XmlResourceParser;
273a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikovimport android.graphics.PorterDuff;
288262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.util.AttributeSet;
298262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.util.Log;
308262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.util.Xml;
318262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.view.InflateException;
3209231da6d922e91d30d06876521106f13230a791Peeyush Agarwalimport android.view.KeyEvent;
3330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.Menu;
3430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.MenuInflater;
3530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.MenuItem;
3630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.SubMenu;
378262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.view.View;
388262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
393de8a4e8305507475d7890205184946a25cf45e7Aurimas Liutikasimport androidx.annotation.LayoutRes;
403de8a4e8305507475d7890205184946a25cf45e7Aurimas Liutikasimport androidx.annotation.RestrictTo;
413de8a4e8305507475d7890205184946a25cf45e7Aurimas Liutikasimport androidx.appcompat.R;
423de8a4e8305507475d7890205184946a25cf45e7Aurimas Liutikasimport androidx.appcompat.view.menu.MenuItemImpl;
433de8a4e8305507475d7890205184946a25cf45e7Aurimas Liutikasimport androidx.appcompat.view.menu.MenuItemWrapperICS;
443de8a4e8305507475d7890205184946a25cf45e7Aurimas Liutikasimport androidx.appcompat.widget.DrawableUtils;
453de8a4e8305507475d7890205184946a25cf45e7Aurimas Liutikasimport androidx.core.internal.view.SupportMenu;
463de8a4e8305507475d7890205184946a25cf45e7Aurimas Liutikasimport androidx.core.view.ActionProvider;
473de8a4e8305507475d7890205184946a25cf45e7Aurimas Liutikasimport androidx.core.view.MenuItemCompat;
483de8a4e8305507475d7890205184946a25cf45e7Aurimas Liutikas
498e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikasimport org.xmlpull.v1.XmlPullParser;
508e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikasimport org.xmlpull.v1.XmlPullParserException;
518e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikas
528262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport java.io.IOException;
538262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport java.lang.reflect.Constructor;
548262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport java.lang.reflect.Method;
558262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
568262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns/**
578262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * This class is used to instantiate menu XML files into Menu objects.
588262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * <p>
598262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * For performance reasons, menu inflation relies heavily on pre-processing of
608262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * XML files that is done at build time. Therefore, it is not currently possible
61e0f27d39b0a4f0ef30ef6446e7b675279961cc94Chris Banes * to use SupportMenuInflater with an XmlPullParser over a plain XML file at runtime;
628262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * it only works with an XmlPullParser returned from a compiled resource (R.
638262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * <em>something</em> file.)
6489208232f3b5d1451408d787872504a190bc7ee0Chris Banes *
6589208232f3b5d1451408d787872504a190bc7ee0Chris Banes * @hide
668262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns */
678e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikas@RestrictTo(LIBRARY_GROUP)
6830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellpublic class SupportMenuInflater extends MenuInflater {
692c1bad7ecd5879bf0f29ce2ce1bc5bd67a3f4682Aurimas Liutikas    static final String LOG_TAG = "SupportMenuInflater";
708262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
718262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    /** Menu tag name in XML. */
728262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    private static final String XML_MENU = "menu";
738262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
748262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    /** Group tag name in XML. */
758262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    private static final String XML_GROUP = "group";
768262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
778262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    /** Item tag name in XML. */
788262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    private static final String XML_ITEM = "item";
798262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
802c1bad7ecd5879bf0f29ce2ce1bc5bd67a3f4682Aurimas Liutikas    static final int NO_ID = 0;
818262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
822c1bad7ecd5879bf0f29ce2ce1bc5bd67a3f4682Aurimas Liutikas    static final Class<?>[] ACTION_VIEW_CONSTRUCTOR_SIGNATURE = new Class[] {Context.class};
838262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
842c1bad7ecd5879bf0f29ce2ce1bc5bd67a3f4682Aurimas Liutikas    static final Class<?>[] ACTION_PROVIDER_CONSTRUCTOR_SIGNATURE =
858262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            ACTION_VIEW_CONSTRUCTOR_SIGNATURE;
868262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
872c1bad7ecd5879bf0f29ce2ce1bc5bd67a3f4682Aurimas Liutikas    final Object[] mActionViewConstructorArguments;
888262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
892c1bad7ecd5879bf0f29ce2ce1bc5bd67a3f4682Aurimas Liutikas    final Object[] mActionProviderConstructorArguments;
908262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
912c1bad7ecd5879bf0f29ce2ce1bc5bd67a3f4682Aurimas Liutikas    Context mContext;
928262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    private Object mRealOwner;
938262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
948262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    /**
958262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     * Constructs a menu inflater.
968262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     *
978262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     * @see Activity#getMenuInflater()
988262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     */
99e0f27d39b0a4f0ef30ef6446e7b675279961cc94Chris Banes    public SupportMenuInflater(Context context) {
10030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        super(context);
1018262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        mContext = context;
1028262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        mActionViewConstructorArguments = new Object[] {context};
1038262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        mActionProviderConstructorArguments = mActionViewConstructorArguments;
1048262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    }
1058262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1068262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    /**
1078262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     * Inflate a menu hierarchy from the specified XML resource. Throws
1088262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     * {@link InflateException} if there is an error.
1098262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     *
1108262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     * @param menuRes Resource ID for an XML layout resource to load (e.g.,
1118262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     *            <code>R.menu.main_activity</code>)
1128262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     * @param menu The Menu to inflate into. The items and submenus will be
1138262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     *            added to this Menu.
1148262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     */
115e0f27d39b0a4f0ef30ef6446e7b675279961cc94Chris Banes    @Override
11650b45b25e10ddbfd726b91910e00bce6a1c63904Aurimas Liutikas    public void inflate(@LayoutRes int menuRes, Menu menu) {
11703527a1c5ca870353671fd8b97a08a989fe62012Chris Banes        // If we're not dealing with a SupportMenu instance, let super handle
11803527a1c5ca870353671fd8b97a08a989fe62012Chris Banes        if (!(menu instanceof SupportMenu)) {
11903527a1c5ca870353671fd8b97a08a989fe62012Chris Banes            super.inflate(menuRes, menu);
12003527a1c5ca870353671fd8b97a08a989fe62012Chris Banes            return;
12103527a1c5ca870353671fd8b97a08a989fe62012Chris Banes        }
12203527a1c5ca870353671fd8b97a08a989fe62012Chris Banes
1238262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        XmlResourceParser parser = null;
1248262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        try {
1258262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            parser = mContext.getResources().getLayout(menuRes);
1268262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            AttributeSet attrs = Xml.asAttributeSet(parser);
1278262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1288262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            parseMenu(parser, attrs, menu);
1298262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        } catch (XmlPullParserException e) {
1308262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            throw new InflateException("Error inflating menu XML", e);
1318262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        } catch (IOException e) {
1328262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            throw new InflateException("Error inflating menu XML", e);
1338262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        } finally {
1348262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            if (parser != null) parser.close();
1358262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
1368262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    }
1378262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1388262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    /**
1398262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     * Called internally to fill the given menu. If a sub menu is seen, it will
1408262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     * call this recursively.
1418262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     */
1428262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    private void parseMenu(XmlPullParser parser, AttributeSet attrs, Menu menu)
1438262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            throws XmlPullParserException, IOException {
1448262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        MenuState menuState = new MenuState(menu);
1458262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1468262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        int eventType = parser.getEventType();
1478262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        String tagName;
1488262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        boolean lookingForEndOfUnknownTag = false;
1498262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        String unknownTagName = null;
1508262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1518262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        // This loop will skip to the menu start tag
1528262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        do {
1538262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            if (eventType == XmlPullParser.START_TAG) {
1548262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                tagName = parser.getName();
1558262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                if (tagName.equals(XML_MENU)) {
1568262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    // Go to next tag
1578262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    eventType = parser.next();
1588262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    break;
1598262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                }
1608262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1618262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                throw new RuntimeException("Expecting menu, got " + tagName);
1628262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            }
1638262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            eventType = parser.next();
1648262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        } while (eventType != XmlPullParser.END_DOCUMENT);
1658262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1668262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        boolean reachedEndOfMenu = false;
1678262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        while (!reachedEndOfMenu) {
1688262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            switch (eventType) {
1698262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                case XmlPullParser.START_TAG:
1708262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    if (lookingForEndOfUnknownTag) {
1718262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        break;
1728262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    }
1738262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1748262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    tagName = parser.getName();
1758262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    if (tagName.equals(XML_GROUP)) {
1768262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        menuState.readGroup(attrs);
1778262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    } else if (tagName.equals(XML_ITEM)) {
1788262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        menuState.readItem(attrs);
1798262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    } else if (tagName.equals(XML_MENU)) {
1808262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        // A menu start tag denotes a submenu for an item
1818262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        SubMenu subMenu = menuState.addSubMenuItem();
1828262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1838262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        // Parse the submenu into returned SubMenu
1848262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        parseMenu(parser, attrs, subMenu);
1858262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    } else {
1868262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        lookingForEndOfUnknownTag = true;
1878262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        unknownTagName = tagName;
1888262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    }
1898262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    break;
1908262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1918262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                case XmlPullParser.END_TAG:
1928262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    tagName = parser.getName();
1938262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    if (lookingForEndOfUnknownTag && tagName.equals(unknownTagName)) {
1948262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        lookingForEndOfUnknownTag = false;
1958262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        unknownTagName = null;
1968262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    } else if (tagName.equals(XML_GROUP)) {
1978262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        menuState.resetGroup();
1988262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    } else if (tagName.equals(XML_ITEM)) {
1998262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        // Add the item if it hasn't been added (if the item was
2008262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        // a submenu, it would have been added already)
2018262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        if (!menuState.hasAddedItem()) {
2028262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                            if (menuState.itemActionProvider != null &&
2038262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                                    menuState.itemActionProvider.hasSubMenu()) {
2048262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                                menuState.addSubMenuItem();
2058262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                            } else {
2068262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                                menuState.addItem();
2078262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                            }
2088262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        }
2098262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    } else if (tagName.equals(XML_MENU)) {
2108262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        reachedEndOfMenu = true;
2118262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    }
2128262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    break;
2138262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
2148262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                case XmlPullParser.END_DOCUMENT:
2158262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    throw new RuntimeException("Unexpected end of document");
2168262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            }
2178262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
2188262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            eventType = parser.next();
2198262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
2208262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    }
2218262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
2222c1bad7ecd5879bf0f29ce2ce1bc5bd67a3f4682Aurimas Liutikas    Object getRealOwner() {
223eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyar        if (mRealOwner == null) {
224eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyar            mRealOwner = findRealOwner(mContext);
225eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyar        }
226eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyar        return mRealOwner;
227eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyar    }
228eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyar
229eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyar    private Object findRealOwner(Object owner) {
230eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyar        if (owner instanceof Activity) {
231eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyar            return owner;
232eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyar        }
233eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyar        if (owner instanceof ContextWrapper) {
234eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyar            return findRealOwner(((ContextWrapper) owner).getBaseContext());
235eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyar        }
236eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyar        return owner;
237eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyar    }
238eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyar
2398262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    private static class InflatedOnMenuItemClickListener
2408262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            implements MenuItem.OnMenuItemClickListener {
2418262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private static final Class<?>[] PARAM_TYPES = new Class[] { MenuItem.class };
2428262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
2438262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private Object mRealOwner;
2448262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private Method mMethod;
2458262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
2468262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        public InflatedOnMenuItemClickListener(Object realOwner, String methodName) {
2478262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            mRealOwner = realOwner;
2488262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            Class<?> c = realOwner.getClass();
2498262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            try {
2508262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                mMethod = c.getMethod(methodName, PARAM_TYPES);
2518262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            } catch (Exception e) {
2528262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                InflateException ex = new InflateException(
2538262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        "Couldn't resolve menu item onClick handler " + methodName +
2548262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                                " in class " + c.getName());
2558262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                ex.initCause(e);
2568262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                throw ex;
2578262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            }
2588262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
2598262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
260e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas        @Override
2618262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        public boolean onMenuItemClick(MenuItem item) {
2628262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            try {
2638262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                if (mMethod.getReturnType() == Boolean.TYPE) {
2648262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    return (Boolean) mMethod.invoke(mRealOwner, item);
2658262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                } else {
2668262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    mMethod.invoke(mRealOwner, item);
2678262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    return true;
2688262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                }
2698262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            } catch (Exception e) {
2708262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                throw new RuntimeException(e);
2718262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            }
2728262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
2738262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    }
2748262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
2758262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    /**
2768262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     * State for the current menu.
2778262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     * <p>
2788262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     * Groups can not be nested unless there is another menu (which will have
2798262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     * its state class).
2808262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     */
2818262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    private class MenuState {
2828262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private Menu menu;
2838262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
2848262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        /*
2858262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         * Group state is set on items as they are added, allowing an item to
2868262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         * override its group state. (As opposed to set on items at the group end tag.)
2878262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         */
2888262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private int groupId;
2898262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private int groupCategory;
2908262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private int groupOrder;
2918262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private int groupCheckable;
2928262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private boolean groupVisible;
2938262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private boolean groupEnabled;
2948262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
2958262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private boolean itemAdded;
2968262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private int itemId;
2978262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private int itemCategoryOrder;
2988262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private CharSequence itemTitle;
2998262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private CharSequence itemTitleCondensed;
3008262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private int itemIconResId;
3018262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private char itemAlphabeticShortcut;
30209231da6d922e91d30d06876521106f13230a791Peeyush Agarwal        private int itemAlphabeticModifiers;
3038262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private char itemNumericShortcut;
30409231da6d922e91d30d06876521106f13230a791Peeyush Agarwal        private int itemNumericModifiers;
3058262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        /**
3068262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         * Sync to attrs.xml enum:
3078262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         * - 0: none
3088262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         * - 1: all
3098262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         * - 2: exclusive
3108262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         */
3118262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private int itemCheckable;
3128262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private boolean itemChecked;
3138262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private boolean itemVisible;
3148262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private boolean itemEnabled;
3158262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
3168262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        /**
3178262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         * Sync to attrs.xml enum, values in MenuItem:
3188262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         * - 0: never
3198262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         * - 1: ifRoom
3208262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         * - 2: always
3218262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         * - -1: Safe sentinel for "no value".
3228262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         */
3238262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private int itemShowAsAction;
3248262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
3258262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private int itemActionViewLayout;
3268262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private String itemActionViewClassName;
3278262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private String itemActionProviderClassName;
3288262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
3298262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private String itemListenerMethodName;
3308262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
3312c1bad7ecd5879bf0f29ce2ce1bc5bd67a3f4682Aurimas Liutikas        ActionProvider itemActionProvider;
3328262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
333fd3c4560bf2348f6a06272a9f02105c9e1bf927eVladislav Kaznacheev        private CharSequence itemContentDescription;
334fd3c4560bf2348f6a06272a9f02105c9e1bf927eVladislav Kaznacheev        private CharSequence itemTooltipText;
335fd3c4560bf2348f6a06272a9f02105c9e1bf927eVladislav Kaznacheev
3363a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov        private ColorStateList itemIconTintList = null;
3373a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov        private PorterDuff.Mode itemIconTintMode = null;
3383a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov
3398262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private static final int defaultGroupId = NO_ID;
3408262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private static final int defaultItemId = NO_ID;
3418262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private static final int defaultItemCategory = 0;
3428262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private static final int defaultItemOrder = 0;
3438262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private static final int defaultItemCheckable = 0;
3448262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private static final boolean defaultItemChecked = false;
3458262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private static final boolean defaultItemVisible = true;
3468262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private static final boolean defaultItemEnabled = true;
3478262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
3488262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        public MenuState(final Menu menu) {
3498262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            this.menu = menu;
3508262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
3518262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            resetGroup();
3528262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
3538262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
3548262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        public void resetGroup() {
3558262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            groupId = defaultGroupId;
3568262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            groupCategory = defaultItemCategory;
3578262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            groupOrder = defaultItemOrder;
3588262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            groupCheckable = defaultItemCheckable;
3598262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            groupVisible = defaultItemVisible;
3608262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            groupEnabled = defaultItemEnabled;
3618262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
3628262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
3638262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        /**
3648262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         * Called when the parser is pointing to a group tag.
3658262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         */
3668262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        public void readGroup(AttributeSet attrs) {
3678262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.MenuGroup);
3688262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
3698262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            groupId = a.getResourceId(R.styleable.MenuGroup_android_id, defaultGroupId);
3708262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            groupCategory = a.getInt(
3718262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    R.styleable.MenuGroup_android_menuCategory, defaultItemCategory);
3728262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            groupOrder = a.getInt(R.styleable.MenuGroup_android_orderInCategory, defaultItemOrder);
3738262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            groupCheckable = a.getInt(
3748262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    R.styleable.MenuGroup_android_checkableBehavior, defaultItemCheckable);
3758262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            groupVisible = a.getBoolean(R.styleable.MenuGroup_android_visible, defaultItemVisible);
3768262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            groupEnabled = a.getBoolean(R.styleable.MenuGroup_android_enabled, defaultItemEnabled);
3778262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
3788262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            a.recycle();
3798262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
3808262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
3818262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        /**
3828262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         * Called when the parser is pointing to an item tag.
3838262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns         */
3848262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        public void readItem(AttributeSet attrs) {
3858262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.MenuItem);
3868262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
3878262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            // Inherit attributes from the group as default value
3888262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            itemId = a.getResourceId(R.styleable.MenuItem_android_id, defaultItemId);
3898262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            final int category = a.getInt(R.styleable.MenuItem_android_menuCategory, groupCategory);
3908262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            final int order = a.getInt(R.styleable.MenuItem_android_orderInCategory, groupOrder);
39130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            itemCategoryOrder = (category & SupportMenu.CATEGORY_MASK) |
39230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                    (order & SupportMenu.USER_MASK);
3938262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            itemTitle = a.getText(R.styleable.MenuItem_android_title);
3948262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            itemTitleCondensed = a.getText(R.styleable.MenuItem_android_titleCondensed);
3958262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            itemIconResId = a.getResourceId(R.styleable.MenuItem_android_icon, 0);
3968262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            itemAlphabeticShortcut =
3978262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    getShortcut(a.getString(R.styleable.MenuItem_android_alphabeticShortcut));
39809231da6d922e91d30d06876521106f13230a791Peeyush Agarwal            itemAlphabeticModifiers =
39909231da6d922e91d30d06876521106f13230a791Peeyush Agarwal                    a.getInt(R.styleable.MenuItem_alphabeticModifiers, KeyEvent.META_CTRL_ON);
4008262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            itemNumericShortcut =
4018262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    getShortcut(a.getString(R.styleable.MenuItem_android_numericShortcut));
40209231da6d922e91d30d06876521106f13230a791Peeyush Agarwal            itemNumericModifiers =
40309231da6d922e91d30d06876521106f13230a791Peeyush Agarwal                    a.getInt(R.styleable.MenuItem_numericModifiers, KeyEvent.META_CTRL_ON);
4048262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            if (a.hasValue(R.styleable.MenuItem_android_checkable)) {
4058262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                // Item has attribute checkable, use it
4068262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                itemCheckable = a.getBoolean(R.styleable.MenuItem_android_checkable, false) ? 1 : 0;
4078262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            } else {
4088262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                // Item does not have attribute, use the group's (group can have one more state
4098262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                // for checkable that represents the exclusive checkable)
4108262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                itemCheckable = groupCheckable;
4118262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            }
4128262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            itemChecked = a.getBoolean(R.styleable.MenuItem_android_checked, defaultItemChecked);
4138262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            itemVisible = a.getBoolean(R.styleable.MenuItem_android_visible, groupVisible);
4148262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            itemEnabled = a.getBoolean(R.styleable.MenuItem_android_enabled, groupEnabled);
4158262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            itemShowAsAction = a.getInt(R.styleable.MenuItem_showAsAction, -1);
4168262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            itemListenerMethodName = a.getString(R.styleable.MenuItem_android_onClick);
4178262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            itemActionViewLayout = a.getResourceId(R.styleable.MenuItem_actionLayout, 0);
4188262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            itemActionViewClassName = a.getString(R.styleable.MenuItem_actionViewClass);
4198262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            itemActionProviderClassName = a.getString(R.styleable.MenuItem_actionProviderClass);
4208262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
4218262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            final boolean hasActionProvider = itemActionProviderClassName != null;
4228262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            if (hasActionProvider && itemActionViewLayout == 0 && itemActionViewClassName == null) {
4238262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                itemActionProvider = newInstance(itemActionProviderClassName,
4248262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        ACTION_PROVIDER_CONSTRUCTOR_SIGNATURE,
4258262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        mActionProviderConstructorArguments);
4268262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            } else {
4278262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                if (hasActionProvider) {
4288262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    Log.w(LOG_TAG, "Ignoring attribute 'actionProviderClass'."
4298262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                            + " Action view already specified.");
4308262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                }
4318262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                itemActionProvider = null;
4328262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            }
4338262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
434fd3c4560bf2348f6a06272a9f02105c9e1bf927eVladislav Kaznacheev            itemContentDescription = a.getText(R.styleable.MenuItem_contentDescription);
435fd3c4560bf2348f6a06272a9f02105c9e1bf927eVladislav Kaznacheev            itemTooltipText = a.getText(R.styleable.MenuItem_tooltipText);
4363a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov            if (a.hasValue(R.styleable.MenuItem_iconTintMode)) {
4373a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov                itemIconTintMode = DrawableUtils.parseTintMode(a.getInt(
4383a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov                        R.styleable.MenuItem_iconTintMode, -1),
4393a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov                        itemIconTintMode);
4403a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov            } else {
4413a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov                // Reset to null so that it's not carried over to the next item
4423a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov                itemIconTintMode = null;
4433a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov            }
4443a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov            if (a.hasValue(R.styleable.MenuItem_iconTint)) {
4453a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov                itemIconTintList = a.getColorStateList(R.styleable.MenuItem_iconTint);
4463a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov            } else {
4473a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov                // Reset to null so that it's not carried over to the next item
4483a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov                itemIconTintList = null;
4493a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov            }
450fd3c4560bf2348f6a06272a9f02105c9e1bf927eVladislav Kaznacheev
4518262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            a.recycle();
4528262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
4538262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            itemAdded = false;
4548262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
4558262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
4568262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private char getShortcut(String shortcutString) {
4578262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            if (shortcutString == null) {
4588262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                return 0;
4598262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            } else {
4608262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                return shortcutString.charAt(0);
4618262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            }
4628262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
4638262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
4648262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private void setItem(MenuItem item) {
4658262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            item.setChecked(itemChecked)
4668262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    .setVisible(itemVisible)
4678262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    .setEnabled(itemEnabled)
4688262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    .setCheckable(itemCheckable >= 1)
4698262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    .setTitleCondensed(itemTitleCondensed)
47009231da6d922e91d30d06876521106f13230a791Peeyush Agarwal                    .setIcon(itemIconResId);
4718262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
4728262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            if (itemShowAsAction >= 0) {
473458543f38db49fdcb1764f007ded33820964c3feAurimas Liutikas                item.setShowAsAction(itemShowAsAction);
4748262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            }
4758262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
4768262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            if (itemListenerMethodName != null) {
4778262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                if (mContext.isRestricted()) {
4788262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    throw new IllegalStateException("The android:onClick attribute cannot "
4798262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                            + "be used within a restricted context");
4808262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                }
4818262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                item.setOnMenuItemClickListener(
482eeb589a57c069e1c1313e74de5876eceb69812a3Yigit Boyar                        new InflatedOnMenuItemClickListener(getRealOwner(), itemListenerMethodName));
4838262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            }
4848262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
48530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            final MenuItemImpl impl = item instanceof MenuItemImpl ? (MenuItemImpl) item : null;
486592df2e7552ba6902c9750ab8453850fc9e30334Chris Banes            if (itemCheckable >= 2) {
487592df2e7552ba6902c9750ab8453850fc9e30334Chris Banes                if (item instanceof MenuItemImpl) {
488592df2e7552ba6902c9750ab8453850fc9e30334Chris Banes                    ((MenuItemImpl) item).setExclusiveCheckable(true);
489592df2e7552ba6902c9750ab8453850fc9e30334Chris Banes                } else if (item instanceof MenuItemWrapperICS) {
490592df2e7552ba6902c9750ab8453850fc9e30334Chris Banes                    ((MenuItemWrapperICS) item).setExclusiveCheckable(true);
491592df2e7552ba6902c9750ab8453850fc9e30334Chris Banes                }
4928262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            }
4938262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
4948262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            boolean actionViewSpecified = false;
4958262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            if (itemActionViewClassName != null) {
4968262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                View actionView = (View) newInstance(itemActionViewClassName,
4978262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        ACTION_VIEW_CONSTRUCTOR_SIGNATURE, mActionViewConstructorArguments);
498458543f38db49fdcb1764f007ded33820964c3feAurimas Liutikas                item.setActionView(actionView);
4998262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                actionViewSpecified = true;
5008262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            }
5018262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            if (itemActionViewLayout > 0) {
5028262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                if (!actionViewSpecified) {
503458543f38db49fdcb1764f007ded33820964c3feAurimas Liutikas                    item.setActionView(itemActionViewLayout);
5048262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    actionViewSpecified = true;
5058262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                } else {
5068262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    Log.w(LOG_TAG, "Ignoring attribute 'itemActionViewLayout'."
5078262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                            + " Action view already specified.");
5088262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                }
5098262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            }
51034452b0d1034da026b8a1d6fe2fe4399844379d6Adam Powell            if (itemActionProvider != null) {
51134452b0d1034da026b8a1d6fe2fe4399844379d6Adam Powell                MenuItemCompat.setActionProvider(item, itemActionProvider);
5128262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            }
513fd3c4560bf2348f6a06272a9f02105c9e1bf927eVladislav Kaznacheev
514fd3c4560bf2348f6a06272a9f02105c9e1bf927eVladislav Kaznacheev            MenuItemCompat.setContentDescription(item, itemContentDescription);
515fd3c4560bf2348f6a06272a9f02105c9e1bf927eVladislav Kaznacheev            MenuItemCompat.setTooltipText(item, itemTooltipText);
51609231da6d922e91d30d06876521106f13230a791Peeyush Agarwal            MenuItemCompat.setAlphabeticShortcut(item, itemAlphabeticShortcut,
51709231da6d922e91d30d06876521106f13230a791Peeyush Agarwal                    itemAlphabeticModifiers);
51809231da6d922e91d30d06876521106f13230a791Peeyush Agarwal            MenuItemCompat.setNumericShortcut(item, itemNumericShortcut, itemNumericModifiers);
5193a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov
5203a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov            if (itemIconTintMode != null) {
5213a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov                MenuItemCompat.setIconTintMode(item, itemIconTintMode);
5223a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov            }
5233a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov            if (itemIconTintList != null) {
5243a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov                MenuItemCompat.setIconTintList(item, itemIconTintList);
5253a7c6d2009dfcf99c738d70eafe146eedf6e0ac2Kirill Grouchnikov            }
5268262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
5278262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
5288262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        public void addItem() {
5298262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            itemAdded = true;
5308262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            setItem(menu.add(groupId, itemId, itemCategoryOrder, itemTitle));
5318262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
5328262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
5338262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        public SubMenu addSubMenuItem() {
5348262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            itemAdded = true;
5358262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            SubMenu subMenu = menu.addSubMenu(groupId, itemId, itemCategoryOrder, itemTitle);
5368262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            setItem(subMenu.getItem());
5378262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            return subMenu;
5388262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
5398262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
5408262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        public boolean hasAddedItem() {
5418262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            return itemAdded;
5428262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
5438262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
544ad1b0e82100ee31e70040d77bfa4d847b2bf0864Aurimas Liutikas        @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"})
5458262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        private <T> T newInstance(String className, Class<?>[] constructorSignature,
5468262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                Object[] arguments) {
5478262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            try {
5488262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                Class<?> clazz = mContext.getClassLoader().loadClass(className);
5498262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                Constructor<?> constructor = clazz.getConstructor(constructorSignature);
550878384f1e6de7bd9196958224ced1ecfca3be6a7Chris Banes                constructor.setAccessible(true);
5518262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                return (T) constructor.newInstance(arguments);
5528262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            } catch (Exception e) {
5538262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                Log.w(LOG_TAG, "Cannot instantiate class: " + className, e);
5548262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            }
5558262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            return null;
5568262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
5578262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    }
5588262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns}
559