aboutsummaryrefslogtreecommitdiffstats
path: root/eclipse/plugins
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2012-12-05 16:26:54 -0800
committerGerrit Code Review <noreply-gerritcodereview@google.com>2012-12-05 16:26:54 -0800
commit408c81cecd6d1bd19fb9e727b9e3fc9a37e614e5 (patch)
tree075cd605024f64339b58e655ef4bc837b121da06 /eclipse/plugins
parent68f663784ed54cb23e1d6d88a1cd9eaa45cdee8d (diff)
parent474bd94478a8ced503e292b17c7e5962de414d99 (diff)
downloadsdk-408c81cecd6d1bd19fb9e727b9e3fc9a37e614e5.zip
sdk-408c81cecd6d1bd19fb9e727b9e3fc9a37e614e5.tar.gz
sdk-408c81cecd6d1bd19fb9e727b9e3fc9a37e614e5.tar.bz2
Merge "Code completion improvements for custom views and themes"
Diffstat (limited to 'eclipse/plugins')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/FragmentRule.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/ScrollViewRule.java5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/ViewTagRule.java49
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssist.java30
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/CompletionProposal.java23
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/OutlineLabelProvider.java7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/animator/AnimationContentAssist.java13
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutContentAssist.java174
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ProjectCallback.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/LayoutDescriptors.java47
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/ViewElementDescriptor.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ClientRulesEngine.java132
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/extra-view-metadata.xml4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java8
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestContentAssist.java13
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/model/UiClassAttributeNode.java45
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesContentAssist.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidPackageRenameParticipant.java5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeMoveParticipant.java5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeRenameParticipant.java5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RefactoringUtil.java35
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/NewXmlFileCreationPage.java1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java33
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion11.txt2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion12.txt2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion39.txt2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion11-expected-complation79.txt10
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion5-expected-completion40.txt2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion9-expected-completion64.txt1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues1-expected-completion32.txt4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/fragmentlayout-expected-applyCompletion47.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/fragmentlayout-expected-complation77.txt5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/fragmentlayout-expected-complation78.txt5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-complation80.txt8
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion69.txt10
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/LayoutTestBase.java7
37 files changed, 671 insertions, 52 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/FragmentRule.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/FragmentRule.java
index e809d00..f99cf0c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/FragmentRule.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/FragmentRule.java
@@ -30,7 +30,7 @@ public class FragmentRule extends BaseViewRule {
@Override
public void onCreate(@NonNull INode node, @NonNull INode parent,
@NonNull InsertType insertType) {
- // When dropping a fragment tag, ask the user which layout to include.
+ // When dropping a fragment tag, ask the user which class to use.
if (insertType == InsertType.CREATE) { // NOT InsertType.CREATE_PREVIEW
String fqcn = mRulesEngine.displayFragmentSourceInput();
if (fqcn != null) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/ScrollViewRule.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/ScrollViewRule.java
index 1dafe53..9f2b4ae 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/ScrollViewRule.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/ScrollViewRule.java
@@ -19,7 +19,9 @@ package com.android.ide.common.layout;
import static com.android.SdkConstants.ANDROID_URI;
import static com.android.SdkConstants.ATTR_LAYOUT_HEIGHT;
import static com.android.SdkConstants.ATTR_LAYOUT_WIDTH;
+import static com.android.SdkConstants.ATTR_ORIENTATION;
import static com.android.SdkConstants.FQCN_LINEAR_LAYOUT;
+import static com.android.SdkConstants.VALUE_VERTICAL;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
@@ -58,7 +60,8 @@ public class ScrollViewRule extends FrameLayoutRule {
// Insert a default linear layout (which will in turn be registered as
// a child of this node and the create child method above will set its
// fill parent attributes, its id, etc.
- node.appendChild(FQCN_LINEAR_LAYOUT);
+ INode linear = node.appendChild(FQCN_LINEAR_LAYOUT);
+ linear.setAttribute(ANDROID_URI, ATTR_ORIENTATION, VALUE_VERTICAL);
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/ViewTagRule.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/ViewTagRule.java
new file mode 100644
index 0000000..a89a3d8
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/ViewTagRule.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 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.common.layout;
+
+import static com.android.SdkConstants.ATTR_CLASS;
+
+import com.android.annotations.NonNull;
+import com.android.ide.common.api.INode;
+import com.android.ide.common.api.IViewRule;
+import com.android.ide.common.api.InsertType;
+import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor;
+
+/**
+ * An {@link IViewRule} for the special XML {@code <view>} tag.
+ */
+public class ViewTagRule extends BaseViewRule {
+ @Override
+ public void onCreate(@NonNull INode node, @NonNull INode parent,
+ @NonNull InsertType insertType) {
+ // When dropping a view tag, ask the user which custom view class to use
+ if (insertType == InsertType.CREATE) { // NOT InsertType.CREATE_PREVIEW
+ String fqcn = mRulesEngine.displayCustomViewClassInput();
+ if (fqcn != null) {
+ if (!ViewElementDescriptor.viewNeedsPackage(fqcn)) {
+ fqcn = fqcn.substring(fqcn.lastIndexOf('.') + 1);
+ }
+ node.editXml("Set Custom View Class",
+ new PropertySettingNodeHandler(null, ATTR_CLASS,
+ fqcn.length() > 0 ? fqcn : null));
+ } else {
+ // Remove the view; the insertion was canceled
+ parent.removeChild(node);
+ }
+ }
+ }
+}
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 09bd627..e620fc3 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
@@ -20,6 +20,7 @@ import static com.android.SdkConstants.ANDROID_URI;
import static com.android.SdkConstants.ATTR_LAYOUT_RESOURCE_PREFIX;
import static com.android.SdkConstants.PREFIX_ANDROID;
import static com.android.SdkConstants.PREFIX_RESOURCE_REF;
+import static com.android.SdkConstants.PREFIX_THEME_REF;
import static com.android.SdkConstants.UNIT_DP;
import static com.android.SdkConstants.UNIT_IN;
import static com.android.SdkConstants.UNIT_MM;
@@ -46,6 +47,9 @@ import com.android.utils.Pair;
import com.android.utils.XmlUtils;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.ui.ISharedImages;
+import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
@@ -226,8 +230,10 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
// or their values).
if (info.isInValue) {
- computeAttributeValues(proposals, offset, parent, info.name, currentNode,
- wordPrefix, info.skipEndTag, info.replaceLength);
+ if (computeAttributeValues(proposals, offset, parent, info.name, currentNode,
+ wordPrefix, info.skipEndTag, info.replaceLength)) {
+ return;
+ }
}
// Look up attribute proposals based on descriptors
@@ -463,14 +469,24 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
choices = UiResourceAttributeNode.computeResourceStringMatches(
mEditor, attributeDescriptor, value);
attrInfo.skipEndTag = false;
+ } else if (value.startsWith(PREFIX_THEME_REF)
+ && !attributeInfo.getFormats().contains(Format.REFERENCE)) {
+ choices = UiResourceAttributeNode.computeResourceStringMatches(
+ mEditor, attributeDescriptor, value);
+ attrInfo.skipEndTag = false;
}
return choices;
}
- protected void computeAttributeValues(List<ICompletionProposal> proposals, int offset,
+ /**
+ * Compute attribute values. Return true if the complete set of values was
+ * added, so addition descriptor information should not be added.
+ */
+ protected boolean computeAttributeValues(List<ICompletionProposal> proposals, int offset,
String parentTagName, String attributeName, Node node, String wordPrefix,
boolean skipEndTag, int replaceLength) {
+ return false;
}
protected void computeTextValues(List<ICompletionProposal> proposals, int offset,
@@ -504,8 +520,8 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
*
* @return An ElementDescriptor[] or null.
*/
- private Object[] getElementChoicesForTextNode(Node parentNode) {
- Object[] choices = null;
+ protected ElementDescriptor[] getElementChoicesForTextNode(Node parentNode) {
+ ElementDescriptor[] choices = null;
String parent;
if (parentNode.getNodeType() == Node.ELEMENT_NODE) {
// We're editing a text node which parent is an element node. Limit
@@ -598,6 +614,10 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
if (isAttribute) {
icon = IconFactory.getInstance().getIcon(ATTRIBUTE_ICON_FILENAME);
}
+ } else if (choice instanceof IType) {
+ IType type = (IType) choice;
+ keyword = type.getFullyQualifiedName();
+ icon = JavaUI.getSharedImages().getImage(ISharedImages.IMG_OBJS_CUNIT);
} else {
continue; // discard unknown choice
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/CompletionProposal.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/CompletionProposal.java
index 74b7dd8..b52f4db 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/CompletionProposal.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/CompletionProposal.java
@@ -16,6 +16,7 @@
package com.android.ide.eclipse.adt.internal.editors;
import com.android.ide.common.api.IAttributeInfo;
+import com.android.ide.eclipse.adt.AdtPlugin;
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;
@@ -23,6 +24,10 @@ import com.android.ide.eclipse.adt.internal.editors.descriptors.IDescriptorProvi
import com.android.ide.eclipse.adt.internal.editors.descriptors.TextAttributeDescriptor;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.core.ISourceRange;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
@@ -142,6 +147,24 @@ class CompletionProposal implements ICompletionProposal {
}
}
+ } else if (mChoice instanceof IType) {
+ IType type = (IType) mChoice;
+ try {
+ ISourceRange javadocRange = type.getJavadocRange();
+ if (javadocRange != null && javadocRange.getLength() > 0) {
+ ISourceRange sourceRange = type.getSourceRange();
+ if (sourceRange != null) {
+ String source = type.getSource();
+ int start = javadocRange.getOffset() - sourceRange.getOffset();
+ int length = javadocRange.getLength();
+ String doc = source.substring(start, start + length);
+ return doc;
+ }
+ }
+ return type.getAttachedJavadoc(new NullProgressMonitor());
+ } catch (JavaModelException e) {
+ AdtPlugin.log(e, null);
+ }
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/OutlineLabelProvider.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/OutlineLabelProvider.java
index 1d27e33..bb5d1ba 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/OutlineLabelProvider.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/OutlineLabelProvider.java
@@ -24,6 +24,8 @@ import static com.android.SdkConstants.ATTR_SRC;
import static com.android.SdkConstants.ATTR_TEXT;
import static com.android.SdkConstants.DRAWABLE_PREFIX;
import static com.android.SdkConstants.LAYOUT_RESOURCE_PREFIX;
+import static com.android.SdkConstants.VIEW;
+import static com.android.SdkConstants.VIEW_TAG;
import org.eclipse.swt.graphics.Image;
import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeLabelProvider;
@@ -43,6 +45,11 @@ class OutlineLabelProvider extends JFaceNodeLabelProvider {
if (element instanceof Element) {
Element e = (Element) element;
String tagName = e.getTagName();
+ if (VIEW_TAG.equals(tagName)) {
+ // Can't have both view.png and View.png; issues on case sensitive vs
+ // case insensitive file systems
+ tagName = VIEW;
+ }
IconFactory factory = IconFactory.getInstance();
Image img = factory.getIcon(tagName, null);
if (img != null) {
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
index 777cf1d..8a4cf23 100644
--- 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
@@ -70,7 +70,7 @@ public final class AnimationContentAssist extends AndroidContentAssist {
}
@Override
- protected void computeAttributeValues(List<ICompletionProposal> proposals, int offset,
+ protected boolean computeAttributeValues(List<ICompletionProposal> proposals, int offset,
String parentTagName, String attributeName, Node node, String wordPrefix,
boolean skipEndTag, int replaceLength) {
@@ -95,8 +95,8 @@ public final class AnimationContentAssist extends AndroidContentAssist {
}
- super.computeAttributeValues(proposals, offset, parentTagName, attributeName, node,
- wordPrefix, skipEndTag, replaceLength);
+ return super.computeAttributeValues(proposals, offset, parentTagName, attributeName,
+ node, wordPrefix, skipEndTag, replaceLength);
} else if (parentTagName.equals(OBJECT_ANIMATOR)
&& attributeName.endsWith(PROPERTY_NAME)) {
@@ -156,12 +156,13 @@ public final class AnimationContentAssist extends AndroidContentAssist {
addMatchingProposals(proposals, pairs.toArray(), offset, node, wordPrefix,
(char) 0 /* needTag */, true /* isAttribute */, false /* isNew */,
skipEndTag /* skipEndTag */, replaceLength);
- return;
}
}
+
+ return false;
} else {
- super.computeAttributeValues(proposals, offset, parentTagName, attributeName, node,
- wordPrefix, skipEndTag, replaceLength);
+ return 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/layout/LayoutContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutContentAssist.java
index 7efa34a..99549ab 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutContentAssist.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutContentAssist.java
@@ -16,13 +16,48 @@
package com.android.ide.eclipse.adt.internal.editors.layout;
+import static com.android.SdkConstants.ANDROID_PKG_PREFIX;
+import static com.android.SdkConstants.ATTR_CLASS;
+import static com.android.SdkConstants.ATTR_CONTEXT;
+import static com.android.SdkConstants.ATTR_NAME;
+import static com.android.SdkConstants.CLASS_ACTIVITY;
+import static com.android.SdkConstants.CLASS_FRAGMENT;
+import static com.android.SdkConstants.CLASS_V4_FRAGMENT;
+import static com.android.SdkConstants.CLASS_VIEW;
+import static com.android.SdkConstants.VIEW_FRAGMENT;
+import static com.android.SdkConstants.VIEW_TAG;
+
+import com.android.annotations.Nullable;
import com.android.annotations.VisibleForTesting;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.AndroidContentAssist;
import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.CustomViewDescriptorService;
+import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.layout.gle2.CustomViewFinder;
+import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
+import com.google.common.collect.Lists;
+import com.google.common.collect.ObjectArrays;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.ITypeHierarchy;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.w3c.dom.Node;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
/**
* Content Assist Processor for /res/layout XML files
*/
@@ -55,6 +90,145 @@ public final class LayoutContentAssist extends AndroidContentAssist {
}
}
+ if (choices == null && parent.length() >= 1 && Character.isLowerCase(parent.charAt(0))) {
+ // Custom view prefix?
+ List<ElementDescriptor> descriptors = getCustomViews();
+ if (descriptors != null && !descriptors.isEmpty()) {
+ List<ElementDescriptor> matches = Lists.newArrayList();
+ for (ElementDescriptor descriptor : descriptors) {
+ if (descriptor.getXmlLocalName().startsWith(parent)) {
+ matches.add(descriptor);
+ }
+ }
+ if (!matches.isEmpty()) {
+ return matches.toArray(new ElementDescriptor[matches.size()]);
+ }
+ }
+ }
+
return choices;
}
+
+ @Override
+ protected ElementDescriptor[] getElementChoicesForTextNode(Node parentNode) {
+ ElementDescriptor[] choices = super.getElementChoicesForTextNode(parentNode);
+
+ // Add in custom views, if any
+ List<ElementDescriptor> descriptors = getCustomViews();
+ if (descriptors != null && !descriptors.isEmpty()) {
+ ElementDescriptor[] array = descriptors.toArray(
+ new ElementDescriptor[descriptors.size()]);
+ choices = ObjectArrays.concat(choices, array, ElementDescriptor.class);
+ choices = sort(choices);
+ }
+
+ return choices;
+ }
+
+ @Nullable
+ private List<ElementDescriptor> getCustomViews() {
+ // Add in custom views, if any
+ IProject project = mEditor.getProject();
+ CustomViewFinder finder = CustomViewFinder.get(project);
+ Collection<String> views = finder.getAllViews();
+ if (views == null) {
+ finder.refresh();
+ views = finder.getAllViews();
+ }
+ if (views != null && !views.isEmpty()) {
+ List<ElementDescriptor> descriptors = Lists.newArrayListWithExpectedSize(views.size());
+ CustomViewDescriptorService customViews = CustomViewDescriptorService.getInstance();
+ for (String fqcn : views) {
+ ViewElementDescriptor descriptor = customViews.getDescriptor(project, fqcn);
+ if (descriptor != null) {
+ descriptors.add(descriptor);
+ }
+ }
+
+ return descriptors;
+ }
+
+ return null;
+ }
+
+ @Override
+ protected boolean computeAttributeValues(List<ICompletionProposal> proposals, int offset,
+ String parentTagName, String attributeName, Node node, String wordPrefix,
+ boolean skipEndTag, int replaceLength) {
+ super.computeAttributeValues(proposals, offset, parentTagName, attributeName, node,
+ wordPrefix, skipEndTag, replaceLength);
+
+ boolean projectOnly = false;
+ List<String> superClasses = null;
+ if (VIEW_FRAGMENT.equals(parentTagName) && (attributeName.endsWith(ATTR_NAME)
+ || attributeName.equals(ATTR_CLASS))) {
+ // Insert fragment class matches
+ superClasses = Arrays.asList(CLASS_V4_FRAGMENT, CLASS_FRAGMENT);
+ } else if (VIEW_TAG.equals(parentTagName) && attributeName.endsWith(ATTR_CLASS)) {
+ // Insert custom view matches
+ superClasses = Collections.singletonList(CLASS_VIEW);
+ projectOnly = true;
+ } else if (attributeName.endsWith(ATTR_CONTEXT)) {
+ // Insert activity matches
+ superClasses = Collections.singletonList(CLASS_ACTIVITY);
+ }
+
+ if (superClasses != null) {
+ IProject project = mEditor.getProject();
+ if (project == null) {
+ return false;
+ }
+ try {
+ IJavaProject javaProject = BaseProjectHelper.getJavaProject(project);
+ IType type = javaProject.findType(superClasses.get(0));
+ Set<IType> elements = new HashSet<IType>();
+ if (type != null) {
+ ITypeHierarchy hierarchy = type.newTypeHierarchy(new NullProgressMonitor());
+ IType[] allSubtypes = hierarchy.getAllSubtypes(type);
+ for (IType subType : allSubtypes) {
+ if (!projectOnly || subType.getResource() != null) {
+ elements.add(subType);
+ }
+ }
+ }
+ assert superClasses.size() <= 2; // If more, need to do additional work below
+ if (superClasses.size() == 2) {
+ type = javaProject.findType(superClasses.get(1));
+ if (type != null) {
+ ITypeHierarchy hierarchy = type.newTypeHierarchy(
+ new NullProgressMonitor());
+ IType[] allSubtypes = hierarchy.getAllSubtypes(type);
+ for (IType subType : allSubtypes) {
+ if (!projectOnly || subType.getResource() != null) {
+ elements.add(subType);
+ }
+ }
+ }
+ }
+
+ List<IType> sorted = new ArrayList<IType>(elements);
+ Collections.sort(sorted, new Comparator<IType>() {
+ @Override
+ public int compare(IType type1, IType type2) {
+ String fqcn1 = type1.getFullyQualifiedName();
+ String fqcn2 = type2.getFullyQualifiedName();
+ int category1 = fqcn1.startsWith(ANDROID_PKG_PREFIX) ? 1 : -1;
+ int category2 = fqcn2.startsWith(ANDROID_PKG_PREFIX) ? 1 : -1;
+ if (category1 != category2) {
+ return category1 - category2;
+ }
+ return fqcn1.compareTo(fqcn2);
+ }
+ });
+ addMatchingProposals(proposals, sorted.toArray(), offset, node, wordPrefix,
+ (char) 0, false /* isAttribute */, false /* isNew */,
+ false /* skipEndTag */, replaceLength);
+ return true;
+ } catch (CoreException e) {
+ AdtPlugin.log(e, null);
+ }
+ }
+
+ return false;
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ProjectCallback.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ProjectCallback.java
index 6aace4c..b261a5f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ProjectCallback.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ProjectCallback.java
@@ -18,6 +18,7 @@ package com.android.ide.eclipse.adt.internal.editors.layout;
import static com.android.SdkConstants.ANDROID_PKG_PREFIX;
import static com.android.SdkConstants.CALENDAR_VIEW;
+import static com.android.SdkConstants.CLASS_VIEW;
import static com.android.SdkConstants.EXPANDABLE_LIST_VIEW;
import static com.android.SdkConstants.FQCN_GRID_VIEW;
import static com.android.SdkConstants.FQCN_SPINNER;
@@ -142,6 +143,11 @@ public final class ProjectCallback extends LegacyCallback {
throws ClassNotFoundException, Exception {
mUsed = true;
+ if (className == null) {
+ // Just make a plain <View> if you specify <view> without a class= attribute.
+ className = CLASS_VIEW;
+ }
+
// look for a cached version
Class<?> clazz = mLoadedClasses.get(className);
if (clazz != null) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/LayoutDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/LayoutDescriptors.java
index 35ef935..7b2fe84 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/LayoutDescriptors.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/LayoutDescriptors.java
@@ -21,11 +21,13 @@ import static com.android.SdkConstants.ATTR_CLASS;
import static com.android.SdkConstants.ATTR_LAYOUT;
import static com.android.SdkConstants.ATTR_NAME;
import static com.android.SdkConstants.ATTR_TAG;
+import static com.android.SdkConstants.CLASS_VIEW;
import static com.android.SdkConstants.FQCN_GESTURE_OVERLAY_VIEW;
import static com.android.SdkConstants.REQUEST_FOCUS;
import static com.android.SdkConstants.VIEW_FRAGMENT;
import static com.android.SdkConstants.VIEW_INCLUDE;
import static com.android.SdkConstants.VIEW_MERGE;
+import static com.android.SdkConstants.VIEW_TAG;
import com.android.SdkConstants;
import com.android.ide.common.api.IAttributeInfo.Format;
@@ -168,6 +170,14 @@ public final class LayoutDescriptors implements IDescriptorProvider {
newDescriptors.addAll(newLayouts);
newDescriptors.addAll(newViews);
+ ViewElementDescriptor viewTag = createViewTag(frameLayoutAttrs);
+ newViews.add(viewTag);
+ newDescriptors.add(viewTag);
+
+ ViewElementDescriptor requestFocus = createRequestFocus();
+ newViews.add(requestFocus);
+ newDescriptors.add(requestFocus);
+
// Link all layouts to everything else here.. recursively
for (ViewElementDescriptor layoutDesc : newLayouts) {
layoutDesc.setChildren(newDescriptors);
@@ -184,10 +194,6 @@ public final class LayoutDescriptors implements IDescriptorProvider {
fixSuperClasses(infoDescMap);
- ViewElementDescriptor requestFocus = createRequestFocus();
- newViews.add(requestFocus);
- newDescriptors.add(requestFocus);
-
// The <merge> tag can only be a root tag, so it is added at the end.
// It gets everything else as children but it is not made a child itself.
ViewElementDescriptor mergeTag = createMerge(frameLayoutAttrs);
@@ -305,7 +311,7 @@ public final class LayoutDescriptors implements IDescriptorProvider {
}
/**
- * Creates a new <include> descriptor and adds it to the list of view descriptors.
+ * Creates a new {@code <include>} descriptor and adds it to the list of view descriptors.
*
* @param knownViews A list of view descriptors being populated. Also used to find the
* View descriptor and extract its layout attributes.
@@ -456,6 +462,37 @@ public final class LayoutDescriptors implements IDescriptorProvider {
}
/**
+ * Creates and returns a new {@code <view>} descriptor.
+ * @param viewLayoutAttribs The layout attributes to use for the new descriptor
+ * @param styleMap The style map provided by the SDK
+ */
+ private ViewElementDescriptor createViewTag(AttributeDescriptor[] viewLayoutAttribs) {
+ String xmlName = VIEW_TAG;
+
+ TextAttributeDescriptor classAttribute = new ClassAttributeDescriptor(
+ CLASS_VIEW,
+ ATTR_CLASS, null /* namespace */,
+ new AttributeInfo(ATTR_CLASS, Format.STRING_SET),
+ true /*mandatory*/)
+ .setTooltip("Supply the name of the view class to instantiate");
+
+ // Create the include descriptor
+ ViewElementDescriptor desc = new ViewElementDescriptor(xmlName,
+ xmlName, // ui_name
+ xmlName, // "class name"; the GLE only treats this as an element tag
+ "A view tag whose class attribute names the class to be instantiated", // tooltip
+ null, // sdk_url
+ new AttributeDescriptor[] { // attributes
+ classAttribute
+ },
+ viewLayoutAttribs, // layout attributes
+ null, // children
+ false /* mandatory */);
+
+ return desc;
+ }
+
+ /**
* Creates and returns a new {@code <requestFocus>} descriptor.
*/
private ViewElementDescriptor createRequestFocus() {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/ViewElementDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/ViewElementDescriptor.java
index 466720a..7999524 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/ViewElementDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/ViewElementDescriptor.java
@@ -19,6 +19,8 @@ package com.android.ide.eclipse.adt.internal.editors.layout.descriptors;
import static com.android.SdkConstants.ANDROID_VIEW_PKG;
import static com.android.SdkConstants.ANDROID_WEBKIT_PKG;
import static com.android.SdkConstants.ANDROID_WIDGET_PREFIX;
+import static com.android.SdkConstants.VIEW;
+import static com.android.SdkConstants.VIEW_TAG;
import com.android.ide.common.resources.platform.AttributeInfo;
import com.android.ide.eclipse.adt.AdtPlugin;
@@ -188,6 +190,10 @@ public class ViewElementDescriptor extends ElementDescriptor {
// "android.gesture.GestureOverlayView" in their XML, we need to look up
// only by basename
name = name.substring(name.lastIndexOf('.') + 1);
+ } else if (VIEW_TAG.equals(name)) {
+ // Can't have both view.png and View.png; issues on case sensitive vs
+ // case insensitive file systems
+ name = VIEW;
}
Image icon = factory.getIcon(name);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ClientRulesEngine.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ClientRulesEngine.java
index 472b158..388907a 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ClientRulesEngine.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ClientRulesEngine.java
@@ -21,6 +21,7 @@ import static com.android.SdkConstants.ATTR_ID;
import static com.android.SdkConstants.AUTO_URI;
import static com.android.SdkConstants.CLASS_FRAGMENT;
import static com.android.SdkConstants.CLASS_V4_FRAGMENT;
+import static com.android.SdkConstants.CLASS_VIEW;
import static com.android.SdkConstants.NEW_ID_PREFIX;
import static com.android.SdkConstants.URI_PREFIX;
@@ -512,7 +513,8 @@ class ClientRulesEngine implements IClientRulesEngine {
int modifiers = typeInfoRequestor.getModifiers();
if (!Flags.isPublic(modifiers)
|| Flags.isInterface(modifiers)
- || Flags.isEnum(modifiers)) {
+ || Flags.isEnum(modifiers)
+ || Flags.isAbstract(modifiers)) {
return false;
}
return true;
@@ -544,6 +546,98 @@ class ClientRulesEngine implements IClientRulesEngine {
}
@Override
+ public String displayCustomViewClassInput() {
+ try {
+ IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
+ IProject project = mRulesEngine.getProject();
+ final IJavaProject javaProject = BaseProjectHelper.getJavaProject(project);
+ if (javaProject != null) {
+ // Look up sub-types of each (new fragment class and compatibility fragment
+ // class, if any) and merge the two arrays - then create a scope from these
+ // elements.
+ IType[] viewTypes = new IType[0];
+ IType fragmentType = javaProject.findType(CLASS_VIEW);
+ if (fragmentType != null) {
+ ITypeHierarchy hierarchy =
+ fragmentType.newTypeHierarchy(new NullProgressMonitor());
+ viewTypes = hierarchy.getAllSubtypes(fragmentType);
+ }
+ scope = SearchEngine.createJavaSearchScope(viewTypes, IJavaSearchScope.SOURCES);
+ }
+
+ Shell parent = AdtPlugin.getShell();
+ final AtomicReference<String> returnValue =
+ new AtomicReference<String>();
+ final AtomicReference<SelectionDialog> dialogHolder =
+ new AtomicReference<SelectionDialog>();
+ final SelectionDialog dialog = JavaUI.createTypeDialog(
+ parent,
+ new ProgressMonitorDialog(parent),
+ scope,
+ IJavaElementSearchConstants.CONSIDER_CLASSES, false,
+ // Use ? as a default filter to fill dialog with matches
+ "?", //$NON-NLS-1$
+ new TypeSelectionExtension() {
+ @Override
+ public Control createContentArea(Composite parentComposite) {
+ Composite composite = new Composite(parentComposite, SWT.NONE);
+ composite.setLayout(new GridLayout(1, false));
+ Button button = new Button(composite, SWT.PUSH);
+ button.setText("Create New...");
+ button.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ String fqcn = createNewCustomViewClass(javaProject);
+ if (fqcn != null) {
+ returnValue.set(fqcn);
+ dialogHolder.get().close();
+ }
+ }
+ });
+ return composite;
+ }
+
+ @Override
+ public ITypeInfoFilterExtension getFilterExtension() {
+ return new ITypeInfoFilterExtension() {
+ @Override
+ public boolean select(ITypeInfoRequestor typeInfoRequestor) {
+ int modifiers = typeInfoRequestor.getModifiers();
+ if (!Flags.isPublic(modifiers)
+ || Flags.isInterface(modifiers)
+ || Flags.isEnum(modifiers)
+ || Flags.isAbstract(modifiers)) {
+ return false;
+ }
+ return true;
+ }
+ };
+ }
+ });
+ dialogHolder.set(dialog);
+
+ dialog.setTitle("Choose Custom View Class");
+ dialog.setMessage("Select a Custom View class (? = any character, * = any string):");
+ if (dialog.open() == IDialogConstants.CANCEL_ID) {
+ return null;
+ }
+ if (returnValue.get() != null) {
+ return returnValue.get();
+ }
+
+ Object[] types = dialog.getResult();
+ if (types != null && types.length > 0) {
+ return ((IType) types[0]).getFullyQualifiedName();
+ }
+ } catch (JavaModelException e) {
+ AdtPlugin.log(e, null);
+ } catch (CoreException e) {
+ AdtPlugin.log(e, null);
+ }
+ return null;
+ }
+
+ @Override
public void redraw() {
mRulesEngine.getEditor().getCanvasControl().redraw();
}
@@ -583,13 +677,17 @@ class ClientRulesEngine implements IClientRulesEngine {
return (int) (pixels / mRulesEngine.getEditor().getCanvasControl().getScale());
}
- String createNewFragmentClass(IJavaProject javaProject) {
+ private String createNewFragmentClass(IJavaProject javaProject) {
NewClassWizardPage page = new NewClassWizardPage();
IProject project = mRulesEngine.getProject();
- IAndroidTarget target = Sdk.getCurrent().getTarget(project);
+ Sdk sdk = Sdk.getCurrent();
+ if (sdk == null) {
+ return null;
+ }
+ IAndroidTarget target = sdk.getTarget(project);
String superClass;
- if (target.getVersion().getApiLevel() < 11) {
+ if (target == null || target.getVersion().getApiLevel() < 11) {
superClass = CLASS_V4_FRAGMENT;
} else {
superClass = CLASS_FRAGMENT;
@@ -615,6 +713,32 @@ class ClientRulesEngine implements IClientRulesEngine {
}
}
+ private String createNewCustomViewClass(IJavaProject javaProject) {
+ NewClassWizardPage page = new NewClassWizardPage();
+
+ IProject project = mRulesEngine.getProject();
+ String superClass = CLASS_VIEW;
+ page.setSuperClass(superClass, true /* canBeModified */);
+ IPackageFragmentRoot root = ManifestInfo.getSourcePackageRoot(javaProject);
+ if (root != null) {
+ page.setPackageFragmentRoot(root, true /* canBeModified */);
+ }
+ ManifestInfo manifestInfo = ManifestInfo.get(project);
+ IPackageFragment pkg = manifestInfo.getPackageFragment();
+ if (pkg != null) {
+ page.setPackageFragment(pkg, true /* canBeModified */);
+ }
+ OpenNewClassWizardAction action = new OpenNewClassWizardAction();
+ action.setConfiguredWizardPage(page);
+ action.run();
+ IType createdType = page.getCreatedType();
+ if (createdType != null) {
+ return createdType.getFullyQualifiedName();
+ } else {
+ return null;
+ }
+ }
+
@Override
public @NonNull String getUniqueId(@NonNull String fqcn) {
UiDocumentNode root = mRulesEngine.getEditor().getModel();
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java
index f7eac4434..8f99237 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java
@@ -18,6 +18,7 @@ package com.android.ide.eclipse.adt.internal.editors.layout.gre;
import static com.android.SdkConstants.ANDROID_WIDGET_PREFIX;
import static com.android.SdkConstants.VIEW_MERGE;
+import static com.android.SdkConstants.VIEW_TAG;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
@@ -792,6 +793,12 @@ public class RulesEngine {
String baseName = realFqcn.substring(dotIndex+1);
// Capitalize rule class name to match naming conventions, if necessary (<merge>)
if (Character.isLowerCase(baseName.charAt(0))) {
+ if (baseName.equals(VIEW_TAG)) {
+ // Hack: ViewRule is generic for the "View" class, so we can't use it
+ // for the special XML "view" tag (lowercase); instead, the rule is
+ // named "ViewTagRule" instead.
+ baseName = "ViewTag"; //$NON-NLS-1$
+ }
baseName = Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1);
}
ruleClassName = packageName + "." + //$NON-NLS-1$
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/extra-view-metadata.xml b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/extra-view-metadata.xml
index 796843f..6a67b1d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/extra-view-metadata.xml
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/extra-view-metadata.xml
@@ -397,6 +397,10 @@
topAttrs="layout,inflatedId,visibility"
render="skip" />
<view
+ class="view"
+ topAttrs="class"
+ render="skip" />
+ <view
class="android.gesture.GestureOverlayView"
topAttrs="gestureStrokeType,uncertainGestureColor,eventsInterceptionEnabled,gestureColor,orientation"
render="skip" />
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java
index 7050be4..d9d2722 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java
@@ -153,11 +153,17 @@ public class UiViewElementNode extends UiElementNode {
if (className != null && className.length() > 0) {
int index = className.lastIndexOf('.');
if (index != -1) {
- className = className.substring(index + 1);
+ className = "customView"; //$NON-NLS-1$
}
img = icons.getIcon(className);
}
}
+
+ if (img == null) {
+ // Can't have both view.png and View.png; issues on case sensitive vs
+ // case insensitive file systems
+ img = icons.getIcon("View"); //$NON-NLS-1$
+ }
}
if (img == null) {
img = desc.getGenericIcon();
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestContentAssist.java
index 8f78a0f..1492adb 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestContentAssist.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestContentAssist.java
@@ -48,7 +48,7 @@ public final class ManifestContentAssist extends AndroidContentAssist {
}
@Override
- protected void computeAttributeValues(List<ICompletionProposal> proposals, int offset,
+ protected boolean computeAttributeValues(List<ICompletionProposal> proposals, int offset,
String parentTagName, String attributeName, Node node, String wordPrefix,
boolean skipEndTag, int replaceLength) {
if (attributeName.endsWith(ATTRIBUTE_MIN_SDK_VERSION)
@@ -60,7 +60,11 @@ public final class ManifestContentAssist extends AndroidContentAssist {
List<Pair<String, String>> choices = new ArrayList<Pair<String, String>>();
int max = AdtUtils.getHighestKnownApiLevel();
// Look for any more recent installed versions the user may have
- IAndroidTarget[] targets = Sdk.getCurrent().getTargets();
+ Sdk sdk = Sdk.getCurrent();
+ if (sdk == null) {
+ return false;
+ }
+ IAndroidTarget[] targets = sdk.getTargets();
for (IAndroidTarget target : targets) {
AndroidVersion version = target.getVersion();
int apiLevel = version.getApiLevel();
@@ -81,9 +85,10 @@ public final class ManifestContentAssist extends AndroidContentAssist {
addMatchingProposals(proposals, choices.toArray(), offset, node, wordPrefix,
needTag, true /* isAttribute */, false /* isNew */,
skipEndTag /* skipEndTag */, replaceLength);
+ return true;
} else {
- super.computeAttributeValues(proposals, offset, parentTagName, attributeName, node,
- wordPrefix, skipEndTag, replaceLength);
+ return 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/manifest/model/UiClassAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/model/UiClassAttributeNode.java
index a1a4b58..4c829d9 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/model/UiClassAttributeNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/model/UiClassAttributeNode.java
@@ -82,6 +82,10 @@ import org.eclipse.ui.forms.widgets.TableWrapData;
import org.w3c.dom.Element;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
/**
* Represents an XML attribute for a class, that can be modified using a simple text field or
@@ -686,7 +690,46 @@ public class UiClassAttributeNode extends UiTextAttributeNode {
@Override
public String[] getPossibleValues(String prefix) {
- // TODO: compute a list of existing classes for content assist completion
+ // Compute a list of existing classes for content assist completion
+ IProject project = getProject();
+ if (project == null || mReferenceClass == null) {
+ return null;
+ }
+
+ try {
+ IJavaProject javaProject = BaseProjectHelper.getJavaProject(project);
+ IType type = javaProject.findType(mReferenceClass);
+ // Use sets because query sometimes repeats the same class
+ Set<String> libraryTypes = new HashSet<String>(80);
+ Set<String> localTypes = new HashSet<String>(30);
+ if (type != null) {
+ ITypeHierarchy hierarchy = type.newTypeHierarchy(new NullProgressMonitor());
+ IType[] allSubtypes = hierarchy.getAllSubtypes(type);
+ for (IType subType : allSubtypes) {
+ int flags = subType.getFlags();
+ if (Flags.isPublic(flags) && !Flags.isAbstract(flags)) {
+ String fqcn = subType.getFullyQualifiedName();
+ if (subType.getResource() != null) {
+ localTypes.add(fqcn);
+ } else {
+ libraryTypes.add(fqcn);
+ }
+ }
+ }
+ }
+
+ List<String> local = new ArrayList<String>(localTypes);
+ List<String> library = new ArrayList<String>(libraryTypes);
+ Collections.sort(local);
+ Collections.sort(library);
+ List<String> combined = new ArrayList<String>(local.size() + library.size());
+ combined.addAll(local);
+ combined.addAll(library);
+ return combined.toArray(new String[combined.size()]);
+ } catch (Exception e) {
+ AdtPlugin.log(e, null);
+ }
+
return null;
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesContentAssist.java
index bd6c079..d0ee92c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesContentAssist.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesContentAssist.java
@@ -70,7 +70,7 @@ public class ValuesContentAssist extends AndroidContentAssist {
}
@Override
- protected void computeAttributeValues(List<ICompletionProposal> proposals, int offset,
+ protected boolean computeAttributeValues(List<ICompletionProposal> proposals, int offset,
String parentTagName, String attributeName, Node node, String wordPrefix,
boolean skipEndTag, int replaceLength) {
super.computeAttributeValues(proposals, offset, parentTagName, attributeName, node,
@@ -129,10 +129,12 @@ public class ValuesContentAssist extends AndroidContentAssist {
addMatchingProposals(proposals, sorted.toArray(), offset, node, wordPrefix,
needTag, true /* isAttribute */, false /* isNew */,
skipEndTag /* skipEndTag */, replaceLength);
- return;
+ return true;
}
}
}
+
+ return false;
}
@Override
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidPackageRenameParticipant.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidPackageRenameParticipant.java
index 1455af6..a5b29e3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidPackageRenameParticipant.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidPackageRenameParticipant.java
@@ -438,7 +438,10 @@ public class AndroidPackageRenameParticipant extends RenameParticipant {
if (tag.equals(VIEW_TAG)) {
classNode = element.getAttributeNode(ATTR_CLASS);
} else if (tag.equals(VIEW_FRAGMENT)) {
- classNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_NAME);
+ classNode = element.getAttributeNode(ATTR_CLASS);
+ if (classNode == null) {
+ classNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_NAME);
+ }
} else if (element.hasAttributeNS(TOOLS_URI, ATTR_CONTEXT)) {
classNode = element.getAttributeNodeNS(TOOLS_URI, ATTR_CONTEXT);
if (classNode != null && classNode.getValue().startsWith(".")) { //$NON-NLS-1$
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeMoveParticipant.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeMoveParticipant.java
index 26ae8d0..7181f98 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeMoveParticipant.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeMoveParticipant.java
@@ -277,7 +277,10 @@ public class AndroidTypeMoveParticipant extends MoveParticipant {
}
}
} else if (tag.equals(VIEW_FRAGMENT)) {
- Attr classNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_NAME);
+ Attr classNode = element.getAttributeNode(ATTR_CLASS);
+ if (classNode == null) {
+ classNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_NAME);
+ }
if (classNode != null && classNode.getValue().equals(mOldFqcn)) {
int start = RefactoringUtil.getAttributeValueRangeStart(classNode, document);
if (start != -1) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeRenameParticipant.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeRenameParticipant.java
index f454c68..383fd13 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeRenameParticipant.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/AndroidTypeRenameParticipant.java
@@ -291,7 +291,10 @@ public class AndroidTypeRenameParticipant extends RenameParticipant {
}
}
} else if (tag.equals(VIEW_FRAGMENT)) {
- Attr classNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_NAME);
+ Attr classNode = element.getAttributeNode(ATTR_CLASS);
+ if (classNode == null) {
+ classNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_NAME);
+ }
if (classNode != null && classNode.getValue().equals(mOldFqcn)) {
int start = RefactoringUtil.getAttributeValueRangeStart(classNode, document);
if (start != -1) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RefactoringUtil.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RefactoringUtil.java
index 41551a4..04ebcfa 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RefactoringUtil.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RefactoringUtil.java
@@ -24,7 +24,9 @@ import static com.android.xml.AndroidManifest.ATTRIBUTE_PARENT_ACTIVITY_NAME;
import static com.android.xml.AndroidManifest.ATTRIBUTE_TARGET_ACTIVITY;
import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.xml.AndroidManifest;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
@@ -174,24 +176,47 @@ public class RefactoringUtil {
* Returns whether the given manifest attribute should be considered to describe
* a class name. These will be eligible for refactoring when classes are renamed
* or moved.
- * <p>
- * TODO: Move to {@link RefactoringUtil}
*
* @param attribute the manifest attribute
* @return true if this attribute can describe a class
*/
public static boolean isManifestClassAttribute(@NonNull Attr attribute) {
- String name = attribute.getLocalName();
+ return isManifestClassAttribute(
+ attribute.getOwnerElement().getTagName(),
+ attribute.getNamespaceURI(),
+ attribute.getLocalName());
+ }
+
+ /**
+ * Returns whether the given manifest attribute should be considered to describe
+ * a class name. These will be eligible for refactoring when classes are renamed
+ * or moved.
+ *
+ * @param tag the tag, if known
+ * @param uri the attribute namespace, if any
+ * @param name the attribute local name, if any
+ * @return true if this attribute can describe a class
+ */
+ public static boolean isManifestClassAttribute(
+ @Nullable String tag,
+ @Nullable String uri,
+ @Nullable String name) {
if (name == null) {
return false;
}
- if (name.equals(ATTR_NAME)
+ if ((name.equals(ATTR_NAME)
+ && (AndroidManifest.NODE_ACTIVITY.equals(tag)
+ || AndroidManifest.NODE_APPLICATION.equals(tag)
+ || AndroidManifest.NODE_INSTRUMENTATION.equals(tag)
+ || AndroidManifest.NODE_PROVIDER.equals(tag)
+ || AndroidManifest.NODE_SERVICE.equals(tag)
+ || AndroidManifest.NODE_RECEIVER.equals(tag)))
|| name.equals(ATTRIBUTE_TARGET_ACTIVITY)
|| name.equals(ATTRIBUTE_MANAGE_SPACE_ACTIVITY)
|| name.equals(ATTRIBUTE_BACKUP_AGENT)
|| name.equals(ATTRIBUTE_PARENT_ACTIVITY_NAME)) {
- return ANDROID_URI.equals(attribute.getNamespaceURI());
+ return ANDROID_URI.equals(uri);
}
return false;
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 ace88a1..28fb8c0 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
@@ -304,6 +304,7 @@ class NewXmlFileCreationPage extends WizardPage {
if (SCROLL_VIEW.equals(root) || HORIZONTAL_SCROLL_VIEW.equals(root)) {
return " <LinearLayout " //$NON-NLS-1$
+ getDefaultAttrs(project, root).replace('\n', ' ')
+ + " android:orientation=\"vertical\"" //$NON-NLS-1$
+ "></LinearLayout>\n"; //$NON-NLS-1$
}
return null;
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 55a6b0b..700e68b 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
@@ -501,6 +501,28 @@ public class AndroidContentAssistTest extends AdtProjectTest {
checkLayoutCompletion("navigation1.xml", "?android:a^ttr/alertDialogStyle");
}
+ public void testComplation77() throws Exception {
+ // Test <fragment class="^" completion
+ checkLayoutCompletion("fragmentlayout.xml", "android:name=\"^com");
+ }
+
+ public void testComplation78() throws Exception {
+ // Test <fragment android:name="^" completion
+ checkLayoutCompletion("fragmentlayout.xml", "class=\"^com");
+ }
+
+ public void testComplation79() throws Exception {
+ // Test tools context completion
+ checkLayoutCompletion("completion11.xml", "tools:context=\"^.MainActivity\"");
+ }
+
+ public void testComplation80() throws Exception {
+ // Test manifest class completion
+ checkManifestCompletion("manifest.xml", "<activity android:name=\"^.");
+ }
+
+ // TODO: Test <view completion!
+
// ---- Test *applying* code completion ----
// The following tests check -applying- a specific code completion
@@ -796,6 +818,12 @@ public class AndroidContentAssistTest extends AdtProjectTest {
"?android:attr/Textapp^", "?android:attr/textAppearanceLargeInverse");
}
+ public void testApplyCompletion47() throws Exception {
+ // Test applying <fragment android:name="^" completion
+ checkApplyLayoutCompletion("fragmentlayout.xml", "class=\"^com",
+ "android.app.ListFragment");
+ }
+
// --- Code Completion test infrastructure ----
private void checkLayoutCompletion(String name, String caretLocation) throws Exception {
@@ -944,11 +972,16 @@ public class AndroidContentAssistTest extends AdtProjectTest {
sb.append("Code completion in " + basename + " for " + caretLocation + ":\n");
for (ICompletionProposal proposal : proposals) {
// TODO: assertNotNull(proposal.getImage());
+ int length = sb.length();
sb.append(proposal.getDisplayString().trim());
String help = proposal.getAdditionalProposalInfo();
if (help != null && help.trim().length() > 0) {
sb.append(" : ");
sb.append(help.replace('\n', ' ').trim());
+ if (sb.length() > length + 300) {
+ sb.setLength(length + 300 - "...".length());
+ sb.append("...");
+ }
}
sb.append('\n');
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion11.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion11.txt
index 8d25f95..20dad3a 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion11.txt
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion11.txt
@@ -63,3 +63,5 @@ Code completion in completion1.xml for ^<TextView:
<android.gesture.GestureOverlayView ></android.gesture.GestureOverlayView> : GestureOverlayView specific attributes.
<fragment /> : A Fragment is a piece of an application's user interface or behavior that can be placed in an Activity
<include /> : Lets you statically include XML layouts inside other XML layouts.
+<requestFocus /> : Requests focus for the parent element or one of its descendants
+<view /> : A view tag whose class attribute names the class to be instantiated
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion12.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion12.txt
index a5fe067..8da18db 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion12.txt
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion12.txt
@@ -63,3 +63,5 @@ Code completion in completion1.xml for btn_default">^</FrameLayout>:
<android.gesture.GestureOverlayView ></android.gesture.GestureOverlayView> : GestureOverlayView specific attributes.
<fragment /> : A Fragment is a piece of an application's user interface or behavior that can be placed in an Activity
<include /> : Lets you statically include XML layouts inside other XML layouts.
+<requestFocus /> : Requests focus for the parent element or one of its descendants
+<view /> : A view tag whose class attribute names the class to be instantiated
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion39.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion39.txt
index ec756c7..2ac2d31 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion39.txt
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion39.txt
@@ -29,7 +29,7 @@ android:minWidth : Makes the TextView be at least this many pixels wide. [dimen
android:gravity : Specifies how to align the text by the view's x- and/or y-axis when the text is smaller than the view. [flag]
android:scrollHorizontally : Whether the text is allowed to be wider than the view (and therefore can be scrolled horizontally). [boolean]
android:password : Whether the characters of the field are displayed as password dots instead of themselves. * Deprecated: Use inputType instead. [boolean]
-android:singleLine : Constrains the text to a single horizontally scrolling line instead of letting it wrap onto multiple lines, and advances focus instead of inserting a newline when you press the enter key. * Deprecated: This attribute is deprecated. Use "maxLines" instead to change the layout of a static text, and use the "textMultiLine" flag in the inputType attribute instead for editable text views (if both singleLine and inputType are supplied, the inputType flags will override the value of singleLine). [boolean]
+android:singleLine : Constrains the text to a single horizontally scrolling line instead of letting it wrap onto multiple lines, and advances focus instead of inserting a newline when you press the enter key. * Deprecated: This attribute is deprecated. Use "maxLines" instead to change the layo...
android:enabled : Specifies whether the widget is enabled. [boolean]
android:selectAllOnFocus : If the text is selectable, select it all when the view takes focus. [boolean]
android:includeFontPadding : Leave enough room for ascenders and descenders instead of using the font ascent and descent strictly. [boolean]
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion11-expected-complation79.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion11-expected-complation79.txt
new file mode 100644
index 0000000..3748c77
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion11-expected-complation79.txt
@@ -0,0 +1,10 @@
+Code completion in completion11.xml for tools:context="^.MainActivity":
+android.accounts.AccountAuthenticatorActivity : <p>See <code><a href="/reference/android/app/SearchManager.html">android.app.SearchManager</a></code> for more details.</td> </tr> <tr class=" api apilevel-1" > <td class="jd-typecol">int</td> <td class="jd-linkcol"...
+android.app.ActivityGroup : <p> <p class="caution"> <strong>This class was deprecated in API level 13</strong>.<br/> Use the new <code><a href="/reference/android/app/Fragment.html">Fragment</a></code> and <code><a href="/reference/android/app/FragmentManager.html">FragmentManager</...
+android.app.AliasActivity : <p>See <code><a href="/reference/android/app/SearchManager.html">android.app.SearchManager</a></code> for more details.</td> </tr> <tr class=" api apilevel-1" > <td class="jd-typecol">int</td> <td class="jd-linkcol"><a href="/reference...
+android.app.ExpandableListActivity : <p> ExpandableListActivity hosts a <code><a href="/reference/android/widget/ExpandableListView.html">ExpandableListView</a></code> object that can be bound to different data sources that provide a two-levels of data (the top-level is group, and below each ...
+android.app.LauncherActivity : <div id="jd-header"> public abstract class <h1 itemprop="name">LauncherActivity</h1> extends <a href="/reference/android/app/ListActivity.html">ListActivity</a><br/> ...
+android.app.ListActivity : <p> ListActivity hosts a <code><a href="/reference/android/widget/ListView.html">ListView</a></code> object that can be bound to different data sources, typically either an array or a Cursor holding query results. Binding, screen layout, and row layout are discussed ...
+android.app.NativeActivity : <p>A typical manifest would look like: <pre>&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.native_activity" android:versionCode="1" android:versionName="1.0"&gt; &lt;!-- This is the platform ...
+android.app.TabActivity : <p> <p class="caution"> <strong>This class was deprecated in API level 13</strong>.<br/> New applications should use Fragments instead of this class; to continue to run on older devices, you can use the v4 support library which provides a version of the F...
+android.preference.PreferenceActivity : <p>This activity shows one or more headers of preferences, each of which is associated with a <code><a href="/reference/android/preference/PreferenceFragment.html">PreferenceFragment</a></code> to display the preferences of that header. The actual layout...
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion5-expected-completion40.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion5-expected-completion40.txt
index 01d86ac..a4cf0fa 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion5-expected-completion40.txt
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion5-expected-completion40.txt
@@ -29,7 +29,7 @@ android:minWidth : Makes the TextView be at least this many pixels wide. [dimen
android:gravity : Specifies how to align the text by the view's x- and/or y-axis when the text is smaller than the view. [flag]
android:scrollHorizontally : Whether the text is allowed to be wider than the view (and therefore can be scrolled horizontally). [boolean]
android:password : Whether the characters of the field are displayed as password dots instead of themselves. * Deprecated: Use inputType instead. [boolean]
-android:singleLine : Constrains the text to a single horizontally scrolling line instead of letting it wrap onto multiple lines, and advances focus instead of inserting a newline when you press the enter key. * Deprecated: This attribute is deprecated. Use "maxLines" instead to change the layout of a static text, and use the "textMultiLine" flag in the inputType attribute instead for editable text views (if both singleLine and inputType are supplied, the inputType flags will override the value of singleLine). [boolean]
+android:singleLine : Constrains the text to a single horizontally scrolling line instead of letting it wrap onto multiple lines, and advances focus instead of inserting a newline when you press the enter key. * Deprecated: This attribute is deprecated. Use "maxLines" instead to change the layo...
android:enabled : Specifies whether the widget is enabled. [boolean]
android:selectAllOnFocus : If the text is selectable, select it all when the view takes focus. [boolean]
android:includeFontPadding : Leave enough room for ascenders and descenders instead of using the font ascent and descent strictly. [boolean]
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion9-expected-completion64.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion9-expected-completion64.txt
index be2096b..2085e96 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion9-expected-completion64.txt
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion9-expected-completion64.txt
@@ -65,3 +65,4 @@ Code completion in completion9.xml for ^<Button:
<include /> : Lets you statically include XML layouts inside other XML layouts.
<merge ></merge> : A root tag useful for XML layouts inflated using a ViewStub.
<requestFocus /> : Requests focus for the parent element or one of its descendants
+<view /> : A view tag whose class attribute names the class to be instantiated
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues1-expected-completion32.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues1-expected-completion32.txt
index 825c7b5..57684d7 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues1-expected-completion32.txt
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues1-expected-completion32.txt
@@ -34,7 +34,7 @@ android:childIndicator : Indicator shown beside the child View. [reference]
android:childIndicatorLeft : The left bound for a child's indicator. [dimension]
android:childIndicatorRight : The right bound for a child's indicator. [dimension]
android:choiceMode : Defines the choice behavior for the view. [enum]
-class : Supply the name of the fragment class to instantiate
+class : Supply the name of the view class to instantiate
android:clickColor : Color of the outline of click feedback. [color]
android:clickable : Defines whether this view reacts to click events. [boolean]
android:clipChildren : Defines whether a child is limited to draw inside of its bounds or not. [boolean]
@@ -244,7 +244,7 @@ android:showDividers : Setting for which dividers to show. [flag]
android:showWeekNumber : Whether do show week numbers. [boolean]
android:shownWeekCount : The number of weeks to be shown. [integer]
android:shrinkColumns : The zero-based index of the columns to shrink. [string]
-android:singleLine : Constrains the text to a single horizontally scrolling line instead of letting it wrap onto multiple lines, and advances focus instead of inserting a newline when you press the enter key. * Deprecated: This attribute is deprecated. Use "maxLines" instead to change the layout of a static text, and use the "textMultiLine" flag in the inputType attribute instead for editable text views (if both singleLine and inputType are supplied, the inputType flags will override the value of singleLine). [boolean]
+android:singleLine : Constrains the text to a single horizontally scrolling line instead of letting it wrap onto multiple lines, and advances focus instead of inserting a newline when you press the enter key. * Deprecated: This attribute is deprecated. Use "maxLines" instead to change the layo...
android:smoothScrollbar : When set to true, the list will use a more refined calculation method based on the pixels height of the items visible on screen. [boolean]
android:soundEffectsEnabled : Boolean that controls whether a view should have sound effects enabled for events such as clicking and touching. [boolean]
android:spacing : [dimension]
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/fragmentlayout-expected-applyCompletion47.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/fragmentlayout-expected-applyCompletion47.diff
new file mode 100644
index 0000000..3ed60f1
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/fragmentlayout-expected-applyCompletion47.diff
@@ -0,0 +1,4 @@
+Code completion in fragmentlayout.xml for class="^com selecting android.app.ListFragment:
+@@ -16 +16
+- <fragment class="^com.android.eclipse.tests.TestFragment"
++ <fragment class="android.app.ListFragment^"
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/fragmentlayout-expected-complation77.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/fragmentlayout-expected-complation77.txt
new file mode 100644
index 0000000..6e8687f
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/fragmentlayout-expected-complation77.txt
@@ -0,0 +1,5 @@
+Code completion in fragmentlayout.xml for android:name="^com:
+android.app.DialogFragment : <p>Implementations should override this class and implement <code><a href="/reference/android/app/Fragment.html#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)">onCreateView(LayoutInflater, ViewGroup, Bundle)</a></code> to supply ...
+android.app.ListFragment : <p> ListFragment hosts a <code><a href="/reference/android/widget/ListView.html">ListView</a></code> object that can be bound to different data sources, typically either an array or a Cursor holding query results. Binding, screen layout, and row layout are discussed ...
+android.preference.PreferenceFragment : <p> Furthermore, the preferences shown will follow the visual style of system preferences. It is easy to create a hierarchy of preferences (that can be shown on multiple screens) via XML. For these reasons, it is recommended to use this fragment (as a s...
+android.webkit.WebViewFragment : <p> The WebView is automically paused or resumed when the Fragment is paused or resumed. </p> </div><!-- jd-descr --> <div class="jd-descr"> <h2>Summary</h2> <!-- =========== ENUM CONSTANT SUMMARY =========== --> <table id="...
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/fragmentlayout-expected-complation78.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/fragmentlayout-expected-complation78.txt
new file mode 100644
index 0000000..e02637c
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/fragmentlayout-expected-complation78.txt
@@ -0,0 +1,5 @@
+Code completion in fragmentlayout.xml for class="^com:
+android.app.DialogFragment : <p>Implementations should override this class and implement <code><a href="/reference/android/app/Fragment.html#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)">onCreateView(LayoutInflater, ViewGroup, Bundle)</a></code> to supply ...
+android.app.ListFragment : <p> ListFragment hosts a <code><a href="/reference/android/widget/ListView.html">ListView</a></code> object that can be bound to different data sources, typically either an array or a Cursor holding query results. Binding, screen layout, and row layout are discussed ...
+android.preference.PreferenceFragment : <p> Furthermore, the preferences shown will follow the visual style of system preferences. It is easy to create a hierarchy of preferences (that can be shown on multiple screens) via XML. For these reasons, it is recommended to use this fragment (as a s...
+android.webkit.WebViewFragment : <p> The WebView is automically paused or resumed when the Fragment is paused or resumed. </p> </div><!-- jd-descr --> <div class="jd-descr"> <h2>Summary</h2> <!-- =========== ENUM CONSTANT SUMMARY =========== --> <table id="...
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-complation80.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-complation80.txt
new file mode 100644
index 0000000..cb1d0ce
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-complation80.txt
@@ -0,0 +1,8 @@
+Code completion in manifest.xml for <activity android:name="^.:
+android.accounts.AccountAuthenticatorActivity
+android.app.ActivityGroup
+android.app.AliasActivity
+android.app.ExpandableListActivity
+android.app.ListActivity
+android.app.NativeActivity
+android.app.TabActivity
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion69.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion69.txt
index 1cd2f93..cf7e0f4 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion69.txt
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion69.txt
@@ -16,13 +16,3 @@ Code completion in manifest.xml for <uses-sdk android:minSdkVersion="^11" />:
3 : API 3: Android 1.5 (Cupcake)
2 : API 2: Android 1.1
1 : API 1: Android 1.0
-@string/
-@android:
-@+id/
-@anim/
-@animator/
-@color/
-@drawable/
-@id/
-@layout/
-@style/
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/LayoutTestBase.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/LayoutTestBase.java
index d0d2cd2..4b4bb81 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/LayoutTestBase.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/LayoutTestBase.java
@@ -359,6 +359,13 @@ public class LayoutTestBase extends TestCase {
fail("Not supported in tests yet");
return false;
}
+
+ @Override
+ @Nullable
+ public String displayCustomViewClassInput() {
+ fail("Not supported in tests yet");
+ return null;
+ }
}
public void testDummy() {