aboutsummaryrefslogtreecommitdiff
path: root/eclipse
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse')
-rw-r--r--eclipse/dictionary.txt12
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml36
-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
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/build/AaptQuickFixTest.java104
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java130
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/AdtProjectTest.java15
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion53.txt6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion54.txt6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion55.txt16
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion56.txt14
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion57.txt3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1.xml20
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion58.txt4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion59.txt10
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion60.txt3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion61.txt18
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1.xml27
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/color1-expected-completion45.txt2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/color1-expected-completion46a.txt2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/color1-expected-completion46b.txt16
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/color1.xml6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion47.txt13
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion48.txt3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion49.txt7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion50.txt13
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1.xml5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable2-expected-completion51.txt10
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable2-expected-completion52.txt7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable2.xml5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/quickfix2-expected-quickFix4.xml3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/quickfix2.xml5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/SdkTestCase.java7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceHelperTest.java1
58 files changed, 2340 insertions, 57 deletions
diff --git a/eclipse/dictionary.txt b/eclipse/dictionary.txt
index 3369ca1ad..9291f472f 100644
--- a/eclipse/dictionary.txt
+++ b/eclipse/dictionary.txt
@@ -17,6 +17,7 @@ app
apps
arg
async
+attr
attrs
avd
avds
@@ -64,8 +65,10 @@ dex
dexified
diff
diffs
+dir
dirs
ditto
+docs
dpi
drawable
drawables
@@ -81,6 +84,7 @@ foreach
fqcn
framelayout
gen
+git
groovy
guava
hardcoded
@@ -101,6 +105,8 @@ inline
instanceof
instantiatable
int
+interpolator
+interpolators
iterable
javac
javadoc
@@ -124,6 +130,7 @@ malformed
marquee
metadata
min
+mipmap
monte
ms
msg
@@ -148,6 +155,7 @@ precompiler
pref
prefs
preload
+preloaded
preloads
primordial
printf
@@ -156,12 +164,14 @@ programmatically
proguard
proxies
proxy
+quickfix
recompilation
rect
redo
refactor
refactoring
regexp
+regexps
registry
reindent
remap
@@ -192,6 +202,8 @@ stderr
stdout
stretchiness
struct
+styleable
+styleables
subclassing
submenu
supertype
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
index 36d9c7125..a16a76650 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
@@ -533,6 +533,30 @@
name="Android Xml Resources Editor">
</editor>
<editor
+ class="com.android.ide.eclipse.adt.internal.editors.animator.AnimationEditor"
+ default="false"
+ extensions="xml"
+ icon="icons/android_file.png"
+ id="com.android.ide.eclipse.editors.animator.AnimationEditor"
+ name="Android Animation Editor">
+ </editor>
+ <editor
+ class="com.android.ide.eclipse.adt.internal.editors.drawable.DrawableEditor"
+ default="false"
+ extensions="xml"
+ icon="icons/android_file.png"
+ id="com.android.ide.eclipse.editors.drawable.DrawableEditor"
+ name="Android Drawable Editor">
+ </editor>
+ <editor
+ class="com.android.ide.eclipse.adt.internal.editors.color.ColorEditor"
+ default="false"
+ extensions="xml"
+ icon="icons/android_file.png"
+ id="com.android.ide.eclipse.editors.color.ColorEditor"
+ name="Android Color Editor">
+ </editor>
+ <editor
class="com.android.ide.eclipse.adt.internal.editors.binaryxml.BinaryXMLMultiPageEditorPart"
contributorClass="org.eclipse.wst.xml.ui.internal.tabletree.XMLMultiPageEditorActionBarContributor"
icon="$nl$/icons/android_file.png"
@@ -577,6 +601,18 @@
class="com.android.ide.eclipse.adt.internal.editors.xml.XmlSourceViewerConfig"
target="com.android.ide.eclipse.editors.xml.XmlEditor">
</sourceViewerConfiguration>
+ <sourceViewerConfiguration
+ class="com.android.ide.eclipse.adt.internal.editors.animator.AnimationSourceViewerConfig"
+ target="com.android.ide.eclipse.editors.animator.AnimationEditor">
+ </sourceViewerConfiguration>
+ <sourceViewerConfiguration
+ class="com.android.ide.eclipse.adt.internal.editors.drawable.DrawableSourceViewerConfig"
+ target="com.android.ide.eclipse.editors.drawable.DrawableEditor">
+ </sourceViewerConfiguration>
+ <sourceViewerConfiguration
+ class="com.android.ide.eclipse.adt.internal.editors.color.ColorSourceViewerConfig"
+ target="com.android.ide.eclipse.editors.color.ColorEditor">
+ </sourceViewerConfiguration>
<provisionalConfiguration
type="org.eclipse.jface.text.quickassist.IQuickAssistProcessor"
class="com.android.ide.eclipse.adt.internal.build.AaptQuickFix"
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) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/build/AaptQuickFixTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/build/AaptQuickFixTest.java
index 07c0fe1bc..78f16a21a 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/build/AaptQuickFixTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/build/AaptQuickFixTest.java
@@ -16,6 +16,7 @@
package com.android.ide.eclipse.adt.internal.build;
+import static com.android.AndroidConstants.FD_RES_COLOR;
import static com.android.AndroidConstants.FD_RES_LAYOUT;
import static com.android.sdklib.SdkConstants.FD_RES;
@@ -58,22 +59,28 @@ public class AaptQuickFixTest extends AdtProjectTest {
public void testQuickFix1() throws Exception {
// Test adding a value into an existing file (res/values/strings.xml)
- checkFixes("quickfix1.xml", "android:text=\"@string/firs^tstring\"",
+ checkResourceFix("quickfix1.xml", "android:text=\"@string/firs^tstring\"",
"res/values/strings.xml");
}
public void testQuickFix2() throws Exception {
// Test adding a value into a new file (res/values/dimens.xml, will be created)
- checkFixes("quickfix1.xml", "android:layout_width=\"@dimen/^testdimen\"",
+ checkResourceFix("quickfix1.xml", "android:layout_width=\"@dimen/^testdimen\"",
"res/values/dimens.xml");
}
public void testQuickFix3() throws Exception {
// Test adding a file based resource (uses new file wizard machinery)
- checkFixes("quickfix1.xml", "layout=\"@layout/^testlayout\"", "res/layout/testlayout.xml");
+ checkResourceFix("quickfix1.xml", "layout=\"@layout/^testlayout\"",
+ "res/layout/testlayout.xml");
}
- private void checkFixes(String name, String caretLocation, String expectedNewPath)
+ public void testQuickFix4() throws Exception {
+ // Test adding a value into a new file (res/values/dimens.xml, will be created)
+ checkNamespaceFix("quickfix2.xml", "<c^olor");
+ }
+
+ private void checkResourceFix(String name, String caretLocation, String expectedNewPath)
throws Exception {
IProject project = getProject();
IFile file = getTestDataFile(project, name, FD_RES + "/" + FD_RES_LAYOUT + "/" + name);
@@ -82,6 +89,10 @@ public class AaptQuickFixTest extends AdtProjectTest {
final int offset = getCaretOffset(file, caretLocation);
+ String osRoot = project.getLocation().toOSString();
+ List<String> errors = new ArrayList<String>();
+ String fileRelativePath = file.getProjectRelativePath().toPortableString();
+ String filePath = osRoot + File.separator + fileRelativePath;
// Run AaptParser such that markers are added...
// When debugging these tests, the project gets a chance to build itself so
// the real aapt errors are there. But when the test is run directly, aapt has
@@ -90,10 +101,6 @@ public class AaptQuickFixTest extends AdtProjectTest {
// etc) so instead this test just hardcodes the aapt errors that should be
// observed on quickfix1.xml.
assertEquals("Unit test is hardcoded to errors for quickfix1.xml", "quickfix1.xml", name);
- String osRoot = project.getLocation().toOSString();
- List<String> errors = new ArrayList<String>();
- String fileRelativePath = file.getProjectRelativePath().toPortableString();
- String filePath = osRoot + File.separator + fileRelativePath;
errors.add(filePath + ":7: error: Error: No resource found that matches the given name"
+ " (at 'text' with value '@string/firststring').");
errors.add(filePath + ":7: error: Error: No resource found that matches the given name"
@@ -192,4 +199,85 @@ public class AaptQuickFixTest extends AdtProjectTest {
assertEqualsGolden(name, newFileWithCaret);
}
+
+ private void checkNamespaceFix(String name, String caretLocation)
+ throws Exception {
+ IProject project = getProject();
+ IFile file = getTestDataFile(project, name, FD_RES + "/" + FD_RES_COLOR + "/" + name);
+
+ // Determine the offset
+ final int offset = getCaretOffset(file, caretLocation);
+
+ String osRoot = project.getLocation().toOSString();
+ List<String> errors = new ArrayList<String>();
+ String fileRelativePath = file.getProjectRelativePath().toPortableString();
+ String filePath = osRoot + File.separator + fileRelativePath;
+ assertEquals("Unit test is hardcoded to errors for quickfix2.xml", "quickfix2.xml", name);
+ errors.add(filePath + ":5: error: Error parsing XML: unbound prefix");
+ AaptParser.parseOutput(errors, project);
+
+ AaptQuickFix aaptQuickFix = new AaptQuickFix();
+
+ // Open file
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ assertNotNull(page);
+ IEditorPart editor = IDE.openEditor(page, file);
+ assertTrue(editor instanceof AndroidXmlEditor);
+ AndroidXmlEditor layoutEditor = (AndroidXmlEditor) editor;
+ final ISourceViewer viewer = layoutEditor.getStructuredSourceViewer();
+
+ // Test marker resolution.
+ IMarker[] markers = file.findMarkers(AdtConstants.MARKER_AAPT_COMPILE, true,
+ IResource.DEPTH_ZERO);
+ assertEquals(1, markers.length);
+ IMarker marker = markers[0];
+ // Found the target marker. Now check the marker resolution of it.
+ assertTrue(aaptQuickFix.hasResolutions(marker));
+ IMarkerResolution[] resolutions = aaptQuickFix.getResolutions(marker);
+ assertNotNull(resolutions);
+ assertEquals(1, resolutions.length);
+ IMarkerResolution resolution = resolutions[0];
+ assertNotNull(resolution);
+ assertTrue(resolution.getLabel().contains("Insert namespace"));
+
+ // Next test quick assist.
+
+ IQuickAssistInvocationContext invocationContext = new IQuickAssistInvocationContext() {
+ public int getLength() {
+ return 0;
+ }
+
+ public int getOffset() {
+ return offset;
+ }
+
+ public ISourceViewer getSourceViewer() {
+ return viewer;
+ }
+ };
+ ICompletionProposal[] proposals = aaptQuickFix
+ .computeQuickAssistProposals(invocationContext);
+ assertNotNull(proposals);
+ assertTrue(proposals.length == 1);
+ ICompletionProposal proposal = proposals[0];
+
+ assertNotNull(proposal.getAdditionalProposalInfo());
+ assertNotNull(proposal.getImage());
+ assertTrue(proposal.getDisplayString().contains("Insert namespace"));
+
+ // Open the file to ensure we can get an XML model with getExistingModelForEdit:
+ AdtPlugin.openFile(file, null);
+ IEditorPart newEditor = Hyperlinks.getEditor();
+ assertTrue(newEditor instanceof AndroidXmlEditor);
+
+ AndroidXmlEditor xmlEditor = (AndroidXmlEditor) newEditor;
+ IDocument document = xmlEditor.getStructuredSourceViewer().getDocument();
+
+ // Apply quick fix
+ String before = document.get();
+ proposal.apply(document);
+ String after = document.get();
+ String diff = getDiff(before, after);
+ assertEqualsGolden(name, diff);
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java
index 6cff2f294..c7a452e40 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java
@@ -16,7 +16,16 @@
*/
package com.android.ide.eclipse.adt.internal.editors;
+import static com.android.AndroidConstants.FD_RES_ANIM;
+import static com.android.AndroidConstants.FD_RES_ANIMATOR;
+import static com.android.AndroidConstants.FD_RES_COLOR;
+import static com.android.AndroidConstants.FD_RES_DRAWABLE;
+import static com.android.sdklib.SdkConstants.FD_RES;
+
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.editors.animator.AnimationContentAssist;
+import com.android.ide.eclipse.adt.internal.editors.color.ColorContentAssist;
+import com.android.ide.eclipse.adt.internal.editors.drawable.DrawableContentAssist;
import com.android.ide.eclipse.adt.internal.editors.layout.LayoutContentAssist;
import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.AdtProjectTest;
import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestContentAssist;
@@ -316,8 +325,101 @@ public class AndroidContentAssistTest extends AdtProjectTest {
checkLayoutCompletion("completion8.xml", "android:layo^ut_width=\"fill_parent\"");
}
+ public void testCompletion45() throws Exception {
+ // Test top level elements in colors
+ checkColorCompletion("color1.xml", "^<selector");
+ }
+
+ public void testCompletion46a() throws Exception {
+ // Test children of selector: should offer item
+ checkColorCompletion("color1.xml", "^<item android");
+ }
+
+ public void testCompletion46b() throws Exception {
+ // Test attribute matching in color files
+ checkColorCompletion("color1.xml", "<item ^android:state_focused=\"true\"/>");
+ }
+
+ public void testCompletion47() throws Exception {
+ // Check root completion in drawables: should list all drawable root elements
+ checkDrawableCompletion("drawable1.xml", "^<layer-list");
+ }
+
+ public void testCompletion48() throws Exception {
+ // Check attributes of the layer list
+ checkDrawableCompletion("drawable1.xml", "^xmlns:android");
+ }
+
+ public void testCompletion49() throws Exception {
+ // Check attributes of the <item> element inside a <layer-list>
+ checkDrawableCompletion("drawable1.xml", "<item ^></item>");
+ }
+
+ public void testCompletion50() throws Exception {
+ // Check elements nested inside the <item> in a layer list: can use any drawable again
+ checkDrawableCompletion("drawable1.xml", "<item >^</item>");
+ }
+
+ public void testCompletion51() throws Exception {
+ // Check attributes of <shape> element
+ checkDrawableCompletion("drawable2.xml", "^android:innerRadiusRatio=\"2\"");
+ }
+
+ public void testCompletion52() throws Exception {
+ // Check list of available elements inside a shape
+ checkDrawableCompletion("drawable2.xml", "^<gradient");
+ }
+
+ public void testCompletion53() throws Exception {
+ // Check list of root anim elements
+ checkAnimCompletion("anim1.xml", "^<set xmlns");
+ }
+
+ public void testCompletion54() throws Exception {
+ // Check that we can nest inside <set>'s
+ checkAnimCompletion("anim1.xml", "^<translate android:id=");
+ }
+
+ public void testCompletion55() throws Exception {
+ // translate properties
+ checkAnimCompletion("anim1.xml", "android:^fromXDelta=");
+ }
+
+ public void testCompletion56() throws Exception {
+ // alpha properties
+ checkAnimCompletion("anim1.xml", "android:^fromAlpha=");
+ }
+
+ public void testCompletion57() throws Exception {
+ // Fractional properties
+ checkAnimCompletion("anim1.xml", "android:fromXDelta=\"100^%p\"");
+ }
+
+ public void testCompletion58() throws Exception {
+ // Top level animator elements
+ checkAnimatorCompletion("animator1.xml", "^<set xmlns");
+ }
+
+ public void testCompletion59() throws Exception {
+ // objectAnimator properties
+ checkAnimatorCompletion("animator1.xml", "android:^duration=\"2000\"");
+ }
+
+ public void testCompletion60() throws Exception {
+ // propertyName completion
+ checkAnimatorCompletion("animator1.xml", "android:propertyName=\"scal^eX\"/>");
+ }
+
+ public void testCompletion61() throws Exception {
+ // Interpolator completion
+ checkAnimatorCompletion("animator1.xml",
+ "android:interpolator=\"^@android:anim/bounce_interpolator\"");
+ }
+
// ---- Test *applying* code completion ----
+
+
// The following tests check -applying- a specific code completion
// match - this verifies that the document is updated correctly, the
// caret is moved appropriately, etc.
@@ -593,6 +695,34 @@ public class AndroidContentAssistTest extends AdtProjectTest {
new LayoutContentAssist());
}
+ private void checkColorCompletion(String name, String caretLocation) throws Exception {
+ IFile file = getTestDataFile(getProject(), name,
+ FD_RES + "/" + FD_RES_COLOR + "/" + name);
+ checkCompletion(name, file, caretLocation,
+ new ColorContentAssist());
+ }
+ private void checkAnimCompletion(String name, String caretLocation) throws Exception {
+ IFile file = getTestDataFile(getProject(), name,
+ FD_RES + "/" + FD_RES_ANIM + "/" + name);
+ checkCompletion(name, file, caretLocation,
+ new AnimationContentAssist());
+ }
+
+ private void checkAnimatorCompletion(String name, String caretLocation) throws Exception {
+ IFile file = getTestDataFile(getProject(), name,
+ FD_RES + "/" + FD_RES_ANIMATOR + "/" + name);
+ checkCompletion(name, file, caretLocation,
+ new AnimationContentAssist());
+ }
+
+
+ private void checkDrawableCompletion(String name, String caretLocation) throws Exception {
+ IFile file = getTestDataFile(getProject(), name,
+ FD_RES + "/" + FD_RES_DRAWABLE + "/" + name);
+ checkCompletion(name, file, caretLocation,
+ new DrawableContentAssist());
+ }
+
private void checkManifestCompletion(String name, String caretLocation) throws Exception {
// Manifest files must be named AndroidManifest.xml. Must overwrite to replace
// the default manifest created in the test project.
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/AdtProjectTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/AdtProjectTest.java
index ead55f91d..3b83bd793 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/AdtProjectTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/AdtProjectTest.java
@@ -66,6 +66,7 @@ import java.util.Map;
@SuppressWarnings("restriction")
public class AdtProjectTest extends SdkTestCase {
+ private static final int TARGET_API_LEVEL = 11;
/** Update golden files if different from the actual results */
private static final boolean UPDATE_DIFFERENT_FILES = false;
/** Create golden files if missing */
@@ -112,6 +113,16 @@ public class AdtProjectTest extends SdkTestCase {
return false;
}
+ @Override
+ protected boolean validateSdk(IAndroidTarget target) {
+ // Not quite working yet. When enabled will make tests run faster.
+ //if (target.getVersion().getApiLevel() < TARGET_API_LEVEL) {
+ // return false;
+ //}
+
+ return true;
+ }
+
/** Returns a name to use for the project used in this test. Subclasses do not need to
* override this if they can share a project with others - which is the case if they do
* not modify the project in a way that does not affect other tests. For example
@@ -207,7 +218,7 @@ public class AdtProjectTest extends SdkTestCase {
IAndroidTarget[] targets = getSdk().getTargets();
for (IAndroidTarget t : targets) {
- if (t.getVersion().getApiLevel() >= 11) {
+ if (t.getVersion().getApiLevel() >= TARGET_API_LEVEL) {
target = t;
break;
}
@@ -232,7 +243,7 @@ public class AdtProjectTest extends SdkTestCase {
IAndroidTarget[] targets = getSdk().getTargets();
for (IAndroidTarget t : targets) {
- if (t.getVersion().getApiLevel() >= 11) {
+ if (t.getVersion().getApiLevel() >= TARGET_API_LEVEL) {
target = t;
break;
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion53.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion53.txt
new file mode 100644
index 000000000..3e44918d9
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion53.txt
@@ -0,0 +1,6 @@
+Code completion in anim1.xml for ^<set xmlns:
+<alpha />
+<rotate />
+<scale />
+<set ></set>
+<translate />
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion54.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion54.txt
new file mode 100644
index 000000000..f5e5cba69
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion54.txt
@@ -0,0 +1,6 @@
+Code completion in anim1.xml for ^<translate android:id=:
+<alpha />
+<rotate />
+<scale />
+<set ></set>
+<translate />
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion55.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion55.txt
new file mode 100644
index 000000000..28b15d3c7
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion55.txt
@@ -0,0 +1,16 @@
+Code completion in anim1.xml for android:^fromXDelta=:
+android:fromXDelta : [float, fraction]
+android:toXDelta : [float, fraction]
+android:fromYDelta : [float, fraction]
+android:toYDelta : [float, fraction]
+android:interpolator : Defines the interpolator used to smooth the animation movement in time. [reference]
+android:fillEnabled : When set to true, fillAfter is taken into account. [boolean]
+android:fillBefore : When set to true, the animation transformation is applied before the animation has started. [boolean]
+android:fillAfter : When set to true, the animation transformation is applied after the animation is over. [boolean]
+android:duration : Amount of time (in milliseconds) for the animation to run. [integer]
+android:startOffset : Delay in milliseconds before the animation runs, once start time is reached. [integer]
+android:repeatCount : Defines how many times the animation should repeat. [integer, enum]
+android:repeatMode : Defines the animation behavior when it reaches the end and the repeat count is greater than 0 or infinite. [enum]
+android:zAdjustment : Allows for an adjustment of the Z ordering of the content being animated for the duration of the animation. [enum]
+android:background : Special background behind animation. [reference, color]
+android:detachWallpaper : Special option for window animations: if this window is on top of a wallpaper, don't animate the wallpaper with it. [boolean]
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion56.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion56.txt
new file mode 100644
index 000000000..632a9c549
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion56.txt
@@ -0,0 +1,14 @@
+Code completion in anim1.xml for android:^fromAlpha=:
+android:fromAlpha : [float]
+android:toAlpha : [float]
+android:interpolator : Defines the interpolator used to smooth the animation movement in time. [reference]
+android:fillEnabled : When set to true, fillAfter is taken into account. [boolean]
+android:fillBefore : When set to true, the animation transformation is applied before the animation has started. [boolean]
+android:fillAfter : When set to true, the animation transformation is applied after the animation is over. [boolean]
+android:duration : Amount of time (in milliseconds) for the animation to run. [integer]
+android:startOffset : Delay in milliseconds before the animation runs, once start time is reached. [integer]
+android:repeatCount : Defines how many times the animation should repeat. [integer, enum]
+android:repeatMode : Defines the animation behavior when it reaches the end and the repeat count is greater than 0 or infinite. [enum]
+android:zAdjustment : Allows for an adjustment of the Z ordering of the content being animated for the duration of the animation. [enum]
+android:background : Special background behind animation. [reference, color]
+android:detachWallpaper : Special option for window animations: if this window is on top of a wallpaper, don't animate the wallpaper with it. [boolean]
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion57.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion57.txt
new file mode 100644
index 000000000..9225dac46
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion57.txt
@@ -0,0 +1,3 @@
+Code completion in anim1.xml for android:fromXDelta="100^%p":
+100% : <b>Fraction</b> - a percentage of the base size
+100%p : <b>Fraction</b> - a percentage relative to parent container
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1.xml
new file mode 100644
index 000000000..48fefc2ba
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1.xml
@@ -0,0 +1,20 @@
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <translate android:id="@+id/test1"
+ android:fromXDelta="100%p"
+ android:pivotY="60%p"
+ android:toXDelta="40%p"
+ android:toYDelta="33%p"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:startOffset="1000"
+ android:duration="1000" />
+ <alpha
+ android:id="@+id/test2"
+ android:fromAlpha="1.0"
+ android:toAlpha="0.0"
+ android:startOffset="3000"
+ android:duration="250"
+ android:fillBefore="true"
+ android:fillAfter="false"
+ />
+</set>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion58.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion58.txt
new file mode 100644
index 000000000..075941502
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion58.txt
@@ -0,0 +1,4 @@
+Code completion in animator1.xml for ^<set xmlns:
+<animator ></animator>
+<objectAnimator ></objectAnimator>
+<set ></set>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion59.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion59.txt
new file mode 100644
index 000000000..070271268
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion59.txt
@@ -0,0 +1,10 @@
+Code completion in animator1.xml for android:^duration="2000":
+android:propertyName : Name of the property being animated. [string]
+android:interpolator : Defines the interpolator used to smooth the animation movement in time. [reference]
+android:duration : Amount of time (in milliseconds) for the animation to run. [integer]
+android:startOffset : Delay in milliseconds before the animation runs, once start time is reached. [integer]
+android:repeatCount : Defines how many times the animation should repeat. [integer, enum]
+android:repeatMode : Defines the animation behavior when it reaches the end and the repeat count is greater than 0 or infinite. [enum]
+android:valueFrom : Value the animation starts from. [integer, float, color, dimension]
+android:valueTo : Value the animation animates to. [integer, float, color, dimension]
+android:valueType : The type of valueFrom and valueTo. [enum]
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion60.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion60.txt
new file mode 100644
index 000000000..3e5e6b127
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion60.txt
@@ -0,0 +1,3 @@
+Code completion in animator1.xml for android:propertyName="scal^eX"/>:
+scaleX : scale of the view in the x direction.
+scaleY : scale of the view in the y direction.
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion61.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion61.txt
new file mode 100644
index 000000000..d4618c2cc
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion61.txt
@@ -0,0 +1,18 @@
+Code completion in animator1.xml for android:interpolator="^@android:anim/bounce_interpolator":
+@android:anim/accelerate_decelerate_interpolator
+@android:anim/accelerate_interpolator
+@android:anim/decelerate_interpolator
+@android:anim/anticipate_interpolator
+@android:anim/overshoot_interpolator
+@android:anim/anticipate_overshoot_interpolator
+@android:anim/bounce_interpolator
+@android:anim/linear_interpolator
+@android:anim/cycle_interpolator
+@android:
+@anim/
+@animator/
+@color/
+@drawable/
+@layout/
+@string/
+@style/
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1.xml
new file mode 100644
index 000000000..bdf10dced
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1.xml
@@ -0,0 +1,27 @@
+<!-- Simple bounce animation -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:ordering="sequentially">
+ <set>
+ <objectAnimator
+ android:duration="2000"
+ android:valueTo="310"
+ android:propertyName="x"/>
+ <objectAnimator
+ android:duration="2000"
+ android:valueTo="130"
+ android:propertyName="y"
+ android:interpolator="@android:anim/bounce_interpolator"/>
+ <objectAnimator
+ android:duration="2000"
+ android:valueTo=".4"
+ android:propertyName="scaleX"/>
+ <objectAnimator
+ android:duration="2000"
+ android:valueTo=".4"
+ android:propertyName="scaleY"/>
+ </set>
+ <objectAnimator
+ android:duration="500"
+ android:valueTo="0"
+ android:propertyName="alpha"/>
+</set>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/color1-expected-completion45.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/color1-expected-completion45.txt
new file mode 100644
index 000000000..c799b8094
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/color1-expected-completion45.txt
@@ -0,0 +1,2 @@
+Code completion in color1.xml for ^<selector:
+<selector ></selector> : Required. This must be the root element. Contains one or more <item> elements.
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/color1-expected-completion46a.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/color1-expected-completion46a.txt
new file mode 100644
index 000000000..32f0066b6
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/color1-expected-completion46a.txt
@@ -0,0 +1,2 @@
+Code completion in color1.xml for ^<item android:
+<item /> : Drawable states.
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/color1-expected-completion46b.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/color1-expected-completion46b.txt
new file mode 100644
index 000000000..7fcc5a923
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/color1-expected-completion46b.txt
@@ -0,0 +1,16 @@
+Code completion in color1.xml for <item ^android:state_focused="true"/>:
+android:state_focused : State value for StateListDrawable, set when a view has input focus. [boolean]
+android:state_window_focused : State value for StateListDrawable, set when a view's window has input focus. [boolean]
+android:state_enabled : State value for StateListDrawable, set when a view is enabled. [boolean]
+android:state_checkable : State identifier indicating that the object <var>may</var> display a check mark. [boolean]
+android:state_checked : State identifier indicating that the object is currently checked. [boolean]
+android:state_selected : State value for StateListDrawable, set when a view (or one of its parents) is currently selected. [boolean]
+android:state_pressed : State value for StateListDrawable, set when the user is pressing down in a view. [boolean]
+android:state_activated : State value for StateListDrawable, set when a view or its parent has been "activated" meaning the user has currently marked it as being of interest. [boolean]
+android:state_active : State value for StateListDrawable. [boolean]
+android:state_single : State value for StateListDrawable. [boolean]
+android:state_first : State value for StateListDrawable. [boolean]
+android:state_middle : State value for StateListDrawable. [boolean]
+android:state_last : State value for StateListDrawable. [boolean]
+android:state_accelerated : State value for StateListDrawable, indicating that the Drawable is in a view that is hardware accelerated. [boolean]
+android:color : Hexadeximal color. Required. The color is specified with an RGB value and optional alpha channel. The value always begins with a pound (#) character and then followed by the Alpha-Red-Green-Blue information in one of the following formats: * RGB * ARGB * RRGGBB * AARRGGBB
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/color1.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/color1.xml
new file mode 100644
index 000000000..a8482abac
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/color1.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true"/>
+ <item />
+</selector>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion47.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion47.txt
new file mode 100644
index 000000000..edf4892fa
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion47.txt
@@ -0,0 +1,13 @@
+Code completion in drawable1.xml for ^<layer-list:
+<animated-rotate />
+<animation-list /> : Drawable used to render several animated frames.
+<bitmap /> : Drawable used to draw bitmaps.
+<clip />
+<color /> : Drawable used to draw a single color.
+<inset />
+<layer-list ></layer-list> : Drawable used to render several drawables stacked on top of each other.
+<nine-patch /> : Drawable used to draw 9-patches.
+<rotate /> : Drawable used to rotate another drawable.
+<scale />
+<selector ></selector> : Drawable used to render several states.
+<shape ></shape> : Drawable used to render a geometric shape, with a gradient or a solid color.
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion48.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion48.txt
new file mode 100644
index 000000000..f98bb4c20
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion48.txt
@@ -0,0 +1,3 @@
+Code completion in drawable1.xml for ^xmlns:android:
+android:opacity : Indicates the opacity of the layer. [enum]
+xmlns:android
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion49.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion49.txt
new file mode 100644
index 000000000..4d3dfe370
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion49.txt
@@ -0,0 +1,7 @@
+Code completion in drawable1.xml for <item ^></item>:
+android:left : Left coordinate of the layer. [dimension]
+android:top : Top coordinate of the layer. [dimension]
+android:right : Right coordinate of the layer. [dimension]
+android:bottom : Bottom coordinate of the layer. [dimension]
+android:drawable : Drawable used to render the layer. [reference]
+android:id : Identifier of the layer. [reference]
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion50.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion50.txt
new file mode 100644
index 000000000..90eab1089
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion50.txt
@@ -0,0 +1,13 @@
+Code completion in drawable1.xml for <item >^</item>:
+<animated-rotate />
+<animation-list /> : Drawable used to render several animated frames.
+<bitmap /> : Drawable used to draw bitmaps.
+<clip />
+<color /> : Drawable used to draw a single color.
+<inset />
+<layer-list ></layer-list> : Drawable used to render several drawables stacked on top of each other.
+<nine-patch /> : Drawable used to draw 9-patches.
+<rotate /> : Drawable used to rotate another drawable.
+<scale />
+<selector ></selector> : Drawable used to render several states.
+<shape ></shape> : Drawable used to render a geometric shape, with a gradient or a solid color.
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1.xml
new file mode 100644
index 000000000..9513f1709
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <item ></item>
+</layer-list>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable2-expected-completion51.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable2-expected-completion51.txt
new file mode 100644
index 000000000..147184597
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable2-expected-completion51.txt
@@ -0,0 +1,10 @@
+Code completion in drawable2.xml for ^android:innerRadiusRatio="2":
+android:visible : Indicates whether the drawable should intially be visible. [boolean]
+android:dither : Enables or disables dithering. [boolean]
+android:shape : Indicates what shape to fill with a gradient. [enum]
+android:innerRadiusRatio : Inner radius of the ring expressed as a ratio of the ring's width. [float]
+android:thicknessRatio : Thickness of the ring expressed as a ratio of the ring's width. [float]
+android:innerRadius : Inner radius of the ring. [dimension]
+android:thickness : Thickness of the ring. [dimension]
+android:useLevel : Indicates whether the drawable's level affects the way the gradient is drawn.
+xmlns:android
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable2-expected-completion52.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable2-expected-completion52.txt
new file mode 100644
index 000000000..2a2853363
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable2-expected-completion52.txt
@@ -0,0 +1,7 @@
+Code completion in drawable2.xml for ^<gradient:
+<corners /> : Describes the corners for the rectangle shape of a GradientDrawable.
+<gradient /> : Used to describe the gradient used to fill the shape of a GradientDrawable.
+<padding /> : Used to specify the optional padding of a GradientDrawable.
+<size /> : Used to specify the size of the shape for GradientDrawable.
+<solid /> : Used to fill the shape of GradientDrawable with a solid color.
+<stroke /> : Used to describe the optional stroke of a GradientDrawable.
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable2.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable2.xml
new file mode 100644
index 000000000..c6a672fd8
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable2.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:innerRadiusRatio="2">
+ <gradient />
+</shape>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/quickfix2-expected-quickFix4.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/quickfix2-expected-quickFix4.xml
new file mode 100644
index 000000000..025fa0a67
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/quickfix2-expected-quickFix4.xml
@@ -0,0 +1,3 @@
+< <color android:color="#0000000"/>
+---
+> <color android:color="#0000000" xmlns:android="http://schemas.android.com/apk/res/android"/>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/quickfix2.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/quickfix2.xml
new file mode 100644
index 000000000..4f2a925a5
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/quickfix2.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ Random comment here
+ -->
+<color android:color="#0000000"/>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/SdkTestCase.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/SdkTestCase.java
index d0998c9f1..d8692ae1c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/SdkTestCase.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/SdkTestCase.java
@@ -93,6 +93,10 @@ public abstract class SdkTestCase extends TestCase {
return sdk;
}
+ protected boolean validateSdk(IAndroidTarget target) {
+ return true;
+ }
+
/**
* Checks that the provided sdk contains one or more valid targets.
* @param sdk the {@link Sdk} to validate.
@@ -100,6 +104,9 @@ public abstract class SdkTestCase extends TestCase {
private void validateSdk(Sdk sdk) {
assertTrue("sdk has no targets", sdk.getTargets().length > 0);
for (IAndroidTarget target : sdk.getTargets()) {
+ if (!validateSdk(target)) {
+ continue;
+ }
IStatus status = new AndroidTargetParser(target).run(new NullProgressMonitor());
if (status.getCode() != IStatus.OK) {
fail("Failed to parse targets data");
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceHelperTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceHelperTest.java
index a653ae280..078e7cb71 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceHelperTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceHelperTest.java
@@ -165,7 +165,6 @@ public class ResourceHelperTest extends TestCase {
assertFalse(ResourceHelper.canCreateResource("@typo/foo")); // nonexistent type
assertFalse(ResourceHelper.canCreateResource("@layout/foo bar")); // space
assertFalse(ResourceHelper.canCreateResource("@layout/new")); // keyword
- assertFalse(ResourceHelper.canCreateResource("@animator/foo")); // unsupported file type
assertFalse(ResourceHelper.canCreateResource("@android:string/foo")); // framework
assertFalse(ResourceHelper.canCreateResource("@android:dimen/foo"));
assertFalse(ResourceHelper.canCreateResource("@android:color/foo"));