aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CustomViewFinder.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CustomViewFinder.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CustomViewFinder.java395
1 files changed, 0 insertions, 395 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CustomViewFinder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CustomViewFinder.java
deleted file mode 100644
index 1f97c8c54..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CustomViewFinder.java
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.eclipse.org/org/documents/epl-v10.php
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
-
-import static com.android.SdkConstants.CLASS_VIEW;
-import static com.android.SdkConstants.CLASS_VIEWGROUP;
-import static com.android.SdkConstants.FN_FRAMEWORK_LIBRARY;
-
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
-import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
-import com.android.ide.eclipse.adt.internal.sdk.Sdk;
-import com.android.utils.Pair;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.core.runtime.QualifiedName;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jdt.core.Flags;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IMethod;
-import org.eclipse.jdt.core.IPackageFragment;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.search.IJavaSearchConstants;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.core.search.SearchEngine;
-import org.eclipse.jdt.core.search.SearchMatch;
-import org.eclipse.jdt.core.search.SearchParticipant;
-import org.eclipse.jdt.core.search.SearchPattern;
-import org.eclipse.jdt.core.search.SearchRequestor;
-import org.eclipse.jdt.internal.core.ResolvedBinaryType;
-import org.eclipse.jdt.internal.core.ResolvedSourceType;
-import org.eclipse.swt.widgets.Display;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * The {@link CustomViewFinder} can look up the custom views and third party views
- * available for a given project.
- */
-@SuppressWarnings("restriction") // JDT model access for custom-view class lookup
-public class CustomViewFinder {
- /**
- * Qualified name for the per-project non-persistent property storing the
- * {@link CustomViewFinder} for this project
- */
- private final static QualifiedName CUSTOM_VIEW_FINDER = new QualifiedName(AdtPlugin.PLUGIN_ID,
- "viewfinder"); //$NON-NLS-1$
-
- /** Project that this view finder locates views for */
- private final IProject mProject;
-
- private final List<Listener> mListeners = new ArrayList<Listener>();
-
- private List<String> mCustomViews;
- private List<String> mThirdPartyViews;
- private boolean mRefreshing;
-
- /**
- * Constructs an {@link CustomViewFinder} for the given project. Don't use this method;
- * use the {@link #get} factory method instead.
- *
- * @param project project to create an {@link CustomViewFinder} for
- */
- private CustomViewFinder(IProject project) {
- mProject = project;
- }
-
- /**
- * Returns the {@link CustomViewFinder} for the given project
- *
- * @param project the project the finder is associated with
- * @return a {@CustomViewFinder} for the given project, never null
- */
- public static CustomViewFinder get(IProject project) {
- CustomViewFinder finder = null;
- try {
- finder = (CustomViewFinder) project.getSessionProperty(CUSTOM_VIEW_FINDER);
- } catch (CoreException e) {
- // Not a problem; we will just create a new one
- }
-
- if (finder == null) {
- finder = new CustomViewFinder(project);
- try {
- project.setSessionProperty(CUSTOM_VIEW_FINDER, finder);
- } catch (CoreException e) {
- AdtPlugin.log(e, "Can't store CustomViewFinder");
- }
- }
-
- return finder;
- }
-
- public void refresh() {
- refresh(null /*listener*/, true /* sync */);
- }
-
- public void refresh(final Listener listener) {
- refresh(listener, false /* sync */);
- }
-
- private void refresh(final Listener listener, boolean sync) {
- // Add this listener to the list of listeners which should be notified when the
- // search is done. (There could be more than one since multiple requests could
- // arrive for a slow search since the search is run in a different thread).
- if (listener != null) {
- synchronized (this) {
- mListeners.add(listener);
- }
- }
- synchronized (this) {
- if (listener != null) {
- mListeners.add(listener);
- }
- if (mRefreshing) {
- return;
- }
- mRefreshing = true;
- }
-
- FindViewsJob job = new FindViewsJob();
- job.schedule();
- if (sync) {
- try {
- job.join();
- } catch (InterruptedException e) {
- AdtPlugin.log(e, null);
- }
- }
- }
-
- public Collection<String> getCustomViews() {
- return mCustomViews == null ? null : Collections.unmodifiableCollection(mCustomViews);
- }
-
- public Collection<String> getThirdPartyViews() {
- return mThirdPartyViews == null
- ? null : Collections.unmodifiableCollection(mThirdPartyViews);
- }
-
- public Collection<String> getAllViews() {
- // Not yet initialized: return null
- if (mCustomViews == null) {
- return null;
- }
- List<String> all = new ArrayList<String>(mCustomViews.size() + mThirdPartyViews.size());
- all.addAll(mCustomViews);
- all.addAll(mThirdPartyViews);
- return all;
- }
-
- /**
- * Returns a pair of view lists - the custom views and the 3rd-party views.
- * This method performs no caching; it is the same as asking the custom view finder
- * to refresh itself and then waiting for the answer and returning it.
- *
- * @param project the Android project
- * @param layoutsOnly if true, only search for layouts
- * @return a pair of lists, the first containing custom views and the second
- * containing 3rd party views
- */
- public static Pair<List<String>,List<String>> findViews(
- final IProject project, boolean layoutsOnly) {
- CustomViewFinder finder = get(project);
-
- return finder.findViews(layoutsOnly);
- }
-
- private Pair<List<String>,List<String>> findViews(final boolean layoutsOnly) {
- final Set<String> customViews = new HashSet<String>();
- final Set<String> thirdPartyViews = new HashSet<String>();
-
- ProjectState state = Sdk.getProjectState(mProject);
- final List<IProject> libraries = state != null
- ? state.getFullLibraryProjects() : Collections.<IProject>emptyList();
-
- SearchRequestor requestor = new SearchRequestor() {
- @Override
- public void acceptSearchMatch(SearchMatch match) throws CoreException {
- // Ignore matches in comments
- if (match.isInsideDocComment()) {
- return;
- }
-
- Object element = match.getElement();
- if (element instanceof ResolvedBinaryType) {
- // Third party view
- ResolvedBinaryType type = (ResolvedBinaryType) element;
- IPackageFragment fragment = type.getPackageFragment();
- IPath path = fragment.getPath();
- String last = path.lastSegment();
- // Filter out android.jar stuff
- if (last.equals(FN_FRAMEWORK_LIBRARY)) {
- return;
- }
- if (!isValidView(type, layoutsOnly)) {
- return;
- }
-
- IProject matchProject = match.getResource().getProject();
- if (mProject == matchProject || libraries.contains(matchProject)) {
- String fqn = type.getFullyQualifiedName();
- thirdPartyViews.add(fqn);
- }
- } else if (element instanceof ResolvedSourceType) {
- // User custom view
- IProject matchProject = match.getResource().getProject();
- if (mProject == matchProject || libraries.contains(matchProject)) {
- ResolvedSourceType type = (ResolvedSourceType) element;
- if (!isValidView(type, layoutsOnly)) {
- return;
- }
- String fqn = type.getFullyQualifiedName();
- fqn = fqn.replace('$', '.');
- customViews.add(fqn);
- }
- }
- }
- };
- try {
- IJavaProject javaProject = BaseProjectHelper.getJavaProject(mProject);
- if (javaProject != null) {
- String className = layoutsOnly ? CLASS_VIEWGROUP : CLASS_VIEW;
- IType viewType = javaProject.findType(className);
- if (viewType != null) {
- IJavaSearchScope scope = SearchEngine.createHierarchyScope(viewType);
- SearchParticipant[] participants = new SearchParticipant[] {
- SearchEngine.getDefaultSearchParticipant()
- };
- int matchRule = SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE;
-
- SearchPattern pattern = SearchPattern.createPattern("*",
- IJavaSearchConstants.CLASS, IJavaSearchConstants.IMPLEMENTORS,
- matchRule);
- SearchEngine engine = new SearchEngine();
- engine.search(pattern, participants, scope, requestor,
- new NullProgressMonitor());
- }
- }
- } catch (CoreException e) {
- AdtPlugin.log(e, null);
- }
-
-
- List<String> custom = new ArrayList<String>(customViews);
- List<String> thirdParty = new ArrayList<String>(thirdPartyViews);
-
- if (!layoutsOnly) {
- // Update our cached answers (unless we were filtered on only layouts)
- mCustomViews = custom;
- mThirdPartyViews = thirdParty;
- }
-
- return Pair.of(custom, thirdParty);
- }
-
- /**
- * Determines whether the given member is a valid android.view.View to be added to the
- * list of custom views or third party views. It checks that the view is public and
- * not abstract for example.
- */
- private static boolean isValidView(IType type, boolean layoutsOnly)
- throws JavaModelException {
- // Skip anonymous classes
- if (type.isAnonymous()) {
- return false;
- }
- int flags = type.getFlags();
- if (Flags.isAbstract(flags) || !Flags.isPublic(flags)) {
- return false;
- }
-
- // TODO: if (layoutsOnly) perhaps try to filter out AdapterViews and other ViewGroups
- // not willing to accept children via XML
-
- // See if the class has one of the acceptable constructors
- // needed for XML instantiation:
- // View(Context context)
- // View(Context context, AttributeSet attrs)
- // View(Context context, AttributeSet attrs, int defStyle)
- // We don't simply do three direct checks via type.getMethod() because the types
- // are not resolved, so we don't know for each parameter if we will get the
- // fully qualified or the unqualified class names.
- // Instead, iterate over the methods and look for a match.
- String typeName = type.getElementName();
- for (IMethod method : type.getMethods()) {
- // Only care about constructors
- if (!method.getElementName().equals(typeName)) {
- continue;
- }
-
- String[] parameterTypes = method.getParameterTypes();
- if (parameterTypes == null || parameterTypes.length < 1 || parameterTypes.length > 3) {
- continue;
- }
-
- String first = parameterTypes[0];
- // Look for the parameter type signatures -- produced by
- // JDT's Signature.createTypeSignature("Context", false /*isResolved*/);.
- // This is not a typo; they were copy/pasted from the actual parameter names
- // observed in the debugger examining these data structures.
- if (first.equals("QContext;") //$NON-NLS-1$
- || first.equals("Qandroid.content.Context;")) { //$NON-NLS-1$
- if (parameterTypes.length == 1) {
- return true;
- }
- String second = parameterTypes[1];
- if (second.equals("QAttributeSet;") //$NON-NLS-1$
- || second.equals("Qandroid.util.AttributeSet;")) { //$NON-NLS-1$
- if (parameterTypes.length == 2) {
- return true;
- }
- String third = parameterTypes[2];
- if (third.equals("I")) { //$NON-NLS-1$
- if (parameterTypes.length == 3) {
- return true;
- }
- }
- }
- }
- }
-
- return false;
- }
-
- /**
- * Interface implemented by clients of the {@link CustomViewFinder} to be notified
- * when a custom view search has completed. Will always be called on the SWT event
- * dispatch thread.
- */
- public interface Listener {
- void viewsUpdated(Collection<String> customViews, Collection<String> thirdPartyViews);
- }
-
- /**
- * Job for performing class search off the UI thread. This is marked as a system job
- * so that it won't show up in the progress monitor etc.
- */
- private class FindViewsJob extends Job {
- FindViewsJob() {
- super("Find Custom Views");
- setSystem(true);
- }
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- Pair<List<String>, List<String>> views = findViews(false);
- mCustomViews = views.getFirst();
- mThirdPartyViews = views.getSecond();
-
- // Notify listeners on SWT's UI thread
- Display.getDefault().asyncExec(new Runnable() {
- @Override
- public void run() {
- Collection<String> customViews =
- Collections.unmodifiableCollection(mCustomViews);
- Collection<String> thirdPartyViews =
- Collections.unmodifiableCollection(mThirdPartyViews);
- synchronized (this) {
- for (Listener l : mListeners) {
- l.viewsUpdated(customViews, thirdPartyViews);
- }
- mListeners.clear();
- mRefreshing = false;
- }
- }
- });
- return Status.OK_STATUS;
- }
- }
-}