diff options
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.java | 395 |
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; - } - } -} |