am 0cef5c46: Merge change 21056 into donut
Merge commit '0cef5c4666b9c77161421c8a52b7dddff42f12da' into eclair * commit '0cef5c4666b9c77161421c8a52b7dddff42f12da': Add a functional test that renders all the layouts of ApiDemos
This commit is contained in:
@@ -52,13 +52,13 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
|
|
||||||
/** List of the qualifier object helping for the parsing of folder names */
|
/** List of the qualifier object helping for the parsing of folder names */
|
||||||
private final ResourceQualifier[] mQualifiers;
|
private final ResourceQualifier[] mQualifiers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map associating project resource with project objects.
|
* Map associating project resource with project objects.
|
||||||
*/
|
*/
|
||||||
private final HashMap<IProject, ProjectResources> mMap =
|
private final HashMap<IProject, ProjectResources> mMap =
|
||||||
new HashMap<IProject, ProjectResources>();
|
new HashMap<IProject, ProjectResources>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the resource manager with the global resource monitor.
|
* Sets up the resource manager with the global resource monitor.
|
||||||
* @param monitor The global resource monitor
|
* @param monitor The global resource monitor
|
||||||
@@ -68,10 +68,10 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
int mask = IResourceDelta.ADDED | IResourceDelta.REMOVED | IResourceDelta.CHANGED;
|
int mask = IResourceDelta.ADDED | IResourceDelta.REMOVED | IResourceDelta.CHANGED;
|
||||||
monitor.addFolderListener(sThis, mask);
|
monitor.addFolderListener(sThis, mask);
|
||||||
monitor.addFileListener(sThis, mask);
|
monitor.addFileListener(sThis, mask);
|
||||||
|
|
||||||
CompiledResourcesMonitor.setupMonitor(monitor);
|
CompiledResourcesMonitor.setupMonitor(monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the singleton instance.
|
* Returns the singleton instance.
|
||||||
*/
|
*/
|
||||||
@@ -87,15 +87,15 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
public ProjectResources getProjectResources(IProject project) {
|
public ProjectResources getProjectResources(IProject project) {
|
||||||
return mMap.get(project);
|
return mMap.get(project);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes folder event.
|
* Processes folder event.
|
||||||
*/
|
*/
|
||||||
public void folderChanged(IFolder folder, int kind) {
|
public void folderChanged(IFolder folder, int kind) {
|
||||||
ProjectResources resources;
|
ProjectResources resources;
|
||||||
|
|
||||||
final IProject project = folder.getProject();
|
final IProject project = folder.getProject();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (project.hasNature(AndroidConstants.NATURE) == false) {
|
if (project.hasNature(AndroidConstants.NATURE) == false) {
|
||||||
return;
|
return;
|
||||||
@@ -104,18 +104,18 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
// can't get the project nature? return!
|
// can't get the project nature? return!
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case IResourceDelta.ADDED:
|
case IResourceDelta.ADDED:
|
||||||
// checks if the folder is under res.
|
// checks if the folder is under res.
|
||||||
IPath path = folder.getFullPath();
|
IPath path = folder.getFullPath();
|
||||||
|
|
||||||
// the path will be project/res/<something>
|
// the path will be project/res/<something>
|
||||||
if (path.segmentCount() == 3) {
|
if (path.segmentCount() == 3) {
|
||||||
if (isInResFolder(path)) {
|
if (isInResFolder(path)) {
|
||||||
// get the project and its resource object.
|
// get the project and its resource object.
|
||||||
resources = mMap.get(project);
|
resources = mMap.get(project);
|
||||||
|
|
||||||
// if it doesn't exist, we create it.
|
// if it doesn't exist, we create it.
|
||||||
if (resources == null) {
|
if (resources == null) {
|
||||||
resources = new ProjectResources(false /* isFrameworkRepository */);
|
resources = new ProjectResources(false /* isFrameworkRepository */);
|
||||||
@@ -146,23 +146,23 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* Sent when a file changed. Depending on the file being changed, and the type of change (ADDED,
|
* Sent when a file changed. Depending on the file being changed, and the type of change (ADDED,
|
||||||
* REMOVED, CHANGED), the file change is processed to update the resource manager data.
|
* REMOVED, CHANGED), the file change is processed to update the resource manager data.
|
||||||
*
|
*
|
||||||
* @param file The file that changed.
|
* @param file The file that changed.
|
||||||
* @param markerDeltas The marker deltas for the file.
|
* @param markerDeltas The marker deltas for the file.
|
||||||
* @param kind The change kind. This is equivalent to
|
* @param kind The change kind. This is equivalent to
|
||||||
* {@link IResourceDelta#accept(IResourceDeltaVisitor)}
|
* {@link IResourceDelta#accept(IResourceDeltaVisitor)}
|
||||||
*
|
*
|
||||||
* @see IFileListener#fileChanged
|
* @see IFileListener#fileChanged
|
||||||
*/
|
*/
|
||||||
public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) {
|
public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) {
|
||||||
ProjectResources resources;
|
ProjectResources resources;
|
||||||
|
|
||||||
final IProject project = file.getProject();
|
final IProject project = file.getProject();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (project.hasNature(AndroidConstants.NATURE) == false) {
|
if (project.hasNature(AndroidConstants.NATURE) == false) {
|
||||||
return;
|
return;
|
||||||
@@ -171,22 +171,22 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
// can't get the project nature? return!
|
// can't get the project nature? return!
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case IResourceDelta.ADDED:
|
case IResourceDelta.ADDED:
|
||||||
// checks if the file is under res/something.
|
// checks if the file is under res/something.
|
||||||
IPath path = file.getFullPath();
|
IPath path = file.getFullPath();
|
||||||
|
|
||||||
if (path.segmentCount() == 4) {
|
if (path.segmentCount() == 4) {
|
||||||
if (isInResFolder(path)) {
|
if (isInResFolder(path)) {
|
||||||
// get the project and its resources
|
// get the project and its resources
|
||||||
resources = mMap.get(project);
|
resources = mMap.get(project);
|
||||||
|
|
||||||
IContainer container = file.getParent();
|
IContainer container = file.getParent();
|
||||||
if (container instanceof IFolder && resources != null) {
|
if (container instanceof IFolder && resources != null) {
|
||||||
|
|
||||||
ResourceFolder folder = resources.getResourceFolder((IFolder)container);
|
ResourceFolder folder = resources.getResourceFolder((IFolder)container);
|
||||||
|
|
||||||
if (folder != null) {
|
if (folder != null) {
|
||||||
processFile(new IFileWrapper(file), folder);
|
processFile(new IFileWrapper(file), folder);
|
||||||
}
|
}
|
||||||
@@ -201,7 +201,7 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
IContainer container = file.getParent();
|
IContainer container = file.getParent();
|
||||||
if (container instanceof IFolder) {
|
if (container instanceof IFolder) {
|
||||||
ResourceFolder resFolder = resources.getResourceFolder((IFolder)container);
|
ResourceFolder resFolder = resources.getResourceFolder((IFolder)container);
|
||||||
|
|
||||||
// we get the delete on the folder before the file, so it is possible
|
// we get the delete on the folder before the file, so it is possible
|
||||||
// the associated ResourceFolder doesn't exist anymore.
|
// the associated ResourceFolder doesn't exist anymore.
|
||||||
if (resFolder != null) {
|
if (resFolder != null) {
|
||||||
@@ -221,7 +221,7 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
IContainer container = file.getParent();
|
IContainer container = file.getParent();
|
||||||
if (container instanceof IFolder) {
|
if (container instanceof IFolder) {
|
||||||
ResourceFolder resFolder = resources.getResourceFolder((IFolder)container);
|
ResourceFolder resFolder = resources.getResourceFolder((IFolder)container);
|
||||||
|
|
||||||
// we get the delete on the folder before the file, so it is possible
|
// we get the delete on the folder before the file, so it is possible
|
||||||
// the associated ResourceFolder doesn't exist anymore.
|
// the associated ResourceFolder doesn't exist anymore.
|
||||||
if (resFolder != null) {
|
if (resFolder != null) {
|
||||||
@@ -249,7 +249,7 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
public void projectOpenedWithWorkspace(IProject project) {
|
public void projectOpenedWithWorkspace(IProject project) {
|
||||||
createProject(project);
|
createProject(project);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link ResourceFolder} for the given file or <code>null</code> if none exists.
|
* Returns the {@link ResourceFolder} for the given file or <code>null</code> if none exists.
|
||||||
*/
|
*/
|
||||||
@@ -258,62 +258,85 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
if (container.getType() == IResource.FOLDER) {
|
if (container.getType() == IResource.FOLDER) {
|
||||||
IFolder parent = (IFolder)container;
|
IFolder parent = (IFolder)container;
|
||||||
IProject project = file.getProject();
|
IProject project = file.getProject();
|
||||||
|
|
||||||
ProjectResources resources = getProjectResources(project);
|
ProjectResources resources = getProjectResources(project);
|
||||||
if (resources != null) {
|
if (resources != null) {
|
||||||
return resources.getResourceFolder(parent);
|
return resources.getResourceFolder(parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads and returns the resources for a given {@link IAndroidTarget}
|
* Loads and returns the resources for a given {@link IAndroidTarget}
|
||||||
* @param androidTarget the target from which to load the framework resources
|
* @param androidTarget the target from which to load the framework resources
|
||||||
*/
|
*/
|
||||||
public ProjectResources loadFrameworkResources(IAndroidTarget androidTarget) {
|
public ProjectResources loadFrameworkResources(IAndroidTarget androidTarget) {
|
||||||
String osResourcesPath = androidTarget.getPath(IAndroidTarget.RESOURCES);
|
String osResourcesPath = androidTarget.getPath(IAndroidTarget.RESOURCES);
|
||||||
|
|
||||||
File frameworkRes = new File(osResourcesPath);
|
File frameworkRes = new File(osResourcesPath);
|
||||||
if (frameworkRes.isDirectory()) {
|
if (frameworkRes.isDirectory()) {
|
||||||
ProjectResources resources = new ProjectResources(true /* isFrameworkRepository */);
|
ProjectResources resources = new ProjectResources(true /* isFrameworkRepository */);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
File[] files = frameworkRes.listFiles();
|
loadResources(resources, frameworkRes);
|
||||||
for (File file : files) {
|
|
||||||
if (file.isDirectory()) {
|
|
||||||
ResourceFolder resFolder = processFolder(new FolderWrapper(file),
|
|
||||||
resources);
|
|
||||||
|
|
||||||
if (resFolder != null) {
|
|
||||||
// now we process the content of the folder
|
|
||||||
File[] children = file.listFiles();
|
|
||||||
|
|
||||||
for (File childRes : children) {
|
|
||||||
if (childRes.isFile()) {
|
|
||||||
processFile(new FileWrapper(childRes), resFolder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now that we have loaded the files, we need to force load the resources from them
|
|
||||||
resources.loadAll();
|
|
||||||
|
|
||||||
return resources;
|
return resources;
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// since we test that folders are folders, and files are files, this shouldn't
|
// since we test that folders are folders, and files are files, this shouldn't
|
||||||
// happen. We can ignore it.
|
// happen. We can ignore it.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the resources from a folder, and fills the given {@link ProjectResources}.
|
||||||
|
* <p/>
|
||||||
|
* This is mostly a utility method that should not be used to process actual Eclipse projects
|
||||||
|
* (Those are loaded with {@link #createProject(IProject)} for new project or
|
||||||
|
* {@link #processFolder(IAbstractFolder, ProjectResources)} and
|
||||||
|
* {@link #processFile(IAbstractFile, ResourceFolder)} for folder/file modifications)<br>
|
||||||
|
* This method will process files/folders with implementations of {@link IAbstractFile} and
|
||||||
|
* {@link IAbstractFolder} based on {@link File} instead of {@link IFile} and {@link IFolder}
|
||||||
|
* respectively. This is not proper for handling {@link IProject}s.
|
||||||
|
* </p>
|
||||||
|
* This is used to load the framework resources, or to do load project resources when
|
||||||
|
* setting rendering tests.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param resources The {@link ProjectResources} files to load. It is expected that the
|
||||||
|
* framework flag has been properly setup. This is filled up with the content of the folder.
|
||||||
|
* @param folder The folder to read the resources from. This is the top level resource folder
|
||||||
|
* (res/)
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void loadResources(ProjectResources resources, File folder) throws IOException {
|
||||||
|
File[] files = folder.listFiles();
|
||||||
|
for (File file : files) {
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
ResourceFolder resFolder = processFolder(new FolderWrapper(file),
|
||||||
|
resources);
|
||||||
|
|
||||||
|
if (resFolder != null) {
|
||||||
|
// now we process the content of the folder
|
||||||
|
File[] children = file.listFiles();
|
||||||
|
|
||||||
|
for (File childRes : children) {
|
||||||
|
if (childRes.isFile()) {
|
||||||
|
processFile(new FileWrapper(childRes), resFolder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now that we have loaded the files, we need to force load the resources from them
|
||||||
|
resources.loadAll();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initial project parsing to gather resource info.
|
* Initial project parsing to gather resource info.
|
||||||
* @param project
|
* @param project
|
||||||
@@ -328,33 +351,33 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
// can't check the nature of the project? ignore it.
|
// can't check the nature of the project? ignore it.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IFolder resourceFolder = project.getFolder(SdkConstants.FD_RESOURCES);
|
IFolder resourceFolder = project.getFolder(SdkConstants.FD_RESOURCES);
|
||||||
|
|
||||||
ProjectResources projectResources = mMap.get(project);
|
ProjectResources projectResources = mMap.get(project);
|
||||||
if (projectResources == null) {
|
if (projectResources == null) {
|
||||||
projectResources = new ProjectResources(false /* isFrameworkRepository */);
|
projectResources = new ProjectResources(false /* isFrameworkRepository */);
|
||||||
mMap.put(project, projectResources);
|
mMap.put(project, projectResources);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resourceFolder != null && resourceFolder.exists()) {
|
if (resourceFolder != null && resourceFolder.exists()) {
|
||||||
try {
|
try {
|
||||||
IResource[] resources = resourceFolder.members();
|
IResource[] resources = resourceFolder.members();
|
||||||
|
|
||||||
for (IResource res : resources) {
|
for (IResource res : resources) {
|
||||||
if (res.getType() == IResource.FOLDER) {
|
if (res.getType() == IResource.FOLDER) {
|
||||||
IFolder folder = (IFolder)res;
|
IFolder folder = (IFolder)res;
|
||||||
ResourceFolder resFolder = processFolder(new IFolderWrapper(folder),
|
ResourceFolder resFolder = processFolder(new IFolderWrapper(folder),
|
||||||
projectResources);
|
projectResources);
|
||||||
|
|
||||||
if (resFolder != null) {
|
if (resFolder != null) {
|
||||||
// now we process the content of the folder
|
// now we process the content of the folder
|
||||||
IResource[] files = folder.members();
|
IResource[] files = folder.members();
|
||||||
|
|
||||||
for (IResource fileRes : files) {
|
for (IResource fileRes : files) {
|
||||||
if (fileRes.getType() == IResource.FILE) {
|
if (fileRes.getType() == IResource.FILE) {
|
||||||
IFile file = (IFile)fileRes;
|
IFile file = (IFile)fileRes;
|
||||||
|
|
||||||
processFile(new IFileWrapper(file), resFolder);
|
processFile(new IFileWrapper(file), resFolder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -383,10 +406,10 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
// Because the order of the qualifier is fixed, we do not reset the first qualifier
|
// Because the order of the qualifier is fixed, we do not reset the first qualifier
|
||||||
// after each sucessful segment.
|
// after each sucessful segment.
|
||||||
// If we run out of qualifier before processing all the segments, we fail.
|
// If we run out of qualifier before processing all the segments, we fail.
|
||||||
|
|
||||||
int qualifierIndex = 0;
|
int qualifierIndex = 0;
|
||||||
int qualifierCount = mQualifiers.length;
|
int qualifierCount = mQualifiers.length;
|
||||||
|
|
||||||
for (int i = 1 ; i < folderSegments.length; i++) {
|
for (int i = 1 ; i < folderSegments.length; i++) {
|
||||||
String seg = folderSegments[i];
|
String seg = folderSegments[i];
|
||||||
if (seg.length() > 0) {
|
if (seg.length() > 0) {
|
||||||
@@ -394,12 +417,12 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
mQualifiers[qualifierIndex].checkAndSet(seg, config) == false) {
|
mQualifiers[qualifierIndex].checkAndSet(seg, config) == false) {
|
||||||
qualifierIndex++;
|
qualifierIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we reached the end of the qualifier we didn't find a matching qualifier.
|
// if we reached the end of the qualifier we didn't find a matching qualifier.
|
||||||
if (qualifierIndex == qualifierCount) {
|
if (qualifierIndex == qualifierCount) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -407,7 +430,7 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a folder and adds it to the list of the project resources.
|
* Processes a folder and adds it to the list of the project resources.
|
||||||
* @param folder the folder to process
|
* @param folder the folder to process
|
||||||
@@ -420,18 +443,18 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
|
|
||||||
// get the enum for the resource type.
|
// get the enum for the resource type.
|
||||||
ResourceFolderType type = ResourceFolderType.getTypeByName(folderSegments[0]);
|
ResourceFolderType type = ResourceFolderType.getTypeByName(folderSegments[0]);
|
||||||
|
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
// get the folder configuration.
|
// get the folder configuration.
|
||||||
FolderConfiguration config = getConfig(folderSegments);
|
FolderConfiguration config = getConfig(folderSegments);
|
||||||
|
|
||||||
if (config != null) {
|
if (config != null) {
|
||||||
ResourceFolder configuredFolder = project.add(type, config, folder);
|
ResourceFolder configuredFolder = project.add(type, config, folder);
|
||||||
|
|
||||||
return configuredFolder;
|
return configuredFolder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,16 +466,16 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
private void processFile(IAbstractFile file, ResourceFolder folder) {
|
private void processFile(IAbstractFile file, ResourceFolder folder) {
|
||||||
// get the type of the folder
|
// get the type of the folder
|
||||||
ResourceFolderType type = folder.getType();
|
ResourceFolderType type = folder.getType();
|
||||||
|
|
||||||
// look for this file if it's already been created
|
// look for this file if it's already been created
|
||||||
ResourceFile resFile = folder.getFile(file);
|
ResourceFile resFile = folder.getFile(file);
|
||||||
|
|
||||||
if (resFile != null) {
|
if (resFile != null) {
|
||||||
// invalidate the file
|
// invalidate the file
|
||||||
resFile.touch();
|
resFile.touch();
|
||||||
} else {
|
} else {
|
||||||
// create a ResourceFile for it.
|
// create a ResourceFile for it.
|
||||||
|
|
||||||
// check if that's a single or multi resource type folder. For now we define this by
|
// check if that's a single or multi resource type folder. For now we define this by
|
||||||
// the number of possible resource type output by files in the folder. This does
|
// the number of possible resource type output by files in the folder. This does
|
||||||
// not make the difference between several resource types from a single file or
|
// not make the difference between several resource types from a single file or
|
||||||
@@ -460,13 +483,13 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
// resource. The former is handled by MultiResourceFile properly while we don't
|
// resource. The former is handled by MultiResourceFile properly while we don't
|
||||||
// handle the latter. If we were to add this behavior we'd have to change this call.
|
// handle the latter. If we were to add this behavior we'd have to change this call.
|
||||||
ResourceType[] types = FolderTypeRelationship.getRelatedResourceTypes(type);
|
ResourceType[] types = FolderTypeRelationship.getRelatedResourceTypes(type);
|
||||||
|
|
||||||
if (types.length == 1) {
|
if (types.length == 1) {
|
||||||
resFile = new SingleResourceFile(file, folder);
|
resFile = new SingleResourceFile(file, folder);
|
||||||
} else {
|
} else {
|
||||||
resFile = new MultiResourceFile(file, folder);
|
resFile = new MultiResourceFile(file, folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add it to the folder
|
// add it to the folder
|
||||||
folder.addFile(resFile);
|
folder.addFile(resFile);
|
||||||
}
|
}
|
||||||
@@ -480,7 +503,7 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
|
|||||||
private boolean isInResFolder(IPath path) {
|
private boolean isInResFolder(IPath path) {
|
||||||
return SdkConstants.FD_RESOURCES.equalsIgnoreCase(path.segment(1));
|
return SdkConstants.FD_RESOURCES.equalsIgnoreCase(path.segment(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private constructor to enforce singleton design.
|
* Private constructor to enforce singleton design.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,5 +6,6 @@
|
|||||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||||
<classpathentry kind="lib" path="kxml2-2.3.0.jar"/>
|
<classpathentry kind="lib" path="kxml2-2.3.0.jar"/>
|
||||||
<classpathentry kind="lib" path="/adt/sdklib.jar" sourcepath="/SdkLib"/>
|
<classpathentry kind="lib" path="/adt/sdklib.jar" sourcepath="/SdkLib"/>
|
||||||
|
<classpathentry kind="lib" path="/adt/layoutlib_api.jar" sourcepath="/layoutlib_api"/>
|
||||||
<classpathentry kind="output" path="bin"/>
|
<classpathentry kind="output" path="bin"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|||||||
@@ -16,4 +16,6 @@ Require-Bundle: org.eclipse.ui,
|
|||||||
Bundle-ActivationPolicy: lazy
|
Bundle-ActivationPolicy: lazy
|
||||||
Bundle-Vendor: The Android Open Source Project
|
Bundle-Vendor: The Android Open Source Project
|
||||||
Bundle-ClassPath: kxml2-2.3.0.jar,
|
Bundle-ClassPath: kxml2-2.3.0.jar,
|
||||||
.
|
.,
|
||||||
|
layoutlib_api.jar,
|
||||||
|
sdklib.jar
|
||||||
|
|||||||
@@ -7,4 +7,6 @@ bin.includes = META-INF/,\
|
|||||||
prefs.template,\
|
prefs.template,\
|
||||||
unittest.xml,\
|
unittest.xml,\
|
||||||
kxml2-2.3.0.jar,\
|
kxml2-2.3.0.jar,\
|
||||||
unittests/data/
|
unittests/data/,\
|
||||||
|
sdklib.jar,\
|
||||||
|
layoutlib_api.jar
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 The Android Open Source Project
|
* Copyright (C) 2008 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Licensed under the Eclipse Public License, Version 1.0 (the "License"); you
|
* 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
|
* may not use this file except in compliance with the License. You may obtain a
|
||||||
* copy of the License at
|
* copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.eclipse.org/org/documents/epl-v10.php
|
* http://www.eclipse.org/org/documents/epl-v10.php
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
@@ -18,7 +18,7 @@ package com.android.ide.eclipse.tests;
|
|||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic superclass for Eclipse Android functional test cases, that provides
|
* Generic superclass for Eclipse Android functional test cases, that provides
|
||||||
* common facilities
|
* common facilities
|
||||||
*/
|
*/
|
||||||
public class FuncTestCase extends TestCase {
|
public class FuncTestCase extends TestCase {
|
||||||
@@ -27,12 +27,15 @@ public class FuncTestCase extends TestCase {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @throws IllegalArgumentException if environment variable "sdk_home" is
|
* @throws IllegalArgumentException if environment variable "sdk_home" is
|
||||||
* not set
|
* not set
|
||||||
*/
|
*/
|
||||||
protected FuncTestCase() {
|
protected FuncTestCase() {
|
||||||
mOsSdkLocation = System.getProperty("sdk_home");
|
mOsSdkLocation = System.getProperty("sdk_home");
|
||||||
|
if (mOsSdkLocation == null) {
|
||||||
|
mOsSdkLocation = System.getenv("sdk_home");
|
||||||
|
}
|
||||||
if (mOsSdkLocation == null || mOsSdkLocation.length() < 1) {
|
if (mOsSdkLocation == null || mOsSdkLocation.length() < 1) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Environment variable sdk_home is not set");
|
"Environment variable sdk_home is not set");
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 The Android Open Source Project
|
* Copyright (C) 2008 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Licensed under the Eclipse Public License, Version 1.0 (the "License"); you
|
* 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
|
* may not use this file except in compliance with the License. You may obtain a
|
||||||
* copy of the License at
|
* copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.eclipse.org/org/documents/epl-v10.php
|
* http://www.eclipse.org/org/documents/epl-v10.php
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.ide.eclipse.tests;
|
package com.android.ide.eclipse.tests;
|
||||||
|
|
||||||
|
import com.android.ide.eclipse.tests.functests.layoutRendering.ApiDemosRenderingTest;
|
||||||
import com.android.ide.eclipse.tests.functests.sampleProjects.SampleProjectTest;
|
import com.android.ide.eclipse.tests.functests.sampleProjects.SampleProjectTest;
|
||||||
|
|
||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
@@ -28,18 +29,19 @@ public class FuncTests extends TestSuite {
|
|||||||
static final String FUNC_TEST_PACKAGE = "com.android.ide.eclipse.tests.functests";
|
static final String FUNC_TEST_PACKAGE = "com.android.ide.eclipse.tests.functests";
|
||||||
|
|
||||||
public FuncTests() {
|
public FuncTests() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a suite of test cases to be run.
|
* Returns a suite of test cases to be run.
|
||||||
* Needed for JUnit3 compliant command line test runner
|
* Needed for JUnit3 compliant command line test runner
|
||||||
*/
|
*/
|
||||||
public static TestSuite suite() {
|
public static TestSuite suite() {
|
||||||
TestSuite suite = new TestSuite();
|
TestSuite suite = new TestSuite();
|
||||||
|
|
||||||
suite.addTestSuite(SampleProjectTest.class);
|
suite.addTestSuite(SampleProjectTest.class);
|
||||||
|
suite.addTestSuite(ApiDemosRenderingTest.class);
|
||||||
|
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,242 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 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.tests.functests.layoutRendering;
|
||||||
|
|
||||||
|
import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
|
||||||
|
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.AndroidTargetParser;
|
||||||
|
import com.android.ide.eclipse.adt.internal.sdk.LoadStatus;
|
||||||
|
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
|
||||||
|
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData.LayoutBridge;
|
||||||
|
import com.android.ide.eclipse.tests.FuncTestCase;
|
||||||
|
import com.android.layoutlib.api.ILayoutResult;
|
||||||
|
import com.android.layoutlib.api.IProjectCallback;
|
||||||
|
import com.android.layoutlib.api.IResourceValue;
|
||||||
|
import com.android.layoutlib.api.IXmlPullParser;
|
||||||
|
import com.android.sdklib.IAndroidTarget;
|
||||||
|
import com.android.sdklib.SdkConstants;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||||
|
import org.kxml2.io.KXmlParser;
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
|
public class ApiDemosRenderingTest extends FuncTestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom parser that implements {@link IXmlPullParser} (which itself extends
|
||||||
|
* {@link XmlPullParser}).
|
||||||
|
*/
|
||||||
|
private final static class TestParser extends KXmlParser implements IXmlPullParser {
|
||||||
|
/**
|
||||||
|
* Since we're not going to go through the result of the rendering/layout, we can return
|
||||||
|
* null for the View Key.
|
||||||
|
*/
|
||||||
|
public Object getViewKey() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static class ProjectCallBack implements IProjectCallback {
|
||||||
|
// resource id counter.
|
||||||
|
// We start at 0x7f000000 to avoid colliding with the framework id
|
||||||
|
// since we have no access to the project R.java and we need to generate them automatically.
|
||||||
|
private int mIdCounter = 0x7f000000;
|
||||||
|
|
||||||
|
// in some cases, the id that getResourceValue(String type, String name) returns
|
||||||
|
// will be sent back to get the type/name. This map stores the id/type/name we generate
|
||||||
|
// to be able to do the reverse resolution.
|
||||||
|
private Map<Integer, String[]> mResourceMap = new HashMap<Integer, String[]>();
|
||||||
|
|
||||||
|
private boolean mCustomViewAttempt = false;
|
||||||
|
|
||||||
|
public String getNamespace() {
|
||||||
|
// TODO: read from the ApiDemos manifest.
|
||||||
|
return "com.example.android.apis";
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getResourceValue(String type, String name) {
|
||||||
|
Integer result = ++mIdCounter;
|
||||||
|
mResourceMap.put(result, new String[] { name, type });
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Object loadView(String name, Class[] constructorSignature, Object[] constructorArgs)
|
||||||
|
throws ClassNotFoundException, Exception {
|
||||||
|
mCustomViewAttempt = true;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] resolveResourceValue(int id) {
|
||||||
|
return mResourceMap.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String resolveResourceValue(int[] id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Sdk mSdk;
|
||||||
|
|
||||||
|
public void testApiDemos() throws IOException, XmlPullParserException {
|
||||||
|
loadSdk();
|
||||||
|
findApiDemos();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the {@link Sdk}.
|
||||||
|
*/
|
||||||
|
private void loadSdk() {
|
||||||
|
mSdk = Sdk.loadSdk(this.getOsSdkLocation());
|
||||||
|
|
||||||
|
int n = mSdk.getTargets().length;
|
||||||
|
if (n > 0) {
|
||||||
|
for (IAndroidTarget target : mSdk.getTargets()) {
|
||||||
|
IStatus status = new AndroidTargetParser(target).run(new NullProgressMonitor());
|
||||||
|
if (status.getCode() != IStatus.OK) {
|
||||||
|
fail("Failed to parse targets data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findApiDemos() throws IOException, XmlPullParserException {
|
||||||
|
IAndroidTarget[] targets = mSdk.getTargets();
|
||||||
|
|
||||||
|
for (IAndroidTarget target : targets) {
|
||||||
|
String path = target.getPath(IAndroidTarget.SAMPLES);
|
||||||
|
File samples = new File(path);
|
||||||
|
if (samples.isDirectory()) {
|
||||||
|
File[] files = samples.listFiles();
|
||||||
|
for (File file : files) {
|
||||||
|
if ("apidemos".equalsIgnoreCase(file.getName())) {
|
||||||
|
testSample(target, file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fail("Failed to find ApiDemos!");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testSample(IAndroidTarget target, File sampleProject) throws IOException, XmlPullParserException {
|
||||||
|
AndroidTargetData data = mSdk.getTargetData(target);
|
||||||
|
if (data == null) {
|
||||||
|
fail("No AndroidData!");
|
||||||
|
}
|
||||||
|
|
||||||
|
LayoutBridge bridge = data.getLayoutBridge();
|
||||||
|
if (bridge.status != LoadStatus.LOADED || bridge.bridge == null) {
|
||||||
|
fail("Fail to load the bridge");
|
||||||
|
}
|
||||||
|
|
||||||
|
File resFolder = new File(sampleProject, SdkConstants.FD_RES);
|
||||||
|
if (resFolder.isDirectory() == false) {
|
||||||
|
fail("Sample project has no res folder!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// look for the layout folder
|
||||||
|
File layoutFolder = new File(resFolder, SdkConstants.FD_LAYOUT);
|
||||||
|
if (layoutFolder.isDirectory() == false) {
|
||||||
|
fail("Sample project has no layout folder!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// first load the project's target framework resource
|
||||||
|
ProjectResources framework = ResourceManager.getInstance().loadFrameworkResources(target);
|
||||||
|
|
||||||
|
// now load the project resources
|
||||||
|
ProjectResources project = new ProjectResources(false /* isFrameworkRepository */);
|
||||||
|
ResourceManager.getInstance().loadResources(project, resFolder);
|
||||||
|
|
||||||
|
|
||||||
|
// Create a folder configuration that will be used for the rendering:
|
||||||
|
FolderConfiguration config = getConfiguration();
|
||||||
|
|
||||||
|
// get the configured resources
|
||||||
|
Map<String, Map<String, IResourceValue>> configuredFramework =
|
||||||
|
framework.getConfiguredResources(config);
|
||||||
|
Map<String, Map<String, IResourceValue>> configuredProject =
|
||||||
|
project.getConfiguredResources(config);
|
||||||
|
|
||||||
|
boolean saveFiles = System.getenv("save_file") != null;
|
||||||
|
|
||||||
|
// loop on the layouts and render them
|
||||||
|
File[] layouts = layoutFolder.listFiles();
|
||||||
|
for (File layout : layouts) {
|
||||||
|
// create a parser for the layout file
|
||||||
|
TestParser parser = new TestParser();
|
||||||
|
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
||||||
|
parser.setInput(new FileReader(layout));
|
||||||
|
|
||||||
|
System.out.println("Rendering " + layout.getName());
|
||||||
|
|
||||||
|
ProjectCallBack projectCallBack = new ProjectCallBack();
|
||||||
|
|
||||||
|
ILayoutResult result = bridge.bridge.computeLayout(
|
||||||
|
parser,
|
||||||
|
null /*projectKey*/,
|
||||||
|
320,
|
||||||
|
480,
|
||||||
|
160, //density
|
||||||
|
160, //xdpi
|
||||||
|
160, // ydpi
|
||||||
|
"Theme", //themeName
|
||||||
|
false, //isProjectTheme
|
||||||
|
configuredProject,
|
||||||
|
configuredFramework,
|
||||||
|
projectCallBack,
|
||||||
|
null //logger
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.getSuccess() != ILayoutResult.SUCCESS) {
|
||||||
|
if (projectCallBack.mCustomViewAttempt == false) {
|
||||||
|
System.out.println("FAILED");
|
||||||
|
fail(String.format("Rendering %1$s: %2$s", layout.getName(),
|
||||||
|
result.getErrorMessage()));
|
||||||
|
} else {
|
||||||
|
System.out.println("Ignore custom views for now");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (saveFiles) {
|
||||||
|
File tmp = File.createTempFile(layout.getName(), ".png");
|
||||||
|
ImageIO.write(result.getImage(), "png", tmp);
|
||||||
|
}
|
||||||
|
System.out.println("Success!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private FolderConfiguration getConfiguration() {
|
||||||
|
FolderConfiguration config = new FolderConfiguration();
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user