blob: 4858ac7c6511f14d6b67a89dc5a797152918c57a [file] [log] [blame]
/*
* Copyright (C) 2011 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.drawable;
import static com.android.SdkConstants.ANDROID_NS_NAME;
import static com.android.SdkConstants.ANDROID_URI;
import com.android.ide.common.api.IAttributeInfo.Format;
import com.android.ide.common.resources.platform.AttributeInfo;
import com.android.ide.common.resources.platform.DeclareStyleableInfo;
import com.android.ide.eclipse.adt.internal.editors.animator.AnimatorDescriptors;
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.ReferenceAttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.resources.ResourceType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Descriptors for /res/drawable files
*/
public class DrawableDescriptors implements IDescriptorProvider {
private static final String SDK_URL_BASE =
"http://d.android.com/guide/topics/resources/"; //$NON-NLS-1$
/** The root element descriptor */
private ElementDescriptor mDescriptor;
/** The root element descriptors */
private ElementDescriptor[] mRootDescriptors;
private Map<String, ElementDescriptor> nameToDescriptor;
/** @return the root descriptor. */
@Override
public ElementDescriptor getDescriptor() {
if (mDescriptor == null) {
mDescriptor = new ElementDescriptor("", getRootElementDescriptors()); //$NON-NLS-1$
}
return mDescriptor;
}
@Override
public ElementDescriptor[] getRootElementDescriptors() {
return mRootDescriptors;
}
/**
* Returns a descriptor for the given root tag name
*
* @param tag the tag name to look up a descriptor for
* @return a descriptor with the given tag name
*/
public ElementDescriptor getElementDescriptor(String tag) {
if (nameToDescriptor == null) {
nameToDescriptor = new HashMap<String, ElementDescriptor>();
for (ElementDescriptor descriptor : getRootElementDescriptors()) {
nameToDescriptor.put(descriptor.getXmlName(), descriptor);
}
}
ElementDescriptor descriptor = nameToDescriptor.get(tag);
if (descriptor == null) {
descriptor = getDescriptor();
}
return descriptor;
}
public synchronized void updateDescriptors(Map<String, DeclareStyleableInfo> styleMap) {
XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor(ANDROID_NS_NAME,
ANDROID_URI);
List<ElementDescriptor> descriptors = new ArrayList<ElementDescriptor>();
AnimatorDescriptors.addElement(descriptors, styleMap,
"animation-list", "Animation List", "AnimationDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
"An animation defined in XML that shows a sequence of images in "
+ "order (like a film)",
SDK_URL_BASE + "animation-resource.html#Frame",
xmlns, null, true /*mandatory*/);
/* For some reason, android.graphics.drawable.AnimatedRotateDrawable is marked with @hide
* so we should not register it and its attributes here. See issue #19248 for details.
AnimatorDescriptors.addElement(descriptors, styleMap,
"animated-rotate", "Animated Rotate", "AnimatedRotateDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
// Need docs
null, // tooltip
null, // sdk_url
xmlns, null, true);
*/
AnimatorDescriptors.addElement(descriptors, styleMap,
"bitmap", "BitMap", "BitmapDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
"An XML bitmap is a resource defined in XML that points to a bitmap file. "
+ "The effect is an alias for a raw bitmap file. The XML can "
+ "specify additional properties for the bitmap such as "
+ "dithering and tiling.",
SDK_URL_BASE + "drawable-resource.html#Bitmap", //$NON-NLS-1$
xmlns, null, true /* mandatory */);
AnimatorDescriptors.addElement(descriptors, styleMap,
"clip", "Clip", "ClipDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
"An XML file that defines a drawable that clips another Drawable based on "
+ "this Drawable's current level value.",
SDK_URL_BASE + "drawable-resource.html#Clip", //$NON-NLS-1$
xmlns, null, true /*mandatory*/);
AnimatorDescriptors.addElement(descriptors, styleMap,
"color", "Color", "ColorDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
"XML resource that carries a color value (a hexadecimal color)",
SDK_URL_BASE + "more-resources.html#Color",
xmlns, null, true /*mandatory*/);
AnimatorDescriptors.addElement(descriptors, styleMap,
"inset", "Inset", "InsetDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
"An XML file that defines a drawable that insets another drawable by a "
+ "specified distance. This is useful when a View needs a background "
+ "drawble that is smaller than the View's actual bounds.",
SDK_URL_BASE + "drawable-resource.html#Inset", //$NON-NLS-1$
xmlns, null, true /*mandatory*/);
// Layer list
// An <item> in a <selector> or <
ElementDescriptor layerItem = AnimatorDescriptors.addElement(null, styleMap,
"item", "Item", "LayerDrawableItem", null, //$NON-NLS-1$ //$NON-NLS-3$
"Defines a drawable to place in the layer drawable, in a position "
+ "defined by its attributes. Must be a child of a <selector> "
+ "element. Accepts child <bitmap> elements.",
SDK_URL_BASE + "drawable-resource.html#LayerList", //$NON-NLS-1$
null, /* extra attribute */
null, /* This is wrong -- we can now embed any above drawable
(but without xmlns as extra) */
false /*mandatory*/);
ElementDescriptor[] layerChildren = layerItem != null
? new ElementDescriptor[] { layerItem } : null;
AnimatorDescriptors.addElement(descriptors, styleMap,
"layer-list", "Layer List", "LayerDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
"A Drawable that manages an array of other Drawables. These are drawn in "
+ "array order, so the element with the largest index is be drawn on top.",
SDK_URL_BASE + "drawable-resource.html#LayerList", //$NON-NLS-1$
xmlns,
layerChildren,
true /*mandatory*/);
// Level list children
ElementDescriptor levelListItem = AnimatorDescriptors.addElement(null, styleMap,
"item", "Item", "LevelListDrawableItem", null, //$NON-NLS-1$ //$NON-NLS-3$
"Defines a drawable to use at a certain level.",
SDK_URL_BASE + "drawable-resource.html#LevelList", //$NON-NLS-1$
null, /* extra attribute */
null, /* no further children */
// TODO: The inflation code seems to show that all drawables can be nested here!
false /*mandatory*/);
AnimatorDescriptors.addElement(descriptors, styleMap,
"level-list", "Level List", "LevelListDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
"An XML file that defines a drawable that manages a number of alternate "
+ "Drawables, each assigned a maximum numerical value",
SDK_URL_BASE + "drawable-resource.html#LevelList", //$NON-NLS-1$
xmlns,
levelListItem != null ? new ElementDescriptor[] { levelListItem } : null,
true /*mandatory*/);
// Not yet supported
//addElement(descriptors, styleMap, "mipmap", "Mipmap", "MipmapDrawable", null,
// null /* tooltip */,
// null /* sdk_url */,
// xmlns, null, true /*mandatory*/);
AnimatorDescriptors.addElement(descriptors, styleMap,
"nine-patch", "Nine Patch", "NinePatchDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
"A PNG file with stretchable regions to allow image resizing "
+ "based on content (.9.png).",
SDK_URL_BASE + "drawable-resource.html#NinePatch", //$NON-NLS-1$
xmlns, null, true /*mandatory*/);
AnimatorDescriptors.addElement(descriptors, styleMap,
"rotate", "Rotate", "RotateDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
// Need docs
null /* tooltip */,
null /* sdk_url */,
xmlns, null, true /*mandatory*/);
AnimatorDescriptors.addElement(descriptors, styleMap,
"scale", "Shape", "ScaleDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
"An XML file that defines a drawable that changes the size of another Drawable "
+ "based on its current level value.",
SDK_URL_BASE + "drawable-resource.html#Scale", //$NON-NLS-1$
xmlns, null, true /*mandatory*/);
// Selector children
ElementDescriptor selectorItem = AnimatorDescriptors.addElement(null, styleMap,
"item", "Item", "DrawableStates", null, //$NON-NLS-1$ //$NON-NLS-3$
"Defines a drawable to use during certain states, as described by "
+ "its attributes. Must be a child of a <selector> element.",
SDK_URL_BASE + "drawable-resource.html#StateList", //$NON-NLS-1$
new ReferenceAttributeDescriptor(
ResourceType.DRAWABLE, "drawable", ANDROID_URI, //$NON-NLS-1$
new AttributeInfo("drawable", Format.REFERENCE_SET))
.setTooltip("Reference to a drawable resource."),
null, /* This is wrong -- we can now embed any above drawable
(but without xmlns as extra) */
false /*mandatory*/);
AnimatorDescriptors.addElement(descriptors, styleMap,
"selector", "Selector", "StateListDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
"An XML file that references different bitmap graphics for different states "
+ "(for example, to use a different image when a button is pressed).",
SDK_URL_BASE + "drawable-resource.html#StateList", //$NON-NLS-1$
xmlns,
selectorItem != null ? new ElementDescriptor[] { selectorItem } : null,
true /*mandatory*/);
// Shape
// Shape children
List<ElementDescriptor> shapeChildren = new ArrayList<ElementDescriptor>();
// Selector children
AnimatorDescriptors.addElement(shapeChildren, styleMap,
"size", "Size", "GradientDrawableSize", null, //$NON-NLS-1$ //$NON-NLS-3$
null /* tooltip */, null /* sdk_url */, null /* extra attribute */,
null /* children */, false /* mandatory */);
AnimatorDescriptors.addElement(shapeChildren, styleMap,
"gradient", "Gradient", "GradientDrawableGradient", null, //$NON-NLS-1$ //$NON-NLS-3$
null /* tooltip */, null /* sdk_url */, null /* extra attribute */,
null /* children */, false /* mandatory */);
AnimatorDescriptors.addElement(shapeChildren, styleMap,
"solid", "Solid", "GradientDrawableSolid", null, //$NON-NLS-1$ //$NON-NLS-3$
null /* tooltip */, null /* sdk_url */, null /* extra attribute */,
null /* children */, false /* mandatory */);
AnimatorDescriptors.addElement(shapeChildren, styleMap,
"stroke", "Stroke", "GradientDrawableStroke", null, //$NON-NLS-1$ //$NON-NLS-3$
null /* tooltip */, null /* sdk_url */, null /* extra attribute */,
null /* children */, false /* mandatory */);
AnimatorDescriptors.addElement(shapeChildren, styleMap,
"corners", "Corners", "DrawableCorners", null, //$NON-NLS-1$ //$NON-NLS-3$
null /* tooltip */, null /* sdk_url */, null /* extra attribute */,
null /* children */, false /* mandatory */);
AnimatorDescriptors.addElement(shapeChildren, styleMap,
"padding", "Padding", "GradientDrawablePadding", null, //$NON-NLS-1$ //$NON-NLS-3$
null /* tooltip */, null /* sdk_url */, null /* extra attribute */,
null /* children */, false /* mandatory */);
AnimatorDescriptors.addElement(descriptors, styleMap,
"shape", "Shape", //$NON-NLS-1$
// The documentation says that a <shape> element creates a ShapeDrawable,
// but ShapeDrawable isn't finished and the code currently creates
// a GradientDrawable.
//"ShapeDrawable", //$NON-NLS-1$
"GradientDrawable", //$NON-NLS-1$
null,
"An XML file that defines a geometric shape, including colors and gradients.",
SDK_URL_BASE + "drawable-resource.html#Shape", //$NON-NLS-1$
xmlns,
// These are the GradientDrawable children, not the ShapeDrawable children
shapeChildren.toArray(new ElementDescriptor[shapeChildren.size()]),
true /*mandatory*/);
AnimatorDescriptors.addElement(descriptors, styleMap,
"transition", "Transition", "TransitionDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
"An XML file that defines a drawable that can cross-fade between two "
+ "drawable resources. Each drawable is represented by an <item> "
+ "element inside a single <transition> element. No more than two "
+ "items are supported. To transition forward, call startTransition(). "
+ "To transition backward, call reverseTransition().",
SDK_URL_BASE + "drawable-resource.html#Transition", //$NON-NLS-1$
xmlns,
layerChildren, // children: a TransitionDrawable is a LayerDrawable
true /*mandatory*/);
mRootDescriptors = descriptors.toArray(new ElementDescriptor[descriptors.size()]);
// A <selector><item> can contain any of the top level drawables
if (selectorItem != null) {
selectorItem.setChildren(mRootDescriptors);
}
// Docs says it can accept <bitmap> but code comment suggests any is possible;
// test and either use this or just { bitmap }
if (layerItem != null) {
layerItem.setChildren(mRootDescriptors);
}
}
}