ADT #1823896: AVD Manager button in the AVD Selector.
Device chooser: avd manager callback + avd list refresh. Device chooser: dialog title. Device launcher tab: avd manager callaback + avd list refresh.
This commit is contained in:
@@ -136,7 +136,7 @@ public final class DelayedLaunchInfo {
|
||||
|
||||
/**
|
||||
* Returns the Android app process name that the debugger should connect to. Typically this is
|
||||
* the same value as {@link getPackageName}
|
||||
* the same value as {@link #getPackageName()}.
|
||||
*/
|
||||
public String getDebugPackageName() {
|
||||
if (mDebugPackageName == null) {
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.android.ddmuilib.ImageHelper;
|
||||
import com.android.ddmuilib.TableHelper;
|
||||
import com.android.ide.eclipse.adt.AdtPlugin;
|
||||
import com.android.ide.eclipse.adt.sdk.Sdk;
|
||||
import com.android.ide.eclipse.adt.wizards.actions.AvdManagerAction;
|
||||
import com.android.ide.eclipse.ddms.DdmsPlugin;
|
||||
import com.android.sdklib.IAndroidTarget;
|
||||
import com.android.sdklib.avd.AvdManager;
|
||||
@@ -53,6 +54,7 @@ import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Control;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.swt.widgets.Table;
|
||||
|
||||
@@ -89,7 +91,7 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
|
||||
private final IAndroidTarget mProjectTarget;
|
||||
private final Sdk mSdk;
|
||||
|
||||
private final AvdInfo[] mFullAvdList;
|
||||
private AvdInfo[] mFullAvdList;
|
||||
|
||||
private Button mDeviceRadioButton;
|
||||
|
||||
@@ -262,14 +264,6 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
|
||||
mProjectTarget = projectTarget;
|
||||
mSdk = Sdk.getCurrent();
|
||||
|
||||
// get the full list of Android Virtual Devices
|
||||
AvdManager avdManager = mSdk.getAvdManager();
|
||||
if (avdManager != null) {
|
||||
mFullAvdList = avdManager.getValidAvds();
|
||||
} else {
|
||||
mFullAvdList = null;
|
||||
}
|
||||
|
||||
loadImages();
|
||||
}
|
||||
|
||||
@@ -310,9 +304,16 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
|
||||
|
||||
@Override
|
||||
protected Control createDialogArea(Composite parent) {
|
||||
// set dialog title
|
||||
getShell().setText("Android Device Chooser");
|
||||
|
||||
Composite top = new Composite(parent, SWT.NONE);
|
||||
top.setLayout(new GridLayout(1, true));
|
||||
|
||||
Label label = new Label(top, SWT.NONE);
|
||||
label.setText(String.format("Select a device compatible with target %s.",
|
||||
mProjectTarget.getFullName()));
|
||||
|
||||
mDeviceRadioButton = new Button(top, SWT.RADIO);
|
||||
mDeviceRadioButton.setText("Choose a running Android device");
|
||||
mDeviceRadioButton.addSelectionListener(new SelectionAdapter() {
|
||||
@@ -344,7 +345,7 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
|
||||
offsetComp.setLayout(layout);
|
||||
|
||||
IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore();
|
||||
mDeviceTable = new Table(offsetComp, SWT.SINGLE | SWT.FULL_SELECTION);
|
||||
mDeviceTable = new Table(offsetComp, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER);
|
||||
GridData gd;
|
||||
mDeviceTable.setLayoutData(gd = new GridData(GridData.FILL_BOTH));
|
||||
gd.heightHint = 100;
|
||||
@@ -413,7 +414,16 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
|
||||
layout.marginLeft = 30;
|
||||
offsetComp.setLayout(layout);
|
||||
|
||||
mPreferredAvdSelector = new AvdSelector(offsetComp, getNonRunningAvds(), mProjectTarget);
|
||||
mPreferredAvdSelector = new AvdSelector(offsetComp,
|
||||
getNonRunningAvds(false /*reloadAvds*/),
|
||||
mProjectTarget,
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
AvdManagerAction action = new AvdManagerAction();
|
||||
action.run(null);
|
||||
refillAvdList(true /*reloadAvds*/);
|
||||
}
|
||||
});
|
||||
mPreferredAvdSelector.setTableHeightHint(100);
|
||||
mPreferredAvdSelector.setEnabled(false);
|
||||
mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() {
|
||||
@@ -446,7 +456,6 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
|
||||
}
|
||||
});
|
||||
|
||||
AndroidDebugBridge.addDeviceChangeListener(this);
|
||||
|
||||
return top;
|
||||
}
|
||||
@@ -529,7 +538,7 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
|
||||
|
||||
// update the display of AvdInfo (since it's filtered to only display
|
||||
// non running AVD.)
|
||||
refillAvdList();
|
||||
refillAvdList(false /*reloadAvds*/);
|
||||
} else {
|
||||
// table is disposed, we need to do something.
|
||||
// lets remove ourselves from the listener.
|
||||
@@ -576,7 +585,7 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
|
||||
// update the display of AvdInfo (since it's filtered to only display
|
||||
// non running AVD). This is done on deviceChanged because the avd name
|
||||
// of a (emulator) device may be updated as the emulator boots.
|
||||
refillAvdList();
|
||||
refillAvdList(false /*reloadAvds*/);
|
||||
|
||||
// if the changed device is the current selection,
|
||||
// we update the OK button based on its state.
|
||||
@@ -692,19 +701,28 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
|
||||
/**
|
||||
* Returns the list of {@link AvdInfo} that are not already running in an emulator.
|
||||
*/
|
||||
private AvdInfo[] getNonRunningAvds() {
|
||||
private AvdInfo[] getNonRunningAvds(boolean reloadAvds) {
|
||||
ArrayList<AvdInfo> list = new ArrayList<AvdInfo>();
|
||||
|
||||
Device[] devices = AndroidDebugBridge.getBridge().getDevices();
|
||||
|
||||
// loop through all the Avd and put the one that are not running in the list.
|
||||
avdLoop: for (AvdInfo info : mFullAvdList) {
|
||||
for (Device d : devices) {
|
||||
if (info.getName().equals(d.getAvdName())) {
|
||||
continue avdLoop;
|
||||
}
|
||||
// get the full list of Android Virtual Devices
|
||||
if (reloadAvds || mFullAvdList == null) {
|
||||
AvdManager avdManager = mSdk.getAvdManager();
|
||||
if (avdManager != null) {
|
||||
mFullAvdList = avdManager.getValidAvds();
|
||||
}
|
||||
}
|
||||
|
||||
// loop through all the Avd and put the one that are not running in the list.
|
||||
if (mFullAvdList != null) {
|
||||
Device[] devices = AndroidDebugBridge.getBridge().getDevices();
|
||||
avdLoop: for (AvdInfo info : mFullAvdList) {
|
||||
for (Device d : devices) {
|
||||
if (info.getName().equals(d.getAvdName())) {
|
||||
continue avdLoop;
|
||||
}
|
||||
}
|
||||
list.add(info);
|
||||
}
|
||||
list.add(info);
|
||||
}
|
||||
|
||||
return list.toArray(new AvdInfo[list.size()]);
|
||||
@@ -713,8 +731,8 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
|
||||
/**
|
||||
* Refills the AVD list keeping the current selection.
|
||||
*/
|
||||
private void refillAvdList() {
|
||||
AvdInfo[] array = getNonRunningAvds();
|
||||
private void refillAvdList(boolean reloadAvds) {
|
||||
AvdInfo[] array = getNonRunningAvds(reloadAvds);
|
||||
|
||||
// save the current selection
|
||||
AvdInfo selected = mPreferredAvdSelector.getFirstSelected();
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.ide.eclipse.adt.launch;
|
||||
import com.android.ide.eclipse.adt.AdtPlugin;
|
||||
import com.android.ide.eclipse.adt.launch.AndroidLaunchConfiguration.TargetMode;
|
||||
import com.android.ide.eclipse.adt.sdk.Sdk;
|
||||
import com.android.ide.eclipse.adt.wizards.actions.AvdManagerAction;
|
||||
import com.android.ide.eclipse.common.project.BaseProjectHelper;
|
||||
import com.android.ide.eclipse.ddms.DdmsPlugin;
|
||||
import com.android.prefs.AndroidLocation.AndroidLocationException;
|
||||
@@ -92,6 +93,8 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
|
||||
|
||||
private Label mPreferredAvdLabel;
|
||||
|
||||
private IAndroidTarget mProjectTarget;
|
||||
|
||||
/**
|
||||
* Returns the emulator ready speed option value.
|
||||
* @param value The index of the combo selection.
|
||||
@@ -187,8 +190,15 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
|
||||
|
||||
mPreferredAvdLabel = new Label(offsetComp, SWT.NONE);
|
||||
mPreferredAvdLabel.setText("Select a preferred Android Virtual Device for deployment:");
|
||||
AvdInfo[] avds = new AvdInfo[0];
|
||||
mPreferredAvdSelector = new AvdSelector(offsetComp, avds);
|
||||
mPreferredAvdSelector = new AvdSelector(offsetComp,
|
||||
null /*avds*/,
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
AvdManagerAction action = new AvdManagerAction();
|
||||
action.run(null);
|
||||
updateAvdList(null);
|
||||
}
|
||||
});
|
||||
mPreferredAvdSelector.setTableHeightHint(100);
|
||||
mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
@@ -296,6 +306,21 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
|
||||
return DdmsPlugin.getImageLoader().loadImage("emulator.png", null); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
|
||||
private void updateAvdList(AvdManager avdManager) {
|
||||
if (avdManager == null) {
|
||||
avdManager = Sdk.getCurrent().getAvdManager();
|
||||
}
|
||||
|
||||
AvdInfo[] avds = null;
|
||||
// no project? we don't want to display any "compatible" AVDs.
|
||||
if (avdManager != null && mProjectTarget != null) {
|
||||
avds = avdManager.getValidAvds();
|
||||
}
|
||||
|
||||
mPreferredAvdSelector.setAvds(avds, mProjectTarget);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
|
||||
*/
|
||||
@@ -336,19 +361,11 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
|
||||
}
|
||||
|
||||
// update the AVD list
|
||||
AvdInfo[] avds = null;
|
||||
if (avdManager != null) {
|
||||
avds = avdManager.getValidAvds();
|
||||
if (project != null) {
|
||||
mProjectTarget = Sdk.getCurrent().getTarget(project);
|
||||
}
|
||||
|
||||
IAndroidTarget projectTarget = null;
|
||||
if (project != null) {
|
||||
projectTarget = Sdk.getCurrent().getTarget(project);
|
||||
} else {
|
||||
avds = null; // no project? we don't want to display any "compatible" AVDs.
|
||||
}
|
||||
|
||||
mPreferredAvdSelector.setAvds(avds, projectTarget);
|
||||
updateAvdList(avdManager);
|
||||
|
||||
stringValue = "";
|
||||
try {
|
||||
|
||||
@@ -445,6 +445,14 @@ class AvdManagerListPage extends WizardPage {
|
||||
|
||||
AvdManager avdm = getAvdManager();
|
||||
|
||||
// For the AVD manager to reload the list, in case AVDs where created using the
|
||||
// command line tool.
|
||||
try {
|
||||
avdm.reloadAvds();
|
||||
} catch (AndroidLocationException e) {
|
||||
AdtPlugin.log(e, "AVD Manager reload failed"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
AvdInfo[] avds = avdm == null ? null : avdm.getValidAvds();
|
||||
mAvdSelector.setAvds(avds, null /*filter*/);
|
||||
|
||||
|
||||
@@ -22,12 +22,14 @@ import com.android.sdklib.avd.AvdManager.AvdInfo;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.ControlAdapter;
|
||||
import org.eclipse.swt.events.ControlEvent;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.events.SelectionListener;
|
||||
import org.eclipse.swt.graphics.Point;
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Event;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
@@ -51,6 +53,8 @@ public final class AvdSelector {
|
||||
private Table mTable;
|
||||
private Label mDescription;
|
||||
|
||||
private static int NUM_COL = 2;
|
||||
|
||||
/**
|
||||
* Creates a new SDK Target Selector, and fills it with a list of {@link AvdInfo}, filtered
|
||||
* by a {@link IAndroidTarget}.
|
||||
@@ -59,30 +63,44 @@ public final class AvdSelector {
|
||||
*
|
||||
* @param parent The parent composite where the selector will be added.
|
||||
* @param avds The list of AVDs. This is <em>not</em> copied, the caller must not modify.
|
||||
* It can be null.
|
||||
* @param filter When non-null, will display only the AVDs matching this target.
|
||||
* @param avdManagerAction A runnable to associate with an "AVD Manager" button. This button
|
||||
* is hidden if null is passed. The caller's action is responsible for reloading
|
||||
* the AVD list using {@link #setAvds(AvdInfo[], IAndroidTarget)}.
|
||||
*/
|
||||
public AvdSelector(Composite parent, AvdInfo[] avds, IAndroidTarget filter) {
|
||||
public AvdSelector(Composite parent,
|
||||
AvdInfo[] avds,
|
||||
IAndroidTarget filter,
|
||||
final Runnable avdManagerAction) {
|
||||
mAvds = avds;
|
||||
|
||||
// Layout has 1 column
|
||||
// Layout has 2 columns
|
||||
Composite group = new Composite(parent, SWT.NONE);
|
||||
group.setLayout(new GridLayout());
|
||||
group.setLayout(new GridLayout(NUM_COL, false /*makeColumnsEqualWidth*/));
|
||||
group.setLayoutData(new GridData(GridData.FILL_BOTH));
|
||||
group.setFont(parent.getFont());
|
||||
|
||||
mTable = new Table(group, SWT.CHECK | SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER);
|
||||
mTable.setHeaderVisible(true);
|
||||
mTable.setLinesVisible(false);
|
||||
|
||||
GridData data = new GridData();
|
||||
data.grabExcessVerticalSpace = true;
|
||||
data.grabExcessHorizontalSpace = true;
|
||||
data.horizontalAlignment = GridData.FILL;
|
||||
data.verticalAlignment = GridData.FILL;
|
||||
mTable.setLayoutData(data);
|
||||
setTableHeightHint(0);
|
||||
|
||||
mDescription = new Label(group, SWT.WRAP);
|
||||
mDescription.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||
|
||||
if (avdManagerAction != null) {
|
||||
Button avdManagerButton = new Button(group, SWT.PUSH);
|
||||
avdManagerButton.setText("AVD Manager...");
|
||||
avdManagerButton.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
super.widgetSelected(e);
|
||||
avdManagerAction.run();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// create the table columns
|
||||
final TableColumn column0 = new TableColumn(mTable, SWT.NONE);
|
||||
column0.setText("AVD Name");
|
||||
@@ -98,23 +116,45 @@ public final class AvdSelector {
|
||||
fillTable(mTable, filter);
|
||||
setupTooltip(mTable);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new SDK Target Selector, and fills it with a list of {@link AvdInfo}.
|
||||
*
|
||||
* @param parent The parent composite where the selector will be added.
|
||||
* @param avds The list of AVDs. This is <em>not</em> copied, the caller must not modify.
|
||||
* It can be null.
|
||||
*/
|
||||
public AvdSelector(Composite parent, AvdInfo[] avds) {
|
||||
this(parent, avds, null /* filter */);
|
||||
this(parent, avds, null /* filter */, null /* avdManagerAction */);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new SDK Target Selector, and fills it with a list of {@link AvdInfo}.
|
||||
*
|
||||
* @param parent The parent composite where the selector will be added.
|
||||
* @param avds The list of AVDs. This is <em>not</em> copied, the caller must not modify.
|
||||
* It can be null.
|
||||
* @param avdManagerAction A runnable to associate with an "AVD Manager" button. This button
|
||||
* is hidden if null is passed. The caller's action is responsible for reloading
|
||||
* the AVD list using {@link #setAvds(AvdInfo[], IAndroidTarget)}.
|
||||
*/
|
||||
public AvdSelector(Composite parent, AvdInfo[] avds, Runnable avdManagerAction) {
|
||||
this(parent, avds, null /* filter */, avdManagerAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the table grid layout data.
|
||||
*
|
||||
* @param heightHint If > 0, tthe height hint is set to the requested value.
|
||||
*/
|
||||
public void setTableHeightHint(int heightHint) {
|
||||
GridData data = new GridData();
|
||||
data.heightHint = heightHint;
|
||||
if (heightHint > 0) {
|
||||
data.heightHint = heightHint;
|
||||
}
|
||||
data.grabExcessVerticalSpace = true;
|
||||
data.grabExcessHorizontalSpace = true;
|
||||
data.horizontalSpan = NUM_COL;
|
||||
data.horizontalAlignment = GridData.FILL;
|
||||
data.verticalAlignment = GridData.FILL;
|
||||
mTable.setLayoutData(data);
|
||||
@@ -125,6 +165,7 @@ public final class AvdSelector {
|
||||
* <p/>This must be called from the UI thread.
|
||||
*
|
||||
* @param avds The list of AVDs. This is <em>not</em> copied, the caller must not modify.
|
||||
* It can be null.
|
||||
* @param filter An IAndroidTarget. If non-null, only AVD whose target are compatible with the
|
||||
* filter target will displayed an available for selection.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user