blob: b7bab1bd34ff6ff3512862f07fa7d0489bcb586b [file] [log] [blame]
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Eclipse Public License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.eclipse.org/org/documents/epl-v10.php
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ide.eclipse.adt.internal.editors.menu.descriptors;
import static com.android.SdkConstants.ANDROID_NS_NAME;
import static com.android.SdkConstants.ANDROID_URI;
import static com.android.SdkConstants.TAG_MENU;
import com.android.ide.common.resources.platform.DeclareStyleableInfo;
import com.android.ide.eclipse.adt.AdtUtils;
import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.adt.internal.editors.descriptors.XmlnsAttributeDescriptor;
import java.util.ArrayList;
import java.util.Map;
/**
* Complete description of the menu structure.
*/
public final class MenuDescriptors implements IDescriptorProvider {
/** The root element descriptor. */
private ElementDescriptor mDescriptor = null;
/** @return the root descriptor. */
@Override
public ElementDescriptor getDescriptor() {
return mDescriptor;
}
@Override
public ElementDescriptor[] getRootElementDescriptors() {
return mDescriptor.getChildren();
}
/**
* Updates the document descriptor.
* <p/>
* It first computes the new children of the descriptor and then updates them
* all at once.
*
* @param styleMap The map style => attributes from the attrs.xml file
*/
public synchronized void updateDescriptors(Map<String, DeclareStyleableInfo> styleMap) {
// There are 3 elements: menu, item and group.
// The root element MUST be a menu.
// A top menu can contain items or group:
// - top groups can contain top items
// - top items can contain sub-menus
// A sub menu can contains sub items or sub groups:
// - sub groups can contain sub items
// - sub items cannot contain anything
if (mDescriptor == null) {
mDescriptor = createElement(styleMap,
TAG_MENU, // xmlName
"Menu", // uiName,
null, // TODO SDK URL
null, // extraAttribute
null, // childrenElements,
true /* mandatory */);
}
// -- sub menu can have sub_items, sub_groups but not sub_menus
ElementDescriptor sub_item = createElement(styleMap,
"item", // xmlName //$NON-NLS-1$
"Item", // uiName,
null, // TODO SDK URL
null, // extraAttribute
null, // childrenElements,
false /* mandatory */);
ElementDescriptor sub_group = createElement(styleMap,
"group", // xmlName //$NON-NLS-1$
"Group", // uiName,
null, // TODO SDK URL
null, // extraAttribute
new ElementDescriptor[] { sub_item }, // childrenElements,
false /* mandatory */);
ElementDescriptor sub_menu = createElement(styleMap,
TAG_MENU, // xmlName
"Sub-Menu", // uiName,
null, // TODO SDK URL
null, // extraAttribute
new ElementDescriptor[] { sub_item, sub_group }, // childrenElements,
true /* mandatory */);
// -- top menu can have all top groups and top items (which can have sub menus)
ElementDescriptor top_item = createElement(styleMap,
"item", // xmlName //$NON-NLS-1$
"Item", // uiName,
null, // TODO SDK URL
null, // extraAttribute
new ElementDescriptor[] { sub_menu }, // childrenElements,
false /* mandatory */);
ElementDescriptor top_group = createElement(styleMap,
"group", // xmlName //$NON-NLS-1$
"Group", // uiName,
null, // TODO SDK URL
null, // extraAttribute
new ElementDescriptor[] { top_item }, // childrenElements,
false /* mandatory */);
XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor(ANDROID_NS_NAME,
ANDROID_URI);
updateElement(mDescriptor, styleMap, "Menu", xmlns); //$NON-NLS-1$
mDescriptor.setChildren(new ElementDescriptor[] { top_item, top_group });
}
/**
* Returns a new ElementDescriptor constructed from the information given here
* and the javadoc & attributes extracted from the style map if any.
*/
private ElementDescriptor createElement(
Map<String, DeclareStyleableInfo> styleMap,
String xmlName, String uiName, String sdkUrl,
AttributeDescriptor extraAttribute,
ElementDescriptor[] childrenElements, boolean mandatory) {
ElementDescriptor element = new ElementDescriptor(xmlName, uiName, null, sdkUrl,
null, childrenElements, mandatory);
return updateElement(element, styleMap,
getStyleName(xmlName),
extraAttribute);
}
/**
* Updates an ElementDescriptor with the javadoc & attributes extracted from the style
* map if any.
*/
private ElementDescriptor updateElement(ElementDescriptor element,
Map<String, DeclareStyleableInfo> styleMap,
String styleName,
AttributeDescriptor extraAttribute) {
ArrayList<AttributeDescriptor> descs = new ArrayList<AttributeDescriptor>();
DeclareStyleableInfo style = styleMap != null ? styleMap.get(styleName) : null;
if (style != null) {
DescriptorsUtils.appendAttributes(descs,
null, // elementName
ANDROID_URI,
style.getAttributes(),
null, // requiredAttributes
null); // overrides
element.setTooltip(style.getJavaDoc());
}
if (extraAttribute != null) {
descs.add(extraAttribute);
}
element.setAttributes(descs.toArray(new AttributeDescriptor[descs.size()]));
return element;
}
/**
* Returns the style name (i.e. the <declare-styleable> name found in attrs.xml)
* for a given XML element name.
* <p/>
* The rule is that all elements have for style name:
* - their xml name capitalized
* - a "Menu" prefix, except for <menu> itself which is just "Menu".
*/
private String getStyleName(String xmlName) {
String styleName = AdtUtils.capitalize(xmlName);
// This is NOT the UI Name but the expected internal style name
final String MENU_STYLE_BASE_NAME = "Menu"; //$NON-NLS-1$
if (!styleName.equals(MENU_STYLE_BASE_NAME)) {
styleName = MENU_STYLE_BASE_NAME + styleName;
}
return styleName;
}
}