Add hardware support to AVD creation dialog.

Change-Id: Ia20b55c788191b40159b5c38b66f1da333179ccc
This commit is contained in:
Xavier Ducrohet
2009-10-07 19:47:30 -07:00
parent 5e5e423346
commit 3a05612f59
4 changed files with 501 additions and 73 deletions

View File

@@ -43,7 +43,6 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.xml.xpath.XPath; import javax.xml.xpath.XPath;
@@ -994,13 +993,16 @@ public class Main {
// get the list of possible hardware properties // get the list of possible hardware properties
File hardwareDefs = new File (mOsSdkFolder + File.separator + File hardwareDefs = new File (mOsSdkFolder + File.separator +
SdkConstants.OS_SDK_TOOLS_LIB_FOLDER, SdkConstants.FN_HARDWARE_INI); SdkConstants.OS_SDK_TOOLS_LIB_FOLDER, SdkConstants.FN_HARDWARE_INI);
List<HardwareProperty> list = HardwareProperties.parseHardwareDefinitions(hardwareDefs, Map<String, HardwareProperty> hwMap = HardwareProperties.parseHardwareDefinitions(
null /*sdkLog*/); hardwareDefs, null /*sdkLog*/);
HashMap<String, String> map = new HashMap<String, String>(); HashMap<String, String> map = new HashMap<String, String>();
for (int i = 0 ; i < list.size() ;) { // we just want to loop on the HardwareProperties
HardwareProperty property = list.get(i); HardwareProperty[] hwProperties = hwMap.values().toArray(
new HardwareProperty[hwMap.size()]);
for (int i = 0 ; i < hwProperties.length ;) {
HardwareProperty property = hwProperties[i];
String description = property.getDescription(); String description = property.getDescription();
if (description != null) { if (description != null) {

View File

@@ -24,43 +24,52 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.ArrayList; import java.util.HashMap;
import java.util.List; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class HardwareProperties { public class HardwareProperties {
private final static Pattern PATTERN_PROP = Pattern.compile( private final static Pattern PATTERN_PROP = Pattern.compile(
"^([a-zA-Z0-9._-]+)\\s*=\\s*(.*)\\s*$"); "^([a-zA-Z0-9._-]+)\\s*=\\s*(.*)\\s*$");
private final static String HW_PROP_NAME = "name"; private final static String HW_PROP_NAME = "name";
private final static String HW_PROP_TYPE = "type"; private final static String HW_PROP_TYPE = "type";
private final static String HW_PROP_DEFAULT = "default"; private final static String HW_PROP_DEFAULT = "default";
private final static String HW_PROP_ABSTRACT = "abstract"; private final static String HW_PROP_ABSTRACT = "abstract";
private final static String HW_PROP_DESC = "description"; private final static String HW_PROP_DESC = "description";
private final static String BOOLEAN_YES = "yes";
private final static String BOOLEAN_NO = "no";
public final static String[] BOOLEAN_VALUES = new String[] { BOOLEAN_YES, BOOLEAN_NO };
public final static Pattern DISKSIZE_PATTERN = Pattern.compile("\\d+[MK]B");
public enum ValueType { public enum ValueType {
INTEGER("integer"), INTEGER("integer"),
BOOLEAN("boolean"), BOOLEAN("boolean"),
DISKSIZE("diskSize"); DISKSIZE("diskSize");
private String mValue; private String mValue;
ValueType(String value) { ValueType(String value) {
mValue = value; mValue = value;
} }
public String getValue() {
return mValue;
}
public static ValueType getEnum(String value) { public static ValueType getEnum(String value) {
for (ValueType type : values()) { for (ValueType type : values()) {
if (type.mValue.equals(value)) { if (type.mValue.equals(value)) {
return type; return type;
} }
} }
return null; return null;
} }
} }
public static final class HardwareProperty { public static final class HardwareProperty {
private String mName; private String mName;
private ValueType mType; private ValueType mType;
@@ -68,40 +77,40 @@ public class HardwareProperties {
private String mDefault; private String mDefault;
private String mAbstract; private String mAbstract;
private String mDescription; private String mDescription;
public String getName() { public String getName() {
return mName; return mName;
} }
public ValueType getType() { public ValueType getType() {
return mType; return mType;
} }
public String getDefault() { public String getDefault() {
return mDefault; return mDefault;
} }
public String getAbstract() { public String getAbstract() {
return mAbstract; return mAbstract;
} }
public String getDescription() { public String getDescription() {
return mDescription; return mDescription;
} }
} }
/** /**
* Parses the hardware definition file. * Parses the hardware definition file.
* @param file the property file to parse * @param file the property file to parse
* @param log the ISdkLog object receiving warning/error from the parsing. * @param log the ISdkLog object receiving warning/error from the parsing.
* @return the map of (key,value) pairs, or null if the parsing failed. * @return the map of (key,value) pairs, or null if the parsing failed.
*/ */
public static List<HardwareProperty> parseHardwareDefinitions(File file, ISdkLog log) { public static Map<String, HardwareProperty> parseHardwareDefinitions(File file, ISdkLog log) {
try { try {
FileInputStream fis = new FileInputStream(file); FileInputStream fis = new FileInputStream(file);
BufferedReader reader = new BufferedReader(new InputStreamReader(fis)); BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
List<HardwareProperty> map = new ArrayList<HardwareProperty>(); Map<String, HardwareProperty> map = new HashMap<String, HardwareProperty>();
String line = null; String line = null;
HardwareProperty prop = null; HardwareProperty prop = null;
@@ -115,15 +124,15 @@ public class HardwareProperties {
if (HW_PROP_NAME.equals(valueName)) { if (HW_PROP_NAME.equals(valueName)) {
prop = new HardwareProperty(); prop = new HardwareProperty();
prop.mName = value; prop.mName = value;
map.add(prop); map.put(prop.mName, prop);
} }
if (prop == null) { if (prop == null) {
log.warning("Error parsing '%1$s': missing '%2$s'", log.warning("Error parsing '%1$s': missing '%2$s'",
file.getAbsolutePath(), HW_PROP_NAME); file.getAbsolutePath(), HW_PROP_NAME);
return null; return null;
} }
if (HW_PROP_TYPE.equals(valueName)) { if (HW_PROP_TYPE.equals(valueName)) {
prop.mType = ValueType.getEnum(value); prop.mType = ValueType.getEnum(value);
} else if (HW_PROP_DEFAULT.equals(valueName)) { } else if (HW_PROP_DEFAULT.equals(valueName)) {
@@ -140,7 +149,7 @@ public class HardwareProperties {
} }
} }
} }
return map; return map;
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
// this should not happen since we usually test the file existence before // this should not happen since we usually test the file existence before
@@ -156,4 +165,16 @@ public class HardwareProperties {
return null; return null;
} }
/**
* Returns the index of <var>value</var> in {@link #BOOLEAN_VALUES}.
*/
public static int getBooleanValueIndex(String value) {
if (BOOLEAN_YES.equals(value)) {
return 0;
} else if (BOOLEAN_NO.equals(value)) {
return 1;
}
return -1;
}
} }

View File

@@ -19,14 +19,32 @@ package com.android.sdkuilib.internal.widgets;
import com.android.prefs.AndroidLocation; import com.android.prefs.AndroidLocation;
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.SdkConstants;
import com.android.sdklib.SdkManager; import com.android.sdklib.SdkManager;
import com.android.sdklib.internal.avd.AvdManager; import com.android.sdklib.internal.avd.AvdManager;
import com.android.sdklib.internal.avd.HardwareProperties;
import com.android.sdklib.internal.avd.AvdManager.AvdInfo; import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
import com.android.sdklib.internal.avd.HardwareProperties.HardwareProperty;
import com.android.sdkuilib.internal.repository.icons.ImageFactory; import com.android.sdkuilib.internal.repository.icons.ImageFactory;
import com.android.sdkuilib.internal.widgets.AvdSelector.SdkLog; import com.android.sdkuilib.internal.widgets.AvdSelector.SdkLog;
import com.android.sdkuilib.ui.GridDialog;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.ModifyListener;
@@ -45,26 +63,36 @@ import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label; 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.TableColumn;
import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.Text;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.Map.Entry;
/** /**
* AVD creator dialog. * AVD creator dialog.
* *
* TODO: * TODO:
* - support custom hardware properties
* - use SdkTargetSelector instead of Combo * - use SdkTargetSelector instead of Combo
* - tooltips on widgets. * - tooltips on widgets.
* *
*/ */
final class AvdCreationDialog extends Dialog { final class AvdCreationDialog extends GridDialog {
private final AvdManager mAvdManager; private final AvdManager mAvdManager;
private final TreeMap<String, IAndroidTarget> mCurrentTargets = private final TreeMap<String, IAndroidTarget> mCurrentTargets =
new TreeMap<String, IAndroidTarget>(); new TreeMap<String, IAndroidTarget>();
private final Map<String, HardwareProperty> mHardwareMap;
private final Map<String, String> mProperties = new HashMap<String, String>();
// a list of user-edited properties.
private final ArrayList<String> mEditedProperties = new ArrayList<String>();
private Text mAvdName; private Text mAvdName;
private Combo mTargetCombo; private Combo mTargetCombo;
@@ -76,17 +104,22 @@ final class AvdCreationDialog extends Dialog {
private Button mBrowseSdCard; private Button mBrowseSdCard;
private Button mSdCardFileRadio; private Button mSdCardFileRadio;
private Button mSkinListRadio;
private Combo mSkinCombo; private Combo mSkinCombo;
private Button mSkinSizeRadio;
private Text mSkinSizeWidth;
private Text mSkinSizeHeight;
private TableViewer mHardwareViewer;
private Button mDeleteHardwareProp;
private Button mForceCreation; private Button mForceCreation;
private Button mOkButton; private Button mOkButton;
private Label mStatusIcon; private Label mStatusIcon;
private Label mStatusLabel; private Label mStatusLabel;
private Composite mStatusComposite; private Composite mStatusComposite;
private final ImageFactory mImageFactory; private final ImageFactory mImageFactory;
private Button mSkinListRadio;
private Button mSkinSizeRadio;
private Text mSkinSizeWidth;
private Text mSkinSizeHeight;
/** /**
* {@link VerifyListener} for {@link Text} widgets that should only contains numbers. * {@link VerifyListener} for {@link Text} widgets that should only contains numbers.
@@ -140,9 +173,14 @@ final class AvdCreationDialog extends Dialog {
protected AvdCreationDialog(Shell parentShell, AvdManager avdManager, protected AvdCreationDialog(Shell parentShell, AvdManager avdManager,
ImageFactory imageFactory) { ImageFactory imageFactory) {
super(parentShell); super(parentShell, 2, false);
mAvdManager = avdManager; mAvdManager = avdManager;
mImageFactory = imageFactory; mImageFactory = imageFactory;
File hardwareDefs = new File (avdManager.getSdkManager().getLocation() + File.separator +
SdkConstants.OS_SDK_TOOLS_LIB_FOLDER, SdkConstants.FN_HARDWARE_INI);
mHardwareMap = HardwareProperties.parseHardwareDefinitions(
hardwareDefs, null /*sdkLog*/);
} }
@Override @Override
@@ -168,31 +206,21 @@ final class AvdCreationDialog extends Dialog {
} }
@Override @Override
protected Control createDialogArea(Composite parent) { public void createDialogContent(final Composite parent) {
GridData gd; GridData gd;
final int groupIndent = 30; GridLayout gl;
Composite top = new Composite(parent, SWT.NONE); Label label = new Label(parent, SWT.NONE);
GridLayout layout = new GridLayout(2, false);
layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
layout.horizontalSpacing = convertHorizontalDLUsToPixels(
IDialogConstants.HORIZONTAL_SPACING);
top.setLayout(layout);
top.setLayoutData(new GridData(GridData.FILL_BOTH));
Label label = new Label(top, SWT.NONE);
label.setText("Name:"); label.setText("Name:");
mAvdName = new Text(top, SWT.BORDER); mAvdName = new Text(parent, SWT.BORDER);
mAvdName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); mAvdName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mAvdName.addModifyListener(new CreateNameModifyListener()); mAvdName.addModifyListener(new CreateNameModifyListener());
label = new Label(top, SWT.NONE); label = new Label(parent, SWT.NONE);
label.setText("Target:"); label.setText("Target:");
mTargetCombo = new Combo(top, SWT.READ_ONLY | SWT.DROP_DOWN); mTargetCombo = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
mTargetCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); mTargetCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mTargetCombo.addSelectionListener(new SelectionAdapter() { mTargetCombo.addSelectionListener(new SelectionAdapter() {
@Override @Override
@@ -204,15 +232,13 @@ final class AvdCreationDialog extends Dialog {
}); });
// --- sd card group // --- sd card group
label = new Label(top, SWT.NONE); label = new Label(parent, SWT.NONE);
label.setText("SD Card:"); label.setText("SD Card:");
label.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING,
gd.horizontalSpan = 2; false, false));
final Group sdCardGroup = new Group(top, SWT.NONE); final Group sdCardGroup = new Group(parent, SWT.NONE);
sdCardGroup.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); sdCardGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
gd.horizontalIndent = groupIndent;
gd.horizontalSpan = 2;
sdCardGroup.setLayout(new GridLayout(3, false)); sdCardGroup.setLayout(new GridLayout(3, false));
mSdCardSizeRadio = new Button(sdCardGroup, SWT.RADIO); mSdCardSizeRadio = new Button(sdCardGroup, SWT.RADIO);
@@ -233,8 +259,8 @@ final class AvdCreationDialog extends Dialog {
mSdCardSize.addVerifyListener(mDigitVerifier); mSdCardSize.addVerifyListener(mDigitVerifier);
mSdCardSizeCombo = new Combo(sdCardGroup, SWT.DROP_DOWN | SWT.READ_ONLY); mSdCardSizeCombo = new Combo(sdCardGroup, SWT.DROP_DOWN | SWT.READ_ONLY);
mSdCardSizeCombo.add("K"); mSdCardSizeCombo.add("KiB");
mSdCardSizeCombo.add("M"); mSdCardSizeCombo.add("MiB");
mSdCardSizeCombo.select(1); mSdCardSizeCombo.select(1);
mSdCardFileRadio = new Button(sdCardGroup, SWT.RADIO); mSdCardFileRadio = new Button(sdCardGroup, SWT.RADIO);
@@ -258,15 +284,13 @@ final class AvdCreationDialog extends Dialog {
enableSdCardWidgets(true); enableSdCardWidgets(true);
// --- skin group // --- skin group
label = new Label(top, SWT.NONE); label = new Label(parent, SWT.NONE);
label.setText("Skin:"); label.setText("Skin:");
label.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING,
gd.horizontalSpan = 2; false, false));
final Group skinGroup = new Group(top, SWT.NONE); final Group skinGroup = new Group(parent, SWT.NONE);
skinGroup.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); skinGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
gd.horizontalIndent = groupIndent;
gd.horizontalSpan = 2;
skinGroup.setLayout(new GridLayout(4, false)); skinGroup.setLayout(new GridLayout(4, false));
mSkinListRadio = new Button(skinGroup, SWT.RADIO); mSkinListRadio = new Button(skinGroup, SWT.RADIO);
@@ -283,6 +307,13 @@ final class AvdCreationDialog extends Dialog {
mSkinCombo = new Combo(skinGroup, SWT.READ_ONLY | SWT.DROP_DOWN); mSkinCombo = new Combo(skinGroup, SWT.READ_ONLY | SWT.DROP_DOWN);
mSkinCombo.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); mSkinCombo.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
gd.horizontalSpan = 3; gd.horizontalSpan = 3;
mSkinCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent arg0) {
// get the skin info
loadSkin();
}
});
mSkinSizeRadio = new Button(skinGroup, SWT.RADIO); mSkinSizeRadio = new Button(skinGroup, SWT.RADIO);
mSkinSizeRadio.setText("Size:"); mSkinSizeRadio.setText("Size:");
@@ -302,9 +333,60 @@ final class AvdCreationDialog extends Dialog {
mSkinListRadio.setSelection(true); mSkinListRadio.setSelection(true);
enableSkinWidgets(true); enableSkinWidgets(true);
// --- end skin group // --- hardware group
label = new Label(parent, SWT.NONE);
label.setText("Hardware:");
label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING,
false, false));
mForceCreation = new Button(top, SWT.CHECK); final Group hwGroup = new Group(parent, SWT.NONE);
hwGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
hwGroup.setLayout(new GridLayout(2, false));
createHardwareTable(hwGroup);
// composite for the side buttons
Composite hwButtons = new Composite(hwGroup, SWT.NONE);
hwButtons.setLayoutData(new GridData(GridData.FILL_VERTICAL));
hwButtons.setLayout(gl = new GridLayout(1, false));
gl.marginHeight = gl.marginWidth = 0;
Button b = new Button(hwButtons, SWT.PUSH | SWT.FLAT);
b.setText("New...");
b.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
b.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
HardwarePropertyChooser dialog = new HardwarePropertyChooser(parent.getShell(),
mHardwareMap, mProperties.keySet());
if (dialog.open() == Window.OK) {
HardwareProperty choice = dialog.getProperty();
if (choice != null) {
mProperties.put(choice.getName(), choice.getDefault());
mHardwareViewer.refresh();
}
}
}
});
mDeleteHardwareProp = new Button(hwButtons, SWT.PUSH | SWT.FLAT);
mDeleteHardwareProp.setText("Delete");
mDeleteHardwareProp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mDeleteHardwareProp.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent arg0) {
ISelection selection = mHardwareViewer.getSelection();
if (selection instanceof IStructuredSelection) {
String hwName = (String)((IStructuredSelection)selection).getFirstElement();
mProperties.remove(hwName);
mHardwareViewer.refresh();
}
}
});
mDeleteHardwareProp.setEnabled(false);
// --- end hardware group
mForceCreation = new Button(parent, SWT.CHECK);
mForceCreation.setText("Force create"); mForceCreation.setText("Force create");
mForceCreation.setToolTipText("Select this to override any existing AVD"); mForceCreation.setToolTipText("Select this to override any existing AVD");
mForceCreation.setLayoutData(new GridData(GridData.END, GridData.CENTER, mForceCreation.setLayoutData(new GridData(GridData.END, GridData.CENTER,
@@ -313,14 +395,13 @@ final class AvdCreationDialog extends Dialog {
mForceCreation.addSelectionListener(validateListener); mForceCreation.addSelectionListener(validateListener);
// add a separator to separate from the ok/cancel button // add a separator to separate from the ok/cancel button
label = new Label(top, SWT.SEPARATOR | SWT.HORIZONTAL); label = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
label.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1)); label.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1));
// add stuff for the error display // add stuff for the error display
mStatusComposite = new Composite(top, SWT.NONE); mStatusComposite = new Composite(parent, SWT.NONE);
mStatusComposite.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, mStatusComposite.setLayoutData(new GridData(GridData.FILL, GridData.CENTER,
true, false, 3, 1)); true, false, 3, 1));
GridLayout gl;
mStatusComposite.setLayout(gl = new GridLayout(2, false)); mStatusComposite.setLayout(gl = new GridLayout(2, false));
gl.marginHeight = gl.marginWidth = 0; gl.marginHeight = gl.marginWidth = 0;
@@ -332,9 +413,141 @@ final class AvdCreationDialog extends Dialog {
mStatusLabel.setText(" \n "); //$NON-NLS-1$ mStatusLabel.setText(" \n "); //$NON-NLS-1$
reloadTargetCombo(); reloadTargetCombo();
}
applyDialogFont(top); /**
return top; * Creates the UI for the hardware properties table.
* This creates the {@link Table}, and several viewers ({@link TableViewer},
* {@link TableViewerColumn}) and adds edit support for the 2nd column
*/
private void createHardwareTable(Composite parent) {
final Table hardwareTable = new Table(parent, SWT.SINGLE | SWT.FULL_SELECTION);
GridData gd = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
gd.widthHint = 200;
gd.heightHint = 100;
hardwareTable.setLayoutData(gd);
hardwareTable.setHeaderVisible(true);
hardwareTable.setLinesVisible(true);
// -- Table viewer
mHardwareViewer = new TableViewer(hardwareTable);
mHardwareViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
// it's a single selection mode, we can just access the selection index
// from the table directly.
mDeleteHardwareProp.setEnabled(hardwareTable.getSelectionIndex() != -1);
}
});
// only a content provider. Use viewers per column below (for editing support)
mHardwareViewer.setContentProvider(new IStructuredContentProvider() {
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// we can just ignore this. we just use mProperties directly.
}
public Object[] getElements(Object arg0) {
return mProperties.keySet().toArray();
}
public void dispose() {
// pass
}
});
// -- column 1: prop abstract name
TableColumn col1 = new TableColumn(hardwareTable, SWT.LEFT);
col1.setText("Property");
col1.setWidth(150);
TableViewerColumn tvc1 = new TableViewerColumn(mHardwareViewer, col1);
tvc1.setLabelProvider(new CellLabelProvider() {
@Override
public void update(ViewerCell cell) {
HardwareProperty prop = mHardwareMap.get(cell.getElement());
cell.setText(prop != null ? prop.getAbstract() : "");
}
});
// -- column 2: prop value
TableColumn col2 = new TableColumn(hardwareTable, SWT.LEFT);
col2.setText("Value");
col2.setWidth(50);
TableViewerColumn tvc2 = new TableViewerColumn(mHardwareViewer, col2);
tvc2.setLabelProvider(new CellLabelProvider() {
@Override
public void update(ViewerCell cell) {
String value = mProperties.get(cell.getElement());
cell.setText(value != null ? value : "");
}
});
// add editing support to the 2nd column
tvc2.setEditingSupport(new EditingSupport(mHardwareViewer) {
@Override
protected void setValue(Object element, Object value) {
String hardwareName = (String)element;
HardwareProperty property = mHardwareMap.get(hardwareName);
switch (property.getType()) {
case INTEGER:
mProperties.put((String)element, (String)value);
break;
case DISKSIZE:
if (HardwareProperties.DISKSIZE_PATTERN.matcher((String)value).matches()) {
mProperties.put((String)element, (String)value);
}
break;
case BOOLEAN:
int index = (Integer)value;
mProperties.put((String)element, HardwareProperties.BOOLEAN_VALUES[index]);
break;
}
mHardwareViewer.refresh(element);
}
@Override
protected Object getValue(Object element) {
String hardwareName = (String)element;
HardwareProperty property = mHardwareMap.get(hardwareName);
String value = mProperties.get(hardwareName);
switch (property.getType()) {
case INTEGER:
// intended fall-through.
case DISKSIZE:
return value;
case BOOLEAN:
return HardwareProperties.getBooleanValueIndex(value);
}
return null;
}
@Override
protected CellEditor getCellEditor(Object element) {
String hardwareName = (String)element;
HardwareProperty property = mHardwareMap.get(hardwareName);
switch (property.getType()) {
// TODO: custom TextCellEditor that restrict input.
case INTEGER:
// intended fall-through.
case DISKSIZE:
return new TextCellEditor(hardwareTable);
case BOOLEAN:
return new ComboBoxCellEditor(hardwareTable,
HardwareProperties.BOOLEAN_VALUES,
SWT.READ_ONLY | SWT.DROP_DOWN);
}
return null;
}
@Override
protected boolean canEdit(Object element) {
String hardwareName = (String)element;
HardwareProperty property = mHardwareMap.get(hardwareName);
return property != null;
}
});
mHardwareViewer.setInput(mProperties);
} }
@Override @Override
@@ -469,6 +682,7 @@ final class AvdCreationDialog extends Dialog {
mSkinCombo.select(index); mSkinCombo.select(index);
} else { } else {
mSkinCombo.select(0); // default mSkinCombo.select(0); // default
loadSkin();
} }
} }
} }
@@ -553,6 +767,78 @@ final class AvdCreationDialog extends Dialog {
mStatusComposite.pack(true); mStatusComposite.pack(true);
} }
private void loadSkin() {
int targetIndex = mTargetCombo.getSelectionIndex();
if (targetIndex < 0) {
return;
}
// resolve the target.
String targetName = mTargetCombo.getItem(targetIndex);
IAndroidTarget target = mCurrentTargets.get(targetName);
if (target == null) {
return;
}
// get the skin name
String skinName = null;
int skinIndex = mSkinCombo.getSelectionIndex();
if (skinIndex < 0) {
return;
} else if (skinIndex == 0) { // default skin for the target
skinName = target.getDefaultSkin();
} else {
skinName = mSkinCombo.getItem(skinIndex);
}
// load the skin properties
String path = target.getPath(IAndroidTarget.SKINS);
File skin = new File(path, skinName);
if (skin.isDirectory() == false && target.isPlatform() == false) {
// it's possible the skin is in the parent target
path = target.getParent().getPath(IAndroidTarget.SKINS);
skin = new File(path, skinName);
}
if (skin.isDirectory() == false) {
return;
}
// now get the hardware.ini from the add-on (if applicable) and from the skin
// (if applicable)
HashMap<String, String> hardwareValues = new HashMap<String, String>();
if (target.isPlatform() == false) {
File targetHardwareFile = new File(target.getLocation(), AvdManager.HARDWARE_INI);
if (targetHardwareFile.isFile()) {
Map<String, String> targetHardwareConfig = SdkManager.parsePropertyFile(
targetHardwareFile, null /*log*/);
if (targetHardwareConfig != null) {
hardwareValues.putAll(targetHardwareConfig);
}
}
}
// from the skin
File skinHardwareFile = new File(skin, AvdManager.HARDWARE_INI);
if (skinHardwareFile.isFile()) {
Map<String, String> skinHardwareConfig = SdkManager.parsePropertyFile(
skinHardwareFile, null /*log*/);
if (skinHardwareConfig != null) {
hardwareValues.putAll(skinHardwareConfig);
}
}
// now set those values in the list of properties for the AVD.
// We just check that none of those properties have been edited by the user yet.
for (Entry<String, String> entry : hardwareValues.entrySet()) {
if (mEditedProperties.contains(entry.getKey()) == false) {
mProperties.put(entry.getKey(), entry.getValue());
}
}
mHardwareViewer.refresh();
}
/** /**
* Creates an AVD from the values in the UI. Called when the user presses the OK button. * Creates an AVD from the values in the UI. Called when the user presses the OK button.
*/ */
@@ -633,7 +919,7 @@ final class AvdCreationDialog extends Dialog {
target, target,
skinName, skinName,
sdName, sdName,
null, // hardwareConfig, mProperties,
force, force,
log); log);

View File

@@ -0,0 +1,119 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.sdkuilib.internal.widgets;
import com.android.sdklib.internal.avd.HardwareProperties.HardwareProperty;
import com.android.sdkuilib.ui.GridDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
/**
* Dialog to choose a hardware property
*/
class HardwarePropertyChooser extends GridDialog {
private final Map<String, HardwareProperty> mProperties;
private final Collection<String> mExceptProperties;
private HardwareProperty mChosenProperty;
private Label mTypeLabel;
private Label mDescriptionLabel;
HardwarePropertyChooser(Shell parentShell, Map<String, HardwareProperty> properties,
Collection<String> exceptProperties) {
super(parentShell, 2, false);
mProperties = properties;
mExceptProperties = exceptProperties;
}
public HardwareProperty getProperty() {
return mChosenProperty;
}
@Override
public void createDialogContent(Composite parent) {
Label l = new Label(parent, SWT.NONE);
l.setText("Property:");
final Combo c = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY);
// simple list for index->name resolution.
final ArrayList<String> indexToName = new ArrayList<String>();
for (Entry<String, HardwareProperty> entry : mProperties.entrySet()) {
if (mExceptProperties.contains(entry.getKey()) == false) {
c.add(entry.getValue().getAbstract());
indexToName.add(entry.getKey());
}
}
boolean hasValues = true;
if (indexToName.size() == 0) {
hasValues = false;
c.add("No properties");
c.select(0);
c.setEnabled(false);
}
c.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
int index = c.getSelectionIndex();
String name = indexToName.get(index);
processSelection(name, true /* pack */);
}
});
l = new Label(parent, SWT.NONE);
l.setText("Type:");
mTypeLabel = new Label(parent, SWT.NONE);
l = new Label(parent, SWT.NONE);
l.setText("Description:");
mDescriptionLabel = new Label(parent, SWT.NONE);
if (hasValues) {
c.select(0);
processSelection(indexToName.get(0), false /* pack */);
}
}
private void processSelection(String name, boolean pack) {
mChosenProperty = mProperties.get(name);
mTypeLabel.setText(mChosenProperty.getType().getValue());
String desc = mChosenProperty.getDescription();
if (desc != null) {
mDescriptionLabel.setText(mChosenProperty.getDescription());
} else {
mDescriptionLabel.setText("N/A");
}
if (pack) {
getShell().pack();
}
}
}