auto import from //branches/cupcake/...@125939

This commit is contained in:
The Android Open Source Project
2009-01-09 17:51:19 -08:00
parent e943f2fd8e
commit 95cf464c5a
176 changed files with 4721 additions and 7588 deletions

View File

@@ -16,6 +16,7 @@
package com.android.ide.eclipse.adt;
import com.android.ide.eclipse.adt.project.internal.AndroidClasspathContainerInitializer;
/**
@@ -42,8 +43,8 @@ public class AdtConstants {
/** Marker for Android Target errors.
* This is not cleared on each like other markers. Instead, it's cleared
* when a ContainerClasspathInitialized has succeeded in creating an
* {@link AndroidClasspathContainer}*/
* when an {@link AndroidClasspathContainerInitializer} has succeeded in creating an
* AndroidClasspathContainer */
public final static String MARKER_TARGET = AdtPlugin.PLUGIN_ID + ".targetProblem"; //$NON-NLS-1$
/** Build verbosity "Always". Those messages are always displayed. */

View File

@@ -1201,7 +1201,7 @@ public class AdtPlugin extends AbstractUIPlugin {
if (file.getFullPath().segmentCount() == 4) {
// check if we are inside the res folder.
String segment = file.getFullPath().segment(1);
if (segment.equalsIgnoreCase(AndroidConstants.FD_RESOURCES)) {
if (segment.equalsIgnoreCase(SdkConstants.FD_RESOURCES)) {
// we are inside a res/ folder, get the actual ResourceFolder
ProjectResources resources = ResourceManager.getInstance().
getProjectResources(file.getProject());

View File

@@ -31,6 +31,7 @@ import com.android.jarutils.DebugKeyProvider.KeytoolException;
import com.android.jarutils.SignedJarBuilder.IZipEntryFilter;
import com.android.prefs.AndroidLocation.AndroidLocationException;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
@@ -120,6 +121,10 @@ public class ApkBuilder extends BaseBuilder {
}
}
/**
* {@inheritDoc}
* @throws CoreException
*/
public boolean visit(IResourceDelta delta) throws CoreException {
// no need to keep looking if we already know we need to convert
// to dex and make the final package.
@@ -589,7 +594,7 @@ public class ApkBuilder extends BaseBuilder {
* @param osBinPath the path to the output folder of the project
* @param osOutFilePath the path of the dex file to create.
* @param referencedJavaProjects the list of referenced projects for this project.
* @return
*
* @throws CoreException
*/
private boolean executeDx(IJavaProject javaProject, String osBinPath, String osOutFilePath,
@@ -756,8 +761,7 @@ public class ApkBuilder extends BaseBuilder {
// now write the native libraries.
// First look if the lib folder is there.
IResource libFolder = javaProject.getProject().findMember(
AndroidConstants.FD_NATIVE_LIBS);
IResource libFolder = javaProject.getProject().findMember(SdkConstants.FD_NATIVE_LIBS);
if (libFolder != null && libFolder.exists() &&
libFolder.getType() == IResource.FOLDER) {
// look inside and put .so in lib/* by keeping the relative folder path.
@@ -829,7 +833,7 @@ public class ApkBuilder extends BaseBuilder {
* lib folder directly goes in this "lib" folder in the archive.
*
*
* @param rooSegmentCount The number of segment of the path of the folder containing the
* @param rootSegmentCount The number of segment of the path of the folder containing the
* libraries. This is used to compute the path in the archive.
* @param jarBuilder the {@link SignedJarBuilder} used to create the archive.
* @param resource the IResource to write.
@@ -847,7 +851,7 @@ public class ApkBuilder extends BaseBuilder {
path = path.removeFirstSegments(rootSegmentCount);
// add it to the archive.
IPath apkPath = new Path(AndroidConstants.FD_APK_NATIVE_LIBS);
IPath apkPath = new Path(SdkConstants.FD_APK_NATIVE_LIBS);
apkPath = apkPath.append(path);
// writes the file in the apk.

View File

@@ -18,6 +18,7 @@ package com.android.ide.eclipse.adt.build;
import com.android.ide.eclipse.adt.build.BaseBuilder.BaseDeltaVisitor;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.sdklib.SdkConstants;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
@@ -98,17 +99,17 @@ public class ApkDeltaVisitor extends BaseDeltaVisitor
mOutputPath = outputfolder.getFullPath();
}
IResource assetFolder = builder.getProject().findMember(AndroidConstants.FD_ASSETS);
IResource assetFolder = builder.getProject().findMember(SdkConstants.FD_ASSETS);
if (assetFolder != null) {
mAssetPath = assetFolder.getFullPath();
}
IResource resFolder = builder.getProject().findMember(AndroidConstants.FD_RESOURCES);
IResource resFolder = builder.getProject().findMember(SdkConstants.FD_RESOURCES);
if (resFolder != null) {
mResPath = resFolder.getFullPath();
}
IResource libFolder = builder.getProject().findMember(AndroidConstants.FD_NATIVE_LIBS);
IResource libFolder = builder.getProject().findMember(SdkConstants.FD_NATIVE_LIBS);
if (libFolder != null) {
mLibFolder = libFolder.getFullPath();
}
@@ -126,8 +127,9 @@ public class ApkDeltaVisitor extends BaseDeltaVisitor
return mMakeFinalPackage;
}
/*
* (non-Javadoc)
/**
* {@inheritDoc}
* @throws CoreException
*
* @see org.eclipse.core.resources.IResourceDeltaVisitor
* #visit(org.eclipse.core.resources.IResourceDelta)

View File

@@ -69,15 +69,15 @@ abstract class BaseBuilder extends IncrementalProjectBuilder {
/**
* First line of dual line aapt error.<br>
* "ERROR at line &lt;line&gt;: &lt;error&gt;"<br>
* " (Occured while parsing &lt;path&gt;)"
* " (Occurred while parsing &lt;path&gt;)"
*/
private final static Pattern sPattern1Line1 = Pattern.compile(
"^ERROR\\s+at\\s+line\\s+(\\d+):\\s+(.*)$"); //$NON-NLS-1$
/**
* Second line of dual line aapt error.<br>
* "ERROR at line &lt;line&gt;: &lt;error&gt;"<br>
* " (Occured while parsing &lt;path&gt;)"<br>
* @see sPattern1Line1
* " (Occurred while parsing &lt;path&gt;)"<br>
* @see #sPattern1Line1
*/
private final static Pattern sPattern1Line2 = Pattern.compile(
"^\\s+\\(Occurred while parsing\\s+(.*)\\)$"); //$NON-NLS-1$
@@ -92,7 +92,7 @@ abstract class BaseBuilder extends IncrementalProjectBuilder {
* Second line of dual line aapt error.<br>
* "ERROR: &lt;error&gt;"<br>
* "Defined at file &lt;path&gt; line &lt;line&gt;"<br>
* @see sPattern2Line1
* @see #sPattern2Line1
*/
private final static Pattern sPattern2Line2 = Pattern.compile(
"Defined\\s+at\\s+file\\s+(.+)\\s+line\\s+(\\d+)"); //$NON-NLS-1$
@@ -113,7 +113,7 @@ abstract class BaseBuilder extends IncrementalProjectBuilder {
* Second line of dual line aapt error.<br>
* "ERROR parsing XML file &lt;path&gt;"<br>
* "&lt;error&gt; at line &lt;line&gt;"<br>
* @see sPattern4Line1
* @see #sPattern4Line1
*/
private final static Pattern sPattern4Line2 = Pattern.compile(
"^(.+)\\s+at\\s+line\\s+(\\d+)$"); //$NON-NLS-1$
@@ -263,7 +263,7 @@ abstract class BaseBuilder extends IncrementalProjectBuilder {
/**
* Adds a marker to the current project.
* @param file the file to be marked
*
* @param markerId The id of the marker to add.
* @param message the message associated with the mark
* @param severity the severity of the marker.
@@ -292,12 +292,11 @@ abstract class BaseBuilder extends IncrementalProjectBuilder {
/**
* Removes markers from a container and its children.
* @param container The container from which to delete the markers.
* @param folder The container from which to delete the markers.
* @param markerId The id of the markers to remove. If null, all marker of
* type <code>IMarker.PROBLEM</code> will be removed.
*/
protected final void removeMarkersFromContainer(IContainer folder,
String markerId) {
protected final void removeMarkersFromContainer(IContainer folder, String markerId) {
try {
if (folder.exists()) {
folder.deleteMarkers(markerId, true, IResource.DEPTH_INFINITE);

View File

@@ -1128,10 +1128,8 @@ public class PreCompilerBuilder extends BaseBuilder {
* Finish a file created/modified by an outside command line process.
* The file is marked as modified by Android, and the parent folder is refreshed, so that,
* in case the file didn't exist beforehand, the file appears in the package explorer.
* @param file The file to "finish".
* @param parent The parent container. Can be null (in which case it'll be
* figured out from the file's IResource.
* @param monitor a monitor to display progress.
* @param rFile The R file to "finish".
* @param manifestFile The manifest file to "finish".
* @throws CoreException
*/
private void finishJavaFilesAfterExternalModification(IFile rFile, IFile manifestFile)
@@ -1150,9 +1148,7 @@ public class PreCompilerBuilder extends BaseBuilder {
* The file is marked as modified by Android, and the parent folder is refreshed, so that,
* in case the file didn't exist beforehand, the file appears in the package explorer.
* @param file The file to "finish".
* @param parent The parent container. Can be null (in which case it'll be
* figured out from the file's IResource.
* @param monitor a monitor to display progress.
* @param aidlFile The AIDL file to "finish".
* @throws CoreException
*/
private void finishFileAfterExternalModification(IFile file, IFile aidlFile)

View File

@@ -23,6 +23,7 @@ import com.android.ide.eclipse.adt.project.ProjectHelper;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestParser;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import com.android.sdklib.SdkConstants;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
@@ -154,7 +155,7 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
// then we are not yet in a source or resource folder
mInRes = mInSrc = false;
if (AndroidConstants.FD_RESOURCES.equalsIgnoreCase(segments[1])) {
if (SdkConstants.FD_RESOURCES.equalsIgnoreCase(segments[1])) {
// this is the resource folder that was modified. we want to
// see its content.

View File

@@ -31,8 +31,12 @@ import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.debug.launching.DeviceChooserDialog.DeviceChooserResponse;
import com.android.ide.eclipse.adt.debug.ui.EmulatorConfigTab;
import com.android.ide.eclipse.adt.project.ProjectHelper;
import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.project.AndroidManifestHelper;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkManager;
import com.android.sdklib.vm.VmManager;
import com.android.sdklib.vm.VmManager.VmInfo;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
@@ -58,6 +62,7 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -69,9 +74,9 @@ import java.util.regex.Pattern;
public final class AndroidLaunchController implements IDebugBridgeChangeListener,
IDeviceChangeListener, IClientChangeListener {
private static final String FLAG_VM = "-vm"; //$NON-NLS-1$
private static final String FLAG_NETDELAY = "-netdelay"; //$NON-NLS-1$
private static final String FLAG_NETSPEED = "-netspeed"; //$NON-NLS-1$
private static final String FLAG_SKIN = "-skin"; //$NON-NLS-1$
private static final String FLAG_WIPE_DATA = "-wipe-data"; //$NON-NLS-1$
private static final String FLAG_NO_BOOT_ANIM = "-no-boot-anim"; //$NON-NLS-1$
@@ -223,11 +228,10 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
public boolean mNoBootAnim = LaunchConfigDelegate.DEFAULT_NO_BOOT_ANIM;
/**
* Screen size parameters.
* This value can be provided to the emulator directly for the option "-skin"
* Vm Name.
*/
public String mSkin = null;
public String mVmName = null;
public String mNetworkSpeed = EmulatorConfigTab.getSpeed(
LaunchConfigDelegate.DEFAULT_SPEED);
public String mNetworkDelay = EmulatorConfigTab.getDelay(
@@ -258,12 +262,8 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
}
try {
mSkin = config.getAttribute(LaunchConfigDelegate.ATTR_SKIN, mSkin);
if (mSkin == null) {
mSkin = SdkConstants.SKIN_DEFAULT;
}
mVmName = config.getAttribute(LaunchConfigDelegate.ATTR_VM_NAME, mVmName);
} catch (CoreException e) {
mSkin = SdkConstants.SKIN_DEFAULT;
}
int index = LaunchConfigDelegate.DEFAULT_SPEED;
@@ -526,11 +526,14 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
// set the launch mode to default.
wc.setAttribute(LaunchConfigDelegate.ATTR_LAUNCH_ACTION,
LaunchConfigDelegate.DEFAULT_LAUNCH_ACTION);
// set default target mode
wc.setAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE,
LaunchConfigDelegate.DEFAULT_TARGET_MODE);
// default VM: None
wc.setAttribute(LaunchConfigDelegate.ATTR_VM_NAME, (String)null);
// set the default network speed
wc.setAttribute(LaunchConfigDelegate.ATTR_SPEED,
LaunchConfigDelegate.DEFAULT_SPEED);
@@ -539,9 +542,6 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
wc.setAttribute(LaunchConfigDelegate.ATTR_DELAY,
LaunchConfigDelegate.DEFAULT_DELAY);
// default skin
wc.setAttribute(LaunchConfigDelegate.ATTR_SKIN, SdkConstants.SKIN_DEFAULT);
// default wipe data mode
wc.setAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA,
LaunchConfigDelegate.DEFAULT_WIPE_DATA);
@@ -627,32 +627,171 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
// set the debug mode
launchInfo.mDebugMode = mode.equals(ILaunchManager.DEBUG_MODE);
// device chooser response.
// get the SDK
Sdk currentSdk = Sdk.getCurrent();
VmManager vmManager = currentSdk.getVmManager();
// get the project target
final IAndroidTarget projectTarget = currentSdk.getTarget(project);
// FIXME: check errors on missing sdk, vm manager, or project target.
// device chooser response object.
final DeviceChooserResponse response = new DeviceChooserResponse();
/*
* Launch logic:
* - Manually Mode
* Always display a UI that lets a user see the current running emulators/devices.
* The UI must show which devices are compatibles, and allow launching new emulators
* with compatible (and not yet running) VM.
* - Automatic Way
* * Preferred VM set.
* If Preferred VM is not running: launch it.
* Launch the application on the preferred VM.
* * No preferred VM.
* Count the number of compatible emulators/devices.
* If != 1, display a UI similar to manual mode.
* If == 1, launch the application on this VM/device.
*/
if (config.mTargetMode == AndroidLaunchConfiguration.AUTO_TARGET_MODE) {
// if we are in automatic target mode, we need to find the current devices
Device[] devices = AndroidDebugBridge.getBridge().getDevices();
// depending on the number of devices, we'll simulate an automatic choice
// from the device chooser or simply show up the device chooser.
if (devices.length == 0) {
// if zero devices, we launch the device.
AdtPlugin.printToConsole(project, "Automatic Target Mode: launching new emulator.");
// first check if we have a preferred VM name, and if it actually exists, and is valid
// (ie able to run the project).
// We need to check this in case the VM was recreated with a different target that is
// not compatible.
VmInfo preferredVm = null;
if (config.mVmName != null) {
preferredVm = vmManager.getVm(config.mVmName);
if (projectTarget.isCompatibleBaseFor(preferredVm.getTarget()) == false) {
preferredVm = null;
AdtPlugin.printErrorToConsole(project, String.format(
"Preferred VM '%1$s' is not compatible with the project target '%2$s'. Looking for a compatible VM...",
config.mVmName, projectTarget.getName()));
}
}
if (preferredVm != null) {
// look for a matching device
for (Device d : devices) {
String deviceVm = d.getVmName();
if (deviceVm != null && deviceVm.equals(config.mVmName)) {
response.mustContinue = true;
response.mustLaunchEmulator = false;
response.deviceToUse = d;
AdtPlugin.printToConsole(project, String.format(
"Automatic Target Mode: Preferred VM '%1$s' is available on emulator '%2$s'",
config.mVmName, d));
continueLaunch(response, project, launch, launchInfo, config);
return;
}
}
// at this point we have a valid preferred VM that is not running.
// We need to start it.
response.mustContinue = true;
response.mustLaunchEmulator = true;
response.vmToLaunch = preferredVm;
AdtPlugin.printToConsole(project, String.format(
"Automatic Target Mode: Preferred VM '%1$s' is not available. Launching new emulator.",
config.mVmName));
continueLaunch(response, project, launch, launchInfo, config);
return;
} else if (devices.length == 1) {
}
// no (valid) preferred VM? look for one.
HashMap<Device, VmInfo> compatibleRunningVms = new HashMap<Device, VmInfo>();
boolean hasDevice = false; // if there's 1+ device running, we may force manual mode,
// as we cannot always detect proper compatibility with
// devices. This is the case if the project target is not
// a standard platform
for (Device d : devices) {
String deviceVm = d.getVmName();
if (deviceVm != null) { // physical devices return null.
VmInfo info = vmManager.getVm(deviceVm);
if (info != null && projectTarget.isCompatibleBaseFor(info.getTarget())) {
compatibleRunningVms.put(d, info);
}
} 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
compatibleRunningVms.put(d, null);
continue;
}
} catch (NumberFormatException e) {
// do nothing, we'll consider it a non compatible device below.
}
}
hasDevice = true;
}
}
// depending on the number of devices, we'll simulate an automatic choice
// from the device chooser or simply show up the device chooser.
if (hasDevice == false && compatibleRunningVms.size() == 0) {
// if zero emulators/devices, we launch an emulator.
// We need to figure out which VM first.
// we are going to take the closest VM. ie a compatible VM that has the API level
// closest to the project target.
VmInfo[] vms = vmManager.getVms();
VmInfo defaultVm = null;
for (VmInfo vm : vms) {
if (projectTarget.isCompatibleBaseFor(vm.getTarget())) {
if (defaultVm == null ||
vm.getTarget().getApiVersionNumber() <
defaultVm.getTarget().getApiVersionNumber()) {
defaultVm = vm;
}
}
}
if (defaultVm != null) {
response.mustContinue = true;
response.mustLaunchEmulator = true;
response.vmToLaunch = defaultVm;
AdtPlugin.printToConsole(project, String.format(
"Automatic Target Mode: launching new emulator with compatible VM '%1$s'",
defaultVm.getName()));
continueLaunch(response, project, launch, launchInfo, config);
return;
} else {
// FIXME: ask the user if he wants to create a VM.
// we found no compatible VM.
AdtPlugin.printErrorToConsole(project, String.format(
"Failed to find a VM compatible with target '%1$s'. Launch aborted.",
projectTarget.getName()));
launch.stopLaunch();
return;
}
} else if (hasDevice == false && compatibleRunningVms.size() == 1) {
Entry<Device, VmInfo> e = compatibleRunningVms.entrySet().iterator().next();
response.mustContinue = true;
response.mustLaunchEmulator = false;
response.deviceToUse = devices[0];
response.deviceToUse = e.getKey();
if (response.deviceToUse.isEmulator()) {
message = String.format("Automatic Target Mode: using existing emulator: %1$s",
response.deviceToUse);
// get the VmInfo, if null, the device is a physical device.
VmInfo vmInfo = e.getValue();
if (vmInfo != null) {
message = String.format("Automatic Target Mode: using existing emulator '%1$s' running compatible VM '%2$s'",
response.deviceToUse, e.getValue().getName());
} else {
message = String.format("Automatic Target Mode: using existing device: %1$s",
message = String.format("Automatic Target Mode: using device '%1$s'",
response.deviceToUse);
}
AdtPlugin.printToConsole(project, message);
@@ -662,8 +801,13 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
}
// if more than one device, we'll bring up the DeviceChooser dialog below.
AdtPlugin.printToConsole(project,
"Automatic Target Mode: user selection for 2+ devices.");
if (compatibleRunningVms.size() >= 2) {
message = "Automatic Target Mode: Several compatible targets. Please select a target device.";
} else if (hasDevice) {
message = "Automatic Target Mode: Unable to detect device compatibility. Please select a target device.";
}
AdtPlugin.printToConsole(project, message);
}
// bring up the device chooser.
@@ -671,7 +815,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
public void run() {
DeviceChooserDialog dialog = new DeviceChooserDialog(
AdtPlugin.getDisplay().getActiveShell());
dialog.open(response, project, launch, launchInfo, config);
dialog.open(response, project, projectTarget, launch, launchInfo, config);
}
});
@@ -705,7 +849,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
synchronized (sListLock) {
mWaitingForEmulatorLaunches.add(launchInfo);
AdtPlugin.printToConsole(project, "Launching a new emulator.");
boolean status = launchEmulator(config);
boolean status = launchEmulator(config, response.vmToLaunch);
if (status == false) {
// launching the emulator failed!
@@ -775,9 +919,6 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* the device requires it and it is not set in the manifest, the launch will be forced to
* "release" mode instead of "debug"</li>
* <ul>
* @param launchInfo
* @param device
* @return
*/
private boolean checkBuildInfo(DelayedLaunchInfo launchInfo, Device device) {
if (device != null) {
@@ -1122,7 +1263,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
/**
* launches an application on a device or emulator
*
* @param classToLaunch the fully-qualified name of the activity to launch
* @param info the {@link DelayedLaunchInfo} that indicates the activity to launch
* @param device the device or emulator to launch the application on
*/
private void launchApp(final DelayedLaunchInfo info, Device device) {
@@ -1182,7 +1323,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
}
}
private boolean launchEmulator(AndroidLaunchConfiguration config) {
private boolean launchEmulator(AndroidLaunchConfiguration config, VmInfo vmToLaunch) {
// split the custom command line in segments
ArrayList<String> customArgs = new ArrayList<String>();
@@ -1212,10 +1353,8 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
ArrayList<String> list = new ArrayList<String>();
list.add(AdtPlugin.getOsAbsoluteEmulator());
if (config.mSkin != null) {
list.add(FLAG_SKIN);
list.add(config.mSkin);
}
list.add(FLAG_VM);
list.add(vmToLaunch.getName());
if (config.mNetworkSpeed != null) {
list.add(FLAG_NETSPEED);
@@ -1329,7 +1468,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* @param debugPort The port to connect the debugger to
* @param androidLaunch The associated AndroidLaunch object.
* @param monitor A Progress monitor
* @see connectRemoveDebugger()
* @see #connectRemoteDebugger(int, AndroidLaunch, IProgressMonitor)
*/
public static void launchRemoteDebugger( final int debugPort, final AndroidLaunch androidLaunch,
final IProgressMonitor monitor) {
@@ -1352,7 +1491,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* This is sent from a non UI thread.
* @param bridge the new {@link AndroidDebugBridge} object.
*
* @see IDebugBridgeChangeListener#serverChanged(AndroidDebugBridge)
* @see IDebugBridgeChangeListener#bridgeChanged(AndroidDebugBridge)
*/
public void bridgeChanged(AndroidDebugBridge bridge) {
// The adb server has changed. We cancel any pending launches.
@@ -1447,7 +1586,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* @param device the device that was updated.
* @param changeMask the mask indicating what changed.
*
* @see IDeviceChangeListener#deviceChanged(Device)
* @see IDeviceChangeListener#deviceChanged(Device, int)
*/
public void deviceChanged(Device device, int changeMask) {
// We could check if any starting device we care about is now ready, but we can wait for
@@ -1622,7 +1761,6 @@ 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
* @throws InterruptedException
*/
private void grabEmulatorOutput(final Process process) {
// read the lines as they come. if null is returned, it's

View File

@@ -19,6 +19,7 @@ package com.android.ide.eclipse.adt.debug.launching;
import com.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.Client;
import com.android.ddmlib.Device;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener;
import com.android.ddmlib.Device.DeviceState;
import com.android.ddmuilib.IImageLoader;
@@ -27,7 +28,10 @@ import com.android.ddmuilib.TableHelper;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.debug.launching.AndroidLaunchController.AndroidLaunchConfiguration;
import com.android.ide.eclipse.adt.debug.launching.AndroidLaunchController.DelayedLaunchInfo;
import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.ddms.DdmsPlugin;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.vm.VmManager.VmInfo;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.preference.IPreferenceStore;
@@ -67,19 +71,26 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
private final static String PREFS_COL_SERIAL = "deviceChooser.serial"; //$NON-NLS-1$
private final static String PREFS_COL_STATE = "deviceChooser.state"; //$NON-NLS-1$
private final static String PREFS_COL_BUILD = "deviceChooser.build"; //$NON-NLS-1$
private final static String PREFS_COL_VM = "deviceChooser.vm"; //$NON-NLS-1$
private final static String PREFS_COL_TARGET = "deviceChooser.target"; //$NON-NLS-1$
private final static String PREFS_COL_DEBUG = "deviceChooser.debug"; //$NON-NLS-1$
private Table mDeviceTable;
private TableViewer mViewer;
private Image mDeviceImage;
private Image mEmulatorImage;
private Image mMatchImage;
private Image mNoMatchImage;
private Image mWarningImage;
private Button mOkButton;
private Button mCreateButton;
private DeviceChooserResponse mResponse;
private DelayedLaunchInfo mLaunchInfo;
private IAndroidTarget mProjectTarget;
private Sdk mSdk;
/**
* Basic Content Provider for a table full of {@link Device} objects. The input is
@@ -111,13 +122,44 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
private class LabelProvider implements ITableLabelProvider {
public Image getColumnImage(Object element, int columnIndex) {
if (columnIndex == 0 && element instanceof Device) {
if (((Device)element).isEmulator()) {
return mEmulatorImage;
if (element instanceof Device) {
Device device = (Device)element;
switch (columnIndex) {
case 0:
return device.isEmulator() ? mEmulatorImage : mDeviceImage;
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);
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;
}
} catch (NumberFormatException e) {
// lets consider the device non compatible
return mNoMatchImage;
}
} else {
// get the VmInfo
VmInfo info = mSdk.getVmManager().getVm(device.getVmName());
if (info == null) {
return mWarningImage;
}
return mProjectTarget.isCompatibleBaseFor(info.getTarget()) ?
mMatchImage : mNoMatchImage;
}
}
return mDeviceImage;
}
return null;
}
@@ -128,15 +170,30 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
case 0:
return device.getSerialNumber();
case 1:
return getStateString(device);
case 2:
String debuggable = device.getProperty(Device.PROP_DEBUGGABLE);
String version = device.getProperty(Device.PROP_BUILD_VERSION);
if (debuggable != null && debuggable.equals("1")) { //$NON-NLS-1$
return String.format("%1$s (debug)", version); //$NON-NLS-1$
if (device.isEmulator()) {
return device.getVmName();
} else {
return String.format("%1$s", version); //$NON-NLS-1$
return "N/A"; // devices don't have VM names.
}
case 2:
if (device.isEmulator()) {
VmInfo info = mSdk.getVmManager().getVm(device.getVmName());
if (info == null) {
return "?";
}
return info.getTarget().getFullName();
} else {
return device.getProperty(IDevice.PROP_BUILD_VERSION);
}
case 3:
String debuggable = device.getProperty(IDevice.PROP_DEBUGGABLE);
if (debuggable != null && debuggable.equals("1")) { //$NON-NLS-1$
return "Yes";
} else {
return "";
}
case 4:
return getStateString(device);
}
}
@@ -164,6 +221,7 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
public static class DeviceChooserResponse {
public boolean mustContinue;
public boolean mustLaunchEmulator;
public VmInfo vmToLaunch;
public Device deviceToUse;
}
@@ -175,14 +233,18 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
* Prepare and display the dialog.
* @param response
* @param project
* @param projectTarget
* @param launch
* @param launchInfo
* @param config
*/
public void open(DeviceChooserResponse response, IProject project,
AndroidLaunch launch, DelayedLaunchInfo launchInfo, AndroidLaunchConfiguration config) {
IAndroidTarget projectTarget, AndroidLaunch launch, DelayedLaunchInfo launchInfo,
AndroidLaunchConfiguration config) {
mResponse = response;
mProjectTarget = projectTarget;
mLaunchInfo = launchInfo;
mSdk = Sdk.getCurrent();
Shell parent = getParent();
Shell shell = new Shell(parent, getStyle());
@@ -218,6 +280,9 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
mEmulatorImage.dispose();
mDeviceImage.dispose();
mMatchImage.dispose();
mNoMatchImage.dispose();
mWarningImage.dispose();
AndroidLaunchController.getInstance().continueLaunch(response, project, launch,
launchInfo, config);
@@ -249,14 +314,22 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
SWT.LEFT, "AAA+AAAAAAAAAAAAAAAAAAA", //$NON-NLS-1$
PREFS_COL_SERIAL, store);
TableHelper.createTableColumn(mDeviceTable, "VM Name",
SWT.LEFT, "engineering", //$NON-NLS-1$
PREFS_COL_VM, store);
TableHelper.createTableColumn(mDeviceTable, "Target",
SWT.LEFT, "AAA+Android 9.9.9", //$NON-NLS-1$
PREFS_COL_TARGET, store);
TableHelper.createTableColumn(mDeviceTable, "Debug",
SWT.LEFT, "Debug", //$NON-NLS-1$
PREFS_COL_DEBUG, store);
TableHelper.createTableColumn(mDeviceTable, "State",
SWT.LEFT, "bootloader", //$NON-NLS-1$
PREFS_COL_STATE, store);
TableHelper.createTableColumn(mDeviceTable, "Build Info",
SWT.LEFT, "engineering", //$NON-NLS-1$
PREFS_COL_BUILD, store);
// create the viewer for it
mViewer = new TableViewer(mDeviceTable);
mViewer.setContentProvider(new ContentProvider());
@@ -357,20 +430,42 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
}
private void loadImages() {
IImageLoader loader = DdmsPlugin.getImageLoader();
IImageLoader ddmsLoader = DdmsPlugin.getImageLoader();
Display display = DdmsPlugin.getDisplay();
IImageLoader adtLoader = AdtPlugin.getImageLoader();
if (mDeviceImage == null) {
mDeviceImage = ImageHelper.loadImage(loader, display,
mDeviceImage = ImageHelper.loadImage(ddmsLoader, display,
"device.png", //$NON-NLS-1$
ICON_WIDTH, ICON_WIDTH,
display.getSystemColor(SWT.COLOR_RED));
}
if (mEmulatorImage == null) {
mEmulatorImage = ImageHelper.loadImage(loader, display,
mEmulatorImage = ImageHelper.loadImage(ddmsLoader, display,
"emulator.png", ICON_WIDTH, ICON_WIDTH, //$NON-NLS-1$
display.getSystemColor(SWT.COLOR_BLUE));
}
if (mMatchImage == null) {
mMatchImage = ImageHelper.loadImage(adtLoader, display,
"match.png", //$NON-NLS-1$
ICON_WIDTH, ICON_WIDTH,
display.getSystemColor(SWT.COLOR_GREEN));
}
if (mNoMatchImage == null) {
mNoMatchImage = ImageHelper.loadImage(adtLoader, display,
"error.png", //$NON-NLS-1$
ICON_WIDTH, ICON_WIDTH,
display.getSystemColor(SWT.COLOR_RED));
}
if (mWarningImage == null) {
mWarningImage = ImageHelper.loadImage(adtLoader, display,
"warning.png", //$NON-NLS-1$
ICON_WIDTH, ICON_WIDTH,
display.getSystemColor(SWT.COLOR_YELLOW));
}
}
@@ -438,7 +533,7 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
* @param device the device that was updated.
* @param changeMask the mask indicating what changed.
*
* @see IDeviceChangeListener#deviceChanged(Device)
* @see IDeviceChangeListener#deviceChanged(Device, int)
*/
public void deviceChanged(final Device device, int changeMask) {
if ((changeMask & (Device.CHANGE_STATE | Device.CHANGE_BUILD_INFO)) != 0) {

View File

@@ -80,9 +80,8 @@ public class LaunchConfigDelegate extends LaunchConfigurationDelegate {
*/
public static final String ATTR_ACTIVITY = AdtPlugin.PLUGIN_ID + ".activity"; //$NON-NLS-1$
/** Skin to be used to launch the emulator */
public static final String ATTR_SKIN = AdtPlugin.PLUGIN_ID + ".skin"; //$NON-NLS-1$
public static final String ATTR_VM_NAME = AdtPlugin.PLUGIN_ID + ".vm"; //$NON-NLS-1$
public static final String ATTR_SPEED = AdtPlugin.PLUGIN_ID + ".speed"; //$NON-NLS-1$
/**
@@ -317,6 +316,10 @@ public class LaunchConfigDelegate extends LaunchConfigurationDelegate {
1 /* code, unused */, "Can't find the project!", null /* exception */));
}
/**
* {@inheritDoc}
* @throws CoreException
*/
@Override
public ILaunch getLaunch(ILaunchConfiguration configuration, String mode)
throws CoreException {
@@ -406,8 +409,6 @@ public class LaunchConfigDelegate extends LaunchConfigurationDelegate {
/**
* Returns the name of the activity.
* @param configuration
* @return
*/
private String getActivityName(ILaunchConfiguration configuration) {
String empty = "";

View File

@@ -22,7 +22,9 @@ import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import com.android.ide.eclipse.ddms.DdmsPlugin;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.vm.VmManager;
import com.android.sdklib.vm.VmManager.VmInfo;
import com.android.sdkuilib.VmSelector;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
@@ -70,6 +72,11 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
{ "UMTS", "umts" }, //$NON-NLS-2$
};
private Button mAutoTargetButton;
private Button mManualTargetButton;
private VmSelector mPreferredVmSelector;
private Combo mSpeedCombo;
private Combo mDelayCombo;
@@ -78,18 +85,10 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
private Text mEmulatorCLOptions;
private Combo mSkinCombo;
private Button mAutoTargetButton;
private Button mManualTargetButton;
private Button mWipeDataButton;
private Button mNoBootAnimButton;
private IAndroidTarget mTarget;
/**
* Returns the emulator ready speed option value.
* @param value The index of the combo selection.
@@ -147,6 +146,11 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
targetModeGroup.setLayout(layout);
targetModeGroup.setFont(font);
mManualTargetButton = new Button(targetModeGroup, SWT.RADIO);
mManualTargetButton.setText("Manual");
// Since there are only 2 radio buttons, we can put a listener on only one (they
// are both called on select and unselect event.
// add the radio button
mAutoTargetButton = new Button(targetModeGroup, SWT.RADIO);
mAutoTargetButton.setText("Automatic");
@@ -159,11 +163,16 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
}
});
mManualTargetButton = new Button(targetModeGroup, SWT.RADIO);
mManualTargetButton.setText("Manual");
// Since there are only 2 radio buttons, we can put a listener on only
// one (they
// are both called on select and unselect event.
new Label(targetModeGroup, SWT.NONE).setText("Preferred VM");
VmInfo[] vms = new VmInfo[0];
mPreferredVmSelector = new VmSelector(targetModeGroup, vms,
false /*allowMultipleSelection*/);
mPreferredVmSelector.setSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
updateLaunchConfigurationDialog();
}
});
// emulator size
mEmulatorOptionsGroup = new Group(topComp, SWT.NONE);
@@ -174,17 +183,6 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
mEmulatorOptionsGroup.setLayout(layout);
mEmulatorOptionsGroup.setFont(font);
new Label(mEmulatorOptionsGroup, SWT.NONE).setText("Screen Size:");
mSkinCombo = new Combo(mEmulatorOptionsGroup, SWT.READ_ONLY);
mSkinCombo.addSelectionListener(new SelectionAdapter() {
// called when selection changes
@Override
public void widgetSelected(SelectionEvent e) {
updateLaunchConfigurationDialog();
}
});
// network options
new Label(mEmulatorOptionsGroup, SWT.NONE).setText("Network Speed:");
@@ -279,8 +277,9 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
*/
public void initializeFrom(ILaunchConfiguration configuration) {
boolean value = LaunchConfigDelegate.DEFAULT_TARGET_MODE; // true ==
// automatic
VmManager vmManager = Sdk.getCurrent().getVmManager();
boolean value = LaunchConfigDelegate.DEFAULT_TARGET_MODE; // true == automatic
try {
value = configuration.getAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE, value);
} catch (CoreException e) {
@@ -290,11 +289,12 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
mManualTargetButton.setSelection(!value);
// look for the project name to get its target.
String projectName = "";
String stringValue = "";
try {
projectName = configuration.getAttribute(
IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, projectName);
stringValue = configuration.getAttribute(
IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, stringValue);
} catch (CoreException ce) {
// let's not do anything here, we'll use the default value
}
IProject project = null;
@@ -304,25 +304,41 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
if (projects != null) {
// look for the project whose name we read from the configuration.
for (IJavaProject p : projects) {
if (p.getElementName().equals(projectName)) {
if (p.getElementName().equals(stringValue)) {
project = p.getProject();
break;
}
}
}
mSkinCombo.removeAll();
// update the VM list
VmInfo[] vms = null;
if (vmManager != null) {
vms = vmManager.getVms();
}
IAndroidTarget projectTarget = null;
if (project != null) {
mTarget = Sdk.getCurrent().getTarget(project);
if (mTarget != null) {
String[] skins = mTarget.getSkins();
if (skins != null) {
for (String skin : skins) {
mSkinCombo.add(skin);
}
mSkinCombo.pack();
}
}
projectTarget = Sdk.getCurrent().getTarget(project);
} else {
vms = null; // no project? we don't want to display any "compatible" VMs.
}
mPreferredVmSelector.setVms(vms, projectTarget);
stringValue = "";
try {
stringValue = configuration.getAttribute(LaunchConfigDelegate.ATTR_VM_NAME,
stringValue);
} catch (CoreException e) {
// let's not do anything here, we'll use the default value
}
if (stringValue != null && stringValue.length() > 0 && vmManager != null) {
VmInfo targetVm = vmManager.getVm(stringValue);
mPreferredVmSelector.setSelection(targetVm);
} else {
mPreferredVmSelector.setSelection(null);
}
value = LaunchConfigDelegate.DEFAULT_WIPE_DATA;
@@ -342,23 +358,6 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
mNoBootAnimButton.setSelection(value);
int index = -1;
try {
String skin = configuration.getAttribute(LaunchConfigDelegate.ATTR_SKIN, (String)null);
if (skin == null) {
skin = SdkConstants.SKIN_DEFAULT;
}
index = getSkinIndex(skin);
} catch (CoreException e) {
index = getSkinIndex(SdkConstants.SKIN_DEFAULT);
}
if (index == -1) {
mSkinCombo.select(0);
updateLaunchConfigurationDialog();
} else {
mSkinCombo.select(index);
}
index = LaunchConfigDelegate.DEFAULT_SPEED;
try {
@@ -405,8 +404,12 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
public void performApply(ILaunchConfigurationWorkingCopy configuration) {
configuration.setAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE,
mAutoTargetButton.getSelection());
configuration.setAttribute(LaunchConfigDelegate.ATTR_SKIN,
getSkinNameByIndex(mSkinCombo.getSelectionIndex()));
VmInfo vm = mPreferredVmSelector.getFirstSelected();
if (vm != null) {
configuration.setAttribute(LaunchConfigDelegate.ATTR_VM_NAME, vm.getName());
} else {
configuration.setAttribute(LaunchConfigDelegate.ATTR_VM_NAME, (String)null);
}
configuration.setAttribute(LaunchConfigDelegate.ATTR_SPEED,
mSpeedCombo.getSelectionIndex());
configuration.setAttribute(LaunchConfigDelegate.ATTR_DELAY,
@@ -425,8 +428,6 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
configuration.setAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE,
LaunchConfigDelegate.DEFAULT_TARGET_MODE);
configuration.setAttribute(LaunchConfigDelegate.ATTR_SKIN,
SdkConstants.SKIN_DEFAULT);
configuration.setAttribute(LaunchConfigDelegate.ATTR_SPEED,
LaunchConfigDelegate.DEFAULT_SPEED);
configuration.setAttribute(LaunchConfigDelegate.ATTR_DELAY,
@@ -440,33 +441,4 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
String emuOptions = store.getString(AdtPlugin.PREFS_EMU_OPTIONS);
configuration.setAttribute(LaunchConfigDelegate.ATTR_COMMANDLINE, emuOptions);
}
private String getSkinNameByIndex(int index) {
if (mTarget != null && index > 0) {
String[] skins = mTarget.getSkins();
if (skins != null && index < skins.length) {
return skins[index];
}
}
return null;
}
private int getSkinIndex(String name) {
if (mTarget != null) {
String[] skins = mTarget.getSkins();
if (skins != null) {
int index = 0;
for (String skin : skins) {
if (skin.equalsIgnoreCase(name)) {
return index;
}
index++;
}
}
}
return -1;
}
}

View File

@@ -398,11 +398,13 @@ public class MainLaunchConfigTab extends AbstractLaunchConfigurationTab {
config.setMappedResources(resources);
}
/** Loads the ui with the activities of the specified project, and store the
* activities in <code>mActivities</code>
/**
* Loads the ui with the activities of the specified project, and stores the
* activities in <code>mActivities</code>.
* <p/>
* First activity is selected by default if present.
* @param project The project to load the activities from
* @return The array of activities or null if none could be found.
*
* @param project The project to load the activities from.
*/
private void loadActivities(IProject project) {
if (project != null) {

View File

@@ -199,7 +199,7 @@ public class BuildPreferencePage extends FieldEditorPreferencePage implements
*/
private void handleException(Throwable t) {
String msg = t.getMessage();
if (t == null) {
if (msg == null) {
Throwable cause = t.getCause();
if (cause != null) {
handleException(cause);

View File

@@ -18,6 +18,7 @@ package com.android.ide.eclipse.adt.project;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.sdklib.SdkConstants;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
@@ -53,13 +54,13 @@ public class FolderDecorator implements ILightweightLabelDecorator {
// check the folder is directly under the project.
if (folder.getParent().getType() == IResource.PROJECT) {
String name = folder.getName();
if (name.equals(AndroidConstants.FD_ASSETS)) {
if (name.equals(SdkConstants.FD_ASSETS)) {
decorate(decoration, " [Android assets]");
decoration.addOverlay(mDescriptor, IDecoration.TOP_RIGHT);
} else if (name.equals(AndroidConstants.FD_RESOURCES)) {
} else if (name.equals(SdkConstants.FD_RESOURCES)) {
decorate(decoration, " [Android resources]");
decoration.addOverlay(mDescriptor, IDecoration.TOP_RIGHT);
} else if (name.equals(AndroidConstants.FD_NATIVE_LIBS)) {
} else if (name.equals(SdkConstants.FD_NATIVE_LIBS)) {
decorate(decoration, " [Native Libraries]");
}
}

View File

@@ -493,7 +493,7 @@ public final class ExportWizard extends Wizard implements IExportWizard {
}
// no more cause and still no message. display the first exception.
return cause.getClass().getCanonicalName();
return t.getClass().getCanonicalName();
}
return message;

View File

@@ -256,7 +256,6 @@ final class ProjectCheckPage extends ExportWizardPage {
/**
* Checks the parameters for correctness, and update the error message and buttons.
* @return the current IProject of this launch config.
*/
private void handleProjectNameChange() {
setPageComplete(false);

View File

@@ -28,8 +28,12 @@ import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.ClasspathContainerInitializer;
import org.eclipse.jdt.core.IAccessRule;
import org.eclipse.jdt.core.IClasspathAttribute;
@@ -125,7 +129,7 @@ public class AndroidClasspathContainerInitializer extends ClasspathContainerInit
*/
private static IClasspathContainer allocateAndroidContainer(String containerId,
IJavaProject javaProject) {
IProject iProject = javaProject.getProject();
final IProject iProject = javaProject.getProject();
// remove potential MARKER_TARGETs.
try {
@@ -139,7 +143,9 @@ public class AndroidClasspathContainerInitializer extends ClasspathContainerInit
}
// first we check if the SDK has been loaded
// First we check if the SDK has been loaded.
// By passing the javaProject to getSdkLoadStatus(), we ensure that, should the SDK
// not be loaded yet, the classpath container will be resolved again once the SDK is loaded.
boolean sdkIsLoaded = AdtPlugin.getDefault().getSdkLoadStatus(javaProject) ==
LoadStatus.LOADED;
@@ -172,8 +178,14 @@ public class AndroidClasspathContainerInitializer extends ClasspathContainerInit
String message = null;
boolean outputToConsole = true;
if (hashString == null || hashString.length() == 0) {
message = String.format(
"Project has no target set. Edit the project properties to set one.");
// if there is no hash string we only show this if the SDK is loaded.
// For a project opened at start-up with no target, this would be displayed twice,
// once when the project is opened, and once after the SDK has finished loading.
// By testing the sdk is loaded, we only show this once in the console.
if (sdkIsLoaded) {
message = String.format(
"Project has no target set. Edit the project properties to set one.");
}
} else if (sdkIsLoaded) {
message = String.format(
"Unable to resolve target '%s'", hashString);
@@ -187,23 +199,41 @@ public class AndroidClasspathContainerInitializer extends ClasspathContainerInit
// and it's expected. (we do keep the error marker though).
outputToConsole = false;
}
if (message != null) {
// log the error and put the marker on the project if we can.
if (outputToConsole) {
AdtPlugin.printBuildToConsole(AdtConstants.BUILD_ALWAYS, iProject, message);
}
try {
BaseProjectHelper.addMarker(iProject, AdtConstants.MARKER_TARGET, message, -1,
IMarker.SEVERITY_ERROR, IMarker.PRIORITY_HIGH);
} catch (CoreException e) {
// In some cases, the workspace may be locked for modification when we pass here.
// We schedule a new job to put the marker after.
final String fmessage = message;
Job markerJob = new Job("Android SDK: Resolving error markers") {
@SuppressWarnings("unchecked")
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
BaseProjectHelper.addMarker(iProject, AdtConstants.MARKER_TARGET,
fmessage, -1, IMarker.SEVERITY_ERROR, IMarker.PRIORITY_HIGH);
} catch (CoreException e2) {
return e2.getStatus();
}
// log the error and put the marker on the project
if (outputToConsole) {
AdtPlugin.printBuildToConsole(AdtConstants.BUILD_ALWAYS, iProject, message);
return Status.OK_STATUS;
}
};
// build jobs are run after other interactive jobs
markerJob.setPriority(Job.BUILD);
markerJob.schedule();
}
}
IMarker marker = BaseProjectHelper.addMarker(iProject, AdtConstants.MARKER_TARGET, message,
IMarker.SEVERITY_ERROR);
// add a marker priority as this is an more important error than the error that will
// spring from the lack of library
try {
marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
} catch (CoreException e) {
// just log the error
AdtPlugin.log(e, "Error changing target marker priority.");
}
// return a dummy container to replace the one we may have had before.
return new IClasspathContainer() {
public IClasspathEntry[] getClasspathEntries() {

View File

@@ -37,7 +37,8 @@ import javax.management.InvalidAttributeValueException;
public class AndroidJarLoader extends ClassLoader implements IAndroidClassLoader {
/**
* Wrapper around a {@link Class} to provide the methods of {@link IClassDescriptor}.
* Wrapper around a {@link Class} to provide the methods of
* {@link IAndroidClassLoader.IClassDescriptor}.
*/
public final static class ClassWrapper implements IClassDescriptor {
private Class<?> mClass;
@@ -416,7 +417,7 @@ public class AndroidJarLoader extends ClassLoader implements IAndroidClassLoader
}
/**
* Returns a {@link IClass} by its fully-qualified name.
* Returns a {@link IAndroidClassLoader.IClassDescriptor} by its fully-qualified name.
* @param className the fully-qualified name of the class to return.
* @throws ClassNotFoundException
*/

View File

@@ -82,11 +82,8 @@ public final class AndroidTargetParser {
/**
* Parses the framework, collects all interesting information and stores them in the
* {@link FrameworkResourceManager} given to the constructor.
* {@link IAndroidTarget} given to the constructor.
*
* @param osSdkPath the OS path of the SDK directory.
* @param resourceManager the {@link FrameworkResourceManager} that will store the parsed
* resources.
* @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.
*/
@@ -400,7 +397,6 @@ public final class AndroidTargetParser {
* 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 osLibPath The OS path to the SDK tools/lib folder, ending with a separator.
* @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.

View File

@@ -64,7 +64,7 @@ public interface IAndroidClassLoader {
throws IOException, InvalidAttributeValueException, ClassFormatError;
/**
* Returns a {@link IClass} by its fully-qualified name.
* Returns a {@link IClassDescriptor} by its fully-qualified name.
* @param className the fully-qualified name of the class to return.
* @throws ClassNotFoundException
*/

View File

@@ -18,17 +18,17 @@ package com.android.ide.eclipse.adt.sdk;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.project.internal.AndroidClasspathContainerInitializer;
import com.android.prefs.AndroidLocation.AndroidLocationException;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.SdkManager;
import com.android.sdklib.project.ProjectProperties;
import com.android.sdklib.project.ProjectProperties.PropertyType;
import com.android.sdklib.vm.VmManager;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
@@ -46,21 +46,20 @@ import java.util.HashMap;
* To start using an SDK, call {@link #loadSdk(String)} which returns the instance of
* the Sdk object.
*
* To get the list of platforms present in the SDK, call {@link #getPlatforms()}.
* To get the list of add-ons present in the SDK, call {@link #getAddons()}.
*
* To get the list of platforms or add-ons present in the SDK, call {@link #getTargets()}.
*/
public class Sdk {
private final static String PROPERTY_PROJECT_TARGET = "androidTarget"; //$NON-NLS-1$
private static Sdk sCurrentSdk = null;
private final SdkManager mManager;
private final VmManager mVmManager;
private final HashMap<IProject, IAndroidTarget> mProjectMap =
new HashMap<IProject, IAndroidTarget>();
private final HashMap<IAndroidTarget, AndroidTargetData> mTargetMap =
new HashMap<IAndroidTarget, AndroidTargetData>();
private final String mDocBaseUrl;
/**
* Loads an SDK and returns an {@link Sdk} object if success.
@@ -74,18 +73,33 @@ public class Sdk {
final ArrayList<String> logMessages = new ArrayList<String>();
ISdkLog log = new ISdkLog() {
public void error(String errorFormat, Object... arg) {
logMessages.add(String.format(errorFormat, arg));
public void error(Throwable throwable, String errorFormat, Object... arg) {
if (errorFormat != null) {
logMessages.add(String.format(errorFormat, arg));
}
if (throwable != null) {
logMessages.add(throwable.getMessage());
}
}
public void warning(String warningFormat, Object... arg) {
logMessages.add(String.format(warningFormat, arg));
}
public void printf(String msgFormat, Object... arg) {
logMessages.add(String.format(msgFormat, arg));
}
};
// get an SdkManager object for the location
SdkManager manager = SdkManager.createManager(sdkLocation, log);
if (manager != null) {
sCurrentSdk = new Sdk(manager);
VmManager vmManager = null;
try {
vmManager = new VmManager(manager, log);
} catch (AndroidLocationException e) {
log.error(e, "Error parsing the VMs");
}
sCurrentSdk = new Sdk(manager, vmManager);
return sCurrentSdk;
} else {
StringBuilder sb = new StringBuilder("Error Loading the SDK:\n");
@@ -105,6 +119,13 @@ public class Sdk {
return sCurrentSdk;
}
/**
* Returns the location (OS path) of the current SDK.
*/
public String getSdkLocation() {
return mManager.getLocation();
}
/**
* Returns the URL to the local documentation.
* Can return null if no documentation is found in the current SDK.
@@ -181,7 +202,8 @@ public class Sdk {
*/
public static String getProjectTargetHashString(IProject project) {
// load the default.properties from the project folder.
ProjectProperties properties = ProjectProperties.load(project.getLocation().toOSString());
ProjectProperties properties = ProjectProperties.load(project.getLocation().toOSString(),
PropertyType.DEFAULT);
if (properties == null) {
AdtPlugin.log(IStatus.ERROR, "Failed to load properties file for project '%s'",
project.getName());
@@ -200,10 +222,12 @@ public class Sdk {
public static void setProjectTargetHashString(IProject project, String targetHashString) {
// because we don't want to erase other properties from default.properties, we first load
// them
ProjectProperties properties = ProjectProperties.load(project.getLocation().toOSString());
ProjectProperties properties = ProjectProperties.load(project.getLocation().toOSString(),
PropertyType.DEFAULT);
if (properties == null) {
// doesn't exist yet? we create it.
properties = ProjectProperties.create(project.getLocation().toOSString());
properties = ProjectProperties.create(project.getLocation().toOSString(),
PropertyType.DEFAULT);
}
// add/change the target hash string.
@@ -218,7 +242,7 @@ public class Sdk {
}
}
/**
* Return the {@link PlatformData} for a given {@link IAndroidTarget}.
* Return the {@link AndroidTargetData} for a given {@link IAndroidTarget}.
*/
public AndroidTargetData getTargetData(IAndroidTarget target) {
synchronized (mTargetMap) {
@@ -226,8 +250,17 @@ public class Sdk {
}
}
private Sdk(SdkManager manager) {
/**
* Returns the {@link VmManager}. If the VmManager failed to parse the VM folder, this could
* be <code>null</code>.
*/
public VmManager getVmManager() {
return mVmManager;
}
private Sdk(SdkManager manager, VmManager vmManager) {
mManager = manager;
mVmManager = vmManager;
// pre-compute some paths
mDocBaseUrl = getDocumentationBaseUrl(mManager.getLocation() +

View File

@@ -323,7 +323,7 @@ public final class WidgetClassLoader implements IAndroidClassLoader {
}
/**
* Returns a {@link IClass} by its fully-qualified name.
* Returns a {@link IAndroidClassLoader.IClassDescriptor} by its fully-qualified name.
* @param className the fully-qualified name of the class to return.
* @throws ClassNotFoundException
*/

View File

@@ -26,6 +26,7 @@ import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestHelper;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import com.android.sdkuilib.SdkTargetSelector;
import org.eclipse.core.filesystem.URIUtil;
@@ -64,9 +65,11 @@ import java.util.regex.Pattern;
* NewAndroidProjectCreationPage is a project creation page that provides the
* following fields:
* <ul>
* <li> Project name
* <li> SDK Target
* <li> Application name
* <li> Package name
* <li> Activity name
* <li> Location of the SDK
* </ul>
* Note: this class is public so that it can be accessed from unit tests.
* It is however an internal class. Its API may change without notice.
@@ -93,13 +96,14 @@ public class NewProjectCreationPage extends WizardPage {
private static final Pattern sProjectNamePattern = Pattern.compile("^[\\w][\\w. -]*$"); //$NON-NLS-1$
/** Last user-browsed location, static so that it be remembered for the whole session */
private static String sCustomLocationOsPath = ""; //$NON-NLS-1$
private static boolean sAutoComputeCustomLocation = true;
private final int MSG_NONE = 0;
private final int MSG_WARNING = 1;
private final int MSG_ERROR = 2;
private String mUserPackageName = ""; //$NON-NLS-1$
private String mUserActivityName = ""; //$NON-NLS-1$
private String mUserActivityName = ""; //$NON-NLS-1$
private boolean mUserCreateActivityCheck = INITIAL_CREATE_ACTIVITY;
private String mSourceFolder = ""; //$NON-NLS-1$
@@ -114,6 +118,8 @@ public class NewProjectCreationPage extends WizardPage {
private Text mLocationPathField;
private Button mBrowseButton;
private Button mCreateActivityCheck;
private Text mMinSdkVersionField;
private SdkTargetSelector mSdkTargetSelector;
private boolean mInternalLocationPathUpdate;
protected boolean mInternalProjectNameUpdate;
@@ -122,7 +128,7 @@ public class NewProjectCreationPage extends WizardPage {
private boolean mInternalActivityNameUpdate;
protected boolean mProjectNameModifiedByUser;
protected boolean mApplicationNameModifiedByUser;
private SdkTargetSelector mSdkTargetSelector;
private boolean mInternalMinSdkVersionUpdate;
/**
@@ -133,13 +139,6 @@ public class NewProjectCreationPage extends WizardPage {
public NewProjectCreationPage(String pageName) {
super(pageName);
setPageComplete(false);
if (sCustomLocationOsPath == null ||
sCustomLocationOsPath.length() == 0 ||
!new File(sCustomLocationOsPath).isDirectory()) {
// FIXME location of samples is pretty much impossible here.
//sCustomLocationOsPath = AdtPlugin.getOsSdkSamplesFolder();
sCustomLocationOsPath = File.listRoots()[0].getAbsolutePath();
}
}
// --- Getters used by NewProjectWizard ---
@@ -170,6 +169,11 @@ public class NewProjectCreationPage extends WizardPage {
return mActivityNameField == null ? INITIAL_NAME : mActivityNameField.getText().trim();
}
/** Returns the value of the min sdk version field with spaces trimmed. */
public String getMinSdkVersion() {
return mMinSdkVersionField == null ? "" : mMinSdkVersionField.getText().trim();
}
/** Returns the value of the application name field with spaces trimmed. */
public String getApplicationName() {
// Return the name of the activity as default application name.
@@ -200,7 +204,7 @@ public class NewProjectCreationPage extends WizardPage {
* "src" constant. */
public String getSourceFolder() {
if (isNewProject() || mSourceFolder == null || mSourceFolder.length() == 0) {
return AndroidConstants.FD_SOURCES;
return SdkConstants.FD_SOURCES;
} else {
return mSourceFolder;
}
@@ -389,9 +393,16 @@ public class NewProjectCreationPage extends WizardPage {
}
mSdkTargetSelector = new SdkTargetSelector(group, targets, false /*multi-selection*/);
// If there's only one target, select it
if (targets != null && targets.length == 1) {
mSdkTargetSelector.setSelection(targets[0]);
}
mSdkTargetSelector.setSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
updateLocationPathField(null);
setPageComplete(validatePage());
}
});
@@ -506,6 +517,25 @@ public class NewProjectCreationPage extends WizardPage {
onActivityNameFieldModified();
}
});
// min sdk version label
label = new Label(group, SWT.NONE);
label.setText("Min SDK Version:");
label.setFont(parent.getFont());
label.setToolTipText("The minimum SDK version number that the application requires. Must be an integer > 0. It can be empty.");
// min sdk version entry field
mMinSdkVersionField = new Text(group, SWT.BORDER);
data = new GridData(GridData.FILL_HORIZONTAL);
label.setToolTipText("The minimum SDK version number that the application requires. Must be an integer > 0. It can be empty.");
mMinSdkVersionField.setLayoutData(data);
mMinSdkVersionField.setFont(parent.getFont());
mMinSdkVersionField.addListener(SWT.Modify, new Listener() {
public void handleEvent(Event event) {
onMinSdkVersionFieldModified();
setPageComplete(validatePage());
}
});
}
@@ -588,7 +618,29 @@ public class NewProjectCreationPage extends WizardPage {
mInternalLocationPathUpdate = true;
if (custom_location) {
if (abs_dir != null) {
// We get here if the user selected a directory with the "Browse" button.
// Disable auto-compute of the custom location unless the user selected
// the exact same path.
sAutoComputeCustomLocation = sAutoComputeCustomLocation &&
abs_dir.equals(sCustomLocationOsPath);
sCustomLocationOsPath = TextProcessor.process(abs_dir);
} else if (sAutoComputeCustomLocation ||
!new File(sCustomLocationOsPath).isDirectory()) {
// By default select the samples directory of the current target
IAndroidTarget target = getSdkTarget();
if (target != null) {
sCustomLocationOsPath = target.getPath(IAndroidTarget.SAMPLES);
}
// If we don't have a target, select the base directory of the
// "universal sdk". If we don't even have that, use a root drive.
if (sCustomLocationOsPath == null || sCustomLocationOsPath.length() == 0) {
if (Sdk.getCurrent() != null) {
sCustomLocationOsPath = Sdk.getCurrent().getSdkLocation();
} else {
sCustomLocationOsPath = File.listRoots()[0].getAbsolutePath();
}
}
}
if (!mLocationPathField.getText().equals(sCustomLocationOsPath)) {
mLocationPathField.setText(sCustomLocationOsPath);
@@ -615,8 +667,13 @@ public class NewProjectCreationPage extends WizardPage {
private void onLocationPathFieldModified() {
if (!mInternalLocationPathUpdate) {
// When the updates doesn't come from updateLocationPathField, it must be the user
// editing the field manually, in which case we want to save the value internally.
sCustomLocationOsPath = getLocationPathFieldValue();
// editing the field manually, in which case we want to save the value internally
// and we disable auto-compute of the custom location (to avoid overriding the user
// value)
String newPath = getLocationPathFieldValue();
sAutoComputeCustomLocation = sAutoComputeCustomLocation &&
newPath.equals(sCustomLocationOsPath);
sCustomLocationOsPath = newPath;
extractNamesFromAndroidManifest();
setPageComplete(validatePage());
}
@@ -664,6 +721,31 @@ public class NewProjectCreationPage extends WizardPage {
}
}
/**
* Called when the min sdk version field has been modified.
*
* Ignore the internal modifications. When modified by the user, try to match
* a target with the same API level.
*/
private void onMinSdkVersionFieldModified() {
if (mInternalMinSdkVersionUpdate) {
return;
}
try {
int version = Integer.parseInt(getMinSdkVersion());
for (IAndroidTarget target : mSdkTargetSelector.getTargets()) {
if (target.getApiVersionNumber() == version) {
mSdkTargetSelector.setSelection(target);
break;
}
}
} catch (NumberFormatException e) {
// ignore
}
}
/**
* Called when the radio buttons are changed between the "create new project" and the
* "use existing source" mode. This reverts the fields to whatever the user manually
@@ -697,89 +779,132 @@ public class NewProjectCreationPage extends WizardPage {
* can actually be found in the custom user directory.
*/
private void extractNamesFromAndroidManifest() {
if (!isNewProject()) {
File f = new File(getProjectLocation());
if (f.isDirectory()) {
Path path = new Path(f.getPath());
String osPath = path.append(AndroidConstants.FN_ANDROID_MANIFEST).toOSString();
AndroidManifestHelper manifest = new AndroidManifestHelper(osPath);
if (manifest.exists()) {
String packageName = null;
String activityName = null;
try {
packageName = manifest.getPackageName();
activityName = manifest.getActivityName(1);
} catch (Exception e) {
// pass
}
if (isNewProject()) {
return;
}
String projectLocation = getProjectLocation();
File f = new File(projectLocation);
if (!f.isDirectory()) {
return;
}
Path path = new Path(f.getPath());
String osPath = path.append(AndroidConstants.FN_ANDROID_MANIFEST).toOSString();
AndroidManifestHelper manifest = new AndroidManifestHelper(osPath);
if (!manifest.exists()) {
return;
}
String packageName = null;
String activityName = null;
String minSdkVersion = null;
try {
packageName = manifest.getPackageName();
activityName = manifest.getActivityName(1);
minSdkVersion = manifest.getMinSdkVersion();
} catch (Exception e) {
// ignore exceptions
}
if (packageName != null && packageName.length() > 0) {
mPackageNameField.setText(packageName);
}
if (packageName != null && packageName.length() > 0) {
mPackageNameField.setText(packageName);
}
if (activityName != null && activityName.length() > 0) {
mInternalActivityNameUpdate = true;
mInternalCreateActivityUpdate = true;
mActivityNameField.setText(activityName);
mCreateActivityCheck.setSelection(true);
mInternalCreateActivityUpdate = false;
mInternalActivityNameUpdate = false;
if (activityName != null && activityName.length() > 0) {
mInternalActivityNameUpdate = true;
mInternalCreateActivityUpdate = true;
mActivityNameField.setText(activityName);
mCreateActivityCheck.setSelection(true);
mInternalCreateActivityUpdate = false;
mInternalActivityNameUpdate = false;
// If project name and application names are empty, use the activity
// name as a default. If the activity name has dots, it's a part of a
// package specification and only the last identifier must be used.
if (activityName.indexOf('.') != -1) {
String[] ids = activityName.split(AndroidConstants.RE_DOT);
activityName = ids[ids.length - 1];
}
if (mProjectNameField.getText().length() == 0 ||
!mProjectNameModifiedByUser) {
mInternalProjectNameUpdate = true;
mProjectNameField.setText(activityName);
mInternalProjectNameUpdate = false;
}
if (mApplicationNameField.getText().length() == 0 ||
!mApplicationNameModifiedByUser) {
mInternalApplicationNameUpdate = true;
mApplicationNameField.setText(activityName);
mInternalApplicationNameUpdate = false;
}
} else {
mInternalActivityNameUpdate = true;
mInternalCreateActivityUpdate = true;
mActivityNameField.setText("");
mCreateActivityCheck.setSelection(false);
mInternalCreateActivityUpdate = false;
mInternalActivityNameUpdate = false;
// There is no activity name to use to fill in the project and application
// name. However if there's a package name, we can use this as a base.
if (packageName != null && packageName.length() > 0) {
// Package name is a java identifier, so it's most suitable for
// an application name.
// If project name and application names are empty, use the activity
// name as a default. If the activity name has dots, it's a part of a
// package specification and only the last identifier must be used.
if (activityName.indexOf('.') != -1) {
String[] ids = activityName.split(AndroidConstants.RE_DOT);
activityName = ids[ids.length - 1];
}
if (mProjectNameField.getText().length() == 0 ||
!mProjectNameModifiedByUser) {
mInternalProjectNameUpdate = true;
mProjectNameField.setText(activityName);
mInternalProjectNameUpdate = false;
}
if (mApplicationNameField.getText().length() == 0 ||
!mApplicationNameModifiedByUser) {
mInternalApplicationNameUpdate = true;
mApplicationNameField.setText(activityName);
mInternalApplicationNameUpdate = false;
}
} else {
mInternalActivityNameUpdate = true;
mInternalCreateActivityUpdate = true;
mActivityNameField.setText(""); //$NON-NLS-1$
mCreateActivityCheck.setSelection(false);
mInternalCreateActivityUpdate = false;
mInternalActivityNameUpdate = false;
// There is no activity name to use to fill in the project and application
// name. However if there's a package name, we can use this as a base.
if (packageName != null && packageName.length() > 0) {
// Package name is a java identifier, so it's most suitable for
// an application name.
if (mApplicationNameField.getText().length() == 0 ||
!mApplicationNameModifiedByUser) {
mInternalApplicationNameUpdate = true;
mApplicationNameField.setText(packageName);
mInternalApplicationNameUpdate = false;
}
if (mApplicationNameField.getText().length() == 0 ||
!mApplicationNameModifiedByUser) {
mInternalApplicationNameUpdate = true;
mApplicationNameField.setText(packageName);
mInternalApplicationNameUpdate = false;
}
// For the project name, remove any dots
packageName = packageName.replace('.', '_');
if (mProjectNameField.getText().length() == 0 ||
!mProjectNameModifiedByUser) {
mInternalProjectNameUpdate = true;
mProjectNameField.setText(packageName);
mInternalProjectNameUpdate = false;
}
}
// For the project name, remove any dots
packageName = packageName.replace('.', '_');
if (mProjectNameField.getText().length() == 0 ||
!mProjectNameModifiedByUser) {
mInternalProjectNameUpdate = true;
mProjectNameField.setText(packageName);
mInternalProjectNameUpdate = false;
}
}
}
// Select the target matching the manifest's sdk, if any
boolean foundTarget = false;
if (minSdkVersion != null) {
try {
int sdkVersion = Integer.parseInt(minSdkVersion);
for (IAndroidTarget target : mSdkTargetSelector.getTargets()) {
if (target.getApiVersionNumber() == sdkVersion) {
mSdkTargetSelector.setSelection(target);
foundTarget = true;
break;
}
}
} catch(NumberFormatException e) {
// ignore
}
}
if (!foundTarget) {
for (IAndroidTarget target : mSdkTargetSelector.getTargets()) {
if (projectLocation.startsWith(target.getLocation())) {
mSdkTargetSelector.setSelection(target);
foundTarget = true;
break;
}
}
}
if (!foundTarget) {
mInternalMinSdkVersionUpdate = true;
mMinSdkVersionField.setText(minSdkVersion == null ? "" : minSdkVersion); //$NON-NLS-1$
mInternalMinSdkVersionUpdate = false;
}
}
/**
@@ -804,6 +929,9 @@ public class NewProjectCreationPage extends WizardPage {
if ((status & MSG_ERROR) == 0) {
status |= validateActivityField();
}
if ((status & MSG_ERROR) == 0) {
status |= validateMinSdkVersionField();
}
if ((status & MSG_ERROR) == 0) {
status |= validateSourceFolder();
}
@@ -949,6 +1077,38 @@ public class NewProjectCreationPage extends WizardPage {
return MSG_NONE;
}
/**
* Validates the sdk target choice.
*
* @return The wizard message type, one of MSG_ERROR, MSG_WARNING or MSG_NONE.
*/
private int validateMinSdkVersionField() {
// If the min sdk version is empty, it is always accepted.
if (getMinSdkVersion().length() == 0) {
return MSG_NONE;
}
int version = -1;
try {
// If not empty, it must be a valid integer > 0
version = Integer.parseInt(getMinSdkVersion());
} catch (NumberFormatException e) {
// ignore
}
if (version < 1) {
return setStatus("Min SDK Version must be an integer > 0.", MSG_ERROR);
}
if (getSdkTarget() != null && getSdkTarget().getApiVersionNumber() != version) {
return setStatus("The API level for the selected SDK target does not match the Min SDK version.",
MSG_WARNING);
}
return MSG_NONE;
}
/**
* Validates the activity name field.
*

View File

@@ -22,6 +22,7 @@ import com.android.ide.eclipse.adt.project.ProjectHelper;
import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
@@ -85,32 +86,36 @@ public class NewProjectWizard extends Wizard implements INewWizard {
private static final String PARAM_IS_NEW_PROJECT = "IS_NEW_PROJECT"; //$NON-NLS-1$
private static final String PARAM_SRC_FOLDER = "SRC_FOLDER"; //$NON-NLS-1$
private static final String PARAM_SDK_TARGET = "SDK_TARGET"; //$NON-NLS-1$
private static final String PARAM_MIN_SDK_VERSION = "MIN_SDK_VERSION"; //$NON-NLS-1$
private static final String PH_ACTIVITIES = "ACTIVITIES"; //$NON-NLS-1$
private static final String PH_USES_SDK = "USES-SDK"; //$NON-NLS-1$
private static final String PH_INTENT_FILTERS = "INTENT_FILTERS"; //$NON-NLS-1$
private static final String PH_STRINGS = "STRINGS"; //$NON-NLS-1$
private static final String BIN_DIRECTORY =
AndroidConstants.FD_BINARIES + AndroidConstants.WS_SEP;
SdkConstants.FD_OUTPUT + AndroidConstants.WS_SEP;
private static final String RES_DIRECTORY =
AndroidConstants.FD_RESOURCES + AndroidConstants.WS_SEP;
SdkConstants.FD_RESOURCES + AndroidConstants.WS_SEP;
private static final String ASSETS_DIRECTORY =
AndroidConstants.FD_ASSETS + AndroidConstants.WS_SEP;
SdkConstants.FD_ASSETS + AndroidConstants.WS_SEP;
private static final String DRAWABLE_DIRECTORY =
AndroidConstants.FD_DRAWABLE + AndroidConstants.WS_SEP;
SdkConstants.FD_DRAWABLE + AndroidConstants.WS_SEP;
private static final String LAYOUT_DIRECTORY =
AndroidConstants.FD_LAYOUT + AndroidConstants.WS_SEP;
SdkConstants.FD_LAYOUT + AndroidConstants.WS_SEP;
private static final String VALUES_DIRECTORY =
AndroidConstants.FD_VALUES + AndroidConstants.WS_SEP;
SdkConstants.FD_VALUES + AndroidConstants.WS_SEP;
private static final String TEMPLATES_DIRECTORY = "templates/"; //$NON-NLS-1$
private static final String TEMPLATE_MANIFEST = TEMPLATES_DIRECTORY
+ "AndroidManifest.template"; //$NON-NLS-1$
private static final String TEMPLATE_ACTIVITIES = TEMPLATES_DIRECTORY
+ "activity.template"; //$NON-NLS-1$
private static final String TEMPLATE_USES_SDK = TEMPLATES_DIRECTORY
+ "uses-sdk.template"; //$NON-NLS-1$
private static final String TEMPLATE_INTENT_LAUNCHER = TEMPLATES_DIRECTORY
+ "launcher_intent_filter.template"; //$NON-NLS-1$
private static final String TEMPLATE_STRINGS = TEMPLATES_DIRECTORY
+ "strings.template"; //$NON-NLS-1$
private static final String TEMPLATE_STRING = TEMPLATES_DIRECTORY
@@ -235,6 +240,7 @@ public class NewProjectWizard extends Wizard implements INewWizard {
parameters.put(PARAM_IS_NEW_PROJECT, mMainPage.isNewProject());
parameters.put(PARAM_SRC_FOLDER, mMainPage.getSourceFolder());
parameters.put(PARAM_SDK_TARGET, mMainPage.getSdkTarget());
parameters.put(PARAM_MIN_SDK_VERSION, mMainPage.getMinSdkVersion());
if (mMainPage.isCreateActivity()) {
// An activity name can be of the form ".package.Class" or ".Class".
@@ -449,6 +455,15 @@ public class NewProjectWizard extends Wizard implements INewWizard {
// remove the activity(ies) from the manifest
manifestTemplate = manifestTemplate.replaceAll(PH_ACTIVITIES, "");
}
String minSdkVersion = (String) parameters.get(PARAM_MIN_SDK_VERSION);
if (minSdkVersion != null && minSdkVersion.length() > 0) {
String usesSdkTemplate = AdtPlugin.readEmbeddedTextFile(TEMPLATE_USES_SDK);
String usesSdk = replaceParameters(usesSdkTemplate, parameters);
manifestTemplate = manifestTemplate.replaceAll(PH_USES_SDK, usesSdk);
} else {
manifestTemplate = manifestTemplate.replaceAll(PH_USES_SDK, "");
}
// Save in the project as UTF-8
InputStream stream = new ByteArrayInputStream(

View File

@@ -130,48 +130,14 @@ public class AndroidConstants {
public final static String FN_TRACEVIEW = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
"traceview.exe" : "traceview"; //$NON-NLS-1$ //$NON-NLS-2$
/** Folder Names for Android Projects . */
/* Resources folder name, i.e. "res". */
public final static String FD_RESOURCES = "res"; //$NON-NLS-1$
/** Assets folder name, i.e. "assets" */
public final static String FD_ASSETS = "assets"; //$NON-NLS-1$
/** Default source folder name, i.e. "src" */
public final static String FD_SOURCES = "src"; //$NON-NLS-1$
/** Default native library folder name inside the project, i.e. "libs"
* While the folder inside the .apk is "lib", we call that one libs because
* that's what we use in ant for both .jar and .so and we need to make the 2 development ways
* compatible. */
public final static String FD_NATIVE_LIBS = "libs"; //$NON-NLS-1$
/** Native lib folder inside the APK: "lib" */
public final static String FD_APK_NATIVE_LIBS = "lib"; //$NON-NLS-1$
/** Default bin folder name, i.e. "bin" */
public final static String FD_BINARIES = "bin"; //$NON-NLS-1$
/** Default anim resource folder name, i.e. "anim" */
public final static String FD_ANIM = "anim"; //$NON-NLS-1$
/** Default color resource folder name, i.e. "color" */
public final static String FD_COLOR = "color"; //$NON-NLS-1$
/** Default drawable resource folder name, i.e. "drawable" */
public final static String FD_DRAWABLE = "drawable"; //$NON-NLS-1$
/** Default layout resource folder name, i.e. "layout" */
public final static String FD_LAYOUT = "layout"; //$NON-NLS-1$
/** Default menu resource folder name, i.e. "menu" */
public final static String FD_MENU = "menu"; //$NON-NLS-1$
/** Default values resource folder name, i.e. "values" */
public final static String FD_VALUES = "values"; //$NON-NLS-1$
/** Default xml resource folder name, i.e. "xml" */
public final static String FD_XML = "xml"; //$NON-NLS-1$
/** Default raw resource folder name, i.e. "raw" */
public final static String FD_RAW = "raw"; //$NON-NLS-1$
/** Absolute path of the workspace root, i.e. "/" */
public final static String WS_ROOT = WS_SEP;
/** Absolute path of the resource folder, eg "/res".<br> This is a workspace path. */
public final static String WS_RESOURCES = WS_SEP + FD_RESOURCES;
public final static String WS_RESOURCES = WS_SEP + SdkConstants.FD_RESOURCES;
/** Absolute path of the resource folder, eg "/assets".<br> This is a workspace path. */
public final static String WS_ASSETS = WS_SEP + FD_ASSETS;
public final static String WS_ASSETS = WS_SEP + SdkConstants.FD_ASSETS;
/** Leaf of the javaDoc folder. Does not start with a separator. */
public final static String WS_JAVADOC_FOLDER_LEAF = SdkConstants.FD_DOCS + "/reference"; //$NON-NLS-1$

View File

@@ -97,7 +97,7 @@ public class AndroidManifestHelper {
*/
public String getPackageName() {
try {
return getPackageNameInternal(mXPath, getSource());
return mXPath.evaluate("/manifest/@package", getSource()); //$NON-NLS-1$
} catch (XPathExpressionException e1) {
// If the XPath failed to evaluate, we'll return null.
} catch (Exception e) {
@@ -110,18 +110,40 @@ public class AndroidManifestHelper {
return null;
}
/**
* Returns the minSdkVersion defined in the manifest file.
*
* @return A String object with the package or null if any error happened.
*/
public String getMinSdkVersion() {
try {
return mXPath.evaluate("/manifest/uses-sdk/@" //$NON-NLS-1$
+ AndroidXPathFactory.DEFAULT_NS_PREFIX
+ ":minSdkVersion", getSource()); //$NON-NLS-1$
} catch (XPathExpressionException e1) {
// If the XPath failed to evaluate, we'll return null.
} catch (Exception e) {
// if this happens this is due to the resource being out of sync.
// so we must refresh it and do it again
// for any other kind of exception we must return null as well;
}
return null;
}
/**
* Returns the i-th activity defined in the manifest file.
*
* @param manifest The manifest's IFile object.
* @param index The 1-based index of the activity to return.
* @param xpath An optional xpath object. If null is provided a new one will
* be created.
* @return A String object with the activity or null if any error happened.
*/
public String getActivityName(int index) {
try {
return getActivityNameInternal(index, mXPath, getSource());
return mXPath.evaluate("/manifest/application/activity[" //$NON-NLS-1$
+ index
+ "]/@" //$NON-NLS-1$
+ AndroidXPathFactory.DEFAULT_NS_PREFIX +":name", //$NON-NLS-1$
getSource());
} catch (XPathExpressionException e1) {
// If the XPath failed to evaluate, we'll return null.
} catch (Exception e) {
@@ -216,26 +238,4 @@ public class AndroidManifestHelper {
return null;
}
/**
* Performs the actual XPath evaluation to get the package name.
* Extracted so that we can share it with AndroidManifestFromProject.
*/
private static String getPackageNameInternal(XPath xpath, InputSource source)
throws XPathExpressionException {
return xpath.evaluate("/manifest/@package", source); //$NON-NLS-1$
}
/**
* Performs the actual XPath evaluation to get the activity name.
* Extracted so that we can share it with AndroidManifestFromProject.
*/
private static String getActivityNameInternal(int index, XPath xpath, InputSource source)
throws XPathExpressionException {
return xpath.evaluate("/manifest/application/activity[" //$NON-NLS-1$
+ index
+ "]/@" //$NON-NLS-1$
+ AndroidXPathFactory.DEFAULT_NS_PREFIX +":name", //$NON-NLS-1$
source);
}
}

View File

@@ -319,7 +319,7 @@ public class AndroidManifestParser {
* @see org.xml.sax.helpers.DefaultHandler#error(org.xml.sax.SAXParseException)
*/
@Override
public void error(SAXParseException e) throws SAXException {
public void error(SAXParseException e) {
if (mMarkErrors) {
handleError(e, e.getLineNumber());
}
@@ -329,7 +329,7 @@ public class AndroidManifestParser {
* @see org.xml.sax.helpers.DefaultHandler#fatalError(org.xml.sax.SAXParseException)
*/
@Override
public void fatalError(SAXParseException e) throws SAXException {
public void fatalError(SAXParseException e) {
if (mMarkErrors) {
handleError(e, e.getLineNumber());
}
@@ -348,7 +348,6 @@ public class AndroidManifestParser {
/**
* Processes the activity node.
* @param attributes the attributes for the activity node.
* @throws CoreException
*/
private void processActivityNode(Attributes attributes) {
// lets get the activity name, and add it to the list
@@ -381,7 +380,6 @@ public class AndroidManifestParser {
* @param attributes the attributes for the activity node.
* @param superClassName the fully qualified name of the super class that this
* node is representing
* @throws CoreException
*/
private void processNode(Attributes attributes, String superClassName) {
// lets get the class name, and check it if required.
@@ -567,12 +565,11 @@ public class AndroidManifestParser {
/**
* Parses the manifest file, collects data, and checks for errors.
* @param javaProject The java project. Required.
* @param manifestFile
* @param manifestFile The manifest file to parse.
* @param errorListener the {@link XmlErrorListener} object being notified of the presence
* of errors. Optional.
* @return an {@link AndroidManifestParser} or null if the parsing failed.
* @throws CoreException
* @see {@link #parse(IJavaProject, IFile, XmlErrorListener, boolean, boolean)}
*/
public static AndroidManifestParser parseForError(IJavaProject javaProject, IFile manifestFile,
XmlErrorListener errorListener) throws CoreException {
@@ -581,12 +578,9 @@ public class AndroidManifestParser {
/**
* Parses the manifest file, and collects data.
* @param manifestFile
* @param errorListener the {@link XmlErrorListener} object being notified of the presence
* of errors. Optional.
* @param manifestFile The manifest file to parse.
* @return an {@link AndroidManifestParser} or null if the parsing failed.
* @throws CoreException
* @see {@link #parse(IJavaProject, IFile, XmlErrorListener, boolean, boolean)}
*/
public static AndroidManifestParser parseForData(IFile manifestFile) throws CoreException {
return parse(null /* javaProject */, manifestFile, null /* errorListener */,

View File

@@ -39,7 +39,7 @@ public class AndroidXPathFactory {
/**
* Construct the context with the prefix associated with the android namespace.
* @param prefix the Prefix
* @param androidPrefix the Prefix
*/
public AndroidNamespaceContext(String androidPrefix) {
mAndroidPrefix = androidPrefix;
@@ -71,7 +71,7 @@ public class AndroidXPathFactory {
/**
* Creates a new XPath object, specifying which prefix in the query is used for the
* android namespace.
* @param prefix The namespace prefix.
* @param androidPrefix The namespace prefix.
*/
public static XPath newXPath(String androidPrefix) {
XPath xpath = sFactory.newXPath();

View File

@@ -82,11 +82,13 @@ public final class BaseProjectHelper {
}
/**
* Adds a marker to a file on a specific line
* Adds a marker to a file on a specific line. This methods catches thrown
* {@link CoreException}, and returns null instead.
* @param file the file to be marked
* @param markerId The id of the marker to add.
* @param message the message associated with the mark
* @param lineNumber the line number where to put the mark
* @param lineNumber the line number where to put the mark. If line is < 1, it puts the marker
* on line 1.
* @param severity the severity of the marker.
* @return the IMarker that was added or null if it failed to add one.
*/
@@ -96,7 +98,7 @@ public final class BaseProjectHelper {
IMarker marker = file.createMarker(markerId);
marker.setAttribute(IMarker.MESSAGE, message);
marker.setAttribute(IMarker.SEVERITY, severity);
if (lineNumber == -1) {
if (lineNumber < 1) {
lineNumber = 1;
}
marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
@@ -108,7 +110,7 @@ public final class BaseProjectHelper {
return marker;
} catch (CoreException e) {
AdtPlugin.log(e, "Failed to add marker '%1$s' to '%2$s'",
AdtPlugin.log(e, "Failed to add marker '%1$s' to '%2$s'", //$NON-NLS-1$
markerId, file.getFullPath());
}
@@ -116,7 +118,8 @@ public final class BaseProjectHelper {
}
/**
* Adds a marker to a resource.
* Adds a marker to a resource. This methods catches thrown {@link CoreException},
* and returns null instead.
* @param resource the file to be marked
* @param markerId The id of the marker to add.
* @param message the message associated with the mark
@@ -129,7 +132,7 @@ public final class BaseProjectHelper {
IMarker marker = resource.createMarker(markerId);
marker.setAttribute(IMarker.MESSAGE, message);
marker.setAttribute(IMarker.SEVERITY, severity);
// on Windows, when adding a marker to a project, it takes a refresh for the marker
// to show. In order to fix this we're forcing a refresh of elements receiving
// markers (and only the element, not its children), to force the marker display.
@@ -137,13 +140,43 @@ public final class BaseProjectHelper {
return marker;
} catch (CoreException e) {
AdtPlugin.log(e, "Failed to add marker '%1$s' to '%2$s'",
AdtPlugin.log(e, "Failed to add marker '%1$s' to '%2$s'", //$NON-NLS-1$
markerId, resource.getFullPath());
}
return null;
}
/**
* Adds a marker to a resource. This method does not catch {@link CoreException} and instead
* throw them.
* @param resource the file to be marked
* @param markerId The id of the marker to add.
* @param message the message associated with the mark
* @param lineNumber the line number where to put the mark if != -1.
* @param severity the severity of the marker.
* @param priority the priority of the marker
* @return the IMarker that was added.
* @throws CoreException
*/
public final static IMarker addMarker(IResource resource, String markerId,
String message, int lineNumber, int severity, int priority) throws CoreException {
IMarker marker = resource.createMarker(markerId);
marker.setAttribute(IMarker.MESSAGE, message);
marker.setAttribute(IMarker.SEVERITY, severity);
if (lineNumber != -1) {
marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
}
marker.setAttribute(IMarker.PRIORITY, priority);
// on Windows, when adding a marker to a project, it takes a refresh for the marker
// to show. In order to fix this we're forcing a refresh of elements receiving
// markers (and only the element, not its children), to force the marker display.
resource.refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor());
return marker;
}
/**
* Tests that a class name is valid for usage in the manifest.
* <p/>

View File

@@ -62,6 +62,7 @@ public class XmlErrorHandler extends DefaultHandler {
/**
* Xml Error call back
* @param exception the parsing exception
* @throws SAXException
*/
@Override
public void error(SAXParseException exception) throws SAXException {
@@ -71,6 +72,7 @@ public class XmlErrorHandler extends DefaultHandler {
/**
* Xml Fatal Error call back
* @param exception the parsing exception
* @throws SAXException
*/
@Override
public void fatalError(SAXParseException exception) throws SAXException {
@@ -80,6 +82,7 @@ public class XmlErrorHandler extends DefaultHandler {
/**
* Xml Warning call back
* @param exception the parsing exception
* @throws SAXException
*/
@Override
public void warning(SAXParseException exception) throws SAXException {

View File

@@ -20,6 +20,7 @@ import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo;
import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo.Format;
import com.android.ide.eclipse.common.resources.ViewClassInfo.LayoutParamsInfo;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import org.eclipse.core.runtime.IStatus;
import org.w3c.dom.Document;
@@ -228,7 +229,7 @@ public final class AttrsXmlParser {
}
mStyleMap.put(name, style);
if (lastComment != null) {
style.setJavaDoc(formatJavadoc(lastComment.getNodeValue()));
style.setJavaDoc(parseJavadoc(lastComment.getNodeValue()));
}
}
}
@@ -263,14 +264,15 @@ public final class AttrsXmlParser {
}
if (info != null) {
if (lastComment != null) {
info.setJavaDoc(formatJavadoc(lastComment.getNodeValue()));
info.setJavaDoc(parseJavadoc(lastComment.getNodeValue()));
info.setDeprecatedDoc(parseDeprecatedDoc(lastComment.getNodeValue()));
}
}
}
}
return info;
}
/**
* Finds all the attributes for a particular style node,
* e.g. a declare-styleable of name "TextView" or "LinearLayout_Layout".
@@ -431,16 +433,23 @@ public final class AttrsXmlParser {
}
/**
* Formats the javadoc.
* Parses the javadoc comment.
* Only keeps the first sentence.
* Removes and simplifies links and references.
* <p/>
* This does not remove nor simplify links and references. Such a transformation
* is done later at "display" time in {@link DescriptorsUtils#formatTooltip(String)} and co.
*/
private String formatJavadoc(String comment) {
private String parseJavadoc(String comment) {
if (comment == null) {
return null;
}
// sanitize & collapse whitespace
comment = comment.replaceAll("\\s+", " "); //$NON-NLS-1$ //$NON-NLS-2$
// Explicitly remove any @deprecated tags since they are handled separately.
comment = comment.replaceAll("(?:\\{@deprecated[^}]*\\}|@deprecated[^@}]*)", "");
// take everything up to the first dot that is followed by a space or the end of the line.
// I love regexps :-). For the curious, the regexp is:
// - start of line
@@ -456,6 +465,41 @@ public final class AttrsXmlParser {
// - followed by a space (?= non-capturing zero-width positive look-ahead)
// - anything else is ignored
comment = comment.replaceFirst("^\\s*(.*?(?:$|(?<![a-zA-Z]\\.[a-zA-Z])\\.(?=\\s))).*", "$1"); //$NON-NLS-1$ //$NON-NLS-2$
return comment;
}
/**
* Parses the javadoc and extract the first @deprecated tag, if any.
* Returns null if there's no @deprecated tag.
* The deprecated tag can be of two forms:
* - {+@deprecated ...text till the next bracket }
* Note: there should be no space or + between { and @. I need one in this comment otherwise
* this method will be tagged as deprecated ;-)
* - @deprecated ...text till the next @tag or end of the comment.
* In both cases the comment can be multi-line.
*/
private String parseDeprecatedDoc(String comment) {
// Skip if we can't even find the tag in the comment.
if (comment == null) {
return null;
}
// sanitize & collapse whitespace
comment = comment.replaceAll("\\s+", " "); //$NON-NLS-1$ //$NON-NLS-2$
int pos = comment.indexOf("{@deprecated");
if (pos >= 0) {
comment = comment.substring(pos + 12 /* len of {@deprecated */);
comment = comment.replaceFirst("^([^}]*).*", "$1");
} else if ((pos = comment.indexOf("@deprecated")) >= 0) {
comment = comment.substring(pos + 11 /* len of @deprecated */);
comment = comment.replaceFirst("^(.*?)(?:@.*|$)", "$1");
} else {
return null;
}
return comment.trim();
}
}

View File

@@ -55,8 +55,10 @@ public class DeclareStyleableInfo {
private String[] mEnumValues;
/** Values for flag. null for other types. */
private String[] mFlagValues;
/** Short javadoc */
/** Short javadoc (i.e. the first sentence). */
private String mJavaDoc;
/** Documentation for deprecated attributes. Null if not deprecated. */
private String mDeprecatedDoc;
/**
* @param name The XML Name of the attribute
@@ -74,6 +76,7 @@ public class DeclareStyleableInfo {
mEnumValues = info.mEnumValues;
mFlagValues = info.mFlagValues;
mJavaDoc = info.mJavaDoc;
mDeprecatedDoc = info.mDeprecatedDoc;
}
/** Returns the XML Name of the attribute */
@@ -93,10 +96,14 @@ public class DeclareStyleableInfo {
public String[] getFlagValues() {
return mFlagValues;
}
/** Returns a short javadoc */
/** Returns a short javadoc, .i.e. the first sentence. */
public String getJavaDoc() {
return mJavaDoc;
}
/** Returns the documentation for deprecated attributes. Null if not deprecated. */
public String getDeprecatedDoc() {
return mDeprecatedDoc;
}
/** Sets the values for enums. null for other types. */
public void setEnumValues(String[] values) {
@@ -106,10 +113,14 @@ public class DeclareStyleableInfo {
public void setFlagValues(String[] values) {
mFlagValues = values;
}
/** Sets a short javadoc */
/** Sets a short javadoc, .i.e. the first sentence. */
public void setJavaDoc(String javaDoc) {
mJavaDoc = javaDoc;
}
/** Sets the documentation for deprecated attributes. Null if not deprecated. */
public void setDeprecatedDoc(String deprecatedDoc) {
mDeprecatedDoc = deprecatedDoc;
}
}

View File

@@ -91,7 +91,12 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
/**
* Constructor for AndroidContentAssist
* @param rootElementDescriptors The valid root elements of the XML hierarchy
* @param descriptorId An id for {@link AndroidTargetData#getDescriptorProvider(int)}.
* The Id can be one of {@link AndroidTargetData#DESCRIPTOR_MANIFEST},
* {@link AndroidTargetData#DESCRIPTOR_LAYOUT},
* {@link AndroidTargetData#DESCRIPTOR_MENU},
* or {@link AndroidTargetData#DESCRIPTOR_XML}.
* All other values will throw an {@link IllegalArgumentException} later at runtime.
*/
public AndroidContentAssist(int descriptorId) {
mDescriptorId = descriptorId;
@@ -723,7 +728,6 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
/**
* Computes (if needed) and returns the root descriptor.
* @return
*/
private ElementDescriptor getRootDescriptor() {
if (mRootDescriptor == null) {

View File

@@ -722,7 +722,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
}
/**
* Returns the {@link PlatformData} for the edited file.
* Returns the {@link AndroidTargetData} for the edited file.
*/
public AndroidTargetData getTargetData() {
IProject project = getProject();

View File

@@ -38,6 +38,7 @@ public abstract class AttributeDescriptor {
private String mXmlLocalName;
private ElementDescriptor mParent;
private final String mNsUri;
private boolean mDeprecated;
/**
* Creates a new {@link AttributeDescriptor}
@@ -70,6 +71,14 @@ public abstract class AttributeDescriptor {
return mParent;
}
public void setDeprecated(boolean isDeprecated) {
mDeprecated = isDeprecated;
}
public boolean isDeprecated() {
return mDeprecated;
}
/**
* Returns an optional icon for the attribute.
* <p/>

View File

@@ -16,6 +16,7 @@
package com.android.ide.eclipse.editors.descriptors;
import com.android.ide.eclipse.editors.IconFactory;
import com.android.ide.eclipse.editors.uimodel.UiAbstractTextAttributeNode;
import org.eclipse.jface.viewers.ILabelProvider;
@@ -35,6 +36,17 @@ public class AttributeDescriptorLabelProvider implements ILabelProvider {
}
public Image getImage(Object element) {
if (element instanceof UiAbstractTextAttributeNode) {
UiAbstractTextAttributeNode node = (UiAbstractTextAttributeNode) element;
if (node.getDescriptor().isDeprecated()) {
String v = node.getCurrentValue();
if (v != null && v.length() > 0) {
IconFactory factory = IconFactory.getInstance();
return factory.getIcon("warning"); //$NON-NLS-1$
}
}
}
return null;
}

View File

@@ -92,8 +92,9 @@ public final class DescriptorsUtils {
* @param nsUri The URI of the attribute. Can be null if attribute has no namespace.
* See {@link AndroidConstants#NS_RESOURCES} for a common value.
* @param infos The array of {@link AttributeInfo} to read and append to attributes
* @param requiredAttributes An optional list of attributes to mark as "required" (i.e. append
* a "*" to their UI name as a hint for the user.)
* @param requiredAttributes An optional set of attributes to mark as "required" (i.e. append
* a "*" to their UI name as a hint for the user.) If not null, must contains
* entries in the form "elem-name/attr-name". Elem-name can be "*".
* @param overrides A map [attribute name => TextAttributeDescriptor creator]. A creator
* can either by a Class<? extends TextAttributeDescriptor> or an instance of
* {@link ITextAttributeCreator} that instantiates the right TextAttributeDescriptor.
@@ -101,16 +102,15 @@ public final class DescriptorsUtils {
public static void appendAttributes(ArrayList<AttributeDescriptor> attributes,
String elementXmlName,
String nsUri, AttributeInfo[] infos,
String[] requiredAttributes,
Set<String> requiredAttributes,
Map<String, Object> overrides) {
for (AttributeInfo info : infos) {
boolean required = false;
if (requiredAttributes != null) {
for(String attr_name : requiredAttributes) {
if (attr_name.equals(info.getName())) {
required = true;
break;
}
String attr_name = info.getName();
if (requiredAttributes.contains("*/" + attr_name) ||
requiredAttributes.contains(elementXmlName + "/" + attr_name)) {
required = true;
}
}
appendAttribute(attributes, elementXmlName, nsUri, info, required, overrides);
@@ -144,7 +144,26 @@ public final class DescriptorsUtils {
if (required) {
uiName += "*"; //$NON-NLS-1$
}
String tooltip = formatTooltip(info.getJavaDoc()); // tooltip
String tooltip = null;
String rawTooltip = info.getJavaDoc();
if (rawTooltip == null) {
rawTooltip = "";
}
String deprecated = info.getDeprecatedDoc();
if (deprecated != null) {
if (rawTooltip.length() > 0) {
rawTooltip += "@@"; //$NON-NLS-1$ insert a break
}
rawTooltip += "* Deprecated";
if (deprecated.length() != 0) {
rawTooltip += ": " + deprecated; //$NON-NLS-1$
}
if (deprecated.length() == 0 || !deprecated.endsWith(".")) { //$NON-NLS-1$
rawTooltip += "."; //$NON-NLS-1$
}
}
// Add the known types to the tooltip
Format[] formats_list = info.getFormats();
@@ -154,11 +173,14 @@ public final class DescriptorsUtils {
HashSet<Format> formats_set = new HashSet<Format>();
StringBuilder sb = new StringBuilder();
if (tooltip != null) {
sb.append(tooltip);
sb.append(" "); //$NON-NLS-1$
if (rawTooltip != null && rawTooltip.length() > 0) {
sb.append(rawTooltip);
sb.append(" "); //$NON-NLS-1$
}
sb.append("["); //$NON-NLS-1$
if (sb.length() > 0) {
sb.append("@@"); //$NON-NLS-1$ @@ inserts a break before the types
}
sb.append("["); //$NON-NLS-1$
for (int i = 0; i < flen; i++) {
Format f = formats_list[i];
formats_set.add(f);
@@ -172,19 +194,21 @@ public final class DescriptorsUtils {
sb.append("]"); //$NON-NLS-1$
if (required) {
sb.append(". Required.");
sb.append(".@@* "); //$NON-NLS-1$ @@ inserts a break.
sb.append("Required.");
}
// The extra space at the end makes the tooltip more readable on Windows.
sb.append(" "); //$NON-NLS-1$
tooltip = sb.toString();
rawTooltip = sb.toString();
tooltip = formatTooltip(rawTooltip);
// Create a specialized attribute if we can
if (overrides != null) {
for (Entry<String, Object> entry: overrides.entrySet()) {
String key = entry.getKey();
String elements[] = key.split("/");
String elements[] = key.split("/"); //$NON-NLS-1$
String overrideAttrLocalName = null;
if (elements.length < 1) {
continue;
@@ -193,7 +217,7 @@ public final class DescriptorsUtils {
elements = null;
} else {
overrideAttrLocalName = elements[elements.length - 1];
elements = elements[0].split(",");
elements = elements[0].split(","); //$NON-NLS-1$
}
if (overrideAttrLocalName == null ||
@@ -204,7 +228,8 @@ public final class DescriptorsUtils {
boolean ok_element = elements.length < 1;
if (!ok_element) {
for (String element : elements) {
if (element.equals("*") || element.equals(elementXmlName)) {
if (element.equals("*") //$NON-NLS-1$
|| element.equals(elementXmlName)) {
ok_element = true;
break;
}
@@ -271,8 +296,12 @@ public final class DescriptorsUtils {
// By default a simple text field is used
if (attr == null) {
if (tooltip == null) {
tooltip = formatTooltip(rawTooltip);
}
attr = new TextAttributeDescriptor(xmlLocalName, uiName, nsUri, tooltip);
}
attr.setDeprecated(info.getDeprecatedDoc() != null);
attributes.add(attr);
}
@@ -582,6 +611,8 @@ public final class DescriptorsUtils {
Pattern p_code = Pattern.compile("<code>(.+?)</code>(.*)"); //$NON-NLS-1$
// Detects @blah@, used in hard-coded tooltip descriptors
Pattern p_elem = Pattern.compile("@([\\w -]+)@(.*)"); //$NON-NLS-1$
// Detects a buffer that starts by @@ (request for a break)
Pattern p_break = Pattern.compile("@@(.*)"); //$NON-NLS-1$
// Detects a buffer that starts by @ < or { (one that was not matched above)
Pattern p_open = Pattern.compile("([@<\\{])(.*)"); //$NON-NLS-1$
// Detects everything till the next potential separator, i.e. @ < or {
@@ -616,6 +647,10 @@ public final class DescriptorsUtils {
if (text != null) {
currentLength += text.length() - 2;
}
} else if ((m = p_break.matcher(javadoc)).matches()) {
spans.add(BREAK);
currentLength = 0;
javadoc = m.group(1);
} else if ((m = p_open.matcher(javadoc)).matches()) {
s = m.group(1);
javadoc = m.group(2);

View File

@@ -95,6 +95,10 @@ public class TextAttributeDescriptor extends AttributeDescriptor implements IPro
}
public String getCategory() {
if (isDeprecated()) {
return "Deprecated";
}
ElementDescriptor parent = getParent();
if (parent != null) {
return parent.getUiName();

View File

@@ -20,7 +20,6 @@ import com.android.layoutlib.api.IXmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
@@ -178,7 +177,7 @@ public abstract class BasePullParser implements IXmlPullParser {
return mParsingState;
}
public int nextTag() throws XmlPullParserException, IOException {
public int nextTag() throws XmlPullParserException {
int eventType = next();
if (eventType != START_TAG && eventType != END_TAG) {
throw new XmlPullParserException("expected start or end tag", this, null);
@@ -186,7 +185,7 @@ public abstract class BasePullParser implements IXmlPullParser {
return eventType;
}
public String nextText() throws XmlPullParserException, IOException {
public String nextText() throws XmlPullParserException {
if (getEventType() != START_TAG) {
throw new XmlPullParserException("parser must be on START_TAG to read next text", this,
null);
@@ -208,7 +207,7 @@ public abstract class BasePullParser implements IXmlPullParser {
}
}
public int nextToken() throws XmlPullParserException, IOException {
public int nextToken() throws XmlPullParserException {
return next();
}

View File

@@ -33,8 +33,10 @@ import org.eclipse.core.runtime.IStatus;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.Map.Entry;
@@ -166,7 +168,13 @@ public final class AndroidManifestDescriptors implements IDescriptorProvider {
"android", //$NON-NLS-1$
AndroidConstants.NS_RESOURCES);
// -- setup the required attributes overrides --
Set<String> required = new HashSet<String>();
required.add("provider/authorities"); //$NON-NLS-1$
// -- setup the various attribute format overrides --
// The key for each override is "element1,element2,.../attr-xml-local-name" or
// "*/attr-xml-local-name" to match the attribute in any element.
@@ -181,7 +189,7 @@ public final class AndroidManifestDescriptors implements IDescriptorProvider {
tooltip);
}
});
overrides.put("*/theme", ThemeAttributeDescriptor.class); //$NON-NLS-1$
overrides.put("*/permission", ListAttributeDescriptor.class); //$NON-NLS-1$
overrides.put("*/targetPackage", PackageAttributeDescriptor.class); //$NON-NLS-1$
@@ -212,8 +220,12 @@ public final class AndroidManifestDescriptors implements IDescriptorProvider {
// --
inflateElement(manifestMap, overrides, elementDescs,
MANIFEST_ELEMENT, "AndroidManifest"); //$NON-NLS-1$
inflateElement(manifestMap,
overrides,
required,
elementDescs,
MANIFEST_ELEMENT,
"AndroidManifest"); //$NON-NLS-1$
insertAttribute(MANIFEST_ELEMENT, PACKAGE_ATTR_DESC);
sanityCheck(manifestMap, MANIFEST_ELEMENT);
@@ -312,16 +324,17 @@ public final class AndroidManifestDescriptors implements IDescriptorProvider {
* "Inflates" the properties of an {@link ElementDescriptor} from the styleable declaration.
* <p/>
* This first creates all the attributes for the given ElementDescriptor.
* It then find all children of the descriptor, inflate them recursively and set them
* It then finds all children of the descriptor, inflate them recursively and set them
* as child to this ElementDescriptor.
*
* @param styleMap The input styleable map for manifest elements & attributes
* @param styleMap The input styleable map for manifest elements & attributes.
* @param overrides A list of attribute overrides (to customize the type of the attribute
* descriptors)
* descriptors).
* @param requiredAttributes Set of attributes to be marked as required.
* @param existingElementDescs A map of already created element descriptors, keyed by
* XML local name. This is used to use the static elements created initially by this
* class, which are referenced directly by editors (so that reloading an SDK won't
* break these references)
* break these references).
* @param elemDesc The current {@link ElementDescriptor} to inflate.
* @param styleName The name of the {@link ElementDescriptor} to inflate. Its XML local name
* will be guessed automatically from the style name.
@@ -329,6 +342,7 @@ public final class AndroidManifestDescriptors implements IDescriptorProvider {
private void inflateElement(
Map<String, DeclareStyleableInfo> styleMap,
Map<String, Object> overrides,
Set<String> requiredAttributes,
HashMap<String, ElementDescriptor> existingElementDescs,
ElementDescriptor elemDesc,
String styleName) {
@@ -342,7 +356,9 @@ public final class AndroidManifestDescriptors implements IDescriptorProvider {
DescriptorsUtils.appendAttributes(attrDescs,
elemDesc.getXmlLocalName(),
AndroidConstants.NS_RESOURCES,
style.getAttributes(), null, overrides);
style.getAttributes(),
requiredAttributes,
overrides);
elemDesc.setTooltip(style.getJavaDoc());
elemDesc.setAttributes(attrDescs.toArray(new AttributeDescriptor[attrDescs.size()]));
}
@@ -373,7 +389,12 @@ public final class AndroidManifestDescriptors implements IDescriptorProvider {
}
children.add(child);
inflateElement(styleMap, overrides, existingElementDescs, child, childStyleName);
inflateElement(styleMap,
overrides,
requiredAttributes,
existingElementDescs,
child,
childStyleName);
}
}
elemDesc.setChildren(children.toArray(new ElementDescriptor[children.size()]));

View File

@@ -66,7 +66,7 @@ public final class CountryCodeQualifier extends ResourceQualifier {
/**
* Returns the folder name segment for the given value. This is equivalent to calling
* {@link #toString()} on a {@link CountryCodeQualifier} object.
* @param value the value of the qualifier, as returned by {@link #getCode()}.
* @param code the value of the qualifier, as returned by {@link #getCode()}.
*/
public static String getFolderSegment(int code) {
if (code != DEFAULT_CODE && code >= 100 && code <=999) { // code is 3 digit.) {

View File

@@ -66,7 +66,7 @@ public final class NetworkCodeQualifier extends ResourceQualifier {
/**
* Returns the folder name segment for the given value. This is equivalent to calling
* {@link #toString()} on a {@link NetworkCodeQualifier} object.
* @param value the value of the qualifier, as returned by {@link #getCode()}.
* @param code the value of the qualifier, as returned by {@link #getCode()}.
*/
public static String getFolderSegment(int code) {
if (code != DEFAULT_CODE && code >= 1 && code <= 999) { // code is 1-3 digit.

View File

@@ -39,7 +39,7 @@ public final class PixelDensityQualifier extends ResourceQualifier {
/**
* Creates and returns a qualifier from the given folder segment. If the segment is incorrect,
* <code>null</code> is returned.
* @param segment the folder segment from which to create a qualifier.
* @param folderSegment the folder segment from which to create a qualifier.
* @return a new {@link CountryCodeQualifier} object or <code>null</code>
*/
public static PixelDensityQualifier getQualifier(String folderSegment) {
@@ -66,7 +66,7 @@ public final class PixelDensityQualifier extends ResourceQualifier {
/**
* Returns the folder name segment for the given value. This is equivalent to calling
* {@link #toString()} on a {@link NetworkCodeQualifier} object.
* @param value the value of the qualifier, as returned by {@link #getCode()}.
* @param value the value of the qualifier, as returned by {@link #getValue()}.
*/
public static String getFolderSegment(int value) {
if (value != DEFAULT_DENSITY) {

View File

@@ -132,7 +132,7 @@ public final class MultiResourceFile extends ResourceFile implements IValueResou
/**
* Adds a resource item to the list
* @param resType The type of the resource
* @param name The name of the resource.
* @param value The value of the resource.
*/
public void addResourceValue(String resType, ResourceValue value) {
ResourceType type = ResourceType.getEnum(resType);

View File

@@ -107,7 +107,6 @@ public final class ProjectClassLoader extends ClassLoader {
* @param parent the root of the file.
* @param segments the segments containing the path of the file
* @param index the offset at which to start looking into segments.
* @return
* @throws FileNotFoundException
*/
private File getFile(File parent, String[] segments, int index)
@@ -168,8 +167,6 @@ public final class ProjectClassLoader extends ClassLoader {
/**
* Loads a class from the 3rd party jar present in the project
* @param name
* @return
* @throws ClassNotFoundException
*/
private Class<?> loadClassFromJar(String name) throws ClassNotFoundException {

View File

@@ -393,8 +393,6 @@ public class ProjectResources implements IResourceRepository {
/**
* Resolves a compiled resource id of type int[] into the resource name.
* @param id
* @return
*/
public String resolveResourceValue(int[] id) {
if (mStyleableValueToNameMap != null) {
@@ -407,9 +405,6 @@ public class ProjectResources implements IResourceRepository {
/**
* Returns the value of a resource by its type and name.
* @param type
* @param name
* @return
*/
public Integer getResourceValue(String type, String name) {
if (mResourceValueMap != null) {
@@ -444,8 +439,7 @@ public class ProjectResources implements IResourceRepository {
/**
* Returns the list of regions used in the resources with the given language.
* @param currentLanguage the current language the region must be associated with
* @return
* @param currentLanguage the current language the region must be associated with.
*/
public Set<String> getRegions(String currentLanguage) {
Set<String> set = new HashSet<String>();

View File

@@ -185,7 +185,7 @@ public final class ResourceFolder extends Resource {
/**
* Returns the {@link ResourceFile} matching a given name.
* @param file The name of the file to return.
* @param filename The name of the file to return.
* @return the {@link ResourceFile} or <code>null</code> if no match was found.
*/
public ResourceFile getFile(String filename) {

View File

@@ -16,21 +16,21 @@
package com.android.ide.eclipse.editors.resources.manager;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration;
import com.android.sdklib.SdkConstants;
/**
* Enum representing a type of resource folder.
*/
public enum ResourceFolderType {
ANIM(AndroidConstants.FD_ANIM),
COLOR(AndroidConstants.FD_COLOR),
DRAWABLE(AndroidConstants.FD_DRAWABLE),
LAYOUT(AndroidConstants.FD_LAYOUT),
MENU(AndroidConstants.FD_MENU),
RAW(AndroidConstants.FD_RAW),
VALUES(AndroidConstants.FD_VALUES),
XML(AndroidConstants.FD_XML);
ANIM(SdkConstants.FD_ANIM),
COLOR(SdkConstants.FD_COLOR),
DRAWABLE(SdkConstants.FD_DRAWABLE),
LAYOUT(SdkConstants.FD_LAYOUT),
MENU(SdkConstants.FD_MENU),
RAW(SdkConstants.FD_RAW),
VALUES(SdkConstants.FD_VALUES),
XML(SdkConstants.FD_XML);
private final String mName;

View File

@@ -30,6 +30,7 @@ import com.android.ide.eclipse.editors.resources.manager.files.IAbstractFolder;
import com.android.ide.eclipse.editors.resources.manager.files.IFileWrapper;
import com.android.ide.eclipse.editors.resources.manager.files.IFolderWrapper;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
@@ -269,8 +270,7 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
/**
* Loads and returns the resources for a given {@link IAndroidTarget}
* @param osFilePath the path to the folder containing all the versions of the framework
* resources
* @param androidTarget the target from which to load the framework resources
*/
public ProjectResources loadFrameworkResources(IAndroidTarget androidTarget) {
String osResourcesPath = androidTarget.getPath(IAndroidTarget.RESOURCES);
@@ -329,7 +329,7 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
return;
}
IFolder resourceFolder = project.getFolder(AndroidConstants.FD_RESOURCES);
IFolder resourceFolder = project.getFolder(SdkConstants.FD_RESOURCES);
ProjectResources projectResources = mMap.get(project);
if (projectResources == null) {
@@ -478,7 +478,7 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
* @return true if the path is under /project res/
*/
private boolean isInResFolder(IPath path) {
return AndroidConstants.FD_RESOURCES.equalsIgnoreCase(path.segment(1));
return SdkConstants.FD_RESOURCES.equalsIgnoreCase(path.segment(1));
}
/**

View File

@@ -115,8 +115,6 @@ public class SingleResourceFile extends ResourceFile {
/**
* Returns the name of the resources.
* @param type
* @return
*/
private String getResourceName(ResourceType type) {
// get the name from the filename.

View File

@@ -17,7 +17,6 @@
package com.android.ide.eclipse.editors.resources.manager.files;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import java.io.File;
import java.io.FileInputStream;
@@ -45,7 +44,7 @@ public class FileWrapper implements IAbstractFile {
mFile = file;
}
public InputStream getContents() throws CoreException {
public InputStream getContents() {
try {
return new FileInputStream(mFile);
} catch (FileNotFoundException e) {
@@ -74,7 +73,7 @@ public class FileWrapper implements IAbstractFile {
}
if (obj instanceof File) {
return mFile.equals((File)obj);
return mFile.equals(obj);
}
return super.equals(obj);

View File

@@ -59,7 +59,7 @@ public class FolderWrapper implements IAbstractFolder {
}
if (obj instanceof File) {
return mFolder.equals((File)obj);
return mFolder.equals(obj);
}
return super.equals(obj);

View File

@@ -55,7 +55,7 @@ public class IFileWrapper implements IAbstractFile {
}
if (obj instanceof IFile) {
return mFile.equals((IFile)obj);
return mFile.equals(obj);
}
return super.equals(obj);

View File

@@ -61,7 +61,7 @@ public class IFolderWrapper implements IAbstractFolder {
}
if (obj instanceof IFolder) {
return mFolder.equals((IFolder)obj);
return mFolder.equals(obj);
}
return super.equals(obj);

View File

@@ -17,7 +17,6 @@
package com.android.ide.eclipse.editors.ui.tree;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;

View File

@@ -79,8 +79,7 @@ import java.util.HashMap;
* To use this, instantiate somewhere in the UI and then:
* <ul>
* <li>Use {@link #setConfiguration(String)} or {@link #setConfiguration(FolderConfiguration)}.
* <li>Retrieve the configuration using {@link #getConfiguration(FolderConfiguration)} and
* test it using {@link FolderConfiguration#isValid()}.
* <li>Retrieve the configuration using {@link #getConfiguration(FolderConfiguration)}.
* </ul>
*/
public class ConfigurationSelector extends Composite {

View File

@@ -30,6 +30,7 @@ import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptor
import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType;
import com.android.ide.eclipse.editors.wizards.ConfigurationSelector.ConfigurationState;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
@@ -243,7 +244,7 @@ class NewXmlFileCreationPage extends WizardPage {
/** Absolute destination folder root, e.g. "/res/" */
private static String sResFolderAbs = AndroidConstants.WS_RESOURCES + AndroidConstants.WS_SEP;
/** Relative destination folder root, e.g. "res/" */
private static String sResFolderRel = AndroidConstants.FD_RESOURCES + AndroidConstants.WS_SEP;
private static String sResFolderRel = SdkConstants.FD_RESOURCES + AndroidConstants.WS_SEP;
private IProject mProject;
private Text mProjectTextField;
@@ -629,7 +630,7 @@ class NewXmlFileCreationPage extends WizardPage {
// Disregard this folder selection if it doesn't point to /res/something
if (wsFolderPath != null &&
wsFolderPath.segmentCount() > 1 &&
AndroidConstants.FD_RESOURCES.equals(wsFolderPath.segment(0))) {
SdkConstants.FD_RESOURCES.equals(wsFolderPath.segment(0))) {
score += 2;
} else {
wsFolderPath = null;
@@ -1002,7 +1003,7 @@ class NewXmlFileCreationPage extends WizardPage {
String fileName = getFileName();
if (fileName == null || fileName.length() == 0) {
error = "A destination file name is required.";
} else if (fileName != null && !fileName.endsWith(AndroidConstants.DOT_XML)) {
} else if (!fileName.endsWith(AndroidConstants.DOT_XML)) {
error = String.format("The filename must end with %1$s.", AndroidConstants.DOT_XML);
}
}

View File

@@ -17,7 +17,6 @@
package com.android.ide.eclipse.editors.wizards;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.resources.IResourceRepository;
import com.android.ide.eclipse.common.resources.ResourceItem;
import com.android.ide.eclipse.common.resources.ResourceType;

View File

@@ -6,4 +6,5 @@
<application android:icon="@drawable/icon" android:label="APPLICATION_NAME">
ACTIVITIES
</application>
USES-SDK
</manifest>

View File

@@ -0,0 +1 @@
<uses-sdk android:minSdkVersion="MIN_SDK_VERSION" />