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. */ 42 public ElementDescriptor getDescriptor() { 43 return mDescriptor; 44 } 45 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 */ 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 */ 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 */ 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 */ 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