diff --git a/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java b/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java index c88186e5d..d90d2960e 100644 --- a/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java +++ b/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java @@ -239,6 +239,9 @@ class Main { */ private void showMainWindow() { try { + // display a message talking about the command line version + System.out.printf("No command line parameters provided, launching UI.\n" + + "See 'android --help' for operations from the command line.\n"); UpdaterWindow window = new UpdaterWindow( mSdkLog, mOsSdkFolder, diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java index d818846e8..dbd1f838b 100644 --- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java +++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java @@ -311,7 +311,7 @@ public final class AvdManager { private final ArrayList mAllAvdList = new ArrayList(); private AvdInfo[] mValidAvdList; private AvdInfo[] mBrokenAvdList; - private final SdkManager mSdk; + private final SdkManager mSdkManager; /** * TODO remove this field. Each caller should give its own logger to the methods @@ -323,12 +323,19 @@ public final class AvdManager { */ private ISdkLog mSdkLog; - public AvdManager(SdkManager sdk, ISdkLog sdkLog) throws AndroidLocationException { - mSdk = sdk; + public AvdManager(SdkManager sdkManager, ISdkLog sdkLog) throws AndroidLocationException { + mSdkManager = sdkManager; mSdkLog = sdkLog; buildAvdList(mAllAvdList); } + /** + * Returns the {@link SdkManager} associated with the {@link AvdManager}. + */ + public SdkManager getSdkManager() { + return mSdkManager; + } + /** * Changes the current {@link ISdkLog}. * @@ -407,7 +414,7 @@ public final class AvdManager { } } else { synchronized (mAllAvdList) { - for (AvdInfo info : getValidAvds()) { + for (AvdInfo info : mAllAvdList) { if (info.getName().equals(name)) { return info; } @@ -558,7 +565,7 @@ public final class AvdManager { String path = sdcardFile.getAbsolutePath(); // execute mksdcard with the proper parameters. - File toolsFolder = new File(mSdk.getLocation(), SdkConstants.FD_TOOLS); + File toolsFolder = new File(mSdkManager.getLocation(), SdkConstants.FD_TOOLS); File mkSdCard = new File(toolsFolder, SdkConstants.mkSdCardCmdName()); if (mkSdCard.isFile() == false) { @@ -712,7 +719,7 @@ public final class AvdManager { String imageFullPath = target.getPath(IAndroidTarget.IMAGES); // make this path relative to the SDK location - String sdkLocation = mSdk.getLocation(); + String sdkLocation = mSdkManager.getLocation(); if (imageFullPath.startsWith(sdkLocation) == false) { // this really really should not happen. assert false; @@ -757,7 +764,7 @@ public final class AvdManager { String path = skin.getAbsolutePath(); // make this path relative to the SDK location - String sdkLocation = mSdk.getLocation(); + String sdkLocation = mSdkManager.getLocation(); if (path.startsWith(sdkLocation) == false) { // this really really should not happen. mSdkLog.error(null, "Target location is not inside the SDK."); @@ -841,9 +848,9 @@ public final class AvdManager { File f = avdInfo.getIniFile(); if (f != null && f.exists()) { - log.printf("Deleting file %1$s", f.getCanonicalPath()); + log.printf("Deleting file %1$s\n", f.getCanonicalPath()); if (!f.delete()) { - log.error(null, "Failed to delete %1$s", f.getCanonicalPath()); + log.error(null, "Failed to delete %1$s\n", f.getCanonicalPath()); error = true; } } @@ -852,10 +859,10 @@ public final class AvdManager { if (path != null) { f = new File(path); if (f.exists()) { - log.printf("Deleting folder %1$s", f.getCanonicalPath()); + log.printf("Deleting folder %1$s\n", f.getCanonicalPath()); recursiveDelete(f); if (!f.delete()) { - log.error(null, "Failed to delete %1$s", f.getCanonicalPath()); + log.error(null, "Failed to delete %1$s\n", f.getCanonicalPath()); error = true; } } @@ -864,10 +871,10 @@ public final class AvdManager { removeAvd(avdInfo); if (error) { - log.printf("\nAVD '%1$s' deleted with errors. See errors above.", + log.printf("\nAVD '%1$s' deleted with errors. See errors above.\n", avdInfo.getName()); } else { - log.printf("\nAVD '%1$s' deleted.", avdInfo.getName()); + log.printf("\nAVD '%1$s' deleted.\n", avdInfo.getName()); return true; } @@ -1031,7 +1038,7 @@ public final class AvdManager { Map properties = null; if (targetHash != null) { - target = mSdk.getTargetFromHashString(targetHash); + target = mSdkManager.getTargetFromHashString(targetHash); } // load the AVD properties. @@ -1055,13 +1062,13 @@ public final class AvdManager { if (properties != null) { String imageSysDir = properties.get(AVD_INI_IMAGES_1); if (imageSysDir != null) { - File f = new File(mSdk.getLocation() + File.separator + imageSysDir); + File f = new File(mSdkManager.getLocation() + File.separator + imageSysDir); if (f.isDirectory() == false) { validImageSysdir = false; } else { imageSysDir = properties.get(AVD_INI_IMAGES_2); if (imageSysDir != null) { - f = new File(mSdk.getLocation() + File.separator + imageSysDir); + f = new File(mSdkManager.getLocation() + File.separator + imageSysDir); if (f.isDirectory() == false) { validImageSysdir = false; } diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java index 260541009..7d9a159f4 100755 --- a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java @@ -114,7 +114,7 @@ public class UpdaterWindowImpl { fl.marginHeight = fl.marginWidth = 5; mAndroidSdkUpdater.setMinimumSize(new Point(200, 50)); mAndroidSdkUpdater.setSize(745, 433); - mAndroidSdkUpdater.setText("Android SDK Updater"); + mAndroidSdkUpdater.setText("Android SDK"); mSashForm = new SashForm(mAndroidSdkUpdater, SWT.NONE); diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java new file mode 100644 index 000000000..6f0d85fd5 --- /dev/null +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java @@ -0,0 +1,448 @@ +/* + * 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.prefs.AndroidLocation; +import com.android.prefs.AndroidLocation.AndroidLocationException; +import com.android.sdklib.IAndroidTarget; +import com.android.sdklib.ISdkLog; +import com.android.sdklib.SdkManager; +import com.android.sdklib.internal.avd.AvdManager; +import com.android.sdklib.internal.avd.AvdManager.AvdInfo; +import com.android.sdkuilib.internal.repository.icons.ImageFactory; +import com.android.sdkuilib.internal.widgets.AvdSelector.SdkLog; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import java.io.File; +import java.util.TreeMap; + +public class AvdCreationDialog extends Dialog { + + private final AvdManager mAvdManager; + private final TreeMap mCurrentTargets = + new TreeMap(); + + private Text mAvdName; + private Combo mTargetCombo; + private Text mSdCard; + private Button mBrowseSdCard; + private Combo mSkinCombo; + private Button mForceCreation; + private Button mOkButton; + private Label mStatusIcon; + private Label mStatusLabel; + private Composite mStatusComposite; + private final ImageFactory mImageFactory; + + /** + * Callback when the AVD name is changed. + * Enables the force checkbox if the name is a duplicate. + */ + private class CreateNameModifyListener implements ModifyListener { + + public void modifyText(ModifyEvent e) { + String name = mAvdName.getText().trim(); + AvdInfo avdMatch = mAvdManager.getAvd(name, false /*validAvdOnly*/); + if (avdMatch != null) { + mForceCreation.setEnabled(true); + } else { + mForceCreation.setEnabled(false); + mForceCreation.setSelection(false); + } + + validatePage(); + } + } + + private class ValidateListener extends SelectionAdapter implements ModifyListener { + + public void modifyText(ModifyEvent e) { + validatePage(); + } + + @Override + public void widgetSelected(SelectionEvent e) { + super.widgetSelected(e); + validatePage(); + } + } + + protected AvdCreationDialog(Shell parentShell, AvdManager avdManager, + ImageFactory imageFactory) { + super(parentShell); + mAvdManager = avdManager; + mImageFactory = imageFactory; + } + + @Override + public void create() { + super.create(); + + Point p = getShell().getSize(); + p.x += 130; + getShell().setSize(p); + } + + @Override + protected Control createContents(Composite parent) { + Control control = super.createContents(parent); + getShell().setText("Create new AVD"); + + mOkButton = getButton(IDialogConstants.OK_ID); + validatePage(); + + return control; + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite top = new Composite(parent, SWT.NONE); + top.setLayoutData(new GridData(GridData.FILL_BOTH)); + top.setLayout(new GridLayout(3, false)); + + Label label = new Label(top, SWT.NONE); + label.setText("Name:"); + + mAvdName = new Text(top, SWT.BORDER); + mAvdName.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, + true, false, 2, 1)); + mAvdName.addModifyListener(new CreateNameModifyListener()); + + label = new Label(top, SWT.NONE); + label.setText("Target:"); + + mTargetCombo = new Combo(top, SWT.READ_ONLY | SWT.DROP_DOWN); + mTargetCombo.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, + true, false, 2, 1)); + mTargetCombo.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + super.widgetSelected(e); + reloadSkinCombo(); + validatePage(); + } + }); + + label = new Label(top, SWT.NONE); + label.setText("SD Card:"); + + ValidateListener validateListener = new ValidateListener(); + + mSdCard = new Text(top, SWT.BORDER); + mSdCard.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + mSdCard.addModifyListener(validateListener); + + mBrowseSdCard = new Button(top, SWT.PUSH); + mBrowseSdCard.setText("Browse..."); + mBrowseSdCard.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent arg0) { + onBrowseSdCard(); + validatePage(); + } + }); + + label = new Label(top, SWT.NONE); + label.setText("Skin"); + + mSkinCombo = new Combo(top, SWT.READ_ONLY | SWT.DROP_DOWN); + mSkinCombo.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, + true, false, 2, 1)); + + // dummies for alignment + label = new Label(top, SWT.NONE); + + mForceCreation = new Button(top, SWT.CHECK); + mForceCreation.setText("Force"); + mForceCreation.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, + true, false, 2, 1)); + mForceCreation.setEnabled(false); + mForceCreation.addSelectionListener(validateListener); + + // add a separator to separate from the ok/cancel button + label = new Label(top, SWT.SEPARATOR | SWT.HORIZONTAL); + label.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1)); + + // add stuff for the error display + mStatusComposite = new Composite(top, SWT.NONE); + mStatusComposite.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, + true, false, 3, 1)); + GridLayout gl; + mStatusComposite.setLayout(gl = new GridLayout(2, false)); + gl.marginHeight = gl.marginWidth = 0; + + mStatusIcon = new Label(mStatusComposite, SWT.NONE); + mStatusIcon.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, + false, false)); + mStatusLabel = new Label(mStatusComposite, SWT.NONE); + mStatusLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + mStatusLabel.setText(" \n "); //$NON-NLS-1$ + + reloadTargetCombo(); + + return top; + } + + @Override + protected Button createButton(Composite parent, int id, String label, boolean defaultButton) { + if (id == IDialogConstants.OK_ID) { + label = "Create AVD"; + } + + return super.createButton(parent, id, label, defaultButton); + } + + @Override + protected void okPressed() { + if (onCreate()) { + super.okPressed(); + } + } + + private void onBrowseSdCard() { + FileDialog dlg = new FileDialog(getContents().getShell(), SWT.OPEN); + dlg.setText("Choose SD Card image file."); + + String fileName = dlg.open(); + if (fileName != null) { + mSdCard.setText(fileName); + } + } + + private void reloadTargetCombo() { + String selected = null; + int index = mTargetCombo.getSelectionIndex(); + if (index >= 0) { + selected = mTargetCombo.getItem(index); + } + + mCurrentTargets.clear(); + mTargetCombo.removeAll(); + + boolean found = false; + index = -1; + + SdkManager sdkManager = mAvdManager.getSdkManager(); + if (sdkManager != null) { + for (IAndroidTarget target : sdkManager.getTargets()) { + String name = String.format("%s - %s", + target.getName(), + target.getApiVersionName()); + mCurrentTargets.put(name, target); + mTargetCombo.add(name); + if (!found) { + index++; + found = name.equals(selected); + } + } + } + + mTargetCombo.setEnabled(mCurrentTargets.size() > 0); + + if (found) { + mTargetCombo.select(index); + } + + reloadSkinCombo(); + } + + private void reloadSkinCombo() { + String selected = null; + int index = mSkinCombo.getSelectionIndex(); + if (index >= 0) { + selected = mSkinCombo.getItem(index); + } + + mSkinCombo.removeAll(); + mSkinCombo.setEnabled(false); + + index = mTargetCombo.getSelectionIndex(); + if (index >= 0) { + + String targetName = mTargetCombo.getItem(index); + + boolean found = false; + IAndroidTarget target = mCurrentTargets.get(targetName); + if (target != null) { + mSkinCombo.add(String.format("Default (%s)", target.getDefaultSkin())); + + index = -1; + for (String skin : target.getSkins()) { + mSkinCombo.add(skin); + if (!found) { + index++; + found = skin.equals(selected); + } + } + + mSkinCombo.setEnabled(true); + + if (found) { + mSkinCombo.select(index); + } else { + mSkinCombo.select(0); // default + } + } + } + } + + /** + * Validates the fields, displays errors and warnings. + * Enables the finish button if there are no errors. + */ + private void validatePage() { + String error = null; + + // Validate AVD name + String avdName = mAvdName.getText().trim(); + boolean hasAvdName = avdName.length() > 0; + if (hasAvdName && !AvdManager.RE_AVD_NAME.matcher(avdName).matches()) { + error = String.format( + "AVD name '%1$s' contains invalid characters.\nAllowed characters are: %2$s", + avdName, AvdManager.CHARS_AVD_NAME); + } + + // Validate target + if (hasAvdName && error == null && mTargetCombo.getSelectionIndex() < 0) { + error = "A target must be selected in order to create an AVD."; + } + + // Validate SDCard path or value + if (error == null) { + String sdName = mSdCard.getText().trim(); + + if (sdName.length() > 0 && + !new File(sdName).isFile() && + !AvdManager.SDCARD_SIZE_PATTERN.matcher(sdName).matches()) { + error = "SD Card must be either a file path or a size\nsuch as 128K or 64M."; + } + } + + // Check for duplicate AVD name + if (hasAvdName && error == null) { + AvdInfo avdMatch = mAvdManager.getAvd(avdName, false /*validAvdOnly*/); + if (avdMatch != null && !mForceCreation.getSelection()) { + error = String.format( + "The AVD name '%s' is already used.\n" + + "Check \"Force\" to override existing AVD.", + avdName); + } + } + + // Validate the create button + boolean can_create = hasAvdName && error == null; + if (can_create) { + can_create &= mTargetCombo.getSelectionIndex() >= 0; + } + mOkButton.setEnabled(can_create); + + // -- update UI + if (error != null) { + mStatusIcon.setImage(mImageFactory.getImageByName("reject_icon16.png")); + mStatusLabel.setText(error); + } else { + mStatusIcon.setImage(null); + mStatusLabel.setText(" \n "); //$NON-NLS-1$ + } + + mStatusComposite.pack(true); + } + + /** + * Creates an AVD from the values in the UI. Called when the user presses the OK button. + */ + private boolean onCreate() { + String avdName = mAvdName.getText().trim(); + String sdName = mSdCard.getText().trim(); + int targetIndex = mTargetCombo.getSelectionIndex(); + int skinIndex = mSkinCombo.getSelectionIndex(); + boolean force = mForceCreation.getSelection(); + + if (avdName.length() == 0 || targetIndex < 0) { + return false; + } + + String targetName = mTargetCombo.getItem(targetIndex); + IAndroidTarget target = mCurrentTargets.get(targetName); + if (target == null) { + return false; + } + + String skinName = null; + if (skinIndex > 0) { + // index 0 is the default, we don't use it + skinName = mSkinCombo.getItem(skinIndex); + } + + SdkLog log = new SdkLog(String.format("Result of creating AVD '%s':", avdName), + getContents().getDisplay()); + + File avdFolder; + try { + avdFolder = new File( + AndroidLocation.getFolder() + AndroidLocation.FOLDER_AVD, + avdName + AvdManager.AVD_FOLDER_EXTENSION); + } catch (AndroidLocationException e) { + return false; + } + + ISdkLog oldLog = null; + boolean success = false; + try { + // Temporarily change the AvdManager's logger for ours, since the API no longer + // takes a logger argument. + // TODO revisit this later. See comments in AvdManager#mSdkLog. + oldLog = mAvdManager.setSdkLog(log); + + AvdInfo avdInfo = mAvdManager.createAvd( + avdFolder, + avdName, + target, + skinName, + sdName, + null, // hardwareConfig, + force); + + success = avdInfo != null; + + } finally { + mAvdManager.setSdkLog(oldLog); + } + + log.displayResult(success); + + return success; + } +} diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java index 5eb74f198..8b054f2db 100644 --- a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java @@ -22,8 +22,6 @@ import com.android.sdklib.internal.avd.AvdManager.AvdInfo; import com.android.sdklib.internal.avd.AvdManager.AvdInfo.AvdStatus; import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ShellAdapter; -import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; @@ -85,12 +83,6 @@ final class AvdDetailsDialog extends Dialog { */ private void createContents() { mDialogShell = new Shell(getParent(), SWT.DIALOG_TRIM | SWT.RESIZE); - mDialogShell.addShellListener(new ShellAdapter() { - @Override - public void shellClosed(ShellEvent e) { - onShellClosed(e); - } - }); mDialogShell.setLayout(new GridLayout(1, false)); mDialogShell.setSize(450, 300); mDialogShell.setText(getText()); @@ -130,7 +122,7 @@ final class AvdDetailsDialog extends Dialog { sdcard = properties.get(AvdManager.AVD_INI_SDCARD_PATH); } if (sdcard != null) { - displayValue(c, "sdcard:", sdcard); + displayValue(c, "SD Card:", sdcard); } // display other hardware @@ -185,10 +177,6 @@ final class AvdDetailsDialog extends Dialog { l.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false)); } - private void onShellClosed(ShellEvent e) { - // TODO Auto-generated method stub - } - /** * Centers the dialog in its parent shell. */ diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java index 39a9c5c5a..35557d65d 100644 --- a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java @@ -25,6 +25,7 @@ import com.android.sdklib.internal.avd.AvdManager.AvdInfo.AvdStatus; import com.android.sdkuilib.internal.repository.icons.ImageFactory; import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; @@ -64,10 +65,10 @@ public final class AvdSelector { private final DisplayMode mDisplayMode; private Button mManagerButton; private IAvdFilter mTargetFilter; - private AvdManager mManager; + private AvdManager mAvdManager; private Image mOkImage; private Image mBrokenImage; - private ImageFactory mIconFactory; + private ImageFactory mImageFactory; /** * The display mode of the AVD Selector. @@ -164,7 +165,7 @@ public final class AvdSelector { AvdManager manager, IAvdFilter filter, DisplayMode displayMode) { - mManager = manager; + mAvdManager = manager; mTargetFilter = filter; mDisplayMode = displayMode; @@ -177,7 +178,7 @@ public final class AvdSelector { group.setFont(parent.getFont()); group.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent arg0) { - mIconFactory.dispose(); + mImageFactory.dispose(); } }); @@ -200,7 +201,12 @@ public final class AvdSelector { Button newButton = new Button(buttons, SWT.PUSH | SWT.FLAT); newButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); newButton.setText("New..."); - // TODO handle 'new' button. + newButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent arg0) { + onNew(); + } + }); Button deleteButton = new Button(buttons, SWT.PUSH | SWT.FLAT); deleteButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); @@ -262,9 +268,9 @@ public final class AvdSelector { column3.setText("API Level"); // get some bitmaps. - mIconFactory = new ImageFactory(parent.getDisplay()); - mOkImage = mIconFactory.getImageByName("accept_icon16.png"); - mBrokenImage = mIconFactory.getImageByName("reject_icon16.png"); + mImageFactory = new ImageFactory(parent.getDisplay()); + mOkImage = mImageFactory.getImageByName("accept_icon16.png"); + mBrokenImage = mImageFactory.getImageByName("reject_icon16.png"); adjustColumnsWidth(mTable, column0, column1, column2, column3); setupSelectionListener(mTable); @@ -331,7 +337,7 @@ public final class AvdSelector { public boolean refresh(boolean reload) { if (reload) { try { - mManager.reloadAvds(); + mAvdManager.reloadAvds(); } catch (AndroidLocationException e) { return false; } @@ -352,7 +358,7 @@ public final class AvdSelector { * @param manager the AVD manager. */ public void setManager(AvdManager manager) { - mManager = manager; + mAvdManager = manager; } /** @@ -595,11 +601,11 @@ public final class AvdSelector { // get the AVDs AvdInfo avds[] = null; - if (mManager != null) { + if (mAvdManager != null) { if (mDisplayMode == DisplayMode.MANAGER) { - avds = mManager.getAllAvds(); + avds = mAvdManager.getAllAvds(); } else { - avds = mManager.getValidAvds(); + avds = mAvdManager.getValidAvds(); } } @@ -647,6 +653,14 @@ public final class AvdSelector { } } + private void onNew() { + AvdCreationDialog dlg = new AvdCreationDialog(mTable.getShell(), mAvdManager, + mImageFactory); + if (dlg.open() == Window.OK) { + refresh(false /*reload*/); + } + } + private void onDetails() { final AvdInfo avdInfo = getSelected(); @@ -683,20 +697,20 @@ public final class AvdSelector { display); // delete the AVD - boolean success = mManager.deleteAvd(avdInfo, log); + boolean success = mAvdManager.deleteAvd(avdInfo, log); // display the result log.displayResult(success); if (success) { - refresh(false); + refresh(false /*reload*/); } } /** * Collects all log from the AVD action and displays it in a dialog. */ - private class SdkLog implements ISdkLog { + static class SdkLog implements ISdkLog { final ArrayList logMessages = new ArrayList(); private final String mMessage; @@ -730,9 +744,8 @@ public final class AvdSelector { */ public void displayResult(final boolean success) { if (logMessages.size() > 0) { - final StringBuilder sb = new StringBuilder(mMessage + "\n"); + final StringBuilder sb = new StringBuilder(mMessage + "\n\n"); for (String msg : logMessages) { - sb.append('\n'); sb.append(msg); } @@ -754,6 +767,4 @@ public final class AvdSelector { } } } - - }