Device chooser: avd manager callback + avd list refresh.
Device chooser: dialog title.
Device launcher tab: avd manager callaback + avd list refresh.
/**
* 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) {
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;
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;
private final IAndroidTarget mProjectTarget;
private final Sdk mSdk;
- private final AvdInfo[] mFullAvdList;
+ private AvdInfo[] mFullAvdList;
private Button mDeviceRadioButton;
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();
}
@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() {
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;
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() {
}
});
- AndroidDebugBridge.addDeviceChangeListener(this);
return top;
}
// 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.
// 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.
/**
* 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();
-
+ // 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.
- avdLoop: for (AvdInfo info : mFullAvdList) {
- for (Device d : devices) {
- if (info.getName().equals(d.getAvdName())) {
- continue avdLoop;
+ 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()]);
/**
* 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();
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;
private Label mPreferredAvdLabel;
+ private IAndroidTarget mProjectTarget;
+
/**
* Returns the emulator ready speed option value.
* @param value The index of the combo selection.
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
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)
*/
}
// update the AVD list
- AvdInfo[] avds = null;
- if (avdManager != null) {
- avds = avdManager.getValidAvds();
- }
-
- 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.
+ mProjectTarget = Sdk.getCurrent().getTarget(project);
}
-
- mPreferredAvdSelector.setAvds(avds, projectTarget);
+
+ updateAvdList(avdManager);
stringValue = "";
try {
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*/);
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;
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}.
*
* @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");
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);
* <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.
*/