Automated import from //branches/master/...@142288,142288
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java
index efa5981..7aad7c8 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java
@@ -70,6 +70,18 @@
mFormats = formats;
}
+ /**
+ * @param name The XML Name of the attribute
+ * @param formats The formats of the attribute. Cannot be null.
+ * Should have at least one format.
+ * @param javadoc Short javadoc (i.e. the first sentence).
+ */
+ public AttributeInfo(String name, Format[] formats, String javadoc) {
+ mName = name;
+ mFormats = formats;
+ mJavaDoc = javadoc;
+ }
+
public AttributeInfo(AttributeInfo info) {
mName = info.mName;
mFormats = info.mFormats;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java
index 5550155..6a9b7db 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java
@@ -24,6 +24,7 @@
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.graphics.Image;
+import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
@@ -221,6 +222,18 @@
mChildren = newChildren;
}
+ /** Sets the list of allowed children.
+ * <p/>
+ * This is just a convenience method that converts a Collection into an array and
+ * calls {@link #setChildren(ElementDescriptor[])}.
+ * <p/>
+ * This means a <em>copy</em> of the collection is made. The collection is not
+ * stored by the recipient and can thus be altered by the caller.
+ */
+ public void setChildren(Collection<ElementDescriptor> newChildren) {
+ setChildren(newChildren.toArray(new ElementDescriptor[newChildren.size()]));
+ }
+
/**
* Returns an optional tooltip. Will be null if not present.
* <p/>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
index 5726d78..2c0f984 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
@@ -43,7 +43,7 @@
public static final String ID_ATTR = "id"; //$NON-NLS-1$
/** The document descriptor. Contains all layouts and views linked together. */
- private DocumentDescriptor mDescriptor =
+ private DocumentDescriptor mRootDescriptor =
new DocumentDescriptor("layout_doc", null); //$NON-NLS-1$
/** The list of all known ViewLayout descriptors. */
@@ -60,7 +60,7 @@
/** @return the document descriptor. Contains all layouts and views linked together. */
public DocumentDescriptor getDescriptor() {
- return mDescriptor;
+ return mRootDescriptor;
}
/** @return The read-only list of all known ViewLayout descriptors. */
@@ -74,7 +74,7 @@
}
public ElementDescriptor[] getRootElementDescriptors() {
- return mDescriptor.getChildren();
+ return mRootDescriptor.getChildren();
}
/**
@@ -98,6 +98,10 @@
}
}
+ // Create <include> as a synthetic regular view.
+ // Note: ViewStub is already described by attrs.xml
+ insertInclude(newViews);
+
ArrayList<ElementDescriptor> newLayouts = new ArrayList<ElementDescriptor>();
if (layouts != null) {
for (ViewClassInfo info : layouts) {
@@ -109,17 +113,22 @@
ArrayList<ElementDescriptor> newDescriptors = new ArrayList<ElementDescriptor>();
newDescriptors.addAll(newLayouts);
newDescriptors.addAll(newViews);
- ElementDescriptor[] newArray = newDescriptors.toArray(
- new ElementDescriptor[newDescriptors.size()]);
// Link all layouts to everything else here.. recursively
for (ElementDescriptor layoutDesc : newLayouts) {
- layoutDesc.setChildren(newArray);
+ layoutDesc.setChildren(newDescriptors);
}
+ // The <merge> tag can only be a root tag, so it is added at the end.
+ // It gets everything else as children but it is not made a child itself.
+ ElementDescriptor mergeTag = createMerge();
+ mergeTag.setChildren(newDescriptors); // mergeTag makes a copy of the list
+ newDescriptors.add(mergeTag);
+ newLayouts.add(mergeTag);
+
mViewDescriptors = newViews;
mLayoutDescriptors = newLayouts;
- mDescriptor.setChildren(newArray);
+ mRootDescriptor.setChildren(newDescriptors);
mROLayoutDescriptors = Collections.unmodifiableList(mLayoutDescriptors);
mROViewDescriptors = Collections.unmodifiableList(mViewDescriptors);
@@ -217,4 +226,91 @@
false /* mandatory */);
}
+ /**
+ * Creates a new <include> descriptor and adds it to the list of view descriptors.
+ *
+ * @param newViews A list of view descriptors being populated. Also used to find the
+ * View description and extract its layout attributes.
+ */
+ private void insertInclude(ArrayList<ElementDescriptor> newViews) {
+ String xml_name = "include"; //$NON-NLS-1$
+
+ // Create the include custom attributes
+ ArrayList<AttributeDescriptor> attributes = new ArrayList<AttributeDescriptor>();
+
+ // Note that the "layout" attribute does NOT have the Android namespace
+ DescriptorsUtils.appendAttribute(attributes,
+ null, //elementXmlName
+ null, //nsUri
+ new AttributeInfo(
+ "layout", //$NON-NLS-1$
+ new AttributeInfo.Format[] { AttributeInfo.Format.REFERENCE }
+ ),
+ true, //required
+ null); //overrides
+
+ DescriptorsUtils.appendAttribute(attributes,
+ null, //elementXmlName
+ SdkConstants.NS_RESOURCES, //nsUri
+ new AttributeInfo(
+ "id", //$NON-NLS-1$
+ new AttributeInfo.Format[] { AttributeInfo.Format.REFERENCE }
+ ),
+ true, //required
+ null); //overrides
+
+ // Find View and inherit all its layout attributes
+ AttributeDescriptor[] viewLayoutAttribs = findViewLayoutAttributes(newViews);
+
+ // Create the include descriptor
+ ViewElementDescriptor desc = new ViewElementDescriptor(xml_name, // xml_name
+ xml_name, // ui_name
+ null, // canonical class name, we don't have one
+ "Lets you statically include XML layouts inside other XML layouts.", // tooltip
+ null, // sdk_url
+ attributes.toArray(new AttributeDescriptor[attributes.size()]),
+ viewLayoutAttribs, // layout attributes
+ null, // children
+ false /* mandatory */);
+
+ newViews.add(desc);
+ }
+
+ /**
+ * Finds the View descriptor and retrieves all its layout attributes.
+ */
+ private AttributeDescriptor[] findViewLayoutAttributes(
+ ArrayList<ElementDescriptor> newViews) {
+
+ for (ElementDescriptor desc : newViews) {
+ if (desc instanceof ViewElementDescriptor) {
+ ViewElementDescriptor viewDesc = (ViewElementDescriptor) desc;
+ if (AndroidConstants.CLASS_VIEW.equals(viewDesc.getCanonicalClassName())) {
+ return viewDesc.getLayoutAttributes();
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates and return a new <merge> descriptor.
+ */
+ private ElementDescriptor createMerge() {
+ String xml_name = "merge"; //$NON-NLS-1$
+
+ // Create the include descriptor
+ ViewElementDescriptor desc = new ViewElementDescriptor(xml_name, // xml_name
+ xml_name, // ui_name
+ null, // canonical class name, we don't have one
+ "A root tag useful for XML layouts inflated using a ViewStub.", // tooltip
+ null, // sdk_url
+ null, // attributes
+ null, // layout attributes
+ null, // children
+ false /* mandatory */);
+
+ return desc;
+ }
}