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:
Raphael
2009-04-30 16:10:47 -07:00
parent 5941176ccd
commit e940a1cad7
5 changed files with 138 additions and 54 deletions

View File

@@ -136,7 +136,7 @@ public final class DelayedLaunchInfo {
/** /**
* Returns the Android app process name that the debugger should connect to. Typically this is * 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() { public String getDebugPackageName() {
if (mDebugPackageName == null) { if (mDebugPackageName == null) {

View File

@@ -27,6 +27,7 @@ import com.android.ddmuilib.ImageHelper;
import com.android.ddmuilib.TableHelper; import com.android.ddmuilib.TableHelper;
import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.sdk.Sdk; 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.ide.eclipse.ddms.DdmsPlugin;
import com.android.sdklib.IAndroidTarget; import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.avd.AvdManager; 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.Composite;
import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.Table;
@@ -89,7 +91,7 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
private final IAndroidTarget mProjectTarget; private final IAndroidTarget mProjectTarget;
private final Sdk mSdk; private final Sdk mSdk;
private final AvdInfo[] mFullAvdList; private AvdInfo[] mFullAvdList;
private Button mDeviceRadioButton; private Button mDeviceRadioButton;
@@ -262,14 +264,6 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
mProjectTarget = projectTarget; mProjectTarget = projectTarget;
mSdk = Sdk.getCurrent(); 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(); loadImages();
} }
@@ -310,9 +304,16 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
@Override @Override
protected Control createDialogArea(Composite parent) { protected Control createDialogArea(Composite parent) {
// set dialog title
getShell().setText("Android Device Chooser");
Composite top = new Composite(parent, SWT.NONE); Composite top = new Composite(parent, SWT.NONE);
top.setLayout(new GridLayout(1, true)); 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 = new Button(top, SWT.RADIO);
mDeviceRadioButton.setText("Choose a running Android device"); mDeviceRadioButton.setText("Choose a running Android device");
mDeviceRadioButton.addSelectionListener(new SelectionAdapter() { mDeviceRadioButton.addSelectionListener(new SelectionAdapter() {
@@ -344,7 +345,7 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
offsetComp.setLayout(layout); offsetComp.setLayout(layout);
IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore(); 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; GridData gd;
mDeviceTable.setLayoutData(gd = new GridData(GridData.FILL_BOTH)); mDeviceTable.setLayoutData(gd = new GridData(GridData.FILL_BOTH));
gd.heightHint = 100; gd.heightHint = 100;
@@ -413,7 +414,16 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
layout.marginLeft = 30; layout.marginLeft = 30;
offsetComp.setLayout(layout); 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.setTableHeightHint(100);
mPreferredAvdSelector.setEnabled(false); mPreferredAvdSelector.setEnabled(false);
mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() { mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() {
@@ -446,7 +456,6 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
} }
}); });
AndroidDebugBridge.addDeviceChangeListener(this);
return top; 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 // update the display of AvdInfo (since it's filtered to only display
// non running AVD.) // non running AVD.)
refillAvdList(); refillAvdList(false /*reloadAvds*/);
} else { } else {
// table is disposed, we need to do something. // table is disposed, we need to do something.
// lets remove ourselves from the listener. // 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 // update the display of AvdInfo (since it's filtered to only display
// non running AVD). This is done on deviceChanged because the avd name // non running AVD). This is done on deviceChanged because the avd name
// of a (emulator) device may be updated as the emulator boots. // of a (emulator) device may be updated as the emulator boots.
refillAvdList(); refillAvdList(false /*reloadAvds*/);
// if the changed device is the current selection, // if the changed device is the current selection,
// we update the OK button based on its state. // 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. * 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>(); ArrayList<AvdInfo> list = new ArrayList<AvdInfo>();
Device[] devices = AndroidDebugBridge.getBridge().getDevices(); // get the full list of Android Virtual Devices
if (reloadAvds || mFullAvdList == null) {
// loop through all the Avd and put the one that are not running in the list. AvdManager avdManager = mSdk.getAvdManager();
avdLoop: for (AvdInfo info : mFullAvdList) { if (avdManager != null) {
for (Device d : devices) { mFullAvdList = avdManager.getValidAvds();
if (info.getName().equals(d.getAvdName())) { }
continue avdLoop; }
}
// 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()]); 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. * Refills the AVD list keeping the current selection.
*/ */
private void refillAvdList() { private void refillAvdList(boolean reloadAvds) {
AvdInfo[] array = getNonRunningAvds(); AvdInfo[] array = getNonRunningAvds(reloadAvds);
// save the current selection // save the current selection
AvdInfo selected = mPreferredAvdSelector.getFirstSelected(); AvdInfo selected = mPreferredAvdSelector.getFirstSelected();

View File

@@ -19,6 +19,7 @@ package com.android.ide.eclipse.adt.launch;
import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.launch.AndroidLaunchConfiguration.TargetMode; import com.android.ide.eclipse.adt.launch.AndroidLaunchConfiguration.TargetMode;
import com.android.ide.eclipse.adt.sdk.Sdk; 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.common.project.BaseProjectHelper;
import com.android.ide.eclipse.ddms.DdmsPlugin; import com.android.ide.eclipse.ddms.DdmsPlugin;
import com.android.prefs.AndroidLocation.AndroidLocationException; import com.android.prefs.AndroidLocation.AndroidLocationException;
@@ -92,6 +93,8 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
private Label mPreferredAvdLabel; private Label mPreferredAvdLabel;
private IAndroidTarget mProjectTarget;
/** /**
* Returns the emulator ready speed option value. * Returns the emulator ready speed option value.
* @param value The index of the combo selection. * @param value The index of the combo selection.
@@ -187,8 +190,15 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
mPreferredAvdLabel = new Label(offsetComp, SWT.NONE); mPreferredAvdLabel = new Label(offsetComp, SWT.NONE);
mPreferredAvdLabel.setText("Select a preferred Android Virtual Device for deployment:"); mPreferredAvdLabel.setText("Select a preferred Android Virtual Device for deployment:");
AvdInfo[] avds = new AvdInfo[0]; mPreferredAvdSelector = new AvdSelector(offsetComp,
mPreferredAvdSelector = new AvdSelector(offsetComp, avds); null /*avds*/,
new Runnable() {
public void run() {
AvdManagerAction action = new AvdManagerAction();
action.run(null);
updateAvdList(null);
}
});
mPreferredAvdSelector.setTableHeightHint(100); mPreferredAvdSelector.setTableHeightHint(100);
mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() { mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() {
@Override @Override
@@ -296,6 +306,21 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
return DdmsPlugin.getImageLoader().loadImage("emulator.png", null); //$NON-NLS-1$ 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) /* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration) * @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 // update the AVD list
AvdInfo[] avds = null; if (project != null) {
if (avdManager != null) { mProjectTarget = Sdk.getCurrent().getTarget(project);
avds = avdManager.getValidAvds();
} }
IAndroidTarget projectTarget = null; updateAvdList(avdManager);
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);
stringValue = ""; stringValue = "";
try { try {

View File

@@ -445,6 +445,14 @@ class AvdManagerListPage extends WizardPage {
AvdManager avdm = getAvdManager(); 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(); AvdInfo[] avds = avdm == null ? null : avdm.getValidAvds();
mAvdSelector.setAvds(avds, null /*filter*/); mAvdSelector.setAvds(avds, null /*filter*/);

View File

@@ -22,12 +22,14 @@ import com.android.sdklib.avd.AvdManager.AvdInfo;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Label;
@@ -51,6 +53,8 @@ public final class AvdSelector {
private Table mTable; private Table mTable;
private Label mDescription; 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 * Creates a new SDK Target Selector, and fills it with a list of {@link AvdInfo}, filtered
* by a {@link IAndroidTarget}. * by a {@link IAndroidTarget}.
@@ -59,30 +63,44 @@ public final class AvdSelector {
* *
* @param parent The parent composite where the selector will be added. * @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. * @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; mAvds = avds;
// Layout has 1 column // Layout has 2 columns
Composite group = new Composite(parent, SWT.NONE); 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.setLayoutData(new GridData(GridData.FILL_BOTH));
group.setFont(parent.getFont()); group.setFont(parent.getFont());
mTable = new Table(group, SWT.CHECK | SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER); mTable = new Table(group, SWT.CHECK | SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER);
mTable.setHeaderVisible(true); mTable.setHeaderVisible(true);
mTable.setLinesVisible(false); mTable.setLinesVisible(false);
setTableHeightHint(0);
GridData data = new GridData();
data.grabExcessVerticalSpace = true;
data.grabExcessHorizontalSpace = true;
data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.FILL;
mTable.setLayoutData(data);
mDescription = new Label(group, SWT.WRAP); mDescription = new Label(group, SWT.WRAP);
mDescription.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 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 // create the table columns
final TableColumn column0 = new TableColumn(mTable, SWT.NONE); final TableColumn column0 = new TableColumn(mTable, SWT.NONE);
column0.setText("AVD Name"); column0.setText("AVD Name");
@@ -98,23 +116,45 @@ public final class AvdSelector {
fillTable(mTable, filter); fillTable(mTable, filter);
setupTooltip(mTable); setupTooltip(mTable);
} }
/** /**
* Creates a new SDK Target Selector, and fills it with a list of {@link AvdInfo}. * 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 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. * @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) { 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) { public void setTableHeightHint(int heightHint) {
GridData data = new GridData(); GridData data = new GridData();
data.heightHint = heightHint; if (heightHint > 0) {
data.heightHint = heightHint;
}
data.grabExcessVerticalSpace = true; data.grabExcessVerticalSpace = true;
data.grabExcessHorizontalSpace = true; data.grabExcessHorizontalSpace = true;
data.horizontalSpan = NUM_COL;
data.horizontalAlignment = GridData.FILL; data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.FILL; data.verticalAlignment = GridData.FILL;
mTable.setLayoutData(data); mTable.setLayoutData(data);
@@ -125,6 +165,7 @@ public final class AvdSelector {
* <p/>This must be called from the UI thread. * <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. * @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 * @param filter An IAndroidTarget. If non-null, only AVD whose target are compatible with the
* filter target will displayed an available for selection. * filter target will displayed an available for selection.
*/ */