blob: 7f3ed093972d6098e940b261fecf6769535c03d2 [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.otherxml.descriptors;
import static com.android.SdkConstants.ANDROID_NS_NAME;
import static com.android.SdkConstants.ANDROID_URI;
import com.android.SdkConstants;
import com.android.ide.common.resources.platform.AttributeInfo;
import com.android.ide.common.resources.platform.DeclareStyleableInfo;
import com.android.ide.common.resources.platform.ViewClassInfo;
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.DocumentDescriptor;
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.SeparatorAttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor;
import java.util.ArrayList;
import java.util.Map;
/**
* Description of the /res/xml structure.
* Currently supports the <searchable> and <preferences> root nodes.
*/
public final class OtherXmlDescriptors implements IDescriptorProvider {
// Public attributes names, attributes descriptors and elements descriptors referenced
// elsewhere.
public static final String PREF_KEY_ATTR = "key"; //$NON-NLS-1$
/** The root document descriptor for both searchable and preferences. */
private DocumentDescriptor mDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$
/** The root document descriptor for searchable. */
private DocumentDescriptor mSearchDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$
/** The root document descriptor for preferences. */
private DocumentDescriptor mPrefDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$
/** The root document descriptor for widget provider. */
private DocumentDescriptor mAppWidgetDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$
/** @return the root descriptor for both searchable and preferences. */
@Override
public DocumentDescriptor getDescriptor() {
return mDescriptor;
}
@Override
public ElementDescriptor[] getRootElementDescriptors() {
return mDescriptor.getChildren();
}
/** @return the root descriptor for searchable. */
public DocumentDescriptor getSearchableDescriptor() {
return mSearchDescriptor;
}
/** @return the root descriptor for preferences. */
public DocumentDescriptor getPreferencesDescriptor() {
return mPrefDescriptor;
}
/** @return the root descriptor for widget providers. */
public DocumentDescriptor getAppWidgetDescriptor() {
return mAppWidgetDescriptor;
}
public IDescriptorProvider getSearchableProvider() {
return new IDescriptorProvider() {
@Override
public ElementDescriptor getDescriptor() {
return mSearchDescriptor;
}
@Override
public ElementDescriptor[] getRootElementDescriptors() {
return mSearchDescriptor.getChildren();
}
};
}
public IDescriptorProvider getPreferencesProvider() {
return new IDescriptorProvider() {
@Override
public ElementDescriptor getDescriptor() {
return mPrefDescriptor;
}
@Override
public ElementDescriptor[] getRootElementDescriptors() {
return mPrefDescriptor.getChildren();
}
};
}
public IDescriptorProvider getAppWidgetProvider() {
return new IDescriptorProvider() {
@Override
public ElementDescriptor getDescriptor() {
return mAppWidgetDescriptor;
}
@Override
public ElementDescriptor[] getRootElementDescriptors() {
return mAppWidgetDescriptor.getChildren();
}
};
}
/**
* Updates the document descriptor.
* <p/>
* It first computes the new children of the descriptor and then updates them
* all at once.
*
* @param searchableStyleMap The map style=>attributes for <searchable> from the attrs.xml file
* @param appWidgetStyleMap The map style=>attributes for <appwidget-provider> from the attrs.xml file
* @param prefs The list of non-group preference descriptions
* @param prefGroups The list of preference group descriptions
*/
public synchronized void updateDescriptors(
Map<String, DeclareStyleableInfo> searchableStyleMap,
Map<String, DeclareStyleableInfo> appWidgetStyleMap,
ViewClassInfo[] prefs, ViewClassInfo[] prefGroups) {
XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor(ANDROID_NS_NAME,
ANDROID_URI);
ElementDescriptor searchable = createSearchable(searchableStyleMap, xmlns);
ElementDescriptor appWidget = createAppWidgetProviderInfo(appWidgetStyleMap, xmlns);
ElementDescriptor preferences = createPreference(prefs, prefGroups, xmlns);
ArrayList<ElementDescriptor> list = new ArrayList<ElementDescriptor>();
if (searchable != null) {
list.add(searchable);
mSearchDescriptor.setChildren(new ElementDescriptor[]{ searchable });
}
if (appWidget != null) {
list.add(appWidget);
mAppWidgetDescriptor.setChildren(new ElementDescriptor[]{ appWidget });
}
if (preferences != null) {
list.add(preferences);
mPrefDescriptor.setChildren(new ElementDescriptor[]{ preferences });
}
if (list.size() > 0) {
mDescriptor.setChildren(list.toArray(new ElementDescriptor[list.size()]));
}
}
//-------------------------
// Creation of <searchable>
//-------------------------
/**
* Returns the new ElementDescriptor for <searchable>
*/
private ElementDescriptor createSearchable(
Map<String, DeclareStyleableInfo> searchableStyleMap,
XmlnsAttributeDescriptor xmlns) {
ElementDescriptor action_key = createElement(searchableStyleMap,
"SearchableActionKey", //$NON-NLS-1$ styleName
"actionkey", //$NON-NLS-1$ xmlName
"Action Key", // uiName
null, // sdk url
null, // extraAttribute
null, // childrenElements
false /* mandatory */ );
ElementDescriptor searchable = createElement(searchableStyleMap,
"Searchable", //$NON-NLS-1$ styleName
"searchable", //$NON-NLS-1$ xmlName
"Searchable", // uiName
null, // sdk url
xmlns, // extraAttribute
new ElementDescriptor[] { action_key }, // childrenElements
false /* mandatory */ );
return searchable;
}
/**
* Returns the new ElementDescriptor for <appwidget-provider>
*/
private ElementDescriptor createAppWidgetProviderInfo(
Map<String, DeclareStyleableInfo> appWidgetStyleMap,
XmlnsAttributeDescriptor xmlns) {
if (appWidgetStyleMap == null) {
return null;
}
ElementDescriptor appWidget = createElement(appWidgetStyleMap,
"AppWidgetProviderInfo", //$NON-NLS-1$ styleName
"appwidget-provider", //$NON-NLS-1$ xmlName
"AppWidget Provider", // uiName
null, // sdk url
xmlns, // extraAttribute
null, // childrenElements
false /* mandatory */ );
return appWidget;
}
/**
* 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 styleName,
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, styleName, 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
SdkConstants.NS_RESOURCES,
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;
}
//--------------------------
// Creation of <Preferences>
//--------------------------
/**
* Returns the new ElementDescriptor for <Preferences>
*/
private ElementDescriptor createPreference(ViewClassInfo[] prefs,
ViewClassInfo[] prefGroups, XmlnsAttributeDescriptor xmlns) {
ArrayList<ElementDescriptor> newPrefs = new ArrayList<ElementDescriptor>();
if (prefs != null) {
for (ViewClassInfo info : prefs) {
ElementDescriptor desc = convertPref(info);
newPrefs.add(desc);
}
}
ElementDescriptor topPreferences = null;
ArrayList<ElementDescriptor> newGroups = new ArrayList<ElementDescriptor>();
if (prefGroups != null) {
for (ViewClassInfo info : prefGroups) {
ElementDescriptor desc = convertPref(info);
newGroups.add(desc);
if (info.getFullClassName() == SdkConstants.CLASS_PREFERENCES) {
topPreferences = desc;
}
}
}
ArrayList<ElementDescriptor> everything = new ArrayList<ElementDescriptor>();
everything.addAll(newGroups);
everything.addAll(newPrefs);
ElementDescriptor[] newArray = everything.toArray(new ElementDescriptor[everything.size()]);
// Link all groups to everything else here.. recursively
for (ElementDescriptor layoutDesc : newGroups) {
layoutDesc.setChildren(newArray);
}
// The "top" element to be returned corresponds to the class "Preferences".
// Its descriptor has already been created. However the root one also needs
// the hidden xmlns:android definition..
if (topPreferences != null) {
AttributeDescriptor[] attrs = topPreferences.getAttributes();
AttributeDescriptor[] newAttrs = new AttributeDescriptor[attrs.length + 1];
System.arraycopy(attrs, 0, newAttrs, 0, attrs.length);
newAttrs[attrs.length] = xmlns;
return new ElementDescriptor(
topPreferences.getXmlName(),
topPreferences.getUiName(),
topPreferences.getTooltip(),
topPreferences.getSdkUrl(),
newAttrs,
topPreferences.getChildren(),
false /* mandatory */);
} else {
return null;
}
}
/**
* Creates an element descriptor from a given {@link ViewClassInfo}.
*/
private ElementDescriptor convertPref(ViewClassInfo info) {
String xml_name = info.getShortClassName();
String tooltip = info.getJavaDoc();
// Process all Preference attributes
ArrayList<AttributeDescriptor> attributes = new ArrayList<AttributeDescriptor>();
DescriptorsUtils.appendAttributes(attributes,
null, // elementName
SdkConstants.NS_RESOURCES,
info.getAttributes(),
null, // requiredAttributes
null); // overrides
for (ViewClassInfo link = info.getSuperClass();
link != null;
link = link.getSuperClass()) {
AttributeInfo[] attrList = link.getAttributes();
if (attrList.length > 0) {
attributes.add(new SeparatorAttributeDescriptor(
String.format("Attributes from %1$s", link.getShortClassName())));
DescriptorsUtils.appendAttributes(attributes,
null, // elementName
SdkConstants.NS_RESOURCES,
attrList,
null, // requiredAttributes
null); // overrides
}
}
return new ViewElementDescriptor(xml_name,
xml_name, // ui_name
info.getFullClassName(),
tooltip,
null, // sdk_url
attributes.toArray(new AttributeDescriptor[attributes.size()]),
null,
null, // children
false /* mandatory */);
}
}