CustomViewDescriptorServicepublic final class CustomViewDescriptorService extends Object Service responsible for creating/managing {@link ElementDescriptor} objects for custom
View classes per project.
The service provides an on-demand monitoring of custom classes to check for changes. Monitoring
starts once a request for an {@link ElementDescriptor} object has been done for a specific
class.
The monitoring will notify a listen of any changes in the class triggering a change in its
associated {@link ElementDescriptor} object.
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. |
Fields Summary |
---|
private static CustomViewDescriptorService | sThis | private HashMap | mCustomDescriptorMapMap 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 ElementDescriptor}. | private ICustomViewDescriptorListener | mListenerTODO will be used to update the ElementDescriptor of the custom view when it
is modified (either the class itself or its attributes.xml) |
Methods Summary |
---|
private com.android.ide.eclipse.editors.descriptors.AttributeDescriptor[] | getAttributeDescriptor(org.eclipse.jdt.core.IType type, com.android.ide.eclipse.editors.descriptors.ElementDescriptor parentDescriptor)Returns the array of {@link AttributeDescriptor} for the specified {@link IType}.
The array should contain the descriptor for this type and all its supertypes.
// TODO add the class attribute descriptors to the parent descriptors.
return parentDescriptor.getAttributes();
| public com.android.ide.eclipse.editors.descriptors.ElementDescriptor | getDescriptor(org.eclipse.core.resources.IProject project, java.lang.String fqClassName)Returns the {@link ElementDescriptor} for a particular project/class.
If it is the first time the ElementDescriptor 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}.
// look in the map first
synchronized (mCustomDescriptorMap) {
HashMap<String, ElementDescriptor> map = mCustomDescriptorMap.get(project);
if (map != null) {
ElementDescriptor descriptor = map.get(fqClassName);
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 = fqClassName.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());
ElementDescriptor parentDescriptor = getDescriptor(
hierarchy.getSuperclass(type), project, hierarchy);
if (parentDescriptor != null) {
// we have a valid parent, lets create a new ElementDescriptor.
ViewElementDescriptor descriptor = new ViewElementDescriptor(fqClassName,
fqClassName, // ui_name
fqClassName, // canonical class name
null, // tooltip
null, // sdk_url
getAttributeDescriptor(type, parentDescriptor),
null, // layout attributes
null, // children
false /* mandatory */);
synchronized (mCustomDescriptorMap) {
map = mCustomDescriptorMap.get(project);
if (map == null) {
map = new HashMap<String, ElementDescriptor>();
mCustomDescriptorMap.put(project, map);
}
map.put(fqClassName, 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 ViewElementDescriptor | getDescriptor(org.eclipse.jdt.core.IType type, org.eclipse.core.resources.IProject project, org.eclipse.jdt.core.ITypeHierarchy typeHierarchy)Computes (if needed) and returns the {@link ElementDescriptor} for the specified type.
// check if the type is a built-in View class.
List<ElementDescriptor> builtInList = null;
Sdk currentSdk = Sdk.getCurrent();
IAndroidTarget target = currentSdk == null ? null : currentSdk.getTarget(project);
if (target != null) {
AndroidTargetData data = currentSdk.getTargetData(target);
builtInList = data.getLayoutDescriptors().getViewDescriptors();
}
// give up if there's no type
if (type == null) {
return null;
}
String canonicalName = type.getFullyQualifiedName();
if (builtInList != null) {
for (ElementDescriptor desc : builtInList) {
if (desc instanceof ViewElementDescriptor) {
ViewElementDescriptor viewDescriptor = (ViewElementDescriptor)desc;
if (canonicalName.equals(viewDescriptor.getCanonicalClassName())) {
return viewDescriptor;
}
}
}
}
// 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 = getDescriptor(parentType, project,
typeHierarchy);
if (parentDescriptor != null) {
// parent class is a valid View class with a descriptor, so we create one
// for this class.
ViewElementDescriptor descriptor = new ViewElementDescriptor(canonicalName,
canonicalName, // ui_name
canonicalName, // canonical name
null, // tooltip
null, // sdk_url
getAttributeDescriptor(type, parentDescriptor),
null, // layout attributes
null, // children
false /* mandatory */);
// add it to the map
synchronized (mCustomDescriptorMap) {
HashMap<String, ElementDescriptor> map = mCustomDescriptorMap.get(project);
if (map == null) {
map = new HashMap<String, ElementDescriptor>();
mCustomDescriptorMap.put(project, map);
}
map.put(canonicalName, 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;
| public static com.android.ide.eclipse.editors.layout.descriptors.CustomViewDescriptorService | getInstance()Returns the singleton instance of {@link CustomViewDescriptorService}.
return sThis;
| public void | setListener(com.android.ide.eclipse.editors.layout.descriptors.CustomViewDescriptorService$ICustomViewDescriptorListener listener)Sets the listener receiving custom View class modification notifications.
mListener = listener;
|
|