auto import from //depot/cupcake/@137055

This commit is contained in:
The Android Open Source Project
2009-03-02 22:54:20 -08:00
parent 74a996a2c7
commit b8747bc7b1
91 changed files with 3663 additions and 838 deletions

View File

@@ -23,9 +23,9 @@ set prog=%~f0
rem Grab current directory before we change it
set workdir=%cd%
rem Change current directory to where ddms is, to avoid issues with directories
rem containing whitespaces.
cd %~dp0
rem Change current directory and drive to where the script is, to avoid
rem issues with directories containing whitespaces.
cd /d %~dp0
set jarfile=sdkmanager.jar
set frameworkdir=

View File

@@ -383,24 +383,28 @@ class Main {
*/
private void displayAvdList() {
try {
AvdManager avdManager = new AvdManager(mSdkManager, null /* sdklog */);
AvdManager avdManager = new AvdManager(mSdkManager, mSdkLog);
mSdkLog.printf("Available Android Virtual Devices:\n");
int index = 1;
for (AvdInfo info : avdManager.getAvds()) {
mSdkLog.printf("[%d] %s\n", index, info.getName());
mSdkLog.printf(" Path: %s\n", info.getPath());
AvdInfo[] avds = avdManager.getAvds();
for (int index = 0 ; index < avds.length ; index++) {
AvdInfo info = avds[index];
if (index > 0) {
mSdkLog.printf("---------\n");
}
mSdkLog.printf(" Name: %s\n", info.getName());
mSdkLog.printf(" Path: %s\n", info.getPath());
// get the target of the AVD
IAndroidTarget target = info.getTarget();
if (target.isPlatform()) {
mSdkLog.printf(" Target: %s (API level %d)\n", target.getName(),
mSdkLog.printf(" Target: %s (API level %d)\n", target.getName(),
target.getApiVersionNumber());
} else {
mSdkLog.printf(" Target: %s (%s)\n", target.getName(), target
mSdkLog.printf(" Target: %s (%s)\n", target.getName(), target
.getVendor());
mSdkLog.printf(" Based on Android %s (API level %d)\n", target
mSdkLog.printf(" Based on Android %s (API level %d)\n", target
.getApiVersionName(), target.getApiVersionNumber());
}
@@ -408,17 +412,15 @@ class Main {
Map<String, String> properties = info.getProperties();
String skin = properties.get(AvdManager.AVD_INI_SKIN_NAME);
if (skin != null) {
mSdkLog.printf(" Skin: %s\n", skin);
mSdkLog.printf(" Skin: %s\n", skin);
}
String sdcard = properties.get(AvdManager.AVD_INI_SDCARD_SIZE);
if (sdcard == null) {
sdcard = properties.get(AvdManager.AVD_INI_SDCARD_PATH);
}
if (sdcard != null) {
mSdkLog.printf(" Sdcard: %s\n", sdcard);
mSdkLog.printf(" Sdcard: %s\n", sdcard);
}
index++;
}
} catch (AndroidLocationException e) {
errorAndExit(e.getMessage());
@@ -499,7 +501,7 @@ class Main {
// Is it NNNxMMM?
if (!valid) {
valid = skin.matches("[0-9]{2,}x[0-9]{2,}");
valid = AvdManager.NUMERIC_SKIN_SIZE.matcher(skin).matches();
}
if (!valid) {

View File

@@ -103,6 +103,8 @@ public final class SdkConstants {
public final static String FD_ASSETS = "assets"; //$NON-NLS-1$
/** Default source folder name, i.e. "src" */
public final static String FD_SOURCES = "src"; //$NON-NLS-1$
/** Default generated source folder name, i.e. "gen" */
public final static String FD_GEN_SOURCES = "gen"; //$NON-NLS-1$
/** Default native library folder name inside the project, i.e. "libs"
* While the folder inside the .apk is "lib", we call that one libs because
* that's what we use in ant for both .jar and .so and we need to make the 2 development ways

View File

@@ -55,6 +55,12 @@ public final class AvdManager {
public final static String AVD_INI_IMAGES_1 = "image.sysdir.1";
public final static String AVD_INI_IMAGES_2 = "image.sysdir.2";
/**
* Pattern to match pixel-sized skin "names", e.g. "320x480".
*/
public final static Pattern NUMERIC_SKIN_SIZE = Pattern.compile("[0-9]{2,}x[0-9]{2,}");
private final static String USERDATA_IMG = "userdata.img";
private final static String CONFIG_INI = "config.ini";
private final static String SDCARD_IMG = "sdcard.img";
@@ -255,16 +261,21 @@ public final class AvdManager {
skinName = target.getDefaultSkin();
}
// get the path of the skin (relative to the SDK)
// assume skin name is valid
String skinPath = getSkinRelativePath(skinName, target, log);
if (skinPath == null) {
needCleanup = true;
return null;
}
if (NUMERIC_SKIN_SIZE.matcher(skinName).matches()) {
// Skin name is an actual screen resolution, no skin.path
values.put(AVD_INI_SKIN_NAME, skinName);
} else {
// get the path of the skin (relative to the SDK)
// assume skin name is valid
String skinPath = getSkinRelativePath(skinName, target, log);
if (skinPath == null) {
needCleanup = true;
return null;
}
values.put(AVD_INI_SKIN_PATH, skinPath);
values.put(AVD_INI_SKIN_NAME, skinName);
values.put(AVD_INI_SKIN_PATH, skinPath);
values.put(AVD_INI_SKIN_NAME, skinName);
}
if (sdcard != null) {
File sdcardFile = new File(sdcard);

View File

@@ -25,24 +25,30 @@ import java.util.Map.Entry;
* Helper class to read and write Apk Configuration into a {@link ProjectProperties} file.
*/
public class ApkConfigurationHelper {
/** Prefix for property names for config definition. This prevents having config named
* after other valid properties such as "target". */
final static String CONFIG_PREFIX = "apk-config-";
/**
* Reads the Apk Configurations from a {@link ProjectProperties} file and returns them as a map.
* <p/>If there are no defined configurations, the returned map will be empty.
* @return a map of apk configurations. The map contains (name, filter) where name is
* the name of the configuration (a-zA-Z0-9 only), and filter is the comma separated list of
* resource configuration to include in the apk (see aapt -c)
*/
public static Map<String, String> getConfigs(ProjectProperties properties) {
HashMap<String, String> configMap = new HashMap<String, String>();
// get the list of configs.
String configList = properties.getProperty(ProjectProperties.PROPERTY_CONFIGS);
String configList = properties.getProperty(ProjectProperties.PROPERTY_APK_CONFIGS);
if (configList != null) {
// this is a comma separated list
String[] configs = configList.split(","); //$NON-NLS-1$
// read the value of each config and store it in a map
for (String config : configs) {
String configValue = properties.getProperty(config);
config = config.trim();
String configValue = properties.getProperty(CONFIG_PREFIX + config);
if (configValue != null) {
configMap.put(config, configValue);
}
@@ -54,6 +60,10 @@ public class ApkConfigurationHelper {
/**
* Writes the Apk Configurations from a given map into a {@link ProjectProperties}.
* @param properties the {@link ProjectProperties} in which to store the apk configurations.
* @param configMap a map of apk configurations. The map contains (name, filter) where name is
* the name of the configuration (a-zA-Z0-9 only), and filter is the comma separated list of
* resource configuration to include in the apk (see aapt -c)
* @return true if the {@link ProjectProperties} contained Apk Configuration that were not
* present in the map.
*/
@@ -62,17 +72,20 @@ public class ApkConfigurationHelper {
// in case a config was removed.
// get the list of configs.
String configList = properties.getProperty(ProjectProperties.PROPERTY_CONFIGS);
// this is a comma separated list
String[] configs = configList.split(","); //$NON-NLS-1$
String configList = properties.getProperty(ProjectProperties.PROPERTY_APK_CONFIGS);
boolean hasRemovedConfig = false;
for (String config : configs) {
if (configMap.containsKey(config) == false) {
hasRemovedConfig = true;
properties.removeProperty(config);
if (configList != null) {
// this is a comma separated list
String[] configs = configList.split(","); //$NON-NLS-1$
for (String config : configs) {
config = config.trim();
if (configMap.containsKey(config) == false) {
hasRemovedConfig = true;
properties.removeProperty(CONFIG_PREFIX + config);
}
}
}
@@ -84,9 +97,9 @@ public class ApkConfigurationHelper {
sb.append(",");
}
sb.append(entry.getKey());
properties.setProperty(entry.getKey(), entry.getValue());
properties.setProperty(CONFIG_PREFIX + entry.getKey(), entry.getValue());
}
properties.setProperty(ProjectProperties.PROPERTY_CONFIGS, sb.toString());
properties.setProperty(ProjectProperties.PROPERTY_APK_CONFIGS, sb.toString());
return hasRemovedConfig;
}

View File

@@ -209,7 +209,7 @@ public class ProjectCreator {
}
// create the source folder and the java package folders.
final String srcFolderPath = SdkConstants.FD_SOURCES + File.separator + packagePath;
String srcFolderPath = SdkConstants.FD_SOURCES + File.separator + packagePath;
File sourceFolder = createDirs(projectFolder, srcFolderPath);
String javaTemplate = "java_file.template";
String activityFileName = activityName + ".java";
@@ -220,6 +220,10 @@ public class ProjectCreator {
installTemplate(javaTemplate, new File(sourceFolder, activityFileName),
keywords, target);
// create the generate source folder
srcFolderPath = SdkConstants.FD_GEN_SOURCES + File.separator + packagePath;
sourceFolder = createDirs(projectFolder, srcFolderPath);
// create other useful folders
File resourceFodler = createDirs(projectFolder, SdkConstants.FD_RESOURCES);
createDirs(projectFolder, SdkConstants.FD_OUTPUT);

View File

@@ -33,7 +33,7 @@ import java.util.Map.Entry;
public final class ProjectProperties {
/** The property name for the project target */
public final static String PROPERTY_TARGET = "target";
public final static String PROPERTY_CONFIGS = "configs";
public final static String PROPERTY_APK_CONFIGS = "apk-configurations";
public final static String PROPERTY_SDK = "sdk-location";
public static enum PropertyType {
@@ -98,7 +98,19 @@ public final class ProjectProperties {
// 1-------10--------20--------30--------40--------50--------60--------70--------80
COMMENT_MAP.put(PROPERTY_TARGET,
"# Project target.\n");
COMMENT_MAP.put(PROPERTY_SDK, "# location of the SDK. This is only used by Ant\n" +
COMMENT_MAP.put(PROPERTY_APK_CONFIGS,
"# apk configurations. This property allows creation of APK files with limited\n" +
"# resources. For example, if your application contains many locales and\n" +
"# you wish to release multiple smaller apks instead of a large one, you can\n" +
"# define configuration to create apks with limited language sets.\n" +
"# Format is a comma separated list of configuration names. For each\n" +
"# configuration, a property will declare the resource configurations to\n" +
"# include. Example:\n" +
"# " + PROPERTY_APK_CONFIGS +"=european,northamerica\n" +
"# " + ApkConfigurationHelper.CONFIG_PREFIX + "european=en,fr,it,de,es\n" +
"# " + ApkConfigurationHelper.CONFIG_PREFIX + "northamerica=en,es\n");
COMMENT_MAP.put(PROPERTY_SDK,
"# location of the SDK. This is only used by Ant\n" +
"# For customization when using a Version Control System, please read the\n" +
"# header note.\n");
}

View File

@@ -0,0 +1,177 @@
/*
* 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;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
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.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
/**
* Edit dialog to create/edit APK configuration. The dialog displays 2 text fields for the config
* name and its filter.
*/
class ApkConfigEditDialog extends Dialog implements ModifyListener, VerifyListener {
private String mName;
private String mFilter;
private Text mNameField;
private Text mFilterField;
private Button mOkButton;
/**
* Creates an edit dialog with optional initial values for the name and filter.
* @param name optional value for the name. Can be null.
* @param filter optional value for the filter. Can be null.
* @param parentShell the parent shell.
*/
protected ApkConfigEditDialog(String name, String filter, Shell parentShell) {
super(parentShell);
mName = name;
mFilter = filter;
}
/**
* Returns the name of the config. This is only valid if the user clicked OK and {@link #open()}
* returned {@link Window#OK}
*/
public String getName() {
return mName;
}
/**
* Returns the filter for the config. This is only valid if the user clicked OK and
* {@link #open()} returned {@link Window#OK}
*/
public String getFilter() {
return mFilter;
}
@Override
protected Control createContents(Composite parent) {
Control control = super.createContents(parent);
mOkButton = getButton(IDialogConstants.OK_ID);
validateButtons();
return control;
}
@Override
protected Control createDialogArea(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
GridLayout layout;
composite.setLayout(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);
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
Label l = new Label(composite, SWT.NONE);
l.setText("Name");
mNameField = new Text(composite, SWT.BORDER);
mNameField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mNameField.addVerifyListener(this);
if (mName != null) {
mNameField.setText(mName);
}
mNameField.addModifyListener(this);
l = new Label(composite, SWT.NONE);
l.setText("Filter");
mFilterField = new Text(composite, SWT.BORDER);
mFilterField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
if (mFilter != null) {
mFilterField.setText(mFilter);
}
mFilterField.addVerifyListener(this);
mFilterField.addModifyListener(this);
applyDialogFont(composite);
return composite;
}
/**
* Validates the OK button based on the content of the 2 text fields.
*/
private void validateButtons() {
mOkButton.setEnabled(mNameField.getText().trim().length() > 0 &&
mFilterField.getText().trim().length() > 0);
}
@Override
protected void okPressed() {
mName = mNameField.getText();
mFilter = mFilterField.getText().trim();
super.okPressed();
}
/**
* Callback for text modification in the 2 text fields.
*/
public void modifyText(ModifyEvent e) {
validateButtons();
}
/**
* Callback to ensure the content of the text field are proper.
*/
public void verifyText(VerifyEvent e) {
Text source = ((Text)e.getSource());
if (source == mNameField) {
// check for a-zA-Z0-9.
final String text = e.text;
final int len = text.length();
for (int i = 0 ; i < len; i++) {
char letter = text.charAt(i);
if (letter > 255 || Character.isLetterOrDigit(letter) == false) {
e.doit = false;
return;
}
}
} else if (source == mFilterField) {
// we can't validate the content as its typed, but we can at least ensure the characters
// are valid. Same as mNameFiled + the comma.
final String text = e.text;
final int len = text.length();
for (int i = 0 ; i < len; i++) {
char letter = text.charAt(i);
if (letter > 255 || (Character.isLetterOrDigit(letter) == false && letter != ',')) {
e.doit = false;
return;
}
}
}
}
}

View File

@@ -0,0 +1,211 @@
/*
* 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;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
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.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.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* The APK Configuration widget is a table that is added to the given parent composite.
* <p/>
* To use, create it using {@link #ApkConfigWidget(Composite)} then
* call {@link #fillTable(Map) to set the initial list of configurations.
*/
public class ApkConfigWidget {
private final static int INDEX_NAME = 0;
private final static int INDEX_FILTER = 1;
private Table mApkConfigTable;
private Button mEditButton;
private Button mDelButton;
public ApkConfigWidget(final Composite parent) {
final Composite apkConfigComp = new Composite(parent, SWT.NONE);
apkConfigComp.setLayoutData(new GridData(GridData.FILL_BOTH));
apkConfigComp.setLayout(new GridLayout(2, false));
mApkConfigTable = new Table(apkConfigComp, SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER);
mApkConfigTable.setHeaderVisible(true);
mApkConfigTable.setLinesVisible(true);
GridData data = new GridData();
data.grabExcessVerticalSpace = true;
data.grabExcessHorizontalSpace = true;
data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.FILL;
mApkConfigTable.setLayoutData(data);
// create the table columns
final TableColumn column0 = new TableColumn(mApkConfigTable, SWT.NONE);
column0.setText("Name");
column0.setWidth(100);
final TableColumn column1 = new TableColumn(mApkConfigTable, SWT.NONE);
column1.setText("Configuration");
column1.setWidth(100);
Composite buttonComp = new Composite(apkConfigComp, SWT.NONE);
buttonComp.setLayoutData(new GridData(GridData.FILL_VERTICAL));
GridLayout gl;
buttonComp.setLayout(gl = new GridLayout(1, false));
gl.marginHeight = gl.marginWidth = 0;
Button newButton = new Button(buttonComp, SWT.PUSH | SWT.FLAT);
newButton.setText("New...");
newButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mEditButton = new Button(buttonComp, SWT.PUSH | SWT.FLAT);
mEditButton.setText("Edit...");
mEditButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mDelButton = new Button(buttonComp, SWT.PUSH | SWT.FLAT);
mDelButton.setText("Delete");
mDelButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
newButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ApkConfigEditDialog dlg = new ApkConfigEditDialog(null /*name*/, null /*filter*/,
apkConfigComp.getShell());
if (dlg.open() == Dialog.OK) {
TableItem item = new TableItem(mApkConfigTable, SWT.NONE);
item.setText(INDEX_NAME, dlg.getName());
item.setText(INDEX_FILTER, dlg.getFilter());
onSelectionChanged();
}
}
});
mEditButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
// get the current selection (single mode so we don't care about any item beyond
// index 0).
TableItem[] items = mApkConfigTable.getSelection();
if (items.length != 0) {
ApkConfigEditDialog dlg = new ApkConfigEditDialog(
items[0].getText(INDEX_NAME), items[0].getText(INDEX_FILTER),
apkConfigComp.getShell());
if (dlg.open() == Dialog.OK) {
items[0].setText(INDEX_NAME, dlg.getName());
items[0].setText(INDEX_FILTER, dlg.getFilter());
}
}
}
});
mDelButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
// get the current selection (single mode so we don't care about any item beyond
// index 0).
int[] indices = mApkConfigTable.getSelectionIndices();
if (indices.length != 0) {
TableItem item = mApkConfigTable.getItem(indices[0]);
if (MessageDialog.openQuestion(parent.getShell(),
"Apk Configuration deletion",
String.format(
"Are you sure you want to delete configuration '%1$s'?",
item.getText(INDEX_NAME)))) {
// delete the item.
mApkConfigTable.remove(indices[0]);
onSelectionChanged();
}
}
}
});
// Add a listener to resize the column to the full width of the table
mApkConfigTable.addControlListener(new ControlAdapter() {
@Override
public void controlResized(ControlEvent e) {
Rectangle r = mApkConfigTable.getClientArea();
column0.setWidth(r.width * 30 / 100); // 30%
column1.setWidth(r.width * 70 / 100); // 70%
}
});
// add a selection listener on the table, to enable/disable buttons.
mApkConfigTable.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
onSelectionChanged();
}
});
}
public void fillTable(Map<String, String> apkConfigMap) {
// get the names in a list so that we can sort them.
if (apkConfigMap != null) {
Set<String> keys = apkConfigMap.keySet();
String[] keyArray = keys.toArray(new String[keys.size()]);
Arrays.sort(keyArray);
for (String key : keyArray) {
TableItem item = new TableItem(mApkConfigTable, SWT.NONE);
item.setText(INDEX_NAME, key);
item.setText(INDEX_FILTER, apkConfigMap.get(key));
}
}
onSelectionChanged();
}
public Map<String, String> getApkConfigs() {
// go through all the items from the table and fill a new map
HashMap<String, String> map = new HashMap<String, String>();
TableItem[] items = mApkConfigTable.getItems();
for (TableItem item : items) {
map.put(item.getText(INDEX_NAME), item.getText(INDEX_FILTER));
}
return map;
}
/**
* Handles table selection changes.
*/
private void onSelectionChanged() {
if (mApkConfigTable.getSelectionCount() > 0) {
mEditButton.setEnabled(true);
mDelButton.setEnabled(true);
} else {
mEditButton.setEnabled(false);
mDelButton.setEnabled(false);
}
}
}

View File

@@ -48,32 +48,57 @@ import java.util.ArrayList;
*/
public class SdkTargetSelector {
private final IAndroidTarget[] mTargets;
private IAndroidTarget[] mTargets;
private final boolean mAllowSelection;
private final boolean mAllowMultipleSelection;
private SelectionListener mSelectionListener;
private Table mTable;
private Label mDescription;
private Composite mInnerGroup;
/**
* Creates a new SDK Target Selector.
*
* @param parent The parent composite where the selector will be added.
* @param targets The list of targets. This is <em>not</em> copied, the caller must not modify.
* Targets can be null or an empty array, in which case the table is disabled.
* @param allowMultipleSelection True if more than one SDK target can be selected at the same
* time.
*/
public SdkTargetSelector(Composite parent, IAndroidTarget[] targets,
boolean allowMultipleSelection) {
this(parent, targets, true /*allowSelection*/, allowMultipleSelection);
}
/**
* Creates a new SDK Target Selector.
*
* @param parent The parent composite where the selector will be added.
* @param targets The list of targets. This is <em>not</em> copied, the caller must not modify.
* Targets can be null or an empty array, in which case the table is disabled.
* @param allowSelection True if selection is enabled.
* @param allowMultipleSelection True if more than one SDK target can be selected at the same
* time.
* time. Used only if allowSelection is true.
*/
public SdkTargetSelector(Composite parent, IAndroidTarget[] targets,
boolean allowSelection,
boolean allowMultipleSelection) {
mTargets = targets;
// Layout has 1 column
Composite group = new Composite(parent, SWT.NONE);
group.setLayout(new GridLayout());
group.setLayoutData(new GridData(GridData.FILL_BOTH));
group.setFont(parent.getFont());
mInnerGroup = new Composite(parent, SWT.NONE);
mInnerGroup.setLayout(new GridLayout());
mInnerGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
mInnerGroup.setFont(parent.getFont());
mAllowSelection = allowSelection;
mAllowMultipleSelection = allowMultipleSelection;
mTable = new Table(group, SWT.CHECK | SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER);
int style = SWT.BORDER;
if (allowSelection) {
style |= SWT.CHECK | SWT.FULL_SELECTION;
}
if (!mAllowMultipleSelection) {
style |= SWT.SINGLE;
}
mTable = new Table(mInnerGroup, style);
mTable.setHeaderVisible(true);
mTable.setLinesVisible(false);
@@ -84,7 +109,7 @@ public class SdkTargetSelector {
data.verticalAlignment = GridData.FILL;
mTable.setLayoutData(data);
mDescription = new Label(group, SWT.WRAP);
mDescription = new Label(mInnerGroup, SWT.WRAP);
mDescription.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
// create the table columns
@@ -93,15 +118,26 @@ public class SdkTargetSelector {
final TableColumn column1 = new TableColumn(mTable, SWT.NONE);
column1.setText("Vendor");
final TableColumn column2 = new TableColumn(mTable, SWT.NONE);
column2.setText("API Level");
column2.setText("Version");
final TableColumn column3 = new TableColumn(mTable, SWT.NONE);
column3.setText("SDK");
column3.setText("API Level");
adjustColumnsWidth(mTable, column0, column1, column2, column3);
setupSelectionListener(mTable);
fillTable(mTable);
setTargets(targets);
setupTooltip(mTable);
}
/**
* Returns the layout data of the inner composite widget that contains the target selector.
* By default the layout data is set to a {@link GridData} with a {@link GridData#FILL_BOTH}
* mode.
* <p/>
* This can be useful if you want to change the {@link GridData#horizontalSpan} for example.
*/
public Object getLayoutData() {
return mInnerGroup.getLayoutData();
}
/**
* Returns the list of known targets.
@@ -112,6 +148,16 @@ public class SdkTargetSelector {
return mTargets;
}
/**
* Changes the targets of the SDK Target Selector.
*
* @param targets The list of targets. This is <em>not</em> copied, the caller must not modify.
*/
public void setTargets(IAndroidTarget[] targets) {
mTargets = targets;
fillTable(mTable);
}
/**
* Sets a selection listener. Set it to null to remove it.
* The listener will be called <em>after</em> this table processed its selection
@@ -139,6 +185,10 @@ public class SdkTargetSelector {
* @return true if the target could be selected, false otherwise.
*/
public boolean setSelection(IAndroidTarget target) {
if (!mAllowSelection) {
return false;
}
boolean found = false;
boolean modified = false;
for (TableItem i : mTable.getItems()) {
@@ -224,6 +274,10 @@ public class SdkTargetSelector {
* double-clicked (aka "the default selection").
*/
private void setupSelectionListener(final Table table) {
if (!mAllowSelection) {
return;
}
// Add a selection listener that will check/uncheck items when they are double-clicked
table.addSelectionListener(new SelectionListener() {
/** Default selection means double-click on "most" platforms */
@@ -281,6 +335,9 @@ public class SdkTargetSelector {
* </ul>
*/
private void fillTable(final Table table) {
table.removeAll();
if (mTargets != null && mTargets.length > 0) {
table.setEnabled(true);
for (IAndroidTarget target : mTargets) {