aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/CustomViewDescriptorService.java621
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/LayoutDescriptors.java597
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/ViewElementDescriptor.java249
3 files changed, 0 insertions, 1467 deletions
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
deleted file mode 100644
index 6df6929a7..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/CustomViewDescriptorService.java
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
- * Copyright (C) 2008 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.descriptors;
-
-import static com.android.SdkConstants.ANDROID_NS_NAME_PREFIX;
-import static com.android.SdkConstants.ANDROID_URI;
-import static com.android.SdkConstants.AUTO_URI;
-import static com.android.SdkConstants.CLASS_VIEWGROUP;
-import static com.android.SdkConstants.URI_PREFIX;
-
-import com.android.annotations.NonNull;
-import com.android.annotations.Nullable;
-import com.android.ide.common.resources.ResourceFile;
-import com.android.ide.common.resources.ResourceItem;
-import com.android.ide.common.resources.platform.AttributeInfo;
-import com.android.ide.common.resources.platform.AttrsXmlParser;
-import com.android.ide.common.resources.platform.ViewClassInfo;
-import com.android.ide.common.resources.platform.ViewClassInfo.LayoutParamsInfo;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.AdtUtils;
-import com.android.ide.eclipse.adt.internal.editors.IconFactory;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo;
-import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
-import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
-import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
-import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
-import com.android.ide.eclipse.adt.internal.sdk.Sdk;
-import com.android.resources.ResourceType;
-import com.android.sdklib.IAndroidTarget;
-import com.google.common.collect.Maps;
-import com.google.common.collect.ObjectArrays;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.jdt.core.IClassFile;
-import org.eclipse.jdt.core.IJavaProject;
-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.swt.graphics.Image;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Service responsible for creating/managing {@link ViewElementDescriptor} objects for custom
- * View classes per project.
- * <p/>
- * The service provides an on-demand monitoring of custom classes to check for changes. Monitoring
- * starts once a request for an {@link ViewElementDescriptor} object has been done for a specific
- * class.
- * <p/>
- * The monitoring will notify a listener of any changes in the class triggering a change in its
- * associated {@link ViewElementDescriptor} object.
- * <p/>
- * If the custom class does not exist, no monitoring is put in place to avoid having to listen
- * to all class changes in the projects.
- */
-public final class CustomViewDescriptorService {
-
- private static CustomViewDescriptorService sThis = new CustomViewDescriptorService();
-
- /**
- * Map where keys are the project, and values are another map containing all the known
- * custom View class for this project. The custom View class are stored in a map
- * where the keys are the fully qualified class name, and the values are their associated
- * {@link ViewElementDescriptor}.
- */
- private HashMap<IProject, HashMap<String, ViewElementDescriptor>> mCustomDescriptorMap =
- new HashMap<IProject, HashMap<String, ViewElementDescriptor>>();
-
- /**
- * TODO will be used to update the ViewElementDescriptor of the custom view when it
- * is modified (either the class itself or its attributes.xml)
- */
- @SuppressWarnings("unused")
- private ICustomViewDescriptorListener mListener;
-
- /**
- * Classes which implements this interface provide a method that deal with modifications
- * in custom View class triggering a change in its associated {@link ViewClassInfo} object.
- */
- public interface ICustomViewDescriptorListener {
- /**
- * Sent when a custom View class has changed and
- * its {@link ViewElementDescriptor} was modified.
- *
- * @param project the project containing the class.
- * @param className the fully qualified class name.
- * @param descriptor the updated ElementDescriptor.
- */
- public void updatedClassInfo(IProject project,
- String className,
- ViewElementDescriptor descriptor);
- }
-
- /**
- * Returns the singleton instance of {@link CustomViewDescriptorService}.
- */
- public static CustomViewDescriptorService getInstance() {
- return sThis;
- }
-
- /**
- * Sets the listener receiving custom View class modification notifications.
- * @param listener the listener to receive the notifications.
- *
- * TODO will be used to update the ViewElementDescriptor of the custom view when it
- * is modified (either the class itself or its attributes.xml)
- */
- public void setListener(ICustomViewDescriptorListener listener) {
- mListener = listener;
- }
-
- /**
- * Returns the {@link ViewElementDescriptor} for a particular project/class when the
- * fully qualified class name actually matches a class from the given project.
- * <p/>
- * Custom descriptors are created as needed.
- * <p/>
- * If it is the first time the {@link ViewElementDescriptor} is requested, the method
- * will check that the specified class is in fact a custom View class. Once this is
- * established, a monitoring for that particular class is initiated. Any change will
- * trigger a notification to the {@link ICustomViewDescriptorListener}.
- *
- * @param project the project containing the class.
- * @param fqcn the fully qualified name of the class.
- * @return a {@link ViewElementDescriptor} or <code>null</code> if the class was not
- * a custom View class.
- */
- public ViewElementDescriptor getDescriptor(IProject project, String fqcn) {
- // look in the map first
- synchronized (mCustomDescriptorMap) {
- HashMap<String, ViewElementDescriptor> map = mCustomDescriptorMap.get(project);
-
- if (map != null) {
- ViewElementDescriptor descriptor = map.get(fqcn);
- if (descriptor != null) {
- return descriptor;
- }
- }
-
- // if we step here, it looks like we haven't created it yet.
- // First lets check this is in fact a valid type in the project
-
- try {
- // We expect the project to be both opened and of java type (since it's an android
- // project), so we can create a IJavaProject object from our IProject.
- IJavaProject javaProject = JavaCore.create(project);
-
- // replace $ by . in the class name
- String javaClassName = fqcn.replaceAll("\\$", "\\."); //$NON-NLS-1$ //$NON-NLS-2$
-
- // look for the IType object for this class
- IType type = javaProject.findType(javaClassName);
- if (type != null && type.exists()) {
- // the type exists. Let's get the parent class and its ViewClassInfo.
-
- // get the type hierarchy
- ITypeHierarchy hierarchy = type.newSupertypeHierarchy(
- new NullProgressMonitor());
-
- ViewElementDescriptor parentDescriptor = createViewDescriptor(
- hierarchy.getSuperclass(type), project, hierarchy);
-
- if (parentDescriptor != null) {
- // we have a valid parent, lets create a new ViewElementDescriptor.
- List<AttributeDescriptor> attrList = new ArrayList<AttributeDescriptor>();
- List<AttributeDescriptor> paramList = new ArrayList<AttributeDescriptor>();
- Map<ResourceFile, Long> files = findCustomDescriptors(project, type,
- attrList, paramList);
-
- AttributeDescriptor[] attributes =
- getAttributeDescriptor(type, parentDescriptor);
- if (!attrList.isEmpty()) {
- attributes = join(attrList, attributes);
- }
- AttributeDescriptor[] layoutAttributes =
- getLayoutAttributeDescriptors(type, parentDescriptor);
- if (!paramList.isEmpty()) {
- layoutAttributes = join(paramList, layoutAttributes);
- }
- String name = DescriptorsUtils.getBasename(fqcn);
- ViewElementDescriptor descriptor = new CustomViewDescriptor(name, fqcn,
- attributes,
- layoutAttributes,
- parentDescriptor.getChildren(),
- project, files);
- descriptor.setSuperClass(parentDescriptor);
-
- synchronized (mCustomDescriptorMap) {
- map = mCustomDescriptorMap.get(project);
- if (map == null) {
- map = new HashMap<String, ViewElementDescriptor>();
- mCustomDescriptorMap.put(project, map);
- }
-
- map.put(fqcn, descriptor);
- }
-
- //TODO setup listener on this resource change.
-
- return descriptor;
- }
- }
- } catch (JavaModelException e) {
- // there was an error accessing any of the IType, we'll just return null;
- }
- }
-
- return null;
- }
-
- private static AttributeDescriptor[] join(
- @NonNull List<AttributeDescriptor> attributeList,
- @NonNull AttributeDescriptor[] attributes) {
- if (!attributeList.isEmpty()) {
- return ObjectArrays.concat(
- attributeList.toArray(new AttributeDescriptor[attributeList.size()]),
- attributes,
- AttributeDescriptor.class);
- } else {
- return attributes;
- }
-
- }
-
- /** Cache used by {@link #getParser(ResourceFile)} */
- private Map<ResourceFile, AttrsXmlParser> mParserCache;
-
- private AttrsXmlParser getParser(ResourceFile file) {
- if (mParserCache == null) {
- mParserCache = new HashMap<ResourceFile, AttrsXmlParser>();
- }
-
- AttrsXmlParser parser = mParserCache.get(file);
- if (parser == null) {
- parser = new AttrsXmlParser(
- file.getFile().getOsLocation(),
- AdtPlugin.getDefault(), 20);
- parser.preload();
- mParserCache.put(file, parser);
- }
-
- return parser;
- }
-
- /** Compute/find the styleable resources for the given type, if possible */
- private Map<ResourceFile, Long> findCustomDescriptors(
- IProject project,
- IType type,
- List<AttributeDescriptor> customAttributes,
- List<AttributeDescriptor> customLayoutAttributes) {
- // Look up the project where the type is declared (could be a library project;
- // we cannot use type.getJavaProject().getProject())
- IProject library = getProjectDeclaringType(type);
- if (library == null) {
- library = project;
- }
-
- String className = type.getElementName();
- Set<ResourceFile> resourceFiles = findAttrsFiles(library, className);
- if (resourceFiles != null && resourceFiles.size() > 0) {
- String appUri = getAppResUri(project);
- Map<ResourceFile, Long> timestamps =
- Maps.newHashMapWithExpectedSize(resourceFiles.size());
- for (ResourceFile file : resourceFiles) {
- AttrsXmlParser attrsXmlParser = getParser(file);
- String fqcn = type.getFullyQualifiedName();
-
- // Attributes
- ViewClassInfo classInfo = new ViewClassInfo(true, fqcn, className);
- attrsXmlParser.loadViewAttributes(classInfo);
- appendAttributes(customAttributes, classInfo.getAttributes(), appUri);
-
- // Layout params
- LayoutParamsInfo layoutInfo = new ViewClassInfo.LayoutParamsInfo(
- classInfo, "Layout", null /*superClassInfo*/); //$NON-NLS-1$
- attrsXmlParser.loadLayoutParamsAttributes(layoutInfo);
- appendAttributes(customLayoutAttributes, layoutInfo.getAttributes(), appUri);
-
- timestamps.put(file, file.getFile().getModificationStamp());
- }
-
- return timestamps;
- }
-
- return null;
- }
-
- /**
- * Finds the set of XML files (if any) in the given library declaring
- * attributes for the given class name
- */
- @Nullable
- private static Set<ResourceFile> findAttrsFiles(IProject library, String className) {
- Set<ResourceFile> resourceFiles = null;
- ResourceManager manager = ResourceManager.getInstance();
- ProjectResources resources = manager.getProjectResources(library);
- if (resources != null) {
- Collection<ResourceItem> items =
- resources.getResourceItemsOfType(ResourceType.DECLARE_STYLEABLE);
- for (ResourceItem item : items) {
- String viewName = item.getName();
- if (viewName.equals(className)
- || (viewName.startsWith(className)
- && viewName.equals(className + "_Layout"))) { //$NON-NLS-1$
- if (resourceFiles == null) {
- resourceFiles = new HashSet<ResourceFile>();
- }
- resourceFiles.addAll(item.getSourceFileList());
- }
- }
- }
- return resourceFiles;
- }
-
- /**
- * Find the project containing this type declaration. We cannot use
- * {@link IType#getJavaProject()} since that will return the including
- * project and we're after the library project such that we can find the
- * attrs.xml file in the same project.
- */
- @Nullable
- private static IProject getProjectDeclaringType(IType type) {
- IClassFile classFile = type.getClassFile();
- if (classFile != null) {
- IPath path = classFile.getPath();
- IWorkspaceRoot workspace = ResourcesPlugin.getWorkspace().getRoot();
- IResource resource;
- if (path.isAbsolute()) {
- resource = AdtUtils.fileToResource(path.toFile());
- } else {
- resource = workspace.findMember(path);
- }
- if (resource != null && resource.getProject() != null) {
- return resource.getProject();
- }
- }
-
- return null;
- }
-
- /** Returns the name space to use for application attributes */
- private static String getAppResUri(IProject project) {
- String appResource;
- ProjectState projectState = Sdk.getProjectState(project);
- if (projectState != null && projectState.isLibrary()) {
- appResource = AUTO_URI;
- } else {
- ManifestInfo manifestInfo = ManifestInfo.get(project);
- appResource = URI_PREFIX + manifestInfo.getPackage();
- }
- return appResource;
- }
-
-
- /** Append the {@link AttributeInfo} objects converted {@link AttributeDescriptor}
- * objects into the given attribute list.
- * <p>
- * This is nearly identical to
- * {@link DescriptorsUtils#appendAttribute(List, String, String, AttributeInfo, boolean, Map)}
- * but it handles namespace declarations in the attrs.xml file where the android:
- * namespace is included in the names.
- */
- private static void appendAttributes(List<AttributeDescriptor> attributes,
- AttributeInfo[] attributeInfos, String appResource) {
- // Custom attributes
- for (AttributeInfo info : attributeInfos) {
- String nsUri;
- if (info.getName().startsWith(ANDROID_NS_NAME_PREFIX)) {
- info.setName(info.getName().substring(ANDROID_NS_NAME_PREFIX.length()));
- nsUri = ANDROID_URI;
- } else {
- nsUri = appResource;
- }
-
- DescriptorsUtils.appendAttribute(attributes,
- null /*elementXmlName*/, nsUri, info, false /*required*/,
- null /*overrides*/);
- }
- }
-
- /**
- * Computes (if needed) and returns the {@link ViewElementDescriptor} for the specified type.
- *
- * @return A {@link ViewElementDescriptor} or null if type or typeHierarchy is null.
- */
- private ViewElementDescriptor createViewDescriptor(IType type, IProject project,
- ITypeHierarchy typeHierarchy) {
- // check if the type is a built-in View class.
- List<ViewElementDescriptor> builtInList = null;
-
- // give up if there's no type
- if (type == null) {
- return null;
- }
-
- String fqcn = type.getFullyQualifiedName();
-
- Sdk currentSdk = Sdk.getCurrent();
- if (currentSdk != null) {
- IAndroidTarget target = currentSdk.getTarget(project);
- if (target != null) {
- AndroidTargetData data = currentSdk.getTargetData(target);
- if (data != null) {
- LayoutDescriptors descriptors = data.getLayoutDescriptors();
- ViewElementDescriptor d = descriptors.findDescriptorByClass(fqcn);
- if (d != null) {
- return d;
- }
- builtInList = descriptors.getViewDescriptors();
- }
- }
- }
-
- // it's not a built-in class? Lets look if the superclass is built-in
- // give up if there's no type
- if (typeHierarchy == null) {
- return null;
- }
-
- IType parentType = typeHierarchy.getSuperclass(type);
- if (parentType != null) {
- ViewElementDescriptor parentDescriptor = createViewDescriptor(parentType, project,
- typeHierarchy);
-
- if (parentDescriptor != null) {
- // parent class is a valid View class with a descriptor, so we create one
- // for this class.
- String name = DescriptorsUtils.getBasename(fqcn);
- // A custom view accepts children if its parent descriptor also does.
- // The only exception to this is ViewGroup, which accepts children even though
- // its parent does not.
- boolean isViewGroup = fqcn.equals(CLASS_VIEWGROUP);
- boolean hasChildren = isViewGroup || parentDescriptor.hasChildren();
- ViewElementDescriptor[] children = null;
- if (hasChildren && builtInList != null) {
- // We can't figure out what the allowable children are by just
- // looking at the class, so assume any View is valid
- children = builtInList.toArray(new ViewElementDescriptor[builtInList.size()]);
- }
- ViewElementDescriptor descriptor = new CustomViewDescriptor(name, fqcn,
- getAttributeDescriptor(type, parentDescriptor),
- getLayoutAttributeDescriptors(type, parentDescriptor),
- children, project, null);
- descriptor.setSuperClass(parentDescriptor);
-
- // add it to the map
- synchronized (mCustomDescriptorMap) {
- HashMap<String, ViewElementDescriptor> map = mCustomDescriptorMap.get(project);
-
- if (map == null) {
- map = new HashMap<String, ViewElementDescriptor>();
- mCustomDescriptorMap.put(project, map);
- }
-
- map.put(fqcn, descriptor);
-
- }
-
- //TODO setup listener on this resource change.
-
- return descriptor;
- }
- }
-
- // class is neither a built-in view class, nor extend one. return null.
- return null;
- }
-
- /**
- * Returns the array of {@link AttributeDescriptor} for the specified {@link IType}.
- * <p/>
- * The array should contain the descriptor for this type and all its supertypes.
- *
- * @param type the type for which the {@link AttributeDescriptor} are returned.
- * @param parentDescriptor the {@link ViewElementDescriptor} of the direct superclass.
- */
- private static AttributeDescriptor[] getAttributeDescriptor(IType type,
- ViewElementDescriptor parentDescriptor) {
- // TODO add the class attribute descriptors to the parent descriptors.
- return parentDescriptor.getAttributes();
- }
-
- private static AttributeDescriptor[] getLayoutAttributeDescriptors(IType type,
- ViewElementDescriptor parentDescriptor) {
- return parentDescriptor.getLayoutAttributes();
- }
-
- private class CustomViewDescriptor extends ViewElementDescriptor {
- private Map<ResourceFile, Long> mTimeStamps;
- private IProject mProject;
-
- public CustomViewDescriptor(String name, String fqcn, AttributeDescriptor[] attributes,
- AttributeDescriptor[] layoutAttributes,
- ElementDescriptor[] children, IProject project,
- Map<ResourceFile, Long> timestamps) {
- super(
- fqcn, // xml name
- name, // ui name
- fqcn, // full class name
- fqcn, // tooltip
- null, // sdk_url
- attributes,
- layoutAttributes,
- children,
- false // mandatory
- );
- mTimeStamps = timestamps;
- mProject = project;
- }
-
- @Override
- public Image getGenericIcon() {
- IconFactory iconFactory = IconFactory.getInstance();
-
- int index = mXmlName.lastIndexOf('.');
- if (index != -1) {
- return iconFactory.getIcon(mXmlName.substring(index + 1),
- "customView"); //$NON-NLS-1$
- }
-
- return iconFactory.getIcon("customView"); //$NON-NLS-1$
- }
-
- @Override
- public boolean syncAttributes() {
- // Check if any of the descriptors
- if (mTimeStamps != null) {
- // Prevent checking actual file timestamps too frequently on rapid burst calls
- long now = System.currentTimeMillis();
- if (now - sLastCheck < 1000) {
- return true;
- }
- sLastCheck = now;
-
- // Check whether the resource files (typically just one) which defined
- // custom attributes for this custom view have changed, and if so,
- // refresh the attribute descriptors.
- // This doesn't work the cases where you add descriptors for a custom
- // view after using it, or add attributes in a separate file, but those
- // scenarios aren't quite as common (and would require a bit more expensive
- // analysis.)
- for (Map.Entry<ResourceFile, Long> entry : mTimeStamps.entrySet()) {
- ResourceFile file = entry.getKey();
- Long timestamp = entry.getValue();
- boolean recompute = false;
- if (file.getFile().getModificationStamp() > timestamp.longValue()) {
- // One or more attributes changed: recompute
- recompute = true;
- mParserCache.remove(file);
- }
-
- if (recompute) {
- IJavaProject javaProject = JavaCore.create(mProject);
- String fqcn = getFullClassName();
- IType type = null;
- try {
- type = javaProject.findType(fqcn);
- } catch (CoreException e) {
- AdtPlugin.log(e, null);
- }
- if (type == null || !type.exists()) {
- return true;
- }
-
- List<AttributeDescriptor> attrList = new ArrayList<AttributeDescriptor>();
- List<AttributeDescriptor> paramList = new ArrayList<AttributeDescriptor>();
-
- mTimeStamps = findCustomDescriptors(mProject, type, attrList, paramList);
-
- ViewElementDescriptor parentDescriptor = getSuperClassDesc();
- AttributeDescriptor[] attributes =
- getAttributeDescriptor(type, parentDescriptor);
- if (!attrList.isEmpty()) {
- attributes = join(attrList, attributes);
- }
- attributes = attrList.toArray(new AttributeDescriptor[attrList.size()]);
- setAttributes(attributes);
-
- return false;
- }
- }
- }
-
- return true;
- }
- }
-
- /** Timestamp of the most recent {@link CustomViewDescriptor#syncAttributes} check */
- private static long sLastCheck;
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/LayoutDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/LayoutDescriptors.java
deleted file mode 100644
index 7b2fe84f0..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/LayoutDescriptors.java
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- * Copyright (C) 2008 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.descriptors;
-
-import static com.android.SdkConstants.ANDROID_URI;
-import static com.android.SdkConstants.ATTR_CLASS;
-import static com.android.SdkConstants.ATTR_LAYOUT;
-import static com.android.SdkConstants.ATTR_NAME;
-import static com.android.SdkConstants.ATTR_TAG;
-import static com.android.SdkConstants.CLASS_VIEW;
-import static com.android.SdkConstants.FQCN_GESTURE_OVERLAY_VIEW;
-import static com.android.SdkConstants.REQUEST_FOCUS;
-import static com.android.SdkConstants.VIEW_FRAGMENT;
-import static com.android.SdkConstants.VIEW_INCLUDE;
-import static com.android.SdkConstants.VIEW_MERGE;
-import static com.android.SdkConstants.VIEW_TAG;
-
-import com.android.SdkConstants;
-import com.android.ide.common.api.IAttributeInfo.Format;
-import com.android.ide.common.resources.platform.AttributeInfo;
-import com.android.ide.common.resources.platform.DeclareStyleableInfo;
-import com.android.ide.common.resources.platform.ViewClassInfo;
-import com.android.ide.common.resources.platform.ViewClassInfo.LayoutParamsInfo;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.DocumentDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.IDescriptorProvider;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.TextAttributeDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.ClassAttributeDescriptor;
-import com.android.sdklib.IAndroidTarget;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-
-/**
- * Complete description of the layout structure.
- */
-public final class LayoutDescriptors implements IDescriptorProvider {
- /** The document descriptor. Contains all layouts and views linked together. */
- private DocumentDescriptor mRootDescriptor =
- new DocumentDescriptor("layout_doc", null); //$NON-NLS-1$
-
- /** The list of all known ViewLayout descriptors. */
- private List<ViewElementDescriptor> mLayoutDescriptors = Collections.emptyList();
-
- /** Read-Only list of View Descriptors. */
- private List<ViewElementDescriptor> mROLayoutDescriptors;
-
- /** The list of all known View (not ViewLayout) descriptors. */
- private List<ViewElementDescriptor> mViewDescriptors = Collections.emptyList();
-
- /** Read-Only list of View Descriptors. */
- private List<ViewElementDescriptor> mROViewDescriptors;
-
- /** The descriptor matching android.view.View. */
- private ViewElementDescriptor mBaseViewDescriptor;
-
- /** Map from view full class name to view descriptor */
- private Map<String, ViewElementDescriptor> mFqcnToDescriptor =
- // As of 3.1 there are 58 items in this map
- new HashMap<String, ViewElementDescriptor>(80);
-
- /** Returns the document descriptor. Contains all layouts and views linked together. */
- @Override
- public DocumentDescriptor getDescriptor() {
- return mRootDescriptor;
- }
-
- /** Returns the read-only list of all known ViewLayout descriptors. */
- public List<ViewElementDescriptor> getLayoutDescriptors() {
- return mROLayoutDescriptors;
- }
-
- /** Returns the read-only list of all known View (not ViewLayout) descriptors. */
- public List<ViewElementDescriptor> getViewDescriptors() {
- return mROViewDescriptors;
- }
-
- @Override
- public ElementDescriptor[] getRootElementDescriptors() {
- return mRootDescriptor.getChildren();
- }
-
- /**
- * Returns the descriptor matching android.view.View, which is guaranteed
- * to be a {@link ViewElementDescriptor}.
- */
- public ViewElementDescriptor getBaseViewDescriptor() {
- if (mBaseViewDescriptor == null) {
- mBaseViewDescriptor = findDescriptorByClass(SdkConstants.CLASS_VIEW);
- }
- return mBaseViewDescriptor;
- }
-
- /**
- * Updates the document descriptor.
- * <p/>
- * It first computes the new children of the descriptor and then update them
- * all at once.
- * <p/>
- * TODO: differentiate groups from views in the tree UI? => rely on icons
- * <p/>
- *
- * @param views The list of views in the framework.
- * @param layouts The list of layouts in the framework.
- * @param styleMap A map from style names to style information provided by the SDK
- * @param target The android target being initialized
- */
- public synchronized void updateDescriptors(ViewClassInfo[] views, ViewClassInfo[] layouts,
- Map<String, DeclareStyleableInfo> styleMap, IAndroidTarget target) {
-
- // This map links every ViewClassInfo to the ElementDescriptor we created.
- // It is filled by convertView() and used later to fix the super-class hierarchy.
- HashMap<ViewClassInfo, ViewElementDescriptor> infoDescMap =
- new HashMap<ViewClassInfo, ViewElementDescriptor>();
-
- ArrayList<ViewElementDescriptor> newViews = new ArrayList<ViewElementDescriptor>(40);
- if (views != null) {
- for (ViewClassInfo info : views) {
- ViewElementDescriptor desc = convertView(info, infoDescMap);
- newViews.add(desc);
- mFqcnToDescriptor.put(desc.getFullClassName(), desc);
- }
- }
-
- // Create <include> as a synthetic regular view.
- // Note: ViewStub is already described by attrs.xml
- insertInclude(newViews);
-
- List<ViewElementDescriptor> newLayouts = new ArrayList<ViewElementDescriptor>(30);
- if (layouts != null) {
- for (ViewClassInfo info : layouts) {
- ViewElementDescriptor desc = convertView(info, infoDescMap);
- newLayouts.add(desc);
- mFqcnToDescriptor.put(desc.getFullClassName(), desc);
- }
- }
-
- // Find View and inherit all its layout attributes
- AttributeDescriptor[] frameLayoutAttrs = findViewLayoutAttributes(
- SdkConstants.CLASS_FRAMELAYOUT);
-
- if (target.getVersion().getApiLevel() >= 4) {
- ViewElementDescriptor fragmentTag = createFragment(frameLayoutAttrs, styleMap);
- newViews.add(fragmentTag);
- }
-
- List<ElementDescriptor> newDescriptors = new ArrayList<ElementDescriptor>(80);
- newDescriptors.addAll(newLayouts);
- newDescriptors.addAll(newViews);
-
- ViewElementDescriptor viewTag = createViewTag(frameLayoutAttrs);
- newViews.add(viewTag);
- newDescriptors.add(viewTag);
-
- ViewElementDescriptor requestFocus = createRequestFocus();
- newViews.add(requestFocus);
- newDescriptors.add(requestFocus);
-
- // Link all layouts to everything else here.. recursively
- for (ViewElementDescriptor layoutDesc : newLayouts) {
- layoutDesc.setChildren(newDescriptors);
- }
-
- // The gesture overlay descriptor is really a layout but not included in the layouts list
- // so handle it specially
- ViewElementDescriptor gestureView = findDescriptorByClass(FQCN_GESTURE_OVERLAY_VIEW);
- if (gestureView != null) {
- gestureView.setChildren(newDescriptors);
- // Inherit layout attributes from FrameLayout
- gestureView.setLayoutAttributes(frameLayoutAttrs);
- }
-
- fixSuperClasses(infoDescMap);
-
- // The <merge> tag can only be a root tag, so it is added at the end.
- // It gets everything else as children but it is not made a child itself.
- ViewElementDescriptor mergeTag = createMerge(frameLayoutAttrs);
- mergeTag.setChildren(newDescriptors); // mergeTag makes a copy of the list
- newDescriptors.add(mergeTag);
- newLayouts.add(mergeTag);
-
- // Sort palette contents
- Collections.sort(newViews);
- Collections.sort(newLayouts);
-
- mViewDescriptors = newViews;
- mLayoutDescriptors = newLayouts;
- mRootDescriptor.setChildren(newDescriptors);
-
- mBaseViewDescriptor = null;
- mROLayoutDescriptors = Collections.unmodifiableList(mLayoutDescriptors);
- mROViewDescriptors = Collections.unmodifiableList(mViewDescriptors);
- }
-
- /**
- * Creates an element descriptor from a given {@link ViewClassInfo}.
- *
- * @param info The {@link ViewClassInfo} to convert into a new {@link ViewElementDescriptor}.
- * @param infoDescMap This map links every ViewClassInfo to the ElementDescriptor it created.
- * It is filled by here and used later to fix the super-class hierarchy.
- */
- private ViewElementDescriptor convertView(
- ViewClassInfo info,
- HashMap<ViewClassInfo, ViewElementDescriptor> infoDescMap) {
- String xmlName = info.getShortClassName();
- String uiName = xmlName;
- String fqcn = info.getFullClassName();
- if (ViewElementDescriptor.viewNeedsPackage(fqcn)) {
- xmlName = fqcn;
- }
- String tooltip = info.getJavaDoc();
-
- // Average is around 90, max (in 3.2) is 145
- ArrayList<AttributeDescriptor> attributes = new ArrayList<AttributeDescriptor>(120);
-
- // All views and groups have an implicit "style" attribute which is a reference.
- AttributeInfo styleInfo = new AttributeInfo(
- "style", //$NON-NLS-1$ xmlLocalName
- Format.REFERENCE_SET);
- styleInfo.setJavaDoc("A reference to a custom style"); //tooltip
- DescriptorsUtils.appendAttribute(attributes,
- "style", //$NON-NLS-1$
- null, //nsUri
- styleInfo,
- false, //required
- null); // overrides
- styleInfo.setDefinedBy(SdkConstants.CLASS_VIEW);
-
- // Process all View attributes
- DescriptorsUtils.appendAttributes(attributes,
- null, // elementName
- ANDROID_URI,
- info.getAttributes(),
- null, // requiredAttributes
- null /* overrides */);
-
- List<String> attributeSources = new ArrayList<String>();
- if (info.getAttributes() != null && info.getAttributes().length > 0) {
- attributeSources.add(fqcn);
- }
-
- for (ViewClassInfo link = info.getSuperClass();
- link != null;
- link = link.getSuperClass()) {
- AttributeInfo[] attrList = link.getAttributes();
- if (attrList.length > 0) {
- attributeSources.add(link.getFullClassName());
- DescriptorsUtils.appendAttributes(attributes,
- null, // elementName
- ANDROID_URI,
- attrList,
- null, // requiredAttributes
- null /* overrides */);
- }
- }
-
- // Process all LayoutParams attributes
- ArrayList<AttributeDescriptor> layoutAttributes = new ArrayList<AttributeDescriptor>();
- LayoutParamsInfo layoutParams = info.getLayoutData();
-
- for(; layoutParams != null; layoutParams = layoutParams.getSuperClass()) {
- for (AttributeInfo attrInfo : layoutParams.getAttributes()) {
- if (DescriptorsUtils.containsAttribute(layoutAttributes,
- ANDROID_URI, attrInfo)) {
- continue;
- }
- DescriptorsUtils.appendAttribute(layoutAttributes,
- null, // elementName
- ANDROID_URI,
- attrInfo,
- false, // required
- null /* overrides */);
- }
- }
-
- ViewElementDescriptor desc = new ViewElementDescriptor(
- xmlName,
- uiName,
- fqcn,
- tooltip,
- null, // sdk_url
- attributes.toArray(new AttributeDescriptor[attributes.size()]),
- layoutAttributes.toArray(new AttributeDescriptor[layoutAttributes.size()]),
- null, // children
- false /* mandatory */);
- desc.setAttributeSources(Collections.unmodifiableList(attributeSources));
- infoDescMap.put(info, desc);
- return desc;
- }
-
- /**
- * Creates a new {@code <include>} descriptor and adds it to the list of view descriptors.
- *
- * @param knownViews A list of view descriptors being populated. Also used to find the
- * View descriptor and extract its layout attributes.
- */
- private void insertInclude(List<ViewElementDescriptor> knownViews) {
- String xmlName = VIEW_INCLUDE;
-
- // Create the include custom attributes
- ArrayList<AttributeDescriptor> attributes = new ArrayList<AttributeDescriptor>();
-
- // Find View and inherit all its layout attributes
- AttributeDescriptor[] viewLayoutAttribs;
- AttributeDescriptor[] viewAttributes = null;
- ViewElementDescriptor viewDesc = findDescriptorByClass(SdkConstants.CLASS_VIEW);
- if (viewDesc != null) {
- viewAttributes = viewDesc.getAttributes();
- attributes = new ArrayList<AttributeDescriptor>(viewAttributes.length + 1);
- viewLayoutAttribs = viewDesc.getLayoutAttributes();
- } else {
- viewLayoutAttribs = new AttributeDescriptor[0];
- }
-
- // Note that the "layout" attribute does NOT have the Android namespace
- DescriptorsUtils.appendAttribute(attributes,
- null, //elementXmlName
- null, //nsUri
- new AttributeInfo(
- ATTR_LAYOUT,
- Format.REFERENCE_SET ),
- true, //required
- null); //overrides
-
- if (viewAttributes != null) {
- for (AttributeDescriptor descriptor : viewAttributes) {
- attributes.add(descriptor);
- }
- }
-
- // Create the include descriptor
- ViewElementDescriptor desc = new ViewElementDescriptor(xmlName,
- xmlName, // ui_name
- VIEW_INCLUDE, // "class name"; the GLE only treats this as an element tag
- "Lets you statically include XML layouts inside other XML layouts.", // tooltip
- null, // sdk_url
- attributes.toArray(new AttributeDescriptor[attributes.size()]),
- viewLayoutAttribs, // layout attributes
- null, // children
- false /* mandatory */);
-
- knownViews.add(desc);
- }
-
- /**
- * Creates and returns a new {@code <merge>} descriptor.
- * @param viewLayoutAttribs The layout attributes to use for the new descriptor
- */
- private ViewElementDescriptor createMerge(AttributeDescriptor[] viewLayoutAttribs) {
- String xmlName = VIEW_MERGE;
-
- // Create the include descriptor
- ViewElementDescriptor desc = new ViewElementDescriptor(xmlName,
- xmlName, // ui_name
- VIEW_MERGE, // "class name"; the GLE only treats this as an element tag
- "A root tag useful for XML layouts inflated using a ViewStub.", // tooltip
- null, // sdk_url
- null, // attributes
- viewLayoutAttribs, // layout attributes
- null, // children
- false /* mandatory */);
-
- return desc;
- }
-
- /**
- * Creates and returns a new {@code <fragment>} descriptor.
- * @param viewLayoutAttribs The layout attributes to use for the new descriptor
- * @param styleMap The style map provided by the SDK
- */
- private ViewElementDescriptor createFragment(AttributeDescriptor[] viewLayoutAttribs,
- Map<String, DeclareStyleableInfo> styleMap) {
- String xmlName = VIEW_FRAGMENT;
- final ViewElementDescriptor descriptor;
-
- // First try to create the descriptor from metadata in attrs.xml:
- DeclareStyleableInfo style = styleMap.get("Fragment"); //$NON-NLS-1$
- String fragmentTooltip =
- "A Fragment is a piece of an application's user interface or behavior that "
- + "can be placed in an Activity";
- String sdkUrl = "http://developer.android.com/guide/topics/fundamentals/fragments.html";
- TextAttributeDescriptor classAttribute = new ClassAttributeDescriptor(
- // Should accept both CLASS_V4_FRAGMENT and CLASS_FRAGMENT
- null /*superClassName*/,
- ATTR_CLASS, null /* namespace */,
- new AttributeInfo(ATTR_CLASS, Format.STRING_SET),
- true /*mandatory*/)
- .setTooltip("Supply the name of the fragment class to instantiate");
-
- if (style != null) {
- descriptor = new ViewElementDescriptor(
- VIEW_FRAGMENT, VIEW_FRAGMENT, VIEW_FRAGMENT,
- fragmentTooltip, // tooltip
- sdkUrl, //,
- null /* attributes */,
- viewLayoutAttribs, // layout attributes
- null /*childrenElements*/,
- false /*mandatory*/);
- ArrayList<AttributeDescriptor> descs = new ArrayList<AttributeDescriptor>();
- // The class attribute is not included in the attrs.xml
- descs.add(classAttribute);
- DescriptorsUtils.appendAttributes(descs,
- null, // elementName
- ANDROID_URI,
- style.getAttributes(),
- null, // requiredAttributes
- null); // overrides
- //descriptor.setTooltip(style.getJavaDoc());
- descriptor.setAttributes(descs.toArray(new AttributeDescriptor[descs.size()]));
- } else {
- // The above will only work on API 11 and up. However, fragments are *also* available
- // on older platforms, via the fragment support library, so add in a manual
- // entry if necessary.
- descriptor = new ViewElementDescriptor(xmlName,
- xmlName, // ui_name
- xmlName, // "class name"; the GLE only treats this as an element tag
- fragmentTooltip,
- sdkUrl,
- new AttributeDescriptor[] {
- new ClassAttributeDescriptor(
- null /*superClassName*/,
- ATTR_NAME, ANDROID_URI,
- new AttributeInfo(ATTR_NAME, Format.STRING_SET),
- true /*mandatory*/)
- .setTooltip("Supply the name of the fragment class to instantiate"),
- classAttribute,
- new ClassAttributeDescriptor(
- null /*superClassName*/,
- ATTR_TAG, ANDROID_URI,
- new AttributeInfo(ATTR_TAG, Format.STRING_SET),
- true /*mandatory*/)
- .setTooltip("Supply a tag for the top-level view containing a String"),
- }, // attributes
- viewLayoutAttribs, // layout attributes
- null, // children
- false /* mandatory */);
- }
-
- return descriptor;
- }
-
- /**
- * Creates and returns a new {@code <view>} descriptor.
- * @param viewLayoutAttribs The layout attributes to use for the new descriptor
- * @param styleMap The style map provided by the SDK
- */
- private ViewElementDescriptor createViewTag(AttributeDescriptor[] viewLayoutAttribs) {
- String xmlName = VIEW_TAG;
-
- TextAttributeDescriptor classAttribute = new ClassAttributeDescriptor(
- CLASS_VIEW,
- ATTR_CLASS, null /* namespace */,
- new AttributeInfo(ATTR_CLASS, Format.STRING_SET),
- true /*mandatory*/)
- .setTooltip("Supply the name of the view class to instantiate");
-
- // Create the include descriptor
- ViewElementDescriptor desc = new ViewElementDescriptor(xmlName,
- xmlName, // ui_name
- xmlName, // "class name"; the GLE only treats this as an element tag
- "A view tag whose class attribute names the class to be instantiated", // tooltip
- null, // sdk_url
- new AttributeDescriptor[] { // attributes
- classAttribute
- },
- viewLayoutAttribs, // layout attributes
- null, // children
- false /* mandatory */);
-
- return desc;
- }
-
- /**
- * Creates and returns a new {@code <requestFocus>} descriptor.
- */
- private ViewElementDescriptor createRequestFocus() {
- String xmlName = REQUEST_FOCUS;
-
- // Create the include descriptor
- return new ViewElementDescriptor(
- xmlName, // xml_name
- xmlName, // ui_name
- xmlName, // "class name"; the GLE only treats this as an element tag
- "Requests focus for the parent element or one of its descendants", // tooltip
- null, // sdk_url
- null, // attributes
- null, // layout attributes
- null, // children
- false /* mandatory */);
- }
-
- /**
- * Finds the descriptor and retrieves all its layout attributes.
- */
- private AttributeDescriptor[] findViewLayoutAttributes(
- String viewFqcn) {
- ViewElementDescriptor viewDesc = findDescriptorByClass(viewFqcn);
- if (viewDesc != null) {
- return viewDesc.getLayoutAttributes();
- }
-
- return null;
- }
-
- /**
- * Set the super-class of each {@link ViewElementDescriptor} by using the super-class
- * information available in the {@link ViewClassInfo}.
- */
- private void fixSuperClasses(Map<ViewClassInfo, ViewElementDescriptor> infoDescMap) {
-
- for (Entry<ViewClassInfo, ViewElementDescriptor> entry : infoDescMap.entrySet()) {
- ViewClassInfo info = entry.getKey();
- ViewElementDescriptor desc = entry.getValue();
-
- ViewClassInfo sup = info.getSuperClass();
- if (sup != null) {
- ViewElementDescriptor supDesc = infoDescMap.get(sup);
- while (supDesc == null && sup != null) {
- // We don't have a descriptor for the super-class. That means the class is
- // probably abstract, so we just need to walk up the super-class chain till
- // we find one we have. All views derive from android.view.View so we should
- // surely find that eventually.
- sup = sup.getSuperClass();
- if (sup != null) {
- supDesc = infoDescMap.get(sup);
- }
- }
- if (supDesc != null) {
- desc.setSuperClass(supDesc);
- }
- }
- }
- }
-
- /**
- * Returns the {@link ViewElementDescriptor} with the given fully qualified class
- * name, or null if not found. This is a quick map lookup.
- *
- * @param fqcn the fully qualified class name
- * @return the corresponding {@link ViewElementDescriptor} or null
- */
- public ViewElementDescriptor findDescriptorByClass(String fqcn) {
- return mFqcnToDescriptor.get(fqcn);
- }
-
- /**
- * Returns the {@link ViewElementDescriptor} with the given XML tag name,
- * which usually does not include the package (depending on the
- * value of {@link ViewElementDescriptor#viewNeedsPackage(String)}).
- *
- * @param tag the XML tag name
- * @return the corresponding {@link ViewElementDescriptor} or null
- */
- public ViewElementDescriptor findDescriptorByTag(String tag) {
- // TODO: Consider whether we need to add a direct map lookup for this as well.
- // Currently not done since this is not frequently needed (only needed for
- // exploded rendering which was already performing list iteration.)
- for (ViewElementDescriptor descriptor : mLayoutDescriptors) {
- if (tag.equals(descriptor.getXmlLocalName())) {
- return descriptor;
- }
- }
-
- return null;
- }
-
- /**
- * Returns a collection of all the view class names, including layouts
- *
- * @return a collection of all the view class names, never null
- */
- public Collection<String> getAllViewClassNames() {
- return mFqcnToDescriptor.keySet();
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/ViewElementDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/ViewElementDescriptor.java
deleted file mode 100644
index 79995249c..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/ViewElementDescriptor.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (C) 2008 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.descriptors;
-
-import static com.android.SdkConstants.ANDROID_VIEW_PKG;
-import static com.android.SdkConstants.ANDROID_WEBKIT_PKG;
-import static com.android.SdkConstants.ANDROID_WIDGET_PREFIX;
-import static com.android.SdkConstants.VIEW;
-import static com.android.SdkConstants.VIEW_TAG;
-
-import com.android.ide.common.resources.platform.AttributeInfo;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.editors.IconFactory;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
-
-import org.eclipse.swt.graphics.Image;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * {@link ViewElementDescriptor} describes the properties expected for a given XML element node
- * representing a class in an XML Layout file.
- * <p/>
- * These descriptors describe Android views XML elements.
- * <p/>
- * The base class {@link ElementDescriptor} has a notion of "children", that is an XML element
- * can produce another set of XML elements. Because of the flat nature of Android's layout
- * XML files all possible views are children of the document and of themselves (that is any
- * view group can contain any other view). This is an implied contract of this class that is
- * enforces at construction by {@link LayoutDescriptors}. Note that by construction any code
- * that deals with the children hierarchy must also deal with potential infinite loops since views
- * <em>will</em> reference themselves (e.g. a ViewGroup can contain a ViewGroup).
- * <p/>
- * Since Views are also Java classes, they derive from each other. Here this is represented
- * as the "super class", which denotes the fact that a given View java class derives from
- * another class. These properties are also set at construction by {@link LayoutDescriptors}.
- * The super class hierarchy is very different from the descriptor's children hierarchy: the
- * later represents Java inheritance, the former represents an XML nesting capability.
- *
- * @see ElementDescriptor
- */
-public class ViewElementDescriptor extends ElementDescriptor {
-
- /** The full class name (FQCN) of this view. */
- private final String mFullClassName;
-
- /** The list of layout attributes. Can be empty but not null. */
- private AttributeDescriptor[] mLayoutAttributes;
-
- /** The super-class descriptor. Can be null. */
- private ViewElementDescriptor mSuperClassDesc;
-
- /** List of attribute sources, classes that contribute attributes to {@link #mAttributes} */
- private List<String> mAttributeSources;
-
- /**
- * Constructs a new {@link ViewElementDescriptor} based on its XML name, UI name,
- * the canonical name of the class it represents, its tooltip, its SDK url, its attributes list,
- * its children list and its mandatory flag.
- *
- * @param xml_name The XML element node name. Case sensitive.
- * @param ui_name The XML element name for the user interface, typically capitalized.
- * @param fullClassName The fully qualified class name the {@link ViewElementDescriptor} is
- * representing.
- * @param tooltip An optional tooltip. Can be null or empty.
- * @param sdk_url An optional SKD URL. Can be null or empty.
- * @param attributes The list of allowed attributes. Can be null or empty.
- * @param layoutAttributes The list of layout attributes. Can be null or empty.
- * @param children The list of allowed children. Can be null or empty.
- * @param mandatory Whether this node must always exist (even for empty models). A mandatory
- * UI node is never deleted and it may lack an actual XML node attached. A non-mandatory
- * UI node MUST have an XML node attached and it will cease to exist when the XML node
- * ceases to exist.
- */
- public ViewElementDescriptor(String xml_name, String ui_name,
- String fullClassName,
- String tooltip, String sdk_url,
- AttributeDescriptor[] attributes, AttributeDescriptor[] layoutAttributes,
- ElementDescriptor[] children, boolean mandatory) {
- super(xml_name, ui_name, tooltip, sdk_url, attributes, children, mandatory);
- mFullClassName = fullClassName;
- mLayoutAttributes = layoutAttributes != null ? layoutAttributes : new AttributeDescriptor[0];
- }
-
- /**
- * Constructs a new {@link ElementDescriptor} based on its XML name and on the canonical
- * name of the class it represents.
- * The UI name is build by capitalizing the XML name.
- * The UI nodes will be non-mandatory.
- *
- * @param xml_name The XML element node name. Case sensitive.
- * @param fullClassName The fully qualified class name the {@link ViewElementDescriptor} is
- * representing.
- */
- public ViewElementDescriptor(String xml_name, String fullClassName) {
- super(xml_name);
- mFullClassName = fullClassName;
- mLayoutAttributes = null;
- }
-
- /**
- * Returns the fully qualified name of the View class represented by this element descriptor
- * e.g. "android.view.View".
- *
- * @return the fully qualified class name, never null
- */
- public String getFullClassName() {
- return mFullClassName;
- }
-
- /** Returns the list of layout attributes. Can be empty but not null.
- *
- * @return the list of layout attributes, never null
- */
- public AttributeDescriptor[] getLayoutAttributes() {
- return mLayoutAttributes;
- }
-
- /**
- * Sets the list of layout attribute attributes.
- *
- * @param attributes the new layout attributes, not null
- */
- public void setLayoutAttributes(AttributeDescriptor[] attributes) {
- assert attributes != null;
- mLayoutAttributes = attributes;
- }
-
- /**
- * Returns a new {@link UiViewElementNode} linked to this descriptor.
- */
- @Override
- public UiElementNode createUiNode() {
- return new UiViewElementNode(this);
- }
-
- /**
- * Returns the {@link ViewElementDescriptor} of the super-class of this View descriptor
- * that matches the java View hierarchy. Can be null.
- *
- * @return the super class' descriptor or null
- */
- public ViewElementDescriptor getSuperClassDesc() {
- return mSuperClassDesc;
- }
-
- /**
- * Sets the {@link ViewElementDescriptor} of the super-class of this View descriptor
- * that matches the java View hierarchy. Can be null.
- *
- * @param superClassDesc the descriptor for the super class, or null
- */
- public void setSuperClass(ViewElementDescriptor superClassDesc) {
- mSuperClassDesc = superClassDesc;
- }
-
- /**
- * Returns an optional icon for the element.
- * <p/>
- * By default this tries to return an icon based on the XML name of the element.
- * If this fails, it tries to return the default element icon as defined in the
- * plugin. If all fails, it returns null.
- *
- * @return An icon for this element or null.
- */
- @Override
- public Image getGenericIcon() {
- IconFactory factory = IconFactory.getInstance();
- String name = mXmlName;
- if (name.indexOf('.') != -1) {
- // If the user uses a fully qualified name, such as
- // "android.gesture.GestureOverlayView" in their XML, we need to look up
- // only by basename
- name = name.substring(name.lastIndexOf('.') + 1);
- } else if (VIEW_TAG.equals(name)) {
- // Can't have both view.png and View.png; issues on case sensitive vs
- // case insensitive file systems
- name = VIEW;
- }
-
- Image icon = factory.getIcon(name);
- if (icon == null) {
- icon = AdtPlugin.getAndroidLogo();
- }
-
- return icon;
- }
-
- /**
- * Returns the list of attribute sources for the attributes provided by this
- * descriptor. An attribute source is the fully qualified class name of the
- * defining class for some of the properties. The specific attribute source
- * of a given {@link AttributeInfo} can be found by calling
- * {@link AttributeInfo#getDefinedBy()}.
- * <p>
- * The attribute sources are ordered from class to super class.
- * <p>
- * The list may <b>not</b> be modified by clients.
- *
- * @return a non null list of attribute sources for this view
- */
- public List<String> getAttributeSources() {
- return mAttributeSources != null ? mAttributeSources : Collections.<String>emptyList();
- }
-
- /**
- * Sets the attribute sources for this view. See {@link #getAttributes()}
- * for details.
- *
- * @param attributeSources a non null list of attribute sources for this
- * view descriptor
- * @see #getAttributeSources()
- */
- public void setAttributeSources(List<String> attributeSources) {
- mAttributeSources = attributeSources;
- }
-
- /**
- * Returns true if views with the given fully qualified class name need to include
- * their package in the layout XML tag
- *
- * @param fqcn the fully qualified class name, such as android.widget.Button
- * @return true if the full package path should be included in the layout XML element
- * tag
- */
- public static boolean viewNeedsPackage(String fqcn) {
- return !(fqcn.startsWith(ANDROID_WIDGET_PREFIX)
- || fqcn.startsWith(ANDROID_VIEW_PKG)
- || fqcn.startsWith(ANDROID_WEBKIT_PKG));
- }
-}