• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
getDescriptor()46     public ElementDescriptor getDescriptor() {
47         return mDescriptor;
48     }
49 
50     @Override
getRootElementDescriptors()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      */
updateDescriptors(Map<String, DeclareStyleableInfo> styleMap)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      */
createElement( Map<String, DeclareStyleableInfo> styleMap, String xmlName, String uiName, String sdkUrl, AttributeDescriptor extraAttribute, ElementDescriptor[] childrenElements, boolean mandatory)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      */
updateElement(ElementDescriptor element, Map<String, DeclareStyleableInfo> styleMap, String styleName, AttributeDescriptor extraAttribute)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      */
getStyleName(String xmlName)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