aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/resources/platform/AttrsXmlParser.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java13
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AaptQuickFix.java150
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssist.java8
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimDescriptors.java124
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimationContentAssist.java167
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimationEditor.java181
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimationSourceViewerConfig.java30
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimatorDescriptors.java182
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/color/ColorContentAssist.java31
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/color/ColorDescriptors.java94
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/color/ColorEditor.java123
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/color/ColorSourceViewerConfig.java30
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/BooleanAttributeDescriptor.java4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/drawable/DrawableContentAssist.java31
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/drawable/DrawableDescriptors.java300
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/drawable/DrawableEditor.java157
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/drawable/DrawableSourceViewerConfig.java30
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestEditor.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/descriptors/AndroidManifestDescriptors.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/resources/ResourcesContentAssist.java4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/resources/ResourcesEditor.java4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java58
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java43
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/NewXmlFileCreationPage.java92
26 files changed, 1822 insertions, 46 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/resources/platform/AttrsXmlParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/resources/platform/AttrsXmlParser.java
index bd79e29b6..1e14f9f0e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/resources/platform/AttrsXmlParser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/resources/platform/AttrsXmlParser.java
@@ -256,7 +256,7 @@ public final class AttrsXmlParser {
if (parents != null) {
String[] parentsArray =
parseStyleableParents(parents, mStyleMap, unknownParents);
- style.setParents(parentsArray); //$NON-NLS-1$
+ style.setParents(parentsArray);
}
mStyleMap.put(name, style);
unknownParents.remove(name);
@@ -441,9 +441,9 @@ public final class AttrsXmlParser {
* </ul>
* The format may be one type or two types (e.g. "reference|color").
* An extra format can be implied: "enum" or "flag" are not specified in the "format" attribute,
- * they are implicitely stated by the presence of sub-nodes <enum> or <flag>.
+ * they are implicitly stated by the presence of sub-nodes <enum> or <flag>.
* <p/>
- * By design, <attr> nodes of the same name MUST have the same type.
+ * By design, attr nodes of the same name MUST have the same type.
* Attribute nodes are thus cached by name and reused as much as possible.
* When reusing a node, it is duplicated and its javadoc reassigned.
*/
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
index 43fd82346..55a5ef8af 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
@@ -25,6 +25,9 @@ import com.android.ide.common.sdk.LoadStatus;
import com.android.ide.eclipse.adt.internal.VersionCheck;
import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
import com.android.ide.eclipse.adt.internal.editors.IconFactory;
+import com.android.ide.eclipse.adt.internal.editors.animator.AnimationEditor;
+import com.android.ide.eclipse.adt.internal.editors.color.ColorEditor;
+import com.android.ide.eclipse.adt.internal.editors.drawable.DrawableEditor;
import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditor;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.IncludeFinder;
import com.android.ide.eclipse.adt.internal.editors.menu.MenuEditor;
@@ -1511,11 +1514,17 @@ public class AdtPlugin extends AbstractUIPlugin implements ILogger {
AdtPlugin.log(IStatus.INFO, " set default editor id to layout");
}
IDE.setDefaultEditor(file, LayoutEditor.ID);
- } else if (type == ResourceFolderType.DRAWABLE
- || type == ResourceFolderType.VALUES) {
+ } else if (type == ResourceFolderType.VALUES) {
IDE.setDefaultEditor(file, ResourcesEditor.ID);
} else if (type == ResourceFolderType.MENU) {
IDE.setDefaultEditor(file, MenuEditor.ID);
+ } else if (type == ResourceFolderType.COLOR) {
+ IDE.setDefaultEditor(file, ColorEditor.ID);
+ } else if (type == ResourceFolderType.DRAWABLE) {
+ IDE.setDefaultEditor(file, DrawableEditor.ID);
+ } else if (type == ResourceFolderType.ANIMATOR
+ || type == ResourceFolderType.ANIM) {
+ IDE.setDefaultEditor(file, AnimationEditor.ID);
} else if (type == ResourceFolderType.XML) {
if (XmlEditor.canHandleFile(file)) {
if (DEBUG_XML_FILE_INIT) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AaptQuickFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AaptQuickFix.java
index 436fcace9..7d79086a2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AaptQuickFix.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AaptQuickFix.java
@@ -16,9 +16,12 @@
package com.android.ide.eclipse.adt.internal.build;
+import static com.android.ide.common.layout.LayoutConstants.ANDROID_URI;
+
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.adt.internal.resources.ResourceHelper;
import com.android.resources.ResourceType;
import com.android.util.Pair;
@@ -31,6 +34,7 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext;
@@ -45,12 +49,21 @@ import org.eclipse.ui.IMarkerResolutionGenerator2;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.editors.text.TextFileDocumentProvider;
import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
/**
* Shared handler for both quick assist processors (Control key handler) and quick fix
* marker resolution (Problem view handling), since there is a lot of overlap between
* these two UI handlers.
*/
+@SuppressWarnings("restriction") // XML model
public class AaptQuickFix implements IMarkerResolutionGenerator2, IQuickAssistProcessor {
public AaptQuickFix() {
@@ -61,6 +74,11 @@ public class AaptQuickFix implements IMarkerResolutionGenerator2, IQuickAssistPr
return "No resource found that matches the given name";
}
+ /** Returns the error message from aapt that signals a missing namespace declaration */
+ private static String getUnboundErrorMessage() {
+ return "Error parsing XML: unbound prefix";
+ }
+
// ---- Implements IMarkerResolution2 ----
public boolean hasResolutions(IMarker marker) {
@@ -71,12 +89,24 @@ public class AaptQuickFix implements IMarkerResolutionGenerator2, IQuickAssistPr
AdtPlugin.log(e, null);
}
- return message != null && message.contains(getTargetMarkerErrorMessage());
+ return message != null
+ && (message.contains(getTargetMarkerErrorMessage())
+ || message.contains(getUnboundErrorMessage()));
}
public IMarkerResolution[] getResolutions(IMarker marker) {
IResource markerResource = marker.getResource();
IProject project = markerResource.getProject();
+ try {
+ String message = (String) marker.getAttribute(IMarker.MESSAGE);
+ if (message.contains(getUnboundErrorMessage()) && markerResource instanceof IFile) {
+ return new IMarkerResolution[] {
+ new CreateNamespaceFix((IFile) markerResource)
+ };
+ }
+ } catch (CoreException e1) {
+ AdtPlugin.log(e1, null);
+ }
int start = marker.getAttribute(IMarker.CHAR_START, 0);
int end = marker.getAttribute(IMarker.CHAR_END, 0);
@@ -158,6 +188,10 @@ public class AaptQuickFix implements IMarkerResolutionGenerator2, IQuickAssistPr
};
}
}
+ } else if (message.contains(getUnboundErrorMessage())) {
+ return new ICompletionProposal[] {
+ new CreateNamespaceFix(null)
+ };
}
}
} catch (CoreException e) {
@@ -174,6 +208,120 @@ public class AaptQuickFix implements IMarkerResolutionGenerator2, IQuickAssistPr
return null;
}
+ /** Quick fix to insert namespace binding when missing */
+ private final static class CreateNamespaceFix
+ implements ICompletionProposal, IMarkerResolution2 {
+ private IFile mFile;
+
+ public CreateNamespaceFix(IFile file) {
+ mFile = file;
+ }
+
+ private IndexedRegion perform(IDocument doc) {
+ IModelManager manager = StructuredModelManager.getModelManager();
+ IStructuredModel model = manager.getExistingModelForEdit(doc);
+ if (model != null) {
+ try {
+ perform(model);
+ } finally {
+ model.releaseFromEdit();
+ }
+ }
+
+ return null;
+ }
+
+ private IndexedRegion perform(IFile file) {
+ IModelManager manager = StructuredModelManager.getModelManager();
+ IStructuredModel model;
+ try {
+ model = manager.getModelForEdit(file);
+ if (model != null) {
+ try {
+ perform(model);
+ } finally {
+ model.releaseFromEdit();
+ }
+ }
+ } catch (Exception e) {
+ AdtPlugin.log(e, "Can't look up XML model");
+ }
+
+ return null;
+ }
+
+ private IndexedRegion perform(IStructuredModel model) {
+ if (model instanceof IDOMModel) {
+ IDOMModel domModel = (IDOMModel) model;
+ Document document = domModel.getDocument();
+ Element element = document.getDocumentElement();
+ Attr attr = document.createAttributeNS(XmlnsAttributeDescriptor.XMLNS_URI,
+ "xmlns:android"); //$NON-NLS-1$
+ attr.setValue(ANDROID_URI);
+ element.getAttributes().setNamedItemNS(attr);
+ return (IndexedRegion) attr;
+ }
+
+ return null;
+ }
+
+ // ---- Implements ICompletionProposal ----
+
+ public void apply(IDocument document) {
+ perform(document);
+ }
+
+ public String getAdditionalProposalInfo() {
+ return "Adds an Android namespace declaratiopn to the root element.";
+ }
+
+ public IContextInformation getContextInformation() {
+ return null;
+ }
+
+ public String getDisplayString() {
+ return "Insert namespace binding";
+ }
+
+ public Image getImage() {
+ return AdtPlugin.getAndroidLogo();
+ }
+
+ public Point getSelection(IDocument doc) {
+ return null;
+ }
+
+
+ // ---- Implements MarkerResolution2 ----
+
+ public String getLabel() {
+ return getDisplayString();
+ }
+
+ public void run(IMarker marker) {
+ try {
+ AdtPlugin.openFile(mFile, null);
+ } catch (PartInitException e) {
+ AdtPlugin.log(e, "Can't open file %1$s", mFile.getName());
+ }
+
+ IndexedRegion indexedRegion = perform(mFile);
+ if (indexedRegion != null) {
+ try {
+ IRegion region =
+ new Region(indexedRegion.getStartOffset(), indexedRegion.getLength());
+ AdtPlugin.openFile(mFile, region);
+ } catch (PartInitException e) {
+ AdtPlugin.log(e, "Can't open file %1$s", mFile.getName());
+ }
+ }
+ }
+
+ public String getDescription() {
+ return getAdditionalProposalInfo();
+ }
+ }
+
private static class CreateResourceProposal
implements ICompletionProposal, IMarkerResolution2 {
private final IProject mProject;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssist.java
index 86ff16e88..17ffe30eb 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssist.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssist.java
@@ -1163,6 +1163,11 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
return null;
}
+ /** Returns the root descriptor id to use */
+ protected int getRootDescriptorId() {
+ return mDescriptorId;
+ }
+
/**
* Computes (if needed) and returns the root descriptor.
*/
@@ -1170,7 +1175,8 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
if (mRootDescriptor == null) {
AndroidTargetData data = mEditor.getTargetData();
if (data != null) {
- IDescriptorProvider descriptorProvider = data.getDescriptorProvider(mDescriptorId);
+ IDescriptorProvider descriptorProvider =
+ data.getDescriptorProvider(getRootDescriptorId());
if (descriptorProvider != null) {
mRootDescriptor = new ElementDescriptor("", //$NON-NLS-1$
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimDescriptors.java
new file mode 100644
index 000000000..dabab8784
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimDescriptors.java
@@ -0,0 +1,124 @@
+/*
+ * 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.animator;
+
+import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_NAME;
+
+import com.android.ide.common.resources.platform.DeclareStyleableInfo;
+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 com.android.sdklib.SdkConstants;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/** Descriptors for the res/anim resources */
+public class AnimDescriptors implements IDescriptorProvider {
+ /** The root element descriptor */
+ private ElementDescriptor mDescriptor;
+ /** The root element descriptors */
+ private ElementDescriptor[] mRootDescriptors;
+ private Map<String, ElementDescriptor> nameToDescriptor;
+
+ /** @return the root descriptor. */
+ public ElementDescriptor getDescriptor() {
+ if (mDescriptor == null) {
+ mDescriptor = new ElementDescriptor("", getRootElementDescriptors()); //$NON-NLS-1$
+ }
+
+ return mDescriptor;
+ }
+
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return mRootDescriptors;
+ }
+
+ public ElementDescriptor getElementDescriptor(String mRootTag) {
+ if (nameToDescriptor == null) {
+ nameToDescriptor = new HashMap<String, ElementDescriptor>();
+ for (ElementDescriptor descriptor : getRootElementDescriptors()) {
+ nameToDescriptor.put(descriptor.getXmlName(), descriptor);
+ }
+ }
+
+ ElementDescriptor descriptor = nameToDescriptor.get(mRootTag);
+ if (descriptor == null) {
+ descriptor = getDescriptor();
+ }
+ return descriptor;
+ }
+
+ public synchronized void updateDescriptors(Map<String, DeclareStyleableInfo> styleMap) {
+ if (styleMap == null) {
+ return;
+ }
+
+ XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor(ANDROID_NS_NAME,
+ SdkConstants.NS_RESOURCES);
+
+ List<ElementDescriptor> descriptors = new ArrayList<ElementDescriptor>();
+
+ String sdkUrl =
+ "http://developer.android.com/guide/topics/graphics/view-animation.html"; //$NON-NLS-1$
+ ElementDescriptor set = AnimatorDescriptors.addElement(descriptors, styleMap,
+ "set", "Set", "AnimationSet", "Animation", //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-4$
+ "A container that holds other animation elements (<alpha>, <scale>, "
+ + "<translate>, <rotate>) or other <set> elements. ",
+ sdkUrl,
+ xmlns, null, true /*mandatory*/);
+
+ AnimatorDescriptors.addElement(descriptors, styleMap,
+ "alpha", "Alpha", "AlphaAnimation", "Animation", //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-4$
+ "A fade-in or fade-out animation.",
+ sdkUrl,
+ xmlns, null, true /*mandatory*/);
+
+ AnimatorDescriptors.addElement(descriptors, styleMap,
+ "scale", "Scale", "ScaleAnimation", "Animation", //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-4$
+ "A resizing animation. You can specify the center point of the image from "
+ + "which it grows outward (or inward) by specifying pivotX and pivotY. "
+ + "For example, if these values are 0, 0 (top-left corner), all growth "
+ + "will be down and to the right.",
+ sdkUrl,
+ xmlns, null, true /*mandatory*/);
+
+ AnimatorDescriptors.addElement(descriptors, styleMap,
+ "rotate", "Rotate", "RotateAnimation", "Animation", //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-4$
+ "A rotation animation.",
+ sdkUrl,
+ xmlns, null, true /*mandatory*/);
+
+ AnimatorDescriptors.addElement(descriptors, styleMap,
+ "translate", "Translate", "TranslateAnimation", "Animation", //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-4$
+ "A vertical and/or horizontal motion. Supports the following attributes in "
+ + "any of the following three formats: values from -100 to 100 ending "
+ + "with \"%\", indicating a percentage relative to itself; values from "
+ + "-100 to 100 ending in \"%p\", indicating a percentage relative to its "
+ + "parent; a float value with no suffix, indicating an absolute value.",
+ sdkUrl,
+ xmlns, null, true /*mandatory*/);
+
+ mRootDescriptors = descriptors.toArray(new ElementDescriptor[descriptors.size()]);
+
+ // Allow <set> to nest the others (and other sets)
+ if (set != null) {
+ set.setChildren(mRootDescriptors);
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimationContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimationContentAssist.java
new file mode 100644
index 000000000..ee0c290c7
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimationContentAssist.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2007 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.animator;
+
+import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_NAME_PREFIX;
+import static com.android.ide.eclipse.adt.AdtConstants.ANDROID_PKG;
+
+import com.android.annotations.VisibleForTesting;
+import com.android.ide.common.api.IAttributeInfo.Format;
+import com.android.ide.common.resources.ResourceItem;
+import com.android.ide.common.resources.ResourceRepository;
+import com.android.ide.eclipse.adt.internal.editors.AndroidContentAssist;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
+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.sdk.AndroidTargetData;
+import com.android.resources.ResourceFolderType;
+import com.android.resources.ResourceType;
+import com.android.util.Pair;
+
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.w3c.dom.Node;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Content Assist Processor for /res/drawable XML files
+ */
+@VisibleForTesting
+public final class AnimationContentAssist extends AndroidContentAssist {
+ private static final String OBJECT_ANIMATOR = "objectAnimator"; //$NON-NLS-1$
+ private static final String PROPERTY_NAME = "propertyName"; //$NON-NLS-1$
+ private static final String INTERPOLATOR_PROPERTY_NAME = "interpolator"; //$NON-NLS-1$
+ private static final String INTERPOLATOR_NAME_SUFFIX = "_interpolator"; //$NON-NLS-1$
+
+ public AnimationContentAssist() {
+ super(AndroidTargetData.DESCRIPTOR_ANIMATOR);
+ }
+
+ @Override
+ protected int getRootDescriptorId() {
+ String folderName = mEditor.getInputFile().getParent().getName();
+ ResourceFolderType folderType = ResourceFolderType.getFolderType(folderName);
+ if (folderType == ResourceFolderType.ANIM) {
+ return AndroidTargetData.DESCRIPTOR_ANIM;
+ } else {
+ return AndroidTargetData.DESCRIPTOR_ANIMATOR;
+ }
+ }
+
+ @Override
+ protected void computeAttributeValues(List<ICompletionProposal> proposals, int offset,
+ String parentTagName, String attributeName, Node node, String wordPrefix,
+ boolean skipEndTag, int replaceLength) {
+
+ // Add value completion for the interpolator and propertyName attributes
+
+ if (attributeName.endsWith(INTERPOLATOR_PROPERTY_NAME)) {
+ if (!wordPrefix.startsWith("@android:anim/")) { //$NON-NLS-1$
+ // List all framework interpolators with full path first
+ AndroidTargetData data = mEditor.getTargetData();
+ ResourceRepository repository = data.getFrameworkResources();
+ List<String> interpolators = new ArrayList<String>();
+ String base = '@' + ANDROID_PKG + ':' + ResourceType.ANIM.getName() + '/';
+ for (ResourceItem item : repository.getResourceItemsOfType(ResourceType.ANIM)) {
+ String name = item.getName();
+ if (name.endsWith(INTERPOLATOR_NAME_SUFFIX)) {
+ interpolators.add(base + item.getName());
+ }
+ }
+ addMatchingProposals(proposals, interpolators.toArray(), offset, node, wordPrefix,
+ (char) 0 /* needTag */, true /* isAttribute */, false /* isNew */,
+ skipEndTag /* skipEndTag */, replaceLength);
+ }
+
+
+ super.computeAttributeValues(proposals, offset, parentTagName, attributeName, node,
+ wordPrefix, skipEndTag, replaceLength);
+ } else if (parentTagName.equals(OBJECT_ANIMATOR)
+ && attributeName.endsWith(PROPERTY_NAME)) {
+
+ // Special case: the user is code completing inside
+ // <objectAnimator propertyName="^">
+ // In this case, offer ALL attribute names that make sense for animation
+ // (e.g. all numeric ones)
+
+ String attributePrefix = wordPrefix;
+ if (startsWith(attributePrefix, ANDROID_NS_NAME_PREFIX)) {
+ attributePrefix = attributePrefix.substring(ANDROID_NS_NAME_PREFIX.length());
+ }
+
+ AndroidTargetData data = mEditor.getTargetData();
+ if (data != null) {
+ IDescriptorProvider descriptorProvider =
+ data.getDescriptorProvider(AndroidTargetData.DESCRIPTOR_LAYOUT);
+ if (descriptorProvider != null) {
+ ElementDescriptor[] rootElementDescriptors =
+ descriptorProvider.getRootElementDescriptors();
+ Map<String, AttributeDescriptor> matches =
+ new HashMap<String, AttributeDescriptor>(180);
+ for (ElementDescriptor elementDesc : rootElementDescriptors) {
+ for (AttributeDescriptor desc : elementDesc.getAttributes()) {
+ if (desc instanceof SeparatorAttributeDescriptor) {
+ continue;
+ }
+ String name = desc.getXmlLocalName();
+ if (startsWith(name, attributePrefix)) {
+ for (Format f : desc.getAttributeInfo().getFormats()) {
+ if (f == Format.INTEGER || f == Format.FLOAT) {
+ // TODO: Filter out some common properties
+ // that the user probably isn't trying to
+ // animate:
+ // num*, min*, max*, *Index, *Threshold,
+ // *Duration, *Id, *Limit
+
+ matches.put(name, desc);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ List<AttributeDescriptor> sorted =
+ new ArrayList<AttributeDescriptor>(matches.size());
+ sorted.addAll(matches.values());
+ Collections.sort(sorted);
+ // Extract just the name+description pairs, since we don't want to
+ // use the full attribute descriptor (which forces the namespace
+ // prefix to be included)
+ List<Pair<String, String>> pairs =
+ new ArrayList<Pair<String, String>>(sorted.size());
+ for (AttributeDescriptor d : sorted) {
+ pairs.add(Pair.of(d.getXmlLocalName(), d.getAttributeInfo().getJavaDoc()));
+ }
+
+ addMatchingProposals(proposals, pairs.toArray(), offset, node, wordPrefix,
+ (char) 0 /* needTag */, true /* isAttribute */, false /* isNew */,
+ skipEndTag /* skipEndTag */, replaceLength);
+ return;
+ }
+ }
+ } else {
+ super.computeAttributeValues(proposals, offset, parentTagName, attributeName, node,
+ wordPrefix, skipEndTag, replaceLength);
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimationEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimationEditor.java
new file mode 100644
index 000000000..9f6123898
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimationEditor.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2007 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.animator;
+
+import static com.android.ide.eclipse.adt.AdtConstants.EDITORS_NAMESPACE;
+
+import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
+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.uimodel.UiElementNode;
+import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
+import com.android.resources.ResourceFolderType;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * Editor for /res/animator XML files.
+ */
+@SuppressWarnings("restriction")
+public class AnimationEditor extends AndroidXmlEditor {
+ public static final String ID = EDITORS_NAMESPACE + ".animator.AnimationEditor"; //$NON-NLS-1$
+
+ /** Root node of the UI element hierarchy */
+ private UiElementNode mUiRootNode;
+ /** The tag used at the root */
+ private String mRootTag;
+
+ public AnimationEditor() {
+ super();
+ }
+
+ @Override
+ public UiElementNode getUiRootNode() {
+ return mUiRootNode;
+ }
+
+ @Override
+ public boolean isSaveAsAllowed() {
+ return true;
+ }
+
+ @Override
+ protected void createFormPages() {
+ /* Disabled for now; doesn't work quite right
+ try {
+ addPage(new AnimatorTreePage(this));
+ } catch (PartInitException e) {
+ AdtPlugin.log(IStatus.ERROR, "Error creating nested page"); //$NON-NLS-1$
+ AdtPlugin.getDefault().getLog().log(e.getStatus());
+ }
+ */
+ }
+
+ /* (non-java doc)
+ * Change the tab/title name to include the project name.
+ */
+ @Override
+ protected void setInput(IEditorInput input) {
+ super.setInput(input);
+ if (input instanceof FileEditorInput) {
+ FileEditorInput fileInput = (FileEditorInput) input;
+ IFile file = fileInput.getFile();
+ setPartName(String.format("%1$s",
+ file.getName()));
+ }
+ }
+
+ /**
+ * Processes the new XML Model.
+ *
+ * @param xmlDoc The XML document, if available, or null if none exists.
+ */
+ @Override
+ protected void xmlModelChanged(Document xmlDoc) {
+ Element rootElement = xmlDoc.getDocumentElement();
+ if (rootElement != null) {
+ mRootTag = rootElement.getTagName();
+ }
+
+ // create the ui root node on demand.
+ initUiRootNode(false /*force*/);
+
+ if (mRootTag != null
+ && !mRootTag.equals(mUiRootNode.getDescriptor().getXmlLocalName())) {
+ AndroidTargetData data = getTargetData();
+ if (data != null) {
+ ElementDescriptor descriptor;
+ if (getFolderType() == ResourceFolderType.ANIM) {
+ descriptor = data.getAnimDescriptors().getElementDescriptor(mRootTag);
+ } else {
+ descriptor = data.getAnimatorDescriptors().getElementDescriptor(mRootTag);
+ }
+ // Replace top level node now that we know the actual type
+
+ // Disconnect from old
+ mUiRootNode.setEditor(null);
+ mUiRootNode.setXmlDocument(null);
+
+ // Create new
+ mUiRootNode = descriptor.createUiNode();
+ mUiRootNode.setXmlDocument(xmlDoc);
+ mUiRootNode.setEditor(this);
+ }
+ }
+
+ if (mUiRootNode.getDescriptor() instanceof DocumentDescriptor) {
+ mUiRootNode.loadFromXmlNode(xmlDoc);
+ } else {
+ mUiRootNode.loadFromXmlNode(rootElement);
+ }
+
+ super.xmlModelChanged(xmlDoc);
+ }
+
+ @Override
+ protected void initUiRootNode(boolean force) {
+ // The manifest UI node is always created, even if there's no corresponding XML node.
+ if (mUiRootNode == null || force) {
+ ElementDescriptor descriptor;
+ boolean reload = false;
+ AndroidTargetData data = getTargetData();
+ if (data == null) {
+ descriptor = new DocumentDescriptor("temp", null /*children*/);
+ } else {
+ if (getFolderType() == ResourceFolderType.ANIM) {
+ descriptor = data.getAnimDescriptors().getElementDescriptor(mRootTag);
+ } else {
+ descriptor = data.getAnimatorDescriptors().getElementDescriptor(mRootTag);
+ }
+ reload = true;
+ }
+ mUiRootNode = descriptor.createUiNode();
+ mUiRootNode.setEditor(this);
+
+ if (reload) {
+ onDescriptorsChanged();
+ }
+ }
+ }
+
+ private ResourceFolderType getFolderType() {
+ IFile inputFile = getInputFile();
+ if (inputFile != null) {
+ String folderName = inputFile.getParent().getName();
+ return ResourceFolderType.getFolderType(folderName);
+ }
+ return ResourceFolderType.ANIMATOR;
+ }
+
+ private void onDescriptorsChanged() {
+ IStructuredModel model = getModelForRead();
+ if (model != null) {
+ try {
+ Node node = getXmlDocument(model).getDocumentElement();
+ mUiRootNode.reloadFromXmlNode(node);
+ } finally {
+ model.releaseFromRead();
+ }
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimationSourceViewerConfig.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimationSourceViewerConfig.java
new file mode 100644
index 000000000..87a145bc7
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimationSourceViewerConfig.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2007 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.animator;
+
+
+import com.android.ide.eclipse.adt.internal.editors.AndroidSourceViewerConfig;
+
+/**
+ * Source Viewer Configuration for animation files.
+ */
+public class AnimationSourceViewerConfig extends AndroidSourceViewerConfig {
+
+ public AnimationSourceViewerConfig() {
+ super(new AnimationContentAssist());
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimatorDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimatorDescriptors.java
new file mode 100644
index 000000000..644aebb64
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimatorDescriptors.java
@@ -0,0 +1,182 @@
+/*
+ * 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.animator;
+
+import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_NAME;
+
+import com.android.ide.common.resources.platform.DeclareStyleableInfo;
+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 com.android.sdklib.SdkConstants;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Descriptors for /res/animator XML files.
+ */
+public class AnimatorDescriptors implements IDescriptorProvider {
+ /** The root element descriptor */
+ private ElementDescriptor mDescriptor;
+ /** The root element descriptors */
+ private ElementDescriptor[] mRootDescriptors;
+ private Map<String, ElementDescriptor> nameToDescriptor;
+
+ /** @return the root descriptor. */
+ public ElementDescriptor getDescriptor() {
+ if (mDescriptor == null) {
+ mDescriptor = new ElementDescriptor("", getRootElementDescriptors()); //$NON-NLS-1$
+ }
+
+ return mDescriptor;
+ }
+
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return mRootDescriptors;
+ }
+
+ public ElementDescriptor getElementDescriptor(String mRootTag) {
+ if (nameToDescriptor == null) {
+ nameToDescriptor = new HashMap<String, ElementDescriptor>();
+ for (ElementDescriptor descriptor : getRootElementDescriptors()) {
+ nameToDescriptor.put(descriptor.getXmlName(), descriptor);
+ }
+ }
+
+ ElementDescriptor descriptor = nameToDescriptor.get(mRootTag);
+ if (descriptor == null) {
+ descriptor = getDescriptor();
+ }
+ return descriptor;
+ }
+
+ public synchronized void updateDescriptors(Map<String, DeclareStyleableInfo> styleMap) {
+ if (styleMap == null) {
+ return;
+ }
+
+ XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor(ANDROID_NS_NAME,
+ SdkConstants.NS_RESOURCES);
+
+ List<ElementDescriptor> descriptors = new ArrayList<ElementDescriptor>();
+
+ String sdkUrl =
+ "http://developer.android.com/guide/topics/graphics/animation.html"; //$NON-NLS-1$
+
+ ElementDescriptor set = addElement(descriptors, styleMap,
+ "set", "Animator Set", "AnimatorSet", null, //$NON-NLS-1$ //$NON-NLS-3$
+ null /* tooltip */, sdkUrl,
+ xmlns, null, true /*mandatory*/);
+
+ ElementDescriptor objectAnimator = addElement(descriptors, styleMap,
+ "objectAnimator", "Object Animator", //$NON-NLS-1$
+ "PropertyAnimator", "Animator", //$NON-NLS-1$ //$NON-NLS-2$
+ null /* tooltip */, sdkUrl,
+ xmlns, null, true /*mandatory*/);
+
+ ElementDescriptor animator = addElement(descriptors, styleMap,
+ "animator", "Animator", "Animator", null, //$NON-NLS-1$ //$NON-NLS-3$
+ null /* tooltip */, sdkUrl,
+ xmlns, null, true /*mandatory*/);
+
+ mRootDescriptors = descriptors.toArray(new ElementDescriptor[descriptors.size()]);
+
+ // Allow arbitrary nesting: the children of all of these element can include
+ // any of the others
+ if (objectAnimator != null) {
+ objectAnimator.setChildren(mRootDescriptors);
+ }
+ if (animator != null) {
+ animator.setChildren(mRootDescriptors);
+ }
+ if (set != null) {
+ set.setChildren(mRootDescriptors);
+ }
+ }
+
+ /**
+ * Looks up the given style, and if found creates a new {@link ElementDescriptor}
+ * corresponding to the style. It can optionally take an extra style to merge in
+ * additional attributes from, and an extra attribute to add in as well. The new
+ * element, if it exists, can also be optionally added into a list.
+ *
+ * @param descriptors an optional list to add the element into, or null
+ * @param styleMap The map style => attributes from the attrs.xml file
+ * @param xmlName the XML tag name to use for the element
+ * @param uiName the UI name to display the element as
+ * @param styleName the name of the style which must exist for this style
+ * @param extraStyle an optional extra style to merge in attributes from, or null
+ * @param tooltip the tooltip or documentation for this element, or null
+ * @param sdkUrl an optional SDK url to display for the element, or null
+ * @param extraAttribute an extra attribute to add to the attributes list, or null
+ * @param childrenElements an array of children allowed by this element, or null
+ * @param mandatory if true, this element is mandatory
+ * @return a newly created element, or null if the style does not exist
+ */
+ public static ElementDescriptor addElement(
+ List<ElementDescriptor> descriptors,
+ Map<String, DeclareStyleableInfo> styleMap,
+ String xmlName, String uiName, String styleName, String extraStyle,
+ String tooltip, String sdkUrl,
+ AttributeDescriptor extraAttribute,
+ ElementDescriptor[] childrenElements,
+ boolean mandatory) {
+ DeclareStyleableInfo style = styleMap.get(styleName);
+ if (style == null) {
+ return null;
+ }
+ ElementDescriptor element = new ElementDescriptor(xmlName, uiName, tooltip, sdkUrl,
+ null, childrenElements, mandatory);
+
+ ArrayList<AttributeDescriptor> descs = new ArrayList<AttributeDescriptor>();
+
+ DescriptorsUtils.appendAttributes(descs,
+ null, // elementName
+ SdkConstants.NS_RESOURCES,
+ style.getAttributes(),
+ null, // requiredAttributes
+ null); // overrides
+ element.setTooltip(style.getJavaDoc());
+
+ if (extraStyle != null) {
+ style = styleMap.get(extraStyle);
+ if (style != null) {
+ DescriptorsUtils.appendAttributes(descs,
+ null, // elementName
+ SdkConstants.NS_RESOURCES,
+ style.getAttributes(),
+ null, // requiredAttributes
+ null); // overrides
+ }
+ }
+
+ if (extraAttribute != null) {
+ descs.add(extraAttribute);
+ }
+
+ element.setAttributes(descs.toArray(new AttributeDescriptor[descs.size()]));
+ if (descriptors != null) {
+ descriptors.add(element);
+ }
+
+ return element;
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/color/ColorContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/color/ColorContentAssist.java
new file mode 100644
index 000000000..15704393e
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/color/ColorContentAssist.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2007 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.color;
+
+import com.android.annotations.VisibleForTesting;
+import com.android.ide.eclipse.adt.internal.editors.AndroidContentAssist;
+import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
+
+/**
+ * Content Assist Processor for /res/color XML files
+ */
+@VisibleForTesting
+public final class ColorContentAssist extends AndroidContentAssist {
+ public ColorContentAssist() {
+ super(AndroidTargetData.DESCRIPTOR_COLOR);
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/color/ColorDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/color/ColorDescriptors.java
new file mode 100644
index 000000000..f6e50a8ea
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/color/ColorDescriptors.java
@@ -0,0 +1,94 @@
+/*
+ * 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.color;
+
+import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_NAME;
+import static com.android.sdklib.SdkConstants.NS_RESOURCES;
+
+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.AttributeDescriptor;
+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 com.android.sdklib.SdkConstants;
+
+import java.util.Map;
+
+/** Descriptors for /res/color XML files */
+public class ColorDescriptors implements IDescriptorProvider {
+ private static final String SDK_URL =
+ "http://d.android.com/guide/topics/resources/color-list-resource.html"; //$NON-NLS-1$
+
+ /** The root element descriptor */
+ private ElementDescriptor mDescriptor = new ElementDescriptor(
+ "selector", "Selector",
+ "Required. This must be the root element. Contains one or more <item> elements.",
+ SDK_URL,
+ new AttributeDescriptor[] { new XmlnsAttributeDescriptor(ANDROID_NS_NAME,
+ NS_RESOURCES) },
+ null /*children: added later*/, true /*mandatory*/);
+
+ /** @return the root descriptor. */
+ public ElementDescriptor getDescriptor() {
+ if (mDescriptor == null) {
+ mDescriptor = new ElementDescriptor("", getRootElementDescriptors()); //$NON-NLS-1$
+ }
+
+ return mDescriptor;
+ }
+
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return new ElementDescriptor[] { mDescriptor };
+ }
+
+ public synchronized void updateDescriptors(Map<String, DeclareStyleableInfo> styleMap) {
+ if (styleMap == null) {
+ return;
+ }
+
+ // 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,
+ new ReferenceAttributeDescriptor(
+ ResourceType.COLOR, "color", "color", //$NON-NLS-1$ //$NON-NLS-2$
+ SdkConstants.NS_RESOURCES,
+ "Hexadeximal color. Required. The color is specified with an RGB value and "
+ + "optional alpha channel.\n"
+ + "The value always begins with a pound (#) character and then "
+ + "followed by the Alpha-Red-Green-Blue information in one of "
+ + "the following formats:\n"
+ + "* RGB\n"
+ + "* ARGB\n"
+ + "* RRGGBB\n"
+ + "* AARRGGBB",
+ new AttributeInfo("drawable", new Format[] { Format.COLOR })),
+ null, /* This is wrong -- we can now embed any above drawable
+ (but without xmlns as extra) */
+ false /*mandatory*/);
+
+ if (selectorItem != null) {
+ mDescriptor.setChildren(new ElementDescriptor[] { selectorItem });
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/color/ColorEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/color/ColorEditor.java
new file mode 100644
index 000000000..b0e33271e
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/color/ColorEditor.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2007 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.color;
+
+import static com.android.ide.eclipse.adt.AdtConstants.EDITORS_NAMESPACE;
+
+import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
+import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * Editor for /res/color XML files.
+ */
+@SuppressWarnings("restriction")
+public class ColorEditor extends AndroidXmlEditor {
+ public static final String ID = EDITORS_NAMESPACE + ".color.ColorEditor"; //$NON-NLS-1$
+
+ /** Root node of the UI element hierarchy */
+ private UiElementNode mUiRootNode;
+
+ public ColorEditor() {
+ super();
+ }
+
+ @Override
+ public UiElementNode getUiRootNode() {
+ return mUiRootNode;
+ }
+
+ @Override
+ public boolean isSaveAsAllowed() {
+ return true;
+ }
+
+ @Override
+ protected void createFormPages() {
+ /* Disabled for now; doesn't work quite right
+ try {
+ addPage(new ColorTreePage(this));
+ } catch (PartInitException e) {
+ AdtPlugin.log(IStatus.ERROR, "Error creating nested page"); //$NON-NLS-1$
+ AdtPlugin.getDefault().getLog().log(e.getStatus());
+ }
+ */
+ }
+
+ /* (non-java doc)
+ * Change the tab/title name to include the project name.
+ */
+ @Override
+ protected void setInput(IEditorInput input) {
+ super.setInput(input);
+ if (input instanceof FileEditorInput) {
+ FileEditorInput fileInput = (FileEditorInput) input;
+ IFile file = fileInput.getFile();
+ setPartName(String.format("%1$s",
+ file.getName()));
+ }
+ }
+
+ @Override
+ protected void xmlModelChanged(Document xmlDoc) {
+ // create the ui root node on demand.
+ initUiRootNode(false /*force*/);
+
+ Element rootElement = xmlDoc.getDocumentElement();
+ mUiRootNode.loadFromXmlNode(rootElement);
+
+ super.xmlModelChanged(xmlDoc);
+ }
+
+ @Override
+ protected void initUiRootNode(boolean force) {
+ // The manifest UI node is always created, even if there's no corresponding XML node.
+ if (mUiRootNode == null || force) {
+ ElementDescriptor descriptor;
+ AndroidTargetData data = getTargetData();
+ if (data == null) {
+ descriptor = new ColorDescriptors().getDescriptor();
+ } else {
+ descriptor = data.getColorDescriptors().getDescriptor();
+ }
+ mUiRootNode = descriptor.createUiNode();
+ mUiRootNode.setEditor(this);
+ onDescriptorsChanged();
+ }
+ }
+
+ private void onDescriptorsChanged() {
+ IStructuredModel model = getModelForRead();
+ if (model != null) {
+ try {
+ Node node = getXmlDocument(model).getDocumentElement();
+ mUiRootNode.reloadFromXmlNode(node);
+ } finally {
+ model.releaseFromRead();
+ }
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/color/ColorSourceViewerConfig.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/color/ColorSourceViewerConfig.java
new file mode 100644
index 000000000..4f12ce571
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/color/ColorSourceViewerConfig.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2007 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.color;
+
+
+import com.android.ide.eclipse.adt.internal.editors.AndroidSourceViewerConfig;
+
+/**
+ * Source Viewer Configuration that calls in ColorContentAssist.
+ */
+public class ColorSourceViewerConfig extends AndroidSourceViewerConfig {
+
+ public ColorSourceViewerConfig() {
+ super(new ColorContentAssist());
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/BooleanAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/BooleanAttributeDescriptor.java
index d0806c583..f1def3977 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/BooleanAttributeDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/BooleanAttributeDescriptor.java
@@ -24,11 +24,11 @@ import com.android.ide.eclipse.adt.internal.editors.uimodel.UiListAttributeNode;
* It is displayed by a {@link UiListAttributeNode}.
*/
public class BooleanAttributeDescriptor extends ListAttributeDescriptor {
+ private static final String[] VALUES = new String[] { "true", "false" }; //$NON-NLS-1$ //$NON-NLS-2$
public BooleanAttributeDescriptor(String xmlLocalName, String uiName, String nsUri,
String tooltip, IAttributeInfo attrInfo) {
- super(xmlLocalName, uiName, nsUri, tooltip, attrInfo,
- new String[] { "true", "false" }); //$NON-NLS-1$ //$NON-NLS-2$
+ super(xmlLocalName, uiName, nsUri, tooltip, attrInfo, VALUES);
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/drawable/DrawableContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/drawable/DrawableContentAssist.java
new file mode 100644
index 000000000..b0bea511d
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/drawable/DrawableContentAssist.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2007 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 com.android.annotations.VisibleForTesting;
+import com.android.ide.eclipse.adt.internal.editors.AndroidContentAssist;
+import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
+
+/**
+ * Content Assist Processor for /res/drawable XML files
+ */
+@VisibleForTesting
+public final class DrawableContentAssist extends AndroidContentAssist {
+ public DrawableContentAssist() {
+ super(AndroidTargetData.DESCRIPTOR_DRAWABLE);
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/drawable/DrawableDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/drawable/DrawableDescriptors.java
new file mode 100644
index 000000000..1e71795c4
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/drawable/DrawableDescriptors.java
@@ -0,0 +1,300 @@
+/*
+ * 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.ide.common.layout.LayoutConstants.ANDROID_NS_NAME;
+
+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 com.android.sdklib.SdkConstants;
+
+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. */
+ public ElementDescriptor getDescriptor() {
+ if (mDescriptor == null) {
+ mDescriptor = new ElementDescriptor("", getRootElementDescriptors()); //$NON-NLS-1$
+ }
+
+ return mDescriptor;
+ }
+
+ 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,
+ SdkConstants.NS_RESOURCES);
+ Format[] referenceFormat = new Format[] { Format.REFERENCE };
+
+ 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*/);
+
+ 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 /*mandatory*/);
+
+ 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", "drawable", //$NON-NLS-1$ //$NON-NLS-2$
+ SdkConstants.NS_RESOURCES,
+ "Reference to a drawable resource.",
+ new AttributeInfo("drawable", referenceFormat)),
+ 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);
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/drawable/DrawableEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/drawable/DrawableEditor.java
new file mode 100644
index 000000000..aaaeb4b6d
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/drawable/DrawableEditor.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2007 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.ide.eclipse.adt.AdtConstants.EDITORS_NAMESPACE;
+
+import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
+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.uimodel.UiElementNode;
+import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * Editor for /res/drawable XML files.
+ */
+@SuppressWarnings("restriction")
+public class DrawableEditor extends AndroidXmlEditor {
+ public static final String ID = EDITORS_NAMESPACE + ".drawable.DrawableEditor"; //$NON-NLS-1$
+
+ /** Root node of the UI element hierarchy */
+ private UiElementNode mUiRootNode;
+ /** The tag used at the root */
+ private String mRootTag;
+
+ /**
+ * Creates the form editor for resources XML files.
+ */
+ public DrawableEditor() {
+ super();
+ }
+
+ @Override
+ public UiElementNode getUiRootNode() {
+ return mUiRootNode;
+ }
+
+ @Override
+ public boolean isSaveAsAllowed() {
+ return true;
+ }
+
+ @Override
+ protected void createFormPages() {
+ /* Disabled for now; doesn't work quite right
+ try {
+ addPage(new DrawableTreePage(this));
+ } catch (PartInitException e) {
+ AdtPlugin.log(IStatus.ERROR, "Error creating nested page"); //$NON-NLS-1$
+ AdtPlugin.getDefault().getLog().log(e.getStatus());
+ }
+ */
+ }
+
+ @Override
+ protected void setInput(IEditorInput input) {
+ super.setInput(input);
+ if (input instanceof FileEditorInput) {
+ FileEditorInput fileInput = (FileEditorInput) input;
+ IFile file = fileInput.getFile();
+ setPartName(String.format("%1$s",
+ file.getName()));
+ }
+ }
+
+ @Override
+ protected void xmlModelChanged(Document xmlDoc) {
+ Element rootElement = xmlDoc.getDocumentElement();
+ if (rootElement != null) {
+ mRootTag = rootElement.getTagName();
+ }
+
+ initUiRootNode(false /*force*/);
+
+ if (mRootTag != null
+ && !mRootTag.equals(mUiRootNode.getDescriptor().getXmlLocalName())) {
+ AndroidTargetData data = getTargetData();
+ if (data != null) {
+ ElementDescriptor descriptor =
+ data.getDrawableDescriptors().getElementDescriptor(mRootTag);
+ // Replace top level node now that we know the actual type
+
+ // Disconnect from old
+ mUiRootNode.setEditor(null);
+ mUiRootNode.setXmlDocument(null);
+
+ // Create new
+ mUiRootNode = descriptor.createUiNode();
+ mUiRootNode.setXmlDocument(xmlDoc);
+ mUiRootNode.setEditor(this);
+ }
+ }
+
+ if (mUiRootNode.getDescriptor() instanceof DocumentDescriptor) {
+ mUiRootNode.loadFromXmlNode(xmlDoc);
+ } else {
+ mUiRootNode.loadFromXmlNode(rootElement);
+ }
+
+ super.xmlModelChanged(xmlDoc);
+ }
+
+ @Override
+ protected void initUiRootNode(boolean force) {
+ // The manifest UI node is always created, even if there's no corresponding XML node.
+ if (mUiRootNode == null || force) {
+ ElementDescriptor descriptor;
+ boolean reload = false;
+ AndroidTargetData data = getTargetData();
+ if (data == null) {
+ descriptor = new DocumentDescriptor("temp", null /*children*/);
+ } else {
+ descriptor = data.getDrawableDescriptors().getElementDescriptor(mRootTag);
+ reload = true;
+ }
+ mUiRootNode = descriptor.createUiNode();
+ mUiRootNode.setEditor(this);
+
+ if (reload) {
+ onDescriptorsChanged();
+ }
+ }
+ }
+
+ private void onDescriptorsChanged() {
+ IStructuredModel model = getModelForRead();
+ if (model != null) {
+ try {
+ Node node = getXmlDocument(model).getDocumentElement();
+ mUiRootNode.reloadFromXmlNode(node);
+ } finally {
+ model.releaseFromRead();
+ }
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/drawable/DrawableSourceViewerConfig.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/drawable/DrawableSourceViewerConfig.java
new file mode 100644
index 000000000..eef6a9e93
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/drawable/DrawableSourceViewerConfig.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2007 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 com.android.ide.eclipse.adt.internal.editors.AndroidSourceViewerConfig;
+
+/**
+ * Source Viewer Configuration for drawable files
+ */
+public class DrawableSourceViewerConfig extends AndroidSourceViewerConfig {
+
+ public DrawableSourceViewerConfig() {
+ super(new DrawableContentAssist());
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestEditor.java
index d19c1e69a..38a5e6b19 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestEditor.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.adt.internal.editors.manifest;
-import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AdtConstants;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.AndroidManifestDescriptors;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/descriptors/AndroidManifestDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/descriptors/AndroidManifestDescriptors.java
index 7bc36921c..c07b7be57 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/descriptors/AndroidManifestDescriptors.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/descriptors/AndroidManifestDescriptors.java
@@ -434,7 +434,7 @@ public final class AndroidManifestDescriptors implements IDescriptorProvider {
* <p/>
* Capitalizes the first letter and replace non-alphabet by a space followed by a capital.
*/
- private String getUiName(String xmlName) {
+ private static String getUiName(String xmlName) {
StringBuilder sb = new StringBuilder();
boolean capitalize = true;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/resources/ResourcesContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/resources/ResourcesContentAssist.java
index 448c27024..166110085 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/resources/ResourcesContentAssist.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/resources/ResourcesContentAssist.java
@@ -30,6 +30,7 @@ import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescrip
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.uimodel.UiAttributeNode;
import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
@@ -106,6 +107,9 @@ public class ResourcesContentAssist extends AndroidContentAssist {
new HashMap<String, AttributeDescriptor>(180);
for (ElementDescriptor elementDesc : rootElementDescriptors) {
for (AttributeDescriptor desc : elementDesc.getAttributes()) {
+ if (desc instanceof SeparatorAttributeDescriptor) {
+ continue;
+ }
String name = desc.getXmlLocalName();
if (startsWith(name, attributePrefix)) {
matches.put(name, desc);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/resources/ResourcesEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/resources/ResourcesEditor.java
index 53ea51392..83e2d8c0d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/resources/ResourcesEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/resources/ResourcesEditor.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.adt.internal.editors.resources;
-import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AdtConstants;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.adt.internal.editors.resources.descriptors.ResourcesDescriptors;
@@ -38,7 +38,7 @@ import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
/**
- * Multi-page form editor for /res/values and /res/drawable XML files.
+ * Multi-page form editor for /res/values XML files.
*/
public class ResourcesEditor extends AndroidXmlEditor {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java
index c94b6c1fb..2b7f3465c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java
@@ -374,6 +374,8 @@ public class UiResourceAttributeNode extends UiTextAttributeNode {
type = "style"; //$NON-NLS-1$
} else if (attribute.equals(LayoutDescriptors.ATTR_LAYOUT)) {
type = "layout"; //$NON-NLS-1$
+ } else if (attribute.equals("drawable")) { //$NON-NLS-1$
+ type = "drawable"; //$NON-NLS-1$
}
if (type != null) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java
index 95e3f984a..69f1267b7 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java
@@ -21,7 +21,11 @@ import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.resources.ResourceRepository;
import com.android.ide.common.sdk.LoadStatus;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.editors.animator.AnimDescriptors;
+import com.android.ide.eclipse.adt.internal.editors.animator.AnimatorDescriptors;
+import com.android.ide.eclipse.adt.internal.editors.color.ColorDescriptors;
import com.android.ide.eclipse.adt.internal.editors.descriptors.IDescriptorProvider;
+import com.android.ide.eclipse.adt.internal.editors.drawable.DrawableDescriptors;
import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors;
import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.AndroidManifestDescriptors;
import com.android.ide.eclipse.adt.internal.editors.menu.descriptors.MenuDescriptors;
@@ -51,6 +55,10 @@ public class AndroidTargetData {
public final static int DESCRIPTOR_SEARCHABLE = 6;
public final static int DESCRIPTOR_PREFERENCES = 7;
public final static int DESCRIPTOR_APPWIDGET_PROVIDER = 8;
+ public final static int DESCRIPTOR_DRAWABLE = 9;
+ public final static int DESCRIPTOR_ANIMATOR = 10;
+ public final static int DESCRIPTOR_ANIM = 11;
+ public final static int DESCRIPTOR_COLOR = 12;
private final IAndroidTarget mTarget;
@@ -67,6 +75,10 @@ public class AndroidTargetData {
private Hashtable<String, String[]> mAttributeValues = new Hashtable<String, String[]>();
private AndroidManifestDescriptors mManifestDescriptors;
+ private DrawableDescriptors mDrawableDescriptors;
+ private AnimatorDescriptors mAnimatorDescriptors;
+ private AnimDescriptors mAnimDescriptors;
+ private ColorDescriptors mColorDescriptors;
private LayoutDescriptors mLayoutDescriptors;
private MenuDescriptors mMenuDescriptors;
private XmlDescriptors mXmlDescriptors;
@@ -84,14 +96,16 @@ public class AndroidTargetData {
/**
* Creates an AndroidTargetData object.
- * @param platformLibraries
- * @param optionalLibraries
*/
void setExtraData(
AndroidManifestDescriptors manifestDescriptors,
LayoutDescriptors layoutDescriptors,
MenuDescriptors menuDescriptors,
XmlDescriptors xmlDescriptors,
+ DrawableDescriptors drawableDescriptors,
+ AnimatorDescriptors animatorDescriptors,
+ AnimDescriptors animDescriptors,
+ ColorDescriptors colorDescriptors,
Map<String, Map<String, Integer>> enumValueMap,
String[] permissionValues,
String[] activityIntentActionValues,
@@ -104,6 +118,10 @@ public class AndroidTargetData {
LayoutLibrary layoutLibrary) {
mManifestDescriptors = manifestDescriptors;
+ mDrawableDescriptors = drawableDescriptors;
+ mAnimatorDescriptors = animatorDescriptors;
+ mAnimDescriptors = animDescriptors;
+ mColorDescriptors = colorDescriptors;
mLayoutDescriptors = layoutDescriptors;
mMenuDescriptors = menuDescriptors;
mXmlDescriptors = xmlDescriptors;
@@ -142,6 +160,14 @@ public class AndroidTargetData {
return mXmlDescriptors.getAppWidgetProvider();
case DESCRIPTOR_SEARCHABLE:
return mXmlDescriptors.getSearchableProvider();
+ case DESCRIPTOR_DRAWABLE:
+ return mDrawableDescriptors;
+ case DESCRIPTOR_ANIMATOR:
+ return mAnimatorDescriptors;
+ case DESCRIPTOR_ANIM:
+ return mAnimDescriptors;
+ case DESCRIPTOR_COLOR:
+ return mColorDescriptors;
default :
throw new IllegalArgumentException();
}
@@ -155,6 +181,34 @@ public class AndroidTargetData {
}
/**
+ * Returns the drawable descriptors
+ */
+ public DrawableDescriptors getDrawableDescriptors() {
+ return mDrawableDescriptors;
+ }
+
+ /**
+ * Returns the animation descriptors
+ */
+ public AnimDescriptors getAnimDescriptors() {
+ return mAnimDescriptors;
+ }
+
+ /**
+ * Returns the color descriptors
+ */
+ public ColorDescriptors getColorDescriptors() {
+ return mColorDescriptors;
+ }
+
+ /**
+ * Returns the animator descriptors
+ */
+ public AnimatorDescriptors getAnimatorDescriptors() {
+ return mAnimatorDescriptors;
+ }
+
+ /**
* Returns the layout Descriptors.
*/
public LayoutDescriptors getLayoutDescriptors() {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java
index 19562e176..19b2e3d0a 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java
@@ -22,6 +22,10 @@ import com.android.ide.common.resources.platform.AttrsXmlParser;
import com.android.ide.common.resources.platform.DeclareStyleableInfo;
import com.android.ide.common.resources.platform.ViewClassInfo;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.editors.animator.AnimDescriptors;
+import com.android.ide.eclipse.adt.internal.editors.animator.AnimatorDescriptors;
+import com.android.ide.eclipse.adt.internal.editors.color.ColorDescriptors;
+import com.android.ide.eclipse.adt.internal.editors.drawable.DrawableDescriptors;
import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors;
import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.AndroidManifestDescriptors;
import com.android.ide.eclipse.adt.internal.editors.menu.descriptors.MenuDescriptors;
@@ -83,7 +87,7 @@ public final class AndroidTargetParser {
try {
SubMonitor progress = SubMonitor.convert(monitor,
String.format("Parsing SDK %1$s", mAndroidTarget.getName()),
- 12);
+ 16);
AndroidTargetData targetData = new AndroidTargetData(mAndroidTarget);
@@ -218,6 +222,39 @@ public final class AndroidTargetParser {
preferenceGroupsInfo);
progress.worked(1);
+ if (progress.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+
+ DrawableDescriptors drawableDescriptors = new DrawableDescriptors();
+ Map<String, DeclareStyleableInfo> map = attrsXmlParser.getDeclareStyleableList();
+ drawableDescriptors.updateDescriptors(map);
+ progress.worked(1);
+
+ if (progress.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+
+ AnimatorDescriptors animatorDescriptors = new AnimatorDescriptors();
+ animatorDescriptors.updateDescriptors(map);
+ progress.worked(1);
+
+ if (progress.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+
+ AnimDescriptors animDescriptors = new AnimDescriptors();
+ animDescriptors.updateDescriptors(map);
+ progress.worked(1);
+
+ if (progress.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+
+ ColorDescriptors colorDescriptors = new ColorDescriptors();
+ colorDescriptors.updateDescriptors(map);
+ progress.worked(1);
+
// load the framework resources.
ResourceRepository frameworkResources =
ResourceManager.getInstance().loadFrameworkResources(mAndroidTarget);
@@ -236,6 +273,10 @@ public final class AndroidTargetParser {
layoutDescriptors,
menuDescriptors,
xmlDescriptors,
+ drawableDescriptors,
+ animatorDescriptors,
+ animDescriptors,
+ colorDescriptors,
enumValueMap,
permissionValues,
activity_actions.toArray(new String[activity_actions.size()]),
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/NewXmlFileCreationPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/NewXmlFileCreationPage.java
index 583202ace..c4f86a657 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/NewXmlFileCreationPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/NewXmlFileCreationPage.java
@@ -27,6 +27,7 @@ import com.android.ide.common.resources.configuration.FolderConfiguration;
import com.android.ide.common.resources.configuration.ResourceQualifier;
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
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;
@@ -72,6 +73,11 @@ import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.FileEditorInput;
import java.util.ArrayList;
import java.util.Collections;
@@ -287,6 +293,15 @@ class NewXmlFileCreationPage extends WizardPage {
null, // default attributes
1 // target API level
),
+ new TypeInfo("Drawable", // UI name
+ "An XML file that describes a drawable.", // tooltip
+ ResourceFolderType.DRAWABLE, // folder type
+ AndroidTargetData.DESCRIPTOR_DRAWABLE, // root seed
+ null, // default root
+ SdkConstants.NS_RESOURCES, // xmlns
+ null, // default attributes
+ 1 // target API level
+ ),
new TypeInfo("Menu", // UI name
"An XML file that describes an menu.", // tooltip
ResourceFolderType.MENU, // folder type
@@ -296,6 +311,33 @@ class NewXmlFileCreationPage extends WizardPage {
null, // default attributes
1 // target API level
),
+ new TypeInfo("Color List", // UI name
+ "An XML file that describes a color state list.", // tooltip
+ ResourceFolderType.COLOR, // folder type
+ AndroidTargetData.DESCRIPTOR_COLOR, // root seed
+ null, // default root
+ SdkConstants.NS_RESOURCES, // xmlns
+ null, // default attributes
+ 1 // target API level
+ ),
+ new TypeInfo("Animator", // UI name
+ "An XML file that describes an animator.", // tooltip
+ ResourceFolderType.ANIMATOR, // folder type
+ AndroidTargetData.DESCRIPTOR_ANIMATOR, // root seed
+ "set", // default root
+ SdkConstants.NS_RESOURCES, // xmlns
+ null, // default attributes
+ 11 // target API level
+ ),
+ new TypeInfo("Animation", // UI name
+ "An XML file that describes an animation.", // tooltip
+ ResourceFolderType.ANIM, // folder type
+ AndroidTargetData.DESCRIPTOR_ANIM, // root seed
+ "set", // default root
+ null, // xmlns
+ null, // default attributes
+ 1 // target API level
+ ),
new TypeInfo("AppWidget Provider", // UI name
"An XML file that describes a widget provider.", // tooltip
ResourceFolderType.XML, // folder type
@@ -323,22 +365,6 @@ class NewXmlFileCreationPage extends WizardPage {
null, // default attributes
1 // target API level
),
- new TypeInfo("Animation", // UI name
- "An XML file that describes an animation.", // tooltip
- ResourceFolderType.ANIM, // folder type
- // TODO reuse constants if we ever make an editor with descriptors for animations
- new String[] { // root seed
- "set", //$NON-NLS-1$
- "alpha", //$NON-NLS-1$
- "scale", //$NON-NLS-1$
- "translate", //$NON-NLS-1$
- "rotate" //$NON-NLS-1$
- },
- "set", //$NON-NLS-1$ // default root
- null, // xmlns
- null, // default attributes
- 1 // target API level
- ),
};
/** Number of columns in the grid layout */
@@ -675,7 +701,7 @@ class NewXmlFileCreationPage extends WizardPage {
};
int n = sTypes.length;
- int num_lines = (n + NUM_COL/2) / NUM_COL;
+ int num_lines = (n + (NUM_COL - 1)) / NUM_COL;
for (int line = 0, k = 0; line < num_lines; line++) {
for (int i = 0; i < NUM_COL; i++, k++) {
if (k < n) {
@@ -837,6 +863,25 @@ class NewXmlFileCreationPage extends WizardPage {
}
if (targetProject == null) {
+ // Try to figure out the project from the active editor
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window != null) {
+ IWorkbenchPage page = window.getActivePage();
+ if (page != null) {
+ IEditorPart activeEditor = page.getActiveEditor();
+ if (activeEditor instanceof AndroidXmlEditor) {
+ Object input = ((AndroidXmlEditor) activeEditor).getEditorInput();
+ if (input instanceof FileEditorInput) {
+ FileEditorInput fileInput = (FileEditorInput) input;
+ targetScore = 1;
+ targetProject = fileInput.getFile().getProject();
+ }
+ }
+ }
+ }
+ }
+
+ if (targetProject == null) {
// If we didn't find a default project based on the selection, check how many
// open Android projects we can find in the current workspace. If there's only
// one, we'll just select it by default.
@@ -1073,19 +1118,6 @@ class NewXmlFileCreationPage extends WizardPage {
}
}
- // For now, treat a selection of /res/animator as /res/anim/,
- // though we need to handle this better
- // TODO: Properly support ANIMATOR templates!
- if (!selected && folderName.equals(AndroidConstants.FD_RES_ANIMATOR)) {
- for (TypeInfo type : sTypes) {
- if (type.getResFolderType() == ResourceFolderType.ANIM) {
- matches.add(type);
- selected |= type.getWidget().getSelection();
- break;
- }
- }
- }
-
if (matches.size() == 1) {
// If there's only one match, select it if it's not already selected
if (!selected) {