Merge change 4425 into donut
* changes: First step of a more standalone AvdSelector.
This commit is contained in:
@@ -26,13 +26,12 @@ 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.internal.sdk.Sdk;
|
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
|
||||||
import com.android.ide.eclipse.adt.internal.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.internal.avd.AvdManager;
|
|
||||||
import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
|
import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
|
||||||
import com.android.sdkuilib.internal.widgets.AvdSelector;
|
import com.android.sdkuilib.internal.widgets.AvdSelector;
|
||||||
import com.android.sdkuilib.internal.widgets.AvdSelector.SelectionMode;
|
import com.android.sdkuilib.internal.widgets.AvdSelector.DisplayMode;
|
||||||
|
import com.android.sdkuilib.internal.widgets.AvdSelector.IAvdFilter;
|
||||||
|
|
||||||
import org.eclipse.jface.dialogs.Dialog;
|
import org.eclipse.jface.dialogs.Dialog;
|
||||||
import org.eclipse.jface.dialogs.IDialogConstants;
|
import org.eclipse.jface.dialogs.IDialogConstants;
|
||||||
@@ -58,8 +57,6 @@ 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;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A dialog that lets the user choose a device to deploy an application.
|
* A dialog that lets the user choose a device to deploy an application.
|
||||||
* The user can either choose an exiting running device (including running emulators)
|
* The user can either choose an exiting running device (including running emulators)
|
||||||
@@ -91,8 +88,6 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
|
|||||||
private final IAndroidTarget mProjectTarget;
|
private final IAndroidTarget mProjectTarget;
|
||||||
private final Sdk mSdk;
|
private final Sdk mSdk;
|
||||||
|
|
||||||
private AvdInfo[] mFullAvdList;
|
|
||||||
|
|
||||||
private Button mDeviceRadioButton;
|
private Button mDeviceRadioButton;
|
||||||
|
|
||||||
private boolean mDisableAvdSelectionChange = false;
|
private boolean mDisableAvdSelectionChange = false;
|
||||||
@@ -264,6 +259,7 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
|
|||||||
mProjectTarget = projectTarget;
|
mProjectTarget = projectTarget;
|
||||||
mSdk = Sdk.getCurrent();
|
mSdk = Sdk.getCurrent();
|
||||||
|
|
||||||
|
AndroidDebugBridge.addDeviceChangeListener(this);
|
||||||
loadImages();
|
loadImages();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,24 +411,9 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
|
|||||||
offsetComp.setLayout(layout);
|
offsetComp.setLayout(layout);
|
||||||
|
|
||||||
mPreferredAvdSelector = new AvdSelector(offsetComp,
|
mPreferredAvdSelector = new AvdSelector(offsetComp,
|
||||||
getNonRunningAvds(false /*reloadAvds*/),
|
mSdk.getAvdManager(),
|
||||||
mProjectTarget,
|
new NonRunningAvdFilter(),
|
||||||
new AvdSelector.IExtraAction() {
|
DisplayMode.SIMPLE_SELECTION);
|
||||||
public void run() {
|
|
||||||
AvdManagerAction action = new AvdManagerAction();
|
|
||||||
action.run(null);
|
|
||||||
refillAvdList(true /*reloadAvds*/);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String label() {
|
|
||||||
return "AVD Manager...";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
SelectionMode.CHECK);
|
|
||||||
mPreferredAvdSelector.setTableHeightHint(100);
|
mPreferredAvdSelector.setTableHeightHint(100);
|
||||||
mPreferredAvdSelector.setEnabled(false);
|
mPreferredAvdSelector.setEnabled(false);
|
||||||
mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() {
|
mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() {
|
||||||
@@ -594,6 +575,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(false /*reloadAvds*/);
|
refillAvdList(false /*reloadAvds*/);
|
||||||
|
|
||||||
// if the changed device is the current selection,
|
// if the changed device is the current selection,
|
||||||
@@ -707,50 +689,44 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
|
|||||||
handleDeviceSelection();
|
handleDeviceSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private final class NonRunningAvdFilter implements IAvdFilter {
|
||||||
* Returns the list of {@link AvdInfo} that are not already running in an emulator.
|
|
||||||
*/
|
|
||||||
private AvdInfo[] getNonRunningAvds(boolean reloadAvds) {
|
|
||||||
ArrayList<AvdInfo> list = new ArrayList<AvdInfo>();
|
|
||||||
|
|
||||||
// get the full list of Android Virtual Devices
|
private IDevice[] mDevices;
|
||||||
if (reloadAvds || mFullAvdList == null) {
|
|
||||||
AvdManager avdManager = mSdk.getAvdManager();
|
public void prepare() {
|
||||||
if (avdManager != null) {
|
mDevices = AndroidDebugBridge.getBridge().getDevices();
|
||||||
mFullAvdList = avdManager.getValidAvds();
|
}
|
||||||
|
|
||||||
|
public boolean accept(AvdInfo avd) {
|
||||||
|
if (mDevices != null) {
|
||||||
|
for (IDevice d : mDevices) {
|
||||||
|
if (mProjectTarget.isCompatibleBaseFor(avd.getTarget()) == false ||
|
||||||
|
avd.getName().equals(d.getAvdName())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop through all the Avd and put the one that are not running in the list.
|
return true;
|
||||||
if (mFullAvdList != null) {
|
|
||||||
IDevice[] devices = AndroidDebugBridge.getBridge().getDevices();
|
|
||||||
avdLoop: for (AvdInfo info : mFullAvdList) {
|
|
||||||
for (IDevice d : devices) {
|
|
||||||
if (info.getName().equals(d.getAvdName())) {
|
|
||||||
continue avdLoop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list.add(info);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return list.toArray(new AvdInfo[list.size()]);
|
public void cleanup() {
|
||||||
|
mDevices = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refills the AVD list keeping the current selection.
|
* Refills the AVD list keeping the current selection.
|
||||||
*/
|
*/
|
||||||
private void refillAvdList(boolean reloadAvds) {
|
private void refillAvdList(boolean reloadAvds) {
|
||||||
AvdInfo[] array = getNonRunningAvds(reloadAvds);
|
|
||||||
|
|
||||||
// save the current selection
|
// save the current selection
|
||||||
AvdInfo selected = mPreferredAvdSelector.getSelected();
|
AvdInfo selected = mPreferredAvdSelector.getSelected();
|
||||||
|
|
||||||
// disable selection change.
|
// disable selection change.
|
||||||
mDisableAvdSelectionChange = true;
|
mDisableAvdSelectionChange = true;
|
||||||
|
|
||||||
// set the new list in the selector
|
// refresh the list
|
||||||
mPreferredAvdSelector.setAvds(array, mProjectTarget);
|
mPreferredAvdSelector.refresh(false);
|
||||||
|
|
||||||
// attempt to reselect the proper avd if needed
|
// attempt to reselect the proper avd if needed
|
||||||
if (selected != null) {
|
if (selected != null) {
|
||||||
|
|||||||
@@ -20,14 +20,13 @@ import com.android.ide.eclipse.adt.AdtPlugin;
|
|||||||
import com.android.ide.eclipse.adt.internal.launch.AndroidLaunchConfiguration.TargetMode;
|
import com.android.ide.eclipse.adt.internal.launch.AndroidLaunchConfiguration.TargetMode;
|
||||||
import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
|
import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
|
||||||
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
|
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
|
||||||
import com.android.ide.eclipse.adt.internal.wizards.actions.AvdManagerAction;
|
|
||||||
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;
|
||||||
import com.android.sdklib.IAndroidTarget;
|
import com.android.sdklib.IAndroidTarget;
|
||||||
import com.android.sdklib.internal.avd.AvdManager;
|
import com.android.sdklib.internal.avd.AvdManager;
|
||||||
import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
|
import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
|
||||||
import com.android.sdkuilib.internal.widgets.AvdSelector;
|
import com.android.sdkuilib.internal.widgets.AvdSelector;
|
||||||
import com.android.sdkuilib.internal.widgets.AvdSelector.SelectionMode;
|
import com.android.sdkuilib.internal.widgets.AvdSelector.DisplayMode;
|
||||||
|
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
@@ -191,24 +190,12 @@ 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:");
|
||||||
mPreferredAvdSelector = new AvdSelector(offsetComp,
|
|
||||||
null /*avds*/,
|
|
||||||
new AvdSelector.IExtraAction() {
|
|
||||||
public void run() {
|
|
||||||
AvdManagerAction action = new AvdManagerAction();
|
|
||||||
action.run(null);
|
|
||||||
updateAvdList(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEnabled() {
|
// create the selector with no manager, we'll reset the manager every time this is
|
||||||
return true;
|
// displayed to ensure we have the latest one (dialog is reused but SDK could have
|
||||||
}
|
// been changed in between.
|
||||||
|
mPreferredAvdSelector = new AvdSelector(offsetComp, null /* avd manager */,
|
||||||
public String label() {
|
DisplayMode.SIMPLE_CHECK);
|
||||||
return "AVD Manager...";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
SelectionMode.CHECK);
|
|
||||||
mPreferredAvdSelector.setTableHeightHint(100);
|
mPreferredAvdSelector.setTableHeightHint(100);
|
||||||
mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() {
|
mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() {
|
||||||
@Override
|
@Override
|
||||||
@@ -322,13 +309,9 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
|
|||||||
avdManager = Sdk.getCurrent().getAvdManager();
|
avdManager = Sdk.getCurrent().getAvdManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
AvdInfo[] avds = null;
|
mPreferredAvdSelector.setManager(avdManager);
|
||||||
// no project? we don't want to display any "compatible" AVDs.
|
mPreferredAvdSelector.setFilter(mProjectTarget);
|
||||||
if (avdManager != null && mProjectTarget != null) {
|
mPreferredAvdSelector.refresh(false);
|
||||||
avds = avdManager.getValidAvds();
|
|
||||||
}
|
|
||||||
|
|
||||||
mPreferredAvdSelector.setAvds(avds, mProjectTarget);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import com.android.sdklib.ISdkLog;
|
|||||||
import com.android.sdklib.internal.avd.AvdManager;
|
import com.android.sdklib.internal.avd.AvdManager;
|
||||||
import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
|
import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
|
||||||
import com.android.sdkuilib.internal.widgets.AvdSelector;
|
import com.android.sdkuilib.internal.widgets.AvdSelector;
|
||||||
import com.android.sdkuilib.internal.widgets.AvdSelector.SelectionMode;
|
import com.android.sdkuilib.internal.widgets.AvdSelector.DisplayMode;
|
||||||
|
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.jface.wizard.WizardPage;
|
import org.eclipse.jface.wizard.WizardPage;
|
||||||
@@ -162,21 +162,7 @@ class AvdManagerListPage extends WizardPage {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mAvdSelector = new AvdSelector(parent,
|
mAvdSelector = new AvdSelector(parent, getAvdManager(), DisplayMode.MANAGER);
|
||||||
SelectionMode.SELECT,
|
|
||||||
new AvdSelector.IExtraAction() {
|
|
||||||
public String label() {
|
|
||||||
return "Delete AVD...";
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return mAvdSelector != null && mAvdSelector.getSelected() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
onDelete();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -430,29 +416,12 @@ class AvdManagerListPage extends WizardPage {
|
|||||||
* Tries to preserve the selection.
|
* Tries to preserve the selection.
|
||||||
*/
|
*/
|
||||||
private void reloadAvdList() {
|
private void reloadAvdList() {
|
||||||
AvdInfo selected = mAvdSelector.getSelected();
|
mAvdSelector.refresh(true /* reload */);
|
||||||
|
|
||||||
AvdManager avdm = getAvdManager();
|
|
||||||
AvdInfo[] avds = null;
|
|
||||||
|
|
||||||
// For the AVD manager to reload the list, in case AVDs where created using the
|
|
||||||
// command line tool.
|
|
||||||
// The AVD manager may not exist yet, typically when loading the SDK.
|
|
||||||
if (avdm != null) {
|
|
||||||
try {
|
|
||||||
avdm.reloadAvds();
|
|
||||||
} catch (AndroidLocationException e) {
|
|
||||||
AdtPlugin.log(e, "AVD Manager reload failed"); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
|
|
||||||
avds = avdm.getValidAvds();
|
|
||||||
}
|
|
||||||
|
|
||||||
mAvdSelector.setAvds(avds, null /*filter*/);
|
|
||||||
|
|
||||||
// Keep the list of known AVD names to check if they exist quickly. however
|
// Keep the list of known AVD names to check if they exist quickly. however
|
||||||
// use the list of all AVDs, including broken ones (unless we don't know their
|
// use the list of all AVDs, including broken ones (unless we don't know their
|
||||||
// name).
|
// name).
|
||||||
|
AvdManager avdm = getAvdManager();
|
||||||
mKnownAvdNames.clear();
|
mKnownAvdNames.clear();
|
||||||
if (avdm != null) {
|
if (avdm != null) {
|
||||||
for (AvdInfo avd : avdm.getAllAvds()) {
|
for (AvdInfo avd : avdm.getAllAvds()) {
|
||||||
@@ -462,14 +431,15 @@ class AvdManagerListPage extends WizardPage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mAvdSelector.setSelection(selected);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggered when the user selects the "delete" button (the extra action in the selector)
|
* Triggered when the user selects the "delete" button (the extra action in the selector)
|
||||||
* Deletes the currently selected AVD, if any.
|
* Deletes the currently selected AVD, if any.
|
||||||
|
*
|
||||||
|
* This is obsolete. Kept around to reuse the code later in the AvdSelector itself.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
private void onDelete() {
|
private void onDelete() {
|
||||||
AvdInfo avdInfo = mAvdSelector.getSelected();
|
AvdInfo avdInfo = mAvdSelector.getSelected();
|
||||||
AvdManager avdm = getAvdManager();
|
AvdManager avdm = getAvdManager();
|
||||||
|
|||||||
@@ -16,29 +16,19 @@
|
|||||||
|
|
||||||
package com.android.sdkuilib.internal.repository;
|
package com.android.sdkuilib.internal.repository;
|
||||||
|
|
||||||
import com.android.sdklib.internal.avd.AvdManager;
|
|
||||||
import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
|
|
||||||
import com.android.sdkuilib.internal.repository.UpdaterData.ISdkListener;
|
import com.android.sdkuilib.internal.repository.UpdaterData.ISdkListener;
|
||||||
import com.android.sdkuilib.internal.widgets.AvdSelector;
|
import com.android.sdkuilib.internal.widgets.AvdSelector;
|
||||||
import com.android.sdkuilib.internal.widgets.AvdSelector.SelectionMode;
|
import com.android.sdkuilib.internal.widgets.AvdSelector.DisplayMode;
|
||||||
|
|
||||||
import org.eclipse.swt.SWT;
|
import org.eclipse.swt.SWT;
|
||||||
import org.eclipse.swt.events.SelectionAdapter;
|
|
||||||
import org.eclipse.swt.events.SelectionEvent;
|
|
||||||
import org.eclipse.swt.layout.GridData;
|
|
||||||
import org.eclipse.swt.layout.GridLayout;
|
import org.eclipse.swt.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.Label;
|
import org.eclipse.swt.widgets.Label;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
public class AvdManagerPage extends Composite implements ISdkListener {
|
public class AvdManagerPage extends Composite implements ISdkListener {
|
||||||
|
|
||||||
private Button mRefreshButton;
|
|
||||||
private AvdSelector mAvdSelector;
|
private AvdSelector mAvdSelector;
|
||||||
|
|
||||||
private final HashSet<String> mKnownAvdNames = new HashSet<String>();
|
|
||||||
private final UpdaterData mUpdaterData;
|
private final UpdaterData mUpdaterData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,43 +47,12 @@ public class AvdManagerPage extends Composite implements ISdkListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void createContents(Composite parent) {
|
private void createContents(Composite parent) {
|
||||||
parent.setLayout(new GridLayout(3, false));
|
parent.setLayout(new GridLayout(1, false));
|
||||||
|
|
||||||
Label label = new Label(parent, SWT.NONE);
|
Label label = new Label(parent, SWT.NONE);
|
||||||
label.setText("List of existing Android Virtual Devices:");
|
label.setText("List of existing Android Virtual Devices:");
|
||||||
label.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, true, false, 2, 1));
|
|
||||||
|
|
||||||
mRefreshButton = new Button(parent, SWT.PUSH);
|
mAvdSelector = new AvdSelector(parent, mUpdaterData.getAvdManager(), DisplayMode.MANAGER);
|
||||||
mRefreshButton.setText("Refresh");
|
|
||||||
mRefreshButton.setLayoutData(new GridData(SWT.END, SWT.CENTER, false, false));
|
|
||||||
mRefreshButton.addSelectionListener(new SelectionAdapter() {
|
|
||||||
@Override
|
|
||||||
public void widgetSelected(SelectionEvent e) {
|
|
||||||
onRefreshSelected(); //$hide$
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Composite group = new Composite(parent, SWT.NONE);
|
|
||||||
group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
|
|
||||||
GridLayout gl;
|
|
||||||
group.setLayout(gl = new GridLayout(1, false /*makeColumnsEqualWidth*/));
|
|
||||||
gl.marginHeight = gl.marginWidth = 0;
|
|
||||||
|
|
||||||
mAvdSelector = new AvdSelector(group,
|
|
||||||
SelectionMode.SELECT,
|
|
||||||
new AvdSelector.IExtraAction() {
|
|
||||||
public String label() {
|
|
||||||
return "Delete AVD...";
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return mAvdSelector != null && mAvdSelector.getSelected() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
//TODO onDelete();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -115,48 +74,11 @@ public class AvdManagerPage extends Composite implements ISdkListener {
|
|||||||
* Called by the constructor right after {@link #createContents(Composite)}.
|
* Called by the constructor right after {@link #createContents(Composite)}.
|
||||||
*/
|
*/
|
||||||
private void postCreate() {
|
private void postCreate() {
|
||||||
reloadAvdList();
|
// nothing to be done for now.
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reloads the AVD list in the AVD selector.
|
|
||||||
* Tries to preserve the selection.
|
|
||||||
*/
|
|
||||||
private void reloadAvdList() {
|
|
||||||
AvdInfo selected = mAvdSelector.getSelected();
|
|
||||||
|
|
||||||
AvdInfo[] avds = null;
|
|
||||||
|
|
||||||
AvdManager manager = mUpdaterData.getAvdManager();
|
|
||||||
if (manager != null) {
|
|
||||||
avds = manager.getValidAvds();
|
|
||||||
}
|
|
||||||
|
|
||||||
mAvdSelector.setAvds(avds, null /*filter*/);
|
|
||||||
|
|
||||||
// Keep the list of known AVD names to check if they exist quickly. however
|
|
||||||
// use the list of all AVDs, including broken ones (unless we don't know their
|
|
||||||
// name).
|
|
||||||
mKnownAvdNames.clear();
|
|
||||||
if (manager != null) {
|
|
||||||
for (AvdInfo avd : manager.getAllAvds()) {
|
|
||||||
String name = avd.getName();
|
|
||||||
if (name != null) {
|
|
||||||
mKnownAvdNames.add(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mAvdSelector.setSelection(selected);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onSdkChange() {
|
public void onSdkChange() {
|
||||||
reloadAvdList();
|
mAvdSelector.refresh(false /*reload*/);
|
||||||
}
|
|
||||||
|
|
||||||
private void onRefreshSelected() {
|
|
||||||
mUpdaterData.reloadAvds();
|
|
||||||
reloadAvdList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// End of hiding from SWT Designer
|
// End of hiding from SWT Designer
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ package com.android.sdkuilib.internal.repository.icons;
|
|||||||
|
|
||||||
import org.eclipse.swt.SWTException;
|
import org.eclipse.swt.SWTException;
|
||||||
import org.eclipse.swt.graphics.Image;
|
import org.eclipse.swt.graphics.Image;
|
||||||
import org.eclipse.swt.graphics.ImageData;
|
|
||||||
import org.eclipse.swt.widgets.Display;
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@@ -74,7 +73,7 @@ public class ImageFactory {
|
|||||||
Iterator<Image> it = mImages.values().iterator();
|
Iterator<Image> it = mImages.values().iterator();
|
||||||
while(it.hasNext()) {
|
while(it.hasNext()) {
|
||||||
Image img = it.next();
|
Image img = it.next();
|
||||||
if (img != null) {
|
if (img != null && img.isDisposed() == false) {
|
||||||
img.dispose();
|
img.dispose();
|
||||||
}
|
}
|
||||||
it.remove();
|
it.remove();
|
||||||
|
|||||||
@@ -16,24 +16,28 @@
|
|||||||
|
|
||||||
package com.android.sdkuilib.internal.widgets;
|
package com.android.sdkuilib.internal.widgets;
|
||||||
|
|
||||||
|
import com.android.prefs.AndroidLocation.AndroidLocationException;
|
||||||
import com.android.sdklib.IAndroidTarget;
|
import com.android.sdklib.IAndroidTarget;
|
||||||
|
import com.android.sdklib.internal.avd.AvdManager;
|
||||||
import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
|
import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
|
||||||
|
import com.android.sdklib.internal.avd.AvdManager.AvdInfo.AvdStatus;
|
||||||
|
import com.android.sdkuilib.internal.repository.icons.ImageFactory;
|
||||||
|
|
||||||
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.DisposeEvent;
|
||||||
|
import org.eclipse.swt.events.DisposeListener;
|
||||||
import org.eclipse.swt.events.SelectionAdapter;
|
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.Image;
|
||||||
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.Button;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
import org.eclipse.swt.widgets.Event;
|
|
||||||
import org.eclipse.swt.widgets.Label;
|
import org.eclipse.swt.widgets.Label;
|
||||||
import org.eclipse.swt.widgets.Listener;
|
|
||||||
import org.eclipse.swt.widgets.Table;
|
import org.eclipse.swt.widgets.Table;
|
||||||
import org.eclipse.swt.widgets.TableColumn;
|
import org.eclipse.swt.widgets.TableColumn;
|
||||||
import org.eclipse.swt.widgets.TableItem;
|
import org.eclipse.swt.widgets.TableItem;
|
||||||
@@ -42,62 +46,96 @@ import org.eclipse.swt.widgets.TableItem;
|
|||||||
/**
|
/**
|
||||||
* The AVD selector is a table that is added to the given parent composite.
|
* The AVD selector is a table that is added to the given parent composite.
|
||||||
* <p/>
|
* <p/>
|
||||||
* To use, create it using {@link #AvdSelector(Composite, SelectionMode, IExtraAction)} then
|
* To use, create it using {@link #AvdSelector(Composite, AvdManager, DisplayMode)} then
|
||||||
* call {@link #setSelection(AvdInfo)}, {@link #setSelectionListener(SelectionListener)}
|
* call {@link #setSelection(AvdInfo)}, {@link #setSelectionListener(SelectionListener)}
|
||||||
* and finally use {@link #getSelected()} to retrieve the selection.
|
* and finally use {@link #getSelected()} to retrieve the selection.
|
||||||
*/
|
*/
|
||||||
public final class AvdSelector {
|
public final class AvdSelector {
|
||||||
|
|
||||||
private AvdInfo[] mAvds;
|
|
||||||
private SelectionListener mSelectionListener;
|
private SelectionListener mSelectionListener;
|
||||||
private Table mTable;
|
private Table mTable;
|
||||||
private Label mDescription;
|
|
||||||
|
|
||||||
private static int NUM_COL = 2;
|
private static int NUM_COL = 2;
|
||||||
private final SelectionMode mSelectionMode;
|
private final DisplayMode mDisplayMode;
|
||||||
private final IExtraAction mExtraAction;
|
private Button mManagerButton;
|
||||||
private Button mExtraActionButton;
|
private IAvdFilter mTargetFilter;
|
||||||
|
private AvdManager mManager;
|
||||||
|
private Image mOkImage;
|
||||||
|
private Image mBrokenImage;
|
||||||
|
private ImageFactory mIconFactory;
|
||||||
|
|
||||||
/** The selection mode, either {@link #SELECT} or {@link #CHECK} */
|
|
||||||
public enum SelectionMode {
|
|
||||||
/**
|
/**
|
||||||
|
* The display mode of the AVD Selector.
|
||||||
|
*/
|
||||||
|
public static enum DisplayMode {
|
||||||
|
/**
|
||||||
|
* Manager mode. Invalid AVDs are displayed. Buttons to create/delete AVDs
|
||||||
|
*/
|
||||||
|
MANAGER,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non manager mode. Only valid AVDs are displayed. Cannot create/delete AVDs, but
|
||||||
|
* there is a button to open the AVD Manager.
|
||||||
* In the "check" selection mode, checkboxes are displayed on each line
|
* In the "check" selection mode, checkboxes are displayed on each line
|
||||||
* and {@link AvdSelector#getSelected()} returns the line that is checked
|
* and {@link AvdSelector#getSelected()} returns the line that is checked
|
||||||
* even if it is not the currently selected line. Only one line can
|
* even if it is not the currently selected line. Only one line can
|
||||||
* be checked at once.
|
* be checked at once.
|
||||||
*/
|
*/
|
||||||
CHECK,
|
SIMPLE_CHECK,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Non manager mode. Only valid AVDs are displayed. Cannot create/delete AVDs, but
|
||||||
|
* there is a button to open the AVD Manager.
|
||||||
* In the "select" selection mode, there are no checkboxes and
|
* In the "select" selection mode, there are no checkboxes and
|
||||||
* {@link AvdSelector#getSelected()} returns the line currently selected.
|
* {@link AvdSelector#getSelected()} returns the line currently selected.
|
||||||
* Only one line can be selected at once.
|
* Only one line can be selected at once.
|
||||||
*/
|
*/
|
||||||
SELECT
|
SIMPLE_SELECTION,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines an "extra action" button that can be shown under the AVD Selector.
|
* A filter to control the whether or not an AVD should be displayed by the AVD Selector.
|
||||||
*/
|
*/
|
||||||
public interface IExtraAction {
|
public interface IAvdFilter {
|
||||||
/**
|
/**
|
||||||
* Label of the button that will be created.
|
* Called before {@link #accept(AvdInfo)} is called for any AVD.
|
||||||
* This is invoked once when the button is created and cannot be changed later.
|
|
||||||
*/
|
*/
|
||||||
public String label();
|
void prepare();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is invoked just after the selection has changed to update the "enabled"
|
* Called to decided whether an AVD should be displayed.
|
||||||
* state of the action. Implementation should use {@link AvdSelector#getSelected()}.
|
* @param avd the AVD to test.
|
||||||
|
* @return true if the AVD should be displayed.
|
||||||
*/
|
*/
|
||||||
public boolean isEnabled();
|
boolean accept(AvdInfo avd);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the action, invoked when the button is clicked.
|
* Called after {@link #accept(AvdInfo)} has been called on all the AVDs.
|
||||||
*
|
|
||||||
* The caller's action is responsible for reloading the AVD list
|
|
||||||
* using {@link AvdSelector#setAvds(AvdInfo[], IAndroidTarget)}.
|
|
||||||
*/
|
*/
|
||||||
public void run();
|
void cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal implementation of {@link IAvdFilter} to filter out the AVDs that are not
|
||||||
|
* running an image compatible with a specific target.
|
||||||
|
*/
|
||||||
|
private final static class TargetBasedFilter implements IAvdFilter {
|
||||||
|
private final IAndroidTarget mTarget;
|
||||||
|
|
||||||
|
TargetBasedFilter(IAndroidTarget target) {
|
||||||
|
mTarget = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void prepare() {
|
||||||
|
// nothing to prepare
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean accept(AvdInfo avd) {
|
||||||
|
return mTarget.isCompatibleBaseFor(avd.getTarget());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanup() {
|
||||||
|
// nothing to clean up
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,20 +145,18 @@ public final class AvdSelector {
|
|||||||
* {@link IAndroidTarget} will be displayed.
|
* {@link IAndroidTarget} will be displayed.
|
||||||
*
|
*
|
||||||
* @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 manager the AVD manager.
|
||||||
* It can be null.
|
* @param filter When non-null, will allow filtering the AVDs to display.
|
||||||
* @param filter When non-null, will display only the AVDs matching this target.
|
|
||||||
* @param extraAction When non-null, displays an extra action button.
|
* @param extraAction When non-null, displays an extra action button.
|
||||||
* @param selectionMode One of {@link SelectionMode#SELECT} or {@link SelectionMode#CHECK}
|
* @param displayMode The display mode ({@link DisplayMode}).
|
||||||
*/
|
*/
|
||||||
public AvdSelector(Composite parent,
|
public AvdSelector(Composite parent,
|
||||||
AvdInfo[] avds,
|
AvdManager manager,
|
||||||
IAndroidTarget filter,
|
IAvdFilter filter,
|
||||||
IExtraAction extraAction,
|
DisplayMode displayMode) {
|
||||||
SelectionMode selectionMode) {
|
mManager = manager;
|
||||||
mAvds = avds;
|
mTargetFilter = filter;
|
||||||
mExtraAction = extraAction;
|
mDisplayMode = displayMode;
|
||||||
mSelectionMode = selectionMode;
|
|
||||||
|
|
||||||
// Layout has 2 columns
|
// Layout has 2 columns
|
||||||
Composite group = new Composite(parent, SWT.NONE);
|
Composite group = new Composite(parent, SWT.NONE);
|
||||||
@@ -129,9 +165,14 @@ public final class AvdSelector {
|
|||||||
gl.marginHeight = gl.marginWidth = 0;
|
gl.marginHeight = gl.marginWidth = 0;
|
||||||
group.setLayoutData(new GridData(GridData.FILL_BOTH));
|
group.setLayoutData(new GridData(GridData.FILL_BOTH));
|
||||||
group.setFont(parent.getFont());
|
group.setFont(parent.getFont());
|
||||||
|
group.addDisposeListener(new DisposeListener() {
|
||||||
|
public void widgetDisposed(DisposeEvent arg0) {
|
||||||
|
mIconFactory.dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
int style = SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER;
|
int style = SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER;
|
||||||
if (selectionMode == SelectionMode.CHECK) {
|
if (displayMode == DisplayMode.SIMPLE_CHECK) {
|
||||||
style |= SWT.CHECK;
|
style |= SWT.CHECK;
|
||||||
}
|
}
|
||||||
mTable = new Table(group, style);
|
mTable = new Table(group, style);
|
||||||
@@ -139,18 +180,53 @@ public final class AvdSelector {
|
|||||||
mTable.setLinesVisible(false);
|
mTable.setLinesVisible(false);
|
||||||
setTableHeightHint(0);
|
setTableHeightHint(0);
|
||||||
|
|
||||||
mDescription = new Label(group, SWT.WRAP);
|
Composite buttons = new Composite(group, SWT.NONE);
|
||||||
mDescription.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
buttons.setLayout(gl = new GridLayout(1, false /*makeColumnsEqualWidth*/));
|
||||||
|
gl.marginHeight = gl.marginWidth = 0;
|
||||||
|
buttons.setLayoutData(new GridData(GridData.FILL_VERTICAL));
|
||||||
|
buttons.setFont(group.getFont());
|
||||||
|
|
||||||
if (extraAction != null) {
|
if (displayMode == DisplayMode.MANAGER) {
|
||||||
mExtraActionButton = new Button(group, SWT.PUSH);
|
Button newButton = new Button(buttons, SWT.PUSH | SWT.FLAT);
|
||||||
mExtraActionButton.setText(extraAction.label());
|
newButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||||
mExtraActionButton.setEnabled(extraAction.isEnabled());
|
newButton.setText("New");
|
||||||
mExtraActionButton.addSelectionListener(new SelectionAdapter() {
|
// TODO: callback for button
|
||||||
|
|
||||||
|
Button deleteButton = new Button(buttons, SWT.PUSH | SWT.FLAT);
|
||||||
|
deleteButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||||
|
deleteButton.setText("Delete");
|
||||||
|
// TODO: callback for button
|
||||||
|
|
||||||
|
Label l = new Label(buttons, SWT.SEPARATOR | SWT.HORIZONTAL);
|
||||||
|
l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||||
|
}
|
||||||
|
|
||||||
|
Button infoButton = new Button(buttons, SWT.PUSH | SWT.FLAT);
|
||||||
|
infoButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||||
|
infoButton.setText("Info...");
|
||||||
|
// TODO: callback for button
|
||||||
|
|
||||||
|
Composite padding = new Composite(buttons, SWT.NONE);
|
||||||
|
padding.setLayoutData(new GridData(GridData.FILL_VERTICAL));
|
||||||
|
|
||||||
|
Button refreshButton = new Button(buttons, SWT.PUSH | SWT.FLAT);
|
||||||
|
refreshButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||||
|
refreshButton.setText("Resfresh");
|
||||||
|
refreshButton.addSelectionListener(new SelectionAdapter() {
|
||||||
|
@Override
|
||||||
|
public void widgetSelected(SelectionEvent arg0) {
|
||||||
|
refresh(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (displayMode != DisplayMode.MANAGER) {
|
||||||
|
mManagerButton = new Button(buttons, SWT.PUSH | SWT.FLAT);
|
||||||
|
mManagerButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||||
|
mManagerButton.setText("Manager...");
|
||||||
|
mManagerButton.addSelectionListener(new SelectionAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void widgetSelected(SelectionEvent e) {
|
public void widgetSelected(SelectionEvent e) {
|
||||||
super.widgetSelected(e);
|
super.widgetSelected(e);
|
||||||
mExtraAction.run();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -165,41 +241,45 @@ public final class AvdSelector {
|
|||||||
final TableColumn column3 = new TableColumn(mTable, SWT.NONE);
|
final TableColumn column3 = new TableColumn(mTable, SWT.NONE);
|
||||||
column3.setText("API Level");
|
column3.setText("API Level");
|
||||||
|
|
||||||
|
// get some bitmaps.
|
||||||
|
mIconFactory = new ImageFactory(parent.getDisplay());
|
||||||
|
mOkImage = mIconFactory.getImage("accept_icon16.png");
|
||||||
|
mBrokenImage = mIconFactory.getImage("reject_icon16.png");
|
||||||
|
|
||||||
adjustColumnsWidth(mTable, column0, column1, column2, column3);
|
adjustColumnsWidth(mTable, column0, column1, column2, column3);
|
||||||
setupSelectionListener(mTable);
|
setupSelectionListener(mTable);
|
||||||
fillTable(mTable, filter);
|
fillTable(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 manager the AVD manager.
|
||||||
* It can be null.
|
* @param displayMode The display mode ({@link DisplayMode}).
|
||||||
* @param extraAction When non-null, displays an extra action button.
|
|
||||||
* @param selectionMode One of {@link SelectionMode#SELECT} or {@link SelectionMode#CHECK}
|
|
||||||
*/
|
*/
|
||||||
public AvdSelector(Composite parent,
|
public AvdSelector(Composite parent, AvdManager manager,
|
||||||
AvdInfo[] avds,
|
DisplayMode displayMode) {
|
||||||
IExtraAction extraAction,
|
this(parent, manager, (IAvdFilter)null /* filter */, displayMode);
|
||||||
SelectionMode selectionMode) {
|
|
||||||
this(parent, avds, null /* filter */, extraAction, selectionMode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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}, filtered
|
||||||
|
* by an {@link IAndroidTarget}.
|
||||||
|
* <p/>Only the {@link AvdInfo} able to run applications developed for the given
|
||||||
|
* {@link IAndroidTarget} will be displayed.
|
||||||
*
|
*
|
||||||
* @param parent The parent composite where the selector will be added.
|
* @param parent The parent composite where the selector will be added.
|
||||||
* @param extraAction When non-null, displays an extra action button.
|
* @param manager the AVD manager.
|
||||||
* @param selectionMode One of {@link SelectionMode#SELECT} or {@link SelectionMode#CHECK}
|
* @param filter Only shows the AVDs matching this target (must not be null).
|
||||||
|
* @param displayMode The display mode ({@link DisplayMode}).
|
||||||
*/
|
*/
|
||||||
public AvdSelector(Composite parent,
|
public AvdSelector(Composite parent,
|
||||||
SelectionMode selectionMode,
|
AvdManager manager,
|
||||||
IExtraAction extraAction) {
|
IAndroidTarget filter,
|
||||||
this(parent, null /*avds*/, null /* filter */, extraAction, selectionMode);
|
DisplayMode displayMode) {
|
||||||
|
this(parent, manager, new TargetBasedFilter(filter), displayMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the table grid layout data.
|
* Sets the table grid layout data.
|
||||||
*
|
*
|
||||||
@@ -212,41 +292,70 @@ public final class AvdSelector {
|
|||||||
}
|
}
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a new set of AVD, with an optional filter.
|
* Refresh the display of Android Virtual Devices.
|
||||||
* Tries to keep the selection.
|
* Tries to keep the selection.
|
||||||
* <p/>
|
* <p/>
|
||||||
* This must be called from the UI thread.
|
* This must be called from the UI thread.
|
||||||
*
|
*
|
||||||
*
|
* @param reload if true, the AVD manager will reload the AVD from the disk.
|
||||||
* @param avds The list of AVDs. This is <em>not</em> copied, the caller must not modify.
|
* @throws AndroidLocationException if reload the AVD failed.
|
||||||
* It can be null.
|
* @return false if the reloading failed. This is always true if <var>reload</var> is
|
||||||
* @param filter An IAndroidTarget. If non-null, only AVD whose target are compatible with the
|
* <code>false</code>.
|
||||||
* filter target will displayed an available for selection.
|
|
||||||
*/
|
*/
|
||||||
public void setAvds(AvdInfo[] avds, IAndroidTarget filter) {
|
public boolean refresh(boolean reload) {
|
||||||
|
if (reload) {
|
||||||
|
try {
|
||||||
|
mManager.reloadAvds();
|
||||||
|
} catch (AndroidLocationException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AvdInfo selected = getSelected();
|
AvdInfo selected = getSelected();
|
||||||
|
|
||||||
mAvds = avds;
|
fillTable(mTable);
|
||||||
fillTable(mTable, filter);
|
|
||||||
|
|
||||||
setSelection(selected);
|
setSelection(selected);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the list of known AVDs.
|
* Sets a new AVD manager
|
||||||
* <p/>
|
* This does not refresh the display. Call {@link #refresh(boolean)} to do so.
|
||||||
* This is not a copy. Callers must <em>not</em> modify this array.
|
* @param manager the AVD manager.
|
||||||
*/
|
*/
|
||||||
public AvdInfo[] getAvds() {
|
public void setManager(AvdManager manager) {
|
||||||
return mAvds;
|
mManager = manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a new AVD filter.
|
||||||
|
* This does not refresh the display. Call {@link #refresh(boolean)} to do so.
|
||||||
|
* @param filter An IAvdFilter. If non-null, this will filter out the AVD to not display.
|
||||||
|
*/
|
||||||
|
public void setFilter(IAvdFilter filter) {
|
||||||
|
mTargetFilter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a new Android Target-based AVD filter.
|
||||||
|
* This does not refresh the display. Call {@link #refresh(boolean)} to do so.
|
||||||
|
* @param target An IAndroidTarget. If non-null, only AVD whose target are compatible with the
|
||||||
|
* filter target will displayed an available for selection.
|
||||||
|
*/
|
||||||
|
public void setFilter(IAndroidTarget target) {
|
||||||
|
if (target != null) {
|
||||||
|
mTargetFilter = new TargetBasedFilter(target);
|
||||||
|
} else {
|
||||||
|
mTargetFilter = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -281,19 +390,7 @@ public final class AvdSelector {
|
|||||||
int selIndex = mTable.getSelectionIndex();
|
int selIndex = mTable.getSelectionIndex();
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (TableItem i : mTable.getItems()) {
|
for (TableItem i : mTable.getItems()) {
|
||||||
if (mSelectionMode == SelectionMode.SELECT) {
|
if (mDisplayMode == DisplayMode.SIMPLE_CHECK) {
|
||||||
if ((AvdInfo) i.getData() == target) {
|
|
||||||
found = true;
|
|
||||||
if (index != selIndex) {
|
|
||||||
mTable.setSelection(index);
|
|
||||||
modified = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
|
|
||||||
} else if (mSelectionMode == SelectionMode.CHECK){
|
|
||||||
if ((AvdInfo) i.getData() == target) {
|
if ((AvdInfo) i.getData() == target) {
|
||||||
found = true;
|
found = true;
|
||||||
if (!i.getChecked()) {
|
if (!i.getChecked()) {
|
||||||
@@ -304,6 +401,17 @@ public final class AvdSelector {
|
|||||||
modified = true;
|
modified = true;
|
||||||
i.setChecked(false);
|
i.setChecked(false);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if ((AvdInfo) i.getData() == target) {
|
||||||
|
found = true;
|
||||||
|
if (index != selIndex) {
|
||||||
|
mTable.setSelection(index);
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,10 +419,6 @@ public final class AvdSelector {
|
|||||||
mSelectionListener.widgetSelected(null);
|
mSelectionListener.widgetSelected(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mExtraAction != null && mExtraActionButton != null) {
|
|
||||||
mExtraActionButton.setEnabled(mExtraAction.isEnabled());
|
|
||||||
}
|
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,18 +428,17 @@ public final class AvdSelector {
|
|||||||
* @return The currently selected item or null.
|
* @return The currently selected item or null.
|
||||||
*/
|
*/
|
||||||
public AvdInfo getSelected() {
|
public AvdInfo getSelected() {
|
||||||
if (mSelectionMode == SelectionMode.SELECT) {
|
if (mDisplayMode == DisplayMode.SIMPLE_CHECK) {
|
||||||
int selIndex = mTable.getSelectionIndex();
|
|
||||||
if (selIndex >= 0) {
|
|
||||||
return (AvdInfo) mTable.getItem(selIndex).getData();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (mSelectionMode == SelectionMode.CHECK) {
|
|
||||||
for (TableItem i : mTable.getItems()) {
|
for (TableItem i : mTable.getItems()) {
|
||||||
if (i.getChecked()) {
|
if (i.getChecked()) {
|
||||||
return (AvdInfo) i.getData();
|
return (AvdInfo) i.getData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
int selIndex = mTable.getSelectionIndex();
|
||||||
|
if (selIndex >= 0) {
|
||||||
|
return (AvdInfo) mTable.getItem(selIndex).getData();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -349,7 +452,6 @@ public final class AvdSelector {
|
|||||||
*/
|
*/
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
mTable.setEnabled(enabled);
|
mTable.setEnabled(enabled);
|
||||||
mDescription.setEnabled(enabled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -368,15 +470,14 @@ public final class AvdSelector {
|
|||||||
@Override
|
@Override
|
||||||
public void controlResized(ControlEvent e) {
|
public void controlResized(ControlEvent e) {
|
||||||
Rectangle r = table.getClientArea();
|
Rectangle r = table.getClientArea();
|
||||||
column0.setWidth(r.width * 30 / 100); // 30%
|
column0.setWidth(r.width * 25 / 100); // 25%
|
||||||
column1.setWidth(r.width * 45 / 100); // 45%
|
column1.setWidth(r.width * 45 / 100); // 45%
|
||||||
column2.setWidth(r.width * 10 / 100); // 10%
|
column2.setWidth(r.width * 15 / 100); // 15%
|
||||||
column3.setWidth(r.width * 15 / 100); // 15%
|
column3.setWidth(r.width * 15 / 100); // 15%
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a selection listener that will check or uncheck the whole line when
|
* Creates a selection listener that will check or uncheck the whole line when
|
||||||
* double-clicked (aka "the default selection").
|
* double-clicked (aka "the default selection").
|
||||||
@@ -393,16 +494,11 @@ public final class AvdSelector {
|
|||||||
if (e.item instanceof TableItem) {
|
if (e.item instanceof TableItem) {
|
||||||
TableItem i = (TableItem) e.item;
|
TableItem i = (TableItem) e.item;
|
||||||
enforceSingleSelection(i);
|
enforceSingleSelection(i);
|
||||||
updateDescription(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSelectionListener != null) {
|
if (mSelectionListener != null) {
|
||||||
mSelectionListener.widgetSelected(e);
|
mSelectionListener.widgetSelected(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mExtraAction != null && mExtraActionButton != null) {
|
|
||||||
mExtraActionButton.setEnabled(mExtraAction.isEnabled());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -416,20 +512,15 @@ public final class AvdSelector {
|
|||||||
public void widgetDefaultSelected(SelectionEvent e) {
|
public void widgetDefaultSelected(SelectionEvent e) {
|
||||||
if (e.item instanceof TableItem) {
|
if (e.item instanceof TableItem) {
|
||||||
TableItem i = (TableItem) e.item;
|
TableItem i = (TableItem) e.item;
|
||||||
if (mSelectionMode == SelectionMode.CHECK) {
|
if (mDisplayMode == DisplayMode.SIMPLE_CHECK) {
|
||||||
i.setChecked(true);
|
i.setChecked(true);
|
||||||
}
|
}
|
||||||
enforceSingleSelection(i);
|
enforceSingleSelection(i);
|
||||||
updateDescription(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSelectionListener != null) {
|
if (mSelectionListener != null) {
|
||||||
mSelectionListener.widgetDefaultSelected(e);
|
mSelectionListener.widgetDefaultSelected(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mExtraAction != null && mExtraActionButton != null) {
|
|
||||||
mExtraActionButton.setEnabled(mExtraAction.isEnabled());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -437,10 +528,7 @@ public final class AvdSelector {
|
|||||||
* This makes the chekboxes act as radio buttons.
|
* This makes the chekboxes act as radio buttons.
|
||||||
*/
|
*/
|
||||||
private void enforceSingleSelection(TableItem item) {
|
private void enforceSingleSelection(TableItem item) {
|
||||||
if (mSelectionMode == SelectionMode.SELECT) {
|
if (mDisplayMode == DisplayMode.SIMPLE_CHECK) {
|
||||||
// pass
|
|
||||||
|
|
||||||
} else if (mSelectionMode == SelectionMode.CHECK) {
|
|
||||||
if (item.getChecked()) {
|
if (item.getChecked()) {
|
||||||
Table parentTable = item.getParent();
|
Table parentTable = item.getParent();
|
||||||
for (TableItem i2 : parentTable.getItems()) {
|
for (TableItem i2 : parentTable.getItems()) {
|
||||||
@@ -449,6 +537,8 @@ public final class AvdSelector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// pass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -464,23 +554,52 @@ public final class AvdSelector {
|
|||||||
* <li>column 3: sdk version
|
* <li>column 3: sdk version
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
private void fillTable(final Table table, IAndroidTarget filter) {
|
private void fillTable(final Table table) {
|
||||||
table.removeAll();
|
table.removeAll();
|
||||||
if (mAvds != null && mAvds.length > 0) {
|
|
||||||
|
// get the AVDs
|
||||||
|
AvdInfo avds[] = null;
|
||||||
|
if (mManager != null) {
|
||||||
|
if (mDisplayMode == DisplayMode.MANAGER) {
|
||||||
|
avds = mManager.getAllAvds();
|
||||||
|
} else {
|
||||||
|
avds = mManager.getValidAvds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (avds != null && avds.length > 0) {
|
||||||
table.setEnabled(true);
|
table.setEnabled(true);
|
||||||
for (AvdInfo avd : mAvds) {
|
|
||||||
if (filter == null || filter.isCompatibleBaseFor(avd.getTarget())) {
|
if (mTargetFilter != null) {
|
||||||
|
mTargetFilter.prepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AvdInfo avd : avds) {
|
||||||
|
if (mTargetFilter == null || mTargetFilter.accept(avd)) {
|
||||||
TableItem item = new TableItem(table, SWT.NONE);
|
TableItem item = new TableItem(table, SWT.NONE);
|
||||||
item.setData(avd);
|
item.setData(avd);
|
||||||
item.setText(0, avd.getName());
|
item.setText(0, avd.getName());
|
||||||
|
if (mDisplayMode == DisplayMode.MANAGER) {
|
||||||
|
item.setImage(0, avd.getStatus() == AvdStatus.OK ? mOkImage : mBrokenImage);
|
||||||
|
}
|
||||||
IAndroidTarget target = avd.getTarget();
|
IAndroidTarget target = avd.getTarget();
|
||||||
|
if (target != null) {
|
||||||
item.setText(1, target.getFullName());
|
item.setText(1, target.getFullName());
|
||||||
item.setText(2, target.getApiVersionName());
|
item.setText(2, target.getApiVersionName());
|
||||||
item.setText(3, Integer.toString(target.getApiVersionNumber()));
|
item.setText(3, Integer.toString(target.getApiVersionNumber()));
|
||||||
|
} else {
|
||||||
|
item.setText(1, "?");
|
||||||
|
item.setText(2, "?");
|
||||||
|
item.setText(3, "?");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mTargetFilter != null) {
|
||||||
|
mTargetFilter.cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (table.getItemCount() == 0) {
|
if (table.getItemCount() == 0) {
|
||||||
table.setEnabled(false);
|
table.setEnabled(false);
|
||||||
TableItem item = new TableItem(table, SWT.NONE);
|
TableItem item = new TableItem(table, SWT.NONE);
|
||||||
@@ -491,61 +610,4 @@ public final class AvdSelector {
|
|||||||
item.setText(3, "--");
|
item.setText(3, "--");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up a tooltip that displays the current item description.
|
|
||||||
* <p/>
|
|
||||||
* Displaying a tooltip over the table looks kind of odd here. Instead we actually
|
|
||||||
* display the description in a label under the table.
|
|
||||||
*/
|
|
||||||
private void setupTooltip(final Table table) {
|
|
||||||
/*
|
|
||||||
* Reference:
|
|
||||||
* http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet125.java?view=markup
|
|
||||||
*/
|
|
||||||
|
|
||||||
final Listener listener = new Listener() {
|
|
||||||
public void handleEvent(Event event) {
|
|
||||||
|
|
||||||
switch(event.type) {
|
|
||||||
case SWT.KeyDown:
|
|
||||||
case SWT.MouseExit:
|
|
||||||
case SWT.MouseDown:
|
|
||||||
return;
|
|
||||||
|
|
||||||
case SWT.MouseHover:
|
|
||||||
updateDescription(table.getItem(new Point(event.x, event.y)));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SWT.Selection:
|
|
||||||
if (event.item instanceof TableItem) {
|
|
||||||
updateDescription((TableItem) event.item);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
table.addListener(SWT.Dispose, listener);
|
|
||||||
table.addListener(SWT.KeyDown, listener);
|
|
||||||
table.addListener(SWT.MouseMove, listener);
|
|
||||||
table.addListener(SWT.MouseHover, listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the description label with the path of the item's AVD, if any.
|
|
||||||
*/
|
|
||||||
private void updateDescription(TableItem item) {
|
|
||||||
if (item != null) {
|
|
||||||
Object data = item.getData();
|
|
||||||
if (data instanceof AvdInfo) {
|
|
||||||
String newTooltip = ((AvdInfo) data).getPath();
|
|
||||||
mDescription.setText(newTooltip == null ? "" : newTooltip); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user