aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/refresh.pngbin0 -> 377 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtils.java21
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ProjectCallback.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/CustomViewDescriptorService.java58
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/AccordionControl.java9
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasViewInfo.java16
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CustomViewFinder.java319
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/IncludeFinder.java2
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java2
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/OutlinePage.java2
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteControl.java117
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/SelectionItem.java7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/SelectionManager.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ViewHierarchy.java4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ChangeViewWizard.java3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/WrapInWizard.java88
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtilsTest.java6
18 files changed, 526 insertions, 138 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/icons/refresh.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/refresh.png
new file mode 100644
index 0000000..7cbebf4
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/refresh.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtils.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtils.java
index 95edfb3..0384ad5 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtils.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtils.java
@@ -671,6 +671,23 @@ public final class DescriptorsUtils {
}
/**
+ * Returns the basename for the given fully qualified class name. It is okay to pass
+ * a basename to this method which will just be returned back.
+ *
+ * @param fqcn The fully qualified class name to convert
+ * @return the basename of the class name
+ */
+ public static String getBasename(String fqcn) {
+ String name = fqcn;
+ int lastDot = name.lastIndexOf('.');
+ if (lastDot != -1) {
+ name = name.substring(lastDot + 1);
+ }
+
+ return name;
+ }
+
+ /**
* Sets the default layout attributes for the a new UiElementNode.
* <p/>
* Note that ideally the node should already be part of a hierarchy so that its
@@ -706,7 +723,7 @@ public final class DescriptorsUtils {
// Don't set default text value into edit texts - they typically start out blank
if (!descriptor.getXmlLocalName().equals(EDIT_TEXT)) {
- String type = descriptor.getUiName();
+ String type = getBasename(descriptor.getUiName());
node.setAttributeValue(
ATTR_TEXT,
SdkConstants.NS_RESOURCES,
@@ -745,7 +762,7 @@ public final class DescriptorsUtils {
* (e.g. "@+id/something")
*/
public static String getFreeWidgetId(UiElementNode uiNode) {
- String name = uiNode.getDescriptor().getXmlLocalName();
+ String name = getBasename(uiNode.getDescriptor().getXmlLocalName());
return getFreeWidgetId(uiNode.getUiRoot(), name);
}
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 d4ba57f..804156a 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
@@ -19,8 +19,8 @@ package com.android.ide.eclipse.adt.internal.editors.layout;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.legacy.LegacyCallback;
-import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AdtConstants;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper;
import com.android.ide.eclipse.adt.internal.resources.manager.ProjectClassLoader;
import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/CustomViewDescriptorService.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/CustomViewDescriptorService.java
index bfc8bb0..db72ac6 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/CustomViewDescriptorService.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/CustomViewDescriptorService.java
@@ -18,6 +18,7 @@ package com.android.ide.eclipse.adt.internal.editors.layout.descriptors;
import com.android.ide.common.resources.platform.ViewClassInfo;
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.sdk.AndroidTargetData;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.sdklib.IAndroidTarget;
@@ -29,6 +30,10 @@ import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.ui.ISharedImages;
+import org.eclipse.jdt.ui.JavaUI;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
import java.util.HashMap;
import java.util.List;
@@ -157,16 +162,9 @@ public final class CustomViewDescriptorService {
if (parentDescriptor != null) {
// we have a valid parent, lets create a new ViewElementDescriptor.
- ViewElementDescriptor descriptor = new ViewElementDescriptor(fqcn,
- fqcn, // ui_name
- fqcn, // canonical class name
- null, // tooltip
- null, // sdk_url
- getAttributeDescriptor(type, parentDescriptor),
- null, // layout attributes
- null, // children
- false /* mandatory */);
-
+ String name = DescriptorsUtils.getBasename(fqcn);
+ ViewElementDescriptor descriptor = new CustomViewDescriptor(name, fqcn,
+ getAttributeDescriptor(type, parentDescriptor));
descriptor.setSuperClass(parentDescriptor);
synchronized (mCustomDescriptorMap) {
@@ -242,16 +240,9 @@ public final class CustomViewDescriptorService {
if (parentDescriptor != null) {
// parent class is a valid View class with a descriptor, so we create one
// for this class.
- ViewElementDescriptor descriptor = new ViewElementDescriptor(fqcn,
- fqcn, // ui_name
- fqcn, // canonical name
- null, // tooltip
- null, // sdk_url
- getAttributeDescriptor(type, parentDescriptor),
- null, // layout attributes
- null, // children
- false /* mandatory */);
-
+ String name = DescriptorsUtils.getBasename(fqcn);
+ ViewElementDescriptor descriptor = new CustomViewDescriptor(name, fqcn,
+ getAttributeDescriptor(type, parentDescriptor));
descriptor.setSuperClass(parentDescriptor);
// add it to the map
@@ -290,4 +281,31 @@ public final class CustomViewDescriptorService {
// TODO add the class attribute descriptors to the parent descriptors.
return parentDescriptor.getAttributes();
}
+
+ private class CustomViewDescriptor extends ViewElementDescriptor {
+ public CustomViewDescriptor(String name, String fqcn, AttributeDescriptor[] attributes) {
+ super(
+ fqcn, // xml name
+ name, // ui name
+ fqcn, // full class name
+ fqcn, // tooltip
+ null, // sdk_url
+ attributes,
+ null, // layout attributes
+ null, // children
+ false // mandatory
+ );
+ }
+
+ @Override
+ public Image getGenericIcon() {
+ // Java source file icon. We could use the Java class icon here
+ // (IMG_OBJS_CLASS), but it does not work well on anything but
+ // white backgrounds
+ ISharedImages sharedImages = JavaUI.getSharedImages();
+ String key = ISharedImages.IMG_OBJS_CUNIT;
+ ImageDescriptor descriptor = sharedImages.getImageDescriptor(key);
+ return descriptor.createImage();
+ }
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/AccordionControl.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/AccordionControl.java
index 24c582d..3c18b16 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/AccordionControl.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/AccordionControl.java
@@ -82,8 +82,8 @@ public abstract class AccordionControl extends Composite {
* overridden to lay out the children with a different layout than the default
* vertical RowLayout
*/
- protected Composite createChildContainer(Composite parent) {
- Composite composite = new Composite(parent, SWT.NONE);
+ protected Composite createChildContainer(Composite parent, Object header, int style) {
+ Composite composite = new Composite(parent, style);
if (mWrap) {
RowLayout layout = new RowLayout(SWT.HORIZONTAL);
layout.center = true;
@@ -335,9 +335,12 @@ public abstract class AccordionControl extends Composite {
updateIcon(label);
if (!scrollGridData.exclude && scrolledComposite.getContent() == null) {
- Composite composite = createChildContainer(scrolledComposite);
Object header = getHeader(label);
+ Composite composite = createChildContainer(scrolledComposite, header, SWT.NONE);
createChildren(composite, header);
+ while (composite.getParent() != scrolledComposite) {
+ composite = composite.getParent();
+ }
scrolledComposite.setContent(composite);
scrolledComposite.setMinSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasViewInfo.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasViewInfo.java
index 30dc3e9..2bb8901 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasViewInfo.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasViewInfo.java
@@ -363,16 +363,16 @@ public class CanvasViewInfo implements IPropertySource {
}
/**
- * Returns true if this {@link CanvasViewInfo} represents an invisible parent - in
- * other words, a view that can have children, and that has zero bounds making it
- * effectively invisible. (We don't actually look for -0- bounds, but
- * bounds smaller than SELECTION_MIN_SIZE.)
+ * Returns true if this {@link CanvasViewInfo} represents an invisible widget that
+ * should be highlighted when selected. This is the case for any layout that is less than the minimum
+ * threshold ({@link #SELECTION_MIN_SIZE}), or any other view that has -0- bounds.
*
- * @return True if this is an invisible parent.
+ * @return True if this is a tiny layout or invisible view
*/
- public boolean isInvisibleParent() {
+ public boolean isInvisible() {
if (mAbsRect.width < SELECTION_MIN_SIZE || mAbsRect.height < SELECTION_MIN_SIZE) {
- return mUiViewNode != null && mUiViewNode.getDescriptor().hasChildren();
+ return mUiViewNode != null && (mUiViewNode.getDescriptor().hasChildren() ||
+ mAbsRect.width <= 0 || mAbsRect.height <= 0);
}
return false;
@@ -383,7 +383,7 @@ public class CanvasViewInfo implements IPropertySource {
* make it visible during selection or dragging? Note that this is NOT considered to
* be the case in the explode-all-views mode where all nodes have their padding
* increased; it's only used for views that individually exploded because they were
- * requested visible and they returned true for {@link #isInvisibleParent()}.
+ * requested visible and they returned true for {@link #isInvisible()}.
*
* @return True if this is an exploded node.
*/
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
new file mode 100644
index 0000000..8cb0d26
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CustomViewFinder.java
@@ -0,0 +1,319 @@
+/*
+ * 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.sdklib.SdkConstants.CLASS_VIEW;
+import static com.android.sdklib.SdkConstants.CLASS_VIEWGROUP;
+import static com.android.sdklib.SdkConstants.FN_FRAMEWORK_LIBRARY;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
+import com.android.ide.eclipse.adt.internal.sdk.Sdk;
+import com.android.util.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.IMember;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
+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.List;
+
+/**
+ * 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);
+ }
+
+ public void refresh(final Listener listener) {
+ // 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();
+ }
+
+ 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 List<String> customViews = new ArrayList<String>();
+ final List<String> thirdPartyViews = new ArrayList<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 {
+ 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 = (IJavaProject) mProject.getNature(JavaCore.NATURE_ID);
+ if (javaProject != null) {
+ String className = layoutsOnly ? CLASS_VIEWGROUP : CLASS_VIEW;
+ IType activityType = javaProject.findType(className);
+ if (activityType != null) {
+ IJavaSearchScope scope = SearchEngine.createHierarchyScope(activityType);
+ SearchParticipant[] participants = new SearchParticipant[] {
+ SearchEngine.getDefaultSearchParticipant()
+ };
+ int matchRule = SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE;
+ SearchPattern pattern = SearchPattern.createPattern("*",
+ IJavaSearchConstants.CLASS, IJavaSearchConstants.DECLARATIONS,
+ matchRule);
+ SearchEngine engine = new SearchEngine();
+ engine.search(pattern, participants, scope, requestor,
+ new NullProgressMonitor());
+ }
+ }
+ } catch (CoreException e) {
+ AdtPlugin.log(e, null);
+ }
+
+ if (!layoutsOnly) {
+ // Update our cached answers (unless we were filtered on only layouts)
+ mCustomViews = customViews;
+ mThirdPartyViews = thirdPartyViews;
+ }
+
+ return Pair.of(customViews, thirdPartyViews);
+ }
+
+ /**
+ * 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(IMember member, boolean layoutsOnly)
+ throws JavaModelException {
+ int flags = member.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
+ return true;
+ }
+
+ /**
+ * 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() {
+ 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;
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java
index 753010f..6d1c25b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java
@@ -300,7 +300,7 @@ public class DomUtilities {
addLowercaseIds(element.getOwnerDocument().getDocumentElement(), ids);
if (prefix == null) {
- prefix = element.getTagName();
+ prefix = DescriptorsUtils.getBasename(element.getTagName());
}
String generated;
int num = 1;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/IncludeFinder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/IncludeFinder.java
index 9da4af9..86e33be 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/IncludeFinder.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/IncludeFinder.java
@@ -90,7 +90,7 @@ public class IncludeFinder {
* {@link IncludeFinder} for this project
*/
private final static QualifiedName INCLUDE_FINDER = new QualifiedName(AdtPlugin.PLUGIN_ID,
- "finder"); //$NON-NLS-1$
+ "includefinder"); //$NON-NLS-1$
/** Project that the include finder locates includes for */
private final IProject mProject;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java
index d29544d..277c194 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java
@@ -747,6 +747,7 @@ public class LayoutCanvas extends Canvas {
if (mShowInvisible == show) {
return;
}
+ mShowInvisible = show;
// Optimization: Avoid doing work when we don't have invisible parents (on show)
// or formerly exploded nodes (on hide).
@@ -756,7 +757,6 @@ public class LayoutCanvas extends Canvas {
return;
}
- mShowInvisible = show;
mLayoutEditor.recomputeLayout();
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/OutlinePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/OutlinePage.java
index b08e616..3c1bd6a 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/OutlinePage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/OutlinePage.java
@@ -483,7 +483,7 @@ public class OutlinePage extends ContentOutlinePage
}
}
if (img == null) {
- img = desc.getCustomizedIcon();
+ img = desc.getGenericIcon();
}
if (img != null) {
if (node.hasError()) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteControl.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteControl.java
index 89e02df..0353d1f 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteControl.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteControl.java
@@ -32,11 +32,13 @@ import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.ViewInfo;
import com.android.ide.common.rendering.api.SessionParams.RenderingMode;
import com.android.ide.eclipse.adt.internal.editors.IconFactory;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.adt.internal.editors.descriptors.DocumentDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditor;
import com.android.ide.eclipse.adt.internal.editors.layout.configuration.ConfigurationComposite;
+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.gre.NodeFactory;
import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeProxy;
@@ -48,6 +50,7 @@ import com.android.ide.eclipse.adt.internal.editors.ui.DecorComposite;
import com.android.ide.eclipse.adt.internal.editors.ui.IDecorContent;
import com.android.ide.eclipse.adt.internal.editors.uimodel.UiDocumentNode;
import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
+import com.android.ide.eclipse.adt.internal.editors.xml.Hyperlinks;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
@@ -70,6 +73,7 @@ import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MenuDetectEvent;
import org.eclipse.swt.events.MenuDetectListener;
+import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.SelectionAdapter;
@@ -82,6 +86,9 @@ import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
+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.Display;
@@ -96,6 +103,7 @@ import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -438,6 +446,8 @@ public class PaletteControl extends Composite {
categoryToItems.put(category, categoryItems);
}
+ headers.add("Custom & Library Views");
+
// Set the categories to expand the first item if
// (1) we don't have a previously selected category, or
// (2) there's just one category anyway, or
@@ -445,7 +455,8 @@ public class PaletteControl extends Composite {
// doesn't exist anymore (can happen when you toggle "Show Categories")
if ((expandedCategories == null && headers.size() > 0) || headers.size() == 1 ||
(expandedCategories != null && expandedCategories.size() >= 1
- && !headers.contains(expandedCategories.iterator().next()))) {
+ && !headers.contains(
+ expandedCategories.iterator().next().replace("&&", "&")))) { //$NON-NLS-1$ //$NON-NLS-2$
// Expand the first category if we don't have a previous selection (e.g. refresh)
expandedCategories = Collections.singleton(headers.get(0));
}
@@ -458,10 +469,45 @@ public class PaletteControl extends Composite {
mAccordion = new AccordionControl(this, SWT.NONE, headers, fillVertical, wrap,
expandedCategories) {
@Override
- protected Composite createChildContainer(Composite parent) {
- Composite composite = super.createChildContainer(parent);
- if (mPaletteMode.isPreview() && mBackground != null) {
- composite.setBackground(mBackground);
+ protected Composite createChildContainer(Composite parent, Object header, int style) {
+ assert categoryToItems != null;
+ List<ViewElementDescriptor> list = categoryToItems.get(header);
+ final Composite composite;
+ if (list == null) {
+ assert header.equals("Custom & Library Views");
+
+ Composite wrapper = new Composite(parent, SWT.NONE);
+ GridLayout gridLayout = new GridLayout(1, false);
+ gridLayout.marginWidth = gridLayout.marginHeight = 0;
+ gridLayout.horizontalSpacing = gridLayout.verticalSpacing = 0;
+ gridLayout.marginBottom = 3;
+ wrapper.setLayout(gridLayout);
+ if (mPaletteMode.isPreview() && mBackground != null) {
+ wrapper.setBackground(mBackground);
+ }
+ composite = super.createChildContainer(wrapper, header,
+ style | SWT.NO_BACKGROUND);
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+
+ Button refreshButton = new Button(wrapper, SWT.PUSH | SWT.FLAT);
+ refreshButton.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER,
+ false, false, 1, 1));
+ refreshButton.setText("Refresh");
+ refreshButton.setImage(IconFactory.getInstance().getIcon("refresh")); //$NON-NLS-1$
+ refreshButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ CustomViewFinder finder = CustomViewFinder.get(mEditor.getProject());
+ finder.refresh(new ViewFinderListener(composite));
+ }
+ });
+
+ wrapper.layout(true);
+ } else {
+ composite = super.createChildContainer(parent, header, style);
+ if (mPaletteMode.isPreview() && mBackground != null) {
+ composite.setBackground(mBackground);
+ }
}
addMenu(composite);
return composite;
@@ -470,8 +516,14 @@ public class PaletteControl extends Composite {
protected void createChildren(Composite parent, Object header) {
assert categoryToItems != null;
List<ViewElementDescriptor> list = categoryToItems.get(header);
- for (ViewElementDescriptor desc : list) {
- createItem(parent, desc);
+ if (list == null) {
+ assert header.equals("Custom & Library Views");
+ addCustomItems(parent);
+ return;
+ } else {
+ for (ViewElementDescriptor desc : list) {
+ createItem(parent, desc);
+ }
}
}
};
@@ -493,6 +545,40 @@ public class PaletteControl extends Composite {
layout(true);
}
+ protected void addCustomItems(final Composite parent) {
+ final CustomViewFinder finder = CustomViewFinder.get(mEditor.getProject());
+ Collection<String> allViews = finder.getAllViews();
+ if (allViews == null) { // Not yet initialized: trigger an async refresh
+ finder.refresh(new ViewFinderListener(parent));
+ return;
+ }
+
+ // Remove previous content
+ for (Control c : parent.getChildren()) {
+ c.dispose();
+ }
+
+ // Add new views
+ for (final String fqcn : allViews) {
+ CustomViewDescriptorService service = CustomViewDescriptorService.getInstance();
+ ViewElementDescriptor desc = service.getDescriptor(mEditor.getProject(), fqcn);
+ Control item = createItem(parent, desc);
+
+ // Add control-click listener on custom view items to you can warp to
+ if (item instanceof IconTextItem) {
+ IconTextItem it = (IconTextItem) item;
+ it.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ if ((e.stateMask & SWT.MOD1) != 0) {
+ Hyperlinks.openJavaClass(mEditor.getProject(), fqcn);
+ }
+ }
+ });
+ }
+ }
+ }
+
/* package */ GraphicalEditorPart getEditor() {
return mEditor;
}
@@ -824,7 +910,8 @@ public class PaletteControl extends Composite {
// This doesn't apply to all, but doesn't seem to cause harm and makes for a
// better experience with text-oriented views like buttons and texts
- element.setAttributeNS(ANDROID_URI, ATTR_TEXT, mDesc.getUiName());
+ element.setAttributeNS(ANDROID_URI, ATTR_TEXT,
+ DescriptorsUtils.getBasename(mDesc.getUiName()));
// Is this a palette variation?
if (mDesc instanceof PaletteMetadataDescriptor) {
@@ -1107,4 +1194,18 @@ public class PaletteControl extends Composite {
menu.setLocation(x, y);
menu.setVisible(true);
}
+
+ private final class ViewFinderListener implements CustomViewFinder.Listener {
+ private final Composite mParent;
+
+ private ViewFinderListener(Composite parent) {
+ this.mParent = parent;
+ }
+
+ public void viewsUpdated(Collection<String> customViews,
+ Collection<String> thirdPartyViews) {
+ addCustomItems(mParent);
+ mParent.layout(true);
+ }
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/SelectionItem.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/SelectionItem.java
index 1e9eebe..01b9314 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/SelectionItem.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/SelectionItem.java
@@ -146,6 +146,11 @@ class SelectionItem {
* @return true if this selection item is a layout
*/
public boolean isLayout() {
- return mCanvasViewInfo.getUiViewNode().getDescriptor().hasChildren();
+ UiViewElementNode node = mCanvasViewInfo.getUiViewNode();
+ if (node != null) {
+ return node.getDescriptor().hasChildren();
+ } else {
+ return false;
+ }
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/SelectionManager.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/SelectionManager.java
index e34ecbf..be17b68 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/SelectionManager.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/SelectionManager.java
@@ -218,7 +218,7 @@ public class SelectionManager implements ISelectionProvider {
mSelections.add(createSelection(newVi));
changed = true;
}
- if (newVi.isInvisibleParent()) {
+ if (newVi.isInvisible()) {
redoLayout = true;
}
}
@@ -419,7 +419,7 @@ public class SelectionManager implements ISelectionProvider {
if (vi != null) {
mSelections.add(createSelection(vi));
- if (vi.isInvisibleParent()) {
+ if (vi.isInvisible()) {
redoLayout = true;
}
}
@@ -461,7 +461,7 @@ public class SelectionManager implements ISelectionProvider {
if (viewInfos != null) {
for (CanvasViewInfo viewInfo : viewInfos) {
mSelections.add(createSelection(viewInfo));
- if (viewInfo.isInvisibleParent()) {
+ if (viewInfo.isInvisible()) {
redoLayout = true;
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ViewHierarchy.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ViewHierarchy.java
index 16d8f43..8624cd3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ViewHierarchy.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ViewHierarchy.java
@@ -82,7 +82,7 @@ public class ViewHierarchy {
private boolean mIsResultValid;
/**
- * A list of invisible parents (see {@link CanvasViewInfo#isInvisibleParent()} for
+ * A list of invisible parents (see {@link CanvasViewInfo#isInvisible()} for
* details) in the current view hierarchy.
*/
private final List<CanvasViewInfo> mInvisibleParents = new ArrayList<CanvasViewInfo>();
@@ -293,7 +293,7 @@ public class ViewHierarchy {
return;
}
- if (vi.isInvisibleParent()) {
+ if (vi.isInvisible()) {
mInvisibleParents.add(vi);
} else if (invisibleNodes != null) {
UiViewElementNode key = vi.getUiViewNode();
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ChangeViewWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ChangeViewWizard.java
index 96d8408..1372006 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ChangeViewWizard.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ChangeViewWizard.java
@@ -19,6 +19,7 @@ package com.android.ide.eclipse.adt.internal.editors.layout.refactoring;
import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditor;
import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors;
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.editors.layout.gre.ViewMetadataRepository;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
@@ -122,7 +123,7 @@ class ChangeViewWizard extends VisualRefactoringWizard {
}
Pair<List<String>,List<String>> result =
- WrapInWizard.findViews(mProject, false);
+ CustomViewFinder.findViews(mProject, false);
List<String> customViews = result.getFirst();
List<String> thirdPartyViews = result.getSecond();
if (customViews.size() > 0) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/WrapInWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/WrapInWizard.java
index d9e746c..69df9a1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/WrapInWizard.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/WrapInWizard.java
@@ -22,13 +22,10 @@ import static com.android.ide.common.layout.LayoutConstants.FQCN_RADIO_BUTTON;
import static com.android.ide.common.layout.LayoutConstants.GESTURE_OVERLAY_VIEW;
import static com.android.ide.common.layout.LayoutConstants.RADIO_GROUP;
import static com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors.VIEW_INCLUDE;
-import static com.android.sdklib.SdkConstants.CLASS_VIEW;
-import static com.android.sdklib.SdkConstants.CLASS_VIEWGROUP;
-import static com.android.sdklib.SdkConstants.FN_FRAMEWORK_LIBRARY;
-import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditor;
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.editors.layout.gre.PaletteMetadataDescriptor;
import com.android.ide.eclipse.adt.internal.editors.layout.gre.ViewMetadataRepository;
import com.android.ide.eclipse.adt.internal.resources.ResourceNameValidator;
@@ -39,22 +36,6 @@ import com.android.sdklib.IAndroidTarget;
import com.android.util.Pair;
import org.eclipse.core.resources.IProject;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IPackageFragment;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaCore;
-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.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
@@ -68,8 +49,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
-@SuppressWarnings("restriction") // JDT model access for custom-view class lookup
-class WrapInWizard extends VisualRefactoringWizard {
+public class WrapInWizard extends VisualRefactoringWizard {
private static final String SEPARATOR_LABEL =
"----------------------------------------"; //$NON-NLS-1$
@@ -196,7 +176,7 @@ class WrapInWizard extends VisualRefactoringWizard {
classNames.add(Pair.<String,ViewElementDescriptor>of(null, null));
}
- Pair<List<String>,List<String>> result = findViews(project, true);
+ Pair<List<String>,List<String>> result = CustomViewFinder.findViews(project, true);
List<String> customViews = result.getFirst();
List<String> thirdPartyViews = result.getSecond();
if (customViews.size() > 0) {
@@ -284,66 +264,4 @@ class WrapInWizard extends VisualRefactoringWizard {
return classNames;
}
-
- /**
- * Returns a pair of view lists - the custom views and the 3rd-party views
- *
- * @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(IProject project, boolean layoutsOnly) {
- final List<String> customViews = new ArrayList<String>();
- final List<String> thirdPartyViews = new ArrayList<String>();
-
- SearchRequestor requestor = new SearchRequestor() {
- @Override
- public void acceptSearchMatch(SearchMatch match) throws CoreException {
- Object element = match.getElement();
-
- if (element instanceof ResolvedBinaryType) {
- ResolvedBinaryType bt = (ResolvedBinaryType) element;
- IPackageFragment fragment = bt.getPackageFragment();
- IPath path = fragment.getPath();
- String last = path.lastSegment();
- // Filter out android.jar stuff
- if (last.equals(FN_FRAMEWORK_LIBRARY)) {
- return;
- }
- String fqn = bt.getFullyQualifiedName();
- thirdPartyViews.add(fqn);
- } else if (element instanceof ResolvedSourceType) {
- ResolvedSourceType type = (ResolvedSourceType) element;
- String fqn = type.getFullyQualifiedName();
- // User custom view
- customViews.add(fqn);
- }
- }
- };
- try {
- IJavaProject javaProject = (IJavaProject) project.getNature(JavaCore.NATURE_ID);
- if (javaProject != null) {
- String className = layoutsOnly ? CLASS_VIEWGROUP : CLASS_VIEW;
- IType activityType = javaProject.findType(className);
- if (activityType != null) {
- IJavaSearchScope scope = SearchEngine.createHierarchyScope(activityType);
- SearchParticipant[] participants = new SearchParticipant[] {
- SearchEngine.getDefaultSearchParticipant()
- };
- int matchRule = SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE;
- SearchPattern pattern = SearchPattern.createPattern("*",
- IJavaSearchConstants.CLASS, IJavaSearchConstants.DECLARATIONS,
- matchRule);
- SearchEngine engine = new SearchEngine();
- engine.search(pattern, participants, scope, requestor,
- new NullProgressMonitor());
- }
- }
- } catch (CoreException e) {
- AdtPlugin.log(e, null);
- }
-
- return Pair.of(customViews, thirdPartyViews);
- }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtilsTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtilsTest.java
index bc0f36f..580fbaa 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtilsTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtilsTest.java
@@ -240,4 +240,10 @@ public class DescriptorsUtilsTest extends TestCase {
return super.findClass(name);
}
}
+
+ public void testGetBasename() {
+ assertEquals("Foo", DescriptorsUtils.getBasename("Foo"));
+ assertEquals("Foo", DescriptorsUtils.getBasename("foo.Foo"));
+ assertEquals("String", DescriptorsUtils.getBasename("java.util.String"));
+ }
}