Home | History | Annotate | Download | only in descriptors
      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.descriptors;
     18 
     19 import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_NAME;
     20 
     21 import com.android.ide.common.resources.platform.DeclareStyleableInfo;
     22 import com.android.ide.eclipse.adt.AdtUtils;
     23 import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
     24 import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils;
     25 import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
     26 import com.android.ide.eclipse.adt.internal.editors.descriptors.IDescriptorProvider;
     27 import com.android.ide.eclipse.adt.internal.editors.descriptors.XmlnsAttributeDescriptor;
     28 import com.android.sdklib.SdkConstants;
     29 
     30 import java.util.ArrayList;
     31 import java.util.Map;
     32 
     33 
     34 /**
     35  * Complete description of the menu structure.
     36  */
     37 public final class MenuDescriptors implements IDescriptorProvider {
     38 
     39     public static final String MENU_ROOT_ELEMENT = "menu"; //$NON-NLS-1$
     40 
     41     /** The root element descriptor. */
     42     private ElementDescriptor mDescriptor = null;
     43 
     44     /** @return the root descriptor. */
     45     @Override
     46     public ElementDescriptor getDescriptor() {
     47         return mDescriptor;
     48     }
     49 
     50     @Override
     51     public ElementDescriptor[] getRootElementDescriptors() {
     52         return mDescriptor.getChildren();
     53     }
     54 
     55     /**
     56      * Updates the document descriptor.
     57      * <p/>
     58      * It first computes the new children of the descriptor and then updates them
     59      * all at once.
     60      *
     61      * @param styleMap The map style => attributes from the attrs.xml file
     62      */
     63     public synchronized void updateDescriptors(Map<String, DeclareStyleableInfo> styleMap) {
     64 
     65         // There are 3 elements: menu, item and group.
     66         // The root element MUST be a menu.
     67         // A top menu can contain items or group:
     68         //  - top groups can contain top items
     69         //  - top items can contain sub-menus
     70         // A sub menu can contains sub items or sub groups:
     71         //  - sub groups can contain sub items
     72         //  - sub items cannot contain anything
     73 
     74         if (mDescriptor == null) {
     75             mDescriptor = createElement(styleMap,
     76                 MENU_ROOT_ELEMENT, // xmlName
     77                 "Menu", // uiName,
     78                 null, // TODO SDK URL
     79                 null, // extraAttribute
     80                 null, // childrenElements,
     81                 true /* mandatory */);
     82         }
     83 
     84         // -- sub menu can have sub_items, sub_groups but not sub_menus
     85 
     86         ElementDescriptor sub_item = createElement(styleMap,
     87                 "item", // xmlName //$NON-NLS-1$
     88                 "Item", // uiName,
     89                 null, // TODO SDK URL
     90                 null, // extraAttribute
     91                 null, // childrenElements,
     92                 false /* mandatory */);
     93 
     94         ElementDescriptor sub_group = createElement(styleMap,
     95                 "group", // xmlName //$NON-NLS-1$
     96                 "Group", // uiName,
     97                 null, // TODO SDK URL
     98                 null, // extraAttribute
     99                 new ElementDescriptor[] { sub_item }, // childrenElements,
    100                 false /* mandatory */);
    101 
    102         ElementDescriptor sub_menu = createElement(styleMap,
    103                 MENU_ROOT_ELEMENT, // xmlName
    104                 "Sub-Menu", // uiName,
    105                 null, // TODO SDK URL
    106                 null, // extraAttribute
    107                 new ElementDescriptor[] { sub_item, sub_group }, // childrenElements,
    108                 true /* mandatory */);
    109 
    110         // -- top menu can have all top groups and top items (which can have sub menus)
    111 
    112         ElementDescriptor top_item = createElement(styleMap,
    113                 "item", // xmlName //$NON-NLS-1$
    114                 "Item", // uiName,
    115                 null, // TODO SDK URL
    116                 null, // extraAttribute
    117                 new ElementDescriptor[] { sub_menu }, // childrenElements,
    118                 false /* mandatory */);
    119 
    120         ElementDescriptor top_group = createElement(styleMap,
    121                 "group", // xmlName //$NON-NLS-1$
    122                 "Group", // uiName,
    123                 null, // TODO SDK URL
    124                 null, // extraAttribute
    125                 new ElementDescriptor[] { top_item }, // childrenElements,
    126                 false /* mandatory */);
    127 
    128         XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor(ANDROID_NS_NAME,
    129                 SdkConstants.NS_RESOURCES);
    130 
    131         updateElement(mDescriptor, styleMap, "Menu", xmlns); //$NON-NLS-1$
    132         mDescriptor.setChildren(new ElementDescriptor[] { top_item, top_group });
    133     }
    134 
    135     /**
    136      * Returns a new ElementDescriptor constructed from the information given here
    137      * and the javadoc & attributes extracted from the style map if any.
    138      */
    139     private ElementDescriptor createElement(
    140             Map<String, DeclareStyleableInfo> styleMap,
    141             String xmlName, String uiName, String sdkUrl,
    142             AttributeDescriptor extraAttribute,
    143             ElementDescriptor[] childrenElements, boolean mandatory) {
    144 
    145         ElementDescriptor element = new ElementDescriptor(xmlName, uiName, null, sdkUrl,
    146                 null, childrenElements, mandatory);
    147 
    148         return updateElement(element, styleMap,
    149                 getStyleName(xmlName),
    150                 extraAttribute);
    151     }
    152 
    153     /**
    154      * Updates an ElementDescriptor with the javadoc & attributes extracted from the style
    155      * map if any.
    156      */
    157     private ElementDescriptor updateElement(ElementDescriptor element,
    158             Map<String, DeclareStyleableInfo> styleMap,
    159             String styleName,
    160             AttributeDescriptor extraAttribute) {
    161         ArrayList<AttributeDescriptor> descs = new ArrayList<AttributeDescriptor>();
    162 
    163         DeclareStyleableInfo style = styleMap != null ? styleMap.get(styleName) : null;
    164         if (style != null) {
    165             DescriptorsUtils.appendAttributes(descs,
    166                     null,   // elementName
    167                     SdkConstants.NS_RESOURCES,
    168                     style.getAttributes(),
    169                     null,   // requiredAttributes
    170                     null);  // overrides
    171             element.setTooltip(style.getJavaDoc());
    172         }
    173 
    174         if (extraAttribute != null) {
    175             descs.add(extraAttribute);
    176         }
    177 
    178         element.setAttributes(descs.toArray(new AttributeDescriptor[descs.size()]));
    179         return element;
    180     }
    181 
    182     /**
    183      * Returns the style name (i.e. the <declare-styleable> name found in attrs.xml)
    184      * for a given XML element name.
    185      * <p/>
    186      * The rule is that all elements have for style name:
    187      * - their xml name capitalized
    188      * - a "Menu" prefix, except for <menu> itself which is just "Menu".
    189      */
    190     private String getStyleName(String xmlName) {
    191         String styleName = AdtUtils.capitalize(xmlName);
    192 
    193         // This is NOT the UI Name but the expected internal style name
    194         final String MENU_STYLE_BASE_NAME = "Menu"; //$NON-NLS-1$
    195 
    196         if (!styleName.equals(MENU_STYLE_BASE_NAME)) {
    197             styleName = MENU_STYLE_BASE_NAME + styleName;
    198         }
    199         return styleName;
    200     }
    201 }
    202