michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: package org.mozilla.gecko.menu; michael@0: michael@0: import org.mozilla.gecko.R; michael@0: michael@0: import org.xmlpull.v1.XmlPullParser; michael@0: import org.xmlpull.v1.XmlPullParserException; michael@0: michael@0: import android.content.Context; michael@0: import android.content.res.TypedArray; michael@0: import android.content.res.XmlResourceParser; michael@0: import android.os.Build; michael@0: import android.util.AttributeSet; michael@0: import android.util.Xml; michael@0: import android.view.InflateException; michael@0: import android.view.Menu; michael@0: import android.view.MenuInflater; michael@0: import android.view.MenuItem; michael@0: import android.view.SubMenu; michael@0: michael@0: import java.io.IOException; michael@0: michael@0: public class GeckoMenuInflater extends MenuInflater { michael@0: private static final String LOGTAG = "GeckoMenuInflater"; michael@0: michael@0: private static final String TAG_MENU = "menu"; michael@0: private static final String TAG_ITEM = "item"; michael@0: private static final int NO_ID = 0; michael@0: michael@0: private Context mContext; michael@0: michael@0: // Private class to hold the parsed menu item. michael@0: private class ParsedItem { michael@0: public int id; michael@0: public int order; michael@0: public CharSequence title; michael@0: public int iconRes; michael@0: public boolean checkable; michael@0: public boolean checked; michael@0: public boolean visible; michael@0: public boolean enabled; michael@0: public int showAsAction; michael@0: public boolean hasSubMenu; michael@0: } michael@0: michael@0: public GeckoMenuInflater(Context context) { michael@0: super(context); michael@0: mContext = context; michael@0: } michael@0: michael@0: @Override michael@0: public void inflate(int menuRes, Menu menu) { michael@0: michael@0: // This does not check for a well-formed XML. michael@0: michael@0: XmlResourceParser parser = null; michael@0: try { michael@0: parser = mContext.getResources().getXml(menuRes); michael@0: AttributeSet attrs = Xml.asAttributeSet(parser); michael@0: michael@0: parseMenu(parser, attrs, menu); michael@0: michael@0: } catch (XmlPullParserException e) { michael@0: throw new InflateException("Error inflating menu XML", e); michael@0: } catch (IOException e) { michael@0: throw new InflateException("Error inflating menu XML", e); michael@0: } finally { michael@0: if (parser != null) michael@0: parser.close(); michael@0: } michael@0: } michael@0: michael@0: private void parseMenu(XmlResourceParser parser, AttributeSet attrs, Menu menu) michael@0: throws XmlPullParserException, IOException { michael@0: ParsedItem item = null; michael@0: michael@0: String tag; michael@0: int eventType = parser.getEventType(); michael@0: michael@0: do { michael@0: tag = parser.getName(); michael@0: michael@0: switch (eventType) { michael@0: case XmlPullParser.START_TAG: michael@0: if (tag.equals(TAG_ITEM)) { michael@0: // Parse the menu item. michael@0: item = new ParsedItem(); michael@0: parseItem(item, attrs); michael@0: } else if (tag.equals(TAG_MENU)) { michael@0: if (item != null) { michael@0: // Add the submenu item. michael@0: SubMenu subMenu = menu.addSubMenu(NO_ID, item.id, item.order, item.title); michael@0: item.hasSubMenu = true; michael@0: michael@0: // Set the menu item in main menu. michael@0: MenuItem menuItem = subMenu.getItem(); michael@0: setValues(item, menuItem); michael@0: michael@0: // Start parsing the sub menu. michael@0: parseMenu(parser, attrs, subMenu); michael@0: } michael@0: } michael@0: break; michael@0: michael@0: case XmlPullParser.END_TAG: michael@0: if (parser.getName().equals(TAG_ITEM)) { michael@0: if (!item.hasSubMenu) { michael@0: // Add the item. michael@0: MenuItem menuItem = menu.add(NO_ID, item.id, item.order, item.title); michael@0: setValues(item, menuItem); michael@0: } michael@0: } else if (tag.equals(TAG_MENU)) { michael@0: return; michael@0: } michael@0: break; michael@0: } michael@0: michael@0: eventType = parser.next(); michael@0: michael@0: } while (eventType != XmlPullParser.END_DOCUMENT); michael@0: } michael@0: michael@0: public void parseItem(ParsedItem item, AttributeSet attrs) { michael@0: TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.MenuItem); michael@0: michael@0: item.id = a.getResourceId(R.styleable.MenuItem_android_id, NO_ID); michael@0: item.order = a.getInt(R.styleable.MenuItem_android_orderInCategory, 0); michael@0: item.title = a.getText(R.styleable.MenuItem_android_title); michael@0: item.iconRes = a.getResourceId(R.styleable.MenuItem_android_icon, 0); michael@0: item.checkable = a.getBoolean(R.styleable.MenuItem_android_checkable, false); michael@0: item.checked = a.getBoolean(R.styleable.MenuItem_android_checked, false); michael@0: item.visible = a.getBoolean(R.styleable.MenuItem_android_visible, true); michael@0: item.enabled = a.getBoolean(R.styleable.MenuItem_android_enabled, true); michael@0: item.hasSubMenu = false; michael@0: michael@0: if (Build.VERSION.SDK_INT >= 11) michael@0: item.showAsAction = a.getInt(R.styleable.MenuItem_android_showAsAction, 0); michael@0: michael@0: a.recycle(); michael@0: } michael@0: michael@0: public void setValues(ParsedItem item, MenuItem menuItem) { michael@0: menuItem.setChecked(item.checked) michael@0: .setVisible(item.visible) michael@0: .setEnabled(item.enabled) michael@0: .setCheckable(item.checkable) michael@0: .setIcon(item.iconRes); michael@0: michael@0: if (Build.VERSION.SDK_INT >= 11) michael@0: menuItem.setShowAsAction(item.showAsAction); michael@0: } michael@0: }