diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java index 77c08b526..5d1ababc2 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java @@ -205,6 +205,7 @@ public final class AndroidManifestDescriptors implements IDescriptorProvider { overrideClassName(overrides, "receiver", AndroidConstants.CLASS_BROADCASTRECEIVER); //$NON-NLS-1$ overrideClassName(overrides, "service", AndroidConstants.CLASS_SERVICE); //$NON-NLS-1$ overrideClassName(overrides, "provider", AndroidConstants.CLASS_CONTENTPROVIDER); //$NON-NLS-1$ + overrideClassName(overrides, "instrumentation", AndroidConstants.CLASS_INSTRUMENTATION); //$NON-NLS-1$ // -- list element nodes already created -- // These elements are referenced by already opened editors, so we want to update them @@ -244,27 +245,42 @@ public final class AndroidManifestDescriptors implements IDescriptorProvider { new DescriptorsUtils.ITextAttributeCreator() { public TextAttributeDescriptor create(String xmlName, String uiName, String nsUri, String tooltip) { + uiName += "*"; //$NON-NLS-1$ if (AndroidConstants.CLASS_ACTIVITY.equals(className)) { return new ClassAttributeDescriptor( className, PostActivityCreationAction.getAction(), - xmlName, uiName + "*", //$NON-NLS-1$ + xmlName, + uiName, nsUri, tooltip, - true /*mandatory */); + true /*mandatory */, + true /*defaultToProjectOnly*/); } else if (AndroidConstants.CLASS_BROADCASTRECEIVER.equals(className)) { return new ClassAttributeDescriptor( className, PostReceiverCreationAction.getAction(), - xmlName, uiName + "*", //$NON-NLS-1$ + xmlName, + uiName, nsUri, tooltip, - true /*mandatory */); - + true /*mandatory */, + true /*defaultToProjectOnly*/); + } else if (AndroidConstants.CLASS_INSTRUMENTATION.equals(className)) { + return new ClassAttributeDescriptor( + className, + null, // no post action + xmlName, + uiName, + nsUri, + tooltip, + true /*mandatory */, + false /*defaultToProjectOnly*/); } else { return new ClassAttributeDescriptor( className, - xmlName, uiName + "*", //$NON-NLS-1$ + xmlName, + uiName, nsUri, tooltip, true /*mandatory */); diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java index eab7f091b..98d0fe895 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java @@ -39,6 +39,7 @@ public class ApplicationAttributeDescriptor extends TextAttributeDescriptor { @Override public UiAttributeNode createUiNode(UiElementNode uiParent) { return new UiClassAttributeNode("android.app.Application", //$NON-NLS-1$ - null /* postCreationAction */, false /* mandatory */, this, uiParent); + null /* postCreationAction */, false /* mandatory */, this, uiParent, + true /*defaultToProjectOnly*/); } } diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java index 629b37c76..d1a76e078 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java @@ -36,6 +36,8 @@ public class ClassAttributeDescriptor extends TextAttributeDescriptor { /** indicates if the class parameter is mandatory */ boolean mMandatory; + + private final boolean mDefaultToProjectOnly; /** * Creates a new {@link ClassAttributeDescriptor} @@ -49,10 +51,14 @@ public class ClassAttributeDescriptor extends TextAttributeDescriptor { * @param mandatory indicates if the class attribute is mandatory. */ public ClassAttributeDescriptor(String superClassName, - String xmlLocalName, String uiName, String nsUri, - String tooltip, boolean mandatory) { + String xmlLocalName, + String uiName, + String nsUri, + String tooltip, + boolean mandatory) { super(xmlLocalName, uiName, nsUri, tooltip); mSuperClassName = superClassName; + mDefaultToProjectOnly = true; } /** @@ -67,14 +73,21 @@ public class ClassAttributeDescriptor extends TextAttributeDescriptor { * See {@link SdkConstants#NS_RESOURCES} for a common value. * @param tooltip A non-empty tooltip string or null. * @param mandatory indicates if the class attribute is mandatory. + * @param defaultToProjectOnly True if only classes from the sources of this project should + * be shown by default in the class browser. */ public ClassAttributeDescriptor(String superClassName, IPostTypeCreationAction postCreationAction, - String xmlLocalName, String uiName, String nsUri, - String tooltip, boolean mandatory) { + String xmlLocalName, + String uiName, + String nsUri, + String tooltip, + boolean mandatory, + boolean defaultToProjectOnly) { super(xmlLocalName, uiName, nsUri, tooltip); mSuperClassName = superClassName; mPostCreationAction = postCreationAction; + mDefaultToProjectOnly = defaultToProjectOnly; } /** @@ -83,6 +96,6 @@ public class ClassAttributeDescriptor extends TextAttributeDescriptor { @Override public UiAttributeNode createUiNode(UiElementNode uiParent) { return new UiClassAttributeNode(mSuperClassName, mPostCreationAction, - mMandatory, this, uiParent); + mMandatory, this, uiParent, mDefaultToProjectOnly); } } diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java deleted file mode 100644 index 6e589f744..000000000 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.editors.manifest.descriptors; - -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; -import com.android.ide.eclipse.editors.manifest.model.UiClassAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; -import com.android.ide.eclipse.editors.uimodel.UiElementNode; - -/** - * Describes a 'Instrumentation' class XML attribute. It is displayed by a - * {@link UiClassAttributeNode}, that restricts creation and selection to classes inheriting from - * android.app.Instrumentation. - */ -public class InstrumentationAttributeDescriptor extends TextAttributeDescriptor { - - public InstrumentationAttributeDescriptor(String xmlLocalName, String uiName, String nsUri, - String tooltip) { - super(xmlLocalName, uiName, nsUri, tooltip); - } - - /** - * @return A new {@link UiClassAttributeNode} linked to this descriptor. - */ - @Override - public UiAttributeNode createUiNode(UiElementNode uiParent) { - return new UiClassAttributeNode(AndroidConstants.CLASS_INSTRUMENTATION, - null /* postCreationAction */, true /* mandatory */, this, uiParent); - } -} - diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java index e32be86b0..c872b6f31 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java @@ -16,6 +16,7 @@ package com.android.ide.eclipse.editors.manifest.model; +import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.common.AndroidConstants; import com.android.ide.eclipse.common.project.AndroidManifestParser; import com.android.ide.eclipse.common.project.BaseProjectHelper; @@ -31,6 +32,7 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; @@ -63,6 +65,7 @@ import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IFileEditorInput; @@ -90,20 +93,28 @@ public class UiClassAttributeNode extends UiTextAttributeNode { private String mReferenceClass; private IPostTypeCreationAction mPostCreationAction; private boolean mMandatory; + private final boolean mDefaultToProjectOnly; private class HierarchyTypeSelection extends TypeSelectionExtension { private IJavaProject mJavaProject; + private IType mReferenceType; + private Button mProjectOnly; + private boolean mUseProjectOnly; - public HierarchyTypeSelection(IProject project, String referenceClass) { + public HierarchyTypeSelection(IProject project, String referenceClass) + throws JavaModelException { mJavaProject = JavaCore.create(project); - mReferenceClass = referenceClass; + mReferenceType = mJavaProject.findType(referenceClass); } @Override public ITypeInfoFilterExtension getFilterExtension() { return new ITypeInfoFilterExtension() { public boolean select(ITypeInfoRequestor typeInfoRequestor) { + + boolean projectOnly = mUseProjectOnly; + String packageName = typeInfoRequestor.getPackageName(); String typeName = typeInfoRequestor.getTypeName(); String enclosingType = typeInfoRequestor.getEnclosingName(); @@ -121,19 +132,35 @@ public class UiClassAttributeNode extends UiTextAttributeNode { try { IType type = mJavaProject.findType(className); - if (type != null) { - // get the type hierarchy - ITypeHierarchy hierarchy = type.newSupertypeHierarchy( - new NullProgressMonitor()); - - // if the super class is not the reference class, it may inherit from - // it so we get its supertype. At some point it will be null and we - // will return false; - IType superType = type; - while ((superType = hierarchy.getSuperclass(superType)) != null) { - if (mReferenceClass.equals(superType.getFullyQualifiedName())) { - return true; - } + + if (type == null) { + return false; + } + + // don't display abstract classes + if ((type.getFlags() & Flags.AccAbstract) != 0) { + return false; + } + + // if project-only is selected, make sure the package fragment is + // an actual source (thus "from this project"). + if (projectOnly) { + IPackageFragment frag = type.getPackageFragment(); + if (frag == null || frag.getKind() != IPackageFragmentRoot.K_SOURCE) { + return false; + } + } + + // get the type hierarchy and reference type is one of the super classes. + ITypeHierarchy hierarchy = type.newSupertypeHierarchy( + new NullProgressMonitor()); + + IType[] supertypes = hierarchy.getAllSupertypes(type); + int n = supertypes.length; + for (int i = 0; i < n; i++) { + IType st = supertypes[i]; + if (mReferenceType.equals(st)) { + return true; } } } catch (JavaModelException e) { @@ -143,6 +170,29 @@ public class UiClassAttributeNode extends UiTextAttributeNode { } }; } + + @Override + public Control createContentArea(Composite parent) { + + mProjectOnly = new Button(parent, SWT.CHECK); + mProjectOnly.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + mProjectOnly.setText(String.format("Display classes from sources of project '%s' only", + mJavaProject.getProject().getName())); + + mUseProjectOnly = mDefaultToProjectOnly; + mProjectOnly.setSelection(mUseProjectOnly); + + mProjectOnly.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + super.widgetSelected(e); + mUseProjectOnly = mProjectOnly.getSelection(); + getTypeSelectionComponent().triggerSearch(); + } + }); + + return super.createContentArea(parent); + } } /** @@ -165,14 +215,18 @@ public class UiClassAttributeNode extends UiTextAttributeNode { * modification of the class. * @param mandatory indicates if the class value is mandatory * @param attributeDescriptor the {@link AttributeDescriptor} object linked to the Ui Node. + * @param defaultToProjectOnly When true display classes of this project only by default. + * When false any class path will be considered. The user can always toggle this. */ public UiClassAttributeNode(String referenceClass, IPostTypeCreationAction postCreationAction, - boolean mandatory, AttributeDescriptor attributeDescriptor, UiElementNode uiParent) { + boolean mandatory, AttributeDescriptor attributeDescriptor, UiElementNode uiParent, + boolean defaultToProjectOnly) { super(attributeDescriptor, uiParent); mReferenceClass = referenceClass; mPostCreationAction = postCreationAction; mMandatory = mandatory; + mDefaultToProjectOnly = defaultToProjectOnly; } /* (non-java doc) @@ -292,8 +346,11 @@ public class UiClassAttributeNode extends UiTextAttributeNode { // Create a search scope including only the source folder of the current // project. + IPackageFragmentRoot[] packageFragmentRoots = getPackageFragmentRoots(project, + true /*include_containers*/); IJavaSearchScope scope = SearchEngine.createJavaSearchScope( - getPackageFragmentRoots(project), false); + packageFragmentRoots, + false); try { SelectionDialog dlg = JavaUI.createTypeDialog(text.getShell(), @@ -301,7 +358,7 @@ public class UiClassAttributeNode extends UiTextAttributeNode { scope, IJavaElementSearchConstants.CONSIDER_CLASSES, // style false, // no multiple selection - "**", //$NON-NLS-1$ //filter + "**", //$NON-NLS-1$ //filter new HierarchyTypeSelection(project, mReferenceClass)); dlg.setMessage(String.format("Select class name for element %1$s:", getUiParent().getBreadcrumbTrailDescription(false /* include_root */))); @@ -316,6 +373,7 @@ public class UiClassAttributeNode extends UiTextAttributeNode { } } } catch (JavaModelException e1) { + AdtPlugin.log(e1, "UiClassAttributeNode HandleBrowser failed"); } } } @@ -363,7 +421,9 @@ public class UiClassAttributeNode extends UiTextAttributeNode { } } } catch (JavaModelException e) { + AdtPlugin.log(e, "UiClassAttributeNode HandleLabel failed"); } catch (PartInitException e) { + AdtPlugin.log(e, "UiClassAttributeNode HandleLabel failed"); } } } @@ -403,16 +463,20 @@ public class UiClassAttributeNode extends UiTextAttributeNode { * Computes and return the {@link IPackageFragmentRoot}s corresponding to the source folders of * the specified project. * @param project the project + * @param b * @return an array of IPackageFragmentRoot. */ - private IPackageFragmentRoot[] getPackageFragmentRoots(IProject project) { + private IPackageFragmentRoot[] getPackageFragmentRoots(IProject project, + boolean include_containers) { ArrayList result = new ArrayList(); try { IJavaProject javaProject = JavaCore.create(project); IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots(); for (int i = 0; i < roots.length; i++) { IClasspathEntry entry = roots[i].getRawClasspathEntry(); - if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { + if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE || + (include_containers && + entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER)) { result.add(roots[i]); } } @@ -457,7 +521,8 @@ public class UiClassAttributeNode extends UiTextAttributeNode { page.setSuperClass(mReferenceClass, true /* canBeModified */); // get the source folders as java elements. - IPackageFragmentRoot[] roots = getPackageFragmentRoots(getProject()); + IPackageFragmentRoot[] roots = getPackageFragmentRoots(getProject(), + true /*include_containers*/); IPackageFragmentRoot currentRoot = null; IPackageFragment currentFragment = null;