PageRenderTime 28ms CodeModel.GetById 2ms app.highlight 21ms RepoModel.GetById 2ms app.codeStats 0ms

/shell/src/com/google/marvin/shell/MenuManager.java

http://eyes-free.googlecode.com/
Java | 278 lines | 204 code | 23 blank | 51 comment | 40 complexity | 32bab27337b42c2bb0ef5b26ffcf7a73 MD5 | raw file
  1/*
  2 * Copyright (C) 2010 Google Inc.
  3 *
  4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5 * use this file except in compliance with the License. You may obtain a copy of
  6 * 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, WITHOUT
 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 13 * License for the specific language governing permissions and limitations under
 14 * the License.
 15 */
 16
 17package com.google.marvin.shell;
 18
 19import android.content.Context;
 20import android.content.pm.PackageManager;
 21import android.content.res.Resources;
 22
 23import com.google.marvin.widget.GestureOverlay.Gesture;
 24
 25import org.w3c.dom.Document;
 26import org.w3c.dom.NamedNodeMap;
 27import org.w3c.dom.Node;
 28import org.w3c.dom.NodeList;
 29
 30import java.io.FileInputStream;
 31import java.io.FileNotFoundException;
 32import java.io.FileOutputStream;
 33import java.io.IOException;
 34import java.io.InputStream;
 35import java.io.OutputStreamWriter;
 36import java.util.HashMap;
 37
 38import javax.xml.parsers.DocumentBuilder;
 39import javax.xml.parsers.DocumentBuilderFactory;
 40
 41/**
 42 * Manages a set of menus and provides functions for saving/loading XML and
 43 * editing menus.
 44 *
 45 * @author clchen@google.com (Charles L. Chen)
 46 * @author credo@google.com (Tim Credo)
 47 */
 48public final class MenuManager extends HashMap<String, Menu> {
 49
 50    private static String XML_SHELL_TAG = "<shell>\n";
 51
 52    private static String XML_VERSION_TAG = "<version number='0.1' />\n";
 53
 54    private static String XML_SHELL_CLOSE_TAG = "</shell>\n";
 55
 56    /**
 57     * Write out the currently loaded set of menus to an XML string.
 58     */
 59    public String toXml() {
 60        StringBuffer xml = new StringBuffer();
 61        xml.append(XML_SHELL_TAG);
 62        xml.append(XML_VERSION_TAG);
 63        for (String menuName : keySet()) {
 64            xml.append(get(menuName).toXml());
 65        }
 66        xml.append(XML_SHELL_CLOSE_TAG);
 67        return xml.toString();
 68    }
 69
 70    /**
 71     * Write currently loaded menus to an XML file.
 72     */
 73    public void save(String filename) {
 74        try {
 75            FileOutputStream fileOutputStream = new FileOutputStream(filename);
 76            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
 77            outputStreamWriter.write(toXml());
 78            outputStreamWriter.close();
 79        } catch (FileNotFoundException e) {
 80            e.printStackTrace();
 81        } catch (IOException e) {
 82            e.printStackTrace();
 83        }
 84    }
 85
 86    /**
 87     * Insert a new menu.
 88     */
 89    public void insertMenu(Menu currentMenu, Integer gesture, String menuName) {
 90
 91        String id = menuName;
 92        int n = 1;
 93        // if the id is a duplicate, add a number
 94        while (containsKey(id)) {
 95            n = n + 1;
 96            id = menuName + " " + String.valueOf(n);
 97        }
 98        int oppositeGesture;
 99        if (gesture == Gesture.EDGELEFT) {
100            oppositeGesture = Gesture.EDGERIGHT;
101        } else if (gesture == Gesture.EDGERIGHT) {
102            oppositeGesture = Gesture.EDGELEFT;
103        } else {
104            return;
105        }
106        Menu nextMenu = null;
107        MenuItem item = currentMenu.get(gesture);
108        if (item.action.equalsIgnoreCase("MENU")) {
109            nextMenu = get(item.data);
110        }
111        Menu newMenu = new Menu(menuName);
112        put(id, newMenu);
113        newMenu.setID(id);
114        MenuItem link = new MenuItem(menuName, "MENU", id, null);
115        MenuItem homeLink = new MenuItem(currentMenu.getName(), "MENU", currentMenu.getID(), null);
116        currentMenu.put(gesture, link);
117        newMenu.put(oppositeGesture, homeLink);
118        if (nextMenu != null) {
119            MenuItem nextLink = new MenuItem(nextMenu.getName(), "MENU", nextMenu.getID(), null);
120            newMenu.put(gesture, nextLink);
121            nextMenu.put(oppositeGesture, link);
122        }
123    }
124
125    /**
126     * Load a set of menus from an XML file.
127     */
128    public static MenuManager loadMenus(Context context, String filename) {
129        MenuManager manager = new MenuManager();
130        try {
131            FileInputStream fis = new FileInputStream(filename);
132            manager = loadMenus(context, fis);
133        } catch (Exception e) {
134            e.printStackTrace();
135        }
136        return manager;
137    }
138
139    /**
140     * Load a set of menus from an XML input stream.
141     */
142    public static MenuManager loadMenus(Context context, InputStream is) {
143        HashMap<String, Menu> shortcutMenus = new HashMap<String, Menu>();
144        try {
145            DocumentBuilder docBuild = DocumentBuilderFactory.newInstance().newDocumentBuilder();
146            Document doc = docBuild.parse(is);
147            String versionNumber;
148            NodeList versionNodes = doc.getElementsByTagName("version");
149            if (versionNodes.getLength() == 0) {
150                versionNumber = "0.0";
151            } else {
152                Node versionNumberNode = versionNodes.item(0).getAttributes().getNamedItem(
153                        "number");
154                if (versionNumberNode == null) {
155                    versionNumber = "0.0";
156                } else {
157                    versionNumber = versionNumberNode.getNodeValue();
158                }
159            }
160            if (versionNumber.equalsIgnoreCase("0.0")) {
161                // Load new default and wipe over one screen with old shortcuts
162                Resources res = context.getResources();
163                InputStream defaultIs = res.openRawResource(R.raw.default_shortcuts);
164                shortcutMenus = loadMenus(context, defaultIs);
165                NodeList items = doc.getElementsByTagName("item");
166                shortcutMenus.get("Shortcuts Left").putAll(readItems(context, items));
167
168            } else {
169                // Load everything normally
170                NodeList menus = doc.getElementsByTagName("menu");
171                for (int i = 0; i < menus.getLength(); i++) {
172                    NamedNodeMap attribs = menus.item(i).getAttributes();
173                    String label = attribs.getNamedItem("label").getNodeValue();
174                    String wallpaper = "";
175                    Node wallpaperNode = attribs.getNamedItem("wallpaper");
176                    if (wallpaperNode != null) {
177                        wallpaper = wallpaperNode.getNodeValue();
178                    }
179                    Node idAttrNode = attribs.getNamedItem("id");
180                    if (idAttrNode != null) {
181                        String id = idAttrNode.getNodeValue();
182                        Menu menu = new Menu(label,
183                                readItems(context, menus.item(i).getChildNodes()), wallpaper);
184                        menu.setID(id);
185                        shortcutMenus.put(id, menu);
186                    } else {
187                        Menu menu = new Menu(label,
188                                readItems(context, menus.item(i).getChildNodes()), wallpaper);
189                        shortcutMenus.put(label, menu);
190                    }
191                }
192            }
193        } catch (Exception e) {
194            e.printStackTrace();
195        }
196        MenuManager manager = new MenuManager();
197        manager.putAll(shortcutMenus);
198        return manager;
199    }
200
201    /**
202     * Loads menu items from a list of XML nodes containing menu items.
203     */
204    public static HashMap<Integer, MenuItem> readItems(Context context, NodeList itemNodes) {
205        HashMap<Integer, MenuItem> menu = new HashMap<Integer, MenuItem>();
206        for (int i = 0; i < itemNodes.getLength(); i++) {
207            if (itemNodes.item(i).getNodeName().equalsIgnoreCase("item")) {
208                NamedNodeMap attribs = itemNodes.item(i).getAttributes();
209                int g = Integer.parseInt(attribs.getNamedItem("gesture").getNodeValue());
210
211                String label = attribs.getNamedItem("label").getNodeValue();
212                String action = attribs.getNamedItem("action").getNodeValue();
213                String data = null;
214                Node dataAttrNode = attribs.getNamedItem("data");
215                if (dataAttrNode != null) {
216                    data = dataAttrNode.getNodeValue();
217                }
218                AppInfo appInfo = null;
219                if (action.equalsIgnoreCase("launch")) {
220                    Node appInfoNode = null;
221                    NodeList nodes = itemNodes.item(i).getChildNodes();
222                    for (int j = 0; j < nodes.getLength(); j++) {
223                        Node currentNode = nodes.item(j);
224                        String tagName = currentNode.getNodeName();
225                        // Only process actual nodes
226                        if (tagName != null) {
227                            if (tagName.equalsIgnoreCase("appInfo")) {
228                                appInfoNode = currentNode;
229                            }
230                        }
231                    }
232                    NamedNodeMap appInfoAttr = appInfoNode.getAttributes();
233                    String packageName = "";
234                    Node packageAttrNode = appInfoAttr.getNamedItem("package");
235                    if (packageAttrNode != null) {
236                        packageName = packageAttrNode.getNodeValue();
237                    }
238                    String className = "";
239                    Node classAttrNode = appInfoAttr.getNamedItem("class");
240                    if (classAttrNode != null) {
241                        className = classAttrNode.getNodeValue();
242                    }
243                    appInfo = new AppInfo(null, packageName, className);
244
245                    // Check to see if the package is still installed
246                    if (packageExists(context, appInfo)) {
247                        menu.put(g, new MenuItem(label, action, data, appInfo));
248                    }
249
250                } else {
251                    menu.put(g, new MenuItem(label, action, data, appInfo));
252                }
253            }
254        }
255        return menu;
256    }
257
258    /**
259     * Check to see if application is installed.
260     */
261    private static boolean packageExists(Context context, AppInfo application) {
262        PackageManager manager = context.getPackageManager();
263        try {
264            manager.getApplicationInfo(application.getPackageName(), 0);
265            return true;
266        } catch (PackageManager.NameNotFoundException e) {
267            return false;
268        }
269    }
270
271    /**
272     * Escape entities in text for XML.
273     */
274    public static String escapeEntities(String string) {
275        return string.replaceAll("\"", "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;")
276                .replaceAll("'", "&apos;").replaceAll("&", "&amp;");
277    }
278}