|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 package org.mozilla.gecko.menu; |
|
6 |
|
7 import org.mozilla.gecko.R; |
|
8 |
|
9 import org.xmlpull.v1.XmlPullParser; |
|
10 import org.xmlpull.v1.XmlPullParserException; |
|
11 |
|
12 import android.content.Context; |
|
13 import android.content.res.TypedArray; |
|
14 import android.content.res.XmlResourceParser; |
|
15 import android.os.Build; |
|
16 import android.util.AttributeSet; |
|
17 import android.util.Xml; |
|
18 import android.view.InflateException; |
|
19 import android.view.Menu; |
|
20 import android.view.MenuInflater; |
|
21 import android.view.MenuItem; |
|
22 import android.view.SubMenu; |
|
23 |
|
24 import java.io.IOException; |
|
25 |
|
26 public class GeckoMenuInflater extends MenuInflater { |
|
27 private static final String LOGTAG = "GeckoMenuInflater"; |
|
28 |
|
29 private static final String TAG_MENU = "menu"; |
|
30 private static final String TAG_ITEM = "item"; |
|
31 private static final int NO_ID = 0; |
|
32 |
|
33 private Context mContext; |
|
34 |
|
35 // Private class to hold the parsed menu item. |
|
36 private class ParsedItem { |
|
37 public int id; |
|
38 public int order; |
|
39 public CharSequence title; |
|
40 public int iconRes; |
|
41 public boolean checkable; |
|
42 public boolean checked; |
|
43 public boolean visible; |
|
44 public boolean enabled; |
|
45 public int showAsAction; |
|
46 public boolean hasSubMenu; |
|
47 } |
|
48 |
|
49 public GeckoMenuInflater(Context context) { |
|
50 super(context); |
|
51 mContext = context; |
|
52 } |
|
53 |
|
54 @Override |
|
55 public void inflate(int menuRes, Menu menu) { |
|
56 |
|
57 // This does not check for a well-formed XML. |
|
58 |
|
59 XmlResourceParser parser = null; |
|
60 try { |
|
61 parser = mContext.getResources().getXml(menuRes); |
|
62 AttributeSet attrs = Xml.asAttributeSet(parser); |
|
63 |
|
64 parseMenu(parser, attrs, menu); |
|
65 |
|
66 } catch (XmlPullParserException e) { |
|
67 throw new InflateException("Error inflating menu XML", e); |
|
68 } catch (IOException e) { |
|
69 throw new InflateException("Error inflating menu XML", e); |
|
70 } finally { |
|
71 if (parser != null) |
|
72 parser.close(); |
|
73 } |
|
74 } |
|
75 |
|
76 private void parseMenu(XmlResourceParser parser, AttributeSet attrs, Menu menu) |
|
77 throws XmlPullParserException, IOException { |
|
78 ParsedItem item = null; |
|
79 |
|
80 String tag; |
|
81 int eventType = parser.getEventType(); |
|
82 |
|
83 do { |
|
84 tag = parser.getName(); |
|
85 |
|
86 switch (eventType) { |
|
87 case XmlPullParser.START_TAG: |
|
88 if (tag.equals(TAG_ITEM)) { |
|
89 // Parse the menu item. |
|
90 item = new ParsedItem(); |
|
91 parseItem(item, attrs); |
|
92 } else if (tag.equals(TAG_MENU)) { |
|
93 if (item != null) { |
|
94 // Add the submenu item. |
|
95 SubMenu subMenu = menu.addSubMenu(NO_ID, item.id, item.order, item.title); |
|
96 item.hasSubMenu = true; |
|
97 |
|
98 // Set the menu item in main menu. |
|
99 MenuItem menuItem = subMenu.getItem(); |
|
100 setValues(item, menuItem); |
|
101 |
|
102 // Start parsing the sub menu. |
|
103 parseMenu(parser, attrs, subMenu); |
|
104 } |
|
105 } |
|
106 break; |
|
107 |
|
108 case XmlPullParser.END_TAG: |
|
109 if (parser.getName().equals(TAG_ITEM)) { |
|
110 if (!item.hasSubMenu) { |
|
111 // Add the item. |
|
112 MenuItem menuItem = menu.add(NO_ID, item.id, item.order, item.title); |
|
113 setValues(item, menuItem); |
|
114 } |
|
115 } else if (tag.equals(TAG_MENU)) { |
|
116 return; |
|
117 } |
|
118 break; |
|
119 } |
|
120 |
|
121 eventType = parser.next(); |
|
122 |
|
123 } while (eventType != XmlPullParser.END_DOCUMENT); |
|
124 } |
|
125 |
|
126 public void parseItem(ParsedItem item, AttributeSet attrs) { |
|
127 TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.MenuItem); |
|
128 |
|
129 item.id = a.getResourceId(R.styleable.MenuItem_android_id, NO_ID); |
|
130 item.order = a.getInt(R.styleable.MenuItem_android_orderInCategory, 0); |
|
131 item.title = a.getText(R.styleable.MenuItem_android_title); |
|
132 item.iconRes = a.getResourceId(R.styleable.MenuItem_android_icon, 0); |
|
133 item.checkable = a.getBoolean(R.styleable.MenuItem_android_checkable, false); |
|
134 item.checked = a.getBoolean(R.styleable.MenuItem_android_checked, false); |
|
135 item.visible = a.getBoolean(R.styleable.MenuItem_android_visible, true); |
|
136 item.enabled = a.getBoolean(R.styleable.MenuItem_android_enabled, true); |
|
137 item.hasSubMenu = false; |
|
138 |
|
139 if (Build.VERSION.SDK_INT >= 11) |
|
140 item.showAsAction = a.getInt(R.styleable.MenuItem_android_showAsAction, 0); |
|
141 |
|
142 a.recycle(); |
|
143 } |
|
144 |
|
145 public void setValues(ParsedItem item, MenuItem menuItem) { |
|
146 menuItem.setChecked(item.checked) |
|
147 .setVisible(item.visible) |
|
148 .setEnabled(item.enabled) |
|
149 .setCheckable(item.checkable) |
|
150 .setIcon(item.iconRes); |
|
151 |
|
152 if (Build.VERSION.SDK_INT >= 11) |
|
153 menuItem.setShowAsAction(item.showAsAction); |
|
154 } |
|
155 } |