Home | History | Annotate | Download | only in menu
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
      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 
     17 package com.android.ide.eclipse.adt.internal.editors.menu;
     18 
     19 import com.android.ide.eclipse.adt.AdtPlugin;
     20 import com.android.ide.eclipse.adt.AndroidConstants;
     21 import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
     22 import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
     23 import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
     24 import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
     25 import com.android.sdklib.xml.AndroidXPathFactory;
     26 
     27 import org.eclipse.core.resources.IFile;
     28 import org.eclipse.ui.IEditorInput;
     29 import org.eclipse.ui.IEditorPart;
     30 import org.eclipse.ui.PartInitException;
     31 import org.eclipse.ui.part.FileEditorInput;
     32 import org.w3c.dom.Document;
     33 import org.w3c.dom.Node;
     34 
     35 import javax.xml.xpath.XPath;
     36 import javax.xml.xpath.XPathConstants;
     37 import javax.xml.xpath.XPathExpressionException;
     38 
     39 /**
     40  * Multi-page form editor for /res/menu XML files.
     41  */
     42 public class MenuEditor extends AndroidXmlEditor {
     43 
     44     public static final String ID = AndroidConstants.EDITORS_NAMESPACE + ".menu.MenuEditor"; //$NON-NLS-1$
     45 
     46     /** Root node of the UI element hierarchy */
     47     private UiElementNode mUiRootNode;
     48 
     49     /**
     50      * Creates the form editor for resources XML files.
     51      */
     52     public MenuEditor() {
     53         super();
     54     }
     55 
     56     /**
     57      * Returns the root node of the UI element hierarchy, which here is
     58      * the "menu" node.
     59      */
     60     @Override
     61     public UiElementNode getUiRootNode() {
     62         return mUiRootNode;
     63     }
     64 
     65     // ---- Base Class Overrides ----
     66 
     67     /**
     68      * Returns whether the "save as" operation is supported by this editor.
     69      * <p/>
     70      * Save-As is a valid operation for the ManifestEditor since it acts on a
     71      * single source file.
     72      *
     73      * @see IEditorPart
     74      */
     75     @Override
     76     public boolean isSaveAsAllowed() {
     77         return true;
     78     }
     79 
     80     /**
     81      * Create the various form pages.
     82      */
     83     @Override
     84     protected void createFormPages() {
     85         try {
     86             addPage(new MenuTreePage(this));
     87         } catch (PartInitException e) {
     88             AdtPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
     89         }
     90 
     91      }
     92 
     93     /* (non-java doc)
     94      * Change the tab/title name to include the project name.
     95      */
     96     @Override
     97     protected void setInput(IEditorInput input) {
     98         super.setInput(input);
     99         if (input instanceof FileEditorInput) {
    100             FileEditorInput fileInput = (FileEditorInput) input;
    101             IFile file = fileInput.getFile();
    102             setPartName(String.format("%1$s", file.getName()));
    103         }
    104     }
    105 
    106     /**
    107      * Processes the new XML Model, which XML root node is given.
    108      *
    109      * @param xml_doc The XML document, if available, or null if none exists.
    110      */
    111     @Override
    112     protected void xmlModelChanged(Document xml_doc) {
    113         // init the ui root on demand
    114         initUiRootNode(false /*force*/);
    115 
    116         mUiRootNode.setXmlDocument(xml_doc);
    117         if (xml_doc != null) {
    118             ElementDescriptor root_desc = mUiRootNode.getDescriptor();
    119             try {
    120                 XPath xpath = AndroidXPathFactory.newXPath();
    121                 Node node = (Node) xpath.evaluate("/" + root_desc.getXmlName(),  //$NON-NLS-1$
    122                         xml_doc,
    123                         XPathConstants.NODE);
    124                 if (node == null && root_desc.isMandatory()) {
    125                     // Create the root element if it doesn't exist yet (for empty new documents)
    126                     node = mUiRootNode.createXmlNode();
    127                 }
    128 
    129                 // Refresh the manifest UI node and all its descendants
    130                 mUiRootNode.loadFromXmlNode(node);
    131 
    132                 // TODO ? startMonitoringMarkers();
    133             } catch (XPathExpressionException e) {
    134                 AdtPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
    135                         root_desc.getXmlName());
    136             }
    137         }
    138 
    139         super.xmlModelChanged(xml_doc);
    140     }
    141 
    142     /**
    143      * Creates the initial UI Root Node, including the known mandatory elements.
    144      * @param force if true, a new UiRootNode is recreated even if it already exists.
    145      */
    146     @Override
    147     protected void initUiRootNode(boolean force) {
    148         // The root UI node is always created, even if there's no corresponding XML node.
    149         if (mUiRootNode == null || force) {
    150             Document doc = null;
    151             if (mUiRootNode != null) {
    152                 doc = mUiRootNode.getXmlDocument();
    153             }
    154 
    155             // get the target data from the opened file (and its project)
    156             AndroidTargetData data = getTargetData();
    157 
    158             ElementDescriptor desc;
    159             if (data == null) {
    160                 desc = new ElementDescriptor("temp", null /*children*/);
    161             } else {
    162                 desc = data.getMenuDescriptors().getDescriptor();
    163             }
    164 
    165             mUiRootNode = desc.createUiNode();
    166             mUiRootNode.setEditor(this);
    167 
    168             onDescriptorsChanged(doc);
    169         }
    170     }
    171 
    172     // ---- Local Methods ----
    173 
    174     /**
    175      * Reloads the UI manifest node from the XML, and calls the pages to update.
    176      */
    177     private void onDescriptorsChanged(Document document) {
    178         if (document != null) {
    179             mUiRootNode.loadFromXmlNode(document);
    180         } else {
    181             mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlNode());
    182         }
    183     }
    184 }
    185