merge from donut
This commit is contained in:
@@ -666,6 +666,12 @@
|
||||
id="com.android.ide.eclipse.adt.refactoring.extract.string"
|
||||
name="Extract Android String">
|
||||
</command>
|
||||
<keyBinding
|
||||
commandId="com.android.ide.eclipse.adt.refactoring.extract.string"
|
||||
contextId="org.eclipse.ui.globalScope"
|
||||
keyConfigurationId="org.eclipse.ui.defaultAcceleratorConfiguration"
|
||||
keySequence="M3+M2+A S">
|
||||
</keyBinding>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ltk.core.refactoring.refactoringContributions">
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
|
||||
import com.android.ide.eclipse.adt.internal.project.FixLaunchConfig;
|
||||
import com.android.ide.eclipse.adt.internal.project.XmlErrorHandler.BasicXmlErrorListener;
|
||||
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
|
||||
import com.android.sdklib.AndroidVersion;
|
||||
import com.android.sdklib.IAndroidTarget;
|
||||
import com.android.sdklib.SdkConstants;
|
||||
|
||||
@@ -89,22 +90,22 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
this.sourceFolder = sourceFolder;
|
||||
this.aidlFile = aidlFile;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (obj instanceof AidlData) {
|
||||
AidlData file = (AidlData)obj;
|
||||
return aidlFile.equals(file.aidlFile) && sourceFolder.equals(file.sourceFolder);
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resource Compile flag. This flag is reset to false after each successful compilation, and
|
||||
* stored in the project persistent properties. This allows the builder to remember its state
|
||||
@@ -120,7 +121,7 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
|
||||
/** cache of the java package defined in the manifest */
|
||||
private String mManifestPackage;
|
||||
|
||||
|
||||
/** Output folder for generated Java File. Created on the Builder init
|
||||
* @see #startupOnInitialize()
|
||||
*/
|
||||
@@ -145,11 +146,11 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
private boolean mDone = false;
|
||||
public DerivedProgressMonitor() {
|
||||
}
|
||||
|
||||
|
||||
void addFile(IFile file) {
|
||||
mFileList.add(file);
|
||||
}
|
||||
|
||||
|
||||
void reset() {
|
||||
mFileList.clear();
|
||||
mDone = false;
|
||||
@@ -198,7 +199,7 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
public PreCompilerBuilder() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
// build() returns a list of project from which this project depends for future compilation.
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
@@ -209,24 +210,24 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
|
||||
// First thing we do is go through the resource delta to not
|
||||
// lose it if we have to abort the build for any reason.
|
||||
|
||||
|
||||
// get the project objects
|
||||
IProject project = getProject();
|
||||
|
||||
|
||||
// Top level check to make sure the build can move forward.
|
||||
abortOnBadSetup(project);
|
||||
|
||||
|
||||
IJavaProject javaProject = JavaCore.create(project);
|
||||
IAndroidTarget projectTarget = Sdk.getCurrent().getTarget(project);
|
||||
|
||||
|
||||
// now we need to get the classpath list
|
||||
ArrayList<IPath> sourceFolderPathList = BaseProjectHelper.getSourceClasspaths(
|
||||
javaProject);
|
||||
|
||||
|
||||
PreCompilerDeltaVisitor dv = null;
|
||||
String javaPackage = null;
|
||||
int minSdkVersion = AndroidManifestParser.INVALID_MIN_SDK;
|
||||
|
||||
String minSdkVersion = null;
|
||||
|
||||
if (kind == FULL_BUILD) {
|
||||
AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
|
||||
Messages.Start_Full_Pre_Compiler);
|
||||
@@ -235,7 +236,7 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
} else {
|
||||
AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
|
||||
Messages.Start_Inc_Pre_Compiler);
|
||||
|
||||
|
||||
// Go through the resources and see if something changed.
|
||||
// Even if the mCompileResources flag is true from a previously aborted
|
||||
// build, we need to go through the Resource delta to get a possible
|
||||
@@ -247,10 +248,10 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
} else {
|
||||
dv = new PreCompilerDeltaVisitor(this, sourceFolderPathList);
|
||||
delta.accept(dv);
|
||||
|
||||
|
||||
// record the state
|
||||
mMustCompileResources |= dv.getCompileResources();
|
||||
|
||||
|
||||
if (dv.getForceAidlCompile()) {
|
||||
buildAidlCompilationList(project, sourceFolderPathList);
|
||||
} else {
|
||||
@@ -258,46 +259,46 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
mergeAidlFileModifications(dv.getAidlToCompile(),
|
||||
dv.getAidlToRemove());
|
||||
}
|
||||
|
||||
|
||||
// get the java package from the visitor
|
||||
javaPackage = dv.getManifestPackage();
|
||||
minSdkVersion = dv.getMinSdkVersion();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// store the build status in the persistent storage
|
||||
saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES , mMustCompileResources);
|
||||
|
||||
|
||||
// if there was some XML errors, we just return w/o doing
|
||||
// anything since we've put some markers in the files anyway.
|
||||
if (dv != null && dv.mXmlError) {
|
||||
AdtPlugin.printErrorToConsole(project, Messages.Xml_Error);
|
||||
|
||||
|
||||
// This interrupts the build. The next builders will not run.
|
||||
stopBuild(Messages.Xml_Error);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// get the manifest file
|
||||
IFile manifest = AndroidManifestParser.getManifest(project);
|
||||
|
||||
|
||||
if (manifest == null) {
|
||||
String msg = String.format(Messages.s_File_Missing,
|
||||
AndroidConstants.FN_ANDROID_MANIFEST);
|
||||
AdtPlugin.printErrorToConsole(project, msg);
|
||||
markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
|
||||
|
||||
|
||||
// This interrupts the build. The next builders will not run.
|
||||
stopBuild(msg);
|
||||
}
|
||||
|
||||
|
||||
// lets check the XML of the manifest first, if that hasn't been done by the
|
||||
// resource delta visitor yet.
|
||||
if (dv == null || dv.getCheckedManifestXml() == false) {
|
||||
BasicXmlErrorListener errorListener = new BasicXmlErrorListener();
|
||||
AndroidManifestParser parser = BaseProjectHelper.parseManifestForError(manifest,
|
||||
errorListener);
|
||||
|
||||
|
||||
if (errorListener.mHasXmlError == true) {
|
||||
// there was an error in the manifest, its file has been marked,
|
||||
// by the XmlErrorHandler.
|
||||
@@ -305,25 +306,71 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
String msg = String.format(Messages.s_Contains_Xml_Error,
|
||||
AndroidConstants.FN_ANDROID_MANIFEST);
|
||||
AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, msg);
|
||||
|
||||
|
||||
// This interrupts the build. The next builders will not run.
|
||||
stopBuild(msg);
|
||||
}
|
||||
|
||||
|
||||
// get the java package from the parser
|
||||
javaPackage = parser.getPackage();
|
||||
minSdkVersion = parser.getApiLevelRequirement();
|
||||
}
|
||||
|
||||
if (minSdkVersion != AndroidManifestParser.INVALID_MIN_SDK &&
|
||||
minSdkVersion < projectTarget.getApiVersionNumber()) {
|
||||
// check it against the target api level
|
||||
String msg = String.format(
|
||||
"Manifest min SDK version (%1$d) is lower than project target API level (%2$d)",
|
||||
minSdkVersion, projectTarget.getApiVersionNumber());
|
||||
AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, msg);
|
||||
BaseProjectHelper.addMarker(manifest, AdtConstants.MARKER_ADT, msg,
|
||||
IMarker.SEVERITY_WARNING);
|
||||
if (minSdkVersion != null) {
|
||||
int minSdkValue = -1;
|
||||
try {
|
||||
minSdkValue = Integer.parseInt(minSdkVersion);
|
||||
} catch (NumberFormatException e) {
|
||||
// it's ok, it means minSdkVersion contains a (hopefully) valid codename.
|
||||
}
|
||||
|
||||
AndroidVersion projectVersion = projectTarget.getVersion();
|
||||
|
||||
if (minSdkValue != -1) {
|
||||
String codename = projectVersion.getCodename();
|
||||
if (codename != null) {
|
||||
// integer minSdk when the target is a preview => fatal error
|
||||
String msg = String.format(
|
||||
"Platform %1$s is a preview and requires appication manifests to set %2$s to '%3$s'",
|
||||
codename, AndroidManifestParser.ATTRIBUTE_MIN_SDK_VERSION,
|
||||
codename);
|
||||
AdtPlugin.printErrorToConsole(project, msg);
|
||||
BaseProjectHelper.addMarker(manifest, AdtConstants.MARKER_ADT, msg,
|
||||
IMarker.SEVERITY_ERROR);
|
||||
stopBuild(msg);
|
||||
} else if (minSdkValue < projectVersion.getApiLevel()) {
|
||||
// integer minSdk is not high enough for the target => warning
|
||||
String msg = String.format(
|
||||
"Manifest min SDK version (%1$d) is lower than project target API level (%2$d)",
|
||||
minSdkVersion, projectVersion.getApiLevel());
|
||||
AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, msg);
|
||||
BaseProjectHelper.addMarker(manifest, AdtConstants.MARKER_ADT, msg,
|
||||
IMarker.SEVERITY_WARNING);
|
||||
}
|
||||
} else {
|
||||
// looks like the min sdk is a codename, check it matches the codename
|
||||
// of the platform
|
||||
String codename = projectVersion.getCodename();
|
||||
if (codename == null) {
|
||||
// platform is not a preview => fatal error
|
||||
String msg = String.format(
|
||||
"Manifest attribute '%1$s' is set to '%2$s'. Integer is expected.",
|
||||
AndroidManifestParser.ATTRIBUTE_MIN_SDK_VERSION, codename);
|
||||
AdtPlugin.printErrorToConsole(project, msg);
|
||||
BaseProjectHelper.addMarker(manifest, AdtConstants.MARKER_ADT, msg,
|
||||
IMarker.SEVERITY_ERROR);
|
||||
stopBuild(msg);
|
||||
} else if (codename.equals(minSdkVersion) == false) {
|
||||
// platform and manifest codenames don't match => fatal error.
|
||||
String msg = String.format(
|
||||
"Value of manifest attribute '%1$s' does not match platform codename '%2$s'",
|
||||
AndroidManifestParser.ATTRIBUTE_MIN_SDK_VERSION, codename);
|
||||
AdtPlugin.printErrorToConsole(project, msg);
|
||||
BaseProjectHelper.addMarker(manifest, AdtConstants.MARKER_ADT, msg,
|
||||
IMarker.SEVERITY_ERROR);
|
||||
stopBuild(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (javaPackage == null || javaPackage.length() == 0) {
|
||||
@@ -332,11 +379,11 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
AndroidConstants.FN_ANDROID_MANIFEST);
|
||||
AdtPlugin.printErrorToConsole(project, msg);
|
||||
markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
|
||||
|
||||
|
||||
// This interrupts the build. The next builders will not run.
|
||||
stopBuild(msg);
|
||||
}
|
||||
|
||||
|
||||
// at this point we have the java package. We need to make sure it's not a different
|
||||
// package than the previous one that were built.
|
||||
if (javaPackage.equals(mManifestPackage) == false) {
|
||||
@@ -345,64 +392,64 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
if (mManifestPackage != null) {
|
||||
AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
|
||||
Messages.Checking_Package_Change);
|
||||
|
||||
|
||||
FixLaunchConfig flc = new FixLaunchConfig(project, mManifestPackage,
|
||||
javaPackage);
|
||||
flc.start();
|
||||
}
|
||||
|
||||
|
||||
// now we delete the generated classes from their previous location
|
||||
deleteObsoleteGeneratedClass(AndroidConstants.FN_RESOURCE_CLASS,
|
||||
mManifestPackage);
|
||||
deleteObsoleteGeneratedClass(AndroidConstants.FN_MANIFEST_CLASS,
|
||||
mManifestPackage);
|
||||
|
||||
|
||||
// record the new manifest package, and save it.
|
||||
mManifestPackage = javaPackage;
|
||||
saveProjectStringProperty(PROPERTY_PACKAGE, mManifestPackage);
|
||||
}
|
||||
|
||||
|
||||
if (mMustCompileResources) {
|
||||
// we need to figure out where to store the R class.
|
||||
// get the parent folder for R.java and update mManifestPackageSourceFolder
|
||||
IFolder packageFolder = getGenManifestPackageFolder(project);
|
||||
|
||||
|
||||
// get the resource folder
|
||||
IFolder resFolder = project.getFolder(AndroidConstants.WS_RESOURCES);
|
||||
|
||||
|
||||
// get the file system path
|
||||
IPath outputLocation = mGenFolder.getLocation();
|
||||
IPath resLocation = resFolder.getLocation();
|
||||
IPath manifestLocation = manifest.getLocation();
|
||||
|
||||
|
||||
// those locations have to exist for us to do something!
|
||||
if (outputLocation != null && resLocation != null
|
||||
&& manifestLocation != null) {
|
||||
String osOutputPath = outputLocation.toOSString();
|
||||
String osResPath = resLocation.toOSString();
|
||||
String osManifestPath = manifestLocation.toOSString();
|
||||
|
||||
|
||||
// remove the aapt markers
|
||||
removeMarkersFromFile(manifest, AndroidConstants.MARKER_AAPT_COMPILE);
|
||||
removeMarkersFromContainer(resFolder, AndroidConstants.MARKER_AAPT_COMPILE);
|
||||
|
||||
|
||||
AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
|
||||
Messages.Preparing_Generated_Files);
|
||||
|
||||
|
||||
// since the R.java file may be already existing in read-only
|
||||
// mode we need to make it readable so that aapt can overwrite
|
||||
// it
|
||||
IFile rJavaFile = packageFolder.getFile(AndroidConstants.FN_RESOURCE_CLASS);
|
||||
|
||||
|
||||
// do the same for the Manifest.java class
|
||||
IFile manifestJavaFile = packageFolder.getFile(
|
||||
AndroidConstants.FN_MANIFEST_CLASS);
|
||||
|
||||
|
||||
// we actually need to delete the manifest.java as it may become empty and
|
||||
// in this case aapt doesn't generate an empty one, but instead doesn't
|
||||
// touch it.
|
||||
manifestJavaFile.delete(true, null);
|
||||
|
||||
|
||||
// launch aapt: create the command line
|
||||
ArrayList<String> array = new ArrayList<String>();
|
||||
array.add(projectTarget.getPath(IAndroidTarget.AAPT));
|
||||
@@ -419,7 +466,7 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
array.add(osResPath);
|
||||
array.add("-I"); //$NON-NLS-1$
|
||||
array.add(projectTarget.getPath(IAndroidTarget.ANDROID_JAR));
|
||||
|
||||
|
||||
if (AdtPlugin.getBuildVerbosity() == AdtConstants.BUILD_VERBOSE) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String c : array) {
|
||||
@@ -429,23 +476,23 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
String cmd_line = sb.toString();
|
||||
AdtPlugin.printToConsole(project, cmd_line);
|
||||
}
|
||||
|
||||
|
||||
// launch
|
||||
int execError = 1;
|
||||
try {
|
||||
// launch the command line process
|
||||
Process process = Runtime.getRuntime().exec(
|
||||
array.toArray(new String[array.size()]));
|
||||
|
||||
|
||||
// list to store each line of stderr
|
||||
ArrayList<String> results = new ArrayList<String>();
|
||||
|
||||
|
||||
// get the output and return code from the process
|
||||
execError = grabProcessOutput(process, results);
|
||||
|
||||
|
||||
// attempt to parse the error output
|
||||
boolean parsingError = parseAaptOutput(results, project);
|
||||
|
||||
|
||||
// if we couldn't parse the output we display it in the console.
|
||||
if (parsingError) {
|
||||
if (execError != 0) {
|
||||
@@ -455,7 +502,7 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
project, results.toArray());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (execError != 0) {
|
||||
// if the exec failed, and we couldn't parse the error output
|
||||
// (and therefore not all files that should have been marked,
|
||||
@@ -464,10 +511,10 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
markProject(AdtConstants.MARKER_ADT, Messages.Unparsed_AAPT_Errors,
|
||||
IMarker.SEVERITY_ERROR);
|
||||
}
|
||||
|
||||
|
||||
AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
|
||||
Messages.AAPT_Error);
|
||||
|
||||
|
||||
// abort if exec failed.
|
||||
// This interrupts the build. The next builders will not run.
|
||||
stopBuild(Messages.AAPT_Error);
|
||||
@@ -477,7 +524,7 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
// mark the project and exit
|
||||
String msg = String.format(Messages.AAPT_Exec_Error, array.get(0));
|
||||
markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
|
||||
|
||||
|
||||
// This interrupts the build. The next builders will not run.
|
||||
stopBuild(msg);
|
||||
} catch (InterruptedException e) {
|
||||
@@ -485,11 +532,11 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
// mark the project and exit
|
||||
String msg = String.format(Messages.AAPT_Exec_Error, array.get(0));
|
||||
markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
|
||||
|
||||
|
||||
// This interrupts the build. The next builders will not run.
|
||||
stopBuild(msg);
|
||||
}
|
||||
|
||||
|
||||
// if the return code was OK, we refresh the folder that
|
||||
// contains R.java to force a java recompile.
|
||||
if (execError == 0) {
|
||||
@@ -497,10 +544,10 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
// as derived.
|
||||
mDerivedProgressMonitor.addFile(rJavaFile);
|
||||
mDerivedProgressMonitor.addFile(manifestJavaFile);
|
||||
|
||||
|
||||
// build has been done. reset the state of the builder
|
||||
mMustCompileResources = false;
|
||||
|
||||
|
||||
// and store it
|
||||
saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES,
|
||||
mMustCompileResources);
|
||||
@@ -509,10 +556,10 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
} else {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
|
||||
// now handle the aidl stuff.
|
||||
boolean aidlStatus = handleAidl(projectTarget, sourceFolderPathList, monitor);
|
||||
|
||||
|
||||
if (aidlStatus == false && mMustCompileResources == false) {
|
||||
AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
|
||||
Messages.Nothing_To_Compile);
|
||||
@@ -540,14 +587,14 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
@Override
|
||||
protected void startupOnInitialize() {
|
||||
super.startupOnInitialize();
|
||||
|
||||
|
||||
mDerivedProgressMonitor = new DerivedProgressMonitor();
|
||||
|
||||
|
||||
IProject project = getProject();
|
||||
|
||||
// load the previous IFolder and java package.
|
||||
mManifestPackage = loadProjectStringProperty(PROPERTY_PACKAGE);
|
||||
|
||||
|
||||
// get the source folder in which all the Java files are created
|
||||
mGenFolder = project.getFolder(SdkConstants.FD_GEN_SOURCES);
|
||||
|
||||
@@ -555,14 +602,14 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
// recompile.
|
||||
mMustCompileResources = loadProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES, true);
|
||||
boolean mustCompileAidl = loadProjectBooleanProperty(PROPERTY_COMPILE_AIDL, true);
|
||||
|
||||
|
||||
// if we stored that we have to compile some aidl, we build the list that will compile them
|
||||
// all
|
||||
if (mustCompileAidl) {
|
||||
IJavaProject javaProject = JavaCore.create(project);
|
||||
ArrayList<IPath> sourceFolderPathList = BaseProjectHelper.getSourceClasspaths(
|
||||
javaProject);
|
||||
|
||||
|
||||
buildAidlCompilationList(project, sourceFolderPathList);
|
||||
}
|
||||
}
|
||||
@@ -576,7 +623,7 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
if (javaPackage == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IPath packagePath = getJavaPackagePath(javaPackage);
|
||||
IPath iPath = packagePath.append(filename);
|
||||
|
||||
@@ -614,10 +661,10 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
path.append(AndroidConstants.WS_SEP_CHAR);
|
||||
path.append(s);
|
||||
}
|
||||
|
||||
|
||||
return new Path(path.toString());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an {@link IFolder} (located inside the 'gen' source folder), that matches the
|
||||
* package defined in the manifest. This {@link IFolder} may not actually exist
|
||||
@@ -630,7 +677,7 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
throws CoreException {
|
||||
// get the path for the package
|
||||
IPath packagePath = getJavaPackagePath(mManifestPackage);
|
||||
|
||||
|
||||
// get a folder for this path under the 'gen' source folder, and return it.
|
||||
// This IFolder may not reference an actual existing folder.
|
||||
return mGenFolder.getFolder(packagePath);
|
||||
@@ -657,10 +704,10 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
command[index++] = projectTarget.getPath(IAndroidTarget.AIDL);
|
||||
command[index++] = "-p" + Sdk.getCurrent().getTarget(getProject()).getPath( //$NON-NLS-1$
|
||||
IAndroidTarget.ANDROID_AIDL);
|
||||
|
||||
|
||||
// since the path are relative to the workspace and not the project itself, we need
|
||||
// the workspace root.
|
||||
IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
|
||||
IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
|
||||
for (IPath p : sourceFolders) {
|
||||
IFolder f = wsRoot.getFolder(p);
|
||||
command[index++] = "-I" + f.getLocation().toOSString(); //$NON-NLS-1$
|
||||
@@ -686,7 +733,7 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
// get the path of the source file.
|
||||
IPath sourcePath = aidlData.aidlFile.getLocation();
|
||||
String osSourcePath = sourcePath.toOSString();
|
||||
|
||||
|
||||
IFile javaFile = getGenDestinationFile(aidlData, true /*createFolders*/, monitor);
|
||||
|
||||
// finish to set the command line.
|
||||
@@ -755,15 +802,15 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
IPath packagePath = aidlData.aidlFile.getFullPath().removeFirstSegments(
|
||||
segmentToSourceFolderCount).removeLastSegments(1);
|
||||
Path destinationPath = new Path(packagePath.toString());
|
||||
|
||||
|
||||
// get an IFolder for this path. It's relative to the 'gen' folder already
|
||||
IFolder destinationFolder = mGenFolder.getFolder(destinationPath);
|
||||
|
||||
|
||||
// create it if needed.
|
||||
if (destinationFolder.exists() == false && createFolders) {
|
||||
createFolder(destinationFolder, monitor);
|
||||
}
|
||||
|
||||
|
||||
// Build the Java file name from the aidl name.
|
||||
String javaName = aidlData.aidlFile.getName().replaceAll(AndroidConstants.RE_AIDL_EXT,
|
||||
AndroidConstants.DOT_JAVA);
|
||||
@@ -776,15 +823,15 @@ public class PreCompilerBuilder extends BaseBuilder {
|
||||
/**
|
||||
* Creates the destination folder. Because
|
||||
* {@link IFolder#create(boolean, boolean, IProgressMonitor)} only works if the parent folder
|
||||
* already exists, this goes and ensure that all the parent folders actually exist, or it
|
||||
* already exists, this goes and ensure that all the parent folders actually exist, or it
|
||||
* creates them as well.
|
||||
* @param destinationFolder The folder to create
|
||||
* @param monitor the {@link IProgressMonitor},
|
||||
* @throws CoreException
|
||||
* @throws CoreException
|
||||
*/
|
||||
private void createFolder(IFolder destinationFolder, IProgressMonitor monitor)
|
||||
throws CoreException {
|
||||
|
||||
|
||||
// check the parent exist and create if necessary.
|
||||
IContainer parent = destinationFolder.getParent();
|
||||
if (parent.getType() == IResource.FOLDER && parent.exists() == false) {
|
||||
|
||||
@@ -44,16 +44,16 @@ import java.util.ArrayList;
|
||||
* {@link PreCompilerBuilder}:
|
||||
* <ul><li>R.java/Manifest.java generated by compiling the resources</li>
|
||||
* <li>Any Java files generated by <code>aidl</code></li></ul>.
|
||||
*
|
||||
*
|
||||
* Therefore it looks for the following:
|
||||
* <ul><li>Any modification in the resource folder</li>
|
||||
* <li>Removed files from the source folder receiving generated Java files</li>
|
||||
* <li>Any modification to aidl files.</li>
|
||||
*
|
||||
*
|
||||
*/
|
||||
class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
|
||||
IResourceDeltaVisitor {
|
||||
|
||||
|
||||
private enum AidlType {
|
||||
UNKNOWN, INTERFACE, PARCELABLE;
|
||||
}
|
||||
@@ -73,7 +73,7 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
|
||||
* into R.java
|
||||
*/
|
||||
private boolean mCompileResources = false;
|
||||
|
||||
|
||||
/**
|
||||
* Aidl force recompilation flag. If true, we'll attempt to recompile all aidl files.
|
||||
*/
|
||||
@@ -84,14 +84,14 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
|
||||
|
||||
/** List of .aidl files that have been removed. */
|
||||
private final ArrayList<AidlData> mAidlToRemove = new ArrayList<AidlData>();
|
||||
|
||||
|
||||
/** Manifest check/parsing flag. */
|
||||
private boolean mCheckedManifestXml = false;
|
||||
|
||||
/** Application Package, gathered from the parsing of the manifest */
|
||||
private String mJavaPackage = null;
|
||||
/** minSDKVersion attribute value, gathered from the parsing of the manifest */
|
||||
private int mMinSdkVersion = AndroidManifestParser.INVALID_MIN_SDK;
|
||||
private String mMinSdkVersion = null;
|
||||
|
||||
// Internal usage fields.
|
||||
/**
|
||||
@@ -126,7 +126,7 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
|
||||
public boolean getForceAidlCompile() {
|
||||
return mForceAidlCompile;
|
||||
}
|
||||
|
||||
|
||||
public ArrayList<AidlData> getAidlToCompile() {
|
||||
return mAidlToCompile;
|
||||
}
|
||||
@@ -134,7 +134,7 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
|
||||
public ArrayList<AidlData> getAidlToRemove() {
|
||||
return mAidlToRemove;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the manifest file was parsed/checked for error during the resource delta
|
||||
* visiting.
|
||||
@@ -142,7 +142,7 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
|
||||
public boolean getCheckedManifestXml() {
|
||||
return mCheckedManifestXml;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the manifest package if the manifest was checked/parsed.
|
||||
* <p/>
|
||||
@@ -162,16 +162,16 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
|
||||
/**
|
||||
* Returns the minSDkVersion attribute from the manifest if it was checked/parsed.
|
||||
* <p/>
|
||||
* This can return {@link AndroidManifestParser#INVALID_MIN_SDK} in two cases:
|
||||
* This can return null in two cases:
|
||||
* <ul>
|
||||
* <li>The manifest was not part of the resource change delta, and the manifest was
|
||||
* not checked/parsed ({@link #getCheckedManifestXml()} returns <code>false</code>)</li>
|
||||
* <li>The manifest was parsed ({@link #getCheckedManifestXml()} returns <code>true</code>),
|
||||
* but the package declaration is missing</li>
|
||||
* </ul>
|
||||
* @return the minSdkVersion or {@link AndroidManifestParser#INVALID_MIN_SDK}.
|
||||
* @return the minSdkVersion or null.
|
||||
*/
|
||||
public int getMinSdkVersion() {
|
||||
public String getMinSdkVersion() {
|
||||
return mMinSdkVersion;
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
|
||||
// parse the manifest for errors
|
||||
AndroidManifestParser parser = BaseProjectHelper.parseManifestForError(
|
||||
(IFile)resource, this);
|
||||
|
||||
|
||||
if (parser != null) {
|
||||
mJavaPackage = parser.getPackage();
|
||||
mMinSdkVersion = parser.getApiLevelRequirement();
|
||||
@@ -287,19 +287,19 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
|
||||
// Look for the source aidl file in all the source folders.
|
||||
String aidlFileName = fileName.replaceAll(AndroidConstants.RE_JAVA_EXT,
|
||||
AndroidConstants.DOT_AIDL);
|
||||
|
||||
|
||||
for (IPath sourceFolderPath : mSourceFolders) {
|
||||
// do not search in the current source folder as it is the 'gen' folder.
|
||||
if (sourceFolderPath.equals(mSourceFolder.getFullPath())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
IFolder sourceFolder = getFolder(sourceFolderPath);
|
||||
if (sourceFolder != null) {
|
||||
// go recursively, segment by segment.
|
||||
// index starts at 2 (0 is project, 1 is 'gen'
|
||||
// index starts at 2 (0 is project, 1 is 'gen'
|
||||
IFile sourceFile = findFile(sourceFolder, segments, 2, aidlFileName);
|
||||
|
||||
|
||||
if (sourceFile != null) {
|
||||
// found the source. add it to the list of files to compile
|
||||
mAidlToCompile.add(new AidlData(sourceFolder, sourceFile));
|
||||
@@ -331,7 +331,7 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
|
||||
if (AndroidConstants.EXT_AIDL.equalsIgnoreCase(ext)) {
|
||||
// first check whether it's a regular file or a parcelable.
|
||||
AidlType type = getAidlType(file);
|
||||
|
||||
|
||||
if (type == AidlType.INTERFACE) {
|
||||
if (kind == IResourceDelta.REMOVED) {
|
||||
// we'll have to remove the generated file.
|
||||
@@ -423,7 +423,7 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
|
||||
path.segment(1).equals(SdkConstants.FD_GEN_SOURCES);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// check if we are on the way to a source folder.
|
||||
int count = sourceFolderPath.matchingFirstSegments(path);
|
||||
if (count == path.segmentCount()) {
|
||||
@@ -443,7 +443,7 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Searches for and return a file in a folder. The file is defined by its segments, and a new
|
||||
* name (replacing the last segment).
|
||||
@@ -482,10 +482,10 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
|
||||
if (resource != null && resource.exists() && resource.getType() == IResource.FOLDER) {
|
||||
return (IFolder)resource;
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the type of the aidl file. Aidl files can either declare interfaces, or declare
|
||||
* parcelables. This method will attempt to parse the file and return the type. If the type
|
||||
|
||||
@@ -310,12 +310,12 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
|
||||
Object[] choices = null;
|
||||
if (attrInfo.isInValue) {
|
||||
// Editing an attribute's value... Get the attribute name and then the
|
||||
// possible choice for the tuple(parent,attribute)
|
||||
// possible choices for the tuple(parent,attribute)
|
||||
String value = attrInfo.value;
|
||||
if (value.startsWith("'") || value.startsWith("\"")) { //$NON-NLS-1$ //$NON-NLS-2$
|
||||
value = value.substring(1);
|
||||
// The prefix that was found at the beginning only scan for characters
|
||||
// valid of tag name. We now know the real prefix for this attribute's
|
||||
// valid for tag name. We now know the real prefix for this attribute's
|
||||
// value, which is needed to generate the completion choices below.
|
||||
attrInfo.correctedPrefix = value;
|
||||
} else {
|
||||
@@ -772,7 +772,7 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
|
||||
IDescriptorProvider descriptorProvider = data.getDescriptorProvider(mDescriptorId);
|
||||
|
||||
if (descriptorProvider != null) {
|
||||
mRootDescriptor = new ElementDescriptor("",
|
||||
mRootDescriptor = new ElementDescriptor("", //$NON-NLS-1$
|
||||
descriptorProvider.getRootElementDescriptors());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ import java.net.URL;
|
||||
* source editor. This can be a no-op if desired.
|
||||
*/
|
||||
public abstract class AndroidEditor extends FormEditor implements IResourceChangeListener {
|
||||
|
||||
|
||||
/** Preference name for the current page of this file */
|
||||
private static final String PREF_CURRENT_PAGE = "_current_page";
|
||||
|
||||
@@ -91,7 +91,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
|
||||
/** Width hint for text fields. Helps the grid layout resize properly on smaller screens */
|
||||
public static final int TEXT_WIDTH_HINT = 50;
|
||||
|
||||
|
||||
/** Page index of the text editor (always the last page) */
|
||||
private int mTextPageIndex;
|
||||
/** The text editor */
|
||||
@@ -108,7 +108,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
public AndroidEditor() {
|
||||
super();
|
||||
ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
|
||||
|
||||
|
||||
mTargetListener = new ITargetChangeListener() {
|
||||
public void onProjectTargetChange(IProject changedProject) {
|
||||
if (changedProject == getProject()) {
|
||||
@@ -118,7 +118,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
|
||||
public void onTargetsLoaded() {
|
||||
commitPages(false /* onSave */);
|
||||
|
||||
|
||||
// recreate the ui root node always
|
||||
initUiRootNode(true /*force*/);
|
||||
}
|
||||
@@ -133,14 +133,14 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
* UI node editor.
|
||||
*/
|
||||
abstract public UiElementNode getUiRootNode();
|
||||
|
||||
|
||||
/**
|
||||
* Creates the various form pages.
|
||||
* <p/>
|
||||
* Derived classes must implement this to add their own specific tabs.
|
||||
*/
|
||||
abstract protected void createFormPages();
|
||||
|
||||
|
||||
/**
|
||||
* Creates the initial UI Root Node, including the known mandatory elements.
|
||||
* @param force if true, a new UiManifestNode is recreated even if it already exists.
|
||||
@@ -150,9 +150,9 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
/**
|
||||
* Subclasses should override this method to process the new XML Model, which XML
|
||||
* root node is given.
|
||||
*
|
||||
*
|
||||
* The base implementation is empty.
|
||||
*
|
||||
*
|
||||
* @param xml_doc The XML document, if available, or null if none exists.
|
||||
*/
|
||||
protected void xmlModelChanged(Document xml_doc) {
|
||||
@@ -169,7 +169,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
createAndroidPages();
|
||||
selectDefaultPage(null /* defaultPageId */);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates the page for the Android Editors
|
||||
*/
|
||||
@@ -193,7 +193,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
|
||||
action = mTextEditor.getAction(ActionFactory.REDO.getId());
|
||||
bars.setGlobalActionHandler(ActionFactory.REDO.getId(), action);
|
||||
|
||||
|
||||
bars.updateActionBars();
|
||||
}
|
||||
}
|
||||
@@ -207,7 +207,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
if (defaultPageId == null) {
|
||||
if (getEditorInput() instanceof IFileEditorInput) {
|
||||
IFile file = ((IFileEditorInput) getEditorInput()).getFile();
|
||||
|
||||
|
||||
QualifiedName qname = new QualifiedName(AdtPlugin.PLUGIN_ID,
|
||||
getClass().getSimpleName() + PREF_CURRENT_PAGE);
|
||||
String pageId;
|
||||
@@ -234,7 +234,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes all the pages from the editor.
|
||||
*/
|
||||
@@ -247,10 +247,10 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
|
||||
/**
|
||||
* Overrides the parent's setActivePage to be able to switch to the xml editor.
|
||||
*
|
||||
*
|
||||
* If the special pageId TEXT_EDITOR_ID is given, switches to the mTextPageIndex page.
|
||||
* This is needed because the editor doesn't actually derive from IFormPage and thus
|
||||
* doesn't have the get-by-page-id method. In this case, the method returns null since
|
||||
* doesn't have the get-by-page-id method. In this case, the method returns null since
|
||||
* IEditorPart does not implement IFormPage.
|
||||
*/
|
||||
@Override
|
||||
@@ -262,18 +262,18 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
return super.setActivePage(pageId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Notifies this multi-page editor that the page with the given id has been
|
||||
* activated. This method is called when the user selects a different tab.
|
||||
*
|
||||
*
|
||||
* @see MultiPageEditorPart#pageChange(int)
|
||||
*/
|
||||
@Override
|
||||
protected void pageChange(int newPageIndex) {
|
||||
super.pageChange(newPageIndex);
|
||||
|
||||
|
||||
if (getEditorInput() instanceof IFileEditorInput) {
|
||||
IFile file = ((IFileEditorInput) getEditorInput()).getFile();
|
||||
|
||||
@@ -288,9 +288,9 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies this listener that some resource changes
|
||||
* Notifies this listener that some resource changes
|
||||
* are happening, or have already happened.
|
||||
*
|
||||
*
|
||||
* Closes all project files on project close.
|
||||
* @see IResourceChangeListener
|
||||
*/
|
||||
@@ -318,7 +318,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
* Initializes the editor part with a site and input.
|
||||
* <p/>
|
||||
* Checks that the input is an instance of {@link IFileEditorInput}.
|
||||
*
|
||||
*
|
||||
* @see FormEditor
|
||||
*/
|
||||
@Override
|
||||
@@ -330,7 +330,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
|
||||
/**
|
||||
* Removes attached listeners.
|
||||
*
|
||||
*
|
||||
* @see WorkbenchPart
|
||||
*/
|
||||
@Override
|
||||
@@ -341,7 +341,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
if (mXmlModelStateListener != null) {
|
||||
xml_model.removeModelStateListener(mXmlModelStateListener);
|
||||
}
|
||||
|
||||
|
||||
} finally {
|
||||
xml_model.releaseFromRead();
|
||||
}
|
||||
@@ -355,7 +355,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Commit all dirty pages then saves the contents of the text editor.
|
||||
* <p/>
|
||||
@@ -403,7 +403,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
* The incorrect casting makes the original implementation crash due
|
||||
* to our {@link StructuredTextEditor} not being an {@link IFormPage}
|
||||
* so we have to override and duplicate to fix it.
|
||||
*
|
||||
*
|
||||
* @param onSave <code>true</code> if commit is performed as part
|
||||
* of the 'save' operation, <code>false</code> otherwise.
|
||||
* @since 3.3
|
||||
@@ -421,7 +421,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -451,8 +451,8 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
* <li> Links starting with "file:/" are simply sent to a local browser.
|
||||
* <li> Links starting with "page:" are expected to be an editor page id to switch to.
|
||||
* <li> Other links are ignored.
|
||||
* </ul>
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* @return A new hyper-link listener for FormText to use.
|
||||
*/
|
||||
public final IHyperlinkListener createHyperlinkListener() {
|
||||
@@ -478,7 +478,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
|
||||
/**
|
||||
* Open the http link into a browser
|
||||
*
|
||||
*
|
||||
* @param link The URL to open in a browser
|
||||
*/
|
||||
private void openLinkInBrowser(String link) {
|
||||
@@ -516,7 +516,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
"Error opening the Android XML editor. Is the document an XML file?");
|
||||
throw new RuntimeException("Android XML Editor Error", new CoreException(status));
|
||||
}
|
||||
|
||||
|
||||
IStructuredModel xml_model = getModelForRead();
|
||||
if (xml_model != null) {
|
||||
try {
|
||||
@@ -534,9 +534,9 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
"Android XML Editor Error", null, e.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the ISourceViewer associated with the Structured Text editor.
|
||||
* Returns the ISourceViewer associated with the Structured Text editor.
|
||||
*/
|
||||
public final ISourceViewer getStructuredSourceViewer() {
|
||||
if (mTextEditor != null) {
|
||||
@@ -558,13 +558,18 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a version of the model that has been shared for read.
|
||||
* <p/>
|
||||
* Callers <em>must</em> call model.releaseFromRead() when done, typically
|
||||
* in a try..finally clause.
|
||||
*
|
||||
*
|
||||
* Portability note: this uses getModelManager which is part of wst.sse.core; however
|
||||
* the interface returned is part of wst.sse.core.internal.provisional so we can
|
||||
* expect it to change in a distant future if they start cleaning their codebase,
|
||||
* however unlikely that is.
|
||||
*
|
||||
* @return The model for the XML document or null if cannot be obtained from the editor
|
||||
*/
|
||||
public final IStructuredModel getModelForRead() {
|
||||
@@ -576,14 +581,14 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version of the model that has been shared for edit.
|
||||
* <p/>
|
||||
* Callers <em>must</em> call model.releaseFromEdit() when done, typically
|
||||
* in a try..finally clause.
|
||||
*
|
||||
*
|
||||
* @return The model for the XML document or null if cannot be obtained from the editor
|
||||
*/
|
||||
public final IStructuredModel getModelForEdit() {
|
||||
@@ -595,7 +600,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to perform edits on the XML model whilst making sure the
|
||||
@@ -609,7 +614,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
* <p/>
|
||||
* The method is synchronous. As soon as the {@link IStructuredModel#changedModel()} method
|
||||
* is called, XML model listeners will be triggered.
|
||||
*
|
||||
*
|
||||
* @param edit_action Something that will change the XML.
|
||||
*/
|
||||
public final void editXmlModel(Runnable edit_action) {
|
||||
@@ -623,7 +628,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
model.releaseFromEdit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Starts an "undo recording" session. This is managed by the underlying undo manager
|
||||
* associated to the structured XML model.
|
||||
@@ -632,7 +637,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
* <p/>
|
||||
* beginUndoRecording/endUndoRecording calls can be nested (inner calls are ignored, only one
|
||||
* undo operation is recorded.)
|
||||
*
|
||||
*
|
||||
* @param label The label for the undo operation. Can be null but we should really try to put
|
||||
* something meaningful if possible.
|
||||
* @return True if the undo recording actually started, false if any kind of error occured.
|
||||
@@ -652,7 +657,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ends an "undo recording" session.
|
||||
* <p/>
|
||||
@@ -671,14 +676,14 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an "undo recording" session by calling the undoableAction runnable
|
||||
* using {@link #beginUndoRecording(String)} and {@link #endUndoRecording()}.
|
||||
* <p>
|
||||
* You can nest several calls to {@link #wrapUndoRecording(String, Runnable)}, only one
|
||||
* recording session will be created.
|
||||
*
|
||||
*
|
||||
* @param label The label for the undo operation. Can be null. Ideally we should really try
|
||||
* to put something meaningful if possible.
|
||||
*/
|
||||
@@ -693,7 +698,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the XML {@link Document} or null if we can't get it
|
||||
*/
|
||||
@@ -709,7 +714,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the {@link IProject} for the edited file.
|
||||
*/
|
||||
@@ -719,16 +724,16 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
if (input instanceof FileEditorInput) {
|
||||
FileEditorInput fileInput = (FileEditorInput)input;
|
||||
IFile inputFile = fileInput.getFile();
|
||||
|
||||
|
||||
if (inputFile != null) {
|
||||
return inputFile.getProject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the {@link AndroidTargetData} for the edited file.
|
||||
*/
|
||||
@@ -738,22 +743,22 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
Sdk currentSdk = Sdk.getCurrent();
|
||||
if (currentSdk != null) {
|
||||
IAndroidTarget target = currentSdk.getTarget(project);
|
||||
|
||||
|
||||
if (target != null) {
|
||||
return currentSdk.getTargetData(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Listen to changes in the underlying XML model in the structured editor.
|
||||
*/
|
||||
private class XmlModelStateListener implements IModelStateListener {
|
||||
|
||||
|
||||
/**
|
||||
* A model is about to be changed. This typically is initiated by one
|
||||
* client of the model, to signal a large change and/or a change to the
|
||||
@@ -765,7 +770,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
public void modelAboutToBeChanged(IStructuredModel model) {
|
||||
// pass
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Signals that the changes foretold by modelAboutToBeChanged have been
|
||||
* made. A typical use might be to refresh, or to resume processing that
|
||||
@@ -776,7 +781,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
public void modelChanged(IStructuredModel model) {
|
||||
xmlModelChanged(getXmlDocument(model));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Notifies that a model's dirty state has changed, and passes that state
|
||||
* in isDirty. A model becomes dirty when any change is made, and becomes
|
||||
@@ -787,7 +792,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
public void modelDirtyStateChanged(IStructuredModel model, boolean isDirty) {
|
||||
// pass
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A modelDeleted means the underlying resource has been deleted. The
|
||||
* model itself is not removed from model management until all have
|
||||
@@ -799,7 +804,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
public void modelResourceDeleted(IStructuredModel model) {
|
||||
// pass
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A model has been renamed or copied (as in saveAs..). In the renamed
|
||||
* case, the two paramenters are the same instance, and only contain the
|
||||
@@ -810,14 +815,14 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
|
||||
public void modelResourceMoved(IStructuredModel oldModel, IStructuredModel newModel) {
|
||||
// pass
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This AndroidEditor implementation of IModelChangedListener is empty.
|
||||
*/
|
||||
public void modelAboutToBeReinitialized(IStructuredModel structuredModel) {
|
||||
// pass
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This AndroidEditor implementation of IModelChangedListener is empty.
|
||||
*/
|
||||
|
||||
@@ -32,8 +32,10 @@ import org.eclipse.swt.widgets.Composite;
|
||||
*/
|
||||
public final class ReferenceAttributeDescriptor extends TextAttributeDescriptor {
|
||||
|
||||
/** The {@link ResourceType} that this reference attribute can accept. It can be null,
|
||||
* in which case any reference type can be used. */
|
||||
private ResourceType mResourceType;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a reference attributes that can contain any type of resources.
|
||||
* @param xmlLocalName The XML name of the attribute (case sensitive)
|
||||
@@ -46,7 +48,7 @@ public final class ReferenceAttributeDescriptor extends TextAttributeDescriptor
|
||||
String tooltip) {
|
||||
super(xmlLocalName, uiName, nsUri, tooltip);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a reference attributes that can contain a reference to a specific
|
||||
* {@link ResourceType}.
|
||||
@@ -58,14 +60,20 @@ public final class ReferenceAttributeDescriptor extends TextAttributeDescriptor
|
||||
* See {@link SdkConstants#NS_RESOURCES} for a common value.
|
||||
* @param tooltip A non-empty tooltip string or null
|
||||
*/
|
||||
public ReferenceAttributeDescriptor(ResourceType resourceType,
|
||||
public ReferenceAttributeDescriptor(ResourceType resourceType,
|
||||
String xmlLocalName, String uiName, String nsUri,
|
||||
String tooltip) {
|
||||
super(xmlLocalName, uiName, nsUri, tooltip);
|
||||
mResourceType = resourceType;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** Returns the {@link ResourceType} that this reference attribute can accept.
|
||||
* It can be null, in which case any reference type can be used. */
|
||||
public ResourceType getResourceType() {
|
||||
return mResourceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A new {@link UiResourceAttributeNode} linked to this reference descriptor.
|
||||
*/
|
||||
@@ -73,7 +81,7 @@ public final class ReferenceAttributeDescriptor extends TextAttributeDescriptor
|
||||
public UiAttributeNode createUiNode(UiElementNode uiParent) {
|
||||
return new UiResourceAttributeNode(mResourceType, this, uiParent);
|
||||
}
|
||||
|
||||
|
||||
// ------- IPropertyDescriptor Methods
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,9 +35,9 @@ import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
|
||||
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
|
||||
import com.android.ide.eclipse.adt.internal.wizards.actions.AvdManagerAction;
|
||||
import com.android.prefs.AndroidLocation.AndroidLocationException;
|
||||
import com.android.sdklib.AndroidVersion;
|
||||
import com.android.sdklib.IAndroidTarget;
|
||||
import com.android.sdklib.NullSdkLog;
|
||||
import com.android.sdklib.SdkManager;
|
||||
import com.android.sdklib.internal.avd.AvdManager;
|
||||
import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
|
||||
|
||||
@@ -274,16 +274,16 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
|
||||
* @param packageName the Android package name of the app
|
||||
* @param debugPackageName the Android package name to debug
|
||||
* @param debuggable the debuggable value of the app, or null if not set.
|
||||
* @param requiredApiVersionNumber the api version required by the app, or
|
||||
* {@link AndroidManifestParser#INVALID_MIN_SDK} if none.
|
||||
* @param requiredApiVersionNumber the api version required by the app, or null if none.
|
||||
* @param launchAction the action to perform after app sync
|
||||
* @param config the launch configuration
|
||||
* @param launch the launch object
|
||||
*/
|
||||
public void launch(final IProject project, String mode, IFile apk,
|
||||
String packageName, String debugPackageName, Boolean debuggable, int requiredApiVersionNumber,
|
||||
final IAndroidLaunchAction launchAction, final AndroidLaunchConfiguration config,
|
||||
final AndroidLaunch launch, IProgressMonitor monitor) {
|
||||
String packageName, String debugPackageName, Boolean debuggable,
|
||||
String requiredApiVersionNumber, final IAndroidLaunchAction launchAction,
|
||||
final AndroidLaunchConfiguration config, final AndroidLaunch launch,
|
||||
IProgressMonitor monitor) {
|
||||
|
||||
String message = String.format("Performing %1$s", launchAction.getLaunchDescription());
|
||||
AdtPlugin.printToConsole(project, message);
|
||||
@@ -398,17 +398,16 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
|
||||
} else {
|
||||
if (projectTarget.isPlatform()) { // means this can run on any device as long
|
||||
// as api level is high enough
|
||||
String apiString = d.getProperty(SdkManager.PROP_VERSION_SDK);
|
||||
try {
|
||||
int apiNumber = Integer.parseInt(apiString);
|
||||
if (apiNumber >= projectTarget.getApiVersionNumber()) {
|
||||
// device is compatible with project
|
||||
compatibleRunningAvds.put(d, null);
|
||||
continue;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// do nothing, we'll consider it a non compatible device below.
|
||||
AndroidVersion deviceVersion = Sdk.getDeviceVersion(d);
|
||||
if (deviceVersion.canRun(projectTarget.getVersion())) {
|
||||
// device is compatible with project
|
||||
compatibleRunningAvds.put(d, null);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// for non project platform, we can't be sure if a device can
|
||||
// run an application or not, since we don't query the device
|
||||
// for the list of optional libraries that it supports.
|
||||
}
|
||||
hasDevice = true;
|
||||
}
|
||||
@@ -544,9 +543,12 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
|
||||
AvdInfo defaultAvd = null;
|
||||
for (AvdInfo avd : avds) {
|
||||
if (projectTarget.isCompatibleBaseFor(avd.getTarget())) {
|
||||
// at this point we can ignore the code name issue since
|
||||
// IAndroidTarget.isCompatibleBaseFor() will already have filtered the non
|
||||
// compatible AVDs.
|
||||
if (defaultAvd == null ||
|
||||
avd.getTarget().getApiVersionNumber() <
|
||||
defaultAvd.getTarget().getApiVersionNumber()) {
|
||||
avd.getTarget().getVersion().getApiLevel() <
|
||||
defaultAvd.getTarget().getVersion().getApiLevel()) {
|
||||
defaultAvd = avd;
|
||||
}
|
||||
}
|
||||
@@ -654,47 +656,67 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
|
||||
if (device != null) {
|
||||
// check the app required API level versus the target device API level
|
||||
|
||||
String deviceApiVersionName = device.getProperty(IDevice.PROP_BUILD_VERSION);
|
||||
String value = device.getProperty(IDevice.PROP_BUILD_VERSION_NUMBER);
|
||||
int deviceApiVersionNumber = AndroidManifestParser.INVALID_MIN_SDK;
|
||||
String deviceVersion = device.getProperty(IDevice.PROP_BUILD_VERSION);
|
||||
String deviceApiLevelString = device.getProperty(IDevice.PROP_BUILD_API_LEVEL);
|
||||
String deviceCodeName = device.getProperty(IDevice.PROP_BUILD_CODENAME);
|
||||
|
||||
int deviceApiLevel = -1;
|
||||
try {
|
||||
deviceApiVersionNumber = Integer.parseInt(value);
|
||||
deviceApiLevel = Integer.parseInt(deviceApiLevelString);
|
||||
} catch (NumberFormatException e) {
|
||||
// pass, we'll keep the deviceVersionNumber value at 0.
|
||||
// pass, we'll keep the apiLevel value at -1.
|
||||
}
|
||||
|
||||
if (launchInfo.getRequiredApiVersionNumber() == AndroidManifestParser.INVALID_MIN_SDK) {
|
||||
// warn the API level requirement is not set.
|
||||
String requiredApiString = launchInfo.getRequiredApiVersionNumber();
|
||||
if (requiredApiString != null) {
|
||||
int requiredApi = -1;
|
||||
try {
|
||||
requiredApi = Integer.parseInt(requiredApiString);
|
||||
} catch (NumberFormatException e) {
|
||||
// pass, we'll keep requiredApi value at -1.
|
||||
}
|
||||
|
||||
if (requiredApi == -1) {
|
||||
// this means the manifest uses a codename for minSdkVersion
|
||||
// check that the device is using the same codename
|
||||
if (requiredApiString.equals(deviceCodeName) == false) {
|
||||
AdtPlugin.printErrorToConsole(launchInfo.getProject(), String.format(
|
||||
"ERROR: Application requires a device running '%1$s'!",
|
||||
requiredApiString));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// app requires a specific API level
|
||||
if (deviceApiLevel == -1) {
|
||||
AdtPlugin.printToConsole(launchInfo.getProject(),
|
||||
"WARNING: Unknown device API version!");
|
||||
} else if (deviceApiLevel < requiredApi) {
|
||||
String msg = String.format(
|
||||
"ERROR: Application requires API version %1$d. Device API version is %2$d (Android %3$s).",
|
||||
requiredApi, deviceApiLevel, deviceVersion);
|
||||
AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg);
|
||||
|
||||
// abort the launch
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// warn the application API level requirement is not set.
|
||||
AdtPlugin.printErrorToConsole(launchInfo.getProject(),
|
||||
"WARNING: Application does not specify an API level requirement!");
|
||||
|
||||
// and display the target device API level (if known)
|
||||
if (deviceApiVersionName == null ||
|
||||
deviceApiVersionNumber == AndroidManifestParser.INVALID_MIN_SDK) {
|
||||
if (deviceApiLevel == -1) {
|
||||
AdtPlugin.printErrorToConsole(launchInfo.getProject(),
|
||||
"WARNING: Unknown device API version!");
|
||||
} else {
|
||||
AdtPlugin.printErrorToConsole(launchInfo.getProject(), String.format(
|
||||
"Device API version is %1$d (Android %2$s)", deviceApiVersionNumber,
|
||||
deviceApiVersionName));
|
||||
}
|
||||
} else { // app requires a specific API level
|
||||
if (deviceApiVersionName == null ||
|
||||
deviceApiVersionNumber == AndroidManifestParser.INVALID_MIN_SDK) {
|
||||
AdtPlugin.printToConsole(launchInfo.getProject(),
|
||||
"WARNING: Unknown device API version!");
|
||||
} else if (deviceApiVersionNumber < launchInfo.getRequiredApiVersionNumber()) {
|
||||
String msg = String.format(
|
||||
"ERROR: Application requires API version %1$d. Device API version is %2$d (Android %3$s).",
|
||||
launchInfo.getRequiredApiVersionNumber(), deviceApiVersionNumber,
|
||||
deviceApiVersionName);
|
||||
AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg);
|
||||
|
||||
// abort the launch
|
||||
return false;
|
||||
"Device API version is %1$d (Android %2$s)", deviceApiLevel,
|
||||
deviceVersion));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// now checks that the device/app can be debugged (if needed)
|
||||
if (device.isEmulator() == false && launchInfo.isDebugMode()) {
|
||||
String debuggableDevice = device.getProperty(IDevice.PROP_DEBUGGABLE);
|
||||
@@ -1521,7 +1543,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
|
||||
/**
|
||||
* Get the stderr/stdout outputs of a process and return when the process is done.
|
||||
* Both <b>must</b> be read or the process will block on windows.
|
||||
* @param process The process to get the ouput from
|
||||
* @param process The process to get the output from
|
||||
*/
|
||||
private void grabEmulatorOutput(final Process process) {
|
||||
// read the lines as they come. if null is returned, it's
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.android.ide.eclipse.adt.internal.launch;
|
||||
|
||||
import com.android.ddmlib.IDevice;
|
||||
import com.android.ide.eclipse.adt.internal.project.AndroidManifestParser;
|
||||
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
@@ -28,14 +27,14 @@ import org.eclipse.core.runtime.IProgressMonitor;
|
||||
* application is launched.
|
||||
*/
|
||||
public final class DelayedLaunchInfo {
|
||||
|
||||
|
||||
/**
|
||||
* Used to indicate behavior when Android app already exists
|
||||
* Used to indicate behavior when Android app already exists
|
||||
*/
|
||||
enum InstallRetryMode {
|
||||
NEVER, ALWAYS, PROMPT;
|
||||
NEVER, ALWAYS, PROMPT;
|
||||
}
|
||||
|
||||
|
||||
/** The device on which to launch the app */
|
||||
private IDevice mDevice = null;
|
||||
|
||||
@@ -44,22 +43,21 @@ public final class DelayedLaunchInfo {
|
||||
|
||||
/** Package name */
|
||||
private final String mPackageName;
|
||||
|
||||
|
||||
/** Debug package name */
|
||||
private final String mDebugPackageName;
|
||||
|
||||
/** IFile to the package (.apk) file */
|
||||
private final IFile mPackageFile;
|
||||
|
||||
|
||||
/** debuggable attribute of the manifest file. */
|
||||
private final Boolean mDebuggable;
|
||||
|
||||
/** Required ApiVersionNumber by the app. {@link AndroidManifestParser#INVALID_MIN_SDK} means
|
||||
* no requirements */
|
||||
private final int mRequiredApiVersionNumber;
|
||||
|
||||
|
||||
/** Required Api level by the app. null means no requirements */
|
||||
private final String mRequiredApiVersionNumber;
|
||||
|
||||
private InstallRetryMode mRetryMode = InstallRetryMode.NEVER;
|
||||
|
||||
|
||||
/** Launch action. */
|
||||
private final IAndroidLaunchAction mLaunchAction;
|
||||
|
||||
@@ -78,23 +76,22 @@ public final class DelayedLaunchInfo {
|
||||
/** cancellation state of launch */
|
||||
private boolean mCancelled = false;
|
||||
|
||||
/**
|
||||
* Basic constructor with activity and package info.
|
||||
*
|
||||
/**
|
||||
* Basic constructor with activity and package info.
|
||||
*
|
||||
* @param project the eclipse project that corresponds to Android app
|
||||
* @param packageName package name of Android app
|
||||
* @param debugPackageName the package name of the Andriod app to debug
|
||||
* @param launchAction action to perform after app install
|
||||
* @param pack IFile to the package (.apk) file
|
||||
* @param debuggable debuggable attribute of the app's manifest file.
|
||||
* @param requiredApiVersionNumber required SDK version by the app.
|
||||
* {@link AndroidManifestParser#INVALID_MIN_SDK} means no requirements.
|
||||
* @param requiredApiVersionNumber required SDK version by the app. null means no requirements.
|
||||
* @param launch the launch object
|
||||
* @param monitor progress monitor for launch
|
||||
*/
|
||||
public DelayedLaunchInfo(IProject project, String packageName, String debugPackageName,
|
||||
IAndroidLaunchAction launchAction, IFile pack, Boolean debuggable,
|
||||
int requiredApiVersionNumber, AndroidLaunch launch, IProgressMonitor monitor) {
|
||||
IAndroidLaunchAction launchAction, IFile pack, Boolean debuggable,
|
||||
String requiredApiVersionNumber, AndroidLaunch launch, IProgressMonitor monitor) {
|
||||
mProject = project;
|
||||
mPackageName = packageName;
|
||||
mDebugPackageName = debugPackageName;
|
||||
@@ -112,7 +109,7 @@ public final class DelayedLaunchInfo {
|
||||
public IDevice getDevice() {
|
||||
return mDevice;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the device on which to launch the app
|
||||
*/
|
||||
@@ -153,16 +150,16 @@ public final class DelayedLaunchInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if Android app is marked as debuggable in its manifest
|
||||
* @return true if Android app is marked as debuggable in its manifest
|
||||
*/
|
||||
public Boolean getDebuggable() {
|
||||
return mDebuggable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the required api version number for the Android app
|
||||
* @return the required api version number for the Android app.
|
||||
*/
|
||||
public int getRequiredApiVersionNumber() {
|
||||
public String getRequiredApiVersionNumber() {
|
||||
return mRequiredApiVersionNumber;
|
||||
}
|
||||
|
||||
@@ -195,7 +192,7 @@ public final class DelayedLaunchInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the launch progress monitor
|
||||
* @return the launch progress monitor
|
||||
*/
|
||||
public IProgressMonitor getMonitor() {
|
||||
return mMonitor;
|
||||
@@ -230,7 +227,7 @@ public final class DelayedLaunchInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if launch has been cancelled
|
||||
* Set if launch has been cancelled
|
||||
*/
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.mCancelled = cancelled;
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.android.ddmuilib.TableHelper;
|
||||
import com.android.ide.eclipse.adt.AdtPlugin;
|
||||
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
|
||||
import com.android.ide.eclipse.ddms.DdmsPlugin;
|
||||
import com.android.sdklib.AndroidVersion;
|
||||
import com.android.sdklib.IAndroidTarget;
|
||||
import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
|
||||
import com.android.sdkuilib.internal.widgets.AvdSelector;
|
||||
@@ -131,26 +132,19 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
|
||||
case 2:
|
||||
// check for compatibility.
|
||||
if (device.isEmulator() == false) { // physical device
|
||||
// get the api level of the device
|
||||
try {
|
||||
String apiValue = device.getProperty(
|
||||
IDevice.PROP_BUILD_VERSION_NUMBER);
|
||||
if (apiValue != null) {
|
||||
int api = Integer.parseInt(apiValue);
|
||||
if (api >= mProjectTarget.getApiVersionNumber()) {
|
||||
// if the project is compiling against an add-on, the optional
|
||||
// API may be missing from the device.
|
||||
return mProjectTarget.isPlatform() ?
|
||||
mMatchImage : mWarningImage;
|
||||
} else {
|
||||
return mNoMatchImage;
|
||||
}
|
||||
} else {
|
||||
return mWarningImage;
|
||||
// get the version of the device
|
||||
AndroidVersion deviceVersion = Sdk.getDeviceVersion(device);
|
||||
if (deviceVersion == null) {
|
||||
return mWarningImage;
|
||||
} else {
|
||||
if (deviceVersion.canRun(mProjectTarget.getVersion()) == false) {
|
||||
return mNoMatchImage;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// lets consider the device non compatible
|
||||
return mNoMatchImage;
|
||||
|
||||
// if the project is compiling against an add-on,
|
||||
// the optional API may be missing from the device.
|
||||
return mProjectTarget.isPlatform() ?
|
||||
mMatchImage : mWarningImage;
|
||||
}
|
||||
} else {
|
||||
// get the AvdInfo
|
||||
@@ -411,6 +405,7 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
|
||||
offsetComp.setLayout(layout);
|
||||
|
||||
mPreferredAvdSelector = new AvdSelector(offsetComp,
|
||||
mSdk.getSdkLocation(),
|
||||
mSdk.getAvdManager(),
|
||||
new NonRunningAvdFilter(),
|
||||
DisplayMode.SIMPLE_SELECTION);
|
||||
|
||||
@@ -195,7 +195,9 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
|
||||
// create the selector with no manager, we'll reset the manager every time this is
|
||||
// displayed to ensure we have the latest one (dialog is reused but SDK could have
|
||||
// been changed in between.
|
||||
mPreferredAvdSelector = new AvdSelector(offsetComp, null /* avd manager */,
|
||||
mPreferredAvdSelector = new AvdSelector(offsetComp,
|
||||
Sdk.getCurrent().getSdkLocation(),
|
||||
null /* avd manager */,
|
||||
DisplayMode.SIMPLE_CHECK);
|
||||
mPreferredAvdSelector.setTableHeightHint(100);
|
||||
mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() {
|
||||
|
||||
@@ -51,7 +51,7 @@ public class AndroidManifestParser {
|
||||
private final static String ATTRIBUTE_NAME = "name"; //$NON-NLS-1$
|
||||
private final static String ATTRIBUTE_PROCESS = "process"; //$NON-NLS-$
|
||||
private final static String ATTRIBUTE_DEBUGGABLE = "debuggable"; //$NON-NLS-$
|
||||
private final static String ATTRIBUTE_MIN_SDK_VERSION = "minSdkVersion"; //$NON-NLS-$
|
||||
public final static String ATTRIBUTE_MIN_SDK_VERSION = "minSdkVersion"; //$NON-NLS-$
|
||||
private final static String ATTRIBUTE_TARGET_PACKAGE = "targetPackage"; //$NON-NLS-1$
|
||||
private final static String ATTRIBUTE_EXPORTED = "exported"; //$NON-NLS-1$
|
||||
private final static String NODE_MANIFEST = "manifest"; //$NON-NLS-1$
|
||||
@@ -76,8 +76,6 @@ public class AndroidManifestParser {
|
||||
private final static String ACTION_MAIN = "android.intent.action.MAIN"; //$NON-NLS-1$
|
||||
private final static String CATEGORY_LAUNCHER = "android.intent.category.LAUNCHER"; //$NON-NLS-1$
|
||||
|
||||
public final static int INVALID_MIN_SDK = -1;
|
||||
|
||||
/**
|
||||
* Instrumentation info obtained from manifest
|
||||
*/
|
||||
@@ -179,9 +177,8 @@ public class AndroidManifestParser {
|
||||
private Set<String> mProcesses = null;
|
||||
/** debuggable attribute value. If null, the attribute is not present. */
|
||||
private Boolean mDebuggable = null;
|
||||
/** API level requirement. if {@link AndroidManifestParser#INVALID_MIN_SDK}
|
||||
* the attribute was not present. */
|
||||
private int mApiLevelRequirement = INVALID_MIN_SDK;
|
||||
/** API level requirement. if null the attribute was not present. */
|
||||
private String mApiLevelRequirement = null;
|
||||
/** List of all instrumentations declared by the manifest */
|
||||
private final ArrayList<Instrumentation> mInstrumentations =
|
||||
new ArrayList<Instrumentation>();
|
||||
@@ -258,10 +255,9 @@ public class AndroidManifestParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>minSdkVersion</code> attribute, or
|
||||
* {@link AndroidManifestParser#INVALID_MIN_SDK} if it's not set.
|
||||
* Returns the <code>minSdkVersion</code> attribute, or null if it's not set.
|
||||
*/
|
||||
int getApiLevelRequirement() {
|
||||
String getApiLevelRequirement() {
|
||||
return mApiLevelRequirement;
|
||||
}
|
||||
|
||||
@@ -331,16 +327,8 @@ public class AndroidManifestParser {
|
||||
|
||||
mValidLevel++;
|
||||
} else if (NODE_USES_SDK.equals(localName)) {
|
||||
value = getAttributeValue(attributes, ATTRIBUTE_MIN_SDK_VERSION,
|
||||
true /* hasNamespace */);
|
||||
|
||||
if (value != null) {
|
||||
try {
|
||||
mApiLevelRequirement = Integer.parseInt(value);
|
||||
} catch (NumberFormatException e) {
|
||||
handleError(e, -1 /* lineNumber */);
|
||||
}
|
||||
}
|
||||
mApiLevelRequirement = getAttributeValue(attributes,
|
||||
ATTRIBUTE_MIN_SDK_VERSION, true /* hasNamespace */);
|
||||
} else if (NODE_INSTRUMENTATION.equals(localName)) {
|
||||
processInstrumentationNode(attributes);
|
||||
}
|
||||
@@ -636,7 +624,7 @@ public class AndroidManifestParser {
|
||||
private final Activity mLauncherActivity;
|
||||
private final String[] mProcesses;
|
||||
private final Boolean mDebuggable;
|
||||
private final int mApiLevelRequirement;
|
||||
private final String mApiLevelRequirement;
|
||||
private final Instrumentation[] mInstrumentations;
|
||||
private final String[] mLibraries;
|
||||
|
||||
@@ -904,10 +892,9 @@ public class AndroidManifestParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>minSdkVersion</code> attribute, or {@link #INVALID_MIN_SDK}
|
||||
* if it's not set.
|
||||
* Returns the <code>minSdkVersion</code> attribute, or null if it's not set.
|
||||
*/
|
||||
public int getApiLevelRequirement() {
|
||||
public String getApiLevelRequirement() {
|
||||
return mApiLevelRequirement;
|
||||
}
|
||||
|
||||
@@ -939,13 +926,13 @@ public class AndroidManifestParser {
|
||||
* @param launcherActivity the launcher activity parser from the manifest.
|
||||
* @param processes the list of custom processes declared in the manifest.
|
||||
* @param debuggable the debuggable attribute, or null if not set.
|
||||
* @param apiLevelRequirement the minSdkVersion attribute value or 0 if not set.
|
||||
* @param apiLevelRequirement the minSdkVersion attribute value or null if not set.
|
||||
* @param instrumentations the list of instrumentations parsed from the manifest.
|
||||
* @param libraries the list of libraries in use parsed from the manifest.
|
||||
*/
|
||||
private AndroidManifestParser(String javaPackage, Activity[] activities,
|
||||
Activity launcherActivity, String[] processes, Boolean debuggable,
|
||||
int apiLevelRequirement, Instrumentation[] instrumentations, String[] libraries) {
|
||||
String apiLevelRequirement, Instrumentation[] instrumentations, String[] libraries) {
|
||||
mJavaPackage = javaPackage;
|
||||
mActivities = activities;
|
||||
mLauncherActivity = launcherActivity;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* 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
|
||||
@@ -47,7 +47,7 @@ import org.eclipse.ui.part.FileEditorInput;
|
||||
* Action executed when the "Extract String" menu item is invoked.
|
||||
* <p/>
|
||||
* The intent of the action is to start a refactoring that extracts a source string and
|
||||
* replaces it by an Android string resource ID.
|
||||
* replaces it by an Android string resource ID.
|
||||
* <p/>
|
||||
* Workflow:
|
||||
* <ul>
|
||||
@@ -74,6 +74,7 @@ public class ExtractStringAction implements IWorkbenchWindowActionDelegate {
|
||||
/** Keep track of the current workbench window. */
|
||||
private IWorkbenchWindow mWindow;
|
||||
private ITextSelection mSelection;
|
||||
private IEditorPart mEditor;
|
||||
private IFile mFile;
|
||||
|
||||
/**
|
||||
@@ -103,11 +104,12 @@ public class ExtractStringAction implements IWorkbenchWindowActionDelegate {
|
||||
|
||||
mSelection = null;
|
||||
mFile = null;
|
||||
|
||||
|
||||
if (selection instanceof ITextSelection) {
|
||||
mSelection = (ITextSelection) selection;
|
||||
if (mSelection.getLength() > 0) {
|
||||
mFile = getSelectedFile();
|
||||
mEditor = getActiveEditor();
|
||||
mFile = getSelectedFile(mEditor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +121,7 @@ public class ExtractStringAction implements IWorkbenchWindowActionDelegate {
|
||||
*/
|
||||
public void run(IAction action) {
|
||||
if (mSelection != null && mFile != null) {
|
||||
ExtractStringRefactoring ref = new ExtractStringRefactoring(mFile, mSelection);
|
||||
ExtractStringRefactoring ref = new ExtractStringRefactoring(mFile, mEditor, mSelection);
|
||||
RefactoringWizard wizard = new ExtractStringWizard(ref, mFile.getProject());
|
||||
RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(wizard);
|
||||
try {
|
||||
@@ -130,6 +132,21 @@ public class ExtractStringAction implements IWorkbenchWindowActionDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the active editor (hopefully matching our selection) or null.
|
||||
*/
|
||||
private IEditorPart getActiveEditor() {
|
||||
IWorkbenchWindow wwin = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
|
||||
if (wwin != null) {
|
||||
IWorkbenchPage page = wwin.getActivePage();
|
||||
if (page != null) {
|
||||
return page.getActiveEditor();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the active {@link IFile} (hopefully matching our selection) or null.
|
||||
* The file is only returned if it's a file from a project with an Android nature.
|
||||
@@ -138,33 +155,26 @@ public class ExtractStringAction implements IWorkbenchWindowActionDelegate {
|
||||
* for the refactoring. This check is performed when the refactoring is invoked since
|
||||
* it can then produce meaningful error messages as needed.
|
||||
*/
|
||||
private IFile getSelectedFile() {
|
||||
IWorkbenchWindow wwin = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
|
||||
if (wwin != null) {
|
||||
IWorkbenchPage page = wwin.getActivePage();
|
||||
if (page != null) {
|
||||
IEditorPart editor = page.getActiveEditor();
|
||||
if (editor != null) {
|
||||
IEditorInput input = editor.getEditorInput();
|
||||
|
||||
if (input instanceof FileEditorInput) {
|
||||
FileEditorInput fi = (FileEditorInput) input;
|
||||
IFile file = fi.getFile();
|
||||
if (file.exists()) {
|
||||
IProject proj = file.getProject();
|
||||
try {
|
||||
if (proj != null && proj.hasNature(AndroidConstants.NATURE)) {
|
||||
return file;
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
// ignore
|
||||
}
|
||||
private IFile getSelectedFile(IEditorPart editor) {
|
||||
if (editor != null) {
|
||||
IEditorInput input = editor.getEditorInput();
|
||||
|
||||
if (input instanceof FileEditorInput) {
|
||||
FileEditorInput fi = (FileEditorInput) input;
|
||||
IFile file = fi.getFile();
|
||||
if (file.exists()) {
|
||||
IProject proj = file.getProject();
|
||||
try {
|
||||
if (proj != null && proj.hasNature(AndroidConstants.NATURE)) {
|
||||
return file;
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.ModifyEvent;
|
||||
import org.eclipse.swt.events.ModifyListener;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Combo;
|
||||
@@ -42,6 +44,7 @@ import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeSet;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -59,7 +62,7 @@ class ExtractStringInputPage extends UserInputWizardPage implements IWizardPage
|
||||
private final IProject mProject;
|
||||
|
||||
/** Text field where the user enters the new ID to be generated or replaced with. */
|
||||
private Text mStringIdField;
|
||||
private Combo mStringIdCombo;
|
||||
/** Text field where the user enters the new string value. */
|
||||
private Text mStringValueField;
|
||||
/** The configuration selector, to select the resource path of the XML file. */
|
||||
@@ -132,7 +135,7 @@ class ExtractStringInputPage extends UserInputWizardPage implements IWizardPage
|
||||
// line: Textfield for string value (based on selection, if any)
|
||||
|
||||
Label label = new Label(group, SWT.NONE);
|
||||
label.setText("String");
|
||||
label.setText("&String");
|
||||
|
||||
String selectedString = ref.getTokenString();
|
||||
|
||||
@@ -156,24 +159,31 @@ class ExtractStringInputPage extends UserInputWizardPage implements IWizardPage
|
||||
|
||||
label = new Label(group, SWT.NONE);
|
||||
if (ref.getMode() == ExtractStringRefactoring.Mode.EDIT_SOURCE) {
|
||||
label.setText("Replace by R.string.");
|
||||
label.setText("&Replace by R.string.");
|
||||
} else if (ref.getMode() == ExtractStringRefactoring.Mode.SELECT_NEW_ID) {
|
||||
label.setText("New R.string.");
|
||||
label.setText("New &R.string.");
|
||||
} else {
|
||||
label.setText("ID R.string.");
|
||||
label.setText("ID &R.string.");
|
||||
}
|
||||
|
||||
mStringIdField = new Text(group, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
|
||||
mStringIdField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||
mStringIdField.setText(guessId(selectedString));
|
||||
mStringIdCombo = new Combo(group, SWT.SINGLE | SWT.LEFT | SWT.BORDER | SWT.DROP_DOWN);
|
||||
mStringIdCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||
mStringIdCombo.setText(guessId(selectedString));
|
||||
mStringIdCombo.forceFocus();
|
||||
|
||||
ref.setNewStringId(mStringIdField.getText().trim());
|
||||
ref.setNewStringId(mStringIdCombo.getText().trim());
|
||||
|
||||
mStringIdField.addModifyListener(new ModifyListener() {
|
||||
mStringIdCombo.addModifyListener(new ModifyListener() {
|
||||
public void modifyText(ModifyEvent e) {
|
||||
validatePage();
|
||||
}
|
||||
});
|
||||
mStringIdCombo.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
validatePage();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,7 +206,7 @@ class ExtractStringInputPage extends UserInputWizardPage implements IWizardPage
|
||||
|
||||
Label label;
|
||||
label = new Label(group, SWT.NONE);
|
||||
label.setText("Configuration:");
|
||||
label.setText("&Configuration:");
|
||||
|
||||
mConfigSelector = new ConfigurationSelector(group);
|
||||
GridData gd = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL);
|
||||
@@ -210,7 +220,7 @@ class ExtractStringInputPage extends UserInputWizardPage implements IWizardPage
|
||||
// line: selection of the output file
|
||||
|
||||
label = new Label(group, SWT.NONE);
|
||||
label.setText("Resource file:");
|
||||
label.setText("Resource &file:");
|
||||
|
||||
mResFileCombo = new Combo(group, SWT.DROP_DOWN);
|
||||
mResFileCombo.select(0);
|
||||
@@ -269,7 +279,7 @@ class ExtractStringInputPage extends UserInputWizardPage implements IWizardPage
|
||||
|
||||
// Analyze fatal errors.
|
||||
|
||||
String text = mStringIdField.getText().trim();
|
||||
String text = mStringIdCombo.getText().trim();
|
||||
if (text == null || text.length() < 1) {
|
||||
setErrorMessage("Please provide a resource ID.");
|
||||
success = false;
|
||||
@@ -313,9 +323,12 @@ class ExtractStringInputPage extends UserInputWizardPage implements IWizardPage
|
||||
ref.setTargetFile(resFile);
|
||||
sLastResFilePath.put(mProject.getFullPath().toPortableString(), resFile);
|
||||
|
||||
if (mXmlHelper.isResIdDuplicate(mProject, resFile, text)) {
|
||||
String msg = String.format("There's already a string item called '%1$s' in %2$s.",
|
||||
text, resFile);
|
||||
String idValue = mXmlHelper.valueOfStringId(mProject, resFile, text);
|
||||
if (idValue != null) {
|
||||
String msg = String.format("%1$s already contains a string ID '%2$s' with value '%3$s'.",
|
||||
resFile,
|
||||
text,
|
||||
idValue);
|
||||
if (ref.getMode() == ExtractStringRefactoring.Mode.SELECT_NEW_ID) {
|
||||
setErrorMessage(msg);
|
||||
success = false;
|
||||
@@ -341,6 +354,23 @@ class ExtractStringInputPage extends UserInputWizardPage implements IWizardPage
|
||||
return success;
|
||||
}
|
||||
|
||||
private void updateStringValueCombo() {
|
||||
String resFile = mResFileCombo.getText();
|
||||
Map<String, String> ids = mXmlHelper.getResIdsForFile(mProject, resFile);
|
||||
|
||||
// get the current text from the combo, to make sure we don't change it
|
||||
String currText = mStringIdCombo.getText();
|
||||
|
||||
// erase the choices and fill with the given ids
|
||||
mStringIdCombo.removeAll();
|
||||
mStringIdCombo.setItems(ids.keySet().toArray(new String[ids.size()]));
|
||||
|
||||
// set the current text to preserve it in case it changed
|
||||
if (!currText.equals(mStringIdCombo.getText())) {
|
||||
mStringIdCombo.setText(currText);
|
||||
}
|
||||
}
|
||||
|
||||
public class OnConfigSelectorUpdated implements Runnable, ModifyListener {
|
||||
|
||||
/** Regex pattern to parse a valid res path: it reads (/res/folder-name/)+(filename). */
|
||||
@@ -457,6 +487,7 @@ class ExtractStringInputPage extends UserInputWizardPage implements IWizardPage
|
||||
}
|
||||
|
||||
// finally validate the whole page
|
||||
updateStringValueCombo();
|
||||
validatePage();
|
||||
}
|
||||
|
||||
@@ -509,6 +540,7 @@ class ExtractStringInputPage extends UserInputWizardPage implements IWizardPage
|
||||
}
|
||||
}
|
||||
|
||||
updateStringValueCombo();
|
||||
validatePage();
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
* 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
|
||||
@@ -22,72 +22,88 @@ import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
/**
|
||||
*
|
||||
* An helper utility to get IDs out of an Android XML resource file.
|
||||
*/
|
||||
class XmlStringFileHelper {
|
||||
|
||||
/** A temporary cache of R.string IDs defined by a given xml file. The key is the
|
||||
* project path of the file, the data is a set of known string Ids for that file. */
|
||||
private HashMap<String,HashSet<String>> mResIdCache;
|
||||
* project path of the file, the data is a set of known string Ids for that file.
|
||||
*
|
||||
* Map type: map [String filename] => map [String id => String value].
|
||||
*/
|
||||
private HashMap<String, Map<String, String>> mResIdCache =
|
||||
new HashMap<String, Map<String, String>>();
|
||||
/** An instance of XPath, created lazily on demand. */
|
||||
private XPath mXPath;
|
||||
|
||||
public XmlStringFileHelper() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility method used by the wizard to check whether the given string ID is already
|
||||
* defined in the XML file which path is given.
|
||||
*
|
||||
* @param project The project contain the XML file.
|
||||
* Utility method used by the wizard to retrieve the actual value definition of a given
|
||||
* string ID.
|
||||
*
|
||||
* @param project The project contain the XML file.
|
||||
* @param xmlFileWsPath The project path of the XML file, e.g. "/res/values/strings.xml".
|
||||
* The given file may or may not exist.
|
||||
* @param stringId The string ID to find.
|
||||
* @return True if such a string ID is already defined.
|
||||
* @return The value string if the ID is defined, null otherwise.
|
||||
*/
|
||||
public boolean isResIdDuplicate(IProject project, String xmlFileWsPath, String stringId) {
|
||||
// This is going to be called many times on the same file.
|
||||
// Build a cache of the existing IDs for a given file.
|
||||
if (mResIdCache == null) {
|
||||
mResIdCache = new HashMap<String, HashSet<String>>();
|
||||
}
|
||||
HashSet<String> cache = mResIdCache.get(xmlFileWsPath);
|
||||
public String valueOfStringId(IProject project, String xmlFileWsPath, String stringId) {
|
||||
Map<String, String> cache = getResIdsForFile(project, xmlFileWsPath);
|
||||
return cache.get(stringId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that retrieves all the *string* IDs defined in the given Android resource
|
||||
* file. The instance maintains an internal cache so a given file is retrieved only once.
|
||||
* Callers should consider the set to be read-only.
|
||||
*
|
||||
* @param project The project contain the XML file.
|
||||
* @param xmlFileWsPath The project path of the XML file, e.g. "/res/values/strings.xml".
|
||||
* The given file may or may not exist.
|
||||
* @return The map of string IDs => values defined in the given file. Cached. Never null.
|
||||
*/
|
||||
public Map<String, String> getResIdsForFile(IProject project, String xmlFileWsPath) {
|
||||
Map<String, String> cache = mResIdCache.get(xmlFileWsPath);
|
||||
if (cache == null) {
|
||||
cache = getResIdsForFile(project, xmlFileWsPath);
|
||||
cache = internalGetResIdsForFile(project, xmlFileWsPath);
|
||||
mResIdCache.put(xmlFileWsPath, cache);
|
||||
}
|
||||
|
||||
return cache.contains(stringId);
|
||||
return cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract all the defined string IDs from a given file using XPath.
|
||||
* @param project The project contain the XML file.
|
||||
* @param project The project contain the XML file.
|
||||
* @param xmlFileWsPath The project path of the file to parse. It may not exist.
|
||||
* @return The set of all string IDs defined in the file. The returned set is always non
|
||||
* null. It is empty if the file does not exist.
|
||||
* @return The map of all string IDs => values defined in the file.
|
||||
* The returned set is always non null. It is empty if the file does not exist.
|
||||
*/
|
||||
private HashSet<String> getResIdsForFile(IProject project, String xmlFileWsPath) {
|
||||
HashSet<String> ids = new HashSet<String>();
|
||||
|
||||
private Map<String, String> internalGetResIdsForFile(IProject project, String xmlFileWsPath) {
|
||||
TreeMap<String, String> ids = new TreeMap<String, String>();
|
||||
|
||||
if (mXPath == null) {
|
||||
mXPath = AndroidXPathFactory.newXPath();
|
||||
}
|
||||
|
||||
// Access the project that contains the resource that contains the compilation unit
|
||||
IResource resource = project.getFile(xmlFileWsPath);
|
||||
|
||||
|
||||
if (resource != null && resource.exists() && resource.getType() == IResource.FILE) {
|
||||
InputSource source;
|
||||
try {
|
||||
@@ -97,25 +113,31 @@ class XmlStringFileHelper {
|
||||
// <resources>
|
||||
// <string name="ID">something</string>
|
||||
// </resources>
|
||||
|
||||
String xpathExpr = "/resources/string/@name"; //$NON-NLS-1$
|
||||
|
||||
|
||||
String xpathExpr = "/resources/string"; //$NON-NLS-1$
|
||||
|
||||
Object result = mXPath.evaluate(xpathExpr, source, XPathConstants.NODESET);
|
||||
if (result instanceof NodeList) {
|
||||
NodeList list = (NodeList) result;
|
||||
for (int n = list.getLength() - 1; n >= 0; n--) {
|
||||
String id = list.item(n).getNodeValue();
|
||||
ids.add(id);
|
||||
Node strNode = list.item(n);
|
||||
NamedNodeMap attrs = strNode.getAttributes();
|
||||
Node nameAttr = attrs.getNamedItem("name"); //$NON-NLS-1$
|
||||
if (nameAttr != null) {
|
||||
String id = nameAttr.getNodeValue();
|
||||
String text = strNode.getTextContent();
|
||||
ids.put(id, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch (CoreException e1) {
|
||||
// IFile.getContents failed. Ignore.
|
||||
} catch (XPathExpressionException e) {
|
||||
} catch (XPathExpressionException e2) {
|
||||
// mXPath.evaluate failed. Ignore.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
|
||||
@@ -366,7 +366,7 @@ public final class FolderConfiguration implements Comparable<FolderConfiguration
|
||||
}
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
return result == null ? null : result.toString();
|
||||
}
|
||||
|
||||
public int compareTo(FolderConfiguration folderConfig) {
|
||||
|
||||
@@ -66,10 +66,10 @@ import javax.management.InvalidAttributeValueException;
|
||||
* <li>Resource ID from <code>android.R</code></li>
|
||||
* <li>The list of permissions values from <code>android.Manifest$permission</code></li>
|
||||
* <li></li>
|
||||
* </ul>
|
||||
* </ul>
|
||||
*/
|
||||
public final class AndroidTargetParser {
|
||||
|
||||
|
||||
private static final String TAG = "Framework Resource Parser";
|
||||
private final IAndroidTarget mAndroidTarget;
|
||||
|
||||
@@ -79,11 +79,11 @@ public final class AndroidTargetParser {
|
||||
public AndroidTargetParser(IAndroidTarget platformTarget) {
|
||||
mAndroidTarget = platformTarget;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses the framework, collects all interesting information and stores them in the
|
||||
* {@link IAndroidTarget} given to the constructor.
|
||||
*
|
||||
*
|
||||
* @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
|
||||
* @return True if the SDK path was valid and parsing has been attempted.
|
||||
*/
|
||||
@@ -92,7 +92,7 @@ public final class AndroidTargetParser {
|
||||
SubMonitor progress = SubMonitor.convert(monitor,
|
||||
String.format("Parsing SDK %1$s", mAndroidTarget.getName()),
|
||||
14);
|
||||
|
||||
|
||||
AndroidTargetData targetData = new AndroidTargetData(mAndroidTarget);
|
||||
|
||||
// load DX.
|
||||
@@ -103,22 +103,22 @@ public final class AndroidTargetParser {
|
||||
String.format("dx.jar loading failed for target '%1$s'",
|
||||
mAndroidTarget.getFullName()));
|
||||
}
|
||||
|
||||
|
||||
// we have loaded dx.
|
||||
targetData.setDexWrapper(dexWrapper);
|
||||
progress.worked(1);
|
||||
|
||||
|
||||
// parse the rest of the data.
|
||||
|
||||
AndroidJarLoader classLoader =
|
||||
new AndroidJarLoader(mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
|
||||
|
||||
|
||||
preload(classLoader, progress.newChild(40, SubMonitor.SUPPRESS_NONE));
|
||||
|
||||
|
||||
if (progress.isCanceled()) {
|
||||
return Status.CANCEL_STATUS;
|
||||
}
|
||||
|
||||
|
||||
// get the resource Ids.
|
||||
progress.subTask("Resource IDs");
|
||||
IResourceRepository frameworkRepository = collectResourceIds(classLoader);
|
||||
@@ -172,7 +172,7 @@ public final class AndroidTargetParser {
|
||||
progress.subTask("Widgets and layouts");
|
||||
collectLayoutClasses(classLoader, attrsXmlParser, mainList, groupList,
|
||||
progress.newChild(1));
|
||||
|
||||
|
||||
if (progress.isCanceled()) {
|
||||
return Status.CANCEL_STATUS;
|
||||
}
|
||||
@@ -180,7 +180,7 @@ public final class AndroidTargetParser {
|
||||
ViewClassInfo[] layoutViewsInfo = mainList.toArray(new ViewClassInfo[mainList.size()]);
|
||||
ViewClassInfo[] layoutGroupsInfo = groupList.toArray(
|
||||
new ViewClassInfo[groupList.size()]);
|
||||
|
||||
|
||||
// collect the preferences classes.
|
||||
mainList.clear();
|
||||
groupList.clear();
|
||||
@@ -203,17 +203,17 @@ public final class AndroidTargetParser {
|
||||
Map<String, Map<String, Integer>> enumValueMap = attrsXmlParser.getEnumFlagValues();
|
||||
|
||||
Map<String, DeclareStyleableInfo> xmlAppWidgetMap = null;
|
||||
if (mAndroidTarget.getApiVersionNumber() >= 3) {
|
||||
if (mAndroidTarget.getVersion().getApiLevel() >= 3) {
|
||||
xmlAppWidgetMap = collectAppWidgetDefinitions(attrsXmlParser);
|
||||
}
|
||||
|
||||
if (progress.isCanceled()) {
|
||||
return Status.CANCEL_STATUS;
|
||||
}
|
||||
|
||||
|
||||
// From the information that was collected, create the pieces that will be put in
|
||||
// the PlatformData object.
|
||||
AndroidManifestDescriptors manifestDescriptors = new AndroidManifestDescriptors();
|
||||
AndroidManifestDescriptors manifestDescriptors = new AndroidManifestDescriptors();
|
||||
manifestDescriptors.updateDescriptors(manifestMap);
|
||||
progress.worked(1);
|
||||
|
||||
@@ -244,16 +244,16 @@ public final class AndroidTargetParser {
|
||||
preferencesInfo,
|
||||
preferenceGroupsInfo);
|
||||
progress.worked(1);
|
||||
|
||||
|
||||
// load the framework resources.
|
||||
ProjectResources resources = ResourceManager.getInstance().loadFrameworkResources(
|
||||
mAndroidTarget);
|
||||
progress.worked(1);
|
||||
|
||||
|
||||
// now load the layout lib bridge
|
||||
LayoutBridge layoutBridge = loadLayoutBridge();
|
||||
progress.worked(1);
|
||||
|
||||
|
||||
// and finally create the PlatformData with all that we loaded.
|
||||
targetData.setExtraData(frameworkRepository,
|
||||
manifestDescriptors,
|
||||
@@ -270,7 +270,7 @@ public final class AndroidTargetParser {
|
||||
mAndroidTarget.getOptionalLibraries(),
|
||||
resources,
|
||||
layoutBridge);
|
||||
|
||||
|
||||
Sdk.getCurrent().setTargetData(mAndroidTarget, targetData);
|
||||
|
||||
return Status.OK_STATUS;
|
||||
@@ -285,7 +285,7 @@ public final class AndroidTargetParser {
|
||||
* Preloads all "interesting" classes from the framework SDK jar.
|
||||
* <p/>
|
||||
* Currently this preloads all classes from the framework jar
|
||||
*
|
||||
*
|
||||
* @param classLoader The framework SDK jar classloader
|
||||
* @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
|
||||
*/
|
||||
@@ -303,7 +303,7 @@ public final class AndroidTargetParser {
|
||||
|
||||
/**
|
||||
* Creates an IResourceRepository for the framework resources.
|
||||
*
|
||||
*
|
||||
* @param classLoader The framework SDK jar classloader
|
||||
* @return a map of the resources, or null if it failed.
|
||||
*/
|
||||
@@ -311,7 +311,7 @@ public final class AndroidTargetParser {
|
||||
AndroidJarLoader classLoader) {
|
||||
try {
|
||||
Class<?> r = classLoader.loadClass(AndroidConstants.CLASS_R);
|
||||
|
||||
|
||||
if (r != null) {
|
||||
Map<ResourceType, List<ResourceItem>> map = parseRClass(r);
|
||||
if (map != null) {
|
||||
@@ -321,23 +321,23 @@ public final class AndroidTargetParser {
|
||||
} catch (ClassNotFoundException e) {
|
||||
AdtPlugin.logAndPrintError(e, TAG,
|
||||
"Collect resource IDs failed, class %1$s not found in %2$s", //$NON-NLS-1$
|
||||
AndroidConstants.CLASS_R,
|
||||
AndroidConstants.CLASS_R,
|
||||
mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse the R class and build the resource map.
|
||||
*
|
||||
*
|
||||
* @param rClass the Class object representing the Resources.
|
||||
* @return a map of the resource or null
|
||||
*/
|
||||
private Map<ResourceType, List<ResourceItem>> parseRClass(Class<?> rClass) {
|
||||
// get the sub classes.
|
||||
Class<?>[] classes = rClass.getClasses();
|
||||
|
||||
|
||||
if (classes.length > 0) {
|
||||
HashMap<ResourceType, List<ResourceItem>> map =
|
||||
new HashMap<ResourceType, List<ResourceItem>>();
|
||||
@@ -346,30 +346,30 @@ public final class AndroidTargetParser {
|
||||
for (int c = 0 ; c < classes.length ; c++) {
|
||||
Class<?> subClass = classes[c];
|
||||
String name = subClass.getSimpleName();
|
||||
|
||||
|
||||
// get the matching ResourceType
|
||||
ResourceType type = ResourceType.getEnum(name);
|
||||
if (type != null) {
|
||||
List<ResourceItem> list = new ArrayList<ResourceItem>();
|
||||
map.put(type, list);
|
||||
|
||||
|
||||
Field[] fields = subClass.getFields();
|
||||
|
||||
|
||||
for (Field f : fields) {
|
||||
list.add(new ResourceItem(f.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads, collects and returns the list of default permissions from the framework.
|
||||
*
|
||||
*
|
||||
* @param classLoader The framework SDK jar classloader
|
||||
* @return a non null (but possibly empty) array containing the permission values.
|
||||
*/
|
||||
@@ -377,12 +377,12 @@ public final class AndroidTargetParser {
|
||||
try {
|
||||
Class<?> permissionClass =
|
||||
classLoader.loadClass(AndroidConstants.CLASS_MANIFEST_PERMISSION);
|
||||
|
||||
|
||||
if (permissionClass != null) {
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
|
||||
Field[] fields = permissionClass.getFields();
|
||||
|
||||
|
||||
for (Field f : fields) {
|
||||
int modifiers = f.getModifiers();
|
||||
if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers) &&
|
||||
@@ -403,23 +403,23 @@ public final class AndroidTargetParser {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return list.toArray(new String[list.size()]);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
AdtPlugin.logAndPrintError(e, TAG,
|
||||
"Collect permissions failed, class %1$s not found in %2$s", //$NON-NLS-1$
|
||||
AndroidConstants.CLASS_MANIFEST_PERMISSION,
|
||||
AndroidConstants.CLASS_MANIFEST_PERMISSION,
|
||||
mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
|
||||
}
|
||||
|
||||
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loads and collects the action and category default values from the framework.
|
||||
* The values are added to the <code>actions</code> and <code>categories</code> lists.
|
||||
*
|
||||
*
|
||||
* @param activityActions the list which will receive the activity action values.
|
||||
* @param broadcastActions the list which will receive the broadcast action values.
|
||||
* @param serviceActions the list which will receive the service action values.
|
||||
@@ -481,7 +481,7 @@ public final class AndroidTargetParser {
|
||||
/**
|
||||
* Collects all layout classes information from the class loader and the
|
||||
* attrs.xml and sets the corresponding structures in the resource manager.
|
||||
*
|
||||
*
|
||||
* @param classLoader The framework SDK jar classloader in case we cannot get the widget from
|
||||
* the platform directly
|
||||
* @param attrsXmlParser The parser of the attrs.xml file
|
||||
@@ -491,7 +491,7 @@ public final class AndroidTargetParser {
|
||||
*/
|
||||
private void collectLayoutClasses(AndroidJarLoader classLoader,
|
||||
AttrsXmlParser attrsXmlParser,
|
||||
Collection<ViewClassInfo> mainList, Collection<ViewClassInfo> groupList,
|
||||
Collection<ViewClassInfo> mainList, Collection<ViewClassInfo> groupList,
|
||||
IProgressMonitor monitor) {
|
||||
LayoutParamsParser ldp = null;
|
||||
try {
|
||||
@@ -510,7 +510,7 @@ public final class AndroidTargetParser {
|
||||
ldp = new LayoutParamsParser(classLoader, attrsXmlParser);
|
||||
}
|
||||
ldp.parseLayoutClasses(monitor);
|
||||
|
||||
|
||||
List<ViewClassInfo> views = ldp.getViews();
|
||||
List<ViewClassInfo> groups = ldp.getGroups();
|
||||
|
||||
@@ -523,7 +523,7 @@ public final class AndroidTargetParser {
|
||||
/**
|
||||
* Collects all preferences definition information from the attrs.xml and
|
||||
* sets the corresponding structures in the resource manager.
|
||||
*
|
||||
*
|
||||
* @param classLoader The framework SDK jar classloader
|
||||
* @param attrsXmlParser The parser of the attrs.xml file
|
||||
* @param mainList the Collection to receive the main list of {@link ViewClassInfo}.
|
||||
@@ -534,13 +534,13 @@ public final class AndroidTargetParser {
|
||||
AttrsXmlParser attrsXmlParser, Collection<ViewClassInfo> mainList,
|
||||
Collection<ViewClassInfo> groupList, IProgressMonitor monitor) {
|
||||
LayoutParamsParser ldp = new LayoutParamsParser(classLoader, attrsXmlParser);
|
||||
|
||||
|
||||
try {
|
||||
ldp.parsePreferencesClasses(monitor);
|
||||
|
||||
|
||||
List<ViewClassInfo> prefs = ldp.getViews();
|
||||
List<ViewClassInfo> groups = ldp.getGroups();
|
||||
|
||||
|
||||
if (prefs != null && groups != null) {
|
||||
mainList.addAll(prefs);
|
||||
groupList.addAll(groups);
|
||||
@@ -548,7 +548,7 @@ public final class AndroidTargetParser {
|
||||
} catch (NoClassDefFoundError e) {
|
||||
AdtPlugin.logAndPrintError(e, TAG,
|
||||
"Collect preferences failed, class %1$s not found in %2$s",
|
||||
e.getMessage(),
|
||||
e.getMessage(),
|
||||
classLoader.getSource());
|
||||
} catch (Throwable e) {
|
||||
AdtPlugin.log(e, "Android Framework Parser: failed to collect preference classes"); //$NON-NLS-1$
|
||||
@@ -559,7 +559,7 @@ public final class AndroidTargetParser {
|
||||
|
||||
/**
|
||||
* Collects all menu definition information from the attrs.xml and returns it.
|
||||
*
|
||||
*
|
||||
* @param attrsXmlParser The parser of the attrs.xml file
|
||||
*/
|
||||
private Map<String, DeclareStyleableInfo> collectMenuDefinitions(
|
||||
@@ -575,18 +575,18 @@ public final class AndroidTargetParser {
|
||||
AdtPlugin.log(IStatus.WARNING,
|
||||
"Menu declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
|
||||
key, attrsXmlParser.getOsAttrsXmlPath());
|
||||
AdtPlugin.printErrorToConsole("Android Framework Parser",
|
||||
AdtPlugin.printErrorToConsole("Android Framework Parser",
|
||||
String.format("Menu declare-styleable %1$s not found in file %2$s", //$NON-NLS-1$
|
||||
key, attrsXmlParser.getOsAttrsXmlPath()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return Collections.unmodifiableMap(map2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects all searchable definition information from the attrs.xml and returns it.
|
||||
*
|
||||
*
|
||||
* @param attrsXmlParser The parser of the attrs.xml file
|
||||
*/
|
||||
private Map<String, DeclareStyleableInfo> collectSearchableDefinitions(
|
||||
@@ -612,7 +612,7 @@ public final class AndroidTargetParser {
|
||||
|
||||
/**
|
||||
* Collects all appWidgetProviderInfo definition information from the attrs.xml and returns it.
|
||||
*
|
||||
*
|
||||
* @param attrsXmlParser The parser of the attrs.xml file
|
||||
*/
|
||||
private Map<String, DeclareStyleableInfo> collectAppWidgetDefinitions(
|
||||
@@ -657,13 +657,13 @@ public final class AndroidTargetParser {
|
||||
AdtPlugin.log(IStatus.ERROR, "layoutlib.jar is missing!"); //$NON-NLS-1$
|
||||
} else {
|
||||
URL url = f.toURL();
|
||||
|
||||
|
||||
// create a class loader. Because this jar reference interfaces
|
||||
// that are in the editors plugin, it's important to provide
|
||||
// that are in the editors plugin, it's important to provide
|
||||
// a parent class loader.
|
||||
layoutBridge.classLoader = new URLClassLoader(new URL[] { url },
|
||||
this.getClass().getClassLoader());
|
||||
|
||||
|
||||
// load the class
|
||||
Class<?> clazz = layoutBridge.classLoader.loadClass(AndroidConstants.CLASS_BRIDGE);
|
||||
if (clazz != null) {
|
||||
@@ -676,7 +676,7 @@ public final class AndroidTargetParser {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (layoutBridge.bridge == null) {
|
||||
layoutBridge.status = LoadStatus.FAILED;
|
||||
AdtPlugin.log(IStatus.ERROR, "Failed to load " + AndroidConstants.CLASS_BRIDGE); //$NON-NLS-1$
|
||||
@@ -688,7 +688,7 @@ public final class AndroidTargetParser {
|
||||
// the first version of the api did not have this method
|
||||
layoutBridge.apiLevel = 1;
|
||||
}
|
||||
|
||||
|
||||
// and mark the lib as loaded.
|
||||
layoutBridge.status = LoadStatus.LOADED;
|
||||
}
|
||||
@@ -698,7 +698,7 @@ public final class AndroidTargetParser {
|
||||
// log the error.
|
||||
AdtPlugin.log(t, "Failed to load the LayoutLib");
|
||||
}
|
||||
|
||||
|
||||
return layoutBridge;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
|
||||
package com.android.ide.eclipse.adt.internal.sdk;
|
||||
|
||||
import com.android.ddmlib.IDevice;
|
||||
import com.android.ide.eclipse.adt.AdtPlugin;
|
||||
import com.android.ide.eclipse.adt.internal.project.AndroidClasspathContainerInitializer;
|
||||
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceMonitor;
|
||||
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceMonitor.IProjectListener;
|
||||
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData.LayoutBridge;
|
||||
import com.android.prefs.AndroidLocation.AndroidLocationException;
|
||||
import com.android.sdklib.AndroidVersion;
|
||||
import com.android.sdklib.IAndroidTarget;
|
||||
import com.android.sdklib.ISdkLog;
|
||||
import com.android.sdklib.SdkConstants;
|
||||
@@ -394,6 +396,21 @@ public class Sdk implements IProjectListener {
|
||||
return mAvdManager;
|
||||
}
|
||||
|
||||
public static AndroidVersion getDeviceVersion(IDevice device) {
|
||||
try {
|
||||
Map<String, String> props = device.getProperties();
|
||||
String apiLevel = props.get(IDevice.PROP_BUILD_API_LEVEL);
|
||||
if (apiLevel == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new AndroidVersion(Integer.parseInt(apiLevel),
|
||||
props.get((IDevice.PROP_BUILD_CODENAME)));
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Sdk(SdkManager manager, AvdManager avdManager) {
|
||||
mManager = manager;
|
||||
mAvdManager = avdManager;
|
||||
|
||||
@@ -840,25 +840,21 @@ public class NewProjectCreationPage extends WizardPage {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
int version = Integer.parseInt(mInfo.getMinSdkVersion());
|
||||
String minSdkVersion = mInfo.getMinSdkVersion();
|
||||
|
||||
// Before changing, compare with the currently selected one, if any.
|
||||
// There can be multiple targets with the same sdk api version, so don't change
|
||||
// it if it's already at the right version.
|
||||
IAndroidTarget curr_target = mInfo.getSdkTarget();
|
||||
if (curr_target != null && curr_target.getApiVersionNumber() == version) {
|
||||
return;
|
||||
}
|
||||
// Before changing, compare with the currently selected one, if any.
|
||||
// There can be multiple targets with the same sdk api version, so don't change
|
||||
// it if it's already at the right version.
|
||||
IAndroidTarget curr_target = mInfo.getSdkTarget();
|
||||
if (curr_target != null && curr_target.getVersion().equals(minSdkVersion)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (IAndroidTarget target : mSdkTargetSelector.getTargets()) {
|
||||
if (target.getApiVersionNumber() == version) {
|
||||
mSdkTargetSelector.setSelection(target);
|
||||
break;
|
||||
}
|
||||
for (IAndroidTarget target : mSdkTargetSelector.getTargets()) {
|
||||
if (target.getVersion().equals(minSdkVersion)) {
|
||||
mSdkTargetSelector.setSelection(target);
|
||||
break;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
@@ -873,7 +869,7 @@ public class NewProjectCreationPage extends WizardPage {
|
||||
|
||||
if (target != null) {
|
||||
mInternalMinSdkVersionUpdate = true;
|
||||
mMinSdkVersionField.setText(Integer.toString(target.getApiVersionNumber()));
|
||||
mMinSdkVersionField.setText(target.getVersion().getApiString());
|
||||
mInternalMinSdkVersionUpdate = false;
|
||||
}
|
||||
}
|
||||
@@ -932,7 +928,7 @@ public class NewProjectCreationPage extends WizardPage {
|
||||
String packageName = null;
|
||||
Activity activity = null;
|
||||
String activityName = null;
|
||||
int minSdkVersion = AndroidManifestParser.INVALID_MIN_SDK;
|
||||
String minSdkVersion = null;
|
||||
try {
|
||||
packageName = manifestData.getPackage();
|
||||
minSdkVersion = manifestData.getApiLevelRequirement();
|
||||
@@ -1033,17 +1029,13 @@ public class NewProjectCreationPage extends WizardPage {
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundTarget && minSdkVersion != AndroidManifestParser.INVALID_MIN_SDK) {
|
||||
try {
|
||||
for (IAndroidTarget target : mSdkTargetSelector.getTargets()) {
|
||||
if (target.getApiVersionNumber() == minSdkVersion) {
|
||||
mSdkTargetSelector.setSelection(target);
|
||||
foundTarget = true;
|
||||
break;
|
||||
}
|
||||
if (!foundTarget && minSdkVersion != null) {
|
||||
for (IAndroidTarget target : mSdkTargetSelector.getTargets()) {
|
||||
if (target.getVersion().equals(minSdkVersion)) {
|
||||
mSdkTargetSelector.setSelection(target);
|
||||
foundTarget = true;
|
||||
break;
|
||||
}
|
||||
} catch(NumberFormatException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1059,9 +1051,9 @@ public class NewProjectCreationPage extends WizardPage {
|
||||
|
||||
if (!foundTarget) {
|
||||
mInternalMinSdkVersionUpdate = true;
|
||||
mMinSdkVersionField.setText(
|
||||
minSdkVersion == AndroidManifestParser.INVALID_MIN_SDK ? "" //$NON-NLS-1$
|
||||
: Integer.toString(minSdkVersion));
|
||||
if (minSdkVersion != null) {
|
||||
mMinSdkVersionField.setText(minSdkVersion);
|
||||
}
|
||||
mInternalMinSdkVersionUpdate = false;
|
||||
}
|
||||
}
|
||||
@@ -1269,21 +1261,10 @@ public class NewProjectCreationPage extends WizardPage {
|
||||
return MSG_NONE;
|
||||
}
|
||||
|
||||
int version = AndroidManifestParser.INVALID_MIN_SDK;
|
||||
try {
|
||||
// If not empty, it must be a valid integer > 0
|
||||
version = Integer.parseInt(mInfo.getMinSdkVersion());
|
||||
} catch (NumberFormatException e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
if (version < 1) {
|
||||
return setStatus("Min SDK Version must be an integer > 0.", MSG_ERROR);
|
||||
}
|
||||
|
||||
if (mInfo.getSdkTarget() != null && mInfo.getSdkTarget().getApiVersionNumber() != version) {
|
||||
if (mInfo.getSdkTarget() != null &&
|
||||
mInfo.getSdkTarget().getVersion().equals(mInfo.getMinSdkVersion()) == false) {
|
||||
return setStatus("The API level for the selected SDK target does not match the Min SDK version.",
|
||||
MSG_WARNING);
|
||||
mInfo.getSdkTarget().getVersion().isPreview() ? MSG_ERROR : MSG_WARNING);
|
||||
}
|
||||
|
||||
return MSG_NONE;
|
||||
|
||||
@@ -821,7 +821,7 @@ public class NewTestProjectCreationPage extends WizardPage {
|
||||
if (manifestData != null) {
|
||||
String appName = String.format("%1$sTest", project.getName());
|
||||
String packageName = manifestData.getPackage();
|
||||
int minSdkVersion = manifestData.getApiLevelRequirement();
|
||||
String minSdkVersion = manifestData.getApiLevelRequirement();
|
||||
IAndroidTarget sdkTarget = null;
|
||||
if (Sdk.getCurrent() != null) {
|
||||
sdkTarget = Sdk.getCurrent().getTarget(project);
|
||||
@@ -859,9 +859,9 @@ public class NewTestProjectCreationPage extends WizardPage {
|
||||
|
||||
if (!mMinSdkVersionModifiedByUser) {
|
||||
mInternalMinSdkVersionUpdate = true;
|
||||
mMinSdkVersionField.setText(
|
||||
minSdkVersion != AndroidManifestParser.INVALID_MIN_SDK ?
|
||||
Integer.toString(minSdkVersion) : ""); //$NON-NLS-1$
|
||||
if (minSdkVersion != null) {
|
||||
mMinSdkVersionField.setText(minSdkVersion);
|
||||
}
|
||||
if (sdkTarget == null) {
|
||||
updateSdkSelectorToMatchMinSdkVersion();
|
||||
}
|
||||
@@ -1052,22 +1052,18 @@ public class NewTestProjectCreationPage extends WizardPage {
|
||||
* that matches.
|
||||
*/
|
||||
private void updateSdkSelectorToMatchMinSdkVersion() {
|
||||
try {
|
||||
int version = Integer.parseInt(mInfo.getMinSdkVersion());
|
||||
String minSdkVersion = mInfo.getMinSdkVersion();
|
||||
|
||||
IAndroidTarget curr_target = mInfo.getSdkTarget();
|
||||
if (curr_target != null && curr_target.getApiVersionNumber() == version) {
|
||||
IAndroidTarget curr_target = mInfo.getSdkTarget();
|
||||
if (curr_target != null && curr_target.getVersion().equals(minSdkVersion)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (IAndroidTarget target : mSdkTargetSelector.getTargets()) {
|
||||
if (target.getVersion().equals(minSdkVersion)) {
|
||||
mSdkTargetSelector.setSelection(target);
|
||||
return;
|
||||
}
|
||||
|
||||
for (IAndroidTarget target : mSdkTargetSelector.getTargets()) {
|
||||
if (target.getApiVersionNumber() == version) {
|
||||
mSdkTargetSelector.setSelection(target);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1086,7 +1082,7 @@ public class NewTestProjectCreationPage extends WizardPage {
|
||||
|
||||
if (target != null) {
|
||||
mInternalMinSdkVersionUpdate = true;
|
||||
mMinSdkVersionField.setText(Integer.toString(target.getApiVersionNumber()));
|
||||
mMinSdkVersionField.setText(target.getVersion().getApiString());
|
||||
mInternalMinSdkVersionUpdate = false;
|
||||
}
|
||||
|
||||
@@ -1261,21 +1257,10 @@ public class NewTestProjectCreationPage extends WizardPage {
|
||||
return MSG_NONE;
|
||||
}
|
||||
|
||||
int version = AndroidManifestParser.INVALID_MIN_SDK;
|
||||
try {
|
||||
// If not empty, it must be a valid integer > 0
|
||||
version = Integer.parseInt(mInfo.getMinSdkVersion());
|
||||
} catch (NumberFormatException e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
if (version < 1) {
|
||||
return setStatus("Min SDK Version must be an integer > 0.", MSG_ERROR);
|
||||
}
|
||||
|
||||
if (mInfo.getSdkTarget() != null && mInfo.getSdkTarget().getApiVersionNumber() != version) {
|
||||
if (mInfo.getSdkTarget() != null &&
|
||||
mInfo.getSdkTarget().getVersion().equals(mInfo.getMinSdkVersion()) == false) {
|
||||
return setStatus("The API level for the selected SDK target does not match the Min SDK version.",
|
||||
MSG_WARNING);
|
||||
mInfo.getSdkTarget().getVersion().isPreview() ? MSG_ERROR : MSG_WARNING);
|
||||
}
|
||||
|
||||
return MSG_NONE;
|
||||
|
||||
@@ -87,10 +87,10 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
private final String mDefaultAttrs;
|
||||
private final String mDefaultRoot;
|
||||
private final int mTargetApiLevel;
|
||||
|
||||
|
||||
public TypeInfo(String uiName,
|
||||
String tooltip,
|
||||
ResourceFolderType resFolderType,
|
||||
String tooltip,
|
||||
ResourceFolderType resFolderType,
|
||||
Object rootSeed,
|
||||
String defaultRoot,
|
||||
String xmlns,
|
||||
@@ -110,12 +110,12 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
String getUiName() {
|
||||
return mUiName;
|
||||
}
|
||||
|
||||
/** Returns the tooltip for the resource type. Can be null. */
|
||||
|
||||
/** Returns the tooltip for the resource type. Can be null. */
|
||||
String getTooltip() {
|
||||
return mTooltip;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the {@link ResourceFolderType}.
|
||||
* Never null but not necessarily unique,
|
||||
@@ -124,7 +124,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
String getResFolderName() {
|
||||
return mResFolderType.getName();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the matching {@link ResourceFolderType}.
|
||||
* Never null but not necessarily unique,
|
||||
@@ -138,16 +138,16 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
void setWidget(Button widget) {
|
||||
mWidget = widget;
|
||||
}
|
||||
|
||||
|
||||
/** Returns the radio button associate with the resource type. Can be null. */
|
||||
Button getWidget() {
|
||||
return mWidget;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the seed used to fill the root element values.
|
||||
* The seed might be either a String, a String array, an {@link ElementDescriptor},
|
||||
* a {@link DocumentDescriptor} or null.
|
||||
* a {@link DocumentDescriptor} or null.
|
||||
*/
|
||||
Object getRootSeed() {
|
||||
return mRootSeed;
|
||||
@@ -278,7 +278,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
private static final String RES_FOLDER_ABS = AndroidConstants.WS_RESOURCES + AndroidConstants.WS_SEP;
|
||||
/** Relative destination folder root, e.g. "res/" */
|
||||
private static final String RES_FOLDER_REL = SdkConstants.FD_RESOURCES + AndroidConstants.WS_SEP;
|
||||
|
||||
|
||||
private IProject mProject;
|
||||
private Text mProjectTextField;
|
||||
private Button mProjectBrowseButton;
|
||||
@@ -297,7 +297,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
private TypeInfo mCurrentTypeInfo;
|
||||
|
||||
// --- UI creation ---
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new {@link NewXmlFileCreationPage}.
|
||||
* <p/>
|
||||
@@ -314,9 +314,9 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
|
||||
/**
|
||||
* Called by the parent Wizard to create the UI for this Wizard Page.
|
||||
*
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*
|
||||
*
|
||||
* @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
|
||||
*/
|
||||
public void createControl(Composite parent) {
|
||||
@@ -347,7 +347,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
installTargetChangeListener();
|
||||
validatePage();
|
||||
}
|
||||
|
||||
|
||||
private void installTargetChangeListener() {
|
||||
mSdkTargetChangeListener = new ITargetChangeListener() {
|
||||
public void onProjectTargetChange(IProject changedProject) {
|
||||
@@ -364,18 +364,18 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
AdtPlugin.getDefault().addTargetListener(mSdkTargetChangeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
|
||||
|
||||
if (mSdkTargetChangeListener != null) {
|
||||
AdtPlugin.getDefault().removeTargetListener(mSdkTargetChangeListener);
|
||||
mSdkTargetChangeListener = null;
|
||||
}
|
||||
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -399,7 +399,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
public String getWsFolderPath() {
|
||||
return mWsFolderPathTextField == null ? "" : mWsFolderPathTextField.getText(); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns an {@link IFile} on the destination file.
|
||||
@@ -426,7 +426,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
/**
|
||||
* Returns the {@link TypeInfo} for the currently selected type radio button.
|
||||
* Returns null if no radio button is selected.
|
||||
*
|
||||
*
|
||||
* @return A {@link TypeInfo} or null.
|
||||
*/
|
||||
public TypeInfo getSelectedType() {
|
||||
@@ -439,10 +439,10 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the selected root element string, if any.
|
||||
*
|
||||
*
|
||||
* @return The selected root element string or null.
|
||||
*/
|
||||
public String getRootElement() {
|
||||
@@ -457,7 +457,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
|
||||
/**
|
||||
* Helper method to create a new GridData with an horizontal span.
|
||||
*
|
||||
*
|
||||
* @param horizSpan The number of cells for the horizontal span.
|
||||
* @return A new GridData with the horizontal span.
|
||||
*/
|
||||
@@ -469,7 +469,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
|
||||
/**
|
||||
* Helper method to create a new GridData with an horizontal span and a style.
|
||||
*
|
||||
*
|
||||
* @param horizSpan The number of cells for the horizontal span.
|
||||
* @param style The style, e.g. {@link GridData#FILL_HORIZONTAL}
|
||||
* @return A new GridData with the horizontal span and the style.
|
||||
@@ -482,7 +482,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
|
||||
/**
|
||||
* Helper method that creates an empty cell in the parent composite.
|
||||
*
|
||||
*
|
||||
* @param parent The parent composite.
|
||||
*/
|
||||
private void emptyCell(Composite parent) {
|
||||
@@ -491,7 +491,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
|
||||
/**
|
||||
* Pads the parent with empty cells to match the number of columns of the parent grid.
|
||||
*
|
||||
*
|
||||
* @param parent A grid layout with NUM_COL columns
|
||||
* @param col The current number of columns used.
|
||||
* @return 0, the new number of columns used, for convenience.
|
||||
@@ -511,7 +511,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
*/
|
||||
private void createProjectGroup(Composite parent) {
|
||||
int col = 0;
|
||||
|
||||
|
||||
// project name
|
||||
String tooltip = "The Android Project where the new resource file will be created.";
|
||||
Label label = new Label(parent, SWT.NONE);
|
||||
@@ -542,7 +542,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
++col;
|
||||
|
||||
col = padWithEmptyCells(parent, col);
|
||||
|
||||
|
||||
// file name
|
||||
tooltip = "The name of the resource file to create.";
|
||||
label = new Label(parent, SWT.NONE);
|
||||
@@ -572,7 +572,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
// separator
|
||||
Label label = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
|
||||
label.setLayoutData(newGridData(NUM_COL, GridData.GRAB_HORIZONTAL));
|
||||
|
||||
|
||||
// label before type radios
|
||||
label = new Label(parent, SWT.NONE);
|
||||
label.setText("What type of resource would you like to create?");
|
||||
@@ -584,7 +584,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
padWithEmptyCells(parent, 2);
|
||||
|
||||
grid.setLayout(new GridLayout(NUM_COL, true /*makeColumnsEqualWidth*/));
|
||||
|
||||
|
||||
SelectionListener radioListener = new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
@@ -594,7 +594,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int n = sTypes.length;
|
||||
int num_lines = (n + NUM_COL/2) / NUM_COL;
|
||||
for (int line = 0, k = 0; line < num_lines; line++) {
|
||||
@@ -627,7 +627,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
mConfigSelector.setLayoutData(gd);
|
||||
mConfigSelector.setOnChangeListener(new onConfigSelectorUpdated());
|
||||
emptyCell(parent);
|
||||
|
||||
|
||||
// folder name
|
||||
String tooltip = "The folder where the file will be generated, relative to the project.";
|
||||
label = new Label(parent, SWT.NONE);
|
||||
@@ -669,7 +669,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
mRootElementCombo.select(0);
|
||||
mRootElementCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||
mRootElementCombo.setToolTipText(tooltip);
|
||||
|
||||
|
||||
padWithEmptyCells(parent, 2);
|
||||
}
|
||||
|
||||
@@ -683,7 +683,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
* <li>The current folder, valid if it's a folder under /res</li>
|
||||
* <li>An existing filename, in which case the user will be asked whether to override it.</li>
|
||||
* <ul>
|
||||
*
|
||||
*
|
||||
* @param selection The selection when the wizard was initiated.
|
||||
*/
|
||||
private void initializeFromSelection(IStructuredSelection selection) {
|
||||
@@ -702,7 +702,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
if (element instanceof IAdaptable) {
|
||||
IResource res = (IResource) ((IAdaptable) element).getAdapter(IResource.class);
|
||||
IProject project = res != null ? res.getProject() : null;
|
||||
|
||||
|
||||
// Is this an Android project?
|
||||
try {
|
||||
if (project == null || !project.hasNature(AndroidConstants.NATURE)) {
|
||||
@@ -712,18 +712,18 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
// checking the nature failed, ignore this resource
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
int score = 1; // we have a valid project at least
|
||||
|
||||
IPath wsFolderPath = null;
|
||||
String fileName = null;
|
||||
if (res.getType() == IResource.FOLDER) {
|
||||
wsFolderPath = res.getProjectRelativePath();
|
||||
wsFolderPath = res.getProjectRelativePath();
|
||||
} else if (res.getType() == IResource.FILE) {
|
||||
fileName = res.getName();
|
||||
wsFolderPath = res.getParent().getProjectRelativePath();
|
||||
}
|
||||
|
||||
|
||||
// Disregard this folder selection if it doesn't point to /res/something
|
||||
if (wsFolderPath != null &&
|
||||
wsFolderPath.segmentCount() > 1 &&
|
||||
@@ -735,7 +735,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
}
|
||||
|
||||
score += fileName != null ? 4 : 0;
|
||||
|
||||
|
||||
if (score > targetScore) {
|
||||
targetScore = score;
|
||||
targetProject = project;
|
||||
@@ -744,7 +744,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Now set the UI accordingly
|
||||
if (targetScore > 0) {
|
||||
mProject = targetProject;
|
||||
@@ -764,7 +764,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
if (roots.size() > 0) {
|
||||
roots.clear();
|
||||
}
|
||||
|
||||
|
||||
// depending of the type of the seed, initialize the root in different ways
|
||||
Object rootSeed = type.getRootSeed();
|
||||
|
||||
@@ -783,7 +783,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
|
||||
// Note: if project is null, the root list will be empty since it has been
|
||||
// cleared above.
|
||||
|
||||
|
||||
// get the AndroidTargetData from the project
|
||||
IAndroidTarget target = null;
|
||||
AndroidTargetData data = null;
|
||||
@@ -793,7 +793,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
// A project should have a target. The target can be missing if the project
|
||||
// is an old project for which a target hasn't been affected or if the
|
||||
// target no longer exists in this SDK. Simply log the error and dismiss.
|
||||
|
||||
|
||||
AdtPlugin.log(IStatus.INFO,
|
||||
"NewXmlFile wizard: no platform target for project %s", //$NON-NLS-1$
|
||||
mProject.getName());
|
||||
@@ -807,14 +807,14 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
// loaded we can end up in a weird case where we have a target but it
|
||||
// doesn't have any data yet.
|
||||
// Lets log a warning and silently ignore this root.
|
||||
|
||||
|
||||
AdtPlugin.log(IStatus.INFO,
|
||||
"NewXmlFile wizard: no data for target %s, project %s", //$NON-NLS-1$
|
||||
target.getName(), mProject.getName());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IDescriptorProvider provider = data.getDescriptorProvider((Integer)rootSeed);
|
||||
ElementDescriptor descriptor = provider.getDescriptor();
|
||||
if (descriptor != null) {
|
||||
@@ -842,22 +842,22 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
roots.add(xmlName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
visited.add(desc);
|
||||
|
||||
|
||||
for (ElementDescriptor child : desc.getChildren()) {
|
||||
if (!visited.contains(child)) {
|
||||
initRootElementDescriptor(roots, child, visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback called when the user edits the project text field.
|
||||
*/
|
||||
private void onProjectFieldUpdated() {
|
||||
String project = mProjectTextField.getText();
|
||||
|
||||
|
||||
// Is this a valid project?
|
||||
IJavaProject[] projects = mProjectChooserHelper.getAndroidProjects(null /*javaModel*/);
|
||||
IProject found = null;
|
||||
@@ -896,15 +896,15 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
|
||||
// enable types based on new API level
|
||||
enableTypesBasedOnApi();
|
||||
|
||||
|
||||
// update the Type with the new descriptors.
|
||||
initializeRootValues();
|
||||
|
||||
|
||||
// update the combo
|
||||
updateRootCombo(getSelectedType());
|
||||
|
||||
|
||||
validatePage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback called when the Folder text field is changed, either programmatically
|
||||
@@ -929,7 +929,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
// We get "res/foo" from selections relative to the project when we want a "/res/foo" path.
|
||||
if (wsFolderPath.startsWith(RES_FOLDER_REL)) {
|
||||
wsFolderPath = RES_FOLDER_ABS + wsFolderPath.substring(RES_FOLDER_REL.length());
|
||||
|
||||
|
||||
mInternalWsFolderPathUpdate = true;
|
||||
mWsFolderPathTextField.setText(wsFolderPath);
|
||||
mInternalWsFolderPathUpdate = false;
|
||||
@@ -937,7 +937,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
|
||||
if (wsFolderPath.startsWith(RES_FOLDER_ABS)) {
|
||||
wsFolderPath = wsFolderPath.substring(RES_FOLDER_ABS.length());
|
||||
|
||||
|
||||
int pos = wsFolderPath.indexOf(AndroidConstants.WS_SEP_CHAR);
|
||||
if (pos >= 0) {
|
||||
wsFolderPath = wsFolderPath.substring(0, pos);
|
||||
@@ -985,7 +985,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
|
||||
/**
|
||||
* Callback called when one of the type radio button is changed.
|
||||
*
|
||||
*
|
||||
* @param typeWidget The type radio button that changed.
|
||||
*/
|
||||
private void onRadioTypeUpdated(Button typeWidget) {
|
||||
@@ -1003,13 +1003,13 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// update the combo
|
||||
|
||||
|
||||
updateRootCombo(type);
|
||||
|
||||
// update the folder path
|
||||
@@ -1022,7 +1022,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
if (qual == null) {
|
||||
// The configuration is valid. Reformat the folder path using the canonical
|
||||
// value from the configuration.
|
||||
|
||||
|
||||
newPath = RES_FOLDER_ABS + mTempConfig.getFolderName(type.getResFolderType());
|
||||
} else {
|
||||
// The configuration is invalid. We still update the path but this time
|
||||
@@ -1049,7 +1049,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
* Helper method that fills the values of the "root element" combo box based
|
||||
* on the currently selected type radio button. Also disables the combo is there's
|
||||
* only one choice. Always select the first root element for the given type.
|
||||
*
|
||||
*
|
||||
* @param type The currently selected {@link TypeInfo}. Cannot be null.
|
||||
*/
|
||||
private void updateRootCombo(TypeInfo type) {
|
||||
@@ -1059,14 +1059,14 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
if (type != null) {
|
||||
// get the list of roots. The list can be empty but not null.
|
||||
ArrayList<String> roots = type.getRoots();
|
||||
|
||||
|
||||
// enable the combo if there's more than one choice
|
||||
mRootElementCombo.setEnabled(roots != null && roots.size() > 1);
|
||||
|
||||
|
||||
for (String root : roots) {
|
||||
mRootElementCombo.add(root);
|
||||
}
|
||||
|
||||
|
||||
int index = 0; // default is to select the first one
|
||||
String defaultRoot = type.getDefaultRoot();
|
||||
if (defaultRoot != null) {
|
||||
@@ -1086,16 +1086,16 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
}
|
||||
|
||||
TypeInfo type = getSelectedType();
|
||||
|
||||
|
||||
if (type != null) {
|
||||
mConfigSelector.getConfiguration(mTempConfig);
|
||||
StringBuffer sb = new StringBuffer(RES_FOLDER_ABS);
|
||||
sb.append(mTempConfig.getFolderName(type.getResFolderType()));
|
||||
|
||||
|
||||
mInternalWsFolderPathUpdate = true;
|
||||
mWsFolderPathTextField.setText(sb.toString());
|
||||
mInternalWsFolderPathUpdate = false;
|
||||
|
||||
|
||||
validatePage();
|
||||
}
|
||||
}
|
||||
@@ -1103,7 +1103,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
|
||||
/**
|
||||
* Helper method to select on of the type radio buttons.
|
||||
*
|
||||
*
|
||||
* @param type The TypeInfo matching the radio button to selected or null to deselect them all.
|
||||
*/
|
||||
private void selectType(TypeInfo type) {
|
||||
@@ -1130,9 +1130,9 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
IAndroidTarget target = mProject != null ? Sdk.getCurrent().getTarget(mProject) : null;
|
||||
int currentApiLevel = 1;
|
||||
if (target != null) {
|
||||
currentApiLevel = target.getApiVersionNumber();
|
||||
currentApiLevel = target.getVersion().getApiLevel();
|
||||
}
|
||||
|
||||
|
||||
for (TypeInfo type : sTypes) {
|
||||
type.getWidget().setEnabled(type.getTargetApiLevel() <= currentApiLevel);
|
||||
}
|
||||
@@ -1175,7 +1175,7 @@ class NewXmlFileCreationPage extends WizardPage {
|
||||
IAndroidTarget target = Sdk.getCurrent().getTarget(mProject);
|
||||
int currentApiLevel = 1;
|
||||
if (target != null) {
|
||||
currentApiLevel = target.getApiVersionNumber();
|
||||
currentApiLevel = target.getVersion().getApiLevel();
|
||||
}
|
||||
|
||||
TypeInfo type = getSelectedType();
|
||||
|
||||
Reference in New Issue
Block a user