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