diff options
author | Raphael Moll <ralf@android.com> | 2013-01-15 19:47:10 -0800 |
---|---|---|
committer | Raphael Moll <ralf@android.com> | 2013-01-15 19:58:34 -0800 |
commit | 20d8d91c41d05b1f5e73a04a2992448a12b82f7b (patch) | |
tree | e201d97d3801c28dc7e01abe06bd395b317456f3 /sdkmanager | |
parent | 1fdcf5c83dd676358668b4934b19475af3ab4d6d (diff) | |
download | sdk-20d8d91c41d05b1f5e73a04a2992448a12b82f7b.zip sdk-20d8d91c41d05b1f5e73a04a2992448a12b82f7b.tar.gz sdk-20d8d91c41d05b1f5e73a04a2992448a12b82f7b.tar.bz2 |
SDK: use prebuilts/devtools for sdkuilib
Change-Id: Icd6597be885179bd1f0b49d227ece7a3fa9f9bcb
Diffstat (limited to 'sdkmanager')
109 files changed, 11 insertions, 26536 deletions
diff --git a/sdkmanager/libs/sdkuilib/Android.mk b/sdkmanager/libs/sdkuilib/Android.mk index 9406fdf..b746632 100644 --- a/sdkmanager/libs/sdkuilib/Android.mk +++ b/sdkmanager/libs/sdkuilib/Android.mk @@ -12,13 +12,18 @@ # 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. -# + LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES := $(call all-java-files-under, src) -LOCAL_JAVA_RESOURCE_DIRS := src +# The sdkuilib code has moved to tools/swt/sdkuilib. +# The rule below uses the prebuilt sdkuilib.jar if found. +# +# If you want to run the tests, cd to tools/swt +# and run ./gradlew :sdkuilib:test +LOCAL_MODULE := sdkuilib +LOCAL_MODULE_TAGS := optional # IMPORTANT: if you add a new dependency here, please make sure # to also check the following file: # sdkmanager/app/etc/android.bat @@ -39,13 +44,8 @@ LOCAL_JAVA_LIBRARIES := \ swt \ swtmenubar -LOCAL_MODULE := sdkuilib - -LOCAL_JAR_MANIFEST := etc/manifest.txt - -include $(BUILD_HOST_JAVA_LIBRARY) - +LOCAL_PREBUILT_JAVA_LIBRARIES := \ + ../../../../prebuilts/devtools/$(LOCAL_MODULE)/$(LOCAL_MODULE)$(COMMON_JAVA_PACKAGE_SUFFIX) +include $(BUILD_HOST_PREBUILT) -# Build all sub-directories -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AboutDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AboutDialog.java deleted file mode 100755 index 717890b..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AboutDialog.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2012 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.repository; - - -import com.android.SdkConstants; -import com.android.sdklib.io.FileOp; -import com.android.sdklib.repository.PkgProps; -import com.android.sdklib.repository.SdkAddonConstants; -import com.android.sdklib.repository.SdkRepoConstants; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.ui.GridDataBuilder; -import com.android.sdkuilib.ui.GridLayoutBuilder; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Properties; - -public class AboutDialog extends UpdaterBaseDialog { - - public AboutDialog(Shell parentShell, UpdaterData updaterData) { - super(parentShell, updaterData, "About" /*title*/); - assert updaterData != null; - } - - @Override - protected void createContents() { - super.createContents(); - Shell shell = getShell(); - shell.setMinimumSize(new Point(450, 150)); - shell.setSize(450, 150); - - GridLayoutBuilder.create(shell).columns(3); - - Label logo = new Label(shell, SWT.NONE); - ImageFactory imgf = getUpdaterData() == null ? null : getUpdaterData().getImageFactory(); - Image image = imgf == null ? null : imgf.getImageByName("sdkman_logo_128.png"); - if (image != null) logo.setImage(image); - - Label label = new Label(shell, SWT.NONE); - GridDataBuilder.create(label).hFill().hGrab().hSpan(2);; - label.setText(String.format( - "Android SDK Manager.\n" + - "Revision %1$s\n" + - "Add-on XML Schema #%2$d\n" + - "Repository XML Schema #%3$d\n" + - // TODO: update with new year date (search this to find other occurrences to update) - "Copyright (C) 2009-2012 The Android Open Source Project.", - getRevision(), - SdkAddonConstants.NS_LATEST_VERSION, - SdkRepoConstants.NS_LATEST_VERSION)); - - Label filler = new Label(shell, SWT.NONE); - GridDataBuilder.create(filler).fill().grab().hSpan(2); - - createCloseButton(); - } - - @Override - protected void checkSubclass() { - // Disable the check that prevents subclassing of SWT components - } - - // -- Start of internal part ---------- - // Hide everything down-below from SWT designer - //$hide>>$ - - // End of hiding from SWT Designer - //$hide<<$ - - private String getRevision() { - Properties p = new Properties(); - try{ - File sourceProp = FileOp.append(getUpdaterData().getOsSdkRoot(), - SdkConstants.FD_TOOLS, - SdkConstants.FN_SOURCE_PROP); - FileInputStream fis = null; - try { - fis = new FileInputStream(sourceProp); - p.load(fis); - } finally { - if (fis != null) { - try { - fis.close(); - } catch (IOException ignore) { - } - } - } - - String revision = p.getProperty(PkgProps.PKG_REVISION); - if (revision != null) { - return revision; - } - } catch (IOException e) { - } - - return "?"; - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ArchiveInfo.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ArchiveInfo.java deleted file mode 100755 index 2c509ca..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ArchiveInfo.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * 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.repository; - -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.archives.ArchiveReplacement; - -import java.util.ArrayList; -import java.util.Collection; - -/** - * Represents an archive that we want to install. - * Note that the installer deals with archives whereas the user mostly sees packages - * but as far as we are concerned for installation there's a 1-to-1 mapping. - * <p/> - * A new archive is always a remote archive that needs to be downloaded and then - * installed. It can replace an existing local one. It can also depends on another - * (new or local) archive, which means the dependent archive needs to be successfully - * installed first. Finally this archive can also be a dependency for another one. - * <p/> - * The accepted and rejected flags are used by {@link SdkUpdaterChooserDialog} to follow - * user choices. The installer should never install something that is not accepted. - * <p/> - * <em>Note</em>: There is currently no logic to support more than one level of - * dependency, either here or in the {@link SdkUpdaterChooserDialog}, since we currently - * have no need for it. - * - * @see ArchiveInfo#ArchiveInfo(Archive, Archive, ArchiveInfo[]) - */ -class ArchiveInfo extends ArchiveReplacement implements Comparable<ArchiveInfo> { - - private final ArchiveInfo[] mDependsOn; - private final ArrayList<ArchiveInfo> mDependencyFor = new ArrayList<ArchiveInfo>(); - private boolean mAccepted; - private boolean mRejected; - - /** - * Creates a new replacement where the {@code newArchive} will replace the - * currently installed {@code replaced} archive. - * When {@code newArchive} is not intended to replace anything (e.g. because - * the user is installing a new package not present on her system yet), then - * {@code replace} shall be null. - * - * @param newArchive A "new archive" to be installed. This is always an archive - * that comes from a remote site. This <em>may</em> be null. - * @param replaced An optional local archive that the new one will replace. - * Can be null if this archive does not replace anything. - * @param dependsOn An optional new or local dependency, that is an archive that - * <em>this</em> archive depends upon. In other words, we can only install - * this archive if the dependency has been successfully installed. It also - * means we need to install the dependency first. Can be null or empty. - * However it cannot contain nulls. - */ - public ArchiveInfo(Archive newArchive, Archive replaced, ArchiveInfo[] dependsOn) { - super(newArchive, replaced); - mDependsOn = dependsOn; - } - - /** - * Returns an optional new or local dependency, that is an archive that <em>this</em> - * archive depends upon. In other words, we can only install this archive if the - * dependency has been successfully installed. It also means we need to install the - * dependency first. - * <p/> - * This array can be null or empty. It can't contain nulls though. - */ - public ArchiveInfo[] getDependsOn() { - return mDependsOn; - } - - /** - * Returns true if this new archive is a dependency for <em>another</em> one that we - * want to install. - */ - public boolean isDependencyFor() { - return mDependencyFor.size() > 0; - } - - /** - * Adds an {@link ArchiveInfo} for which <em>this</em> package is a dependency. - * This means the package added here depends on this package. - */ - public ArchiveInfo addDependencyFor(ArchiveInfo dependencyFor) { - if (!mDependencyFor.contains(dependencyFor)) { - mDependencyFor.add(dependencyFor); - } - - return this; - } - - /** - * Returns the list of {@link ArchiveInfo} for which <em>this</em> package is a dependency. - * This means the packages listed here depend on this package. - * <p/> - * Implementation detail: this is the internal mutable list. Callers should not modify it. - * This list can be empty but is never null. - */ - public Collection<ArchiveInfo> getDependenciesFor() { - return mDependencyFor; - } - - /** - * Sets whether this archive was accepted (either manually by the user or - * automatically if it doesn't have a license) for installation. - */ - public void setAccepted(boolean accepted) { - mAccepted = accepted; - } - - /** - * Returns whether this archive was accepted (either manually by the user or - * automatically if it doesn't have a license) for installation. - */ - public boolean isAccepted() { - return mAccepted; - } - - /** - * Sets whether this archive was rejected manually by the user. - * An archive can neither accepted nor rejected. - */ - public void setRejected(boolean rejected) { - mRejected = rejected; - } - - /** - * Returns whether this archive was rejected manually by the user. - * An archive can neither accepted nor rejected. - */ - public boolean isRejected() { - return mRejected; - } - - /** - * ArchiveInfos are compared using ther "new archive" ordering. - * - * @see Archive#compareTo(Archive) - */ - @Override - public int compareTo(ArchiveInfo rhs) { - if (getNewArchive() != null && rhs != null) { - return getNewArchive().compareTo(rhs.getNewArchive()); - } - return 0; - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ISdkUpdaterWindow.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ISdkUpdaterWindow.java deleted file mode 100755 index e5f2521..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ISdkUpdaterWindow.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.repository; - -import com.android.sdkuilib.repository.ISdkChangeListener; - -/** - * Interface for the actual implementation of the Update Window. - */ -public interface ISdkUpdaterWindow { - - /** - * Adds a new listener to be notified when a change is made to the content of the SDK. - */ - public abstract void addListener(ISdkChangeListener listener); - - /** - * Removes a new listener to be notified anymore when a change is made to the content of - * the SDK. - */ - public abstract void removeListener(ISdkChangeListener listener); - - /** - * Opens the window. - */ - public abstract void open(); - -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ISettingsPage.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ISettingsPage.java deleted file mode 100755 index 333644f..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ISettingsPage.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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.repository; - -import com.android.sdklib.internal.repository.DownloadCache; - -import java.net.URL; -import java.util.Properties; - -/** - * Interface that a settings page must implement. - */ -public interface ISettingsPage { - - /** - * Java system setting picked up by {@link URL} for http proxy port. - * Type: String. - */ - public static final String KEY_HTTP_PROXY_PORT = "http.proxyPort"; //$NON-NLS-1$ - - /** - * Java system setting picked up by {@link URL} for http proxy host. - * Type: String. - */ - public static final String KEY_HTTP_PROXY_HOST = "http.proxyHost"; //$NON-NLS-1$ - - /** - * Setting to force using http:// instead of https:// connections. - * Type: Boolean. - * Default: False. - */ - public static final String KEY_FORCE_HTTP = "sdkman.force.http"; //$NON-NLS-1$ - - /** - * Setting to display only packages that are new or updates. - * Type: Boolean. - * Default: True. - */ - public static final String KEY_SHOW_UPDATE_ONLY = "sdkman.show.update.only"; //$NON-NLS-1$ - - /** - * Setting to ask for permission before restarting ADB. - * Type: Boolean. - * Default: False. - */ - public static final String KEY_ASK_ADB_RESTART = "sdkman.ask.adb.restart"; //$NON-NLS-1$ - - /** - * Setting to use the {@link DownloadCache}, for small manifest XML files. - * Type: Boolean. - * Default: True. - */ - public static final String KEY_USE_DOWNLOAD_CACHE = "sdkman.use.dl.cache"; //$NON-NLS-1$ - - /** - * Setting to enabling previews in the package list - * Type: Boolean. - * Default: False. - */ - public static final String KEY_ENABLE_PREVIEWS = "sdkman.enable.previews"; //$NON-NLS-1$ - - /** - * Setting to set the density of the monitor. - * Type: Integer. - * Default: -1 - */ - public static final String KEY_MONITOR_DENSITY = "sdkman.monitor.density"; //$NON-NLS-1$ - - /** Loads settings from the given {@link Properties} container and update the page UI. */ - public abstract void loadSettings(Properties inSettings); - - /** Called by the application to retrieve settings from the UI and store them in - * the given {@link Properties} container. */ - public abstract void retrieveSettings(Properties outSettings); - - /** - * Called by the application to give a callback that the page should invoke when - * settings have changed. - */ - public abstract void setOnSettingsChanged(SettingsChangedCallback settingsChangedCallback); - - /** - * Callback used to notify the application that settings have changed and need to be - * applied. - */ - public interface SettingsChangedCallback { - /** - * Invoked by the settings page when settings have changed and need to be - * applied. The application will call {@link ISettingsPage#retrieveSettings(Properties)} - * and apply the new settings. - */ - public abstract void onSettingsChanged(ISettingsPage page); - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/IUpdaterData.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/IUpdaterData.java deleted file mode 100755 index acc3990..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/IUpdaterData.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2010 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.repository; - -import com.android.sdklib.SdkManager; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdklib.internal.repository.DownloadCache; -import com.android.sdklib.internal.repository.ITaskFactory; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.utils.ILogger; - -import org.eclipse.swt.widgets.Shell; - - -/** - * Interface used to retrieve some parameters from an {@link UpdaterData} instance. - * Useful mostly for unit tests purposes. - */ -interface IUpdaterData { - - public abstract ITaskFactory getTaskFactory(); - - public abstract ILogger getSdkLog(); - - public abstract DownloadCache getDownloadCache(); - - public abstract ImageFactory getImageFactory(); - - public abstract SdkManager getSdkManager(); - - public abstract AvdManager getAvdManager(); - - public abstract SettingsController getSettingsController(); - - public abstract Shell getWindowShell(); - -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/MenuBarWrapper.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/MenuBarWrapper.java deleted file mode 100755 index 8d3eabd..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/MenuBarWrapper.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2011 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.repository; - - -import com.android.menubar.IMenuBarCallback; -import com.android.menubar.MenuBarEnhancer; -import com.android.sdkuilib.internal.repository.ui.SdkUpdaterWindowImpl2; - -import org.eclipse.swt.widgets.Menu; - -/** - * A simple wrapper/delegate around the {@link MenuBarEnhancer}. - * - * The {@link MenuBarEnhancer} and {@link IMenuBarCallback} classes are only - * available when the SwtMenuBar library is available too. This wrapper helps - * {@link SdkUpdaterWindowImpl2} make the call conditional, otherwise the updater - * window class would fail to load when the SwtMenuBar library isn't found. - */ -public abstract class MenuBarWrapper { - - public MenuBarWrapper(String appName, Menu menu) { - MenuBarEnhancer.setupMenu(appName, menu, new IMenuBarCallback() { - @Override - public void onPreferencesMenuSelected() { - MenuBarWrapper.this.onPreferencesMenuSelected(); - } - - @Override - public void onAboutMenuSelected() { - MenuBarWrapper.this.onAboutMenuSelected(); - } - - @Override - public void printError(String format, Object... args) { - MenuBarWrapper.this.printError(format, args); - } - }); - } - - abstract public void onPreferencesMenuSelected(); - - abstract public void onAboutMenuSelected(); - - abstract public void printError(String format, Object... args); -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SdkUpdaterChooserDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SdkUpdaterChooserDialog.java deleted file mode 100755 index 48f5553..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SdkUpdaterChooserDialog.java +++ /dev/null @@ -1,781 +0,0 @@ -/* - * 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.repository; - -import com.android.SdkConstants; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.packages.FullRevision; -import com.android.sdklib.internal.repository.packages.IAndroidVersionProvider; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.ui.GridDialog; - -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.LabelProvider; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.SashForm; -import org.eclipse.swt.custom.StyleRange; -import org.eclipse.swt.custom.StyledText; -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.Image; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Group; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Link; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; - -import java.util.ArrayList; -import java.util.Collection; - - -/** - * Implements an {@link SdkUpdaterChooserDialog}. - */ -final class SdkUpdaterChooserDialog extends GridDialog { - - /** Last dialog size for this session. */ - private static Point sLastSize; - private boolean mLicenseAcceptAll; - private boolean mInternalLicenseRadioUpdate; - - // UI fields - private SashForm mSashForm; - private Composite mPackageRootComposite; - private TableViewer mTableViewPackage; - private Table mTablePackage; - private TableColumn mTableColum; - private StyledText mPackageText; - private Button mLicenseRadioAccept; - private Button mLicenseRadioReject; - private Button mLicenseRadioAcceptAll; - private Group mPackageTextGroup; - private final UpdaterData mUpdaterData; - private Group mTableGroup; - private Label mErrorLabel; - - /** - * List of all archives to be installed with dependency information. - * <p/> - * Note: in a lot of cases, we need to find the archive info for a given archive. This - * is currently done using a simple linear search, which is fine since we only have a very - * limited number of archives to deal with (e.g. < 10 now). We might want to revisit - * this later if it becomes an issue. Right now just do the simple thing. - *<p/> - * Typically we could add a map Archive=>ArchiveInfo later. - */ - private final Collection<ArchiveInfo> mArchives; - - - - /** - * Create the dialog. - * @param parentShell The shell to use, typically updaterData.getWindowShell() - * @param updaterData The updater data - * @param archives The archives to be installed - */ - public SdkUpdaterChooserDialog(Shell parentShell, - UpdaterData updaterData, - Collection<ArchiveInfo> archives) { - super(parentShell, 3, false/*makeColumnsEqual*/); - mUpdaterData = updaterData; - mArchives = archives; - } - - @Override - protected boolean isResizable() { - return true; - } - - /** - * Returns the results, i.e. the list of selected new archives to install. - * This is similar to the {@link ArchiveInfo} list instance given to the constructor - * except only accepted archives are present. - * - * An empty list is returned if cancel was choosen. - */ - public ArrayList<ArchiveInfo> getResult() { - ArrayList<ArchiveInfo> ais = new ArrayList<ArchiveInfo>(); - - if (getReturnCode() == Window.OK) { - for (ArchiveInfo ai : mArchives) { - if (ai.isAccepted()) { - ais.add(ai); - } - } - } - - return ais; - } - - /** - * Create the main content of the dialog. - * See also {@link #createButtonBar(Composite)} below. - */ - @Override - public void createDialogContent(Composite parent) { - // Sash form - mSashForm = new SashForm(parent, SWT.NONE); - mSashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); - - - // Left part of Sash Form - - mTableGroup = new Group(mSashForm, SWT.NONE); - mTableGroup.setText("Packages"); - mTableGroup.setLayout(new GridLayout(1, false/*makeColumnsEqual*/)); - - mTableViewPackage = new TableViewer(mTableGroup, SWT.BORDER | SWT.V_SCROLL | SWT.SINGLE); - mTablePackage = mTableViewPackage.getTable(); - mTablePackage.setHeaderVisible(false); - mTablePackage.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); - - mTablePackage.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onPackageSelected(); //$hide$ - } - @Override - public void widgetDefaultSelected(SelectionEvent e) { - onPackageDoubleClick(); - } - }); - - mTableColum = new TableColumn(mTablePackage, SWT.NONE); - mTableColum.setWidth(100); - mTableColum.setText("Packages"); - - - // Right part of Sash form - mPackageRootComposite = new Composite(mSashForm, SWT.NONE); - mPackageRootComposite.setLayout(new GridLayout(4, false/*makeColumnsEqual*/)); - mPackageRootComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - - mPackageTextGroup = new Group(mPackageRootComposite, SWT.NONE); - mPackageTextGroup.setText("Package Description && License"); - mPackageTextGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1)); - mPackageTextGroup.setLayout(new GridLayout(1, false/*makeColumnsEqual*/)); - - mPackageText = new StyledText(mPackageTextGroup, - SWT.MULTI | SWT.READ_ONLY | SWT.WRAP | SWT.V_SCROLL); - mPackageText.setBackground( - getParentShell().getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); - mPackageText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); - - mLicenseRadioAccept = new Button(mPackageRootComposite, SWT.RADIO); - mLicenseRadioAccept.setText("Accept"); - mLicenseRadioAccept.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onLicenseRadioSelected(); - } - }); - - mLicenseRadioReject = new Button(mPackageRootComposite, SWT.RADIO); - mLicenseRadioReject.setText("Reject"); - mLicenseRadioReject.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onLicenseRadioSelected(); - } - }); - - Link link = new Link(mPackageRootComposite, SWT.NONE); - link.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false, 1, 1)); - final String printAction = "Print"; // extracted for NLS, to compare with below. - link.setText(String.format("<a>Copy to clipboard</a> | <a>%1$s</a>", printAction)); - link.setToolTipText("Copies all text and license to clipboard | Print using system defaults."); - link.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - if (printAction.equals(e.text)) { - mPackageText.print(); - } else { - Point p = mPackageText.getSelection(); - mPackageText.selectAll(); - mPackageText.copy(); - mPackageText.setSelection(p); - } - } - }); - - - mLicenseRadioAcceptAll = new Button(mPackageRootComposite, SWT.RADIO); - mLicenseRadioAcceptAll.setText("Accept All"); - mLicenseRadioAcceptAll.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onLicenseRadioSelected(); - } - }); - - mSashForm.setWeights(new int[] {200, 300}); - } - - /** - * Creates and returns the contents of this dialog's button bar. - * <p/> - * This reimplements most of the code from the base class with a few exceptions: - * <ul> - * <li>Enforces 3 columns. - * <li>Inserts a full-width error label. - * <li>Inserts a help label on the left of the first button. - * <li>Renames the OK button into "Install" - * </ul> - */ - @Override - protected Control createButtonBar(Composite parent) { - Composite composite = new Composite(parent, SWT.NONE); - GridLayout layout = new GridLayout(); - layout.numColumns = 0; // this is incremented by createButton - layout.makeColumnsEqualWidth = false; - layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); - layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); - layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); - layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); - composite.setLayout(layout); - GridData data = new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1); - composite.setLayoutData(data); - composite.setFont(parent.getFont()); - - // Error message area - mErrorLabel = new Label(composite, SWT.NONE); - mErrorLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1)); - - // Label at the left of the install/cancel buttons - Label label = new Label(composite, SWT.NONE); - label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); - label.setText("[*] Something depends on this package"); - label.setEnabled(false); - layout.numColumns++; - - // Add the ok/cancel to the button bar. - createButtonsForButtonBar(composite); - - // the ok button should be an "install" button - Button button = getButton(IDialogConstants.OK_ID); - button.setText("Install"); - - return composite; - } - - // -- End of UI, Start of internal logic ---------- - // Hide everything down-below from SWT designer - //$hide>>$ - - @Override - public void create() { - super.create(); - - // set window title - getShell().setText("Choose Packages to Install"); - - setWindowImage(); - - // Automatically accept those with an empty license or no license - for (ArchiveInfo ai : mArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - String license = a.getParentPackage().getLicense(); - ai.setAccepted(license == null || license.trim().length() == 0); - } - } - - // Fill the list with the replacement packages - mTableViewPackage.setLabelProvider(new NewArchivesLabelProvider()); - mTableViewPackage.setContentProvider(new NewArchivesContentProvider()); - mTableViewPackage.setInput(mArchives); - - adjustColumnsWidth(); - - // select first item - mTablePackage.select(0); - onPackageSelected(); - } - - /** - * Creates the icon of the window shell. - */ - private void setWindowImage() { - String imageName = "android_icon_16.png"; //$NON-NLS-1$ - if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_DARWIN) { - imageName = "android_icon_128.png"; //$NON-NLS-1$ - } - - if (mUpdaterData != null) { - ImageFactory imgFactory = mUpdaterData.getImageFactory(); - if (imgFactory != null) { - getShell().setImage(imgFactory.getImageByName(imageName)); - } - } - } - - /** - * Adds a listener to adjust the columns width when the parent is resized. - * <p/> - * If we need something more fancy, we might want to use this: - * http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet77.java?view=co - */ - private void adjustColumnsWidth() { - // Add a listener to resize the column to the full width of the table - ControlAdapter resizer = new ControlAdapter() { - @Override - public void controlResized(ControlEvent e) { - Rectangle r = mTablePackage.getClientArea(); - mTableColum.setWidth(r.width); - } - }; - mTablePackage.addControlListener(resizer); - resizer.controlResized(null); - } - - /** - * Captures the window size before closing this. - * @see #getInitialSize() - */ - @Override - public boolean close() { - sLastSize = getShell().getSize(); - return super.close(); - } - - /** - * Tries to reuse the last window size during this session. - * <p/> - * Note: the alternative would be to implement {@link #getDialogBoundsSettings()} - * since the default {@link #getDialogBoundsStrategy()} is to persist both location - * and size. - */ - @Override - protected Point getInitialSize() { - if (sLastSize != null) { - return sLastSize; - } else { - // Arbitrary values that look good on my screen and fit on 800x600 - return new Point(740, 470); - } - } - - /** - * Callback invoked when a package item is selected in the list. - */ - private void onPackageSelected() { - ArchiveInfo ai = getSelectedArchive(); - displayInformation(ai); - displayMissingDependency(ai); - updateLicenceRadios(ai); - } - - /** Returns the currently selected {@link ArchiveInfo} or null. */ - private ArchiveInfo getSelectedArchive() { - ISelection sel = mTableViewPackage.getSelection(); - if (sel instanceof IStructuredSelection) { - Object elem = ((IStructuredSelection) sel).getFirstElement(); - if (elem instanceof ArchiveInfo) { - return (ArchiveInfo) elem; - } - } - return null; - } - - /** - * Updates the package description and license text depending on the selected package. - * <p/> - * Note that right now there is no logic to support more than one level of dependencies - * (e.g. A <- B <- C and A is disabled so C should be disabled; currently C's state depends - * solely on B's state). We currently don't need this. It would be straightforward to add - * if we had a need for it, though. This would require changes to {@link ArchiveInfo} and - * {@link SdkUpdaterLogic}. - */ - private void displayInformation(ArchiveInfo ai) { - if (ai == null) { - mPackageText.setText("Please select a package."); - return; - } - - Archive aNew = ai.getNewArchive(); - if (aNew == null) { - // Only missing archives have a null archive, so we shouldn't be here. - return; - } - - Package pNew = aNew.getParentPackage(); - - mPackageText.setText(""); //$NON-NLS-1$ - - addSectionTitle("Package Description\n"); - addText(pNew.getLongDescription(), "\n\n"); //$NON-NLS-1$ - - Archive aOld = ai.getReplaced(); - if (aOld != null) { - Package pOld = aOld.getParentPackage(); - - FullRevision rOld = pOld.getRevision(); - FullRevision rNew = pNew.getRevision(); - - boolean showRev = true; - - if (pNew instanceof IAndroidVersionProvider && - pOld instanceof IAndroidVersionProvider) { - AndroidVersion vOld = ((IAndroidVersionProvider) pOld).getAndroidVersion(); - AndroidVersion vNew = ((IAndroidVersionProvider) pNew).getAndroidVersion(); - - if (!vOld.equals(vNew)) { - // Versions are different, so indicate more than just the revision. - addText(String.format("This update will replace API %1$s revision %2$s with API %3$s revision %4$s.\n\n", - vOld.getApiString(), rOld.toShortString(), - vNew.getApiString(), rNew.toShortString())); - showRev = false; - } - } - - if (showRev) { - addText(String.format("This update will replace revision %1$s with revision %2$s.\n\n", - rOld.toShortString(), - rNew.toShortString())); - } - } - - ArchiveInfo[] aDeps = ai.getDependsOn(); - if ((aDeps != null && aDeps.length > 0) || ai.isDependencyFor()) { - addSectionTitle("Dependencies\n"); - - if (aDeps != null && aDeps.length > 0) { - addText("Installing this package also requires installing:"); - for (ArchiveInfo aDep : aDeps) { - addText(String.format("\n- %1$s", - aDep.getShortDescription())); - } - addText("\n\n"); - } - - if (ai.isDependencyFor()) { - addText("This package is a dependency for:"); - for (ArchiveInfo ai2 : ai.getDependenciesFor()) { - addText(String.format("\n- %1$s", - ai2.getShortDescription())); - } - addText("\n\n"); - } - } - - addSectionTitle("Archive Description\n"); - addText(aNew.getLongDescription(), "\n\n"); //$NON-NLS-1$ - - String license = pNew.getLicense(); - if (license != null) { - addSectionTitle("License\n"); - addText(license.trim(), "\n\n"); //$NON-NLS-1$ - } - - addSectionTitle("Site\n"); - SdkSource source = pNew.getParentSource(); - if (source != null) { - addText(source.getShortDescription()); - } - } - - /** - * Computes and displays missing dependencies. - * - * If there's a selected package, check the dependency for that one. - * Otherwise display the first missing dependency of any other package. - */ - private void displayMissingDependency(ArchiveInfo ai) { - String error = null; - - try { - if (ai != null) { - if (ai.isAccepted()) { - // Case where this package is accepted but blocked by another non-accepted one - ArchiveInfo[] adeps = ai.getDependsOn(); - if (adeps != null) { - for (ArchiveInfo adep : adeps) { - if (!adep.isAccepted()) { - error = String.format("This package depends on '%1$s'.", - adep.getShortDescription()); - return; - } - } - } - } else { - // Case where this package blocks another one when not accepted - for (ArchiveInfo adep : ai.getDependenciesFor()) { - // It only matters if the blocked one is accepted - if (adep.isAccepted()) { - error = String.format("Package '%1$s' depends on this one.", - adep.getShortDescription()); - return; - } - } - } - } - - // If there is no missing dependency on the current selection, - // just find the first missing dependency of any other package. - for (ArchiveInfo ai2 : mArchives) { - if (ai2 == ai) { - // We already processed that one above. - continue; - } - if (ai2.isAccepted()) { - // The user requested to install this package. - // Check if all its dependencies are met. - ArchiveInfo[] adeps = ai2.getDependsOn(); - if (adeps != null) { - for (ArchiveInfo adep : adeps) { - if (!adep.isAccepted()) { - error = String.format("Package '%1$s' depends on '%2$s'", - ai2.getShortDescription(), - adep.getShortDescription()); - return; - } - } - } - } else { - // The user did not request to install this package. - // Check whether this package blocks another one when not accepted. - for (ArchiveInfo adep : ai2.getDependenciesFor()) { - // It only matters if the blocked one is accepted - // or if it's a local archive that is already installed (these - // are marked as implicitly accepted, so it's the same test.) - if (adep.isAccepted()) { - error = String.format("Package '%1$s' depends on '%2$s'", - adep.getShortDescription(), - ai2.getShortDescription()); - return; - } - } - } - } - } finally { - mErrorLabel.setText(error == null ? "" : error); //$NON-NLS-1$ - } - } - - private void addText(String...string) { - for (String s : string) { - mPackageText.append(s); - } - } - - private void addSectionTitle(String string) { - String s = mPackageText.getText(); - int start = (s == null ? 0 : s.length()); - mPackageText.append(string); - - StyleRange sr = new StyleRange(); - sr.start = start; - sr.length = string.length(); - sr.fontStyle = SWT.BOLD; - sr.underline = true; - mPackageText.setStyleRange(sr); - } - - private void updateLicenceRadios(ArchiveInfo ai) { - if (mInternalLicenseRadioUpdate) { - return; - } - mInternalLicenseRadioUpdate = true; - - boolean oneAccepted = false; - - if (mLicenseAcceptAll) { - mLicenseRadioAcceptAll.setSelection(true); - mLicenseRadioAccept.setEnabled(true); - mLicenseRadioReject.setEnabled(true); - mLicenseRadioAccept.setSelection(false); - mLicenseRadioReject.setSelection(false); - } else { - mLicenseRadioAcceptAll.setSelection(false); - oneAccepted = ai != null && ai.isAccepted(); - mLicenseRadioAccept.setEnabled(ai != null); - mLicenseRadioReject.setEnabled(ai != null); - mLicenseRadioAccept.setSelection(oneAccepted); - mLicenseRadioReject.setSelection(ai != null && ai.isRejected()); - } - - // The install button is enabled if there's at least one package accepted. - // If the current one isn't, look for another one. - boolean missing = mErrorLabel.getText() != null && mErrorLabel.getText().length() > 0; - if (!missing && !oneAccepted) { - for(ArchiveInfo ai2 : mArchives) { - if (ai2.isAccepted()) { - oneAccepted = true; - break; - } - } - } - - getButton(IDialogConstants.OK_ID).setEnabled(!missing && oneAccepted); - - mInternalLicenseRadioUpdate = false; - } - - /** - * Callback invoked when one of the radio license buttons is selected. - * - * - accept/refuse: toggle, update item checkbox - * - accept all: set accept-all, check all items - */ - private void onLicenseRadioSelected() { - if (mInternalLicenseRadioUpdate) { - return; - } - mInternalLicenseRadioUpdate = true; - - ArchiveInfo ai = getSelectedArchive(); - - if (ai == null) { - // Should never happen. - return; - } - - boolean needUpdate = true; - - if (!mLicenseAcceptAll && mLicenseRadioAcceptAll.getSelection()) { - // Accept all has been switched on. Mark all packages as accepted - mLicenseAcceptAll = true; - for(ArchiveInfo ai2 : mArchives) { - ai2.setAccepted(true); - ai2.setRejected(false); - } - - } else if (mLicenseRadioAccept.getSelection()) { - // Accept only this one - mLicenseAcceptAll = false; - ai.setAccepted(true); - ai.setRejected(false); - - } else if (mLicenseRadioReject.getSelection()) { - // Reject only this one - mLicenseAcceptAll = false; - ai.setAccepted(false); - ai.setRejected(true); - - } else { - needUpdate = false; - } - - mInternalLicenseRadioUpdate = false; - - if (needUpdate) { - if (mLicenseAcceptAll) { - mTableViewPackage.refresh(); - } else { - mTableViewPackage.refresh(ai); - } - displayMissingDependency(ai); - updateLicenceRadios(ai); - } - } - - /** - * Callback invoked when a package item is double-clicked in the list. - */ - private void onPackageDoubleClick() { - ArchiveInfo ai = getSelectedArchive(); - - if (ai == null) { - // Should never happen. - return; - } - - boolean wasAccepted = ai.isAccepted(); - ai.setAccepted(!wasAccepted); - ai.setRejected(wasAccepted); - - // update state - mLicenseAcceptAll = false; - mTableViewPackage.refresh(ai); - displayMissingDependency(ai); - updateLicenceRadios(ai); - } - - private class NewArchivesLabelProvider extends LabelProvider { - @Override - public Image getImage(Object element) { - assert element instanceof ArchiveInfo; - ArchiveInfo ai = (ArchiveInfo) element; - - ImageFactory imgFactory = mUpdaterData.getImageFactory(); - if (imgFactory != null) { - if (ai.isAccepted()) { - return imgFactory.getImageByName("accept_icon16.png"); - } else if (ai.isRejected()) { - return imgFactory.getImageByName("reject_icon16.png"); - } - return imgFactory.getImageByName("unknown_icon16.png"); - } - return super.getImage(element); - } - - @Override - public String getText(Object element) { - assert element instanceof ArchiveInfo; - ArchiveInfo ai = (ArchiveInfo) element; - - String desc = ai.getShortDescription(); - - if (ai.isDependencyFor()) { - desc += " [*]"; - } - - return desc; - } - } - - private class NewArchivesContentProvider implements IStructuredContentProvider { - - @Override - public void dispose() { - // pass - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - // Ignore. The input is always mArchives - } - - @Override - public Object[] getElements(Object inputElement) { - return mArchives.toArray(); - } - } - - // End of hiding from SWT Designer - //$hide<<$ -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SdkUpdaterLogic.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SdkUpdaterLogic.java deleted file mode 100755 index 25e6553..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SdkUpdaterLogic.java +++ /dev/null @@ -1,1477 +0,0 @@ -/* - * 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.repository; - -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.packages.AddonPackage; -import com.android.sdklib.internal.repository.packages.DocPackage; -import com.android.sdklib.internal.repository.packages.ExtraPackage; -import com.android.sdklib.internal.repository.packages.FullRevision; -import com.android.sdklib.internal.repository.packages.IAndroidVersionProvider; -import com.android.sdklib.internal.repository.packages.IExactApiLevelDependency; -import com.android.sdklib.internal.repository.packages.IMinApiLevelDependency; -import com.android.sdklib.internal.repository.packages.IMinPlatformToolsDependency; -import com.android.sdklib.internal.repository.packages.IMinToolsDependency; -import com.android.sdklib.internal.repository.packages.IPlatformDependency; -import com.android.sdklib.internal.repository.packages.MinToolsPackage; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.packages.Package.UpdateInfo; -import com.android.sdklib.internal.repository.packages.PlatformPackage; -import com.android.sdklib.internal.repository.packages.PlatformToolPackage; -import com.android.sdklib.internal.repository.packages.SamplePackage; -import com.android.sdklib.internal.repository.packages.SystemImagePackage; -import com.android.sdklib.internal.repository.packages.ToolPackage; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.internal.repository.sources.SdkSources; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * The logic to compute which packages to install, based on the choices - * made by the user. This adds required packages as needed. - * <p/> - * When the user doesn't provide a selection, looks at local package to find - * those that can be updated and compute dependencies too. - */ -class SdkUpdaterLogic { - - private final IUpdaterData mUpdaterData; - - public SdkUpdaterLogic(IUpdaterData updaterData) { - mUpdaterData = updaterData; - } - - /** - * Retrieves an unfiltered list of all remote archives. - * The archives are guaranteed to be compatible with the current platform. - */ - public List<ArchiveInfo> getAllRemoteArchives( - SdkSources sources, - Package[] localPkgs, - boolean includeAll) { - - List<Package> remotePkgs = new ArrayList<Package>(); - SdkSource[] remoteSources = sources.getAllSources(); - fetchRemotePackages(remotePkgs, remoteSources); - - ArrayList<Archive> archives = new ArrayList<Archive>(); - for (Package remotePkg : remotePkgs) { - // Only look for non-obsolete updates unless requested to include them - if (includeAll || !remotePkg.isObsolete()) { - // Found a suitable update. Only accept the remote package - // if it provides at least one compatible archive - - addArchives: - for (Archive a : remotePkg.getArchives()) { - if (a.isCompatible()) { - - // If we're trying to add a package for revision N, - // make sure we don't also have a package for revision N-1. - for (int i = archives.size() - 1; i >= 0; i--) { - Package pkgFound = archives.get(i).getParentPackage(); - if (pkgFound.canBeUpdatedBy(remotePkg) == UpdateInfo.UPDATE) { - // This package can update one we selected earlier. - // Remove the one that can be updated by this new one. - archives.remove(i); - } else if (remotePkg.canBeUpdatedBy(pkgFound) == UpdateInfo.UPDATE) { - // There is a package in the list that is already better - // than the one we want to add, so don't add it. - break addArchives; - } - } - - archives.add(a); - break; - } - } - } - } - - ArrayList<ArchiveInfo> result = new ArrayList<ArchiveInfo>(); - - ArchiveInfo[] localArchives = createLocalArchives(localPkgs); - - for (Archive a : archives) { - insertArchive(a, - result, - archives, - remotePkgs, - remoteSources, - localArchives, - false /*automated*/); - } - - return result; - } - - /** - * Compute which packages to install by taking the user selection - * and adding required packages as needed. - * - * When the user doesn't provide a selection, looks at local packages to find - * those that can be updated and compute dependencies too. - */ - public List<ArchiveInfo> computeUpdates( - Collection<Archive> selectedArchives, - SdkSources sources, - Package[] localPkgs, - boolean includeAll) { - - List<ArchiveInfo> archives = new ArrayList<ArchiveInfo>(); - List<Package> remotePkgs = new ArrayList<Package>(); - SdkSource[] remoteSources = sources.getAllSources(); - - // Create ArchiveInfos out of local (installed) packages. - ArchiveInfo[] localArchives = createLocalArchives(localPkgs); - - // If we do not have a specific list of archives to install (that is the user - // selected "update all" rather than request specific packages), then we try to - // find updates based on the *existing* packages. - if (selectedArchives == null) { - selectedArchives = findUpdates( - localArchives, - remotePkgs, - remoteSources, - includeAll); - } - - // Once we have a list of packages to install, we try to solve all their - // dependencies by automatically adding them to the list of things to install. - // This works on the list provided either by the user directly or the list - // computed from potential updates. - for (Archive a : selectedArchives) { - insertArchive(a, - archives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - false /*automated*/); - } - - // Finally we need to look at *existing* packages which are not being updated - // and check if they have any missing dependencies and suggest how to fix - // these dependencies. - fixMissingLocalDependencies( - archives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives); - - return archives; - } - - private double getRevisionRank(FullRevision rev) { - int p = rev.isPreview() ? 999 : 999 - rev.getPreview(); - return rev.getMajor() + - rev.getMinor() / 1000.d + - rev.getMicro() / 1000000.d + - p / 1000000000.d; - } - - /** - * Finds new packages that the user does not have in his/her local SDK - * and adds them to the list of archives to install. - * <p/> - * The default is to only find "new" platforms, that is anything more - * recent than the highest platform currently installed. - * A side effect is that for an empty SDK install this will list *all* - * platforms available (since there's no "highest" installed platform.) - * - * @param archives The in-out list of archives to install. Typically the - * list is not empty at first as it should contain any archives that is - * already scheduled for install. This method will add to the list. - * @param sources The list of all sources, to fetch them as necessary. - * @param localPkgs The list of all currently installed packages. - * @param includeAll When true, this will list all platforms. - * (included these lower than the highest installed one) as well as - * all obsolete packages of these platforms. - */ - public void addNewPlatforms( - Collection<ArchiveInfo> archives, - SdkSources sources, - Package[] localPkgs, - boolean includeAll) { - - // Create ArchiveInfos out of local (installed) packages. - ArchiveInfo[] localArchives = createLocalArchives(localPkgs); - - // Find the highest platform installed - double currentPlatformScore = 0; - double currentSampleScore = 0; - double currentAddonScore = 0; - double currentDocScore = 0; - HashMap<String, Double> currentExtraScore = new HashMap<String, Double>(); - if (!includeAll) { - if (localPkgs != null) { - for (Package p : localPkgs) { - double rev = getRevisionRank(p.getRevision()); - int api = 0; - boolean isPreview = false; - if (p instanceof IAndroidVersionProvider) { - AndroidVersion vers = ((IAndroidVersionProvider) p).getAndroidVersion(); - api = vers.getApiLevel(); - isPreview = vers.isPreview(); - } - - // The score is 1000*api + (999 if preview) + rev - // This allows previews to rank above a non-preview and - // allows revisions to rank appropriately. - double score = api * 1000 + (isPreview ? 999 : 0) + rev; - - if (p instanceof PlatformPackage) { - currentPlatformScore = Math.max(currentPlatformScore, score); - } else if (p instanceof SamplePackage) { - currentSampleScore = Math.max(currentSampleScore, score); - } else if (p instanceof AddonPackage) { - currentAddonScore = Math.max(currentAddonScore, score); - } else if (p instanceof ExtraPackage) { - currentExtraScore.put(((ExtraPackage) p).getPath(), score); - } else if (p instanceof DocPackage) { - currentDocScore = Math.max(currentDocScore, score); - } - } - } - } - - SdkSource[] remoteSources = sources.getAllSources(); - ArrayList<Package> remotePkgs = new ArrayList<Package>(); - fetchRemotePackages(remotePkgs, remoteSources); - - Package suggestedDoc = null; - - for (Package p : remotePkgs) { - // Skip obsolete packages unless requested to include them. - if (p.isObsolete() && !includeAll) { - continue; - } - - double rev = getRevisionRank(p.getRevision()); - int api = 0; - boolean isPreview = false; - if (p instanceof IAndroidVersionProvider) { - AndroidVersion vers = ((IAndroidVersionProvider) p).getAndroidVersion(); - api = vers.getApiLevel(); - isPreview = vers.isPreview(); - } - - double score = api * 1000 + (isPreview ? 999 : 0) + rev; - - boolean shouldAdd = false; - if (p instanceof PlatformPackage) { - shouldAdd = score > currentPlatformScore; - } else if (p instanceof SamplePackage) { - shouldAdd = score > currentSampleScore; - } else if (p instanceof AddonPackage) { - shouldAdd = score > currentAddonScore; - } else if (p instanceof ExtraPackage) { - String key = ((ExtraPackage) p).getPath(); - shouldAdd = !currentExtraScore.containsKey(key) || - score > currentExtraScore.get(key).doubleValue(); - } else if (p instanceof DocPackage) { - // We don't want all the doc, only the most recent one - if (score > currentDocScore) { - suggestedDoc = p; - currentDocScore = score; - } - } - - if (shouldAdd) { - // We should suggest this package for installation. - for (Archive a : p.getArchives()) { - if (a.isCompatible()) { - insertArchive(a, - archives, - null /*selectedArchives*/, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - - if (p instanceof PlatformPackage && (score >= currentPlatformScore)) { - // We just added a new platform *or* we are visiting the highest currently - // installed platform. In either case we want to make sure it either has - // its own system image or that we provide one by default. - PlatformPackage pp = (PlatformPackage) p; - if (pp.getIncludedAbi() == null) { - for (Package p2 : remotePkgs) { - if (!(p2 instanceof SystemImagePackage) || - (p2.isObsolete() && !includeAll)) { - continue; - } - SystemImagePackage sip = (SystemImagePackage) p2; - if (sip.getAndroidVersion().equals(pp.getAndroidVersion())) { - for (Archive a : sip.getArchives()) { - if (a.isCompatible()) { - insertArchive(a, - archives, - null /*selectedArchives*/, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - } - } - } - } - - if (suggestedDoc != null) { - // We should suggest this package for installation. - for (Archive a : suggestedDoc.getArchives()) { - if (a.isCompatible()) { - insertArchive(a, - archives, - null /*selectedArchives*/, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - } - - /** - * Create a array of {@link ArchiveInfo} based on all local (already installed) - * packages. The array is always non-null but may be empty. - * <p/> - * The local {@link ArchiveInfo} are guaranteed to have one non-null archive - * that you can retrieve using {@link ArchiveInfo#getNewArchive()}. - */ - protected ArchiveInfo[] createLocalArchives(Package[] localPkgs) { - - if (localPkgs != null) { - ArrayList<ArchiveInfo> list = new ArrayList<ArchiveInfo>(); - for (Package p : localPkgs) { - // Only accept packages that have one compatible archive. - // Local package should have 1 and only 1 compatible archive anyway. - for (Archive a : p.getArchives()) { - if (a != null && a.isCompatible()) { - // We create an "installed" archive info to wrap the local package. - // Note that dependencies are not computed since right now we don't - // deal with more than one level of dependencies and installed archives - // are deemed implicitly accepted anyway. - list.add(new LocalArchiveInfo(a)); - } - } - } - - return list.toArray(new ArchiveInfo[list.size()]); - } - - return new ArchiveInfo[0]; - } - - /** - * Find suitable updates to all current local packages. - * <p/> - * Returns a list of potential updates for *existing* packages. This does NOT solve - * dependencies for the new packages. - * <p/> - * Always returns a non-null collection, which can be empty. - */ - private Collection<Archive> findUpdates( - ArchiveInfo[] localArchives, - Collection<Package> remotePkgs, - SdkSource[] remoteSources, - boolean includeAll) { - ArrayList<Archive> updates = new ArrayList<Archive>(); - - fetchRemotePackages(remotePkgs, remoteSources); - - for (ArchiveInfo ai : localArchives) { - Archive na = ai.getNewArchive(); - if (na == null) { - continue; - } - Package localPkg = na.getParentPackage(); - - for (Package remotePkg : remotePkgs) { - // Only look for non-obsolete updates unless requested to include them - if ((includeAll || !remotePkg.isObsolete()) && - localPkg.canBeUpdatedBy(remotePkg) == UpdateInfo.UPDATE) { - // Found a suitable update. Only accept the remote package - // if it provides at least one compatible archive - - addArchives: - for (Archive a : remotePkg.getArchives()) { - if (a.isCompatible()) { - - // If we're trying to add a package for revision N, - // make sure we don't also have a package for revision N-1. - for (int i = updates.size() - 1; i >= 0; i--) { - Package pkgFound = updates.get(i).getParentPackage(); - if (pkgFound.canBeUpdatedBy(remotePkg) == UpdateInfo.UPDATE) { - // This package can update one we selected earlier. - // Remove the one that can be updated by this new one. - updates.remove(i); - } else if (remotePkg.canBeUpdatedBy(pkgFound) == - UpdateInfo.UPDATE) { - // There is a package in the list that is already better - // than the one we want to add, so don't add it. - break addArchives; - } - } - - updates.add(a); - break; - } - } - } - } - } - - return updates; - } - - /** - * Check all local archives which are NOT being updated and see if they - * miss any dependency. If they do, try to fix that dependency by selecting - * an appropriate package. - */ - private void fixMissingLocalDependencies( - Collection<ArchiveInfo> outArchives, - Collection<Archive> selectedArchives, - Collection<Package> remotePkgs, - SdkSource[] remoteSources, - ArchiveInfo[] localArchives) { - - nextLocalArchive: for (ArchiveInfo ai : localArchives) { - Archive a = ai.getNewArchive(); - Package p = a == null ? null : a.getParentPackage(); - if (p == null) { - continue; - } - - // Is this local archive being updated? - for (ArchiveInfo ai2 : outArchives) { - if (ai2.getReplaced() == a) { - // this new archive will replace the current local one, - // so we don't have to care about fixing dependencies (since the - // new archive should already have had its dependencies resolved) - continue nextLocalArchive; - } - } - - // find dependencies for the local archive and add them as needed - // to the outArchives collection. - ArchiveInfo[] deps = findDependency(p, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives); - - if (deps != null) { - // The already installed archive has a missing dependency, which we - // just selected for install. Make sure we remember the dependency - // so that we can enforce it later in the UI. - for (ArchiveInfo aid : deps) { - aid.addDependencyFor(ai); - } - } - } - } - - private ArchiveInfo insertArchive(Archive archive, - Collection<ArchiveInfo> outArchives, - Collection<Archive> selectedArchives, - Collection<Package> remotePkgs, - SdkSource[] remoteSources, - ArchiveInfo[] localArchives, - boolean automated) { - Package p = archive.getParentPackage(); - - // Is this an update? - Archive updatedArchive = null; - for (ArchiveInfo ai : localArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package lp = a.getParentPackage(); - - if (lp.canBeUpdatedBy(p) == UpdateInfo.UPDATE) { - updatedArchive = a; - } - } - } - - // Find dependencies and adds them as needed to outArchives - ArchiveInfo[] deps = findDependency(p, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives); - - // Make sure it's not a dup - ArchiveInfo ai = null; - - for (ArchiveInfo ai2 : outArchives) { - Archive a2 = ai2.getNewArchive(); - if (a2 != null && a2.getParentPackage().sameItemAs(archive.getParentPackage())) { - ai = ai2; - break; - } - } - - if (ai == null) { - ai = new ArchiveInfo( - archive, //newArchive - updatedArchive, //replaced - deps //dependsOn - ); - outArchives.add(ai); - } - - if (deps != null) { - for (ArchiveInfo d : deps) { - d.addDependencyFor(ai); - } - } - - return ai; - } - - /** - * Resolves dependencies for a given package. - * - * Returns null if no dependencies were found. - * Otherwise return an array of {@link ArchiveInfo}, which is guaranteed to have - * at least size 1 and contain no null elements. - */ - private ArchiveInfo[] findDependency(Package pkg, - Collection<ArchiveInfo> outArchives, - Collection<Archive> selectedArchives, - Collection<Package> remotePkgs, - SdkSource[] remoteSources, - ArchiveInfo[] localArchives) { - - // Current dependencies can be: - // - addon: *always* depends on platform of same API level - // - platform: *might* depends on tools of rev >= min-tools-rev - // - extra: *might* depends on platform with api >= min-api-level - - Set<ArchiveInfo> aiFound = new HashSet<ArchiveInfo>(); - - if (pkg instanceof IPlatformDependency) { - ArchiveInfo ai = findPlatformDependency( - (IPlatformDependency) pkg, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives); - - if (ai != null) { - aiFound.add(ai); - } - } - - if (pkg instanceof IMinToolsDependency) { - - ArchiveInfo ai = findToolsDependency( - (IMinToolsDependency) pkg, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives); - - if (ai != null) { - aiFound.add(ai); - } - } - - if (pkg instanceof IMinPlatformToolsDependency) { - - ArchiveInfo ai = findPlatformToolsDependency( - (IMinPlatformToolsDependency) pkg, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives); - - if (ai != null) { - aiFound.add(ai); - } - } - - if (pkg instanceof IMinApiLevelDependency) { - - ArchiveInfo ai = findMinApiLevelDependency( - (IMinApiLevelDependency) pkg, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives); - - if (ai != null) { - aiFound.add(ai); - } - } - - if (pkg instanceof IExactApiLevelDependency) { - - ArchiveInfo ai = findExactApiLevelDependency( - (IExactApiLevelDependency) pkg, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives); - - if (ai != null) { - aiFound.add(ai); - } - } - - if (aiFound.size() > 0) { - ArchiveInfo[] result = aiFound.toArray(new ArchiveInfo[aiFound.size()]); - Arrays.sort(result); - return result; - } - - return null; - } - - /** - * Resolves dependencies on tools. - * - * A platform or an extra package can both have a min-tools-rev, in which case it - * depends on having a tools package of the requested revision. - * Finds the tools dependency. If found, add it to the list of things to install. - * Returns the archive info dependency, if any. - */ - protected ArchiveInfo findToolsDependency( - IMinToolsDependency pkg, - Collection<ArchiveInfo> outArchives, - Collection<Archive> selectedArchives, - Collection<Package> remotePkgs, - SdkSource[] remoteSources, - ArchiveInfo[] localArchives) { - // This is the requirement to match. - FullRevision rev = pkg.getMinToolsRevision(); - - if (rev.equals(MinToolsPackage.MIN_TOOLS_REV_NOT_SPECIFIED)) { - // Well actually there's no requirement. - return null; - } - - // First look in locally installed packages. - for (ArchiveInfo ai : localArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof ToolPackage) { - if (((ToolPackage) p).getRevision().compareTo(rev) >= 0) { - // We found one already installed. - return null; - } - } - } - } - - // Look in archives already scheduled for install - for (ArchiveInfo ai : outArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof ToolPackage) { - if (((ToolPackage) p).getRevision().compareTo(rev) >= 0) { - // The dependency is already scheduled for install, nothing else to do. - return ai; - } - } - } - } - - // Otherwise look in the selected archives. - if (selectedArchives != null) { - for (Archive a : selectedArchives) { - Package p = a.getParentPackage(); - if (p instanceof ToolPackage) { - if (((ToolPackage) p).getRevision().compareTo(rev) >= 0) { - // It's not already in the list of things to install, so add it now - return insertArchive(a, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - } - - // Finally nothing matched, so let's look at all available remote packages - fetchRemotePackages(remotePkgs, remoteSources); - FullRevision localRev = rev; - Archive localArch = null; - for (Package p : remotePkgs) { - if (p instanceof ToolPackage) { - FullRevision r = ((ToolPackage) p).getRevision(); - if (r.compareTo(localRev) >= 0) { - // It's not already in the list of things to install, so add the - // first compatible archive we can find. - for (Archive a : p.getArchives()) { - if (a.isCompatible()) { - localRev = r; - localArch = a; - break; - } - } - } - } - } - if (localArch != null) { - return insertArchive(localArch, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - - } - - // We end up here if nothing matches. We don't have a good platform to match. - // We need to indicate this extra depends on a missing platform archive - // so that it can be impossible to install later on. - return new MissingArchiveInfo(MissingArchiveInfo.TITLE_TOOL, rev); - } - - /** - * Resolves dependencies on platform-tools. - * - * A tool package can have a min-platform-tools-rev, in which case it depends on - * having a platform-tool package of the requested revision. - * Finds the platform-tool dependency. If found, add it to the list of things to install. - * Returns the archive info dependency, if any. - */ - protected ArchiveInfo findPlatformToolsDependency( - IMinPlatformToolsDependency pkg, - Collection<ArchiveInfo> outArchives, - Collection<Archive> selectedArchives, - Collection<Package> remotePkgs, - SdkSource[] remoteSources, - ArchiveInfo[] localArchives) { - // This is the requirement to match. - FullRevision rev = pkg.getMinPlatformToolsRevision(); - boolean findMax = false; - int compareThreshold = 0; - ArchiveInfo aiMax = null; - Archive aMax = null; - - if (rev.equals(IMinPlatformToolsDependency.MIN_PLATFORM_TOOLS_REV_INVALID)) { - // The requirement is invalid, which is not supposed to happen since this - // property is mandatory. However in a typical upgrade scenario we can end - // up with the previous updater managing a new package and not dealing - // correctly with the new unknown property. - // So instead we parse all the existing and remote packages and try to find - // the max available revision and we'll use it. - findMax = true; - // When findMax is false, we want r.compareTo(rev) >= 0. - // When findMax is true, we want r.compareTo(rev) > 0 (so >= 1). - compareThreshold = 1; - } - - // First look in locally installed packages. - for (ArchiveInfo ai : localArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof PlatformToolPackage) { - FullRevision r = ((PlatformToolPackage) p).getRevision(); - if (findMax && r.compareTo(rev) > compareThreshold) { - rev = r; - aiMax = ai; - } else if (!findMax && r.compareTo(rev) >= compareThreshold) { - // We found one already installed. - return null; - } - } - } - } - - // Because of previews, we can have more than 1 choice, so get the local max. - FullRevision localRev = rev; - ArchiveInfo localAiMax = null; - // Look in archives already scheduled for install - for (ArchiveInfo ai : outArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof PlatformToolPackage) { - FullRevision r = ((PlatformToolPackage) p).getRevision(); - if (r.compareTo(localRev) >= compareThreshold) { - localRev = r; - localAiMax = ai; - } - } - } - } - if (localAiMax != null) { - if (findMax) { - rev = localRev; - aiMax = localAiMax; - } else { - // The dependency is already scheduled for install, nothing else to do. - return localAiMax; - } - } - - - // Otherwise look in the selected archives. - localRev = rev; - Archive localAMax = null; - if (selectedArchives != null) { - for (Archive a : selectedArchives) { - Package p = a.getParentPackage(); - if (p instanceof PlatformToolPackage) { - FullRevision r = ((PlatformToolPackage) p).getRevision(); - if (r.compareTo(localRev) >= compareThreshold) { - localRev = r; - localAiMax = null; - localAMax = a; - } - } - } - if (localAMax != null) { - if (findMax) { - rev = localRev; - aiMax = null; - aMax = localAMax; - } else { - // It's not already in the list of things to install, so add it now - return insertArchive(localAMax, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - - // Finally nothing matched, so let's look at all available remote packages - fetchRemotePackages(remotePkgs, remoteSources); - localRev = rev; - localAMax = null; - for (Package p : remotePkgs) { - if (p instanceof PlatformToolPackage) { - FullRevision r = ((PlatformToolPackage) p).getRevision(); - if (r.compareTo(rev) >= 0) { - // Make sure there's at least one valid archive here - for (Archive a : p.getArchives()) { - if (a.isCompatible()) { - if (r.compareTo(localRev) >= compareThreshold) { - localRev = r; - localAiMax = null; - localAMax = a; - break; - } - } - } - } - } - } - if (localAMax != null) { - if (findMax) { - rev = localRev; - aiMax = null; - aMax = localAMax; - } else { - // It's not already in the list of things to install, so add the - // first compatible archive we can find. - return insertArchive(localAMax, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - - if (findMax) { - if (aMax != null) { - return insertArchive(aMax, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } else if (aiMax != null) { - return aiMax; - } - } - - // We end up here if nothing matches. We don't have a good platform to match. - // We need to indicate this package depends on a missing platform archive - // so that it can be impossible to install later on. - return new MissingArchiveInfo(MissingArchiveInfo.TITLE_PLATFORM_TOOL, rev); - } - - /** - * Resolves dependencies on platform for an addon. - * - * An addon depends on having a platform with the same API level. - * - * Finds the platform dependency. If found, add it to the list of things to install. - * Returns the archive info dependency, if any. - */ - protected ArchiveInfo findPlatformDependency( - IPlatformDependency pkg, - Collection<ArchiveInfo> outArchives, - Collection<Archive> selectedArchives, - Collection<Package> remotePkgs, - SdkSource[] remoteSources, - ArchiveInfo[] localArchives) { - // This is the requirement to match. - AndroidVersion v = pkg.getAndroidVersion(); - - // Find a platform that would satisfy the requirement. - - // First look in locally installed packages. - for (ArchiveInfo ai : localArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof PlatformPackage) { - if (v.equals(((PlatformPackage) p).getAndroidVersion())) { - // We found one already installed. - return null; - } - } - } - } - - // Look in archives already scheduled for install - for (ArchiveInfo ai : outArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof PlatformPackage) { - if (v.equals(((PlatformPackage) p).getAndroidVersion())) { - // The dependency is already scheduled for install, nothing else to do. - return ai; - } - } - } - } - - // Otherwise look in the selected archives. - if (selectedArchives != null) { - for (Archive a : selectedArchives) { - Package p = a.getParentPackage(); - if (p instanceof PlatformPackage) { - if (v.equals(((PlatformPackage) p).getAndroidVersion())) { - // It's not already in the list of things to install, so add it now - return insertArchive(a, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - } - - // Finally nothing matched, so let's look at all available remote packages - fetchRemotePackages(remotePkgs, remoteSources); - for (Package p : remotePkgs) { - if (p instanceof PlatformPackage) { - if (v.equals(((PlatformPackage) p).getAndroidVersion())) { - // It's not already in the list of things to install, so add the - // first compatible archive we can find. - for (Archive a : p.getArchives()) { - if (a.isCompatible()) { - return insertArchive(a, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - } - } - - // We end up here if nothing matches. We don't have a good platform to match. - // We need to indicate this addon depends on a missing platform archive - // so that it can be impossible to install later on. - return new MissingPlatformArchiveInfo(pkg.getAndroidVersion()); - } - - /** - * Resolves platform dependencies for extras. - * An extra depends on having a platform with a minimun API level. - * - * We try to return the highest API level available above the specified minimum. - * Note that installed packages have priority so if one installed platform satisfies - * the dependency, we'll use it even if there's a higher API platform available but - * not installed yet. - * - * Finds the platform dependency. If found, add it to the list of things to install. - * Returns the archive info dependency, if any. - */ - protected ArchiveInfo findMinApiLevelDependency( - IMinApiLevelDependency pkg, - Collection<ArchiveInfo> outArchives, - Collection<Archive> selectedArchives, - Collection<Package> remotePkgs, - SdkSource[] remoteSources, - ArchiveInfo[] localArchives) { - - int api = pkg.getMinApiLevel(); - - if (api == IMinApiLevelDependency.MIN_API_LEVEL_NOT_SPECIFIED) { - return null; - } - - // Find a platform that would satisfy the requirement. - - // First look in locally installed packages. - for (ArchiveInfo ai : localArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof PlatformPackage) { - if (((PlatformPackage) p).getAndroidVersion().isGreaterOrEqualThan(api)) { - // We found one already installed. - return null; - } - } - } - } - - // Look in archives already scheduled for install - int foundApi = 0; - ArchiveInfo foundAi = null; - - for (ArchiveInfo ai : outArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof PlatformPackage) { - if (((PlatformPackage) p).getAndroidVersion().isGreaterOrEqualThan(api)) { - if (api > foundApi) { - foundApi = api; - foundAi = ai; - } - } - } - } - } - - if (foundAi != null) { - // The dependency is already scheduled for install, nothing else to do. - return foundAi; - } - - // Otherwise look in the selected archives *or* available remote packages - // and takes the best out of the two sets. - foundApi = 0; - Archive foundArchive = null; - if (selectedArchives != null) { - for (Archive a : selectedArchives) { - Package p = a.getParentPackage(); - if (p instanceof PlatformPackage) { - if (((PlatformPackage) p).getAndroidVersion().isGreaterOrEqualThan(api)) { - if (api > foundApi) { - foundApi = api; - foundArchive = a; - } - } - } - } - } - - // Finally nothing matched, so let's look at all available remote packages - fetchRemotePackages(remotePkgs, remoteSources); - for (Package p : remotePkgs) { - if (p instanceof PlatformPackage) { - if (((PlatformPackage) p).getAndroidVersion().isGreaterOrEqualThan(api)) { - if (api > foundApi) { - // It's not already in the list of things to install, so add the - // first compatible archive we can find. - for (Archive a : p.getArchives()) { - if (a.isCompatible()) { - foundApi = api; - foundArchive = a; - } - } - } - } - } - } - - if (foundArchive != null) { - // It's not already in the list of things to install, so add it now - return insertArchive(foundArchive, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - - // We end up here if nothing matches. We don't have a good platform to match. - // We need to indicate this extra depends on a missing platform archive - // so that it can be impossible to install later on. - return new MissingPlatformArchiveInfo(new AndroidVersion(api, null /*codename*/)); - } - - /** - * Resolves platform dependencies for add-ons. - * An add-ons depends on having a platform with an exact specific API level. - * - * Finds the platform dependency. If found, add it to the list of things to install. - * Returns the archive info dependency, if any. - */ - protected ArchiveInfo findExactApiLevelDependency( - IExactApiLevelDependency pkg, - Collection<ArchiveInfo> outArchives, - Collection<Archive> selectedArchives, - Collection<Package> remotePkgs, - SdkSource[] remoteSources, - ArchiveInfo[] localArchives) { - - int api = pkg.getExactApiLevel(); - - if (api == IExactApiLevelDependency.API_LEVEL_INVALID) { - return null; - } - - // Find a platform that would satisfy the requirement. - - // First look in locally installed packages. - for (ArchiveInfo ai : localArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof PlatformPackage) { - if (((PlatformPackage) p).getAndroidVersion().equals(api)) { - // We found one already installed. - return null; - } - } - } - } - - // Look in archives already scheduled for install - - for (ArchiveInfo ai : outArchives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p instanceof PlatformPackage) { - if (((PlatformPackage) p).getAndroidVersion().equals(api)) { - return ai; - } - } - } - } - - // Otherwise look in the selected archives. - if (selectedArchives != null) { - for (Archive a : selectedArchives) { - Package p = a.getParentPackage(); - if (p instanceof PlatformPackage) { - if (((PlatformPackage) p).getAndroidVersion().equals(api)) { - // It's not already in the list of things to install, so add it now - return insertArchive(a, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - } - - // Finally nothing matched, so let's look at all available remote packages - fetchRemotePackages(remotePkgs, remoteSources); - for (Package p : remotePkgs) { - if (p instanceof PlatformPackage) { - if (((PlatformPackage) p).getAndroidVersion().equals(api)) { - // It's not already in the list of things to install, so add the - // first compatible archive we can find. - for (Archive a : p.getArchives()) { - if (a.isCompatible()) { - return insertArchive(a, - outArchives, - selectedArchives, - remotePkgs, - remoteSources, - localArchives, - true /*automated*/); - } - } - } - } - } - - // We end up here if nothing matches. We don't have a good platform to match. - // We need to indicate this extra depends on a missing platform archive - // so that it can be impossible to install later on. - return new MissingPlatformArchiveInfo(new AndroidVersion(api, null /*codename*/)); - } - - /** - * Fetch all remote packages only if really needed. - * <p/> - * This method takes a list of sources. Each source is only fetched once -- that is each - * source keeps the list of packages that we fetched from the remote XML file. If the list - * is null, it means this source has never been fetched so we'll do it once here. Otherwise - * we rely on the cached list of packages from this source. - * <p/> - * This method also takes a remote package list as input, which it will fill out. - * If a source has already been fetched, we'll add its packages to the remote package list - * if they are not already present. Otherwise, the source will be fetched and the packages - * added to the list. - * - * @param remotePkgs An in-out list of packages available from remote sources. - * This list must not be null. - * It can be empty or already contain some packages. - * @param remoteSources A list of available remote sources to fetch from. - */ - protected void fetchRemotePackages( - final Collection<Package> remotePkgs, - final SdkSource[] remoteSources) { - if (remotePkgs.size() > 0) { - return; - } - - // First check if there's any remote source we need to fetch. - // This will bring the task window, so we rather not display it unless - // necessary. - boolean needsFetch = false; - for (final SdkSource remoteSrc : remoteSources) { - Package[] pkgs = remoteSrc.getPackages(); - if (pkgs == null) { - // This source has never been fetched. We'll do it below. - needsFetch = true; - } else { - // This source has already been fetched and we know its package list. - // We still need to make sure all of its packages are present in the - // remotePkgs list. - - nextPackage: for (Package pkg : pkgs) { - for (Archive a : pkg.getArchives()) { - // Only add a package if it contains at least one compatible archive - // and is not already in the remote package list. - if (a.isCompatible()) { - if (!remotePkgs.contains(pkg)) { - remotePkgs.add(pkg); - continue nextPackage; - } - } - } - } - } - } - - if (!needsFetch) { - return; - } - - final boolean forceHttp = mUpdaterData.getSettingsController().getSettings().getForceHttp(); - - mUpdaterData.getTaskFactory().start("Refresh Sources", new ITask() { - @Override - public void run(ITaskMonitor monitor) { - for (SdkSource remoteSrc : remoteSources) { - Package[] pkgs = remoteSrc.getPackages(); - - if (pkgs == null) { - remoteSrc.load(mUpdaterData.getDownloadCache(), monitor, forceHttp); - pkgs = remoteSrc.getPackages(); - } - - if (pkgs != null) { - nextPackage: for (Package pkg : pkgs) { - for (Archive a : pkg.getArchives()) { - // Only add a package if it contains at least one compatible archive - // and is not already in the remote package list. - if (a.isCompatible()) { - if (!remotePkgs.contains(pkg)) { - remotePkgs.add(pkg); - continue nextPackage; - } - } - } - } - } - } - } - }); - } - - - /** - * A {@link LocalArchiveInfo} is an {@link ArchiveInfo} that wraps an already installed - * "local" package/archive. - * <p/> - * In this case, the "new Archive" is still expected to be non null and the - * "replaced Archive" is null. Installed archives are always accepted and never - * rejected. - * <p/> - * Dependencies are not set. - */ - private static class LocalArchiveInfo extends ArchiveInfo { - - public LocalArchiveInfo(Archive localArchive) { - super(localArchive, null /*replaced*/, null /*dependsOn*/); - } - - /** Installed archives are always accepted. */ - @Override - public boolean isAccepted() { - return true; - } - - /** Installed archives are never rejected. */ - @Override - public boolean isRejected() { - return false; - } - } - - /** - * A {@link MissingPlatformArchiveInfo} is an {@link ArchiveInfo} that represents a - * package/archive that we <em>really</em> need as a dependency but that we don't have. - * <p/> - * This is currently used for addons and extras in case we can't find a matching base platform. - * <p/> - * This kind of archive has specific properties: the new archive to install is null, - * there are no dependencies and no archive is being replaced. The info can never be - * accepted and is always rejected. - */ - private static class MissingPlatformArchiveInfo extends ArchiveInfo { - - private final AndroidVersion mVersion; - - /** - * Constructs a {@link MissingPlatformArchiveInfo} that will indicate the - * given platform version is missing. - */ - public MissingPlatformArchiveInfo(AndroidVersion version) { - super(null /*newArchive*/, null /*replaced*/, null /*dependsOn*/); - mVersion = version; - } - - /** Missing archives are never accepted. */ - @Override - public boolean isAccepted() { - return false; - } - - /** Missing archives are always rejected. */ - @Override - public boolean isRejected() { - return true; - } - - @Override - public String getShortDescription() { - return String.format("Missing SDK Platform Android%1$s, API %2$d", - mVersion.isPreview() ? " Preview" : "", - mVersion.getApiLevel()); - } - } - - /** - * A {@link MissingArchiveInfo} is an {@link ArchiveInfo} that represents a - * package/archive that we <em>really</em> need as a dependency but that we don't have. - * <p/> - * This is currently used for extras in case we can't find a matching tool revision - * or when a platform-tool is missing. - * <p/> - * This kind of archive has specific properties: the new archive to install is null, - * there are no dependencies and no archive is being replaced. The info can never be - * accepted and is always rejected. - */ - private static class MissingArchiveInfo extends ArchiveInfo { - - private final FullRevision mRevision; - private final String mTitle; - - public static final String TITLE_TOOL = "Tools"; - public static final String TITLE_PLATFORM_TOOL = "Platform-tools"; - - /** - * Constructs a {@link MissingPlatformArchiveInfo} that will indicate the - * given platform version is missing. - * - * @param title Typically "Tools" or "Platform-tools". - * @param revision The required revision. - */ - public MissingArchiveInfo(String title, FullRevision revision) { - super(null /*newArchive*/, null /*replaced*/, null /*dependsOn*/); - mTitle = title; - mRevision = revision; - } - - /** Missing archives are never accepted. */ - @Override - public boolean isAccepted() { - return false; - } - - /** Missing archives are always rejected. */ - @Override - public boolean isRejected() { - return true; - } - - @Override - public String getShortDescription() { - return String.format("Missing Android SDK %1$s, revision %2$s", - mTitle, - mRevision.toShortString()); - } - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SdkUpdaterNoWindow.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SdkUpdaterNoWindow.java deleted file mode 100755 index 5e7143d..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SdkUpdaterNoWindow.java +++ /dev/null @@ -1,624 +0,0 @@ -/* - * Copyright (C) 2010 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.repository; - -import com.android.annotations.NonNull; -import com.android.sdklib.SdkManager; -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskFactory; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.NullTaskMonitor; -import com.android.sdklib.internal.repository.UserCredentials; -import com.android.sdklib.repository.SdkRepoConstants; -import com.android.utils.ILogger; -import com.android.utils.Pair; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Properties; - -/** - * Performs an update using only a non-interactive console output with no GUI. - */ -public class SdkUpdaterNoWindow { - - /** The {@link UpdaterData} to use. */ - private final UpdaterData mUpdaterData; - /** The {@link ILogger} logger to use. */ - private final ILogger mSdkLog; - /** The reply to any question asked by the update process. Currently this will - * be yes/no for ability to replace modified samples or restart ADB. */ - private final boolean mForce; - - /** - * Creates an UpdateNoWindow object that will update using the given SDK root - * and outputs to the given SDK logger. - * - * @param osSdkRoot The OS path of the SDK folder to update. - * @param sdkManager An existing SDK manager to list current platforms and addons. - * @param sdkLog A logger object, that should ideally output to a write-only console. - * @param force The reply to any question asked by the update process. Currently this will - * be yes/no for ability to replace modified samples or restart ADB. - * @param useHttp True to force using HTTP instead of HTTPS for downloads. - * @param proxyPort An optional HTTP/HTTPS proxy port. Can be null. - * @param proxyHost An optional HTTP/HTTPS proxy host. Can be null. - */ - public SdkUpdaterNoWindow(String osSdkRoot, - SdkManager sdkManager, - ILogger sdkLog, - boolean force, - boolean useHttp, - String proxyHost, - String proxyPort) { - mSdkLog = sdkLog; - mForce = force; - mUpdaterData = new UpdaterData(osSdkRoot, sdkLog); - - // Read and apply settings from settings file, so that http/https proxy is set - // and let the command line args override them as necessary. - SettingsController settingsController = mUpdaterData.getSettingsController(); - settingsController.loadSettings(); - settingsController.applySettings(); - setupProxy(proxyHost, proxyPort); - - // Change the in-memory settings to force the http/https mode - settingsController.setSetting(ISettingsPage.KEY_FORCE_HTTP, useHttp); - - // Use a factory that only outputs to the given ILogger. - mUpdaterData.setTaskFactory(new ConsoleTaskFactory()); - - // Check that the AVD Manager has been correctly initialized. This is done separately - // from the constructor in the GUI-based UpdaterWindowImpl to give time to the UI to - // initialize before displaying a message box. Since we don't have any GUI here - // we can call it whenever we want. - if (mUpdaterData.checkIfInitFailed()) { - return; - } - - // Setup the default sources including the getenv overrides. - mUpdaterData.setupDefaultSources(); - - mUpdaterData.getLocalSdkParser().parseSdk( - osSdkRoot, - sdkManager, - new NullTaskMonitor(sdkLog)); - } - - /** - * Performs the actual update. - * - * @param pkgFilter A list of {@link SdkRepoConstants#NODES} to limit the type of packages - * we can update. A null or empty list means to update everything possible. - * @param includeAll True to list and install all packages, including obsolete ones. - * @param dryMode True to check what would be updated/installed but do not actually - * download or install anything. - */ - public void updateAll( - ArrayList<String> pkgFilter, - boolean includeAll, - boolean dryMode) { - mUpdaterData.updateOrInstallAll_NoGUI(pkgFilter, includeAll, dryMode); - } - - /** - * Lists remote packages available for install using 'android update sdk --no-ui'. - * - * @param includeAll True to list and install all packages, including obsolete ones. - * @param extendedOutput True to display more details on each package. - */ - public void listRemotePackages(boolean includeAll, boolean extendedOutput) { - mUpdaterData.listRemotePackages_NoGUI(includeAll, extendedOutput); - } - - // ----- - - /** - * Sets both the HTTP and HTTPS proxy system properties, overriding the ones - * from the settings with these values if they are defined. - */ - private void setupProxy(String proxyHost, String proxyPort) { - - // The system property constants can be found in the Java SE documentation at - // http://download.oracle.com/javase/6/docs/technotes/guides/net/proxies.html - final String JAVA_PROP_HTTP_PROXY_HOST = "http.proxyHost"; //$NON-NLS-1$ - final String JAVA_PROP_HTTP_PROXY_PORT = "http.proxyPort"; //$NON-NLS-1$ - final String JAVA_PROP_HTTPS_PROXY_HOST = "https.proxyHost"; //$NON-NLS-1$ - final String JAVA_PROP_HTTPS_PROXY_PORT = "https.proxyPort"; //$NON-NLS-1$ - - Properties props = System.getProperties(); - - if (proxyHost != null && proxyHost.length() > 0) { - props.setProperty(JAVA_PROP_HTTP_PROXY_HOST, proxyHost); - props.setProperty(JAVA_PROP_HTTPS_PROXY_HOST, proxyHost); - } - if (proxyPort != null && proxyPort.length() > 0) { - props.setProperty(JAVA_PROP_HTTP_PROXY_PORT, proxyPort); - props.setProperty(JAVA_PROP_HTTPS_PROXY_PORT, proxyPort); - } - } - - /** - * A custom implementation of {@link ITaskFactory} that - * provides {@link ConsoleTaskMonitor} objects. - */ - private class ConsoleTaskFactory implements ITaskFactory { - @Override - public void start(String title, ITask task) { - start(title, null /*parentMonitor*/, task); - } - - @Override - public void start(String title, ITaskMonitor parentMonitor, ITask task) { - if (parentMonitor == null) { - task.run(new ConsoleTaskMonitor(title, task)); - } else { - // Use all the reminder of the parent monitor. - if (parentMonitor.getProgressMax() == 0) { - parentMonitor.setProgressMax(1); - } - - ITaskMonitor sub = parentMonitor.createSubMonitor( - parentMonitor.getProgressMax() - parentMonitor.getProgress()); - try { - task.run(sub); - } finally { - int delta = - sub.getProgressMax() - sub.getProgress(); - if (delta > 0) { - sub.incProgress(delta); - } - } - } - } - } - - /** - * A custom implementation of {@link ITaskMonitor} that defers all output to the - * super {@link SdkUpdaterNoWindow#mSdkLog}. - */ - private class ConsoleTaskMonitor implements ITaskMonitor { - - private static final double MAX_COUNT = 10000.0; - private double mIncCoef = 0; - private double mValue = 0; - private String mLastDesc = null; - private String mLastProgressBase = null; - - /** - * Creates a new {@link ConsoleTaskMonitor} with the given title. - */ - public ConsoleTaskMonitor(String title, ITask task) { - mSdkLog.info("%s:\n", title); - } - - /** - * Sets the description in the current task dialog. - */ - @Override - public void setDescription(String format, Object...args) { - - String last = mLastDesc; - String line = String.format(" " + format, args); //$NON-NLS-1$ - - // If the description contains a %, it generally indicates a recurring - // progress so we want a \r at the end. - int pos = line.indexOf('%'); - if (pos > -1) { - String base = line.trim(); - if (mLastProgressBase != null && base.startsWith(mLastProgressBase)) { - line = " " + base.substring(mLastProgressBase.length()); //$NON-NLS-1$ - } - line += '\r'; - } else { - mLastProgressBase = line.trim(); - line += '\n'; - } - - // Skip line if it's the same as the last one. - if (last != null && last.equals(line.trim())) { - return; - } - mLastDesc = line.trim(); - - // If the last line terminated with a \r but the new one doesn't, we need to - // insert a \n to avoid erasing the previous line. - if (last != null && - last.endsWith("\r") && //$NON-NLS-1$ - !line.endsWith("\r")) { //$NON-NLS-1$ - line = '\n' + line; - } - - mSdkLog.info("%s", line); //$NON-NLS-1$ - } - - @Override - public void log(String format, Object...args) { - setDescription(" " + format, args); //$NON-NLS-1$ - } - - @Override - public void logError(String format, Object...args) { - setDescription(format, args); - } - - @Override - public void logVerbose(String format, Object...args) { - // The ConsoleTask does not display verbose log messages. - } - - // --- ILogger --- - - @Override - public void error(Throwable t, String errorFormat, Object... args) { - mSdkLog.error(t, errorFormat, args); - } - - @Override - public void warning(@NonNull String warningFormat, Object... args) { - mSdkLog.warning(warningFormat, args); - } - - @Override - public void info(@NonNull String msgFormat, Object... args) { - mSdkLog.info(msgFormat, args); - } - - @Override - public void verbose(@NonNull String msgFormat, Object... args) { - mSdkLog.verbose(msgFormat, args); - } - - /** - * Sets the max value of the progress bar. - * - * Weird things will happen if setProgressMax is called multiple times - * *after* {@link #incProgress(int)}: we don't try to adjust it on the - * fly. - */ - @Override - public void setProgressMax(int max) { - assert max > 0; - // Always set the dialog's progress max to 10k since it only handles - // integers and we want to have a better inner granularity. Instead - // we use the max to compute a coefficient for inc deltas. - mIncCoef = max > 0 ? MAX_COUNT / max : 0; - assert mIncCoef > 0; - } - - @Override - public int getProgressMax() { - return mIncCoef > 0 ? (int) (MAX_COUNT / mIncCoef) : 0; - } - - /** - * Increments the current value of the progress bar. - */ - @Override - public void incProgress(int delta) { - if (delta > 0 && mIncCoef > 0) { - internalIncProgress(delta * mIncCoef); - } - } - - private void internalIncProgress(double realDelta) { - mValue += realDelta; - // max value is 10k, so 10k/100 == 100%. - // Experimentation shows that it is not really useful to display this - // progression since during download the description line will change. - // mSdkLog.printf(" [%3d%%]\r", ((int)mValue) / 100); - } - - /** - * Returns the current value of the progress bar, - * between 0 and up to {@link #setProgressMax(int)} - 1. - */ - @Override - public int getProgress() { - assert mIncCoef > 0; - return mIncCoef > 0 ? (int)(mValue / mIncCoef) : 0; - } - - /** - * Returns true if the "Cancel" button was selected. - */ - @Override - public boolean isCancelRequested() { - return false; - } - - /** - * Display a yes/no question dialog box. - * - * This implementation allow this to be called from any thread, it - * makes sure the dialog is opened synchronously in the ui thread. - * - * @param title The title of the dialog box - * @param message The error message - * @return true if YES was clicked. - */ - @Override - public boolean displayPrompt(final String title, final String message) { - // TODO Make it interactive if mForce==false - mSdkLog.info("\n%1$s\n%2$s\n%3$s", //$NON-NLS-1$ - title, - message, - mForce ? "--force used, will reply yes\n" : - "Note: you can use --force to override to yes.\n"); - if (mForce) { - return true; - } - - while (true) { - mSdkLog.info("%1$s", "[y/n] =>"); //$NON-NLS-1$ - try { - byte[] readBuffer = new byte[2048]; - String reply = readLine(readBuffer).trim(); - mSdkLog.info("\n"); //$NON-NLS-1$ - if (reply.length() > 0 && reply.length() <= 3) { - char c = reply.charAt(0); - if (c == 'y' || c == 'Y') { - return true; - } else if (c == 'n' || c == 'N') { - return false; - } - } - mSdkLog.info("Unknown reply '%s'. Please use y[es]/n[o].\n"); //$NON-NLS-1$ - - } catch (IOException e) { - // Exception. Be conservative and say no. - mSdkLog.info("\n"); //$NON-NLS-1$ - return false; - } - } - } - - /** - * Displays a prompt message to the user and read two values, - * login/password. - * <p> - * <i>Asks user for login/password information.</i> - * <p> - * This method shows a question in the standard output, asking for login - * and password.</br> - * <b>Method Output:</b></br> - * Title</br> - * Message</br> - * Login: (Wait for user input)</br> - * Password: (Wait for user input)</br> - * <p> - * - * @param title The title of the iteration. - * @param message The message to be displayed. - * @return A {@link Pair} holding the entered login and password. The - * <b>first element</b> is always the <b>Login</b>, and the - * <b>second element</b> is always the <b>Password</b>. This - * method will never return null, in case of error the pair will - * be filled with empty strings. - * @see ITaskMonitor#displayLoginCredentialsPrompt(String, String) - */ - @Override - public UserCredentials displayLoginCredentialsPrompt(String title, String message) { - String login = ""; //$NON-NLS-1$ - String password = ""; //$NON-NLS-1$ - String workstation = ""; //$NON-NLS-1$ - String domain = ""; //$NON-NLS-1$ - - mSdkLog.info("\n%1$s\n%2$s", title, message); - byte[] readBuffer = new byte[2048]; - try { - mSdkLog.info("\nLogin: "); - login = readLine(readBuffer); - mSdkLog.info("\nPassword: "); - password = readLine(readBuffer); - mSdkLog.info("\nIf your proxy uses NTLM authentication, provide the following information. Leave blank otherwise."); - mSdkLog.info("\nWorkstation: "); - workstation = readLine(readBuffer); - mSdkLog.info("\nDomain: "); - domain = readLine(readBuffer); - - /* - * TODO: Implement a way to don't echo the typed password On - * Java 5 there's no simple way to do this. There's just a - * workaround which is output backspaces on each keystroke. - * A good alternative is to use Java 6 java.io.Console - */ - } catch (IOException e) { - // Reset login/pass to empty Strings. - login = ""; //$NON-NLS-1$ - password = ""; //$NON-NLS-1$ - workstation = ""; //$NON-NLS-1$ - domain = ""; //$NON-NLS-1$ - //Just print the error to console. - mSdkLog.info("\nError occurred during login/pass query: %s\n", e.getMessage()); - } - - return new UserCredentials(login, password, workstation, domain); - } - - /** - * Reads current console input in the given buffer. - * - * @param buffer Buffer to hold the user input. Must be larger than the largest - * expected input. Cannot be null. - * @return A new string. May be empty but not null. - * @throws IOException in case the buffer isn't long enough. - */ - private String readLine(byte[] buffer) throws IOException { - int count = System.in.read(buffer); - - // is the input longer than the buffer? - if (count == buffer.length && buffer[count-1] != 10) { - throw new IOException(String.format( - "Input is longer than the buffer size, (%1$s) bytes", buffer.length)); - } - - // ignore end whitespace - while (count > 0 && (buffer[count-1] == '\r' || buffer[count-1] == '\n')) { - count--; - } - - return new String(buffer, 0, count); - } - - /** - * Creates a sub-monitor that will use up to tickCount on the progress bar. - * tickCount must be 1 or more. - */ - @Override - public ITaskMonitor createSubMonitor(int tickCount) { - assert mIncCoef > 0; - assert tickCount > 0; - return new ConsoleSubTaskMonitor(this, null, mValue, tickCount * mIncCoef); - } - } - - private interface IConsoleSubTaskMonitor extends ITaskMonitor { - public void subIncProgress(double realDelta); - } - - private static class ConsoleSubTaskMonitor implements IConsoleSubTaskMonitor { - - private final ConsoleTaskMonitor mRoot; - private final IConsoleSubTaskMonitor mParent; - private final double mStart; - private final double mSpan; - private double mSubValue; - private double mSubCoef; - - /** - * Creates a new sub task monitor which will work for the given range [start, start+span] - * in its parent. - * - * @param root The ProgressTask root - * @param parent The immediate parent. Can be the null or another sub task monitor. - * @param start The start value in the root's coordinates - * @param span The span value in the root's coordinates - */ - public ConsoleSubTaskMonitor(ConsoleTaskMonitor root, - IConsoleSubTaskMonitor parent, - double start, - double span) { - mRoot = root; - mParent = parent; - mStart = start; - mSpan = span; - mSubValue = start; - } - - @Override - public boolean isCancelRequested() { - return mRoot.isCancelRequested(); - } - - @Override - public void setDescription(String format, Object... args) { - mRoot.setDescription(format, args); - } - - @Override - public void log(String format, Object... args) { - mRoot.log(format, args); - } - - @Override - public void logError(String format, Object... args) { - mRoot.logError(format, args); - } - - @Override - public void logVerbose(String format, Object... args) { - mRoot.logVerbose(format, args); - } - - @Override - public void setProgressMax(int max) { - assert max > 0; - mSubCoef = max > 0 ? mSpan / max : 0; - assert mSubCoef > 0; - } - - @Override - public int getProgressMax() { - return mSubCoef > 0 ? (int) (mSpan / mSubCoef) : 0; - } - - @Override - public int getProgress() { - assert mSubCoef > 0; - return mSubCoef > 0 ? (int)((mSubValue - mStart) / mSubCoef) : 0; - } - - @Override - public void incProgress(int delta) { - if (delta > 0 && mSubCoef > 0) { - subIncProgress(delta * mSubCoef); - } - } - - @Override - public void subIncProgress(double realDelta) { - mSubValue += realDelta; - if (mParent != null) { - mParent.subIncProgress(realDelta); - } else { - mRoot.internalIncProgress(realDelta); - } - } - - @Override - public boolean displayPrompt(String title, String message) { - return mRoot.displayPrompt(title, message); - } - - @Override - public UserCredentials displayLoginCredentialsPrompt(String title, String message) { - return mRoot.displayLoginCredentialsPrompt(title, message); - } - - @Override - public ITaskMonitor createSubMonitor(int tickCount) { - assert mSubCoef > 0; - assert tickCount > 0; - return new ConsoleSubTaskMonitor(mRoot, - this, - mSubValue, - tickCount * mSubCoef); - } - - // --- ILogger --- - - @Override - public void error(Throwable t, String errorFormat, Object... args) { - mRoot.error(t, errorFormat, args); - } - - @Override - public void warning(@NonNull String warningFormat, Object... args) { - mRoot.warning(warningFormat, args); - } - - @Override - public void info(@NonNull String msgFormat, Object... args) { - mRoot.info(msgFormat, args); - } - - @Override - public void verbose(@NonNull String msgFormat, Object... args) { - mRoot.verbose(msgFormat, args); - } - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SettingsController.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SettingsController.java deleted file mode 100755 index 2d2352b..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SettingsController.java +++ /dev/null @@ -1,382 +0,0 @@ -/* - * 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.repository; - -import com.android.annotations.NonNull; -import com.android.prefs.AndroidLocation; -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.utils.ILogger; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map.Entry; -import java.util.Properties; - -/** - * Controller class to get settings values. Settings are kept in-memory. - * Users of this class must first load the settings before changing them and save - * them when modified. - * <p/> - * Settings are enumerated by constants in {@link ISettingsPage}. - */ -public class SettingsController { - - private static final String SETTINGS_FILENAME = "androidtool.cfg"; //$NON-NLS-1$ - - private final ILogger mSdkLog; - private final Settings mSettings; - - public interface OnChangedListener { - public void onSettingsChanged(SettingsController controller, Settings oldSettings); - } - private final List<OnChangedListener> mChangedListeners = new ArrayList<OnChangedListener>(1); - - /** The currently associated {@link ISettingsPage}. Can be null. */ - private ISettingsPage mSettingsPage; - - /** - * Constructs a new default {@link SettingsController}. - * - * @param sdkLog A non-null logger to use. - */ - public SettingsController(@NonNull ILogger sdkLog) { - mSdkLog = sdkLog; - mSettings = new Settings(); - } - - /** - * Specialized constructor that wraps an existing {@link Settings} instance. - * This is mostly used in unit-tests to override settings that are being used. - * Normal usage should NOT need to call this constructor. - * - * @param sdkLog A non-null logger to use. - * @param settings A non-null {@link Settings} to use as-is. It is not duplicated. - */ - protected SettingsController(@NonNull ILogger sdkLog, @NonNull Settings settings) { - mSdkLog = sdkLog; - mSettings = settings; - } - - public Settings getSettings() { - return mSettings; - } - - public void registerOnChangedListener(OnChangedListener listener) { - if (listener != null && !mChangedListeners.contains(listener)) { - mChangedListeners.add(listener); - } - } - - public void unregisterOnChangedListener(OnChangedListener listener) { - if (listener != null) { - mChangedListeners.remove(listener); - } - } - - //--- Access to settings ------------ - - - public static class Settings { - private final Properties mProperties; - - /** Initialize an empty set of settings. */ - public Settings() { - mProperties = new Properties(); - } - - /** Duplicates a set of settings. */ - public Settings(Settings settings) { - this(); - for (Entry<Object, Object> entry : settings.mProperties.entrySet()) { - mProperties.put(entry.getKey(), entry.getValue()); - } - } - - /** - * Specialized constructor for unit-tests that wraps an existing - * {@link Properties} instance. The properties instance is not duplicated, - * it's merely used as-is and changes will be reflected directly. - */ - protected Settings(Properties properties) { - mProperties = properties; - } - - /** - * Returns the value of the {@link ISettingsPage#KEY_FORCE_HTTP} setting. - * - * @see ISettingsPage#KEY_FORCE_HTTP - */ - public boolean getForceHttp() { - return Boolean.parseBoolean(mProperties.getProperty(ISettingsPage.KEY_FORCE_HTTP)); - } - - /** - * Returns the value of the {@link ISettingsPage#KEY_ASK_ADB_RESTART} setting. - * - * @see ISettingsPage#KEY_ASK_ADB_RESTART - */ - public boolean getAskBeforeAdbRestart() { - return Boolean.parseBoolean(mProperties.getProperty(ISettingsPage.KEY_ASK_ADB_RESTART)); - } - - /** - * Returns the value of the {@link ISettingsPage#KEY_USE_DOWNLOAD_CACHE} setting. - * - * @see ISettingsPage#KEY_USE_DOWNLOAD_CACHE - */ - public boolean getUseDownloadCache() { - return Boolean.parseBoolean( - mProperties.getProperty( - ISettingsPage.KEY_USE_DOWNLOAD_CACHE, - Boolean.TRUE.toString())); - } - - /** - * Returns the value of the {@link ISettingsPage#KEY_SHOW_UPDATE_ONLY} setting. - * - * @see ISettingsPage#KEY_SHOW_UPDATE_ONLY - */ - public boolean getShowUpdateOnly() { - return Boolean.parseBoolean( - mProperties.getProperty( - ISettingsPage.KEY_SHOW_UPDATE_ONLY, - Boolean.TRUE.toString())); - } - - /** - * Returns the value of the {@link ISettingsPage#KEY_ENABLE_PREVIEWS} setting. - * - * @see ISettingsPage#KEY_ENABLE_PREVIEWS - */ - public boolean getEnablePreviews() { - return Boolean.parseBoolean(mProperties.getProperty(ISettingsPage.KEY_ENABLE_PREVIEWS)); - } - - /** - * Returns the value of the {@link ISettingsPage#KEY_MONITOR_DENSITY} setting - * @see ISettingsPage#KEY_MONITOR_DENSITY - */ - public int getMonitorDensity() { - String value = mProperties.getProperty(ISettingsPage.KEY_MONITOR_DENSITY, null); - if (value == null) { - return -1; - } - - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - return -1; - } - } - } - - /** - * Sets the value of the {@link ISettingsPage#KEY_SHOW_UPDATE_ONLY} setting. - * - * @param enabled True if only compatible non-obsolete update items should be shown. - * @see ISettingsPage#KEY_SHOW_UPDATE_ONLY - */ - public void setShowUpdateOnly(boolean enabled) { - setSetting(ISettingsPage.KEY_SHOW_UPDATE_ONLY, enabled); - } - - /** - * Sets the value of the {@link ISettingsPage#KEY_MONITOR_DENSITY} setting. - * - * @param density the density of the monitor - * @see ISettingsPage#KEY_MONITOR_DENSITY - */ - public void setMonitorDensity(int density) { - mSettings.mProperties.setProperty( - ISettingsPage.KEY_MONITOR_DENSITY, Integer.toString(density)); - } - - /** - * Internal helper to set a boolean setting. - */ - void setSetting(String key, boolean value) { - mSettings.mProperties.setProperty(key, Boolean.toString(value)); - } - - //--- Controller methods ------------- - - /** - * Associate the given {@link ISettingsPage} with this {@link SettingsController}. - * <p/> - * This loads the current properties into the setting page UI. - * It then associates the SettingsChanged callback with this controller. - * <p/> - * If the setting page given is null, it will be unlinked from controller. - * - * @param settingsPage An {@link ISettingsPage} to associate with the controller. - */ - public void setSettingsPage(ISettingsPage settingsPage) { - mSettingsPage = settingsPage; - - if (settingsPage != null) { - settingsPage.loadSettings(mSettings.mProperties); - - settingsPage.setOnSettingsChanged(new ISettingsPage.SettingsChangedCallback() { - @Override - public void onSettingsChanged(ISettingsPage page) { - SettingsController.this.onSettingsChanged(); - } - }); - } - } - - /** - * Load settings from the settings file. - */ - public void loadSettings() { - FileInputStream fis = null; - String path = null; - try { - String folder = AndroidLocation.getFolder(); - File f = new File(folder, SETTINGS_FILENAME); - path = f.getPath(); - if (f.exists()) { - fis = new FileInputStream(f); - - mSettings.mProperties.load(fis); - - // Properly reformat some settings to enforce their default value when missing. - setShowUpdateOnly(mSettings.getShowUpdateOnly()); - setSetting(ISettingsPage.KEY_ASK_ADB_RESTART, mSettings.getAskBeforeAdbRestart()); - setSetting(ISettingsPage.KEY_USE_DOWNLOAD_CACHE, mSettings.getUseDownloadCache()); - } - - } catch (Exception e) { - if (mSdkLog != null) { - mSdkLog.error(e, - "Failed to load settings from .android folder. Path is '%1$s'.", - path); - } - } finally { - if (fis != null) { - try { - fis.close(); - } catch (IOException e) { - } - } - } - } - - /** - * Saves settings to the settings file. - */ - public void saveSettings() { - - FileOutputStream fos = null; - String path = null; - try { - String folder = AndroidLocation.getFolder(); - File f = new File(folder, SETTINGS_FILENAME); - path = f.getPath(); - - fos = new FileOutputStream(f); - - mSettings.mProperties.store(fos, "## Settings for Android Tool"); //$NON-NLS-1$ - - } catch (Exception e) { - if (mSdkLog != null) { - // This is important enough that we want to really nag the user about it - String reason = null; - - if (e instanceof FileNotFoundException) { - reason = "File not found"; - } else if (e instanceof AndroidLocationException) { - reason = ".android folder not found, please define ANDROID_SDK_HOME"; - } else if (e.getMessage() != null) { - reason = String.format("%1$s: %2$s", - e.getClass().getSimpleName(), - e.getMessage()); - } else { - reason = e.getClass().getName(); - } - - mSdkLog.error(e, "Failed to save settings file '%1$s': %2$s", path, reason); - } - } finally { - if (fos != null) { - try { - fos.close(); - } catch (IOException e) { - } - } - } - } - - /** - * When settings have changed: retrieve the new settings, apply them, save them - * and notify on-settings-changed listeners. - */ - private void onSettingsChanged() { - if (mSettingsPage == null) { - return; - } - - Settings oldSettings = new Settings(mSettings); - mSettingsPage.retrieveSettings(mSettings.mProperties); - applySettings(); - saveSettings(); - - for (OnChangedListener listener : mChangedListeners) { - try { - listener.onSettingsChanged(this, oldSettings); - } catch (Throwable ignore) {} - } - } - - /** - * Applies the current settings. - */ - public void applySettings() { - Properties props = System.getProperties(); - - // Get the configured HTTP proxy settings - String proxyHost = mSettings.mProperties.getProperty(ISettingsPage.KEY_HTTP_PROXY_HOST, - ""); //$NON-NLS-1$ - String proxyPort = mSettings.mProperties.getProperty(ISettingsPage.KEY_HTTP_PROXY_PORT, - ""); //$NON-NLS-1$ - - // Set both the HTTP and HTTPS proxy system properties. - // The system property constants can be found in the Java SE documentation at - // http://download.oracle.com/javase/6/docs/technotes/guides/net/proxies.html - final String JAVA_PROP_HTTP_PROXY_HOST = "http.proxyHost"; //$NON-NLS-1$ - final String JAVA_PROP_HTTP_PROXY_PORT = "http.proxyPort"; //$NON-NLS-1$ - final String JAVA_PROP_HTTPS_PROXY_HOST = "https.proxyHost"; //$NON-NLS-1$ - final String JAVA_PROP_HTTPS_PROXY_PORT = "https.proxyPort"; //$NON-NLS-1$ - - // Only change the proxy if have something in the preferences. - // Do not erase the default settings by empty values. - if (proxyHost != null && proxyHost.length() > 0) { - props.setProperty(JAVA_PROP_HTTP_PROXY_HOST, proxyHost); - props.setProperty(JAVA_PROP_HTTPS_PROXY_HOST, proxyHost); - } - if (proxyPort != null && proxyPort.length() > 0) { - props.setProperty(JAVA_PROP_HTTP_PROXY_PORT, proxyPort); - props.setProperty(JAVA_PROP_HTTPS_PROXY_PORT, proxyPort); - } - } - -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SettingsDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SettingsDialog.java deleted file mode 100755 index f05be4c..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SettingsDialog.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (C) 2012 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.repository; - -import com.android.sdklib.internal.repository.DownloadCache; -import com.android.sdklib.internal.repository.DownloadCache.Strategy; -import com.android.sdklib.util.FormatUtils; -import com.android.sdkuilib.ui.GridDataBuilder; -import com.android.sdkuilib.ui.GridLayoutBuilder; - -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.widgets.Button; -import org.eclipse.swt.widgets.Group; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; - -import java.util.Properties; - - -public class SettingsDialog extends UpdaterBaseDialog implements ISettingsPage { - - - // data members - private final DownloadCache mDownloadCache = new DownloadCache(Strategy.SERVE_CACHE); - private final SettingsController mSettingsController; - private SettingsChangedCallback mSettingsChangedCallback; - - // UI widgets - private Text mTextProxyServer; - private Text mTextProxyPort; - private Text mTextCacheSize; - private Button mCheckUseCache; - private Button mCheckForceHttp; - private Button mCheckAskAdbRestart; - private Button mCheckEnablePreviews; - - private SelectionAdapter mApplyOnSelected = new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - applyNewSettings(); //$hide$ - } - }; - - private ModifyListener mApplyOnModified = new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - applyNewSettings(); //$hide$ - } - }; - - public SettingsDialog(Shell parentShell, UpdaterData updaterData) { - super(parentShell, updaterData, "Settings" /*title*/); - assert updaterData != null; - mSettingsController = updaterData.getSettingsController(); - } - - @Override - protected void createShell() { - super.createShell(); - Shell shell = getShell(); - shell.setMinimumSize(new Point(450, 370)); - shell.setSize(450, 400); - } - - @Override - protected void createContents() { - super.createContents(); - Shell shell = getShell(); - - Group group = new Group(shell, SWT.NONE); - group.setText("Proxy Settings"); - GridDataBuilder.create(group).fill().grab().hSpan(2); - GridLayoutBuilder.create(group).columns(2); - - Label label = new Label(group, SWT.NONE); - GridDataBuilder.create(label).hRight().vCenter(); - label.setText("HTTP Proxy Server"); - String tooltip = "The hostname or IP of the HTTP & HTTPS proxy server to use (e.g. proxy.example.com).\n" + - "When empty, the default Java proxy setting is used."; - label.setToolTipText(tooltip); - - mTextProxyServer = new Text(group, SWT.BORDER); - GridDataBuilder.create(mTextProxyServer).hFill().hGrab().vCenter(); - mTextProxyServer.addModifyListener(mApplyOnModified); - mTextProxyServer.setToolTipText(tooltip); - - label = new Label(group, SWT.NONE); - GridDataBuilder.create(label).hRight().vCenter(); - label.setText("HTTP Proxy Port"); - tooltip = "The port of the HTTP & HTTPS proxy server to use (e.g. 3128).\n" + - "When empty, the default Java proxy setting is used."; - label.setToolTipText(tooltip); - - mTextProxyPort = new Text(group, SWT.BORDER); - GridDataBuilder.create(mTextProxyPort).hFill().hGrab().vCenter(); - mTextProxyPort.addModifyListener(mApplyOnModified); - mTextProxyPort.setToolTipText(tooltip); - - // ---- - group = new Group(shell, SWT.NONE); - group.setText("Manifest Cache"); - GridDataBuilder.create(group).fill().grab().hSpan(2); - GridLayoutBuilder.create(group).columns(3); - - label = new Label(group, SWT.NONE); - GridDataBuilder.create(label).hRight().vCenter(); - label.setText("Directory:"); - - Text text = new Text(group, SWT.NONE); - GridDataBuilder.create(text).hFill().hGrab().vCenter().hSpan(2); - text.setEnabled(false); - text.setText(mDownloadCache.getCacheRoot().getAbsolutePath()); - - label = new Label(group, SWT.NONE); - GridDataBuilder.create(label).hRight().vCenter(); - label.setText("Current Size:"); - - mTextCacheSize = new Text(group, SWT.NONE); - GridDataBuilder.create(mTextCacheSize).hFill().hGrab().vCenter().hSpan(2); - mTextCacheSize.setEnabled(false); - updateDownloadCacheSize(); - - mCheckUseCache = new Button(group, SWT.CHECK); - GridDataBuilder.create(mCheckUseCache).vCenter().hSpan(1); - mCheckUseCache.setText("Use download cache"); - mCheckUseCache.setToolTipText("When checked, small manifest files are cached locally.\n" + - "Large binary files are never cached locally."); - mCheckUseCache.addSelectionListener(mApplyOnSelected); - - label = new Label(group, SWT.NONE); - GridDataBuilder.create(label).hFill().hGrab().hSpan(1); - - Button button = new Button(group, SWT.PUSH); - GridDataBuilder.create(button).vCenter().hSpan(1); - button.setText("Clear Cache"); - button.setToolTipText("Deletes all cached files."); - button.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - mDownloadCache.clearCache(); - updateDownloadCacheSize(); - } - }); - - // ---- - group = new Group(shell, SWT.NONE); - group.setText("Others"); - GridDataBuilder.create(group).fill().grab().hSpan(2); - GridLayoutBuilder.create(group).columns(2); - - mCheckForceHttp = new Button(group, SWT.CHECK); - GridDataBuilder.create(mCheckForceHttp).hFill().hGrab().vCenter().hSpan(2); - mCheckForceHttp.setText("Force https://... sources to be fetched using http://..."); - mCheckForceHttp.setToolTipText( - "If you are not able to connect to the official Android repository using HTTPS,\n" + - "enable this setting to force accessing it via HTTP."); - mCheckForceHttp.addSelectionListener(mApplyOnSelected); - - mCheckAskAdbRestart = new Button(group, SWT.CHECK); - GridDataBuilder.create(mCheckAskAdbRestart).hFill().hGrab().vCenter().hSpan(2); - mCheckAskAdbRestart.setText("Ask before restarting ADB"); - mCheckAskAdbRestart.setToolTipText( - "When checked, the user will be asked for permission to restart ADB\n" + - "after updating an addon-on package or a tool package."); - mCheckAskAdbRestart.addSelectionListener(mApplyOnSelected); - - mCheckEnablePreviews = new Button(group, SWT.CHECK); - GridDataBuilder.create(mCheckEnablePreviews).hFill().hGrab().vCenter().hSpan(2); - mCheckEnablePreviews.setText("Enable Preview Tools"); - mCheckEnablePreviews.setToolTipText( - "When checked, the package list will also display preview versions of the tools.\n" + - "These are optional future release candidates that the Android tools team\n" + - "publishes from time to time for early feedback."); - mCheckEnablePreviews.addSelectionListener(mApplyOnSelected); - - Label filler = new Label(shell, SWT.NONE); - GridDataBuilder.create(filler).hFill().hGrab(); - - createCloseButton(); - } - - @Override - protected void postCreate() { - super.postCreate(); - // This tells the controller to load the settings into the page UI. - mSettingsController.setSettingsPage(this); - } - - @Override - protected void close() { - // Dissociate this page from the controller - mSettingsController.setSettingsPage(null); - super.close(); - } - - - // -- Start of internal part ---------- - // Hide everything down-below from SWT designer - //$hide>>$ - - /** Loads settings from the given {@link Properties} container and update the page UI. */ - @Override - public void loadSettings(Properties inSettings) { - mTextProxyServer.setText(inSettings.getProperty(KEY_HTTP_PROXY_HOST, "")); //$NON-NLS-1$ - mTextProxyPort.setText( inSettings.getProperty(KEY_HTTP_PROXY_PORT, "")); //$NON-NLS-1$ - mCheckForceHttp.setSelection( - Boolean.parseBoolean(inSettings.getProperty(KEY_FORCE_HTTP))); - mCheckAskAdbRestart.setSelection( - Boolean.parseBoolean(inSettings.getProperty(KEY_ASK_ADB_RESTART))); - mCheckUseCache.setSelection( - Boolean.parseBoolean(inSettings.getProperty(KEY_USE_DOWNLOAD_CACHE))); - mCheckEnablePreviews.setSelection( - Boolean.parseBoolean(inSettings.getProperty(KEY_ENABLE_PREVIEWS))); - - } - - /** Called by the application to retrieve settings from the UI and store them in - * the given {@link Properties} container. */ - @Override - public void retrieveSettings(Properties outSettings) { - outSettings.setProperty(KEY_HTTP_PROXY_HOST, mTextProxyServer.getText()); - outSettings.setProperty(KEY_HTTP_PROXY_PORT, mTextProxyPort.getText()); - outSettings.setProperty(KEY_FORCE_HTTP, - Boolean.toString(mCheckForceHttp.getSelection())); - outSettings.setProperty(KEY_ASK_ADB_RESTART, - Boolean.toString(mCheckAskAdbRestart.getSelection())); - outSettings.setProperty(KEY_USE_DOWNLOAD_CACHE, - Boolean.toString(mCheckUseCache.getSelection())); - outSettings.setProperty(KEY_ENABLE_PREVIEWS, - Boolean.toString(mCheckEnablePreviews.getSelection())); - - } - - /** - * Called by the application to give a callback that the page should invoke when - * settings must be applied. The page does not apply the settings itself, instead - * it notifies the application. - */ - @Override - public void setOnSettingsChanged(SettingsChangedCallback settingsChangedCallback) { - mSettingsChangedCallback = settingsChangedCallback; - } - - /** - * Callback invoked when user touches one of the settings. - * There is no "Apply" button, settings are applied immediately as they are changed. - * Notify the application that settings have changed. - */ - private void applyNewSettings() { - if (mSettingsChangedCallback != null) { - mSettingsChangedCallback.onSettingsChanged(this); - } - } - - private void updateDownloadCacheSize() { - long size = mDownloadCache.getCurrentSize(); - String str = FormatUtils.byteSizeToString(size); - mTextCacheSize.setText(str); - } - - - // End of hiding from SWT Designer - //$hide<<$ -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterBaseDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterBaseDialog.java deleted file mode 100755 index 02b39b4..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterBaseDialog.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2012 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.repository; - -import com.android.SdkConstants; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.internal.repository.ui.SdkUpdaterWindowImpl2; -import com.android.sdkuilib.ui.GridDataBuilder; -import com.android.sdkuilib.ui.GridLayoutBuilder; -import com.android.sdkuilib.ui.SwtBaseDialog; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Shell; - - - -/** - * Base class for auxiliary dialogs shown in the updater (for example settings, - * about box or add-on site.) - */ -public abstract class UpdaterBaseDialog extends SwtBaseDialog { - - private final UpdaterData mUpdaterData; - - protected UpdaterBaseDialog(Shell parentShell, UpdaterData updaterData, String title) { - super(parentShell, - SWT.APPLICATION_MODAL, - String.format("%1$s - %2$s", SdkUpdaterWindowImpl2.APP_NAME, title)); //$NON-NLS-1$ - mUpdaterData = updaterData; - } - - public UpdaterData getUpdaterData() { - return mUpdaterData; - } - - /** - * Initializes the shell with a 2-column Grid layout. - * Caller should use {@link #createCloseButton()} to inject the - * close button at the bottom of the dialog. - */ - @Override - protected void createContents() { - Shell shell = getShell(); - setWindowImage(shell); - - GridLayoutBuilder.create(shell).columns(2); - } - - protected void createCloseButton() { - Button close = new Button(getShell(), SWT.PUSH); - close.setText("Close"); - GridDataBuilder.create(close).hFill().vBottom(); - close.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - close(); - } - }); - } - - @Override - protected void postCreate() { - // pass - } - - @Override - protected void close() { - super.close(); - } - - /** - * Creates the icon of the window shell. - * - * @param shell The shell on which to put the icon - */ - private void setWindowImage(Shell shell) { - String imageName = "android_icon_16.png"; //$NON-NLS-1$ - if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_DARWIN) { - imageName = "android_icon_128.png"; //$NON-NLS-1$ - } - - if (mUpdaterData != null) { - ImageFactory imgFactory = mUpdaterData.getImageFactory(); - if (imgFactory != null) { - shell.setImage(imgFactory.getImageByName(imageName)); - } - } - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterData.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterData.java deleted file mode 100755 index 7fc1b1e..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterData.java +++ /dev/null @@ -1,1159 +0,0 @@ -/* - * 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.repository; - -import com.android.SdkConstants; -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.sdklib.SdkManager; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdklib.internal.repository.AdbWrapper; -import com.android.sdklib.internal.repository.DownloadCache; -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskFactory; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.LocalSdkParser; -import com.android.sdklib.internal.repository.NullTaskMonitor; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.archives.ArchiveInstaller; -import com.android.sdklib.internal.repository.packages.AddonPackage; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.packages.PlatformToolPackage; -import com.android.sdklib.internal.repository.packages.ToolPackage; -import com.android.sdklib.internal.repository.sources.SdkRepoSource; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.internal.repository.sources.SdkSourceCategory; -import com.android.sdklib.internal.repository.sources.SdkSources; -import com.android.sdklib.repository.SdkAddonConstants; -import com.android.sdklib.repository.SdkRepoConstants; -import com.android.sdklib.util.LineUtil; -import com.android.sdklib.util.SparseIntArray; -import com.android.sdkuilib.internal.repository.SettingsController.OnChangedListener; -import com.android.sdkuilib.internal.repository.core.PackageLoader; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.internal.repository.ui.SdkUpdaterWindowImpl2; -import com.android.sdkuilib.repository.ISdkChangeListener; -import com.android.utils.ILogger; - -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.swt.widgets.Shell; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Data shared between {@link SdkUpdaterWindowImpl2} and its pages. - */ -public class UpdaterData implements IUpdaterData { - - public static final int NO_TOOLS_MSG = 0; - public static final int TOOLS_MSG_UPDATED_FROM_ADT = 1; - public static final int TOOLS_MSG_UPDATED_FROM_SDKMAN = 2; - - private String mOsSdkRoot; - - private final LocalSdkParser mLocalSdkParser = new LocalSdkParser(); - /** Holds all sources. Do not use this directly. - * Instead use {@link #getSources()} so that unit tests can override this as needed. */ - private final SdkSources mSources = new SdkSources(); - /** Holds settings. Do not use this directly. - * Instead use {@link #getSettingsController()} so that unit tests can override this. */ - private final SettingsController mSettingsController; - private final ArrayList<ISdkChangeListener> mListeners = new ArrayList<ISdkChangeListener>(); - private final ILogger mSdkLog; - private ITaskFactory mTaskFactory; - private Shell mWindowShell; - private SdkManager mSdkManager; - private AvdManager mAvdManager; - /** - * The current {@link PackageLoader} to use. - * Lazily created in {@link #getPackageLoader()}. - */ - private PackageLoader mPackageLoader; - /** - * The current {@link DownloadCache} to use. - * Lazily created in {@link #getDownloadCache()}. - */ - private DownloadCache mDownloadCache; - /** - * The current {@link ImageFactory}. - * Set via {@link #setImageFactory(ImageFactory)} by the window implementation. - * It is null when invoked using the command-line interface. - */ - private ImageFactory mImageFactory; - private AndroidLocationException mAvdManagerInitError; - - /** - * Creates a new updater data. - * - * @param sdkLog Logger. Cannot be null. - * @param osSdkRoot The OS path to the SDK root. - */ - public UpdaterData(String osSdkRoot, ILogger sdkLog) { - mOsSdkRoot = osSdkRoot; - mSdkLog = sdkLog; - - - mSettingsController = initSettingsController(); - initSdk(); - } - - // ----- getters, setters ---- - - public String getOsSdkRoot() { - return mOsSdkRoot; - } - - @Override - public DownloadCache getDownloadCache() { - if (mDownloadCache == null) { - mDownloadCache = new DownloadCache( - getSettingsController().getSettings().getUseDownloadCache() ? - DownloadCache.Strategy.FRESH_CACHE : - DownloadCache.Strategy.DIRECT); - } - return mDownloadCache; - } - - public void setTaskFactory(ITaskFactory taskFactory) { - mTaskFactory = taskFactory; - } - - @Override - public ITaskFactory getTaskFactory() { - return mTaskFactory; - } - - public SdkSources getSources() { - return mSources; - } - - public LocalSdkParser getLocalSdkParser() { - return mLocalSdkParser; - } - - @Override - public ILogger getSdkLog() { - return mSdkLog; - } - - public void setImageFactory(ImageFactory imageFactory) { - mImageFactory = imageFactory; - } - - @Override - public ImageFactory getImageFactory() { - return mImageFactory; - } - - @Override - public SdkManager getSdkManager() { - return mSdkManager; - } - - @Override - public AvdManager getAvdManager() { - return mAvdManager; - } - - @Override - public SettingsController getSettingsController() { - return mSettingsController; - } - - /** Adds a listener ({@link ISdkChangeListener}) that is notified when the SDK is reloaded. */ - public void addListeners(ISdkChangeListener listener) { - if (mListeners.contains(listener) == false) { - mListeners.add(listener); - } - } - - /** Removes a listener ({@link ISdkChangeListener}) that is notified when the SDK is reloaded. */ - public void removeListener(ISdkChangeListener listener) { - mListeners.remove(listener); - } - - public void setWindowShell(Shell windowShell) { - mWindowShell = windowShell; - } - - @Override - public Shell getWindowShell() { - return mWindowShell; - } - - public PackageLoader getPackageLoader() { - // The package loader is lazily initialized here. - if (mPackageLoader == null) { - mPackageLoader = new PackageLoader(this); - } - return mPackageLoader; - } - - /** - * Check if any error occurred during initialization. - * If it did, display an error message. - * - * @return True if an error occurred, false if we should continue. - */ - public boolean checkIfInitFailed() { - if (mAvdManagerInitError != null) { - String example; - if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_WINDOWS) { - example = "%USERPROFILE%"; //$NON-NLS-1$ - } else { - example = "~"; //$NON-NLS-1$ - } - - String error = String.format( - "The AVD manager normally uses the user's profile directory to store " + - "AVD files. However it failed to find the default profile directory. " + - "\n" + - "To fix this, please set the environment variable ANDROID_SDK_HOME to " + - "a valid path such as \"%s\".", - example); - - // We may not have any UI. Only display a dialog if there's a window shell available. - if (mWindowShell != null && !mWindowShell.isDisposed()) { - MessageDialog.openError(mWindowShell, - "Android Virtual Devices Manager", - error); - } else { - mSdkLog.error(null /* Throwable */, "%s", error); //$NON-NLS-1$ - } - - return true; - } - return false; - } - - // ----- - - /** - * Initializes the {@link SdkManager} and the {@link AvdManager}. - * Extracted so that we can override this in unit tests. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected void initSdk() { - setSdkManager(SdkManager.createManager(mOsSdkRoot, mSdkLog)); - try { - mAvdManager = null; - mAvdManager = AvdManager.getInstance(mSdkManager, mSdkLog); - } catch (AndroidLocationException e) { - mSdkLog.error(e, "Unable to read AVDs: " + e.getMessage()); //$NON-NLS-1$ - - // Note: we used to continue here, but the thing is that - // mAvdManager==null so nothing is really going to work as - // expected. Let's just display an error later in checkIfInitFailed() - // and abort right there. This step is just too early in the SWT - // setup process to display a message box yet. - - mAvdManagerInitError = e; - } - - // notify listeners. - broadcastOnSdkReload(); - } - - /** - * Initializes the {@link SettingsController} - * Extracted so that we can override this in unit tests. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected SettingsController initSettingsController() { - SettingsController settingsController = new SettingsController(mSdkLog); - settingsController.registerOnChangedListener(new OnChangedListener() { - @Override - public void onSettingsChanged( - SettingsController controller, - SettingsController.Settings oldSettings) { - - // Reset the download cache if it doesn't match the right strategy. - // The cache instance gets lazily recreated later in getDownloadCache(). - if (mDownloadCache != null) { - if (controller.getSettings().getUseDownloadCache() && - mDownloadCache.getStrategy() != DownloadCache.Strategy.FRESH_CACHE) { - mDownloadCache = null; - } else if (!controller.getSettings().getUseDownloadCache() && - mDownloadCache.getStrategy() != DownloadCache.Strategy.DIRECT) { - mDownloadCache = null; - } - } - } - }); - return settingsController; - } - - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected void setSdkManager(SdkManager sdkManager) { - mSdkManager = sdkManager; - } - - /** - * Reloads the SDK content (targets). - * <p/> - * This also reloads the AVDs in case their status changed. - * <p/> - * This does not notify the listeners ({@link ISdkChangeListener}). - */ - public void reloadSdk() { - // reload SDK - mSdkManager.reloadSdk(mSdkLog); - - // reload AVDs - if (mAvdManager != null) { - try { - mAvdManager.reloadAvds(mSdkLog); - } catch (AndroidLocationException e) { - // FIXME - } - } - - mLocalSdkParser.clearPackages(); - - // notify listeners - broadcastOnSdkReload(); - } - - /** - * Reloads the AVDs. - * <p/> - * This does not notify the listeners. - */ - public void reloadAvds() { - // reload AVDs - if (mAvdManager != null) { - try { - mAvdManager.reloadAvds(mSdkLog); - } catch (AndroidLocationException e) { - mSdkLog.error(e, null); - } - } - } - - /** - * Sets up the default sources: <br/> - * - the default google SDK repository, <br/> - * - the user sources from prefs <br/> - * - the extra repo URLs from the environment, <br/> - * - and finally the extra user repo URLs from the environment. - */ - public void setupDefaultSources() { - SdkSources sources = getSources(); - - // Load the conventional sources. - // For testing, the env var can be set to replace the default root download URL. - // It must end with a / and its the location where the updater will look for - // the repository.xml, addons_list.xml and such files. - - String baseUrl = System.getenv("SDK_TEST_BASE_URL"); //$NON-NLS-1$ - if (baseUrl == null || baseUrl.length() <= 0 || !baseUrl.endsWith("/")) { //$NON-NLS-1$ - baseUrl = SdkRepoConstants.URL_GOOGLE_SDK_SITE; - } - - sources.add(SdkSourceCategory.ANDROID_REPO, - new SdkRepoSource(baseUrl, - SdkSourceCategory.ANDROID_REPO.getUiName())); - - // Load user sources (this will also notify change listeners but this operation is - // done early enough that there shouldn't be any anyway.) - sources.loadUserAddons(getSdkLog()); - } - - /** - * Returns the list of installed packages, parsing them if this has not yet been done. - * <p/> - * The package list is cached in the {@link LocalSdkParser} and will be reset when - * {@link #reloadSdk()} is invoked. - */ - public Package[] getInstalledPackages(ITaskMonitor monitor) { - LocalSdkParser parser = getLocalSdkParser(); - - Package[] packages = parser.getPackages(); - - if (packages == null) { - // load on demand the first time - packages = parser.parseSdk(getOsSdkRoot(), getSdkManager(), monitor); - } - - return packages; - } - /** - * Install the list of given {@link Archive}s. This is invoked by the user selecting some - * packages in the remote page and then clicking "install selected". - * - * @param archives The archives to install. Incompatible ones will be skipped. - * @param flags Optional flags for the installer, such as {@link #NO_TOOLS_MSG}. - * @return A list of archives that have been installed. Can be empty but not null. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected List<Archive> installArchives(final List<ArchiveInfo> archives, final int flags) { - if (mTaskFactory == null) { - throw new IllegalArgumentException("Task Factory is null"); - } - - // this will accumulate all the packages installed. - final List<Archive> newlyInstalledArchives = new ArrayList<Archive>(); - - final boolean forceHttp = getSettingsController().getSettings().getForceHttp(); - - // sort all archives based on their dependency level. - Collections.sort(archives, new InstallOrderComparator()); - - mTaskFactory.start("Installing Archives", new ITask() { - @Override - public void run(ITaskMonitor monitor) { - - final int progressPerArchive = 2 * ArchiveInstaller.NUM_MONITOR_INC; - monitor.setProgressMax(1 + archives.size() * progressPerArchive); - monitor.setDescription("Preparing to install archives"); - - boolean installedAddon = false; - boolean installedTools = false; - boolean installedPlatformTools = false; - boolean preInstallHookInvoked = false; - - // Mark all current local archives as already installed. - HashSet<Archive> installedArchives = new HashSet<Archive>(); - for (Package p : getInstalledPackages(monitor.createSubMonitor(1))) { - for (Archive a : p.getArchives()) { - installedArchives.add(a); - } - } - - int numInstalled = 0; - nextArchive: for (ArchiveInfo ai : archives) { - Archive archive = ai.getNewArchive(); - if (archive == null) { - // This is not supposed to happen. - continue nextArchive; - } - - int nextProgress = monitor.getProgress() + progressPerArchive; - try { - if (monitor.isCancelRequested()) { - break; - } - - ArchiveInfo[] adeps = ai.getDependsOn(); - if (adeps != null) { - for (ArchiveInfo adep : adeps) { - Archive na = adep.getNewArchive(); - if (na == null) { - // This archive depends on a missing archive. - // We shouldn't get here. - // Skip it. - monitor.log("Skipping '%1$s'; it depends on a missing package.", - archive.getParentPackage().getShortDescription()); - continue nextArchive; - } else if (!installedArchives.contains(na)) { - // This archive depends on another one that was not installed. - // We shouldn't get here. - // Skip it. - monitor.logError("Skipping '%1$s'; it depends on '%2$s' which was not installed.", - archive.getParentPackage().getShortDescription(), - adep.getShortDescription()); - continue nextArchive; - } - } - } - - if (!preInstallHookInvoked) { - preInstallHookInvoked = true; - broadcastPreInstallHook(); - } - - ArchiveInstaller installer = createArchiveInstaler(); - if (installer.install(ai, - mOsSdkRoot, - forceHttp, - mSdkManager, - getDownloadCache(), - monitor)) { - // We installed this archive. - newlyInstalledArchives.add(archive); - installedArchives.add(archive); - numInstalled++; - - // If this package was replacing an existing one, the old one - // is no longer installed. - installedArchives.remove(ai.getReplaced()); - - // Check if we successfully installed a platform-tool or add-on package. - if (archive.getParentPackage() instanceof AddonPackage) { - installedAddon = true; - } else if (archive.getParentPackage() instanceof ToolPackage) { - installedTools = true; - } else if (archive.getParentPackage() instanceof PlatformToolPackage) { - installedPlatformTools = true; - } - } - - } catch (Throwable t) { - // Display anything unexpected in the monitor. - String msg = t.getMessage(); - if (msg != null) { - msg = String.format("Unexpected Error installing '%1$s': %2$s: %3$s", - archive.getParentPackage().getShortDescription(), - t.getClass().getCanonicalName(), msg); - } else { - // no error info? get the stack call to display it - // At least that'll give us a better bug report. - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - t.printStackTrace(new PrintStream(baos)); - - msg = String.format("Unexpected Error installing '%1$s'\n%2$s", - archive.getParentPackage().getShortDescription(), - baos.toString()); - } - - monitor.log( "%1$s", msg); //$NON-NLS-1$ - mSdkLog.error(t, "%1$s", msg); //$NON-NLS-1$ - } finally { - - // Always move the progress bar to the desired position. - // This allows internal methods to not have to care in case - // they abort early - monitor.incProgress(nextProgress - monitor.getProgress()); - } - } - - if (installedAddon) { - // Update the USB vendor ids for adb - try { - mSdkManager.updateAdb(); - monitor.log("Updated ADB to support the USB devices declared in the SDK add-ons."); - } catch (Exception e) { - mSdkLog.error(e, "Update ADB failed"); - monitor.logError("failed to update adb to support the USB devices declared in the SDK add-ons."); - } - } - - if (preInstallHookInvoked) { - broadcastPostInstallHook(); - } - - if (installedAddon || installedPlatformTools) { - // We need to restart ADB. Actually since we don't know if it's even - // running, maybe we should just kill it and not start it. - // Note: it turns out even under Windows we don't need to kill adb - // before updating the tools folder, as adb.exe is (surprisingly) not - // locked. - - askForAdbRestart(monitor); - } - - if (installedTools) { - notifyToolsNeedsToBeRestarted(flags); - } - - if (numInstalled == 0) { - monitor.setDescription("Done. Nothing was installed."); - } else { - monitor.setDescription("Done. %1$d %2$s installed.", - numInstalled, - numInstalled == 1 ? "package" : "packages"); - - //notify listeners something was installed, so that they can refresh - reloadSdk(); - } - } - }); - - return newlyInstalledArchives; - } - - /** - * A comparator to sort all the {@link ArchiveInfo} based on their - * dependency level. This forces the installer to install first all packages - * with no dependency, then those with one level of dependency, etc. - */ - private static class InstallOrderComparator implements Comparator<ArchiveInfo> { - - private final Map<ArchiveInfo, Integer> mOrders = new HashMap<ArchiveInfo, Integer>(); - - @Override - public int compare(ArchiveInfo o1, ArchiveInfo o2) { - int n1 = getDependencyOrder(o1); - int n2 = getDependencyOrder(o2); - - return n1 - n2; - } - - private int getDependencyOrder(ArchiveInfo ai) { - if (ai == null) { - return 0; - } - - // reuse cached value, if any - Integer cached = mOrders.get(ai); - if (cached != null) { - return cached.intValue(); - } - - ArchiveInfo[] deps = ai.getDependsOn(); - if (deps == null) { - return 0; - } - - // compute dependencies, recursively - int n = deps.length; - - for (ArchiveInfo dep : deps) { - n += getDependencyOrder(dep); - } - - // cache it - mOrders.put(ai, Integer.valueOf(n)); - - return n; - } - - } - - /** - * Attempts to restart ADB. - * <p/> - * If the "ask before restart" setting is set (the default), prompt the user whether - * now is a good time to restart ADB. - * - * @param monitor - */ - private void askForAdbRestart(ITaskMonitor monitor) { - final boolean[] canRestart = new boolean[] { true }; - - if (getWindowShell() != null && - getSettingsController().getSettings().getAskBeforeAdbRestart()) { - // need to ask for permission first - final Shell shell = getWindowShell(); - if (shell != null && !shell.isDisposed()) { - shell.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - if (!shell.isDisposed()) { - canRestart[0] = MessageDialog.openQuestion(shell, - "ADB Restart", - "A package that depends on ADB has been updated. \n" + - "Do you want to restart ADB now?"); - } - } - }); - } - } - - if (canRestart[0]) { - AdbWrapper adb = new AdbWrapper(getOsSdkRoot(), monitor); - adb.stopAdb(); - adb.startAdb(); - } - } - - private void notifyToolsNeedsToBeRestarted(int flags) { - - String msg = null; - if ((flags & TOOLS_MSG_UPDATED_FROM_ADT) != 0) { - msg = - "The Android SDK and AVD Manager that you are currently using has been updated. " + - "Please also run Eclipse > Help > Check for Updates to see if the Android " + - "plug-in needs to be updated."; - - } else if ((flags & TOOLS_MSG_UPDATED_FROM_SDKMAN) != 0) { - msg = - "The Android SDK and AVD Manager that you are currently using has been updated. " + - "It is recommended that you now close the manager window and re-open it. " + - "If you use Eclipse, please run Help > Check for Updates to see if the Android " + - "plug-in needs to be updated."; - } - - final String msg2 = msg; - - final Shell shell = getWindowShell(); - if (msg2 != null && shell != null && !shell.isDisposed()) { - shell.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - if (!shell.isDisposed()) { - MessageDialog.openInformation(shell, - "Android Tools Updated", - msg2); - } - } - }); - } - } - - - /** - * Tries to update all the *existing* local packages. - * This version *requires* to be run with a GUI. - * <p/> - * There are two modes of operation: - * <ul> - * <li>If selectedArchives is null, refreshes all sources, compares the available remote - * packages with the current local ones and suggest updates to be done to the user (including - * new platforms that the users doesn't have yet). - * <li>If selectedArchives is not null, this represents a list of archives/packages that - * the user wants to install or update, so just process these. - * </ul> - * - * @param selectedArchives The list of remote archives to consider for the update. - * This can be null, in which case a list of remote archive is fetched from all - * available sources. - * @param includeObsoletes True if obsolete packages should be used when resolving what - * to update. - * @param flags Optional flags for the installer, such as {@link #NO_TOOLS_MSG}. - * @return A list of archives that have been installed. Can be null if nothing was done. - */ - public List<Archive> updateOrInstallAll_WithGUI( - Collection<Archive> selectedArchives, - boolean includeObsoletes, - int flags) { - - // Note: we no longer call refreshSources(true) here. This will be done - // automatically by computeUpdates() iif it needs to access sources to - // resolve missing dependencies. - - SdkUpdaterLogic ul = new SdkUpdaterLogic(this); - List<ArchiveInfo> archives = ul.computeUpdates( - selectedArchives, - getSources(), - getLocalSdkParser().getPackages(), - includeObsoletes); - - if (selectedArchives == null) { - getPackageLoader().loadRemoteAddonsList(new NullTaskMonitor(getSdkLog())); - ul.addNewPlatforms( - archives, - getSources(), - getLocalSdkParser().getPackages(), - includeObsoletes); - } - - // TODO if selectedArchives is null and archives.len==0, find if there are - // any new platform we can suggest to install instead. - - Collections.sort(archives); - - SdkUpdaterChooserDialog dialog = - new SdkUpdaterChooserDialog(getWindowShell(), this, archives); - dialog.open(); - - ArrayList<ArchiveInfo> result = dialog.getResult(); - if (result != null && result.size() > 0) { - return installArchives(result, flags); - } - return null; - } - - /** - * Fetches all archives available on the known remote sources. - * - * Used by {@link UpdaterData#listRemotePackages_NoGUI} and - * {@link UpdaterData#updateOrInstallAll_NoGUI}. - * - * @param includeAll True to list and install all packages, including obsolete ones. - * @return A list of potential {@link ArchiveInfo} to install. - */ - private List<ArchiveInfo> getRemoteArchives_NoGUI(boolean includeAll) { - refreshSources(true); - getPackageLoader().loadRemoteAddonsList(new NullTaskMonitor(getSdkLog())); - - List<ArchiveInfo> archives; - SdkUpdaterLogic ul = new SdkUpdaterLogic(this); - - if (includeAll) { - archives = ul.getAllRemoteArchives( - getSources(), - getLocalSdkParser().getPackages(), - includeAll); - - } else { - archives = ul.computeUpdates( - null /*selectedArchives*/, - getSources(), - getLocalSdkParser().getPackages(), - includeAll); - - ul.addNewPlatforms( - archives, - getSources(), - getLocalSdkParser().getPackages(), - includeAll); - } - - Collections.sort(archives); - return archives; - } - - /** - * Lists remote packages available for install using - * {@link UpdaterData#updateOrInstallAll_NoGUI}. - * - * @param includeAll True to list and install all packages, including obsolete ones. - * @param extendedOutput True to display more details on each package. - */ - public void listRemotePackages_NoGUI(boolean includeAll, boolean extendedOutput) { - - List<ArchiveInfo> archives = getRemoteArchives_NoGUI(includeAll); - - mSdkLog.info("Packages available for installation or update: %1$d\n", archives.size()); - - int index = 1; - for (ArchiveInfo ai : archives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p != null) { - if (extendedOutput) { - mSdkLog.info("----------\n"); - mSdkLog.info("id: %1$d or \"%2$s\"\n", index, p.installId()); - mSdkLog.info(" Type: %1$s\n", - p.getClass().getSimpleName().replaceAll("Package", "")); //$NON-NLS-1$ //$NON-NLS-2$ - String desc = LineUtil.reformatLine(" Desc: %s\n", - p.getLongDescription()); - mSdkLog.info("%s", desc); //$NON-NLS-1$ - } else { - mSdkLog.info("%1$ 4d- %2$s\n", - index, - p.getShortDescription()); - } - index++; - } - } - } - } - - /** - * Tries to update all the *existing* local packages. - * This version is intended to run without a GUI and - * only outputs to the current {@link ILogger}. - * - * @param pkgFilter A list of {@link SdkRepoConstants#NODES} or {@link Package#installId()} - * or package indexes to limit the packages we can update or install. - * A null or empty list means to update everything possible. - * @param includeAll True to list and install all packages, including obsolete ones. - * @param dryMode True to check what would be updated/installed but do not actually - * download or install anything. - * @return A list of archives that have been installed. Can be null if nothing was done. - */ - public List<Archive> updateOrInstallAll_NoGUI( - Collection<String> pkgFilter, - boolean includeAll, - boolean dryMode) { - - List<ArchiveInfo> archives = getRemoteArchives_NoGUI(includeAll); - - // Filter the selected archives to only keep the ones matching the filter - if (pkgFilter != null && pkgFilter.size() > 0 && archives != null && archives.size() > 0) { - // Map filter types to an SdkRepository Package type, - // e.g. create a map "platform" => PlatformPackage.class - HashMap<String, Class<? extends Package>> pkgMap = - new HashMap<String, Class<? extends Package>>(); - - mapFilterToPackageClass(pkgMap, SdkRepoConstants.NODES); - mapFilterToPackageClass(pkgMap, SdkAddonConstants.NODES); - - // Prepare a map install-id => package instance - HashMap<String, Package> installIdMap = new HashMap<String, Package>(); - for (ArchiveInfo ai : archives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p != null) { - String id = p.installId(); - if (id != null && id.length() > 0 && !installIdMap.containsKey(id)) { - installIdMap.put(id, p); - } - } - } - } - - // Now intersect this with the pkgFilter requested by the user, in order to - // only keep the classes that the user wants to install. - // We also create a set with the package indices requested by the user - // and a set of install-ids requested by the user. - - HashSet<Class<? extends Package>> userFilteredClasses = - new HashSet<Class<? extends Package>>(); - SparseIntArray userFilteredIndices = new SparseIntArray(); - Set<String> userFilteredInstallIds = new HashSet<String>(); - - for (String type : pkgFilter) { - if (installIdMap.containsKey(type)) { - userFilteredInstallIds.add(type); - - } else if (type.replaceAll("[0-9]+", "").length() == 0) {//$NON-NLS-1$ //$NON-NLS-2$ - // An all-digit number is a package index requested by the user. - int index = Integer.parseInt(type); - userFilteredIndices.put(index, index); - - } else if (pkgMap.containsKey(type)) { - userFilteredClasses.add(pkgMap.get(type)); - - } else { - // This should not happen unless there's a mismatch in the package map. - mSdkLog.error(null, "Ignoring unknown package filter '%1$s'", type); - } - } - - // we don't need the maps anymore - pkgMap = null; - installIdMap = null; - - // Now filter the remote archives list to keep: - // - any package which class matches userFilteredClasses - // - any package index which matches userFilteredIndices - // - any package install id which matches userFilteredInstallIds - - int index = 1; - for (Iterator<ArchiveInfo> it = archives.iterator(); it.hasNext(); ) { - boolean keep = false; - ArchiveInfo ai = it.next(); - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p != null) { - if (userFilteredInstallIds.contains(p.installId()) || - userFilteredClasses.contains(p.getClass()) || - userFilteredIndices.get(index) > 0) { - keep = true; - } - - index++; - } - } - - if (!keep) { - it.remove(); - } - } - - if (archives.size() == 0) { - mSdkLog.info(LineUtil.reflowLine( - "Warning: The package filter removed all packages. There is nothing to install.\nPlease consider trying to update again without a package filter.\n")); - return null; - } - } - - if (archives != null && archives.size() > 0) { - if (dryMode) { - mSdkLog.info("Packages selected for install:\n"); - for (ArchiveInfo ai : archives) { - Archive a = ai.getNewArchive(); - if (a != null) { - Package p = a.getParentPackage(); - if (p != null) { - mSdkLog.info("- %1$s\n", p.getShortDescription()); - } - } - } - mSdkLog.info("\nDry mode is on so nothing is actually being installed.\n"); - } else { - return installArchives(archives, NO_TOOLS_MSG); - } - } else { - mSdkLog.info("There is nothing to install or update.\n"); - } - - return null; - } - - @SuppressWarnings("unchecked") - private void mapFilterToPackageClass( - HashMap<String, Class<? extends Package>> inOutPkgMap, - String[] nodes) { - - // Automatically find the classes matching the node names - ClassLoader classLoader = getClass().getClassLoader(); - String basePackage = Package.class.getPackage().getName(); - - for (String node : nodes) { - // Capitalize the name - String name = node.substring(0, 1).toUpperCase() + node.substring(1); - - // We can have one dash at most in a name. If it's present, we'll try - // with the dash or with the next letter capitalized. - int dash = name.indexOf('-'); - if (dash > 0) { - name = name.replaceFirst("-", ""); - } - - for (int alternatives = 0; alternatives < 2; alternatives++) { - - String fqcn = basePackage + '.' + name + "Package"; //$NON-NLS-1$ - try { - Class<? extends Package> clazz = - (Class<? extends Package>) classLoader.loadClass(fqcn); - if (clazz != null) { - inOutPkgMap.put(node, clazz); - continue; - } - } catch (Throwable ignore) { - } - - if (alternatives == 0 && dash > 0) { - // Try an alternative where the next letter after the dash - // is converted to an upper case. - name = name.substring(0, dash) + - name.substring(dash, dash + 1).toUpperCase() + - name.substring(dash + 1); - } else { - break; - } - } - } - } - - /** - * Refresh all sources. This is invoked either internally (reusing an existing monitor) - * or as a UI callback on the remote page "Refresh" button (in which case the monitor is - * null and a new task should be created.) - * - * @param forceFetching When true, load sources that haven't been loaded yet. - * When false, only refresh sources that have been loaded yet. - */ - public void refreshSources(final boolean forceFetching) { - assert mTaskFactory != null; - - final boolean forceHttp = getSettingsController().getSettings().getForceHttp(); - - mTaskFactory.start("Refresh Sources", new ITask() { - @Override - public void run(ITaskMonitor monitor) { - - getPackageLoader().loadRemoteAddonsList(monitor); - - SdkSource[] sources = getSources().getAllSources(); - monitor.setDescription("Refresh Sources"); - monitor.setProgressMax(monitor.getProgress() + sources.length); - for (SdkSource source : sources) { - if (forceFetching || - source.getPackages() != null || - source.getFetchError() != null) { - source.load(getDownloadCache(), monitor.createSubMonitor(1), forceHttp); - } - monitor.incProgress(1); - } - } - }); - } - - /** - * Safely invoke all the registered {@link ISdkChangeListener#onSdkLoaded()}. - * This can be called from any thread. - */ - public void broadcastOnSdkLoaded() { - if (mWindowShell != null && !mWindowShell.isDisposed() && mListeners.size() > 0) { - mWindowShell.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - for (ISdkChangeListener listener : mListeners) { - try { - listener.onSdkLoaded(); - } catch (Throwable t) { - mSdkLog.error(t, null); - } - } - } - }); - } - } - - /** - * Safely invoke all the registered {@link ISdkChangeListener#onSdkReload()}. - * This can be called from any thread. - */ - private void broadcastOnSdkReload() { - if (mWindowShell != null && !mWindowShell.isDisposed() && mListeners.size() > 0) { - mWindowShell.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - for (ISdkChangeListener listener : mListeners) { - try { - listener.onSdkReload(); - } catch (Throwable t) { - mSdkLog.error(t, null); - } - } - } - }); - } - } - - /** - * Safely invoke all the registered {@link ISdkChangeListener#preInstallHook()}. - * This can be called from any thread. - */ - private void broadcastPreInstallHook() { - if (mWindowShell != null && !mWindowShell.isDisposed() && mListeners.size() > 0) { - mWindowShell.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - for (ISdkChangeListener listener : mListeners) { - try { - listener.preInstallHook(); - } catch (Throwable t) { - mSdkLog.error(t, null); - } - } - } - }); - } - } - - /** - * Safely invoke all the registered {@link ISdkChangeListener#postInstallHook()}. - * This can be called from any thread. - */ - private void broadcastPostInstallHook() { - if (mWindowShell != null && !mWindowShell.isDisposed() && mListeners.size() > 0) { - mWindowShell.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - for (ISdkChangeListener listener : mListeners) { - try { - listener.postInstallHook(); - } catch (Throwable t) { - mSdkLog.error(t, null); - } - } - } - }); - } - } - - /** - * Internal helper to return a new {@link ArchiveInstaller}. - * This allows us to override the installer for unit-testing. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected ArchiveInstaller createArchiveInstaler() { - return new ArchiveInstaller(); - } - -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PackageLoader.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PackageLoader.java deleted file mode 100755 index 18cccae..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PackageLoader.java +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright (C) 2011 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.repository.core; - -import com.android.sdklib.internal.repository.AddonsListFetcher; -import com.android.sdklib.internal.repository.AddonsListFetcher.Site; -import com.android.sdklib.internal.repository.DownloadCache; -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.NullTaskMonitor; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.packages.Package.UpdateInfo; -import com.android.sdklib.internal.repository.sources.SdkAddonSource; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.internal.repository.sources.SdkSourceCategory; -import com.android.sdklib.internal.repository.sources.SdkSources; -import com.android.sdklib.internal.repository.sources.SdkSysImgSource; -import com.android.sdklib.repository.SdkAddonsListConstants; -import com.android.sdklib.repository.SdkRepoConstants; -import com.android.sdkuilib.internal.repository.UpdaterData; - -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Loads packages fetched from the remote SDK Repository and keeps track - * of their state compared with the current local SDK installation. - */ -public class PackageLoader { - - /** The update data context. Never null. */ - private final UpdaterData mUpdaterData; - - /** - * The {@link DownloadCache} override. Can be null, in which case the one from - * {@link UpdaterData} is used instead. - * @see #getDownloadCache() - */ - private final DownloadCache mOverrideCache; - - /** - * 0 = need to fetch remote addons list once.. - * 1 = fetch succeeded, don't need to do it any more. - * -1= fetch failed, do it again only if the user requests a refresh - * or changes the force-http setting. - */ - private int mStateFetchRemoteAddonsList; - - - /** - * Interface for the callback called by - * {@link PackageLoader#loadPackages(boolean, ISourceLoadedCallback)}. - * <p/> - * After processing each source, the package loader calls {@link #onUpdateSource} - * with the list of packages found in that source. - * By returning true from {@link #onUpdateSource}, the client tells the loader to - * continue and process the next source. By returning false, it tells to stop loading. - * <p/> - * The {@link #onLoadCompleted()} method is guaranteed to be called at the end, no - * matter how the loader stopped, so that the client can clean up or perform any - * final action. - */ - public interface ISourceLoadedCallback { - /** - * After processing each source, the package loader calls this method with the - * list of packages found in that source. - * By returning true from {@link #onUpdateSource}, the client tells - * the loader to continue and process the next source. - * By returning false, it tells to stop loading. - * <p/> - * <em>Important</em>: This method is called from a sub-thread, so clients which - * try to access any UI widgets must wrap their calls into - * {@link Display#syncExec(Runnable)} or {@link Display#asyncExec(Runnable)}. - * - * @param packages All the packages loaded from the source. Never null. - * @return True if the load operation should continue, false if it should stop. - */ - public boolean onUpdateSource(SdkSource source, Package[] packages); - - /** - * This method is guaranteed to be called at the end, no matter how the - * loader stopped, so that the client can clean up or perform any final action. - */ - public void onLoadCompleted(); - } - - /** - * Interface describing the task of installing a specific package. - * For details on the operation, - * see {@link PackageLoader#loadPackagesWithInstallTask(int, IAutoInstallTask)}. - * - * @see PackageLoader#loadPackagesWithInstallTask(int, IAutoInstallTask) - */ - public interface IAutoInstallTask { - /** - * Invoked by the loader once a source has been loaded and its package - * definitions are known. The method should return the {@code packages} - * array and can modify it if necessary. - * The loader will call {@link #acceptPackage(Package)} on all the packages returned. - * - * @param source The source of the packages. Null for the locally installed packages. - * @param packages The packages found in the source. - */ - public Package[] filterLoadedSource(SdkSource source, Package[] packages); - - /** - * Called by the install task for every package available (new ones, updates as well - * as existing ones that don't have a potential update.) - * The method should return true if this is a package that should be installed. - * <p/> - * <em>Important</em>: This method is called from a sub-thread, so clients who try - * to access any UI widgets must wrap their calls into {@link Display#syncExec(Runnable)} - * or {@link Display#asyncExec(Runnable)}. - */ - public boolean acceptPackage(Package pkg); - - /** - * Called when the accepted package has been installed, successfully or not. - * If an already installed (aka existing) package has been accepted, this will - * be called with a 'true' success and the actual install paths. - * <p/> - * <em>Important</em>: This method is called from a sub-thread, so clients who try - * to access any UI widgets must wrap their calls into {@link Display#syncExec(Runnable)} - * or {@link Display#asyncExec(Runnable)}. - */ - public void setResult(boolean success, Map<Package, File> installPaths); - - /** - * Called when the task is done iterating and completed. - */ - public void taskCompleted(); - } - - /** - * Creates a new PackageManager associated with the given {@link UpdaterData} - * and using the {@link UpdaterData}'s default {@link DownloadCache}. - * - * @param updaterData The {@link UpdaterData}. Must not be null. - */ - public PackageLoader(UpdaterData updaterData) { - mUpdaterData = updaterData; - mOverrideCache = null; - } - - /** - * Creates a new PackageManager associated with the given {@link UpdaterData} - * but using the specified {@link DownloadCache} instead of the one from - * {@link UpdaterData}. - * - * @param updaterData The {@link UpdaterData}. Must not be null. - * @param cache The {@link DownloadCache} to use instead of the one from {@link UpdaterData}. - */ - public PackageLoader(UpdaterData updaterData, DownloadCache cache) { - mUpdaterData = updaterData; - mOverrideCache = cache; - } - - /** - * Loads all packages from the remote repository. - * This runs in an {@link ITask}. The call is blocking. - * <p/> - * The callback is called with each set of {@link PkgItem} found in each source. - * The caller is responsible to accumulate the packages given to the callback - * after each source is finished loaded. In return the callback tells the loader - * whether to continue loading sources. - * <p/> - * Normally this method doesn't access the remote source if it's already - * been loaded in the in-memory source (e.g. don't fetch twice). - * - * @param overrideExisting Set this to true when the caller wants to - * check for updates and discard any existing source already - * loaded in memory. It should be false for normal use. - * @param sourceLoadedCallback The callback to invoke for each loaded source. - */ - public void loadPackages( - final boolean overrideExisting, - final ISourceLoadedCallback sourceLoadedCallback) { - try { - if (mUpdaterData == null) { - return; - } - - mUpdaterData.getTaskFactory().start("Loading Sources", new ITask() { - @Override - public void run(ITaskMonitor monitor) { - monitor.setProgressMax(10); - - // get local packages and offer them to the callback - Package[] localPkgs = - mUpdaterData.getInstalledPackages(monitor.createSubMonitor(1)); - if (localPkgs == null) { - localPkgs = new Package[0]; - } - if (!sourceLoadedCallback.onUpdateSource(null, localPkgs)) { - return; - } - - // get remote packages - boolean forceHttp = - mUpdaterData.getSettingsController().getSettings().getForceHttp(); - loadRemoteAddonsList(monitor.createSubMonitor(1)); - - SdkSource[] sources = mUpdaterData.getSources().getAllSources(); - try { - if (sources != null && sources.length > 0) { - ITaskMonitor subMonitor = monitor.createSubMonitor(8); - subMonitor.setProgressMax(sources.length); - for (SdkSource source : sources) { - Package[] pkgs = source.getPackages(); - if (pkgs == null || overrideExisting) { - source.load(getDownloadCache(), - subMonitor.createSubMonitor(1), - forceHttp); - pkgs = source.getPackages(); - } - if (pkgs == null) { - continue; - } - - // Notify the callback a new source has finished loading. - // If the callback requests so, stop right away. - if (!sourceLoadedCallback.onUpdateSource(source, pkgs)) { - return; - } - } - } - } catch(Exception e) { - monitor.logError("Loading source failed: %1$s", e.toString()); - } finally { - monitor.setDescription("Done loading packages."); - } - } - }); - } finally { - sourceLoadedCallback.onLoadCompleted(); - } - } - - /** - * Load packages, source by source using - * {@link #loadPackages(boolean, ISourceLoadedCallback)}, - * and executes the given {@link IAutoInstallTask} on the current package list. - * That is for each package known, the install task is queried to find if - * the package is the one to be installed or updated. - * <p/> - * - If an already installed package is accepted by the task, it is returned. <br/> - * - If a new package (remotely available but not installed locally) is accepted, - * the user will be <em>prompted</em> for permission to install it. <br/> - * - If an existing package has updates, the install task will be accept if it - * accepts one of the updating packages, and if yes the the user will be - * <em>prompted</em> for permission to install it. <br/> - * <p/> - * Only one package can be accepted, after which the task is completed. - * There is no direct return value, {@link IAutoInstallTask#setResult} is called on the - * result of the accepted package. - * When the task is completed, {@link IAutoInstallTask#taskCompleted()} is called. - * <p/> - * <em>Important</em>: Since some UI will be displayed to install the selected package, - * the {@link UpdaterData} must have a window {@link Shell} associated using - * {@link UpdaterData#setWindowShell(Shell)}. - * <p/> - * The call is blocking. Although the name says "Task", this is not an {@link ITask} - * running in its own thread but merely a synchronous call. - * - * @param installFlags Flags for installation such as - * {@link UpdaterData#TOOLS_MSG_UPDATED_FROM_ADT}. - * @param installTask The task to perform. - */ - public void loadPackagesWithInstallTask( - final int installFlags, - final IAutoInstallTask installTask) { - - loadPackages(false /*overrideExisting*/, new ISourceLoadedCallback() { - List<Archive> mArchivesToInstall = new ArrayList<Archive>(); - Map<Package, File> mInstallPaths = new HashMap<Package, File>(); - - @Override - public boolean onUpdateSource(SdkSource source, Package[] packages) { - packages = installTask.filterLoadedSource(source, packages); - if (packages == null || packages.length == 0) { - // Tell loadPackages() to process the next source. - return true; - } - - for (Package pkg : packages) { - if (pkg.isLocal()) { - // This is a local (aka installed) package - if (installTask.acceptPackage(pkg)) { - // If the caller is accepting an installed package, - // return a success and give the package's install path - Archive[] a = pkg.getArchives(); - // an installed package should have one local compatible archive - if (a.length == 1 && a[0].isCompatible()) { - mInstallPaths.put(pkg, new File(a[0].getLocalOsPath())); - } - } - - } else { - // This is a remote package - if (installTask.acceptPackage(pkg)) { - // The caller is accepting this remote package. We'll install it. - for (Archive archive : pkg.getArchives()) { - if (archive.isCompatible()) { - mArchivesToInstall.add(archive); - break; - } - } - } - } - } - - // Tell loadPackages() to process the next source. - return true; - } - - @Override - public void onLoadCompleted() { - if (!mArchivesToInstall.isEmpty()) { - installArchives(mArchivesToInstall); - } - if (mInstallPaths == null) { - installTask.setResult(false, null); - } else { - installTask.setResult(true, mInstallPaths); - } - - installTask.taskCompleted(); - } - - /** - * Shows the UI of the install selector. - * If the package is then actually installed, refresh the local list and - * notify the install task of the installation path. - * - * @param archivesToInstall The archives to install. - */ - private void installArchives(final List<Archive> archivesToInstall) { - // Actually install the new archives that we just found. - // This will display some UI so we need a shell's sync exec. - - final List<Archive> installedArchives = new ArrayList<Archive>(); - - Shell shell = mUpdaterData.getWindowShell(); - if (shell != null && !shell.isDisposed()) { - shell.getDisplay().syncExec(new Runnable() {; - @Override - public void run() { - List<Archive> archives = - mUpdaterData.updateOrInstallAll_WithGUI( - archivesToInstall, - true /* includeObsoletes */, - installFlags); - - if (archives != null) { - installedArchives.addAll(archives); - } - } - }); - } - - if (installedArchives.isEmpty()) { - // We failed to install anything. - mInstallPaths = null; - return; - } - - // The local package list has changed, make sure to refresh it - mUpdaterData.getSdkManager().reloadSdk(mUpdaterData.getSdkLog()); - mUpdaterData.getLocalSdkParser().clearPackages(); - final Package[] localPkgs = mUpdaterData.getInstalledPackages( - new NullTaskMonitor(mUpdaterData.getSdkLog())); - - // Scan the installed package list to find the install paths. - for (Archive installedArchive : installedArchives) { - Package pkg = installedArchive.getParentPackage(); - - for (Package localPkg : localPkgs) { - if (localPkg.canBeUpdatedBy(pkg) == UpdateInfo.NOT_UPDATE) { - Archive[] localArchive = localPkg.getArchives(); - if (localArchive.length == 1 && localArchive[0].isCompatible()) { - mInstallPaths.put( - localPkg, - new File(localArchive[0].getLocalOsPath())); - } - } - } - } - } - }); - } - - - /** - * Loads the remote add-ons list. - */ - public void loadRemoteAddonsList(ITaskMonitor monitor) { - - if (mStateFetchRemoteAddonsList != 0) { - return; - } - - mUpdaterData.getTaskFactory().start("Load Add-ons List", monitor, new ITask() { - @Override - public void run(ITaskMonitor subMonitor) { - loadRemoteAddonsListInTask(subMonitor); - } - }); - } - - private void loadRemoteAddonsListInTask(ITaskMonitor monitor) { - mStateFetchRemoteAddonsList = -1; - - String url = SdkAddonsListConstants.URL_ADDON_LIST; - - // We override SdkRepoConstants.URL_GOOGLE_SDK_SITE if this is defined - String baseUrl = System.getenv("SDK_TEST_BASE_URL"); //$NON-NLS-1$ - if (baseUrl != null) { - if (baseUrl.length() > 0 && baseUrl.endsWith("/")) { //$NON-NLS-1$ - if (url.startsWith(SdkRepoConstants.URL_GOOGLE_SDK_SITE)) { - url = baseUrl + url.substring(SdkRepoConstants.URL_GOOGLE_SDK_SITE.length()); - } - } else { - monitor.logError("Ignoring invalid SDK_TEST_BASE_URL: %1$s", baseUrl); //$NON-NLS-1$ - } - } - - if (mUpdaterData.getSettingsController().getSettings().getForceHttp()) { - url = url.replaceAll("https://", "http://"); //$NON-NLS-1$ //$NON-NLS-2$ - } - - // Hook to bypass loading 3rd party addons lists. - boolean fetch3rdParties = System.getenv("SDK_SKIP_3RD_PARTIES") == null; - - AddonsListFetcher fetcher = new AddonsListFetcher(); - Site[] sites = fetcher.fetch(url, getDownloadCache(), monitor); - if (sites != null) { - SdkSources sources = mUpdaterData.getSources(); - sources.removeAll(SdkSourceCategory.ADDONS_3RD_PARTY); - - if (fetch3rdParties) { - for (Site s : sites) { - switch (s.getType()) { - case ADDON_SITE: - sources.add(SdkSourceCategory.ADDONS_3RD_PARTY, - new SdkAddonSource(s.getUrl(), s.getUiName())); - break; - case SYS_IMG_SITE: - sources.add(SdkSourceCategory.ADDONS_3RD_PARTY, - new SdkSysImgSource(s.getUrl(), s.getUiName())); - break; - } - } - } - - sources.notifyChangeListeners(); - - mStateFetchRemoteAddonsList = 1; - } - - monitor.setDescription("Fetched Add-ons List successfully"); - } - - /** - * Returns the {@link DownloadCache} to use. - * - * @return Returns {@link #mOverrideCache} if not null; otherwise returns the - * one from {@link UpdaterData} is used instead. - */ - private DownloadCache getDownloadCache() { - return mOverrideCache != null ? mOverrideCache : mUpdaterData.getDownloadCache(); - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PackagesDiffLogic.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PackagesDiffLogic.java deleted file mode 100755 index a95c8ac..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PackagesDiffLogic.java +++ /dev/null @@ -1,947 +0,0 @@ -/* - * Copyright (C) 2011 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.repository.core; - -import com.android.SdkConstants; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.internal.repository.packages.ExtraPackage; -import com.android.sdklib.internal.repository.packages.IAndroidVersionProvider; -import com.android.sdklib.internal.repository.packages.IFullRevisionProvider; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.packages.Package.UpdateInfo; -import com.android.sdklib.internal.repository.packages.PlatformPackage; -import com.android.sdklib.internal.repository.packages.PlatformToolPackage; -import com.android.sdklib.internal.repository.packages.SystemImagePackage; -import com.android.sdklib.internal.repository.packages.ToolPackage; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.util.SparseArray; -import com.android.sdkuilib.internal.repository.UpdaterData; -import com.android.sdkuilib.internal.repository.core.PkgItem.PkgState; -import com.android.sdkuilib.internal.repository.ui.PackagesPageIcons; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Helper class that separates the logic of package management from the UI - * so that we can test it using head-less unit tests. - */ -public class PackagesDiffLogic { - private final UpdaterData mUpdaterData; - private boolean mFirstLoadComplete = true; - - public PackagesDiffLogic(UpdaterData updaterData) { - mUpdaterData = updaterData; - } - - /** - * Removes all the internal state and resets the object. - * Useful for testing. - */ - public void clear() { - mFirstLoadComplete = true; - mOpApi.clear(); - mOpSource.clear(); - } - - /** Return mFirstLoadComplete and resets it to false. - * All following calls will returns false. */ - public boolean isFirstLoadComplete() { - boolean b = mFirstLoadComplete; - mFirstLoadComplete = false; - return b; - } - - /** - * Mark all new and update PkgItems as checked. - * - * @param selectNew If true, select all new packages (except the rc/preview ones). - * @param selectUpdates If true, select all update packages. - * @param selectTop If true, select the top platform. - * If the top platform has nothing installed, select all items in it (except the rc/preview); - * If it is partially installed, at least select the platform and system images if none of - * the system images are installed. - * @param currentPlatform The {@link SdkConstants#currentPlatform()} value. - */ - public void checkNewUpdateItems( - boolean selectNew, - boolean selectUpdates, - boolean selectTop, - int currentPlatform) { - int maxApi = 0; - Set<Integer> installedPlatforms = new HashSet<Integer>(); - SparseArray<List<PkgItem>> platformItems = new SparseArray<List<PkgItem>>(); - - // sort items in platforms... directly deal with new/update items - List<PkgItem> allItems = getAllPkgItems(true /*byApi*/, true /*bySource*/); - for (PkgItem item : allItems) { - if (!item.hasCompatibleArchive()) { - // Ignore items that have no archive compatible with the current platform. - continue; - } - - // Get the main package's API level. We don't need to look at the updates - // since by definition they should target the same API level. - int api = 0; - Package p = item.getMainPackage(); - if (p instanceof IAndroidVersionProvider) { - api = ((IAndroidVersionProvider) p).getAndroidVersion().getApiLevel(); - } - - if (selectTop && api > 0) { - // Keep track of the max api seen - maxApi = Math.max(maxApi, api); - - // keep track of what platform is currently installed (that is, has at least - // one thing installed.) - if (item.getState() == PkgState.INSTALLED) { - installedPlatforms.add(api); - } - - // for each platform, collect all its related item for later use below. - List<PkgItem> items = platformItems.get(api); - if (items == null) { - platformItems.put(api, items = new ArrayList<PkgItem>()); - } - items.add(item); - } - - if ((selectUpdates || selectNew) && - item.getState() == PkgState.NEW && - !item.getRevision().isPreview()) { - boolean sameFound = false; - Package newPkg = item.getMainPackage(); - if (newPkg instanceof IFullRevisionProvider) { - // We have a potential new non-preview package; but this kind of package - // supports having previews, which means we want to make sure we're not - // offering an older "new" non-preview if there's a newer preview installed. - // - // We should get into this odd situation only when updating an RC/preview - // by a final release pkg. - - IFullRevisionProvider newPkg2 = (IFullRevisionProvider) newPkg; - for (PkgItem item2 : allItems) { - if (item2.getState() == PkgState.INSTALLED) { - Package installed = item2.getMainPackage(); - - if (installed.getRevision().isPreview() && - newPkg2.sameItemAs(installed, true /*ignorePreviews*/)) { - sameFound = true; - - if (installed.canBeUpdatedBy(newPkg) == UpdateInfo.UPDATE) { - item.setChecked(true); - break; - } - } - } - } - } - - if (selectNew && !sameFound) { - item.setChecked(true); - } - - } else if (selectUpdates && item.hasUpdatePkg()) { - item.setChecked(true); - } - } - - List<PkgItem> items = platformItems.get(maxApi); - if (selectTop && maxApi > 0 && items != null) { - if (!installedPlatforms.contains(maxApi)) { - // If the top platform has nothing installed at all, select everything in it - for (PkgItem item : items) { - if ((item.getState() == PkgState.NEW && !item.getRevision().isPreview()) || - item.hasUpdatePkg()) { - item.setChecked(true); - } - } - - } else { - // The top platform has at least one thing installed. - - // First make sure the platform package itself is installed, or select it. - for (PkgItem item : items) { - Package p = item.getMainPackage(); - if (p instanceof PlatformPackage && - item.getState() == PkgState.NEW && !item.getRevision().isPreview()) { - item.setChecked(true); - break; - } - } - - // Check we have at least one system image installed, otherwise select them - boolean hasSysImg = false; - for (PkgItem item : items) { - Package p = item.getMainPackage(); - if (p instanceof PlatformPackage && item.getState() == PkgState.INSTALLED) { - if (item.hasUpdatePkg() && item.isChecked()) { - // If the installed platform is scheduled for update, look for the - // system image in the update package, not the current one. - p = item.getUpdatePkg(); - if (p instanceof PlatformPackage) { - hasSysImg = ((PlatformPackage) p).getIncludedAbi() != null; - } - } else { - // Otherwise look into the currently installed platform - hasSysImg = ((PlatformPackage) p).getIncludedAbi() != null; - } - if (hasSysImg) { - break; - } - } - if (p instanceof SystemImagePackage && item.getState() == PkgState.INSTALLED) { - hasSysImg = true; - break; - } - } - if (!hasSysImg) { - // No system image installed. - // Try whether the current platform or its update would bring one. - - for (PkgItem item : items) { - Package p = item.getMainPackage(); - if (p instanceof PlatformPackage) { - if (item.getState() == PkgState.NEW && - !item.getRevision().isPreview() && - ((PlatformPackage) p).getIncludedAbi() != null) { - item.setChecked(true); - hasSysImg = true; - } else if (item.hasUpdatePkg()) { - p = item.getUpdatePkg(); - if (p instanceof PlatformPackage && - ((PlatformPackage) p).getIncludedAbi() != null) { - item.setChecked(true); - hasSysImg = true; - } - } - } - } - } - if (!hasSysImg) { - // No system image in the platform, try a system image package - for (PkgItem item : items) { - Package p = item.getMainPackage(); - if (p instanceof SystemImagePackage && item.getState() == PkgState.NEW) { - item.setChecked(true); - } - } - } - } - } - - if (selectTop) { - for (PkgItem item : getAllPkgItems(true /*byApi*/, true /*bySource*/)) { - Package p = item.getMainPackage(); - if (p instanceof ExtraPackage && - item.getState() == PkgState.NEW && - !item.getRevision().isPreview()) { - ExtraPackage ep = (ExtraPackage) p; - - // On Windows, we'll also auto-select the USB driver - if (currentPlatform == SdkConstants.PLATFORM_WINDOWS) { - if (ep.getVendorId().equals("google") && //$NON-NLS-1$ - ep.getPath().equals("usb_driver")) { //$NON-NLS-1$ - item.setChecked(true); - continue; - } - } - - // On all platforms, we'll auto-select the support library. - if (ep.getVendorId().equals("android") && //$NON-NLS-1$ - ep.getPath().equals("support")) { //$NON-NLS-1$ - item.setChecked(true); - continue; - } - - } - } - } - } - - /** - * Mark all PkgItems as not checked. - */ - public void uncheckAllItems() { - for (PkgItem item : getAllPkgItems(true /*byApi*/, true /*bySource*/)) { - item.setChecked(false); - } - } - - /** - * An update operation, customized to either sort by API or sort by source. - */ - abstract class UpdateOp { - private final Set<SdkSource> mVisitedSources = new HashSet<SdkSource>(); - private final List<PkgCategory> mCategories = new ArrayList<PkgCategory>(); - private final Set<PkgCategory> mCatsToRemove = new HashSet<PkgCategory>(); - private final Set<PkgItem> mItemsToRemove = new HashSet<PkgItem>(); - private final Map<Package, PkgItem> mUpdatesToRemove = new HashMap<Package, PkgItem>(); - - /** Removes all internal state. */ - public void clear() { - mVisitedSources.clear(); - mCategories.clear(); - } - - /** Retrieve the sorted category list. */ - public List<PkgCategory> getCategories() { - return mCategories; - } - - /** Retrieve the category key for the given package, either local or remote. */ - public abstract Object getCategoryKey(Package pkg); - - /** Modified {@code currentCategories} to add default categories. */ - public abstract void addDefaultCategories(); - - /** Creates the category for the given key and returns it. */ - public abstract PkgCategory createCategory(Object catKey); - /** Adjust attributes of an existing category. */ - public abstract void adjustCategory(PkgCategory cat, Object catKey); - - /** Sorts the category list (but not the items within the categories.) */ - public abstract void sortCategoryList(); - - /** Called after items of a given category have changed. Used to sort the - * items and/or adjust the category name. */ - public abstract void postCategoryItemsChanged(); - - public void updateStart() { - mVisitedSources.clear(); - - // Note that default categories are created after the unused ones so that - // the callback can decide whether they should be marked as unused or not. - mCatsToRemove.clear(); - mItemsToRemove.clear(); - mUpdatesToRemove.clear(); - for (PkgCategory cat : mCategories) { - mCatsToRemove.add(cat); - List<PkgItem> items = cat.getItems(); - mItemsToRemove.addAll(items); - for (PkgItem item : items) { - if (item.hasUpdatePkg()) { - mUpdatesToRemove.put(item.getUpdatePkg(), item); - } - } - } - - addDefaultCategories(); - } - - public boolean updateSourcePackages(SdkSource source, Package[] newPackages) { - mVisitedSources.add(source); - if (source == null) { - return processLocals(this, newPackages); - } else { - return processSource(this, source, newPackages); - } - } - - public boolean updateEnd() { - boolean hasChanged = false; - - // Remove unused categories & items at the end of the update - synchronized (mCategories) { - for (PkgCategory unusedCat : mCatsToRemove) { - if (mCategories.remove(unusedCat)) { - hasChanged = true; - } - } - } - - for (PkgCategory cat : mCategories) { - for (Iterator<PkgItem> itemIt = cat.getItems().iterator(); itemIt.hasNext(); ) { - PkgItem item = itemIt.next(); - if (mItemsToRemove.contains(item)) { - itemIt.remove(); - hasChanged = true; - } else if (item.hasUpdatePkg() && - mUpdatesToRemove.containsKey(item.getUpdatePkg())) { - item.removeUpdate(); - hasChanged = true; - } - } - } - - mCatsToRemove.clear(); - mItemsToRemove.clear(); - mUpdatesToRemove.clear(); - - return hasChanged; - } - - public boolean isKeep(PkgItem item) { - return !mItemsToRemove.contains(item); - } - - public void keep(Package pkg) { - mUpdatesToRemove.remove(pkg); - } - - public void keep(PkgItem item) { - mItemsToRemove.remove(item); - } - - public void keep(PkgCategory cat) { - mCatsToRemove.remove(cat); - } - - public void dontKeep(PkgItem item) { - mItemsToRemove.add(item); - } - - public void dontKeep(PkgCategory cat) { - mCatsToRemove.add(cat); - } - } - - private final UpdateOpApi mOpApi = new UpdateOpApi(); - private final UpdateOpSource mOpSource = new UpdateOpSource(); - - public List<PkgCategory> getCategories(boolean displayIsSortByApi) { - return displayIsSortByApi ? mOpApi.getCategories() : mOpSource.getCategories(); - } - - public List<PkgItem> getAllPkgItems(boolean byApi, boolean bySource) { - List<PkgItem> items = new ArrayList<PkgItem>(); - - if (byApi) { - List<PkgCategory> cats = getCategories(true /*displayIsSortByApi*/); - synchronized (cats) { - for (PkgCategory cat : cats) { - items.addAll(cat.getItems()); - } - } - } - - if (bySource) { - List<PkgCategory> cats = getCategories(false /*displayIsSortByApi*/); - synchronized (cats) { - for (PkgCategory cat : cats) { - items.addAll(cat.getItems()); - } - } - } - - return items; - } - - public void updateStart() { - mOpApi.updateStart(); - mOpSource.updateStart(); - } - - public boolean updateSourcePackages( - boolean displayIsSortByApi, - SdkSource source, - Package[] newPackages) { - - boolean apiListChanged = mOpApi.updateSourcePackages(source, newPackages); - boolean sourceListChanged = mOpSource.updateSourcePackages(source, newPackages); - return displayIsSortByApi ? apiListChanged : sourceListChanged; - } - - public boolean updateEnd(boolean displayIsSortByApi) { - boolean apiListChanged = mOpApi.updateEnd(); - boolean sourceListChanged = mOpSource.updateEnd(); - return displayIsSortByApi ? apiListChanged : sourceListChanged; - } - - - /** Process all local packages. Returns true if something changed. */ - private boolean processLocals(UpdateOp op, Package[] packages) { - boolean hasChanged = false; - List<PkgCategory> cats = op.getCategories(); - Set<PkgItem> keep = new HashSet<PkgItem>(); - - // For all locally installed packages, check they are either listed - // as installed or create new installed items for them. - - nextPkg: for (Package localPkg : packages) { - // Check to see if we already have the exact same package - // (type & revision) marked as installed. - for (PkgCategory cat : cats) { - for (PkgItem currItem : cat.getItems()) { - if (currItem.getState() == PkgState.INSTALLED && - currItem.isSameMainPackageAs(localPkg)) { - // This package is already listed as installed. - op.keep(currItem); - op.keep(cat); - keep.add(currItem); - continue nextPkg; - } - } - } - - // If not found, create a new installed package item - keep.add(addNewItem(op, localPkg, PkgState.INSTALLED)); - hasChanged = true; - } - - // Remove installed items that we don't want to keep anymore. They would normally be - // cleanup up in UpdateOp.updateEnd(); however it's easier to remove them before we - // run processSource() to avoid merging updates in items that would be removed later. - - for (PkgCategory cat : cats) { - for (Iterator<PkgItem> itemIt = cat.getItems().iterator(); itemIt.hasNext(); ) { - PkgItem item = itemIt.next(); - if (item.getState() == PkgState.INSTALLED && !keep.contains(item)) { - itemIt.remove(); - hasChanged = true; - } - } - } - - if (hasChanged) { - op.postCategoryItemsChanged(); - } - - return hasChanged; - } - - /** - * {@link PkgState}s to check in {@link #processSource(UpdateOp, SdkSource, Package[])}. - * The order matters. - * When installing the diff will have both the new and the installed item and we - * need to merge with the installed one before the new one. - */ - private final static PkgState[] PKG_STATES = { PkgState.INSTALLED, PkgState.NEW }; - - /** Process all remote packages. Returns true if something changed. */ - private boolean processSource(UpdateOp op, SdkSource source, Package[] packages) { - boolean hasChanged = false; - List<PkgCategory> cats = op.getCategories(); - - boolean enablePreviews = - mUpdaterData.getSettingsController().getSettings().getEnablePreviews(); - - nextPkg: for (Package newPkg : packages) { - - if (!enablePreviews && newPkg.getRevision().isPreview()) { - // This is a preview and previews are not enabled. Ignore the package. - continue nextPkg; - } - - for (PkgCategory cat : cats) { - for (PkgState state : PKG_STATES) { - for (Iterator<PkgItem> currItemIt = cat.getItems().iterator(); - currItemIt.hasNext(); ) { - PkgItem currItem = currItemIt.next(); - // We need to merge with installed items first. When installing - // the diff will have both the new and the installed item and we - // need to merge with the installed one before the new one. - if (currItem.getState() != state) { - continue; - } - // Only process current items if they represent the same item (but - // with a different revision number) than the new package. - Package mainPkg = currItem.getMainPackage(); - if (!mainPkg.sameItemAs(newPkg)) { - continue; - } - - // Check to see if we already have the exact same package - // (type & revision) marked as main or update package. - if (currItem.isSameMainPackageAs(newPkg)) { - op.keep(currItem); - op.keep(cat); - continue nextPkg; - } else if (currItem.hasUpdatePkg() && - currItem.isSameUpdatePackageAs(newPkg)) { - op.keep(currItem.getUpdatePkg()); - op.keep(cat); - continue nextPkg; - } - - switch (currItem.getState()) { - case NEW: - if (newPkg.getRevision().compareTo(mainPkg.getRevision()) < 0) { - if (!op.isKeep(currItem)) { - // The new item has a lower revision than the current one, - // but the current one hasn't been marked as being kept so - // it's ok to downgrade it. - currItemIt.remove(); - addNewItem(op, newPkg, PkgState.NEW); - hasChanged = true; - } - } else if (newPkg.getRevision().compareTo(mainPkg.getRevision()) > 0) { - // We have a more recent new version, remove the current one - // and replace by a new one - currItemIt.remove(); - addNewItem(op, newPkg, PkgState.NEW); - hasChanged = true; - } - break; - case INSTALLED: - // if newPkg.revision<=mainPkg.revision: it's already installed, ignore. - if (newPkg.getRevision().compareTo(mainPkg.getRevision()) > 0) { - // This is a new update for the main package. - if (currItem.mergeUpdate(newPkg)) { - op.keep(currItem.getUpdatePkg()); - op.keep(cat); - hasChanged = true; - } - } - break; - } - continue nextPkg; - } - } - } - // If not found, create a new package item - addNewItem(op, newPkg, PkgState.NEW); - hasChanged = true; - } - - if (hasChanged) { - op.postCategoryItemsChanged(); - } - - return hasChanged; - } - - private PkgItem addNewItem(UpdateOp op, Package pkg, PkgState state) { - List<PkgCategory> cats = op.getCategories(); - Object catKey = op.getCategoryKey(pkg); - PkgCategory cat = findCurrentCategory(cats, catKey); - - if (cat == null) { - // This is a new category. Create it and add it to the list. - cat = op.createCategory(catKey); - synchronized (cats) { - cats.add(cat); - } - op.sortCategoryList(); - } else { - // Not a new category. Give op a chance to adjust the category attributes - op.adjustCategory(cat, catKey); - } - - PkgItem item = new PkgItem(pkg, state); - op.keep(item); - cat.getItems().add(item); - op.keep(cat); - return item; - } - - private PkgCategory findCurrentCategory( - List<PkgCategory> currentCategories, - Object categoryKey) { - for (PkgCategory cat : currentCategories) { - if (cat.getKey().equals(categoryKey)) { - return cat; - } - } - return null; - } - - /** - * {@link UpdateOp} describing the Sort-by-API operation. - */ - private class UpdateOpApi extends UpdateOp { - @Override - public Object getCategoryKey(Package pkg) { - // Sort by API - - if (pkg instanceof IAndroidVersionProvider) { - return ((IAndroidVersionProvider) pkg).getAndroidVersion(); - - } else if (pkg instanceof ToolPackage || pkg instanceof PlatformToolPackage) { - if (pkg.getRevision().isPreview()) { - return PkgCategoryApi.KEY_TOOLS_PREVIEW; - } else { - return PkgCategoryApi.KEY_TOOLS; - } - } else { - return PkgCategoryApi.KEY_EXTRA; - } - } - - @Override - public void addDefaultCategories() { - boolean needTools = true; - boolean needExtras = true; - - List<PkgCategory> cats = getCategories(); - for (PkgCategory cat : cats) { - if (cat.getKey().equals(PkgCategoryApi.KEY_TOOLS)) { - // Mark them as no unused to prevent their removal in updateEnd(). - keep(cat); - needTools = false; - } else if (cat.getKey().equals(PkgCategoryApi.KEY_EXTRA)) { - keep(cat); - needExtras = false; - } - } - - // Always add the tools & extras categories, even if empty (unlikely anyway) - if (needTools) { - PkgCategoryApi acat = new PkgCategoryApi( - PkgCategoryApi.KEY_TOOLS, - null, - mUpdaterData.getImageFactory().getImageByName(PackagesPageIcons.ICON_CAT_OTHER)); - synchronized (cats) { - cats.add(acat); - } - } - - if (needExtras) { - PkgCategoryApi acat = new PkgCategoryApi( - PkgCategoryApi.KEY_EXTRA, - null, - mUpdaterData.getImageFactory().getImageByName(PackagesPageIcons.ICON_CAT_OTHER)); - synchronized (cats) { - cats.add(acat); - } - } - } - - @Override - public PkgCategory createCategory(Object catKey) { - // Create API category. - PkgCategory cat = null; - - assert catKey instanceof AndroidVersion; - AndroidVersion key = (AndroidVersion) catKey; - - // We should not be trying to recreate the tools or extra categories. - assert !key.equals(PkgCategoryApi.KEY_TOOLS) && !key.equals(PkgCategoryApi.KEY_EXTRA); - - // We need a label for the category. - // If we have an API level, try to get the info from the SDK Manager. - // If we don't (e.g. when installing a new platform that isn't yet available - // locally in the SDK Manager), it's OK we'll try to find the first platform - // package available. - String platformName = null; - for (IAndroidTarget target : - mUpdaterData.getSdkManager().getTargets()) { - if (target.isPlatform() && key.equals(target.getVersion())) { - platformName = target.getVersionName(); - break; - } - } - - cat = new PkgCategoryApi( - key, - platformName, - mUpdaterData.getImageFactory().getImageByName(PackagesPageIcons.ICON_CAT_PLATFORM)); - - return cat; - } - - @Override - public void adjustCategory(PkgCategory cat, Object catKey) { - // Pass. Nothing to do for API-sorted categories - } - - @Override - public void sortCategoryList() { - // Sort the categories list. - // We always want categories in order tools..platforms..extras. - // For platform, we compare in descending order (o2-o1). - // This order is achieved by having the category keys ordered as - // needed for the sort to just do what we expect. - - synchronized (getCategories()) { - Collections.sort(getCategories(), new Comparator<PkgCategory>() { - @Override - public int compare(PkgCategory cat1, PkgCategory cat2) { - assert cat1 instanceof PkgCategoryApi; - assert cat2 instanceof PkgCategoryApi; - assert cat1.getKey() instanceof AndroidVersion; - assert cat2.getKey() instanceof AndroidVersion; - AndroidVersion v1 = (AndroidVersion) cat1.getKey(); - AndroidVersion v2 = (AndroidVersion) cat2.getKey(); - return v2.compareTo(v1); - } - }); - } - } - - @Override - public void postCategoryItemsChanged() { - // Sort the items - for (PkgCategory cat : getCategories()) { - Collections.sort(cat.getItems()); - - // When sorting by API, we can't always get the platform name - // from the package manager. In this case at the very end we - // look for a potential platform package we can use to extract - // the platform version name (e.g. '1.5') from the first suitable - // platform package we can find. - - assert cat instanceof PkgCategoryApi; - PkgCategoryApi pac = (PkgCategoryApi) cat; - if (pac.getPlatformName() == null) { - // Check whether we can get the actual platform version name (e.g. "1.5") - // from the first Platform package we find in this category. - - for (PkgItem item : cat.getItems()) { - Package p = item.getMainPackage(); - if (p instanceof PlatformPackage) { - String platformName = ((PlatformPackage) p).getVersionName(); - if (platformName != null) { - pac.setPlatformName(platformName); - break; - } - } - } - } - } - - } - } - - /** - * {@link UpdateOp} describing the Sort-by-Source operation. - */ - private class UpdateOpSource extends UpdateOp { - - @Override - public boolean updateSourcePackages(SdkSource source, Package[] newPackages) { - // When displaying the repo by source, we want to create all the - // categories so that they can appear on the UI even if empty. - if (source != null) { - List<PkgCategory> cats = getCategories(); - Object catKey = source; - PkgCategory cat = findCurrentCategory(cats, catKey); - - if (cat == null) { - // This is a new category. Create it and add it to the list. - cat = createCategory(catKey); - synchronized (cats) { - cats.add(cat); - } - sortCategoryList(); - } - - keep(cat); - } - - return super.updateSourcePackages(source, newPackages); - } - - @Override - public Object getCategoryKey(Package pkg) { - // Sort by source - SdkSource source = pkg.getParentSource(); - if (source == null) { - return PkgCategorySource.UNKNOWN_SOURCE; - } - return source; - } - - @Override - public void addDefaultCategories() { - List<PkgCategory> cats = getCategories(); - for (PkgCategory cat : cats) { - if (cat.getKey().equals(PkgCategorySource.UNKNOWN_SOURCE)) { - // Already present. - return; - } - } - - // Always add the local categories, even if empty (unlikely anyway) - PkgCategorySource cat = new PkgCategorySource( - PkgCategorySource.UNKNOWN_SOURCE, - mUpdaterData); - // Mark it so that it can be cleared in updateEnd() if not used. - dontKeep(cat); - synchronized (cats) { - cats.add(cat); - } - } - - /** - * Create a new source category. - * <p/> - * One issue is that local archives are processed first and we don't have the - * full source information on them (e.g. we know the referral URL but not - * the referral name of the site). - * In this case this will just create {@link PkgCategorySource} where the label isn't - * known yet. - */ - @Override - public PkgCategory createCategory(Object catKey) { - assert catKey instanceof SdkSource; - PkgCategory cat = new PkgCategorySource((SdkSource) catKey, mUpdaterData); - return cat; - } - - /** - * Checks whether the category needs to be adjust. - * As mentioned in {@link #createCategory(Object)}, local archives are processed - * first and result in a {@link PkgCategorySource} where the label isn't known. - * Once we process the external source with the actual name, we'll update it. - */ - @Override - public void adjustCategory(PkgCategory cat, Object catKey) { - assert cat instanceof PkgCategorySource; - assert catKey instanceof SdkSource; - if (cat instanceof PkgCategorySource) { - ((PkgCategorySource) cat).adjustLabel((SdkSource) catKey); - } - } - - @Override - public void sortCategoryList() { - // Sort the sources in ascending source name order, - // with the local packages always first. - - synchronized (getCategories()) { - Collections.sort(getCategories(), new Comparator<PkgCategory>() { - @Override - public int compare(PkgCategory cat1, PkgCategory cat2) { - assert cat1 instanceof PkgCategorySource; - assert cat2 instanceof PkgCategorySource; - - SdkSource src1 = ((PkgCategorySource) cat1).getSource(); - SdkSource src2 = ((PkgCategorySource) cat2).getSource(); - - if (src1 == src2) { - return 0; - } else if (src1 == PkgCategorySource.UNKNOWN_SOURCE) { - return -1; - } else if (src2 == PkgCategorySource.UNKNOWN_SOURCE) { - return 1; - } - assert src1 != null; // true because LOCAL_SOURCE==null - assert src2 != null; - return src1.toString().compareTo(src2.toString()); - } - }); - } - } - - @Override - public void postCategoryItemsChanged() { - // Sort the items - for (PkgCategory cat : getCategories()) { - Collections.sort(cat.getItems()); - } - } - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PkgCategory.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PkgCategory.java deleted file mode 100755 index a08b6ef..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PkgCategory.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2011 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.repository.core; - - -import java.util.ArrayList; -import java.util.List; - -public abstract class PkgCategory { - private final Object mKey; - private final Object mIconRef; - private final List<PkgItem> mItems = new ArrayList<PkgItem>(); - private String mLabel; - - public PkgCategory(Object key, String label, Object iconRef) { - mKey = key; - mLabel = label; - mIconRef = iconRef; - } - - public Object getKey() { - return mKey; - } - - public String getLabel() { - return mLabel; - } - - public void setLabel(String label) { - mLabel = label; - } - - public Object getIconRef() { - return mIconRef; - } - - public List<PkgItem> getItems() { - return mItems; - } - - @Override - public String toString() { - return String.format("%s <key=%s, label=%s, #items=%d>", - this.getClass().getSimpleName(), - mKey == null ? "null" : mKey.toString(), - mLabel, - mItems.size()); - } - - /** {@link PkgCategory}s are equal if their internal keys are equal. */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((mKey == null) ? 0 : mKey.hashCode()); - return result; - } - - /** {@link PkgCategory}s are equal if their internal keys are equal. */ - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - PkgCategory other = (PkgCategory) obj; - if (mKey == null) { - if (other.mKey != null) return false; - } else if (!mKey.equals(other.mKey)) return false; - return true; - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PkgCategoryApi.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PkgCategoryApi.java deleted file mode 100755 index aff11e5..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PkgCategoryApi.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2011 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.repository.core; - -import com.android.sdklib.AndroidVersion; - - -public class PkgCategoryApi extends PkgCategory { - - /** Platform name, in the form "Android 1.2". Can be null if we don't have the name. */ - private String mPlatformName; - - // When sorting by Source, key is the hash of the source's name. - // When storing by API, key is the AndroidVersion (API level >=1 + optional codename). - // We always want categories in order tools..platforms..extras; to achieve that tools - // and extras have the special values so they get "naturally" sorted the way we want - // them. - // (Note: don't use integer.max to avoid integers wrapping in comparisons. We can - // revisit the day we get 2^30 platforms.) - public final static AndroidVersion KEY_TOOLS = new AndroidVersion(Integer.MAX_VALUE / 2, null); - public final static AndroidVersion KEY_TOOLS_PREVIEW = - new AndroidVersion(Integer.MAX_VALUE / 2 - 1, null); - public final static AndroidVersion KEY_EXTRA = new AndroidVersion(-1, null); - - public PkgCategoryApi(AndroidVersion version, String platformName, Object iconRef) { - super(version, null /*label*/, iconRef); - setPlatformName(platformName); - } - - public String getPlatformName() { - return mPlatformName; - } - - public void setPlatformName(String platformName) { - if (platformName != null) { - // Normal case for actual platform categories - mPlatformName = String.format("Android %1$s", platformName); - super.setLabel(null); - } - } - - public String getApiLabel() { - AndroidVersion key = (AndroidVersion) getKey(); - if (key.equals(KEY_TOOLS)) { - return "TOOLS"; //$NON-NLS-1$ // for internal debug use only - } else if (key.equals(KEY_TOOLS_PREVIEW)) { - return "TOOLS-PREVIEW"; //$NON-NLS-1$ // for internal debug use only - } else if (key.equals(KEY_EXTRA)) { - return "EXTRAS"; //$NON-NLS-1$ // for internal debug use only - } else { - return key.toString(); - } - } - - @Override - public String getLabel() { - String label = super.getLabel(); - if (label == null) { - AndroidVersion key = (AndroidVersion) getKey(); - - if (key.equals(KEY_TOOLS)) { - label = "Tools"; - } else if (key.equals(KEY_TOOLS_PREVIEW)) { - label = "Tools (Preview Channel)"; - } else if (key.equals(KEY_EXTRA)) { - label = "Extras"; - } else { - if (mPlatformName != null) { - label = String.format("%1$s (%2$s)", mPlatformName, getApiLabel()); - } else { - label = getApiLabel(); - } - } - super.setLabel(label); - } - return label; - } - - @Override - public void setLabel(String label) { - throw new UnsupportedOperationException("Use setPlatformName() instead."); - } - - @Override - public String toString() { - return String.format("%s <API=%s, label=%s, #items=%d>", - this.getClass().getSimpleName(), - getApiLabel(), - getLabel(), - getItems().size()); - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PkgCategorySource.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PkgCategorySource.java deleted file mode 100755 index b73288b..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PkgCategorySource.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2011 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.repository.core; - -import com.android.sdklib.internal.repository.sources.SdkRepoSource; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdkuilib.internal.repository.UpdaterData; -import com.android.sdkuilib.internal.repository.ui.PackagesPageIcons; - - -public class PkgCategorySource extends PkgCategory { - - /** - * A special {@link SdkSource} object that represents the locally installed - * items, or more exactly a lack of remote source. - */ - public final static SdkSource UNKNOWN_SOURCE = - new SdkRepoSource("http://no.source", "Local Packages"); - private final SdkSource mSource; - - /** - * Creates a new {@link PkgCategorySource}. - * This uses {@link SdkSource#toString()} to get the source's description. - * Note that if the name of the source isn't known, the description will use its URL. - */ - public PkgCategorySource(SdkSource source, UpdaterData updaterData) { - super( - source, // the source is the key and it can be null - source == UNKNOWN_SOURCE ? "Local Packages" : source.toString(), - source == UNKNOWN_SOURCE ? - updaterData.getImageFactory().getImageByName(PackagesPageIcons.ICON_PKG_INSTALLED) : - source); - mSource = source; - } - - @Override - public String toString() { - return String.format("%s <source=%s, #items=%d>", - this.getClass().getSimpleName(), - mSource.toString(), - getItems().size()); - } - - public SdkSource getSource() { - return mSource; - } - - /** Sets the label to match the source's UI name if the label wasn't already set. */ - public void adjustLabel(SdkSource source) { - if (getLabel() == null || getLabel().startsWith("http")) { //$NON-NLS-1$ - setLabel(source == UNKNOWN_SOURCE ? "Local Packages" : source.toString()); - } - } - -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PkgContentProvider.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PkgContentProvider.java deleted file mode 100755 index 8adf428..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PkgContentProvider.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (C) 2012 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.repository.core; - -import com.android.sdklib.internal.repository.IDescription; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdkuilib.internal.repository.ui.PackagesPage; - -import org.eclipse.jface.viewers.IInputProvider; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.Viewer; - -import java.util.ArrayList; -import java.util.List; - -/** - * Content provider for the main tree view in {@link PackagesPage}. - */ -public class PkgContentProvider implements ITreeContentProvider { - - private final IInputProvider mViewer; - private boolean mDisplayArchives; - - public PkgContentProvider(IInputProvider viewer) { - mViewer = viewer; - } - - public void setDisplayArchives(boolean displayArchives) { - mDisplayArchives = displayArchives; - } - - @Override - public Object[] getChildren(Object parentElement) { - if (parentElement instanceof ArrayList<?>) { - return ((ArrayList<?>) parentElement).toArray(); - - } else if (parentElement instanceof PkgCategorySource) { - return getSourceChildren((PkgCategorySource) parentElement); - - } else if (parentElement instanceof PkgCategory) { - return ((PkgCategory) parentElement).getItems().toArray(); - - } else if (parentElement instanceof PkgItem) { - if (mDisplayArchives) { - - Package pkg = ((PkgItem) parentElement).getUpdatePkg(); - - // Display update packages as sub-items if the details mode is activated. - if (pkg != null) { - return new Object[] { pkg }; - } - - return ((PkgItem) parentElement).getArchives(); - } - - } else if (parentElement instanceof Package) { - if (mDisplayArchives) { - return ((Package) parentElement).getArchives(); - } - - } - - return new Object[0]; - } - - @Override - @SuppressWarnings("unchecked") - public Object getParent(Object element) { - // This operation is expensive, so we do the minimum - // and don't try to cover all cases. - - if (element instanceof PkgItem) { - Object input = mViewer.getInput(); - if (input != null) { - for (PkgCategory cat : (List<PkgCategory>) input) { - if (cat.getItems().contains(element)) { - return cat; - } - } - } - } - - return null; - } - - @Override - public boolean hasChildren(Object parentElement) { - if (parentElement instanceof ArrayList<?>) { - return true; - - } else if (parentElement instanceof PkgCategory) { - return true; - - } else if (parentElement instanceof PkgItem) { - if (mDisplayArchives) { - Package pkg = ((PkgItem) parentElement).getUpdatePkg(); - - // Display update packages as sub-items if the details mode is activated. - if (pkg != null) { - return true; - } - - Archive[] archives = ((PkgItem) parentElement).getArchives(); - return archives.length > 0; - } - } else if (parentElement instanceof Package) { - if (mDisplayArchives) { - return ((Package) parentElement).getArchives().length > 0; - } - } - - return false; - } - - @Override - public Object[] getElements(Object inputElement) { - return getChildren(inputElement); - } - - @Override - public void dispose() { - // unused - - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - // unused - } - - - private Object[] getSourceChildren(PkgCategorySource parentElement) { - List<?> children = parentElement.getItems(); - - SdkSource source = parentElement.getSource(); - IDescription error = null; - IDescription empty = null; - - String errStr = source.getFetchError(); - if (errStr != null) { - error = new RepoSourceError(source); - } - if (!source.isEnabled() || children.isEmpty()) { - empty = new RepoSourceNotification(source); - } - - if (error != null || empty != null) { - ArrayList<Object> children2 = new ArrayList<Object>(); - if (error != null) { - children2.add(error); - } - if (empty != null) { - children2.add(empty); - } - children2.addAll(children); - children = children2; - } - - return children.toArray(); - } - - - /** - * A dummy entry returned for sources which had load errors. - * It displays a summary of the error as its short description or - * it displays the source's long description. - */ - public static class RepoSourceError implements IDescription { - - private final SdkSource mSource; - - public RepoSourceError(SdkSource source) { - mSource = source; - } - - @Override - public String getLongDescription() { - return mSource.getLongDescription(); - } - - @Override - public String getShortDescription() { - return mSource.getFetchError(); - } - } - - /** - * A dummy entry returned for sources with no packages. - * We need that to force the SWT tree to display an open/close triangle - * even for empty sources. - */ - public static class RepoSourceNotification implements IDescription { - - private final SdkSource mSource; - - public RepoSourceNotification(SdkSource source) { - mSource = source; - } - - @Override - public String getLongDescription() { - if (mSource.isEnabled()) { - return mSource.getLongDescription(); - } else { - return "Loading from this site has been disabled. " + - "To enable it, use Tools > Manage Add-ons Sites."; - } - } - - @Override - public String getShortDescription() { - if (mSource.isEnabled()) { - return "No packages found."; - } else { - return "This site is disabled. "; - } - } - } - -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PkgItem.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PkgItem.java deleted file mode 100755 index cac43e4..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/PkgItem.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (C) 2011 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.repository.core; - -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.packages.FullRevision; -import com.android.sdklib.internal.repository.packages.IAndroidVersionProvider; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.packages.Package.UpdateInfo; -import com.android.sdklib.internal.repository.sources.SdkSource; - -/** - * A {@link PkgItem} represents one main {@link Package} combined with its state - * and an optional update package. - * <p/> - * The main package is final and cannot change since it's what "defines" this PkgItem. - * The state or update package can change later. - */ -public class PkgItem implements Comparable<PkgItem> { - private final PkgState mState; - private final Package mMainPkg; - private Package mUpdatePkg; - private boolean mChecked; - - /** - * The state of the a given {@link PkgItem}, that is the relationship between - * a given remote package and the local repository. - */ - public enum PkgState { - // Implementation detail: if this is changed then PackageDiffLogic#STATES - // and PackageDiffLogic#processSource() need to be changed accordingly. - - /** - * Package is locally installed and may or may not have an update. - */ - INSTALLED, - - /** - * There's a new package available on the remote site that isn't installed locally. - */ - NEW - } - - /** - * Create a new {@link PkgItem} for this main package. - * The main package is final and cannot change since it's what "defines" this PkgItem. - * The state or update package can change later. - */ - public PkgItem(Package mainPkg, PkgState state) { - mMainPkg = mainPkg; - mState = state; - assert mMainPkg != null; - } - - public boolean isObsolete() { - return mMainPkg.isObsolete(); - } - - public boolean isChecked() { - return mChecked; - } - - public void setChecked(boolean checked) { - mChecked = checked; - } - - public Package getUpdatePkg() { - return mUpdatePkg; - } - - public boolean hasUpdatePkg() { - return mUpdatePkg != null; - } - - public String getName() { - return mMainPkg.getListDescription(); - } - - public FullRevision getRevision() { - return mMainPkg.getRevision(); - } - - public String getDescription() { - return mMainPkg.getDescription(); - } - - public Package getMainPackage() { - return mMainPkg; - } - - public PkgState getState() { - return mState; - } - - public SdkSource getSource() { - return mMainPkg.getParentSource(); - } - - public int getApi() { - return mMainPkg instanceof IAndroidVersionProvider ? - ((IAndroidVersionProvider) mMainPkg).getAndroidVersion().getApiLevel() : - -1; - } - - public Archive[] getArchives() { - return mMainPkg.getArchives(); - } - - @Override - public int compareTo(PkgItem pkg) { - return getMainPackage().compareTo(pkg.getMainPackage()); - } - - /** - * Returns true if this package or its updating packages contains - * the exact given archive. - * Important: This compares object references, not object equality. - */ - public boolean hasArchive(Archive archive) { - if (mMainPkg.hasArchive(archive)) { - return true; - } - if (mUpdatePkg != null && mUpdatePkg.hasArchive(archive)) { - return true; - } - return false; - } - - /** - * Returns true if the main package has at least one archive - * compatible with the current platform. - */ - public boolean hasCompatibleArchive() { - return mMainPkg.hasCompatibleArchive(); - } - - /** - * Checks whether the main packages are of the same type and are - * not an update of each other and have the same revision number. - */ - public boolean isSameMainPackageAs(Package pkg) { - if (mMainPkg.canBeUpdatedBy(pkg) == UpdateInfo.NOT_UPDATE) { - // package revision numbers must match - return mMainPkg.getRevision().equals(pkg.getRevision()); - } - return false; - } - - /** - * Checks whether the update packages are of the same type and are - * not an update of each other and have the same revision numbers. - */ - public boolean isSameUpdatePackageAs(Package pkg) { - if (mUpdatePkg != null && mUpdatePkg.canBeUpdatedBy(pkg) == UpdateInfo.NOT_UPDATE) { - // package revision numbers must match - return mUpdatePkg.getRevision().equals(pkg.getRevision()); - } - return false; - } - - /** - * Checks whether too {@link PkgItem} are the same. - * This checks both items have the same state, both main package are similar - * and that they have the same updating packages. - */ - public boolean isSameItemAs(PkgItem item) { - if (this == item) { - return true; - } - boolean same = this.mState == item.mState; - if (same) { - same = isSameMainPackageAs(item.getMainPackage()); - } - - if (same) { - // check updating packages are the same - Package p1 = this.mUpdatePkg; - Package p2 = item.getUpdatePkg(); - same = (p1 == p2) || (p1 == null && p2 == null) || (p1 != null && p2 != null); - - if (same && p1 != null) { - same = p1.canBeUpdatedBy(p2) == UpdateInfo.NOT_UPDATE; - } - } - - return same; - } - - /** - * Equality is defined as {@link #isSameItemAs(PkgItem)}: state, main package - * and update package must be the similar. - */ - @Override - public boolean equals(Object obj) { - return (obj instanceof PkgItem) && this.isSameItemAs((PkgItem) obj); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((mState == null) ? 0 : mState.hashCode()); - result = prime * result + ((mMainPkg == null) ? 0 : mMainPkg.hashCode()); - result = prime * result + ((mUpdatePkg == null) ? 0 : mUpdatePkg.hashCode()); - return result; - } - - /** - * Check whether the 'pkg' argument is an update for this package. - * If it is, record it as an updating package. - * If there's already an updating package, only keep the most recent update. - * Returns true if it is update (even if there was already an update and this - * ended up not being the most recent), false if incompatible or not an update. - * - * This should only be used for installed packages. - */ - public boolean mergeUpdate(Package pkg) { - if (mUpdatePkg == pkg) { - return true; - } - if (mMainPkg.canBeUpdatedBy(pkg) == UpdateInfo.UPDATE) { - if (mUpdatePkg == null) { - mUpdatePkg = pkg; - } else if (mUpdatePkg.canBeUpdatedBy(pkg) == UpdateInfo.UPDATE) { - // If we have more than one, keep only the most recent update - mUpdatePkg = pkg; - } - return true; - } - - return false; - } - - public void removeUpdate() { - mUpdatePkg = null; - } - - /** Returns a string representation of this item, useful when debugging. */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append('<'); - - if (mChecked) { - sb.append(" * "); //$NON-NLS-1$ - } - - sb.append(mState.toString()); - - if (mMainPkg != null) { - sb.append(", pkg:"); //$NON-NLS-1$ - sb.append(mMainPkg.toString()); - } - - if (mUpdatePkg != null) { - sb.append(", updated by:"); //$NON-NLS-1$ - sb.append(mUpdatePkg.toString()); - } - - sb.append('>'); - return sb.toString(); - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/SdkLogAdapter.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/SdkLogAdapter.java deleted file mode 100755 index 5f24030..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/core/SdkLogAdapter.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2011 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.repository.core; - -import com.android.sdkuilib.internal.tasks.ILogUiProvider; -import com.android.utils.ILogger; - - -/** - * Adapter that transform log from an {@link ILogUiProvider} to an {@link ILogger}. - */ -public final class SdkLogAdapter implements ILogUiProvider { - - private ILogger mSdkLog; - private String mLastLogMsg; - - /** - * Creates a new adapter to output log on the given {@code sdkLog}. - * - * @param sdkLog The logger to output to. Must not be null. - */ - public SdkLogAdapter(ILogger sdkLog) { - mSdkLog = sdkLog; - } - - /** - * Sets the description in the current task dialog. - * This method can be invoked from a non-UI thread. - */ - @Override - public void setDescription(final String description) { - if (acceptLog(description)) { - mSdkLog.info("%1$s", description); //$NON-NLS-1$ - } - } - - /** - * Logs a "normal" information line. - * This method can be invoked from a non-UI thread. - */ - @Override - public void log(String log) { - if (acceptLog(log)) { - mSdkLog.info(" %1$s", log); //$NON-NLS-1$ - } - } - - /** - * Logs an "error" information line. - * This method can be invoked from a non-UI thread. - */ - @Override - public void logError(String log) { - if (acceptLog(log)) { - mSdkLog.error(null, " %1$s", log); //$NON-NLS-1$ - } - } - - /** - * Logs a "verbose" information line, that is extra details which are typically - * not that useful for the end-user and might be hidden until explicitly shown. - * This method can be invoked from a non-UI thread. - */ - @Override - public void logVerbose(String log) { - if (acceptLog(log)) { - mSdkLog.verbose(" %1$s", log); //$NON-NLS-1$ - } - } - - // ---- - - /** - * Filter messages displayed in the log: <br/> - * - Messages with a % are typical part of a progress update and shouldn't be in the log. <br/> - * - Messages that are the same as the same output message should be output a second time. - * - * @param msg The potential log line to print. - * @return True if the log line should be printed, false otherwise. - */ - private boolean acceptLog(String msg) { - if (msg == null) { - return false; - } - - msg = msg.trim(); - if (msg.indexOf('%') != -1) { - return false; - } - - if (msg.equals(mLastLogMsg)) { - return false; - } - - mLastLogMsg = msg; - return true; - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/ImageFactory.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/ImageFactory.java deleted file mode 100755 index ab84cc2..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/ImageFactory.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * 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.repository.icons; - -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.internal.repository.sources.SdkSourceCategory; -import com.android.sdkuilib.internal.repository.core.PkgContentProvider; - -import org.eclipse.swt.SWTException; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; - -import java.io.InputStream; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; - - -/** - * An utility class to serve {@link Image} correspond to the various icons - * present in this package and dispose of them correctly at the end. - */ -public class ImageFactory { - - private final Display mDisplay; - private final Map<String, Image> mImages = new HashMap<String, Image>(); - - public ImageFactory(Display display) { - mDisplay = display; - } - - /** - * Loads an image given its filename (with its extension). - * Might return null if the image cannot be loaded. - * The image is cached. Successive calls will return the <em>same</em> object. - * - * @param imageName The filename (with extension) of the image to load. - * @return A new or existing {@link Image}. The caller must NOT dispose the image (the - * image will disposed by {@link #dispose()}). The returned image can be null if the - * expected file is missing. - */ - public Image getImageByName(String imageName) { - - Image image = mImages.get(imageName); - if (image != null) { - return image; - } - - InputStream stream = getClass().getResourceAsStream(imageName); - if (stream != null) { - try { - image = new Image(mDisplay, stream); - } catch (SWTException e) { - // ignore - } catch (IllegalArgumentException e) { - // ignore - } - } - - // Store the image in the hash, even if this failed. If it fails now, it will fail later. - mImages.put(imageName, image); - - return image; - } - - /** - * Loads and returns the appropriate image for a given package, archive or source object. - * The image is cached. Successive calls will return the <em>same</em> object. - * - * @param object A {@link SdkSource} or {@link Package} or {@link Archive}. - * @return A new or existing {@link Image}. The caller must NOT dispose the image (the - * image will disposed by {@link #dispose()}). The returned image can be null if the - * object is of an unknown type. - */ - public Image getImageForObject(Object object) { - - if (object == null) { - return null; - } - - if (object instanceof Image) { - return (Image) object; - } - - String clz = object.getClass().getSimpleName(); - if (clz.endsWith(Package.class.getSimpleName())) { - String name = clz.replaceFirst(Package.class.getSimpleName(), "") //$NON-NLS-1$ - .replace("SystemImage", "sysimg") //$NON-NLS-1$ //$NON-NLS-2$ - .toLowerCase(Locale.US); - name += "_pkg_16.png"; //$NON-NLS-1$ - return getImageByName(name); - } - - if (object instanceof SdkSourceCategory) { - return getImageByName("source_cat_icon_16.png"); //$NON-NLS-1$ - - } else if (object instanceof SdkSource) { - return getImageByName("source_icon_16.png"); //$NON-NLS-1$ - - } else if (object instanceof PkgContentProvider.RepoSourceError) { - return getImageByName("error_icon_16.png"); //$NON-NLS-1$ - - } else if (object instanceof PkgContentProvider.RepoSourceNotification) { - return getImageByName("nopkg_icon_16.png"); //$NON-NLS-1$ - } - - if (object instanceof Archive) { - if (((Archive) object).isCompatible()) { - return getImageByName("archive_icon16.png"); //$NON-NLS-1$ - } else { - return getImageByName("incompat_icon16.png"); //$NON-NLS-1$ - } - } - - if (object instanceof String) { - return getImageByName((String) object); - } - - - if (object != null) { - // For debugging - // System.out.println("No image for object " + object.getClass().getSimpleName()); - } - - return null; - } - - /** - * Dispose all the images created by this factory so far. - */ - public void dispose() { - Iterator<Image> it = mImages.values().iterator(); - while(it.hasNext()) { - Image img = it.next(); - if (img != null && img.isDisposed() == false) { - img.dispose(); - } - it.remove(); - } - } - -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/accept_icon16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/accept_icon16.png Binary files differdeleted file mode 100755 index a9483fb..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/accept_icon16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/addon_pkg_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/addon_pkg_16.png Binary files differdeleted file mode 100755 index ca6a231..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/addon_pkg_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/android_icon_128.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/android_icon_128.png Binary files differdeleted file mode 100644 index 830c04b..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/android_icon_128.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/android_icon_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/android_icon_16.png Binary files differdeleted file mode 100644 index 08ffda8..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/android_icon_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/archive_icon16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/archive_icon16.png Binary files differdeleted file mode 100755 index be5edd7..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/archive_icon16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/broken_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/broken_16.png Binary files differdeleted file mode 100755 index 945d871..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/broken_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/broken_pkg_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/broken_pkg_16.png Binary files differdeleted file mode 100755 index 6daa67b..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/broken_pkg_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/devman_generic_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/devman_generic_16.png Binary files differdeleted file mode 100755 index 6f59cd4..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/devman_generic_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/devman_manufacturer_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/devman_manufacturer_16.png Binary files differdeleted file mode 100755 index 422276d..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/devman_manufacturer_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/devman_user_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/devman_user_16.png Binary files differdeleted file mode 100755 index f8a173c..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/devman_user_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/doc_pkg_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/doc_pkg_16.png Binary files differdeleted file mode 100755 index 186b3b1..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/doc_pkg_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/error_icon_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/error_icon_16.png Binary files differdeleted file mode 100755 index ccb4d0a..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/error_icon_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/extra_pkg_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/extra_pkg_16.png Binary files differdeleted file mode 100755 index a6529f0..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/extra_pkg_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/incompat_icon16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/incompat_icon16.png Binary files differdeleted file mode 100755 index 2a307e9..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/incompat_icon16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/log_off_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/log_off_16.png Binary files differdeleted file mode 100755 index c9d7cb7..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/log_off_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/log_on_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/log_on_16.png Binary files differdeleted file mode 100755 index 58f4195..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/log_on_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/nopkg_icon_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/nopkg_icon_16.png Binary files differdeleted file mode 100755 index 147837f..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/nopkg_icon_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkg_incompat_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkg_incompat_16.png Binary files differdeleted file mode 100755 index 7ef989e..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkg_incompat_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkg_installed_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkg_installed_16.png Binary files differdeleted file mode 100755 index 78b7e5a..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkg_installed_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkg_new_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkg_new_16.png Binary files differdeleted file mode 100755 index 0976ad4..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkg_new_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkg_update_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkg_update_16.png Binary files differdeleted file mode 100755 index e766251..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkg_update_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkgcat_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkgcat_16.png Binary files differdeleted file mode 100755 index cd9b807..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkgcat_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkgcat_other_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkgcat_other_16.png Binary files differdeleted file mode 100755 index 395a240..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/pkgcat_other_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/platform_pkg_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/platform_pkg_16.png Binary files differdeleted file mode 100755 index 0b0744b..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/platform_pkg_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/platformtool_pkg_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/platformtool_pkg_16.png Binary files differdeleted file mode 100755 index 8bb0bb3..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/platformtool_pkg_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/reject_icon16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/reject_icon16.png Binary files differdeleted file mode 100755 index b87bbc9..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/reject_icon16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/sample_pkg_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/sample_pkg_16.png Binary files differdeleted file mode 100755 index 8d31865..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/sample_pkg_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/sdkman_logo_128.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/sdkman_logo_128.png Binary files differdeleted file mode 100644 index 0f1670d..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/sdkman_logo_128.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/source_cat_icon_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/source_cat_icon_16.png Binary files differdeleted file mode 100755 index 13c8bb3..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/source_cat_icon_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/source_icon_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/source_icon_16.png Binary files differdeleted file mode 100755 index 5eb1ead..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/source_icon_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/source_pkg_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/source_pkg_16.png Binary files differdeleted file mode 100755 index 9992cda..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/source_pkg_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/status_ok_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/status_ok_16.png Binary files differdeleted file mode 100755 index eeb0a6f..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/status_ok_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/stop_disabled_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/stop_disabled_16.png Binary files differdeleted file mode 100755 index ae6da31..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/stop_disabled_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/stop_enabled_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/stop_enabled_16.png Binary files differdeleted file mode 100755 index 7ce1864..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/stop_enabled_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/sysimg_pkg_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/sysimg_pkg_16.png Binary files differdeleted file mode 100755 index 7795c2c..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/sysimg_pkg_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/tool_pkg_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/tool_pkg_16.png Binary files differdeleted file mode 100755 index 8ca7710..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/tool_pkg_16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/unknown_icon16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/unknown_icon16.png Binary files differdeleted file mode 100755 index 1b97eb7..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/unknown_icon16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/warning_icon16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/warning_icon16.png Binary files differdeleted file mode 100755 index ca3b6ed..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/icons/warning_icon16.png +++ /dev/null diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/AddonSitesDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/AddonSitesDialog.java deleted file mode 100755 index 77f82b1..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/AddonSitesDialog.java +++ /dev/null @@ -1,574 +0,0 @@ -/* - * Copyright (C) 2011 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.repository.ui; - -import com.android.sdklib.internal.repository.sources.SdkAddonSource; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.internal.repository.sources.SdkSourceCategory; -import com.android.sdklib.internal.repository.sources.SdkSourceProperties; -import com.android.sdklib.internal.repository.sources.SdkSources; -import com.android.sdklib.internal.repository.sources.SdkSysImgSource; -import com.android.sdklib.repository.SdkSysImgConstants; -import com.android.sdkuilib.internal.repository.UpdaterBaseDialog; -import com.android.sdkuilib.internal.repository.UpdaterData; -import com.android.sdkuilib.ui.GridDataBuilder; -import com.android.sdkuilib.ui.GridLayoutBuilder; - -import org.eclipse.jface.dialogs.IInputValidator; -import org.eclipse.jface.dialogs.InputDialog; -import org.eclipse.jface.viewers.CheckStateChangedEvent; -import org.eclipse.jface.viewers.CheckboxTableViewer; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.ICheckStateListener; -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.LabelProvider; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.TableViewerColumn; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ControlAdapter; -import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.events.MouseAdapter; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.MessageBox; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.TabFolder; -import org.eclipse.swt.widgets.TabItem; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; - -import java.util.ArrayList; -import java.util.Arrays; - -/** - * Dialog that displays 2 tabs: <br/> - * - one tab with the list of extra add-ons sites defined by the user. <br/> - * - one tab with the list of 3rd-party add-ons currently available, which the user can - * deactivate to prevent from loading them. - */ -public class AddonSitesDialog extends UpdaterBaseDialog { - - private final SdkSources mSources; - private Table mUserTable; - private TableViewer mUserTableViewer; - private CheckboxTableViewer mSitesTableViewer; - private Button mUserButtonNew; - private Button mUserButtonDelete; - private Button mUserButtonEdit; - private Runnable mSourcesChangeListener; - - /** - * Create the dialog. - * - * @param parent The parent's shell - * @wbp.parser.entryPoint - */ - public AddonSitesDialog(Shell parent, UpdaterData updaterData) { - super(parent, updaterData, "Add-on Sites"); - mSources = updaterData.getSources(); - assert mSources != null; - } - - /** - * Create contents of the dialog. - * @wbp.parser.entryPoint - */ - @Override - protected void createContents() { - super.createContents(); - Shell shell = getShell(); - shell.setMinimumSize(new Point(300, 300)); - shell.setSize(600, 400); - - TabFolder tabFolder = new TabFolder(shell, SWT.NONE); - GridDataBuilder.create(tabFolder).fill().grab().hSpan(2); - - TabItem sitesTabItem = new TabItem(tabFolder, SWT.NONE); - sitesTabItem.setText("Official Add-on Sites"); - createTabOfficialSites(tabFolder, sitesTabItem); - - TabItem userTabItem = new TabItem(tabFolder, SWT.NONE); - userTabItem.setText("User Defined Sites"); - createTabUserSites(tabFolder, userTabItem); - - // placeholder for aligning close button - Label label = new Label(shell, SWT.NONE); - GridDataBuilder.create(label).hFill().hGrab(); - - createCloseButton(); - } - - void createTabOfficialSites(TabFolder tabFolder, TabItem sitesTabItem) { - Composite root = new Composite(tabFolder, SWT.NONE); - sitesTabItem.setControl(root); - GridLayoutBuilder.create(root).columns(3); - - Label label = new Label(root, SWT.NONE); - GridDataBuilder.create(label).hGrab().vCenter().hSpan(3); - label.setText( - "This lets select which official 3rd-party sites you want to load.\n" + - "\n" + - "These sites are managed by non-Android vendors to provide add-ons and extra packages.\n" + - "They are by default all enabled. When you disable one, the SDK Manager will not check the site for new packages." - ); - - mSitesTableViewer = CheckboxTableViewer.newCheckList(root, SWT.BORDER | SWT.FULL_SELECTION); - mSitesTableViewer.setContentProvider(new SourcesContentProvider()); - - Table sitesTable = mSitesTableViewer.getTable(); - sitesTable.setToolTipText("Enable 3rd-Party Site"); - sitesTable.setLinesVisible(true); - sitesTable.setHeaderVisible(true); - GridDataBuilder.create(sitesTable).fill().grab().hSpan(3); - - TableViewerColumn columnViewer = new TableViewerColumn(mSitesTableViewer, SWT.NONE); - TableColumn column = columnViewer.getColumn(); - column.setResizable(true); - column.setWidth(150); - column.setText("Name"); - columnViewer.setLabelProvider(new ColumnLabelProvider() { - @Override - public String getText(Object element) { - if (element instanceof SdkSource) { - String name = ((SdkSource) element).getUiName(); - if (name != null) { - return name; - } - return ((SdkSource) element).getShortDescription(); - } - return super.getText(element); - } - }); - - columnViewer = new TableViewerColumn(mSitesTableViewer, SWT.NONE); - column = columnViewer.getColumn(); - column.setResizable(true); - column.setWidth(400); - column.setText("URL"); - columnViewer.setLabelProvider(new ColumnLabelProvider() { - @Override - public String getText(Object element) { - if (element instanceof SdkSource) { - return ((SdkSource) element).getUrl(); - } - return super.getText(element); - } - }); - - mSitesTableViewer.addCheckStateListener(new ICheckStateListener() { - @Override - public void checkStateChanged(CheckStateChangedEvent event) { - on_SitesTableViewer_checkStateChanged(event); - } - }); - - // "enable all" and "disable all" buttons under the table - Button selectAll = new Button(root, SWT.NONE); - selectAll.setText("Enable All"); - GridDataBuilder.create(selectAll).hLeft(); - selectAll.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - on_SitesTableViewer_selectAll(); - } - }); - - // placeholder between both buttons - label = new Label(root, SWT.NONE); - GridDataBuilder.create(label).hFill().hGrab(); - - Button deselectAll = new Button(root, SWT.NONE); - deselectAll.setText("Disable All"); - GridDataBuilder.create(deselectAll).hRight(); - deselectAll.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - on_SitesTableViewer_deselectAll(); - } - }); - } - - void createTabUserSites(TabFolder tabFolder, TabItem userTabItem) { - Composite root = new Composite(tabFolder, SWT.NONE); - userTabItem.setControl(root); - GridLayoutBuilder.create(root).columns(2); - - Label label = new Label(root, SWT.NONE); - GridDataBuilder.create(label).hLeft().vCenter().hSpan(2); - label.setText( - "This lets you manage a list of user-contributed external add-on sites URLs.\n" + - "\n" + - "Add-on sites can provide new add-ons and extra packages.\n" + - "They cannot provide standard Android platforms, system images or docs.\n" + - "Adding a URL here will not allow you to clone an official Android repository." - ); - - mUserTableViewer = new TableViewer(root, SWT.BORDER | SWT.FULL_SELECTION); - mUserTableViewer.setContentProvider(new SourcesContentProvider()); - - mUserTableViewer.addPostSelectionChangedListener(new ISelectionChangedListener() { - @Override - public void selectionChanged(SelectionChangedEvent event) { - on_UserTableViewer_selectionChanged(event); - } - }); - mUserTable = mUserTableViewer.getTable(); - mUserTable.setLinesVisible(true); - mUserTable.addMouseListener(new MouseAdapter() { - @Override - public void mouseUp(MouseEvent event) { - on_UserTable_mouseUp(event); - } - }); - GridDataBuilder.create(mUserTable).fill().grab().vSpan(5); - - TableViewerColumn tableViewerColumn = new TableViewerColumn(mUserTableViewer, SWT.NONE); - TableColumn userColumnUrl = tableViewerColumn.getColumn(); - userColumnUrl.setWidth(100); - - // Implementation detail: set the label provider on the table viewer *after* associating - // a column. This will set the label provider on the column for us. - mUserTableViewer.setLabelProvider(new LabelProvider()); - - - mUserButtonNew = new Button(root, SWT.NONE); - mUserButtonNew.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - userNewOrEdit(false /*isEdit*/); - } - }); - GridDataBuilder.create(mUserButtonNew).hFill().vCenter(); - mUserButtonNew.setText("New..."); - - mUserButtonEdit = new Button(root, SWT.NONE); - mUserButtonEdit.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - userNewOrEdit(true /*isEdit*/); - } - }); - GridDataBuilder.create(mUserButtonEdit).hFill().vCenter(); - mUserButtonEdit.setText("Edit..."); - - mUserButtonDelete = new Button(root, SWT.NONE); - mUserButtonDelete.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - on_UserButtonDelete_widgetSelected(e); - } - }); - GridDataBuilder.create(mUserButtonDelete).hFill().vCenter(); - mUserButtonDelete.setText("Delete..."); - - adjustColumnsWidth(mUserTable, userColumnUrl); - } - - @Override - protected void close() { - if (mSources != null && mSourcesChangeListener != null) { - mSources.removeChangeListener(mSourcesChangeListener); - } - SdkSourceProperties p = new SdkSourceProperties(); - p.save(); - super.close(); - } - - /** - * Adds a listener to adjust the column width when the parent is resized. - */ - private void adjustColumnsWidth(final Table table, final TableColumn column0) { - // Add a listener to resize the column to the full width of the table - table.addControlListener(new ControlAdapter() { - @Override - public void controlResized(ControlEvent e) { - Rectangle r = table.getClientArea(); - column0.setWidth(r.width * 100 / 100); // 100% - } - }); - } - - private void userNewOrEdit(final boolean isEdit) { - final SdkSource[] knownSources = mSources.getAllSources(); - String title = isEdit ? "Edit Add-on Site URL" : "Add Add-on Site URL"; - String msg = "Please enter the URL of the addon.xml:"; - IStructuredSelection sel = (IStructuredSelection) mUserTableViewer.getSelection(); - final String initialValue = !isEdit || sel.isEmpty() ? null : - sel.getFirstElement().toString(); - - if (isEdit && initialValue == null) { - // Edit with no actual value is not supposed to happen. Ignore this case. - return; - } - - InputDialog dlg = new InputDialog( - getShell(), - title, - msg, - initialValue, - new IInputValidator() { - @Override - public String isValid(String newText) { - - newText = newText == null ? null : newText.trim(); - - if (newText == null || newText.length() == 0) { - return "Error: URL field is empty. Please enter a URL."; - } - - // A URL should have one of the following prefixes - if (!newText.startsWith("file://") && //$NON-NLS-1$ - !newText.startsWith("ftp://") && //$NON-NLS-1$ - !newText.startsWith("http://") && //$NON-NLS-1$ - !newText.startsWith("https://")) { //$NON-NLS-1$ - return "Error: The URL must start by one of file://, ftp://, http:// or https://"; - } - - if (isEdit && newText.equals(initialValue)) { - // Edited value hasn't changed. This isn't an error. - return null; - } - - // Reject URLs that are already in the source list. - // URLs are generally case-insensitive (except for file:// where it all depends - // on the current OS so we'll ignore this case.) - for (SdkSource s : knownSources) { - if (newText.equalsIgnoreCase(s.getUrl())) { - return "Error: This site is already listed."; - } - } - - return null; - } - }); - - if (dlg.open() == Window.OK) { - String url = dlg.getValue().trim(); - - if (!url.equals(initialValue)) { - if (isEdit && initialValue != null) { - // Remove the old value before we add the new one, which is we just - // asserted will be different. - for (SdkSource source : mSources.getSources(SdkSourceCategory.USER_ADDONS)) { - if (initialValue.equals(source.getUrl())) { - mSources.remove(source); - break; - } - } - - } - - // create the source, store it and update the list - SdkSource newSource; - // use url suffix to decide whether this is a SysImg or Addon; - // see SdkSources.loadUserAddons() for another check like this - if (url.endsWith(SdkSysImgConstants.URL_DEFAULT_FILENAME)) { - newSource = new SdkSysImgSource(url, null/*uiName*/); - } else { - newSource = new SdkAddonSource(url, null/*uiName*/); - } - mSources.add(SdkSourceCategory.USER_ADDONS, newSource); - setReturnValue(true); - // notify sources change listeners. This will invoke our own loadUserUrlsList(). - mSources.notifyChangeListeners(); - - // select the new source - IStructuredSelection newSel = new StructuredSelection(newSource); - mUserTableViewer.setSelection(newSel, true /*reveal*/); - } - } - } - - private void on_UserButtonDelete_widgetSelected(SelectionEvent e) { - IStructuredSelection sel = (IStructuredSelection) mUserTableViewer.getSelection(); - String selectedUrl = sel.isEmpty() ? null : sel.getFirstElement().toString(); - - if (selectedUrl == null) { - return; - } - - MessageBox mb = new MessageBox(getShell(), - SWT.YES | SWT.NO | SWT.ICON_QUESTION | SWT.APPLICATION_MODAL); - mb.setText("Delete add-on site"); - mb.setMessage(String.format("Do you want to delete the URL %1$s?", selectedUrl)); - if (mb.open() == SWT.YES) { - for (SdkSource source : mSources.getSources(SdkSourceCategory.USER_ADDONS)) { - if (selectedUrl.equals(source.getUrl())) { - mSources.remove(source); - setReturnValue(true); - mSources.notifyChangeListeners(); - break; - } - } - } - } - - private void on_UserTable_mouseUp(MouseEvent event) { - Point p = new Point(event.x, event.y); - if (mUserTable.getItem(p) == null) { - mUserTable.deselectAll(); - on_UserTableViewer_selectionChanged(null /*event*/); - } - } - - private void on_UserTableViewer_selectionChanged(SelectionChangedEvent event) { - ISelection sel = mUserTableViewer.getSelection(); - mUserButtonDelete.setEnabled(!sel.isEmpty()); - mUserButtonEdit.setEnabled(!sel.isEmpty()); - } - - private void on_SitesTableViewer_checkStateChanged(CheckStateChangedEvent event) { - Object element = event.getElement(); - if (element instanceof SdkSource) { - SdkSource source = (SdkSource) element; - boolean isChecked = event.getChecked(); - if (source.isEnabled() != isChecked) { - setReturnValue(true); - source.setEnabled(isChecked); - mSources.notifyChangeListeners(); - } - } - } - - private void on_SitesTableViewer_selectAll() { - for (Object item : (Object[]) mSitesTableViewer.getInput()) { - if (!mSitesTableViewer.getChecked(item)) { - mSitesTableViewer.setChecked(item, true); - on_SitesTableViewer_checkStateChanged( - new CheckStateChangedEvent(mSitesTableViewer, item, true)); - } - } - } - - private void on_SitesTableViewer_deselectAll() { - for (Object item : (Object[]) mSitesTableViewer.getInput()) { - if (mSitesTableViewer.getChecked(item)) { - mSitesTableViewer.setChecked(item, false); - on_SitesTableViewer_checkStateChanged( - new CheckStateChangedEvent(mSitesTableViewer, item, false)); - } - } - } - - - @Override - protected void postCreate() { - // A runnable to initially load and then update the user urls & sites lists. - final Runnable updateInUiThread = new Runnable() { - @Override - public void run() { - loadUserUrlsList(); - loadSiteUrlsList(); - } - }; - - // A listener that runs when the sources have changed. - // This is most likely called on a worker thread. - mSourcesChangeListener = new Runnable() { - @Override - public void run() { - Shell shell = getShell(); - if (shell != null) { - Display display = shell.getDisplay(); - if (display != null) { - display.syncExec(updateInUiThread); - } - } - } - }; - - mSources.addChangeListener(mSourcesChangeListener); - - // initialize the list - updateInUiThread.run(); - } - - private void loadUserUrlsList() { - SdkSource[] knownSources = mSources.getSources(SdkSourceCategory.USER_ADDONS); - Arrays.sort(knownSources); - - ISelection oldSelection = mUserTableViewer.getSelection(); - - mUserTableViewer.setInput(knownSources); - mUserTableViewer.refresh(); - // initialize buttons' state that depend on the list - on_UserTableViewer_selectionChanged(null /*event*/); - - if (oldSelection != null && !oldSelection.isEmpty()) { - mUserTableViewer.setSelection(oldSelection, true /*reveal*/); - } - } - - private void loadSiteUrlsList() { - SdkSource[] knownSources = mSources.getSources(SdkSourceCategory.ADDONS_3RD_PARTY); - Arrays.sort(knownSources); - - ISelection oldSelection = mSitesTableViewer.getSelection(); - - mSitesTableViewer.setInput(knownSources); - mSitesTableViewer.refresh(); - - if (oldSelection != null && !oldSelection.isEmpty()) { - mSitesTableViewer.setSelection(oldSelection, true /*reveal*/); - } - - // Check the sources which are currently enabled. - ArrayList<SdkSource> disabled = new ArrayList<SdkSource>(knownSources.length); - for (SdkSource source : knownSources) { - if (source.isEnabled()) { - disabled.add(source); - } - } - mSitesTableViewer.setCheckedElements(disabled.toArray()); - } - - - private static class SourcesContentProvider implements IStructuredContentProvider { - @Override - public void dispose() { - // pass - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - // pass - } - - @Override - public Object[] getElements(Object inputElement) { - if (inputElement instanceof SdkSource[]) { - return (Object[]) inputElement; - } else { - return new Object[0]; - } - } - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/AdtUpdateDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/AdtUpdateDialog.java deleted file mode 100755 index e90c3d9..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/AdtUpdateDialog.java +++ /dev/null @@ -1,494 +0,0 @@ -/* - * Copyright (C) 2011 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.repository.ui; - - -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.internal.repository.packages.ExtraPackage; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.packages.PlatformPackage; -import com.android.sdklib.internal.repository.packages.PlatformToolPackage; -import com.android.sdklib.internal.repository.packages.ToolPackage; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdkuilib.internal.repository.SettingsController; -import com.android.sdkuilib.internal.repository.UpdaterData; -import com.android.sdkuilib.internal.repository.core.PackageLoader; -import com.android.sdkuilib.internal.repository.core.SdkLogAdapter; -import com.android.sdkuilib.internal.repository.core.PackageLoader.IAutoInstallTask; -import com.android.sdkuilib.internal.tasks.ProgressView; -import com.android.sdkuilib.internal.tasks.ProgressViewFactory; -import com.android.sdkuilib.ui.GridDataBuilder; -import com.android.sdkuilib.ui.GridLayoutBuilder; -import com.android.sdkuilib.ui.SwtBaseDialog; -import com.android.utils.ILogger; -import com.android.utils.Pair; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.ProgressBar; -import org.eclipse.swt.widgets.Shell; - -import java.io.File; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -/** - * This is a private implementation of UpdateWindow for ADT, - * designed to install a very specific package. - * <p/> - * Example of usage: - * <pre> - * AdtUpdateDialog dialog = new AdtUpdateDialog( - * AdtPlugin.getDisplay().getActiveShell(), - * new AdtConsoleSdkLog(), - * sdk.getSdkLocation()); - * - * Pair<Boolean, File> result = dialog.installExtraPackage( - * "android", "compatibility"); //$NON-NLS-1$ //$NON-NLS-2$ - * or - * Pair<Boolean, File> result = dialog.installPlatformPackage(11); - * </pre> - */ -public class AdtUpdateDialog extends SwtBaseDialog { - - public static final int USE_MAX_REMOTE_API_LEVEL = 0; - - private static final String APP_NAME = "Android SDK Manager"; - private final UpdaterData mUpdaterData; - - private Boolean mResultCode = Boolean.FALSE; - private Map<Package, File> mResultPaths = null; - private SettingsController mSettingsController; - private PackageFilter mPackageFilter; - private PackageLoader mPackageLoader; - - private ProgressBar mProgressBar; - private Label mStatusText; - - /** - * Creates a new {@link AdtUpdateDialog}. - * Callers will want to call {@link #installExtraPackage} or - * {@link #installPlatformPackage} after this. - * - * @param parentShell The existing parent shell. Must not be null. - * @param sdkLog An SDK logger. Must not be null. - * @param osSdkRoot The current SDK root OS path. Must not be null or empty. - */ - public AdtUpdateDialog( - Shell parentShell, - ILogger sdkLog, - String osSdkRoot) { - super(parentShell, SWT.NONE, APP_NAME); - mUpdaterData = new UpdaterData(osSdkRoot, sdkLog); - } - - /** - * Displays the update dialog and triggers installation of the requested {@code extra} - * package with the specified vendor and path attributes. - * <p/> - * Callers must not try to reuse this dialog after this call. - * - * @param vendor The extra package vendor string to match. - * @param path The extra package path string to match. - * @return A boolean indicating whether the installation was successful (meaning the package - * was either already present, or got installed or updated properly) and a {@link File} - * with the path to the root folder of the package. The file is null when the boolean - * is false, otherwise it should point to an existing valid folder. - * @wbp.parser.entryPoint - */ - public Pair<Boolean, File> installExtraPackage(String vendor, String path) { - mPackageFilter = createExtraFilter(vendor, path); - open(); - - File installPath = null; - if (mResultPaths != null) { - for (Entry<Package, File> entry : mResultPaths.entrySet()) { - if (entry.getKey() instanceof ExtraPackage) { - installPath = entry.getValue(); - break; - } - } - } - - return Pair.of(mResultCode, installPath); - } - - /** - * Displays the update dialog and triggers installation of platform-tools package. - * <p/> - * Callers must not try to reuse this dialog after this call. - * - * @return A boolean indicating whether the installation was successful (meaning the package - * was either already present, or got installed or updated properly) and a {@link File} - * with the path to the root folder of the package. The file is null when the boolean - * is false, otherwise it should point to an existing valid folder. - * @wbp.parser.entryPoint - */ - public Pair<Boolean, File> installPlatformTools() { - mPackageFilter = createPlatformToolsFilter(); - open(); - - File installPath = null; - if (mResultPaths != null) { - for (Entry<Package, File> entry : mResultPaths.entrySet()) { - if (entry.getKey() instanceof ExtraPackage) { - installPath = entry.getValue(); - break; - } - } - } - - return Pair.of(mResultCode, installPath); - } - - /** - * Displays the update dialog and triggers installation of the requested platform - * package with the specified API level. - * <p/> - * Callers must not try to reuse this dialog after this call. - * - * @param apiLevel The platform API level to match. - * The special value {@link #USE_MAX_REMOTE_API_LEVEL} means to use - * the highest API level available on the remote repository. - * @return A boolean indicating whether the installation was successful (meaning the package - * was either already present, or got installed or updated properly) and a {@link File} - * with the path to the root folder of the package. The file is null when the boolean - * is false, otherwise it should point to an existing valid folder. - */ - public Pair<Boolean, File> installPlatformPackage(int apiLevel) { - mPackageFilter = createPlatformFilter(apiLevel); - open(); - - File installPath = null; - if (mResultPaths != null) { - for (Entry<Package, File> entry : mResultPaths.entrySet()) { - if (entry.getKey() instanceof PlatformPackage) { - installPath = entry.getValue(); - break; - } - } - } - - return Pair.of(mResultCode, installPath); - } - - /** - * Displays the update dialog and triggers installation of a new SDK. This works by - * requesting a remote platform package with the specified API levels as well as - * the first tools or platform-tools packages available. - * <p/> - * Callers must not try to reuse this dialog after this call. - * - * @param apiLevels A set of platform API levels to match. - * The special value {@link #USE_MAX_REMOTE_API_LEVEL} means to use - * the highest API level available in the repository. - * @return A boolean indicating whether the installation was successful (meaning the packages - * were either already present, or got installed or updated properly). - */ - public boolean installNewSdk(Set<Integer> apiLevels) { - mPackageFilter = createNewSdkFilter(apiLevels); - open(); - return mResultCode.booleanValue(); - } - - @Override - protected void createContents() { - Shell shell = getShell(); - shell.setMinimumSize(new Point(450, 100)); - shell.setSize(450, 100); - - mUpdaterData.setWindowShell(shell); - - GridLayoutBuilder.create(shell).columns(1); - - Composite composite1 = new Composite(shell, SWT.NONE); - composite1.setLayout(new GridLayout(1, false)); - GridDataBuilder.create(composite1).fill().grab(); - - mProgressBar = new ProgressBar(composite1, SWT.NONE); - GridDataBuilder.create(mProgressBar).hFill().hGrab(); - - mStatusText = new Label(composite1, SWT.NONE); - mStatusText.setText("Status Placeholder"); //$NON-NLS-1$ placeholder - GridDataBuilder.create(mStatusText).hFill().hGrab(); - } - - @Override - protected void postCreate() { - ProgressViewFactory factory = new ProgressViewFactory(); - factory.setProgressView(new ProgressView( - mStatusText, - mProgressBar, - null /*buttonStop*/, - new SdkLogAdapter(mUpdaterData.getSdkLog()))); - mUpdaterData.setTaskFactory(factory); - - setupSources(); - initializeSettings(); - - if (mUpdaterData.checkIfInitFailed()) { - close(); - return; - } - - mUpdaterData.broadcastOnSdkLoaded(); - - mPackageLoader = new PackageLoader(mUpdaterData); - } - - @Override - protected void eventLoop() { - mPackageLoader.loadPackagesWithInstallTask( - mPackageFilter.installFlags(), - new IAutoInstallTask() { - @Override - public Package[] filterLoadedSource(SdkSource source, Package[] packages) { - for (Package pkg : packages) { - mPackageFilter.visit(pkg); - } - return packages; - } - - @Override - public boolean acceptPackage(Package pkg) { - // Is this the package we want to install? - return mPackageFilter.accept(pkg); - } - - @Override - public void setResult(boolean success, Map<Package, File> installPaths) { - // Capture the result from the installation. - mResultCode = Boolean.valueOf(success); - mResultPaths = installPaths; - } - - @Override - public void taskCompleted() { - // We can close that window now. - close(); - } - }); - - super.eventLoop(); - } - - // -- Start of internal part ---------- - // Hide everything down-below from SWT designer - //$hide>>$ - - // --- Public API ----------- - - - // --- Internals & UI Callbacks ----------- - - /** - * Used to initialize the sources. - */ - private void setupSources() { - mUpdaterData.setupDefaultSources(); - } - - /** - * Initializes settings. - */ - private void initializeSettings() { - mSettingsController = mUpdaterData.getSettingsController(); - mSettingsController.loadSettings(); - mSettingsController.applySettings(); - } - - // ---- - - private static abstract class PackageFilter { - /** Returns the installer flags for the corresponding mode. */ - abstract int installFlags(); - - /** Visit a new package definition, in case we need to adjust the filter dynamically. */ - abstract void visit(Package pkg); - - /** Checks whether this is the package we've been looking for. */ - abstract boolean accept(Package pkg); - } - - public static PackageFilter createExtraFilter( - final String vendor, - final String path) { - return new PackageFilter() { - String mVendor = vendor; - String mPath = path; - - @Override - boolean accept(Package pkg) { - if (pkg instanceof ExtraPackage) { - ExtraPackage ep = (ExtraPackage) pkg; - if (ep.getVendorId().equals(mVendor)) { - // Check actual extra <path> field first - if (ep.getPath().equals(mPath)) { - return true; - } - // If not, check whether this is one of the <old-paths> values. - for (String oldPath : ep.getOldPaths()) { - if (oldPath.equals(mPath)) { - return true; - } - } - } - } - return false; - } - - @Override - void visit(Package pkg) { - // nop - } - - @Override - int installFlags() { - return UpdaterData.TOOLS_MSG_UPDATED_FROM_ADT; - } - }; - } - - private PackageFilter createPlatformToolsFilter() { - return new PackageFilter() { - @Override - boolean accept(Package pkg) { - return pkg instanceof PlatformToolPackage; - } - - @Override - void visit(Package pkg) { - // nop - } - - @Override - int installFlags() { - return UpdaterData.TOOLS_MSG_UPDATED_FROM_ADT; - } - }; - } - - public static PackageFilter createPlatformFilter(final int apiLevel) { - return new PackageFilter() { - int mApiLevel = apiLevel; - boolean mFindMaxApi = apiLevel == USE_MAX_REMOTE_API_LEVEL; - - @Override - boolean accept(Package pkg) { - if (pkg instanceof PlatformPackage) { - PlatformPackage pp = (PlatformPackage) pkg; - AndroidVersion v = pp.getAndroidVersion(); - return !v.isPreview() && v.getApiLevel() == mApiLevel; - } - return false; - } - - @Override - void visit(Package pkg) { - // Try to find the max API in all remote packages - if (mFindMaxApi && - pkg instanceof PlatformPackage && - !pkg.isLocal()) { - PlatformPackage pp = (PlatformPackage) pkg; - AndroidVersion v = pp.getAndroidVersion(); - if (!v.isPreview()) { - int api = v.getApiLevel(); - if (api > mApiLevel) { - mApiLevel = api; - } - } - } - } - - @Override - int installFlags() { - return UpdaterData.TOOLS_MSG_UPDATED_FROM_ADT; - } - }; - } - - public static PackageFilter createNewSdkFilter(final Set<Integer> apiLevels) { - return new PackageFilter() { - int mMaxApiLevel; - boolean mFindMaxApi = apiLevels.contains(USE_MAX_REMOTE_API_LEVEL); - boolean mNeedTools = true; - boolean mNeedPlatformTools = true; - - @Override - boolean accept(Package pkg) { - if (!pkg.isLocal()) { - if (pkg instanceof PlatformPackage) { - PlatformPackage pp = (PlatformPackage) pkg; - AndroidVersion v = pp.getAndroidVersion(); - if (!v.isPreview()) { - int level = v.getApiLevel(); - if ((mFindMaxApi && level == mMaxApiLevel) || - (level > 0 && apiLevels.contains(level))) { - return true; - } - } - } else if (mNeedTools && pkg instanceof ToolPackage) { - // We want a tool package. There should be only one, - // but in case of error just take the first one. - mNeedTools = false; - return true; - } else if (mNeedPlatformTools && pkg instanceof PlatformToolPackage) { - // We want a platform-tool package. There should be only one, - // but in case of error just take the first one. - mNeedPlatformTools = false; - return true; - } - } - return false; - } - - @Override - void visit(Package pkg) { - // Try to find the max API in all remote packages - if (mFindMaxApi && - pkg instanceof PlatformPackage && - !pkg.isLocal()) { - PlatformPackage pp = (PlatformPackage) pkg; - AndroidVersion v = pp.getAndroidVersion(); - if (!v.isPreview()) { - int api = v.getApiLevel(); - if (api > mMaxApiLevel) { - mMaxApiLevel = api; - } - } - } - } - - @Override - int installFlags() { - return UpdaterData.NO_TOOLS_MSG; - } - }; - } - - - - // End of hiding from SWT Designer - //$hide<<$ - - // ----- - -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/AvdManagerPage.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/AvdManagerPage.java deleted file mode 100755 index a092550..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/AvdManagerPage.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * 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.repository.ui; - -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.sdklib.devices.DeviceManager; -import com.android.sdklib.devices.DeviceManager.DevicesChangedListener; -import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdkuilib.internal.repository.UpdaterData; -import com.android.sdkuilib.internal.widgets.AvdSelector; -import com.android.sdkuilib.internal.widgets.AvdSelector.DisplayMode; -import com.android.sdkuilib.repository.ISdkChangeListener; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; - -/** - * An Update page displaying AVD Manager entries. - * This is the sole page displayed by {@link AvdManagerWindowImpl1}. - * - * Note: historically the SDK Manager was a single window with several sub-pages and a tab - * switcher. For simplicity each page was separated in its own window. The AVD Manager is - * thus composed of the {@link AvdManagerWindowImpl1} (the window shell itself) and this - * page displays the actually list of AVDs and various action buttons. - */ -public class AvdManagerPage extends Composite - implements ISdkChangeListener, DevicesChangedListener, DisposeListener { - - private AvdSelector mAvdSelector; - - private final UpdaterData mUpdaterData; - private final DeviceManager mDeviceManager; - /** - * Create the composite. - * @param parent The parent of the composite. - * @param updaterData An instance of {@link UpdaterData}. - */ - public AvdManagerPage(Composite parent, - int swtStyle, - UpdaterData updaterData, - DeviceManager deviceManager) { - super(parent, swtStyle); - - mUpdaterData = updaterData; - mUpdaterData.addListeners(this); - - mDeviceManager = deviceManager; - mDeviceManager.registerListener(this); - - createContents(this); - postCreate(); //$hide$ - } - - private void createContents(Composite parent) { - parent.setLayout(new GridLayout(1, false)); - - Label label = new Label(parent, SWT.NONE); - label.setLayoutData(new GridData()); - - try { - if (mUpdaterData != null && mUpdaterData.getAvdManager() != null) { - label.setText(String.format( - "List of existing Android Virtual Devices located at %s", - mUpdaterData.getAvdManager().getBaseAvdFolder())); - } else { - label.setText("Error: cannot find the AVD folder location.\r\n Please set the 'ANDROID_SDK_HOME' env variable."); - } - } catch (AndroidLocationException e) { - label.setText(e.getMessage()); - } - - mAvdSelector = new AvdSelector(parent, - mUpdaterData.getOsSdkRoot(), - mUpdaterData.getAvdManager(), - DisplayMode.MANAGER, - mUpdaterData.getSdkLog()); - mAvdSelector.setSettingsController(mUpdaterData.getSettingsController()); - } - - @Override - public void widgetDisposed(DisposeEvent e) { - dispose(); - } - - @Override - public void dispose() { - mUpdaterData.removeListener(this); - mDeviceManager.unregisterListener(this); - super.dispose(); - } - - @Override - protected void checkSubclass() { - // Disable the check that prevents subclassing of SWT components - } - - public void selectAvd(AvdInfo avdInfo, boolean reloadAvdList) { - if (reloadAvdList) { - mAvdSelector.refresh(true /*reload*/); - - // Reloading the AVDs created new objects, so the reference to avdInfo - // will never be selected. Instead reselect it based on its unique name. - AvdManager am = mUpdaterData.getAvdManager(); - avdInfo = am.getAvd(avdInfo.getName(), false /*validAvdOnly*/); - } - mAvdSelector.setSelection(avdInfo); - } - - // -- Start of internal part ---------- - // Hide everything down-below from SWT designer - //$hide>>$ - - /** - * Called by the constructor right after {@link #createContents(Composite)}. - */ - private void postCreate() { - // nothing to be done for now. - } - - // --- Implementation of ISdkChangeListener --- - - @Override - public void onSdkLoaded() { - onSdkReload(); - } - - @Override - public void onSdkReload() { - mAvdSelector.refresh(false /*reload*/); - } - - @Override - public void preInstallHook() { - // nothing to be done for now. - } - - @Override - public void postInstallHook() { - // nothing to be done for now. - } - - // --- Implementation of DevicesChangeListener - - @Override - public void onDevicesChanged() { - mAvdSelector.refresh(false /*reload*/); - } - - - // End of hiding from SWT Designer - //$hide<<$ -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/AvdManagerWindowImpl1.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/AvdManagerWindowImpl1.java deleted file mode 100755 index e3efca6..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/AvdManagerWindowImpl1.java +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Copyright (C) 2011 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.repository.ui; - - -import com.android.SdkConstants; -import com.android.sdklib.devices.DeviceManager; -import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdklib.internal.repository.ITaskFactory; -import com.android.sdkuilib.internal.repository.AboutDialog; -import com.android.sdkuilib.internal.repository.MenuBarWrapper; -import com.android.sdkuilib.internal.repository.SettingsController; -import com.android.sdkuilib.internal.repository.SettingsDialog; -import com.android.sdkuilib.internal.repository.UpdaterData; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.internal.repository.ui.DeviceManagerPage.IAvdCreatedListener; -import com.android.sdkuilib.repository.AvdManagerWindow.AvdInvocationContext; -import com.android.sdkuilib.repository.ISdkChangeListener; -import com.android.sdkuilib.repository.SdkUpdaterWindow; -import com.android.sdkuilib.ui.GridDataBuilder; -import com.android.sdkuilib.ui.GridLayoutBuilder; -import com.android.utils.ILogger; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Menu; -import org.eclipse.swt.widgets.MenuItem; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.TabFolder; -import org.eclipse.swt.widgets.TabItem; - -/** - * This is an intermediate version of the {@link AvdManagerPage} - * wrapped in its own standalone window for use from the SDK Manager 2. - */ -public class AvdManagerWindowImpl1 { - - private static final String APP_NAME = "Android Virtual Device Manager"; - private static final String APP_NAME_MAC_MENU = "AVD Manager"; - private static final String SIZE_POS_PREFIX = "avdman1"; //$NON-NLS-1$ - - private final Shell mParentShell; - private final AvdInvocationContext mContext; - /** Internal data shared between the window and its pages. */ - private final UpdaterData mUpdaterData; - /** True if this window created the UpdaterData, in which case it needs to dispose it. */ - private final boolean mOwnUpdaterData; - private final DeviceManager mDeviceManager; - - - // --- UI members --- - - protected Shell mShell; - private AvdManagerPage mAvdPage; - private SettingsController mSettingsController; - private TabFolder mTabFolder; - - /** - * Creates a new window. Caller must call open(), which will block. - * - * @param parentShell Parent shell. - * @param sdkLog Logger. Cannot be null. - * @param osSdkRoot The OS path to the SDK root. - * @param context The {@link AvdInvocationContext} to change the behavior depending on who's - * opening the SDK Manager. - */ - public AvdManagerWindowImpl1( - Shell parentShell, - ILogger sdkLog, - String osSdkRoot, - AvdInvocationContext context) { - mParentShell = parentShell; - mContext = context; - mUpdaterData = new UpdaterData(osSdkRoot, sdkLog); - mOwnUpdaterData = true; - mDeviceManager = DeviceManager.createInstance(osSdkRoot, sdkLog); - } - - /** - * Creates a new window. Caller must call open(), which will block. - * <p/> - * This is to be used when the window is opened from {@link SdkUpdaterWindowImpl2} - * to share the same {@link UpdaterData} structure. - * - * @param parentShell Parent shell. - * @param updaterData The parent's updater data. - * @param context The {@link AvdInvocationContext} to change the behavior depending on who's - * opening the SDK Manager. - */ - public AvdManagerWindowImpl1( - Shell parentShell, - UpdaterData updaterData, - AvdInvocationContext context) { - mParentShell = parentShell; - mContext = context; - mUpdaterData = updaterData; - mOwnUpdaterData = false; - mDeviceManager = DeviceManager.createInstance(mUpdaterData.getOsSdkRoot(), - mUpdaterData.getSdkLog()); - } - - /** - * Opens the window. - * @wbp.parser.entryPoint - */ - public void open() { - if (mParentShell == null) { - Display.setAppName(APP_NAME); //$hide$ (hide from SWT designer) - } - - createShell(); - preCreateContent(); - createContents(); - createMenuBar(); - mShell.open(); - mShell.layout(); - - boolean ok = postCreateContent(); - - if (ok && mContext == AvdInvocationContext.STANDALONE) { - Display display = Display.getDefault(); - while (!mShell.isDisposed()) { - if (!display.readAndDispatch()) { - display.sleep(); - } - } - - dispose(); //$hide$ - } - } - - private void createShell() { - // The AVD Manager must use a shell trim when standalone - // or a dialog trim when invoked from somewhere else. - int style = SWT.SHELL_TRIM; - if (mContext != AvdInvocationContext.STANDALONE) { - style |= SWT.APPLICATION_MODAL; - } - - mShell = new Shell(mParentShell, style); - mShell.addDisposeListener(new DisposeListener() { - @Override - public void widgetDisposed(DisposeEvent e) { - ShellSizeAndPos.saveSizeAndPos(mShell, SIZE_POS_PREFIX); //$hide$ - onAndroidSdkUpdaterDispose(); //$hide$ - mAvdPage.dispose(); //$hide$ - } - }); - - GridLayout glShell = new GridLayout(2, false); - mShell.setLayout(glShell); - - mShell.setMinimumSize(new Point(500, 300)); - mShell.setSize(700, 500); - mShell.setText(APP_NAME); - - ShellSizeAndPos.loadSizeAndPos(mShell, SIZE_POS_PREFIX); - } - - private void createContents() { - - mTabFolder = new TabFolder(mShell, SWT.NONE); - GridDataBuilder.create(mTabFolder).fill().grab().hSpan(2); - - // avd tab - TabItem avdTabItem = new TabItem(mTabFolder, SWT.NONE); - avdTabItem.setText("Android Virtual Devices"); - createAvdTab(mTabFolder, avdTabItem); - - // device tab - TabItem devTabItem = new TabItem(mTabFolder, SWT.NONE); - devTabItem.setText("Device Definitions"); - createDeviceTab(mTabFolder, devTabItem); - } - - private void createAvdTab(TabFolder tabFolder, TabItem avdTabItem) { - Composite root = new Composite(tabFolder, SWT.NONE); - avdTabItem.setControl(root); - GridLayoutBuilder.create(root).columns(1); - - mAvdPage = new AvdManagerPage(root, SWT.NONE, mUpdaterData, mDeviceManager); - GridDataBuilder.create(mAvdPage).fill().grab(); - } - - private void createDeviceTab(TabFolder tabFolder, TabItem devTabItem) { - Composite root = new Composite(tabFolder, SWT.NONE); - devTabItem.setControl(root); - GridLayoutBuilder.create(root).columns(1); - - DeviceManagerPage devicePage = - new DeviceManagerPage(root, SWT.NONE, mUpdaterData, mDeviceManager); - GridDataBuilder.create(devicePage).fill().grab(); - - devicePage.setAvdCreatedListener(new IAvdCreatedListener() { - @Override - public void onAvdCreated(AvdInfo avdInfo) { - if (avdInfo != null) { - mTabFolder.setSelection(0); // display mAvdPage - mAvdPage.selectAvd(avdInfo, true /*reloadAvdList*/); - } - } - }); - } - - @SuppressWarnings("unused") - // MenuBarWrapper works using side effects - private void createMenuBar() { - Menu menuBar = new Menu(mShell, SWT.BAR); - mShell.setMenuBar(menuBar); - - // Only create the tools menu when running as standalone. - // We don't need the tools menu when invoked from the IDE, or the SDK Manager - // or from the AVD Chooser dialog. The only point of the tools menu is to - // get the about box, and invoke Tools > SDK Manager, which we don't - // need to do in these cases. - if (mContext == AvdInvocationContext.STANDALONE) { - - MenuItem menuBarTools = new MenuItem(menuBar, SWT.CASCADE); - menuBarTools.setText("Tools"); - - Menu menuTools = new Menu(menuBarTools); - menuBarTools.setMenu(menuTools); - - MenuItem manageSdk = new MenuItem(menuTools, SWT.NONE); - manageSdk.setText("Manage SDK..."); - manageSdk.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - onSdkManager(); - } - }); - - try { - new MenuBarWrapper(APP_NAME_MAC_MENU, menuTools) { - @Override - public void onPreferencesMenuSelected() { - SettingsDialog sd = new SettingsDialog(mShell, mUpdaterData); - sd.open(); - } - - @Override - public void onAboutMenuSelected() { - AboutDialog ad = new AboutDialog(mShell, mUpdaterData); - ad.open(); - } - - @Override - public void printError(String format, Object... args) { - if (mUpdaterData != null) { - mUpdaterData.getSdkLog().error(null, format, args); - } - } - }; - } catch (Throwable e) { - mUpdaterData.getSdkLog().error(e, "Failed to setup menu bar"); - e.printStackTrace(); - } - } - } - - - // -- Start of internal part ---------- - // Hide everything down-below from SWT designer - //$hide>>$ - - // --- Public API ----------- - - /** - * Adds a new listener to be notified when a change is made to the content of the SDK. - */ - public void addListener(ISdkChangeListener listener) { - mUpdaterData.addListeners(listener); - } - - /** - * Removes a new listener to be notified anymore when a change is made to the content of - * the SDK. - */ - public void removeListener(ISdkChangeListener listener) { - mUpdaterData.removeListener(listener); - } - - // --- Internals & UI Callbacks ----------- - - /** - * Called before the UI is created. - */ - private void preCreateContent() { - mUpdaterData.setWindowShell(mShell); - // We need the UI factory to create the UI - mUpdaterData.setImageFactory(new ImageFactory(mShell.getDisplay())); - // Note: we can't create the TaskFactory yet because we need the UI - // to be created first, so this is done in postCreateContent(). - } - - /** - * Once the UI has been created, initializes the content. - * This creates the pages, selects the first one, setup sources and scan for local folders. - * - * Returns true if we should show the window. - */ - private boolean postCreateContent() { - setWindowImage(mShell); - - setupSources(); - initializeSettings(); - - if (mUpdaterData.checkIfInitFailed()) { - return false; - } - - mUpdaterData.broadcastOnSdkLoaded(); - - return true; - } - - /** - * Creates the icon of the window shell. - * - * @param shell The shell on which to put the icon - */ - private void setWindowImage(Shell shell) { - String imageName = "android_icon_16.png"; //$NON-NLS-1$ - if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_DARWIN) { - imageName = "android_icon_128.png"; - } - - if (mUpdaterData != null) { - ImageFactory imgFactory = mUpdaterData.getImageFactory(); - if (imgFactory != null) { - shell.setImage(imgFactory.getImageByName(imageName)); - } - } - } - - /** - * Called by the main loop when the window has been disposed. - */ - private void dispose() { - mUpdaterData.getSources().saveUserAddons(mUpdaterData.getSdkLog()); - } - - /** - * Callback called when the window shell is disposed. - */ - private void onAndroidSdkUpdaterDispose() { - if (mOwnUpdaterData && mUpdaterData != null) { - ImageFactory imgFactory = mUpdaterData.getImageFactory(); - if (imgFactory != null) { - imgFactory.dispose(); - } - } - } - - /** - * Used to initialize the sources. - */ - private void setupSources() { - mUpdaterData.setupDefaultSources(); - } - - /** - * Initializes settings. - * This must be called after addExtraPages(), which created a settings page. - * Iterate through all the pages to find the first (and supposedly unique) setting page, - * and use it to load and apply these settings. - */ - private void initializeSettings() { - mSettingsController = mUpdaterData.getSettingsController(); - mSettingsController.loadSettings(); - mSettingsController.applySettings(); - } - - private void onSdkManager() { - ITaskFactory oldFactory = mUpdaterData.getTaskFactory(); - - try { - SdkUpdaterWindowImpl2 win = new SdkUpdaterWindowImpl2( - mShell, - mUpdaterData, - SdkUpdaterWindow.SdkInvocationContext.AVD_MANAGER); - - win.open(); - } catch (Exception e) { - mUpdaterData.getSdkLog().error(e, "SDK Manager window error"); - } finally { - mUpdaterData.setTaskFactory(oldFactory); - } - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/DeviceManagerPage.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/DeviceManagerPage.java deleted file mode 100755 index 7b63d39..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/DeviceManagerPage.java +++ /dev/null @@ -1,832 +0,0 @@ -/* - * Copyright (C) 2012 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.repository.ui; - -import com.android.sdklib.devices.Device; -import com.android.sdklib.devices.DeviceManager; -import com.android.sdklib.devices.DeviceManager.DevicesChangedListener; -import com.android.sdklib.devices.Hardware; -import com.android.sdklib.devices.Screen; -import com.android.sdklib.devices.Storage; -import com.android.sdklib.devices.Storage.Unit; -import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdkuilib.internal.repository.UpdaterData; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.internal.widgets.AvdCreationDialog; -import com.android.sdkuilib.internal.widgets.AvdSelector; -import com.android.sdkuilib.internal.widgets.DeviceCreationDialog; -import com.android.sdkuilib.repository.ISdkChangeListener; -import com.android.sdkuilib.ui.GridDataBuilder; -import com.android.sdkuilib.ui.GridLayoutBuilder; - -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; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.FontData; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.graphics.Resource; -import org.eclipse.swt.graphics.TextLayout; -import org.eclipse.swt.graphics.TextStyle; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; -import org.eclipse.swt.widgets.TableItem; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * A page displaying Device Manager entries. - * <p/> - * This is displayed as a second tab in the AVD Manager window. - * The layout purposely matches the one from {@link AvdManagerPage} and {@link AvdSelector} - * so that there's a good consistency when switching tabs. - * The table displays a few properties of each device as well as actions to edit/add/delete - * devices and a button to create an AVD from a given device. - * - * Non-goals: this tries to keep it simple for a first iteration. Possible enhancements: - * - a way to sort the device list by name, manufacturer or screen size. - * - possibly a tree organized by manufacturer. - * - a filter box to do a string search on any part of the display. - */ -public class DeviceManagerPage extends Composite - implements ISdkChangeListener, DevicesChangedListener, DisposeListener { - - public interface IAvdCreatedListener { - public void onAvdCreated(AvdInfo createdAvdInfo); - } - - private final UpdaterData mUpdaterData; - private final DeviceManager mDeviceManager; - private Table mTable; - private Button mNewButton; - private Button mEditButton; - private Button mDeleteButton; - private Button mNewAvdButton; - private Button mRefreshButton; - private ImageFactory mImageFactory; - private Image mUserImage; - private Image mGenericImage; - private Image mOtherImage; - private int mImageWidth; - private boolean mDisableRefresh; - private IAvdCreatedListener mAvdCreatedListener; - - /** - * Create the composite. - * @param parent The parent of the composite. - * @param updaterData An instance of {@link UpdaterData}. - */ - public DeviceManagerPage(Composite parent, - int swtStyle, - UpdaterData updaterData, - DeviceManager deviceManager) { - super(parent, swtStyle); - - mUpdaterData = updaterData; - mUpdaterData.addListeners(this); - - mDeviceManager = deviceManager; - mDeviceManager.registerListener(this); - - createContents(this); - postCreate(); //$hide$ - } - - public void setAvdCreatedListener(IAvdCreatedListener avdCreatedListener) { - mAvdCreatedListener = avdCreatedListener; - } - - private void createContents(Composite parent) { - - // get some bitmaps. - mImageFactory = new ImageFactory(parent.getDisplay()); - mUserImage = mImageFactory.getImageByName("devman_user_16.png"); - mGenericImage = mImageFactory.getImageByName("devman_generic_16.png"); - mOtherImage = mImageFactory.getImageByName("devman_manufacturer_16.png"); - mImageWidth = Math.max(mGenericImage.getImageData().width, - Math.max(mUserImage.getImageData().width, - mOtherImage.getImageData().width)); - - // Layout has 2 columns - GridLayoutBuilder.create(parent).columns(2); - - // Insert a top label explanation. This matches the design in AvdManagerPage so - // that the table starts at the same height on both tabs. - Label label = new Label(parent, SWT.NONE); - label.setText("List of known device definitions. This can later be used to create Android Virtual Devices."); - GridDataBuilder.create(label).hSpan(2); - - // Device table. - mTable = new Table(parent, SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER); - mTable.setHeaderVisible(true); - mTable.setLinesVisible(true); - mTable.setFont(parent.getFont()); - setTableHeightHint(30); - - // Buttons on the side. - Composite buttons = new Composite(parent, SWT.NONE); - GridLayoutBuilder.create(buttons).columns(1).noMargins(); - GridDataBuilder.create(buttons).vFill(); - buttons.setFont(parent.getFont()); - - mNewButton = new Button(buttons, SWT.PUSH | SWT.FLAT); - mNewButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mNewButton.setText("New Device..."); - mNewButton.setToolTipText("Creates a new user device definition."); - mNewButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - onNewDevice(); - } - }); - - mEditButton = new Button(buttons, SWT.PUSH | SWT.FLAT); - mEditButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mEditButton.setText("Edit..."); - mEditButton.setToolTipText("Edit an existing device definition."); - mEditButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - onEditDevice(); - } - }); - - mDeleteButton = new Button(buttons, SWT.PUSH | SWT.FLAT); - mDeleteButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mDeleteButton.setText("Delete..."); - mDeleteButton.setToolTipText("Deletes the selected AVD."); - mDeleteButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - onDeleteDevice(); - } - }); - - @SuppressWarnings("unused") - Label spacing = new Label(buttons, SWT.NONE); - - mNewAvdButton = new Button(buttons, SWT.PUSH | SWT.FLAT); - mNewAvdButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mNewAvdButton.setText("Create AVD..."); - mNewAvdButton.setToolTipText("Creates a new AVD based on this device definition."); - mNewAvdButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - onCreateAvd(); - } - }); - - Composite padding = new Composite(buttons, SWT.NONE); - padding.setLayoutData(new GridData(GridData.FILL_VERTICAL)); - - mRefreshButton = new Button(buttons, SWT.PUSH | SWT.FLAT); - mRefreshButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mRefreshButton.setText("Refresh"); - mRefreshButton.setToolTipText("Reloads the list of devices."); - mRefreshButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - onRefresh(); - } - }); - - // Legend at the bottom. - // This matches the one on AvdSelector so that the table height in the tab be similar. - Composite legend = new Composite(parent, SWT.NONE); - GridLayoutBuilder.create(legend).columns(4).noMargins(); - GridDataBuilder.create(legend).hFill().vTop().hGrab().hSpan(2); - legend.setFont(parent.getFont()); - - new Label(legend, SWT.NONE).setImage(mUserImage); - new Label(legend, SWT.NONE).setText("A user-created device definition."); - new Label(legend, SWT.NONE).setImage(mGenericImage); - new Label(legend, SWT.NONE).setText("A generic device definition."); - Label icon = new Label(legend, SWT.NONE); - icon.setImage(mOtherImage); - Label l = new Label(legend, SWT.NONE); - l.setText("A manufacturer-specific device definition."); - GridData gd; - l.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.horizontalSpan = 3; - icon.setVisible(false); - l.setVisible(false); - - // create the table columns - final TableColumn column0 = new TableColumn(mTable, SWT.NONE); - column0.setText("Device"); - - adjustColumnsWidth(mTable, column0); - setupSelectionListener(mTable); - fillTable(mTable); - updateButtonStates(); - setEnabled(true); - } - - private void adjustColumnsWidth(final Table table, final TableColumn column0) { - // Add a listener to resize the column to the full width of the table - table.addControlListener(new ControlAdapter() { - @Override - public void controlResized(ControlEvent e) { - Rectangle r = table.getClientArea(); - column0.setWidth(r.width * 100 / 100 - 1); // 100% - } - }); - } - - private void setupSelectionListener(Table table) { - // TODO Auto-generated method stub - - } - - /** - * Sets the table grid layout data. - * - * @param heightHint If > 0, the height hint is set to the requested value. - */ - public void setTableHeightHint(int heightHint) { - GridData data = new GridData(); - if (heightHint > 0) { - data.heightHint = heightHint; - } - data.grabExcessVerticalSpace = true; - data.grabExcessHorizontalSpace = true; - data.horizontalAlignment = GridData.FILL; - data.verticalAlignment = GridData.FILL; - mTable.setLayoutData(data); - } - - @Override - public void widgetDisposed(DisposeEvent e) { - dispose(); - } - - @Override - public void dispose() { - mUpdaterData.removeListener(this); - mDeviceManager.unregisterListener(this); - super.dispose(); - } - - @Override - protected void checkSubclass() { - // Disable the check that prevents subclassing of SWT components - } - - // -- Start of internal part ---------- - // Hide everything down-below from SWT designer - //$hide>>$ - - /** - * Called by the constructor right after {@link #createContents(Composite)}. - */ - private void postCreate() { - // nothing to be done for now. - } - - - // ------- - - private static class CellInfo { - final boolean mIsUser; - final Device mDevice; - final TextLayout mWidget; - Rectangle mBounds; - - CellInfo(boolean isUser, Device device, TextLayout widget) { - mIsUser = isUser; - mDevice = device; - mWidget = widget; - } - } - - private void fillTable(final Table table) { - - table.removeAll(); - disposeTableResources(table.getData("disposeResources")); - - final List<Resource> disposables = new ArrayList<Resource>(); - - Font boldFont = getBoldFont(table); - if (boldFont != null) { - disposables.add(boldFont); - } else { - boldFont = table.getFont(); - } - - try { - mDisableRefresh = true; - disposables.addAll(fillDevices(table, boldFont, true, - mDeviceManager.getDevices(DeviceManager.USER_DEVICES))); - disposables.addAll(fillDevices(table, boldFont, false, - mDeviceManager.getDevices(DeviceManager.DEFAULT_DEVICES | - DeviceManager.VENDOR_DEVICES))); - } finally { - mDisableRefresh = false; - } - - table.setData("disposeResources", disposables); - - if (!Boolean.TRUE.equals(table.getData("createdTableListeners"))) { - table.addListener(SWT.PaintItem, new Listener() { - @Override - public void handleEvent(Event event) { - if (event.item != null) { - Object info = event.item.getData(); - if (info instanceof CellInfo) { - ((CellInfo) info).mWidget.draw(event.gc, event.x, event.y + 1); - } - } - } - }); - - table.addListener(SWT.MeasureItem, new Listener() { - @Override - public void handleEvent(Event event) { - if (event.item != null) { - Object info = event.item.getData(); - if (info instanceof CellInfo) { - CellInfo ci = (CellInfo) info; - Rectangle bounds = ci.mBounds; - if (bounds == null) { - // TextLayout.getBounds() seems expensive, so let's cache it. - ci.mBounds = bounds = ci.mWidget.getBounds(); - } - event.width = bounds.width + 2; - event.height = bounds.height + 4; - } - } - } - }); - - table.addDisposeListener(new DisposeListener() { - @Override - public void widgetDisposed(DisposeEvent event) { - disposeTableResources(table.getData("disposeResources")); - } - }); - - table.addSelectionListener(new SelectionListener() { - /** Handles single clicks on a row. */ - @Override - public void widgetSelected(SelectionEvent event) { - updateButtonStates(); - } - - /** Handles double click on a row. */ - @Override - public void widgetDefaultSelected(SelectionEvent event) { - // FIXME: should double-click be to edit a device or create a new AVD? - onEditDevice(); - } - }); - } - - if (table.getItemCount() == 0) { - table.setEnabled(true); - TableItem item = new TableItem(table, SWT.NONE); - item.setData(null); - item.setText(0, "No devices available"); - return; - } - - table.setData("createdTableListeners", Boolean.TRUE); - } - - private void disposeTableResources(Object disposablesList) { - if (disposablesList instanceof List<?>) { - for (Object obj : (List<?>) disposablesList) { - if (obj instanceof Resource) { - ((Resource) obj).dispose(); - } - } - } - } - - private Font getBoldFont(Table table) { - Display display = table.getDisplay(); - FontData[] fds = table.getFont().getFontData(); - if (fds != null && fds.length > 0) { - fds[0].setStyle(SWT.BOLD); - return new Font(display, fds[0]); - } - return null; - } - - private List<Resource> fillDevices( - Table table, - Font boldFont, - boolean isUser, - List<Device> devices) { - List<Resource> disposables = new ArrayList<Resource>(); - Display display = table.getDisplay(); - - TextStyle boldStyle = new TextStyle(); - boldStyle.font = boldFont; - - // We need the list to be be modifiable so that we can sort it. - devices = new ArrayList<Device>(devices); - - if (isUser) { - // Just sort user devices by alphabetical name. They will show up at the top. - Collections.sort(devices, new Comparator<Device>() { - @Override - public int compare(Device d1, Device d2) { - String s1 = d1 == null ? "" : d1.getName(); - String s2 = d2 == null ? "" : d2.getName(); - return s1.compareTo(s2); - }}); - } else { - // Sort non-user devices by descending "pretty name" - // TODO revisit. Doesn't perform as well as expected. - Collections.sort(devices, new Comparator<Device>() { - @Override - public int compare(Device d1, Device d2) { - String s1 = getPrettyName(d1, true /*leadZeroes*/); - String s2 = getPrettyName(d2, true /*leadZeroes*/); - return s2.compareTo(s1); - }}); - } - - // Generate a list of the AVD names using these devices - Map<Device, List<String>> device2avdMap = new HashMap<Device, List<String>>(); - for (AvdInfo avd : mUpdaterData.getAvdManager().getAllAvds()) { - String n = avd.getDeviceName(); - String m = avd.getDeviceManufacturer(); - if (n == null || m == null || n.isEmpty() || m.isEmpty()) { - continue; - } - for (Device device : devices) { - if (m.equals(device.getManufacturer()) && n.equals(device.getName())) { - List<String> list = device2avdMap.get(device); - if (list == null) { - list = new LinkedList<String>(); - device2avdMap.put(device, list); - } - list.add(avd.getName()); - } - } - } - - final String prefix = "\n "; - - for (Device device : devices) { - TableItem item = new TableItem(table, SWT.NONE); - TextLayout widget = new TextLayout(display); - CellInfo ci = new CellInfo(isUser, device, widget); - item.setData(ci); - - widget.setIndent(mImageWidth * 2); - widget.setFont(table.getFont()); - - StringBuilder sb = new StringBuilder(); - String name = getPrettyName(device, false /*leadZeroes*/); - sb.append(name); - int pos1 = sb.length(); - - String manufacturer = device.getManufacturer(); - String manu = manufacturer; - if (isUser) { - item.setImage(mUserImage); - } else if (GENERIC.equals(manu)) { - item.setImage(mGenericImage); - } else { - item.setImage(mOtherImage); - if (!manufacturer.contains(NEXUS)) { - sb.append(" by ").append(manufacturer); - } - } - - Hardware hw = device.getDefaultHardware(); - Screen screen = hw.getScreen(); - sb.append(prefix); - sb.append(String.format(java.util.Locale.US, - "Screen: %1$.1f\", %2$d \u00D7 %3$d, %4$s %5$s", // U+00D7: Unicode multiplication sign - screen.getDiagonalLength(), - screen.getXDimension(), - screen.getYDimension(), - screen.getSize().getShortDisplayValue(), - screen.getPixelDensity().getResourceValue() - )); - - Storage sto = hw.getRam(); - Unit unit = sto.getSizeAsUnit(Unit.GiB) > 1 ? Unit.GiB : Unit.MiB; - sb.append(prefix); - sb.append(String.format(java.util.Locale.US, - "RAM: %1$d %2$s", - sto.getSizeAsUnit(unit), - unit)); - - List<String> avdList = device2avdMap.get(device); - if (avdList != null && !avdList.isEmpty()) { - sb.append(prefix); - sb.append("Used by: "); - boolean first = true; - for (String avd : avdList) { - if (!first) { - sb.append(", "); - } - sb.append(avd); - first = false; - } - } - - widget.setText(sb.toString()); - widget.setStyle(boldStyle, 0, pos1); - } - - return disposables; - } - - // Constants extracted from DeviceMenuListerner -- TODO refactor somewhere else. - private static final String NEXUS = "Nexus"; //$NON-NLS-1$ - private static final String GENERIC = "Generic"; //$NON-NLS-1$ - private static Pattern PATTERN = Pattern.compile( - "(\\d+\\.?\\d*)in (.+?)( \\(.*Nexus.*\\))?"); //$NON-NLS-1$ - /** - * Returns a pretty name for the device. - * - * Extracted from DeviceMenuListener. - * Modified to remove the leading space insertion as it doesn't render - * neatly in the avd manager. Instead added the option to add leading - * zeroes to make the string names sort properly. - * - * Replace "'in'" with '"' (e.g. 2.7" QVGA instead of 2.7in QVGA) - * Use the same precision for all devices (all but one specify decimals) - * Add in screen resolution and density - */ - private static String getPrettyName(Device d, boolean leadZeroes) { - if (d == null) { - return ""; - } - String name = d.getName(); - if (name.equals("3.7 FWVGA slider")) { //$NON-NLS-1$ - // Fix metadata: this one entry doesn't have "in" like the rest of them - name = "3.7in FWVGA slider"; //$NON-NLS-1$ - } - - Matcher matcher = PATTERN.matcher(name); - if (matcher.matches()) { - String size = matcher.group(1); - String n = matcher.group(2); - int dot = size.indexOf('.'); - if (dot == -1) { - size = size + ".0"; - dot = size.length() - 2; - } - if (leadZeroes && dot < 3) { - // Pad to have at least 3 digits before the dot, for sorting purposes. - // We can revisit this once we get devices that are more than 999 inches wide. - size = "000".substring(dot) + size; - } - name = size + "\" " + n; - } - - return name; - } - - /** - * Returns the currently selected cell info in the table or null - */ - private CellInfo getTableSelection() { - if (mTable.isDisposed()) { - return null; - } - int selIndex = mTable.getSelectionIndex(); - if (selIndex >= 0) { - return (CellInfo) mTable.getItem(selIndex).getData(); - } - - return null; - } - - private void updateButtonStates() { - CellInfo ci = getTableSelection(); - - mNewButton.setEnabled(true); - mEditButton.setEnabled(ci != null); - mEditButton.setText((ci != null && !ci.mIsUser) ? "Clone..." : "Edit..."); - mDeleteButton.setEnabled(ci != null && ci.mIsUser); - mNewAvdButton.setEnabled(ci != null); - mRefreshButton.setEnabled(true); - } - - private void onNewDevice() { - DeviceCreationDialog dlg = new DeviceCreationDialog( - getShell(), - mDeviceManager, - mUpdaterData.getImageFactory(), - null /*device*/); - if (dlg.open() == Window.OK) { - onRefresh(); - - // Select the new device, if any. - selectCellByDevice(dlg.getCreatedDevice()); - updateButtonStates(); - } - } - - private void onEditDevice() { - CellInfo ci = getTableSelection(); - if (ci == null || ci.mDevice == null) { - return; - } - - DeviceCreationDialog dlg = new DeviceCreationDialog( - getShell(), - mDeviceManager, - mUpdaterData.getImageFactory(), - ci.mDevice); - if (dlg.open() == Window.OK) { - onRefresh(); - - // Select the new device, if any. - selectCellByDevice(dlg.getCreatedDevice()); - updateButtonStates(); - } - } - - private void onDeleteDevice() { - CellInfo ci = getTableSelection(); - if (ci == null || ci.mDevice == null || !ci.mIsUser) { - return; - } - - final String name = getPrettyName(ci.mDevice, false /*leadZeroes*/); - final AtomicBoolean result = new AtomicBoolean(false); - getDisplay().syncExec(new Runnable() { - @Override - public void run() { - Shell shell = getDisplay().getActiveShell(); - boolean ok = MessageDialog.openQuestion(shell, - "Delete Device Definition", - String.format( - "Please confirm that you want to delete the device definition named '%s'. This operation cannot be reverted.", - name)); - result.set(ok); - } - }); - - if (result.get()) { - mDeviceManager.removeUserDevice(ci.mDevice); - mDeviceManager.saveUserDevices(); - onRefresh(); - } - } - - private void onCreateAvd() { - CellInfo ci = getTableSelection(); - if (ci == null || ci.mDevice == null) { - return; - } - - final AvdCreationDialog dlg = new AvdCreationDialog(mTable.getShell(), - mUpdaterData.getAvdManager(), - mImageFactory, - mUpdaterData.getSdkLog(), - null); - dlg.selectInitialDevice(ci.mDevice); - - if (dlg.open() == Window.OK) { - onRefresh(); - - if (mAvdCreatedListener != null) { - mAvdCreatedListener.onAvdCreated(dlg.getCreatedAvd()); - } - } - } - - private void onRefresh() { - if (mDisableRefresh || mTable.isDisposed()) { - return; - } - int selIndex = mTable.getSelectionIndex(); - CellInfo selected = getTableSelection(); - - fillTable(mTable); - - if (selected != null) { - if (selectCellByName(selected)) { - updateButtonStates(); - return; - } - } - // If not found by name, use the position if available. - if (selIndex >= 0 && selIndex < mTable.getItemCount()) { - mTable.select(selIndex); - } - } - - private boolean selectCellByName(CellInfo selected) { - if (mTable.isDisposed() || selected == null || selected.mDevice == null) { - return false; - } - String name = selected.mDevice.getName(); - for (int n = mTable.getItemCount() - 1; n >= 0; n--) { - TableItem item = mTable.getItem(n); - Object data = item.getData(); - if (data instanceof CellInfo) { - CellInfo ci = (CellInfo) data; - if (ci != null && ci.mDevice != null && name.equals(ci.mDevice.getName())) { - // Same cell object. Select it. - mTable.select(n); - return true; - } - } - } - return false; - } - - private boolean selectCellByDevice(Device selected) { - if (mTable.isDisposed() || selected == null) { - return false; - } - for (int n = mTable.getItemCount() - 1; n >= 0; n--) { - TableItem item = mTable.getItem(n); - Object data = item.getData(); - if (data instanceof CellInfo) { - CellInfo ci = (CellInfo) data; - if (ci != null && ci.mDevice == selected) { - // Same device object. Select it. - mTable.select(n); - return true; - } - } - } - return false; - } - - // ------- - - - // --- Implementation of ISdkChangeListener --- - - @Override - public void onSdkLoaded() { - onSdkReload(); - } - - @Override - public void onSdkReload() { - onRefresh(); - } - - @Override - public void preInstallHook() { - // nothing to be done for now. - } - - @Override - public void postInstallHook() { - // nothing to be done for now. - } - - // --- Implementation of DevicesChangeListener - - @Override - public void onDevicesChanged() { - onRefresh(); - } - - - // End of hiding from SWT Designer - //$hide<<$ -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/LogWindow.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/LogWindow.java deleted file mode 100755 index 43dbaf5..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/LogWindow.java +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (C) 2011 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.repository.ui; - -import com.android.sdkuilib.internal.tasks.ILogUiProvider; -import com.android.sdkuilib.ui.GridDataBuilder; -import com.android.sdkuilib.ui.GridLayoutBuilder; -import com.android.utils.ILogger; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.StyleRange; -import org.eclipse.swt.custom.StyledText; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -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.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Widget; - - -/** - * A floating log window that can be displayed or hidden by the main SDK Manager 2 window. - * It displays a log of the sdk manager operation (listing, install, delete) including - * any errors (e.g. network error or install/delete errors.) - * <p/> - * Since the SDK Manager will direct all log to this window, its purpose is to be - * opened by the main window at startup and left open all the time. When not needed - * the floating window is hidden but not closed. This way it can easily accumulate - * all the log. - */ -class LogWindow implements ILogUiProvider { - - private Shell mParentShell; - private Shell mShell; - private Composite mRootComposite; - private StyledText mStyledText; - private Label mLogDescription; - private Button mCloseButton; - - private final ILogger mSecondaryLog; - private boolean mCloseRequested; - private boolean mInitPosition = true; - private String mLastLogMsg = null; - - private enum TextStyle { - DEFAULT, - TITLE, - ERROR - } - - /** - * Creates the floating window. Callers should use {@link #open()} later. - * - * @param parentShell Parent container - * @param secondaryLog An optional logger where messages will <em>also</em> be output. - */ - public LogWindow(Shell parentShell, ILogger secondaryLog) { - mParentShell = parentShell; - mSecondaryLog = secondaryLog; - } - - /** - * For testing only. See {@link #open()} and {@link #close()} for normal usage. - * @wbp.parser.entryPoint - */ - void openBlocking() { - open(); - Display display = Display.getDefault(); - while (!mShell.isDisposed()) { - if (!display.readAndDispatch()) { - display.sleep(); - } - } - close(); - } - - /** - * Opens the window. - * This call does not block and relies on the fact that the main window is - * already running an SWT event dispatch loop. - * Caller should use {@link #close()} later. - */ - public void open() { - createShell(); - createContents(); - mShell.open(); - mShell.layout(); - mShell.setVisible(false); - } - - /** - * Closes and <em>destroys</em> the window. - * This must be called just before quitting the app. - * <p/> - * To simply hide/show the window, use {@link #setVisible(boolean)} instead. - */ - public void close() { - if (mShell != null && !mShell.isDisposed()) { - mCloseRequested = true; - mShell.close(); - mShell = null; - } - } - - /** - * Determines whether the window is currently shown or not. - * - * @return True if the window is shown. - */ - public boolean isVisible() { - return mShell != null && !mShell.isDisposed() && mShell.isVisible(); - } - - /** - * Toggles the window visibility. - * - * @param visible True to make the window visible, false to hide it. - */ - public void setVisible(boolean visible) { - if (mShell != null && !mShell.isDisposed()) { - mShell.setVisible(visible); - if (visible && mInitPosition) { - mInitPosition = false; - positionWindow(); - } - } - } - - private void createShell() { - mShell = new Shell(mParentShell, SWT.SHELL_TRIM | SWT.TOOL); - mShell.setMinimumSize(new Point(600, 300)); - mShell.setSize(450, 300); - mShell.setText("Android SDK Manager Log"); - GridLayoutBuilder.create(mShell); - - mShell.addShellListener(new ShellAdapter() { - @Override - public void shellClosed(ShellEvent e) { - if (!mCloseRequested) { - e.doit = false; - setVisible(false); - } - } - }); - } - - /** - * Create contents of the dialog. - */ - private void createContents() { - mRootComposite = new Composite(mShell, SWT.NONE); - GridLayoutBuilder.create(mRootComposite).columns(2); - GridDataBuilder.create(mRootComposite).fill().grab(); - - mStyledText = new StyledText(mRootComposite, - SWT.BORDER | SWT.MULTI | SWT.READ_ONLY | SWT.WRAP | SWT.V_SCROLL); - GridDataBuilder.create(mStyledText).hSpan(2).fill().grab(); - - mLogDescription = new Label(mRootComposite, SWT.NONE); - GridDataBuilder.create(mLogDescription).hFill().hGrab(); - - mCloseButton = new Button(mRootComposite, SWT.NONE); - mCloseButton.setText("Close"); - mCloseButton.setToolTipText("Closes the log window"); - mCloseButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - setVisible(false); //$hide$ - } - }); - } - - // --- Implementation of ILogUiProvider --- - - - /** - * Sets the description in the current task dialog. - * This method can be invoked from a non-UI thread. - */ - @Override - public void setDescription(final String description) { - syncExec(mLogDescription, new Runnable() { - @Override - public void run() { - mLogDescription.setText(description); - - if (acceptLog(description, true /*isDescription*/)) { - appendLine(TextStyle.TITLE, description); - - if (mSecondaryLog != null) { - mSecondaryLog.info("%1$s", description); //$NON-NLS-1$ - } - } - } - }); - } - - /** - * Logs a "normal" information line. - * This method can be invoked from a non-UI thread. - */ - @Override - public void log(final String log) { - if (acceptLog(log, false /*isDescription*/)) { - syncExec(mLogDescription, new Runnable() { - @Override - public void run() { - appendLine(TextStyle.DEFAULT, log); - } - }); - - if (mSecondaryLog != null) { - mSecondaryLog.info(" %1$s", log); //$NON-NLS-1$ - } - } - } - - /** - * Logs an "error" information line. - * This method can be invoked from a non-UI thread. - */ - @Override - public void logError(final String log) { - if (acceptLog(log, false /*isDescription*/)) { - syncExec(mLogDescription, new Runnable() { - @Override - public void run() { - appendLine(TextStyle.ERROR, log); - } - }); - - if (mSecondaryLog != null) { - mSecondaryLog.error(null, "%1$s", log); //$NON-NLS-1$ - } - } - } - - /** - * Logs a "verbose" information line, that is extra details which are typically - * not that useful for the end-user and might be hidden until explicitly shown. - * This method can be invoked from a non-UI thread. - */ - @Override - public void logVerbose(final String log) { - if (acceptLog(log, false /*isDescription*/)) { - syncExec(mLogDescription, new Runnable() { - @Override - public void run() { - appendLine(TextStyle.DEFAULT, " " + log); //$NON-NLS-1$ - } - }); - - if (mSecondaryLog != null) { - mSecondaryLog.info(" %1$s", log); //$NON-NLS-1$ - } - } - } - - - // ---- - - - /** - * Centers the dialog in its parent shell. - */ - private void positionWindow() { - // Centers the dialog in its parent shell - Shell child = mShell; - if (child != null && mParentShell != null) { - // get the parent client area with a location relative to the display - Rectangle parentArea = mParentShell.getClientArea(); - Point parentLoc = mParentShell.getLocation(); - int px = parentLoc.x; - int py = parentLoc.y; - int pw = parentArea.width; - int ph = parentArea.height; - - Point childSize = child.getSize(); - int cw = Math.max(childSize.x, pw); - int ch = childSize.y; - - int x = 30 + px + (pw - cw) / 2; - if (x < 0) x = 0; - - int y = py + (ph - ch) / 2; - if (y < py) y = py; - - child.setLocation(x, y); - child.setSize(cw, ch); - } - } - - private void appendLine(TextStyle style, String text) { - if (!text.endsWith("\n")) { //$NON-NLS-1$ - text += '\n'; - } - - int start = mStyledText.getCharCount(); - - if (style == TextStyle.DEFAULT) { - mStyledText.append(text); - - } else { - mStyledText.append(text); - - StyleRange sr = new StyleRange(); - sr.start = start; - sr.length = text.length(); - sr.fontStyle = SWT.BOLD; - if (style == TextStyle.ERROR) { - sr.foreground = mStyledText.getDisplay().getSystemColor(SWT.COLOR_DARK_RED); - } - sr.underline = false; - mStyledText.setStyleRange(sr); - } - - // Scroll caret if it was already at the end before we added new text. - // Ideally we would scroll if the scrollbar is at the bottom but we don't - // have direct access to the scrollbar without overriding the SWT impl. - if (mStyledText.getCaretOffset() >= start) { - mStyledText.setSelection(mStyledText.getCharCount()); - } - } - - - private void syncExec(final Widget widget, final Runnable runnable) { - if (widget != null && !widget.isDisposed()) { - widget.getDisplay().syncExec(runnable); - } - } - - /** - * Filter messages displayed in the log: <br/> - * - Messages with a % are typical part of a progress update and shouldn't be in the log. <br/> - * - Messages that are the same as the same output message should be output a second time. - * - * @param msg The potential log line to print. - * @return True if the log line should be printed, false otherwise. - */ - private boolean acceptLog(String msg, boolean isDescription) { - if (msg == null) { - return false; - } - - msg = msg.trim(); - - // Descriptions also have the download progress status (0..100%) which we want to avoid - if (isDescription && msg.indexOf('%') != -1) { - return false; - } - - if (msg.equals(mLastLogMsg)) { - return false; - } - - mLastLogMsg = msg; - return true; - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PackagesPage.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PackagesPage.java deleted file mode 100755 index d9a1102..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PackagesPage.java +++ /dev/null @@ -1,1297 +0,0 @@ -/* - * Copyright (C) 2011 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.repository.ui; - -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.archives.ArchiveInstaller; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdkuilib.internal.repository.UpdaterData; -import com.android.sdkuilib.internal.repository.core.PkgCategory; -import com.android.sdkuilib.internal.repository.core.PkgCategoryApi; -import com.android.sdkuilib.internal.repository.core.PkgContentProvider; -import com.android.sdkuilib.internal.repository.core.PkgItem; -import com.android.sdkuilib.internal.repository.core.PkgItem.PkgState; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.repository.ISdkChangeListener; -import com.android.sdkuilib.repository.SdkUpdaterWindow.SdkInvocationContext; -import com.android.sdkuilib.ui.GridDataBuilder; -import com.android.sdkuilib.ui.GridLayoutBuilder; - -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.CheckStateChangedEvent; -import org.eclipse.jface.viewers.CheckboxTreeViewer; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; -import org.eclipse.jface.viewers.DoubleClickEvent; -import org.eclipse.jface.viewers.ICheckStateListener; -import org.eclipse.jface.viewers.IDoubleClickListener; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.ITreeSelection; -import org.eclipse.jface.viewers.TreeViewerColumn; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerFilter; -import org.eclipse.jface.window.ToolTip; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.FontData; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Group; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Link; -import org.eclipse.swt.widgets.MenuItem; -import org.eclipse.swt.widgets.Text; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.swt.widgets.TreeColumn; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -/** - * Page that displays both locally installed packages as well as all known - * remote available packages. This gives an overview of what is installed - * vs what is available and allows the user to update or install packages. - */ -public final class PackagesPage extends Composite implements ISdkChangeListener { - - enum MenuAction { - RELOAD (SWT.NONE, "Reload"), - SHOW_ADDON_SITES (SWT.NONE, "Manage Add-on Sites..."), - TOGGLE_SHOW_ARCHIVES (SWT.CHECK, "Show Archives Details"), - TOGGLE_SHOW_INSTALLED_PKG (SWT.CHECK, "Show Installed Packages"), - TOGGLE_SHOW_OBSOLETE_PKG (SWT.CHECK, "Show Obsolete Packages"), - TOGGLE_SHOW_UPDATE_NEW_PKG (SWT.CHECK, "Show Updates/New Packages"), - SORT_API_LEVEL (SWT.RADIO, "Sort by API Level"), - SORT_SOURCE (SWT.RADIO, "Sort by Repository") - ; - - private final int mMenuStyle; - private final String mMenuTitle; - - MenuAction(int menuStyle, String menuTitle) { - mMenuStyle = menuStyle; - mMenuTitle = menuTitle; - } - - public int getMenuStyle() { - return mMenuStyle; - } - - public String getMenuTitle() { - return mMenuTitle; - } - }; - - private final Map<MenuAction, MenuItem> mMenuActions = new HashMap<MenuAction, MenuItem>(); - - private final PackagesPageImpl mImpl; - private final SdkInvocationContext mContext; - - private boolean mDisplayArchives = false; - private boolean mOperationPending; - - private Composite mGroupPackages; - private Text mTextSdkOsPath; - private Button mCheckSortSource; - private Button mCheckSortApi; - private Button mCheckFilterObsolete; - private Button mCheckFilterInstalled; - private Button mCheckFilterNew; - private Composite mGroupOptions; - private Composite mGroupSdk; - private Button mButtonDelete; - private Button mButtonInstall; - private Font mTreeFontItalic; - private TreeColumn mTreeColumnName; - private CheckboxTreeViewer mTreeViewer; - - public PackagesPage( - Composite parent, - int swtStyle, - UpdaterData updaterData, - SdkInvocationContext context) { - super(parent, swtStyle); - mImpl = new PackagesPageImpl(updaterData) { - @Override - protected boolean isUiDisposed() { - return mGroupPackages == null || mGroupPackages.isDisposed(); - }; - @Override - protected void syncExec(Runnable runnable) { - if (!isUiDisposed()) { - mGroupPackages.getDisplay().syncExec(runnable); - } - }; - - @Override - protected void syncViewerSelection() { - PackagesPage.this.syncViewerSelection(); - } - - @Override - protected void refreshViewerInput() { - PackagesPage.this.refreshViewerInput(); - } - - @Override - protected boolean isSortByApi() { - return PackagesPage.this.isSortByApi(); - } - - @Override - protected Font getTreeFontItalic() { - return mTreeFontItalic; - } - - @Override - protected void loadPackages(boolean useLocalCache, boolean overrideExisting) { - PackagesPage.this.loadPackages(useLocalCache, overrideExisting); - } - }; - mContext = context; - - createContents(this); - postCreate(); //$hide$ - } - - public void performFirstLoad() { - mImpl.performFirstLoad(); - } - - @SuppressWarnings("unused") - private void createContents(Composite parent) { - GridLayoutBuilder.create(parent).noMargins().columns(2); - - mGroupSdk = new Composite(parent, SWT.NONE); - GridDataBuilder.create(mGroupSdk).hFill().vCenter().hGrab().hSpan(2); - GridLayoutBuilder.create(mGroupSdk).columns(2); - - Label label1 = new Label(mGroupSdk, SWT.NONE); - label1.setText("SDK Path:"); - - mTextSdkOsPath = new Text(mGroupSdk, SWT.NONE); - GridDataBuilder.create(mTextSdkOsPath).hFill().vCenter().hGrab(); - mTextSdkOsPath.setEnabled(false); - - Group groupPackages = new Group(parent, SWT.NONE); - mGroupPackages = groupPackages; - GridDataBuilder.create(mGroupPackages).fill().grab().hSpan(2); - groupPackages.setText("Packages"); - GridLayoutBuilder.create(groupPackages).columns(1); - - mTreeViewer = new CheckboxTreeViewer(groupPackages, SWT.BORDER); - mImpl.setITreeViewer(new PackagesPageImpl.ICheckboxTreeViewer() { - @Override - public Object getInput() { - return mTreeViewer.getInput(); - } - - @Override - public void setInput(List<PkgCategory> cats) { - mTreeViewer.setInput(cats); - } - - @Override - public void setContentProvider(PkgContentProvider pkgContentProvider) { - mTreeViewer.setContentProvider(pkgContentProvider); - } - - @Override - public void refresh() { - mTreeViewer.refresh(); - } - - @Override - public Object[] getCheckedElements() { - return mTreeViewer.getCheckedElements(); - } - }); - mTreeViewer.addFilter(new ViewerFilter() { - @Override - public boolean select(Viewer viewer, Object parentElement, Object element) { - return filterViewerItem(element); - } - }); - - mTreeViewer.addCheckStateListener(new ICheckStateListener() { - @Override - public void checkStateChanged(CheckStateChangedEvent event) { - onTreeCheckStateChanged(event); //$hide$ - } - }); - - mTreeViewer.addDoubleClickListener(new IDoubleClickListener() { - @Override - public void doubleClick(DoubleClickEvent event) { - onTreeDoubleClick(event); //$hide$ - } - }); - - Tree tree = mTreeViewer.getTree(); - tree.setLinesVisible(true); - tree.setHeaderVisible(true); - GridDataBuilder.create(tree).fill().grab(); - - // column name icon is set when loading depending on the current filter type - // (e.g. API level or source) - TreeViewerColumn columnName = new TreeViewerColumn(mTreeViewer, SWT.NONE); - mTreeColumnName = columnName.getColumn(); - mTreeColumnName.setText("Name"); - mTreeColumnName.setWidth(340); - - TreeViewerColumn columnApi = new TreeViewerColumn(mTreeViewer, SWT.NONE); - TreeColumn treeColumn2 = columnApi.getColumn(); - treeColumn2.setText("API"); - treeColumn2.setAlignment(SWT.CENTER); - treeColumn2.setWidth(50); - - TreeViewerColumn columnRevision = new TreeViewerColumn(mTreeViewer, SWT.NONE); - TreeColumn treeColumn3 = columnRevision.getColumn(); - treeColumn3.setText("Rev."); - treeColumn3.setToolTipText("Revision currently installed"); - treeColumn3.setAlignment(SWT.CENTER); - treeColumn3.setWidth(50); - - - TreeViewerColumn columnStatus = new TreeViewerColumn(mTreeViewer, SWT.NONE); - TreeColumn treeColumn4 = columnStatus.getColumn(); - treeColumn4.setText("Status"); - treeColumn4.setAlignment(SWT.LEAD); - treeColumn4.setWidth(190); - - mImpl.setIColumns( - wrapColumn(columnName), - wrapColumn(columnApi), - wrapColumn(columnRevision), - wrapColumn(columnStatus)); - - mGroupOptions = new Composite(groupPackages, SWT.NONE); - GridDataBuilder.create(mGroupOptions).hFill().vCenter().hGrab(); - GridLayoutBuilder.create(mGroupOptions).columns(7).noMargins(); - - // Options line 1, 7 columns - - Label label3 = new Label(mGroupOptions, SWT.NONE); - label3.setText("Show:"); - - mCheckFilterNew = new Button(mGroupOptions, SWT.CHECK); - mCheckFilterNew.setText("Updates/New"); - mCheckFilterNew.setToolTipText("Show Updates and New"); - mCheckFilterNew.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - refreshViewerInput(); - } - }); - mCheckFilterNew.setSelection(true); - - mCheckFilterInstalled = new Button(mGroupOptions, SWT.CHECK); - mCheckFilterInstalled.setToolTipText("Show Installed"); - mCheckFilterInstalled.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - refreshViewerInput(); - } - }); - mCheckFilterInstalled.setSelection(true); - mCheckFilterInstalled.setText("Installed"); - - mCheckFilterObsolete = new Button(mGroupOptions, SWT.CHECK); - mCheckFilterObsolete.setText("Obsolete"); - mCheckFilterObsolete.setToolTipText("Also show obsolete packages"); - mCheckFilterObsolete.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - refreshViewerInput(); - } - }); - mCheckFilterObsolete.setSelection(false); - - Link linkSelectNew = new Link(mGroupOptions, SWT.NONE); - // Note for i18n: we need to identify which link is used, and this is done by using the - // text itself so for translation purposes we want to keep the <a> link strings separate. - final String strLinkNew = "New"; - final String strLinkUpdates = "Updates"; - linkSelectNew.setText( - String.format("Select <a>%1$s</a> or <a>%2$s</a>", strLinkNew, strLinkUpdates)); - linkSelectNew.setToolTipText("Selects all items that are either new or updates."); - GridDataBuilder.create(linkSelectNew).hFill(); - linkSelectNew.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - boolean selectNew = e.text == null || e.text.equals(strLinkNew); - onSelectNewUpdates(selectNew, !selectNew, false/*selectTop*/); - } - }); - - // placeholder between "select all" and "install" - Label placeholder = new Label(mGroupOptions, SWT.NONE); - GridDataBuilder.create(placeholder).hFill().hGrab(); - - mButtonInstall = new Button(mGroupOptions, SWT.NONE); - mButtonInstall.setText(""); //$NON-NLS-1$ placeholder, filled in updateButtonsState() - mButtonInstall.setToolTipText("Install one or more packages"); - GridDataBuilder.create(mButtonInstall).vCenter().wHint(150); - mButtonInstall.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onButtonInstall(); //$hide$ - } - }); - - // Options line 2, 7 columns - - Label label2 = new Label(mGroupOptions, SWT.NONE); - label2.setText("Sort by:"); - - mCheckSortApi = new Button(mGroupOptions, SWT.RADIO); - mCheckSortApi.setToolTipText("Sort by API level"); - mCheckSortApi.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - if (mCheckSortApi.getSelection()) { - refreshViewerInput(); - copySelection(true /*toApi*/); - syncViewerSelection(); - } - } - }); - mCheckSortApi.setText("API level"); - mCheckSortApi.setSelection(true); - - mCheckSortSource = new Button(mGroupOptions, SWT.RADIO); - mCheckSortSource.setText("Repository"); - mCheckSortSource.setToolTipText("Sort by Repository"); - mCheckSortSource.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - if (mCheckSortSource.getSelection()) { - refreshViewerInput(); - copySelection(false /*toApi*/); - syncViewerSelection(); - } - } - }); - - // placeholder between "repository" and "deselect" - new Label(mGroupOptions, SWT.NONE); - - Link linkDeselect = new Link(mGroupOptions, SWT.NONE); - linkDeselect.setText("<a>Deselect All</a>"); - linkDeselect.setToolTipText("Deselects all the currently selected items"); - GridDataBuilder.create(linkDeselect).hFill(); - linkDeselect.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - onDeselectAll(); - } - }); - - // placeholder between "deselect" and "delete" - placeholder = new Label(mGroupOptions, SWT.NONE); - GridDataBuilder.create(placeholder).hFill().hGrab(); - - mButtonDelete = new Button(mGroupOptions, SWT.NONE); - mButtonDelete.setText(""); //$NON-NLS-1$ placeholder, filled in updateButtonsState() - mButtonDelete.setToolTipText("Delete one ore more installed packages"); - GridDataBuilder.create(mButtonDelete).vCenter().wHint(150); - mButtonDelete.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onButtonDelete(); //$hide$ - } - }); - } - - private PackagesPageImpl.ITreeViewerColumn wrapColumn(final TreeViewerColumn column) { - return new PackagesPageImpl.ITreeViewerColumn() { - @Override - public void setLabelProvider(ColumnLabelProvider labelProvider) { - column.setLabelProvider(labelProvider); - } - }; - } - - private Image getImage(String filename) { - if (mImpl.mUpdaterData != null) { - ImageFactory imgFactory = mImpl.mUpdaterData.getImageFactory(); - if (imgFactory != null) { - return imgFactory.getImageByName(filename); - } - } - return null; - } - - - // -- Start of internal part ---------- - // Hide everything down-below from SWT designer - //$hide>>$ - - - // --- menu interactions --- - - public void registerMenuAction(final MenuAction action, MenuItem item) { - item.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - Button button = null; - - switch (action) { - case RELOAD: - mImpl.fullReload(); - break; - case SHOW_ADDON_SITES: - AddonSitesDialog d = new AddonSitesDialog(getShell(), mImpl.mUpdaterData); - if (d.open()) { - mImpl.loadPackages(); - } - break; - case TOGGLE_SHOW_ARCHIVES: - mDisplayArchives = !mDisplayArchives; - // Force the viewer to be refreshed - ((PkgContentProvider) mTreeViewer.getContentProvider()). - setDisplayArchives(mDisplayArchives); - mTreeViewer.setInput(null); - refreshViewerInput(); - syncViewerSelection(); - break; - case TOGGLE_SHOW_INSTALLED_PKG: - button = mCheckFilterInstalled; - break; - case TOGGLE_SHOW_OBSOLETE_PKG: - button = mCheckFilterObsolete; - break; - case TOGGLE_SHOW_UPDATE_NEW_PKG: - button = mCheckFilterNew; - break; - case SORT_API_LEVEL: - button = mCheckSortApi; - break; - case SORT_SOURCE: - button = mCheckSortSource; - break; - } - - if (button != null && !button.isDisposed()) { - // Toggle this button (radio or checkbox) - - boolean value = button.getSelection(); - - // SWT doesn't automatically switch radio buttons when using the - // Widget#setSelection method, so we'll do it here manually. - if (!value && (button.getStyle() & SWT.RADIO) != 0) { - // we'll be selecting this radio button, so deselect all ther other ones - // in the parent group. - for (Control child : button.getParent().getChildren()) { - if (child instanceof Button && - child != button && - (child.getStyle() & SWT.RADIO) != 0) { - ((Button) child).setSelection(value); - } - } - } - - button.setSelection(!value); - - // SWT doesn't actually invoke the listeners when using Widget#setSelection - // so let's run the actual action. - button.notifyListeners(SWT.Selection, new Event()); - } - - updateMenuCheckmarks(); - } - }); - - mMenuActions.put(action, item); - } - - // --- internal methods --- - - private void updateMenuCheckmarks() { - - for (Entry<MenuAction, MenuItem> entry : mMenuActions.entrySet()) { - MenuAction action = entry.getKey(); - MenuItem item = entry.getValue(); - - if (action.getMenuStyle() == SWT.NONE) { - continue; - } - - boolean value = false; - Button button = null; - - switch (action) { - case TOGGLE_SHOW_ARCHIVES: - value = mDisplayArchives; - break; - case TOGGLE_SHOW_INSTALLED_PKG: - button = mCheckFilterInstalled; - break; - case TOGGLE_SHOW_OBSOLETE_PKG: - button = mCheckFilterObsolete; - break; - case TOGGLE_SHOW_UPDATE_NEW_PKG: - button = mCheckFilterNew; - break; - case SORT_API_LEVEL: - button = mCheckSortApi; - break; - case SORT_SOURCE: - button = mCheckSortSource; - break; - } - - if (button != null && !button.isDisposed()) { - value = button.getSelection(); - } - - if (!item.isDisposed()) { - item.setSelection(value); - } - } - } - - private void postCreate() { - mImpl.postCreate(); - - if (mImpl.mUpdaterData != null) { - mTextSdkOsPath.setText(mImpl.mUpdaterData.getOsSdkRoot()); - } - - ((PkgContentProvider) mTreeViewer.getContentProvider()).setDisplayArchives( - mDisplayArchives); - - ColumnViewerToolTipSupport.enableFor(mTreeViewer, ToolTip.NO_RECREATE); - - Tree tree = mTreeViewer.getTree(); - FontData fontData = tree.getFont().getFontData()[0]; - fontData.setStyle(SWT.ITALIC); - mTreeFontItalic = new Font(tree.getDisplay(), fontData); - - tree.addDisposeListener(new DisposeListener() { - @Override - public void widgetDisposed(DisposeEvent e) { - mTreeFontItalic.dispose(); - mTreeFontItalic = null; - } - }); - } - - private void loadPackages(boolean useLocalCache, boolean overrideExisting) { - if (mImpl.mUpdaterData == null) { - return; - } - - // LoadPackage is synchronous but does not block the UI. - // Consequently it's entirely possible for the user - // to request the app to close whilst the packages are loading. Any - // action done after loadPackages must check the UI hasn't been - // disposed yet. Otherwise hilarity ensues. - - boolean displaySortByApi = isSortByApi(); - - if (mTreeColumnName.isDisposed()) { - // If the UI got disposed, don't try to load anything since we won't be - // able to display it anyway. - return; - } - - mTreeColumnName.setImage(getImage( - displaySortByApi ? PackagesPageIcons.ICON_SORT_BY_API - : PackagesPageIcons.ICON_SORT_BY_SOURCE)); - - mImpl.loadPackagesImpl(useLocalCache, overrideExisting); - } - - private void refreshViewerInput() { - // Dynamically update the table while we load after each source. - // Since the official Android source gets loaded first, it makes the - // window look non-empty a lot sooner. - if (!mGroupPackages.isDisposed()) { - try { - mImpl.setViewerInput(); - } catch (Exception ignore) {} - - // set the initial expanded state - expandInitial(mTreeViewer.getInput()); - - updateButtonsState(); - updateMenuCheckmarks(); - } - } - - private boolean isSortByApi() { - return mCheckSortApi != null && !mCheckSortApi.isDisposed() && mCheckSortApi.getSelection(); - } - - /** - * Decide whether to keep an item in the current tree based on user-chosen filter options. - */ - private boolean filterViewerItem(Object treeElement) { - if (treeElement instanceof PkgCategory) { - PkgCategory cat = (PkgCategory) treeElement; - - if (!cat.getItems().isEmpty()) { - // A category is hidden if all of its content is hidden. - // However empty categories are always visible. - for (PkgItem item : cat.getItems()) { - if (filterViewerItem(item)) { - // We found at least one element that is visible. - return true; - } - } - return false; - } - } - - if (treeElement instanceof PkgItem) { - PkgItem item = (PkgItem) treeElement; - - if (!mCheckFilterObsolete.getSelection()) { - if (item.isObsolete()) { - return false; - } - } - - if (!mCheckFilterInstalled.getSelection()) { - if (item.getState() == PkgState.INSTALLED) { - return false; - } - } - - if (!mCheckFilterNew.getSelection()) { - if (item.getState() == PkgState.NEW || item.hasUpdatePkg()) { - return false; - } - } - } - - return true; - } - - /** - * Performs the initial expansion of the tree. This expands categories that contain - * at least one installed item and collapses the ones with nothing installed. - * - * TODO: change this to only change the expanded state on categories that have not - * been touched by the user yet. Once we do that, call this every time a new source - * is added or the list is reloaded. - */ - private void expandInitial(Object elem) { - if (elem == null) { - return; - } - if (mTreeViewer != null && !mTreeViewer.getTree().isDisposed()) { - - boolean enablePreviews = - mImpl.mUpdaterData.getSettingsController().getSettings().getEnablePreviews(); - - mTreeViewer.setExpandedState(elem, true); - nextCategory: for (Object pkg : - ((ITreeContentProvider) mTreeViewer.getContentProvider()). - getChildren(elem)) { - if (pkg instanceof PkgCategory) { - PkgCategory cat = (PkgCategory) pkg; - - // Always expand the Tools category (and the preview one, if enabled) - if (cat.getKey().equals(PkgCategoryApi.KEY_TOOLS) || - (enablePreviews && - cat.getKey().equals(PkgCategoryApi.KEY_TOOLS_PREVIEW))) { - expandInitial(pkg); - continue nextCategory; - } - - - for (PkgItem item : cat.getItems()) { - if (item.getState() == PkgState.INSTALLED) { - expandInitial(pkg); - continue nextCategory; - } - } - } - } - } - } - - /** - * Handle checking and unchecking of the tree items. - * - * When unchecking, all sub-tree items checkboxes are cleared too. - * When checking a source, all of its packages are checked too. - * When checking a package, only its compatible archives are checked. - */ - private void onTreeCheckStateChanged(CheckStateChangedEvent event) { - boolean checked = event.getChecked(); - Object elem = event.getElement(); - - assert event.getSource() == mTreeViewer; - - // When selecting, we want to only select compatible archives and expand the super nodes. - checkAndExpandItem(elem, checked, true/*fixChildren*/, true/*fixParent*/); - updateButtonsState(); - } - - private void onTreeDoubleClick(DoubleClickEvent event) { - assert event.getSource() == mTreeViewer; - ISelection sel = event.getSelection(); - if (sel.isEmpty() || !(sel instanceof ITreeSelection)) { - return; - } - ITreeSelection tsel = (ITreeSelection) sel; - Object elem = tsel.getFirstElement(); - if (elem == null) { - return; - } - - ITreeContentProvider provider = - (ITreeContentProvider) mTreeViewer.getContentProvider(); - Object[] children = provider.getElements(elem); - if (children == null) { - return; - } - - if (children.length > 0) { - // If the element has children, expand/collapse it. - if (mTreeViewer.getExpandedState(elem)) { - mTreeViewer.collapseToLevel(elem, 1); - } else { - mTreeViewer.expandToLevel(elem, 1); - } - } else { - // If the element is a terminal one, select/deselect it. - checkAndExpandItem( - elem, - !mTreeViewer.getChecked(elem), - false /*fixChildren*/, - true /*fixParent*/); - updateButtonsState(); - } - } - - private void checkAndExpandItem( - Object elem, - boolean checked, - boolean fixChildren, - boolean fixParent) { - ITreeContentProvider provider = - (ITreeContentProvider) mTreeViewer.getContentProvider(); - - // fix the item itself - if (checked != mTreeViewer.getChecked(elem)) { - mTreeViewer.setChecked(elem, checked); - } - if (elem instanceof PkgItem) { - // update the PkgItem to reflect the selection - ((PkgItem) elem).setChecked(checked); - } - - if (!checked) { - if (fixChildren) { - // when de-selecting, we deselect all children too - mTreeViewer.setSubtreeChecked(elem, checked); - for (Object child : provider.getChildren(elem)) { - checkAndExpandItem(child, checked, fixChildren, false/*fixParent*/); - } - } - - // fix the parent when deselecting - if (fixParent) { - Object parent = provider.getParent(elem); - if (parent != null && mTreeViewer.getChecked(parent)) { - mTreeViewer.setChecked(parent, false); - } - } - return; - } - - // When selecting, we also select sub-items (for a category) - if (fixChildren) { - if (elem instanceof PkgCategory || elem instanceof PkgItem) { - Object[] children = provider.getChildren(elem); - for (Object child : children) { - checkAndExpandItem(child, true, fixChildren, false/*fixParent*/); - } - // only fix the parent once the last sub-item is set - if (elem instanceof PkgCategory) { - if (children.length > 0) { - checkAndExpandItem( - children[0], true, false/*fixChildren*/, true/*fixParent*/); - } else { - mTreeViewer.setChecked(elem, false); - } - } - } else if (elem instanceof Package) { - // in details mode, we auto-select compatible packages - selectCompatibleArchives(elem, provider); - } - } - - if (fixParent && checked && elem instanceof PkgItem) { - Object parent = provider.getParent(elem); - if (!mTreeViewer.getChecked(parent)) { - Object[] children = provider.getChildren(parent); - boolean allChecked = children.length > 0; - for (Object e : children) { - if (!mTreeViewer.getChecked(e)) { - allChecked = false; - break; - } - } - if (allChecked) { - mTreeViewer.setChecked(parent, true); - } - } - } - } - - private void selectCompatibleArchives(Object pkg, ITreeContentProvider provider) { - for (Object archive : provider.getChildren(pkg)) { - if (archive instanceof Archive) { - mTreeViewer.setChecked(archive, ((Archive) archive).isCompatible()); - } - } - } - - /** - * Checks all PkgItems that are either new or have updates or select top platform - * for initial run. - */ - private void onSelectNewUpdates(boolean selectNew, boolean selectUpdates, boolean selectTop) { - // This will update the tree's "selected" state and then invoke syncViewerSelection() - // which will in turn update tree. - mImpl.onSelectNewUpdates(selectNew, selectUpdates, selectTop); - } - - /** - * Deselect all checked PkgItems. - */ - private void onDeselectAll() { - // This does not update the tree itself, syncViewerSelection does it below. - mImpl.onDeselectAll(); - syncViewerSelection(); - } - - /** - * When switching between the tree-by-api and the tree-by-source, copy the selection - * (aka the checked items) from one list to the other. - * This does not update the tree itself. - */ - private void copySelection(boolean fromSourceToApi) { - List<PkgItem> fromItems = - mImpl.mDiffLogic.getAllPkgItems(!fromSourceToApi, fromSourceToApi); - List<PkgItem> toItems = - mImpl.mDiffLogic.getAllPkgItems(fromSourceToApi, !fromSourceToApi); - - // deselect all targets - for (PkgItem item : toItems) { - item.setChecked(false); - } - - // mark new one from the source - for (PkgItem source : fromItems) { - if (source.isChecked()) { - // There should typically be a corresponding item in the target side - for (PkgItem target : toItems) { - if (target.isSameMainPackageAs(source.getMainPackage())) { - target.setChecked(true); - break; - } - } - } - } - } - - /** - * Synchronize the 'checked' state of PkgItems in the tree with their internal isChecked state. - */ - private void syncViewerSelection() { - ITreeContentProvider provider = (ITreeContentProvider) mTreeViewer.getContentProvider(); - - Object input = mTreeViewer.getInput(); - if (input != null) { - for (Object cat : provider.getElements(input)) { - Object[] children = provider.getElements(cat); - boolean allChecked = children.length > 0; - for (Object child : children) { - if (child instanceof PkgItem) { - PkgItem item = (PkgItem) child; - boolean checked = item.isChecked(); - allChecked &= checked; - - if (checked != mTreeViewer.getChecked(item)) { - if (checked) { - if (!mTreeViewer.getExpandedState(cat)) { - mTreeViewer.setExpandedState(cat, true); - } - } - checkAndExpandItem( - item, - checked, - true/*fixChildren*/, - false/*fixParent*/); - } - } - } - - if (allChecked != mTreeViewer.getChecked(cat)) { - mTreeViewer.setChecked(cat, allChecked); - } - } - } - - updateButtonsState(); - } - - /** - * Indicate an install/delete operation is pending. - * This disables the install/delete buttons. - * Use {@link #endOperationPending()} to revert, typically in a {@code try..finally} block. - */ - private void beginOperationPending() { - mOperationPending = true; - updateButtonsState(); - } - - private void endOperationPending() { - mOperationPending = false; - updateButtonsState(); - } - - /** - * Updates the Install and Delete Package buttons. - */ - private void updateButtonsState() { - if (!mButtonInstall.isDisposed()) { - int numPackages = getArchivesForInstall(null /*archives*/); - - mButtonInstall.setEnabled((numPackages > 0) && !mOperationPending); - mButtonInstall.setText( - numPackages == 0 ? "Install packages..." : // disabled button case - numPackages == 1 ? "Install 1 package..." : - String.format("Install %d packages...", numPackages)); - } - - if (!mButtonDelete.isDisposed()) { - // We can only delete local archives - int numPackages = getArchivesToDelete(null /*outMsg*/, null /*outArchives*/); - - mButtonDelete.setEnabled((numPackages > 0) && !mOperationPending); - mButtonDelete.setText( - numPackages == 0 ? "Delete packages..." : // disabled button case - numPackages == 1 ? "Delete 1 package..." : - String.format("Delete %d packages...", numPackages)); - } - } - - /** - * Called when the Install Package button is selected. - * Collects the packages to be installed and shows the installation window. - */ - private void onButtonInstall() { - ArrayList<Archive> archives = new ArrayList<Archive>(); - getArchivesForInstall(archives); - - if (mImpl.mUpdaterData != null) { - boolean needsRefresh = false; - try { - beginOperationPending(); - - List<Archive> installed = mImpl.mUpdaterData.updateOrInstallAll_WithGUI( - archives, - mCheckFilterObsolete.getSelection() /* includeObsoletes */, - mContext == SdkInvocationContext.IDE ? - UpdaterData.TOOLS_MSG_UPDATED_FROM_ADT : - UpdaterData.TOOLS_MSG_UPDATED_FROM_SDKMAN); - needsRefresh = installed != null && !installed.isEmpty(); - } finally { - endOperationPending(); - - if (needsRefresh) { - // The local package list has changed, make sure to refresh it - mImpl.localReload(); - } - } - } - } - - /** - * Selects the archives that can be installed. - * This can be used with a null {@code outArchives} just to count the number of - * installable archives. - * - * @param outArchives An archive list where to add the archives that can be installed. - * This can be null. - * @return The number of archives that can be installed. - */ - private int getArchivesForInstall(List<Archive> outArchives) { - if (mTreeViewer == null || - mTreeViewer.getTree() == null || - mTreeViewer.getTree().isDisposed()) { - return 0; - } - Object[] checked = mTreeViewer.getCheckedElements(); - if (checked == null) { - return 0; - } - - int count = 0; - - // Give us a way to force install of incompatible archives. - boolean checkIsCompatible = - System.getenv(ArchiveInstaller.ENV_VAR_IGNORE_COMPAT) == null; - - if (mDisplayArchives) { - // In detail mode, we display archives so we can install only the - // archives that are actually selected. - - for (Object c : checked) { - if (c instanceof Archive) { - Archive a = (Archive) c; - if (a != null) { - if (checkIsCompatible && !a.isCompatible()) { - continue; - } - count++; - if (outArchives != null) { - outArchives.add((Archive) c); - } - } - } - } - } else { - // In non-detail mode, we install all the compatible archives - // found in the selected pkg items. We also automatically - // select update packages rather than the root package if any. - - for (Object c : checked) { - Package p = null; - if (c instanceof Package) { - // This is an update package - p = (Package) c; - } else if (c instanceof PkgItem) { - p = ((PkgItem) c).getMainPackage(); - - PkgItem pi = (PkgItem) c; - if (pi.getState() == PkgState.INSTALLED) { - // We don't allow installing items that are already installed - // unless they have a pending update. - p = pi.getUpdatePkg(); - - } else if (pi.getState() == PkgState.NEW) { - p = pi.getMainPackage(); - } - } - if (p != null) { - for (Archive a : p.getArchives()) { - if (a != null) { - if (checkIsCompatible && !a.isCompatible()) { - continue; - } - count++; - if (outArchives != null) { - outArchives.add(a); - } - } - } - } - } - } - - return count; - } - - /** - * Called when the Delete Package button is selected. - * Collects the packages to be deleted, prompt the user for confirmation - * and actually performs the deletion. - */ - private void onButtonDelete() { - final String title = "Delete SDK Package"; - StringBuilder msg = new StringBuilder("Are you sure you want to delete:"); - - // A list of archives to delete - final ArrayList<Archive> archives = new ArrayList<Archive>(); - - getArchivesToDelete(msg, archives); - - if (!archives.isEmpty()) { - msg.append("\n").append("This cannot be undone."); //$NON-NLS-1$ - if (MessageDialog.openQuestion(getShell(), title, msg.toString())) { - try { - beginOperationPending(); - - mImpl.mUpdaterData.getTaskFactory().start("Delete Package", new ITask() { - @Override - public void run(ITaskMonitor monitor) { - monitor.setProgressMax(archives.size() + 1); - for (Archive a : archives) { - monitor.setDescription("Deleting '%1$s' (%2$s)", - a.getParentPackage().getShortDescription(), - a.getLocalOsPath()); - - // Delete the actual package - a.deleteLocal(); - - monitor.incProgress(1); - if (monitor.isCancelRequested()) { - break; - } - } - - monitor.incProgress(1); - monitor.setDescription("Done"); - } - }); - } finally { - endOperationPending(); - - // The local package list has changed, make sure to refresh it - mImpl.localReload(); - } - } - } - } - - /** - * Selects the archives that can be deleted and collect their names. - * This can be used with a null {@code outArchives} and a null {@code outMsg} - * just to count the number of archives to be deleted. - * - * @param outMsg A StringBuilder where the names of the packages to be deleted is - * accumulated. This is used to confirm deletion with the user. - * @param outArchives An archive list where to add the archives that can be installed. - * This can be null. - * @return The number of archives that can be deleted. - */ - private int getArchivesToDelete(StringBuilder outMsg, List<Archive> outArchives) { - if (mTreeViewer == null || - mTreeViewer.getTree() == null || - mTreeViewer.getTree().isDisposed()) { - return 0; - } - Object[] checked = mTreeViewer.getCheckedElements(); - if (checked == null) { - // This should not happen since the button should be disabled - return 0; - } - - int count = 0; - - if (mDisplayArchives) { - // In detail mode, select archives that can be deleted - - for (Object c : checked) { - if (c instanceof Archive) { - Archive a = (Archive) c; - if (a != null && a.isLocal()) { - count++; - if (outMsg != null) { - String osPath = a.getLocalOsPath(); - File dir = new File(osPath); - Package p = a.getParentPackage(); - if (p != null && dir.isDirectory()) { - outMsg.append("\n - ") //$NON-NLS-1$ - .append(p.getShortDescription()); - } - } - if (outArchives != null) { - outArchives.add(a); - } - } - } - } - } else { - // In non-detail mode, select archives of selected packages that can be deleted. - - for (Object c : checked) { - if (c instanceof PkgItem) { - PkgItem pi = (PkgItem) c; - PkgState state = pi.getState(); - if (state == PkgState.INSTALLED) { - Package p = pi.getMainPackage(); - - for (Archive a : p.getArchives()) { - if (a != null && a.isLocal()) { - count++; - if (outMsg != null) { - String osPath = a.getLocalOsPath(); - File dir = new File(osPath); - if (dir.isDirectory()) { - outMsg.append("\n - ") //$NON-NLS-1$ - .append(p.getShortDescription()); - } - } - if (outArchives != null) { - outArchives.add(a); - } - } - } - } - } - } - } - - return count; - } - - // ---------------------- - - - // --- Implementation of ISdkChangeListener --- - - @Override - public void onSdkLoaded() { - onSdkReload(); - } - - @Override - public void onSdkReload() { - // The sdkmanager finished reloading its data. We must not call localReload() from here - // since we don't want to alter the sdkmanager's data that just finished loading. - mImpl.loadPackages(); - } - - @Override - public void preInstallHook() { - // nothing to be done for now. - } - - @Override - public void postInstallHook() { - // nothing to be done for now. - } - - - // --- End of hiding from SWT Designer --- - //$hide<<$ -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PackagesPageIcons.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PackagesPageIcons.java deleted file mode 100755 index 4fe8fca..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PackagesPageIcons.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2012 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.repository.ui; - - -/** - * Icons used by {@link PackagesPage}. - */ -public class PackagesPageIcons { - - public static final String ICON_CAT_OTHER = "pkgcat_other_16.png"; //$NON-NLS-1$ - public static final String ICON_CAT_PLATFORM = "pkgcat_16.png"; //$NON-NLS-1$ - public static final String ICON_SORT_BY_SOURCE = "source_icon16.png"; //$NON-NLS-1$ - public static final String ICON_SORT_BY_API = "platform_pkg_16.png"; //$NON-NLS-1$ - public static final String ICON_PKG_NEW = "pkg_new_16.png"; //$NON-NLS-1$ - public static final String ICON_PKG_INCOMPAT = "pkg_incompat_16.png"; //$NON-NLS-1$ - public static final String ICON_PKG_UPDATE = "pkg_update_16.png"; //$NON-NLS-1$ - public static final String ICON_PKG_INSTALLED = "pkg_installed_16.png"; //$NON-NLS-1$ -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PackagesPageImpl.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PackagesPageImpl.java deleted file mode 100755 index 96d9db2..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PackagesPageImpl.java +++ /dev/null @@ -1,574 +0,0 @@ -/* - * Copyright (C) 2012 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.repository.ui; - -import com.android.SdkConstants; -import com.android.sdklib.internal.repository.DownloadCache; -import com.android.sdklib.internal.repository.DownloadCache.Strategy; -import com.android.sdklib.internal.repository.IDescription; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdkuilib.internal.repository.UpdaterData; -import com.android.sdkuilib.internal.repository.core.PackageLoader; -import com.android.sdkuilib.internal.repository.core.PackageLoader.ISourceLoadedCallback; -import com.android.sdkuilib.internal.repository.core.PackagesDiffLogic; -import com.android.sdkuilib.internal.repository.core.PkgCategory; -import com.android.sdkuilib.internal.repository.core.PkgCategoryApi; -import com.android.sdkuilib.internal.repository.core.PkgContentProvider; -import com.android.sdkuilib.internal.repository.core.PkgItem; -import com.android.sdkuilib.internal.repository.core.PkgItem.PkgState; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; - -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.IInputProvider; -import org.eclipse.jface.viewers.ITableFontProvider; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.List; - -/** - * Base class for {@link PackagesPage} that holds most of the logic to display - * the tree/list of packages. This class holds most of the logic and {@link PackagesPage} - * holds most of the UI (creating the UI, dealing with menus and buttons and tree - * selection.) This makes it easier to test the functionality by mocking only a - * subset of the UI. - */ -abstract class PackagesPageImpl { - - final UpdaterData mUpdaterData; - final PackagesDiffLogic mDiffLogic; - - private ICheckboxTreeViewer mITreeViewer; - private ITreeViewerColumn mIColumnName; - private ITreeViewerColumn mIColumnApi; - private ITreeViewerColumn mIColumnRevision; - private ITreeViewerColumn mIColumnStatus; - - PackagesPageImpl(UpdaterData updaterData) { - mUpdaterData = updaterData; - mDiffLogic = new PackagesDiffLogic(updaterData); - } - - /** - * Utility method that derived classes can override to check whether the UI is disposed. - * When the UI is disposed, most operations that affect the UI will be bypassed. - * @return True if UI is not available and should not be touched. - */ - abstract protected boolean isUiDisposed(); - - /** - * Utility method to execute a runnable on the main UI thread. - * Will do nothing if {@link #isUiDisposed()} returns false. - * @param runnable The runnable to execute on the main UI thread. - */ - abstract protected void syncExec(Runnable runnable); - - /** - * Synchronizes the 'checked' state of PkgItems in the tree with their internal isChecked state. - */ - abstract protected void syncViewerSelection(); - - void performFirstLoad() { - // First a package loader is created that only checks - // the local cache xml files. It populates the package - // list based on what the client got last, essentially. - loadPackages(true /*useLocalCache*/, false /*overrideExisting*/); - - // Next a regular package loader is created that will - // respect the expiration and refresh parameters of the - // download cache. - loadPackages(false /*useLocalCache*/, true /*overrideExisting*/); - } - - public void setITreeViewer(ICheckboxTreeViewer iTreeViewer) { - mITreeViewer = iTreeViewer; - } - - public void setIColumns( - ITreeViewerColumn columnName, - ITreeViewerColumn columnApi, - ITreeViewerColumn columnRevision, - ITreeViewerColumn columnStatus) { - mIColumnName = columnName; - mIColumnApi = columnApi; - mIColumnRevision = columnRevision; - mIColumnStatus = columnStatus; - } - - void postCreate() { - // Caller needs to call setITreeViewer before this. - assert mITreeViewer != null; - // Caller needs to call setIColumns before this. - assert mIColumnApi != null; - assert mIColumnName != null; - assert mIColumnStatus != null; - assert mIColumnRevision != null; - - mITreeViewer.setContentProvider(new PkgContentProvider(mITreeViewer)); - - mIColumnApi.setLabelProvider( - new PkgTreeColumnViewerLabelProvider(new PkgCellLabelProvider(mIColumnApi))); - mIColumnName.setLabelProvider( - new PkgTreeColumnViewerLabelProvider(new PkgCellLabelProvider(mIColumnName))); - mIColumnStatus.setLabelProvider( - new PkgTreeColumnViewerLabelProvider(new PkgCellLabelProvider(mIColumnStatus))); - mIColumnRevision.setLabelProvider( - new PkgTreeColumnViewerLabelProvider(new PkgCellLabelProvider(mIColumnRevision))); - } - - /** - * Performs a full reload by removing all cached packages data, including the platforms - * and addons from the sdkmanager instance. This will perform a full local parsing - * as well as a full reload of the remote data (by fetching all sources again.) - */ - void fullReload() { - // Clear all source information, forcing them to be refreshed. - mUpdaterData.getSources().clearAllPackages(); - // Clear and reload all local data too. - localReload(); - } - - /** - * Performs a full reload of all the local package information, including the platforms - * and addons from the sdkmanager instance. This will perform a full local parsing. - * <p/> - * This method does NOT force a new fetch of the remote sources. - * - * @see #fullReload() - */ - void localReload() { - // Clear all source caches, otherwise loading will use the cached data - mUpdaterData.getLocalSdkParser().clearPackages(); - mUpdaterData.getSdkManager().reloadSdk(mUpdaterData.getSdkLog()); - loadPackages(); - } - - /** - * Performs a "normal" reload of the package information, use the default download - * cache and refreshing strategy as needed. - */ - void loadPackages() { - loadPackages(false /*useLocalCache*/, false /*overrideExisting*/); - } - - /** - * Performs a reload of the package information. - * - * @param useLocalCache When true, the {@link PackageLoader} is switched to use - * a specific {@link DownloadCache} using the {@link Strategy#ONLY_CACHE}, meaning - * it will only use data from the local cache. It will not try to fetch or refresh - * manifests. This is used once the very first time the sdk manager window opens - * and is typically followed by a regular load with refresh. - */ - abstract protected void loadPackages(boolean useLocalCache, boolean overrideExisting); - - /** - * Actual implementation of {@link #loadPackages(boolean, boolean)}. - * Derived implementations must call this to do the actual work after setting up the UI. - */ - void loadPackagesImpl(final boolean useLocalCache, final boolean overrideExisting) { - if (mUpdaterData == null) { - return; - } - - final boolean displaySortByApi = isSortByApi(); - - PackageLoader packageLoader = getPackageLoader(useLocalCache); - assert packageLoader != null; - - mDiffLogic.updateStart(); - packageLoader.loadPackages(overrideExisting, new ISourceLoadedCallback() { - @Override - public boolean onUpdateSource(SdkSource source, Package[] newPackages) { - // This runs in a thread and must not access UI directly. - final boolean changed = mDiffLogic.updateSourcePackages( - displaySortByApi, source, newPackages); - - syncExec(new Runnable() { - @Override - public void run() { - if (changed || - mITreeViewer.getInput() != mDiffLogic.getCategories(isSortByApi())) { - refreshViewerInput(); - } - } - }); - - // Return true to tell the loader to continue with the next source. - // Return false to stop the loader if any UI has been disposed, which can - // happen if the user is trying to close the window during the load operation. - return !isUiDisposed(); - } - - @Override - public void onLoadCompleted() { - // This runs in a thread and must not access UI directly. - final boolean changed = mDiffLogic.updateEnd(displaySortByApi); - - syncExec(new Runnable() { - @Override - public void run() { - if (changed || - mITreeViewer.getInput() != mDiffLogic.getCategories(isSortByApi())) { - try { - refreshViewerInput(); - } catch (Exception ignore) {} - } - - if (!useLocalCache && - mDiffLogic.isFirstLoadComplete() && - !isUiDisposed()) { - // At the end of the first load, if nothing is selected then - // automatically select all new and update packages. - Object[] checked = mITreeViewer.getCheckedElements(); - if (checked == null || checked.length == 0) { - onSelectNewUpdates( - false, //selectNew - true, //selectUpdates, - true); //selectTop - } - } - } - }); - } - }); - } - - /** - * Used by {@link #loadPackagesImpl(boolean, boolean)} to get the package - * loader for the first or second pass update. When starting the manager - * starts with a first pass that reads only from the local cache, with no - * extra network access. That's {@code useLocalCache} being true. - * <p/> - * Leter it does a second pass with {@code useLocalCache} set to false - * and actually uses the download cache specified in {@link UpdaterData}. - * - * This is extracted so that we can control this cache via unit tests. - */ - protected PackageLoader getPackageLoader(boolean useLocalCache) { - if (useLocalCache) { - return new PackageLoader(mUpdaterData, new DownloadCache(Strategy.ONLY_CACHE)); - } else { - return mUpdaterData.getPackageLoader(); - } - } - - /** - * Overridden by the UI to respond to a request to refresh the tree viewer - * when the input has changed. - * The implementation must call {@link #setViewerInput()} somehow and will - * also need to adjust the expand state of the tree items and/or update - * some buttons or other state. - */ - abstract protected void refreshViewerInput(); - - /** - * Invoked from {@link #refreshViewerInput()} to actually either set the - * input of the tree viewer or refresh it if it's the <em>same</em> input - * object. - */ - protected void setViewerInput() { - List<PkgCategory> cats = mDiffLogic.getCategories(isSortByApi()); - if (mITreeViewer.getInput() != cats) { - // set initial input - mITreeViewer.setInput(cats); - } else { - // refresh existing, which preserves the expanded state, the selection - // and the checked state. - mITreeViewer.refresh(); - } - } - - /** - * Overridden by the UI to determine if the tree should display packages sorted - * by API (returns true) or by repository source (returns false.) - */ - abstract protected boolean isSortByApi(); - - /** - * Checks all PkgItems that are either new or have updates or select top platform - * for initial run. - */ - void onSelectNewUpdates(boolean selectNew, boolean selectUpdates, boolean selectTop) { - // This does not update the tree itself, syncViewerSelection does it in the caller. - mDiffLogic.checkNewUpdateItems( - selectNew, - selectUpdates, - selectTop, - SdkConstants.CURRENT_PLATFORM); - syncViewerSelection(); - } - - /** - * Deselect all checked PkgItems. - */ - void onDeselectAll() { - // This does not update the tree itself, syncViewerSelection does it in the caller. - mDiffLogic.uncheckAllItems(); - } - - // ---------------------- - - abstract protected Font getTreeFontItalic(); - - class PkgCellLabelProvider extends ColumnLabelProvider implements ITableFontProvider { - - private final ITreeViewerColumn mColumn; - - public PkgCellLabelProvider(ITreeViewerColumn column) { - super(); - mColumn = column; - } - - @Override - public String getText(Object element) { - - if (mColumn == mIColumnName) { - if (element instanceof PkgCategory) { - return ((PkgCategory) element).getLabel(); - } else if (element instanceof PkgItem) { - return getPkgItemName((PkgItem) element); - } else if (element instanceof IDescription) { - return ((IDescription) element).getShortDescription(); - } - - } else if (mColumn == mIColumnApi) { - int api = -1; - if (element instanceof PkgItem) { - api = ((PkgItem) element).getApi(); - } - if (api >= 1) { - return Integer.toString(api); - } - - } else if (mColumn == mIColumnRevision) { - if (element instanceof PkgItem) { - PkgItem pkg = (PkgItem) element; - return pkg.getRevision().toShortString(); - } - - } else if (mColumn == mIColumnStatus) { - if (element instanceof PkgItem) { - PkgItem pkg = (PkgItem) element; - - switch(pkg.getState()) { - case INSTALLED: - Package update = pkg.getUpdatePkg(); - if (update != null) { - return String.format( - "Update available: rev. %1$s", - update.getRevision().toShortString()); - } - return "Installed"; - - case NEW: - Package p = pkg.getMainPackage(); - if (p != null && p.hasCompatibleArchive()) { - return "Not installed"; - } else { - return String.format("Not compatible with %1$s", - SdkConstants.currentPlatformName()); - } - } - return pkg.getState().toString(); - - } else if (element instanceof Package) { - // This is an update package. - return "New revision " + ((Package) element).getRevision().toShortString(); - } - } - - return ""; //$NON-NLS-1$ - } - - private String getPkgItemName(PkgItem item) { - String name = item.getName().trim(); - - if (isSortByApi()) { - // When sorting by API, the package name might contains the API number - // or the platform name at the end. If we find it, cut it out since it's - // redundant. - - PkgCategoryApi cat = (PkgCategoryApi) findCategoryForItem(item); - String apiLabel = cat.getApiLabel(); - String platLabel = cat.getPlatformName(); - - if (platLabel != null && name.endsWith(platLabel)) { - return name.substring(0, name.length() - platLabel.length()); - - } else if (apiLabel != null && name.endsWith(apiLabel)) { - return name.substring(0, name.length() - apiLabel.length()); - - } else if (platLabel != null && item.isObsolete() && name.indexOf(platLabel) > 0) { - // For obsolete items, the format is "<base name> <platform name> (Obsolete)" - // so in this case only accept removing a platform name that is not at - // the end. - name = name.replace(platLabel, ""); //$NON-NLS-1$ - } - } - - // Collapse potential duplicated spacing - name = name.replaceAll(" +", " "); //$NON-NLS-1$ //$NON-NLS-2$ - - return name; - } - - private PkgCategory findCategoryForItem(PkgItem item) { - List<PkgCategory> cats = mDiffLogic.getCategories(isSortByApi()); - for (PkgCategory cat : cats) { - for (PkgItem i : cat.getItems()) { - if (i == item) { - return cat; - } - } - } - - return null; - } - - @Override - public Image getImage(Object element) { - ImageFactory imgFactory = mUpdaterData.getImageFactory(); - - if (imgFactory != null) { - if (mColumn == mIColumnName) { - if (element instanceof PkgCategory) { - return imgFactory.getImageForObject(((PkgCategory) element).getIconRef()); - } else if (element instanceof PkgItem) { - return imgFactory.getImageForObject(((PkgItem) element).getMainPackage()); - } - return imgFactory.getImageForObject(element); - - } else if (mColumn == mIColumnStatus && element instanceof PkgItem) { - PkgItem pi = (PkgItem) element; - switch(pi.getState()) { - case INSTALLED: - if (pi.hasUpdatePkg()) { - return imgFactory.getImageByName(PackagesPageIcons.ICON_PKG_UPDATE); - } else { - return imgFactory.getImageByName(PackagesPageIcons.ICON_PKG_INSTALLED); - } - case NEW: - Package p = pi.getMainPackage(); - if (p != null && p.hasCompatibleArchive()) { - return imgFactory.getImageByName(PackagesPageIcons.ICON_PKG_NEW); - } else { - return imgFactory.getImageByName(PackagesPageIcons.ICON_PKG_INCOMPAT); - } - } - } - } - return super.getImage(element); - } - - // -- ITableFontProvider - - @Override - public Font getFont(Object element, int columnIndex) { - if (element instanceof PkgItem) { - if (((PkgItem) element).getState() == PkgState.NEW) { - return getTreeFontItalic(); - } - } else if (element instanceof Package) { - // update package - return getTreeFontItalic(); - } - return super.getFont(element); - } - - // -- Tooltip support - - @Override - public String getToolTipText(Object element) { - PkgItem pi = element instanceof PkgItem ? (PkgItem) element : null; - if (pi != null) { - element = pi.getMainPackage(); - } - if (element instanceof IDescription) { - String s = getTooltipDescription((IDescription) element); - - if (pi != null && pi.hasUpdatePkg()) { - s += "\n-----------------" + //$NON-NLS-1$ - "\nUpdate Available:\n" + //$NON-NLS-1$ - getTooltipDescription(pi.getUpdatePkg()); - } - - return s; - } - return super.getToolTipText(element); - } - - private String getTooltipDescription(IDescription element) { - String s = element.getLongDescription(); - if (element instanceof Package) { - Package p = (Package) element; - - if (!p.isLocal()) { - // For non-installed item, try to find a download size - for (Archive a : p.getArchives()) { - if (!a.isLocal() && a.isCompatible()) { - s += '\n' + a.getSizeDescription(); - break; - } - } - } - - // Display info about where this package comes/came from - SdkSource src = p.getParentSource(); - if (src != null) { - try { - URL url = new URL(src.getUrl()); - String host = url.getHost(); - if (p.isLocal()) { - s += String.format("\nInstalled from %1$s", host); - } else { - s += String.format("\nProvided by %1$s", host); - } - } catch (MalformedURLException ignore) { - } - } - } - return s; - } - - @Override - public Point getToolTipShift(Object object) { - return new Point(15, 5); - } - - @Override - public int getToolTipDisplayDelayTime(Object object) { - return 500; - } - } - - interface ICheckboxTreeViewer extends IInputProvider { - void setContentProvider(PkgContentProvider pkgContentProvider); - void refresh(); - void setInput(List<PkgCategory> cats); - Object[] getCheckedElements(); - } - - interface ITreeViewerColumn { - void setLabelProvider(ColumnLabelProvider labelProvider); - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PkgTreeColumnViewerLabelProvider.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PkgTreeColumnViewerLabelProvider.java deleted file mode 100755 index 3323104..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PkgTreeColumnViewerLabelProvider.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2012 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.repository.ui; - -import org.eclipse.jface.viewers.CellLabelProvider; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.TreeColumnViewerLabelProvider; -import org.eclipse.jface.viewers.TreePath; -import org.eclipse.jface.viewers.TreeViewerColumn; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; - -/** - * A custom version of {@link TreeColumnViewerLabelProvider} which - * handles {@link TreePath}s and delegates content to the given - * {@link ColumnLabelProvider} for a given {@link TreeViewerColumn}. - * <p/> - * The implementation handles a variety of providers (table label, table - * color, table font) but does not implement a tooltip provider, so we - * delegate the calls here to the appropriate {@link ColumnLabelProvider}. - * <p/> - * Only {@link #getToolTipText(Object)} is really useful for us but we - * delegate all the tooltip calls for completeness and avoid surprises later - * if we ever decide to override more things in the label provider. - */ -class PkgTreeColumnViewerLabelProvider extends TreeColumnViewerLabelProvider { - - private CellLabelProvider mTooltipProvider; - - public PkgTreeColumnViewerLabelProvider(ColumnLabelProvider columnLabelProvider) { - super(columnLabelProvider); - } - - @Override - public void setProviders(Object provider) { - super.setProviders(provider); - if (provider instanceof CellLabelProvider) { - mTooltipProvider = (CellLabelProvider) provider; - } - } - - @Override - public Image getToolTipImage(Object object) { - if (mTooltipProvider != null) { - return mTooltipProvider.getToolTipImage(object); - } - return super.getToolTipImage(object); - } - - @Override - public String getToolTipText(Object element) { - if (mTooltipProvider != null) { - return mTooltipProvider.getToolTipText(element); - } - return super.getToolTipText(element); - } - - @Override - public Color getToolTipBackgroundColor(Object object) { - if (mTooltipProvider != null) { - return mTooltipProvider.getToolTipBackgroundColor(object); - } - return super.getToolTipBackgroundColor(object); - } - - @Override - public Color getToolTipForegroundColor(Object object) { - if (mTooltipProvider != null) { - return mTooltipProvider.getToolTipForegroundColor(object); - } - return super.getToolTipForegroundColor(object); - } - - @Override - public Font getToolTipFont(Object object) { - if (mTooltipProvider != null) { - return mTooltipProvider.getToolTipFont(object); - } - return super.getToolTipFont(object); - } - - @Override - public Point getToolTipShift(Object object) { - if (mTooltipProvider != null) { - return mTooltipProvider.getToolTipShift(object); - } - return super.getToolTipShift(object); - } - - @Override - public boolean useNativeToolTip(Object object) { - if (mTooltipProvider != null) { - return mTooltipProvider.useNativeToolTip(object); - } - return super.useNativeToolTip(object); - } - - @Override - public int getToolTipTimeDisplayed(Object object) { - if (mTooltipProvider != null) { - return mTooltipProvider.getToolTipTimeDisplayed(object); - } - return super.getToolTipTimeDisplayed(object); - } - - @Override - public int getToolTipDisplayDelayTime(Object object) { - if (mTooltipProvider != null) { - return mTooltipProvider.getToolTipDisplayDelayTime(object); - } - return super.getToolTipDisplayDelayTime(object); - } - - @Override - public int getToolTipStyle(Object object) { - if (mTooltipProvider != null) { - return mTooltipProvider.getToolTipStyle(object); - } - return super.getToolTipStyle(object); - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/SdkUpdaterWindowImpl2.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/SdkUpdaterWindowImpl2.java deleted file mode 100755 index ae1bf6b..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/SdkUpdaterWindowImpl2.java +++ /dev/null @@ -1,590 +0,0 @@ -/* - * Copyright (C) 2011 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.repository.ui; - - -import com.android.SdkConstants; -import com.android.sdklib.internal.repository.ITaskFactory; -import com.android.sdklib.internal.repository.sources.SdkSourceProperties; -import com.android.sdkuilib.internal.repository.AboutDialog; -import com.android.sdkuilib.internal.repository.ISdkUpdaterWindow; -import com.android.sdkuilib.internal.repository.MenuBarWrapper; -import com.android.sdkuilib.internal.repository.SettingsController; -import com.android.sdkuilib.internal.repository.SettingsController.Settings; -import com.android.sdkuilib.internal.repository.SettingsDialog; -import com.android.sdkuilib.internal.repository.UpdaterData; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.internal.repository.ui.PackagesPage.MenuAction; -import com.android.sdkuilib.internal.tasks.ILogUiProvider; -import com.android.sdkuilib.internal.tasks.ProgressView; -import com.android.sdkuilib.internal.tasks.ProgressViewFactory; -import com.android.sdkuilib.internal.widgets.ImgDisabledButton; -import com.android.sdkuilib.internal.widgets.ToggleButton; -import com.android.sdkuilib.repository.AvdManagerWindow.AvdInvocationContext; -import com.android.sdkuilib.repository.ISdkChangeListener; -import com.android.sdkuilib.repository.SdkUpdaterWindow.SdkInvocationContext; -import com.android.utils.ILogger; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Menu; -import org.eclipse.swt.widgets.MenuItem; -import org.eclipse.swt.widgets.ProgressBar; -import org.eclipse.swt.widgets.Shell; - -/** - * This is the private implementation of the UpdateWindow - * for the second version of the SDK Manager. - * <p/> - * This window features only one embedded page, the combined installed+available package list. - */ -public class SdkUpdaterWindowImpl2 implements ISdkUpdaterWindow { - - public static final String APP_NAME = "Android SDK Manager"; - private static final String SIZE_POS_PREFIX = "sdkman2"; //$NON-NLS-1$ - - private final Shell mParentShell; - private final SdkInvocationContext mContext; - /** Internal data shared between the window and its pages. */ - private final UpdaterData mUpdaterData; - - // --- UI members --- - - protected Shell mShell; - private PackagesPage mPkgPage; - private ProgressBar mProgressBar; - private Label mStatusText; - private ImgDisabledButton mButtonStop; - private ToggleButton mButtonShowLog; - private SettingsController mSettingsController; - private LogWindow mLogWindow; - - /** - * Creates a new window. Caller must call open(), which will block. - * - * @param parentShell Parent shell. - * @param sdkLog Logger. Cannot be null. - * @param osSdkRoot The OS path to the SDK root. - * @param context The {@link SdkInvocationContext} to change the behavior depending on who's - * opening the SDK Manager. - */ - public SdkUpdaterWindowImpl2( - Shell parentShell, - ILogger sdkLog, - String osSdkRoot, - SdkInvocationContext context) { - mParentShell = parentShell; - mContext = context; - mUpdaterData = new UpdaterData(osSdkRoot, sdkLog); - } - - /** - * Creates a new window. Caller must call open(), which will block. - * <p/> - * This is to be used when the window is opened from {@link AvdManagerWindowImpl1} - * to share the same {@link UpdaterData} structure. - * - * @param parentShell Parent shell. - * @param updaterData The parent's updater data. - * @param context The {@link SdkInvocationContext} to change the behavior depending on who's - * opening the SDK Manager. - */ - public SdkUpdaterWindowImpl2( - Shell parentShell, - UpdaterData updaterData, - SdkInvocationContext context) { - mParentShell = parentShell; - mContext = context; - mUpdaterData = updaterData; - } - - /** - * Opens the window. - * @wbp.parser.entryPoint - */ - @Override - public void open() { - if (mParentShell == null) { - Display.setAppName(APP_NAME); //$hide$ (hide from SWT designer) - } - - createShell(); - preCreateContent(); - createContents(); - createMenuBar(); - createLogWindow(); - mShell.open(); - mShell.layout(); - - if (postCreateContent()) { //$hide$ (hide from SWT designer) - Display display = Display.getDefault(); - while (!mShell.isDisposed()) { - if (!display.readAndDispatch()) { - display.sleep(); - } - } - } - - SdkSourceProperties p = new SdkSourceProperties(); - p.save(); - - dispose(); //$hide$ - } - - private void createShell() { - // The SDK Manager must use a shell trim when standalone - // or a dialog trim when invoked from somewhere else. - int style = SWT.SHELL_TRIM; - if (mContext != SdkInvocationContext.STANDALONE) { - style |= SWT.APPLICATION_MODAL; - } - - mShell = new Shell(mParentShell, style); - mShell.addDisposeListener(new DisposeListener() { - @Override - public void widgetDisposed(DisposeEvent e) { - ShellSizeAndPos.saveSizeAndPos(mShell, SIZE_POS_PREFIX); - onAndroidSdkUpdaterDispose(); //$hide$ (hide from SWT designer) - } - }); - - GridLayout glShell = new GridLayout(2, false); - glShell.verticalSpacing = 0; - glShell.horizontalSpacing = 0; - glShell.marginWidth = 0; - glShell.marginHeight = 0; - mShell.setLayout(glShell); - - mShell.setMinimumSize(new Point(600, 300)); - mShell.setSize(700, 500); - mShell.setText(APP_NAME); - - ShellSizeAndPos.loadSizeAndPos(mShell, SIZE_POS_PREFIX); - } - - private void createContents() { - mPkgPage = new PackagesPage(mShell, SWT.NONE, mUpdaterData, mContext); - mPkgPage.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); - - Composite composite1 = new Composite(mShell, SWT.NONE); - composite1.setLayout(new GridLayout(1, false)); - composite1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); - - mProgressBar = new ProgressBar(composite1, SWT.NONE); - mProgressBar.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); - - mStatusText = new Label(composite1, SWT.NONE); - mStatusText.setText("Status Placeholder"); //$NON-NLS-1$ placeholder - mStatusText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); - - Composite composite2 = new Composite(mShell, SWT.NONE); - composite2.setLayout(new GridLayout(2, false)); - - mButtonStop = new ImgDisabledButton(composite2, SWT.NONE, - getImage("stop_enabled_16.png"), //$NON-NLS-1$ - getImage("stop_disabled_16.png"), //$NON-NLS-1$ - "Click to abort the current task", - ""); //$NON-NLS-1$ nothing to abort - mButtonStop.addListener(SWT.Selection, new Listener() { - @Override - public void handleEvent(Event event) { - onStopSelected(); - } - }); - - mButtonShowLog = new ToggleButton(composite2, SWT.NONE, - getImage("log_off_16.png"), //$NON-NLS-1$ - getImage("log_on_16.png"), //$NON-NLS-1$ - "Click to show the log window", // tooltip for state hidden=>shown - "Click to hide the log window"); // tooltip for state shown=>hidden - mButtonShowLog.addListener(SWT.Selection, new Listener() { - @Override - public void handleEvent(Event event) { - onToggleLogWindow(); - } - }); - } - - @SuppressWarnings("unused") // MenuItem works using side effects - private void createMenuBar() { - - Menu menuBar = new Menu(mShell, SWT.BAR); - mShell.setMenuBar(menuBar); - - MenuItem menuBarPackages = new MenuItem(menuBar, SWT.CASCADE); - menuBarPackages.setText("Packages"); - - Menu menuPkgs = new Menu(menuBarPackages); - menuBarPackages.setMenu(menuPkgs); - - MenuItem showUpdatesNew = new MenuItem(menuPkgs, - MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG.getMenuStyle()); - showUpdatesNew.setText( - MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG.getMenuTitle()); - mPkgPage.registerMenuAction( - MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG, showUpdatesNew); - - MenuItem showInstalled = new MenuItem(menuPkgs, - MenuAction.TOGGLE_SHOW_INSTALLED_PKG.getMenuStyle()); - showInstalled.setText( - MenuAction.TOGGLE_SHOW_INSTALLED_PKG.getMenuTitle()); - mPkgPage.registerMenuAction( - MenuAction.TOGGLE_SHOW_INSTALLED_PKG, showInstalled); - - MenuItem showObsoletePackages = new MenuItem(menuPkgs, - MenuAction.TOGGLE_SHOW_OBSOLETE_PKG.getMenuStyle()); - showObsoletePackages.setText( - MenuAction.TOGGLE_SHOW_OBSOLETE_PKG.getMenuTitle()); - mPkgPage.registerMenuAction( - MenuAction.TOGGLE_SHOW_OBSOLETE_PKG, showObsoletePackages); - - MenuItem showArchives = new MenuItem(menuPkgs, - MenuAction.TOGGLE_SHOW_ARCHIVES.getMenuStyle()); - showArchives.setText( - MenuAction.TOGGLE_SHOW_ARCHIVES.getMenuTitle()); - mPkgPage.registerMenuAction( - MenuAction.TOGGLE_SHOW_ARCHIVES, showArchives); - - new MenuItem(menuPkgs, SWT.SEPARATOR); - - MenuItem sortByApi = new MenuItem(menuPkgs, - MenuAction.SORT_API_LEVEL.getMenuStyle()); - sortByApi.setText( - MenuAction.SORT_API_LEVEL.getMenuTitle()); - mPkgPage.registerMenuAction( - MenuAction.SORT_API_LEVEL, sortByApi); - - MenuItem sortBySource = new MenuItem(menuPkgs, - MenuAction.SORT_SOURCE.getMenuStyle()); - sortBySource.setText( - MenuAction.SORT_SOURCE.getMenuTitle()); - mPkgPage.registerMenuAction( - MenuAction.SORT_SOURCE, sortBySource); - - new MenuItem(menuPkgs, SWT.SEPARATOR); - - MenuItem reload = new MenuItem(menuPkgs, - MenuAction.RELOAD.getMenuStyle()); - reload.setText( - MenuAction.RELOAD.getMenuTitle()); - mPkgPage.registerMenuAction( - MenuAction.RELOAD, reload); - - MenuItem menuBarTools = new MenuItem(menuBar, SWT.CASCADE); - menuBarTools.setText("Tools"); - - Menu menuTools = new Menu(menuBarTools); - menuBarTools.setMenu(menuTools); - - if (mContext == SdkInvocationContext.STANDALONE) { - MenuItem manageAvds = new MenuItem(menuTools, SWT.NONE); - manageAvds.setText("Manage AVDs..."); - manageAvds.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - onAvdManager(); - } - }); - } - - MenuItem manageSources = new MenuItem(menuTools, - MenuAction.SHOW_ADDON_SITES.getMenuStyle()); - manageSources.setText( - MenuAction.SHOW_ADDON_SITES.getMenuTitle()); - mPkgPage.registerMenuAction( - MenuAction.SHOW_ADDON_SITES, manageSources); - - if (mContext == SdkInvocationContext.STANDALONE || mContext == SdkInvocationContext.IDE) { - try { - new MenuBarWrapper(APP_NAME, menuTools) { - @Override - public void onPreferencesMenuSelected() { - - // capture a copy of the initial settings - Settings settings1 = new Settings(mSettingsController.getSettings()); - - // open the dialog and wait for it to close - SettingsDialog sd = new SettingsDialog(mShell, mUpdaterData); - sd.open(); - - // get the new settings - Settings settings2 = mSettingsController.getSettings(); - - // We need to reload the package list if the http mode or the preview - // modes have changed. - if (settings1.getForceHttp() != settings2.getForceHttp() || - settings1.getEnablePreviews() != settings2.getEnablePreviews()) { - mPkgPage.onSdkReload(); - } - } - - @Override - public void onAboutMenuSelected() { - AboutDialog ad = new AboutDialog(mShell, mUpdaterData); - ad.open(); - } - - @Override - public void printError(String format, Object... args) { - if (mUpdaterData != null) { - mUpdaterData.getSdkLog().error(null, format, args); - } - } - }; - } catch (Throwable e) { - mUpdaterData.getSdkLog().error(e, "Failed to setup menu bar"); - e.printStackTrace(); - } - } - } - - private Image getImage(String filename) { - if (mUpdaterData != null) { - ImageFactory imgFactory = mUpdaterData.getImageFactory(); - if (imgFactory != null) { - return imgFactory.getImageByName(filename); - } - } - return null; - } - - /** - * Creates the log window. - * <p/> - * If this is invoked from an IDE, we also define a secondary logger so that all - * messages flow to the IDE log. This may or may not be what we want in the end - * (e.g. a middle ground would be to repeat error, and ignore normal/verbose) - */ - private void createLogWindow() { - mLogWindow = new LogWindow(mShell, - mContext == SdkInvocationContext.IDE ? mUpdaterData.getSdkLog() : null); - mLogWindow.open(); - } - - - // -- Start of internal part ---------- - // Hide everything down-below from SWT designer - //$hide>>$ - - // --- Public API ----------- - - /** - * Adds a new listener to be notified when a change is made to the content of the SDK. - */ - @Override - public void addListener(ISdkChangeListener listener) { - mUpdaterData.addListeners(listener); - } - - /** - * Removes a new listener to be notified anymore when a change is made to the content of - * the SDK. - */ - @Override - public void removeListener(ISdkChangeListener listener) { - mUpdaterData.removeListener(listener); - } - - // --- Internals & UI Callbacks ----------- - - /** - * Called before the UI is created. - */ - private void preCreateContent() { - mUpdaterData.setWindowShell(mShell); - // We need the UI factory to create the UI - mUpdaterData.setImageFactory(new ImageFactory(mShell.getDisplay())); - // Note: we can't create the TaskFactory yet because we need the UI - // to be created first, so this is done in postCreateContent(). - } - - /** - * Once the UI has been created, initializes the content. - * This creates the pages, selects the first one, setups sources and scans for local folders. - * - * Returns true if we should show the window. - */ - private boolean postCreateContent() { - ProgressViewFactory factory = new ProgressViewFactory(); - - // This class delegates all logging to the mLogWindow window - // and filters errors to make sure the window is visible when - // an error is logged. - ILogUiProvider logAdapter = new ILogUiProvider() { - @Override - public void setDescription(String description) { - mLogWindow.setDescription(description); - } - - @Override - public void log(String log) { - mLogWindow.log(log); - } - - @Override - public void logVerbose(String log) { - mLogWindow.logVerbose(log); - } - - @Override - public void logError(String log) { - mLogWindow.logError(log); - - // Run the window visibility check/toggle on the UI thread. - // Note: at least on Windows, it seems ok to check for the window visibility - // on a sub-thread but that doesn't seem cross-platform safe. We shouldn't - // have a lot of error logging, so this should be acceptable. If not, we could - // cache the visibility state. - if (mShell != null && !mShell.isDisposed()) { - mShell.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - if (!mLogWindow.isVisible()) { - // Don't toggle the window visibility directly. - // Instead use the same action as the log-toggle button - // so that the button's state be kept in sync. - onToggleLogWindow(); - } - } - }); - } - } - }; - - factory.setProgressView( - new ProgressView(mStatusText, mProgressBar, mButtonStop, logAdapter)); - mUpdaterData.setTaskFactory(factory); - - setWindowImage(mShell); - - setupSources(); - initializeSettings(); - - if (mUpdaterData.checkIfInitFailed()) { - return false; - } - - mUpdaterData.broadcastOnSdkLoaded(); - - // Tell the one page its the selected one - mPkgPage.performFirstLoad(); - - return true; - } - - /** - * Creates the icon of the window shell. - * - * @param shell The shell on which to put the icon - */ - private void setWindowImage(Shell shell) { - String imageName = "android_icon_16.png"; //$NON-NLS-1$ - if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_DARWIN) { - imageName = "android_icon_128.png"; //$NON-NLS-1$ - } - - if (mUpdaterData != null) { - ImageFactory imgFactory = mUpdaterData.getImageFactory(); - if (imgFactory != null) { - shell.setImage(imgFactory.getImageByName(imageName)); - } - } - } - - /** - * Called by the main loop when the window has been disposed. - */ - private void dispose() { - mLogWindow.close(); - mUpdaterData.getSources().saveUserAddons(mUpdaterData.getSdkLog()); - } - - /** - * Callback called when the window shell is disposed. - */ - private void onAndroidSdkUpdaterDispose() { - if (mUpdaterData != null) { - ImageFactory imgFactory = mUpdaterData.getImageFactory(); - if (imgFactory != null) { - imgFactory.dispose(); - } - } - } - - /** - * Used to initialize the sources. - */ - private void setupSources() { - mUpdaterData.setupDefaultSources(); - } - - /** - * Initializes settings. - * This must be called after addExtraPages(), which created a settings page. - * Iterate through all the pages to find the first (and supposedly unique) setting page, - * and use it to load and apply these settings. - */ - private void initializeSettings() { - mSettingsController = mUpdaterData.getSettingsController(); - mSettingsController.loadSettings(); - mSettingsController.applySettings(); - } - - private void onToggleLogWindow() { - // toggle visibility - if (!mButtonShowLog.isDisposed()) { - mLogWindow.setVisible(!mLogWindow.isVisible()); - mButtonShowLog.setState(mLogWindow.isVisible() ? 1 : 0); - } - } - - private void onStopSelected() { - // TODO - } - - private void onAvdManager() { - ITaskFactory oldFactory = mUpdaterData.getTaskFactory(); - - try { - AvdManagerWindowImpl1 win = new AvdManagerWindowImpl1( - mShell, - mUpdaterData, - AvdInvocationContext.DIALOG); - - win.open(); - } catch (Exception e) { - mUpdaterData.getSdkLog().error(e, "AVD Manager window error"); - } finally { - mUpdaterData.setTaskFactory(oldFactory); - } - } - - // End of hiding from SWT Designer - //$hide<<$ -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/ShellSizeAndPos.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/ShellSizeAndPos.java deleted file mode 100755 index 4921ba0..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/ShellSizeAndPos.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2011 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.repository.ui; - - -import com.android.prefs.AndroidLocation; - -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Monitor; -import org.eclipse.swt.widgets.Shell; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Properties; - -/** - * Utility to save & restore the size and position on a window - * using a common config file. - */ -public class ShellSizeAndPos { - - private static final String SETTINGS_FILENAME = "androidwin.cfg"; //$NON-NLS-1$ - private static final String PX = "_px"; //$NON-NLS-1$ - private static final String PY = "_py"; //$NON-NLS-1$ - private static final String SX = "_sx"; //$NON-NLS-1$ - private static final String SY = "_sy"; //$NON-NLS-1$ - - public static void loadSizeAndPos(Shell shell, String prefix) { - Properties props = loadProperties(); - - try { - int px = Integer.parseInt(props.getProperty(prefix + PX)); - int py = Integer.parseInt(props.getProperty(prefix + PY)); - int sx = Integer.parseInt(props.getProperty(prefix + SX)); - int sy = Integer.parseInt(props.getProperty(prefix + SY)); - - Point p1 = new Point(px, py); - Point p2 = new Point(px + sx, py + sy); - Rectangle r = new Rectangle(px, py, sy, sy); - - Monitor bestMatch = null; - int bestSurface = -1; - for (Monitor monitor : shell.getDisplay().getMonitors()) { - Rectangle area = monitor.getClientArea(); - if (area.contains(p1) && area.contains(p2)) { - // The shell is fully visible on this monitor. Just use that. - bestMatch = monitor; - bestSurface = Integer.MAX_VALUE; - break; - } else { - // Find which monitor displays the largest surface of the window. - // We'll use this one to center the window there, to make sure we're not - // starting split between several monitors. - Rectangle i = area.intersection(r); - int surface = i.width * i.height; - if (surface > bestSurface) { - bestSurface = surface; - bestMatch = monitor; - } - } - } - - if (bestMatch != null && bestSurface != Integer.MAX_VALUE) { - // Recenter the window on this monitor and make sure it fits - Rectangle area = bestMatch.getClientArea(); - - sx = Math.min(sx, area.width); - sy = Math.min(sy, area.height); - px = area.x + (area.width - sx) / 2; - py = area.y + (area.height - sy) / 2; - } - - shell.setLocation(px, py); - shell.setSize(sx, sy); - - } catch ( Exception e) { - // Ignore exception. We could typically get NPE from the getProperty - // or NumberFormatException from parseInt calls. Either way, do - // nothing if anything goes wrong. - } - } - - public static void saveSizeAndPos(Shell shell, String prefix) { - Properties props = loadProperties(); - - Point loc = shell.getLocation(); - Point size = shell.getSize(); - - props.setProperty(prefix + PX, Integer.toString(loc.x)); - props.setProperty(prefix + PY, Integer.toString(loc.y)); - props.setProperty(prefix + SX, Integer.toString(size.x)); - props.setProperty(prefix + SY, Integer.toString(size.y)); - - saveProperties(props); - } - - /** - * Load properties saved in {@link #SETTINGS_FILENAME}. - * If the file does not exists or doesn't load properly, just return an - * empty set of properties. - */ - private static Properties loadProperties() { - Properties props = new Properties(); - FileInputStream fis = null; - - try { - String folder = AndroidLocation.getFolder(); - File f = new File(folder, SETTINGS_FILENAME); - if (f.exists()) { - fis = new FileInputStream(f); - - props.load(fis); - } - } catch (Exception e) { - // Ignore - } finally { - if (fis != null) { - try { - fis.close(); - } catch (IOException e) { - } - } - } - - return props; - } - - private static void saveProperties(Properties props) { - FileOutputStream fos = null; - - try { - String folder = AndroidLocation.getFolder(); - File f = new File(folder, SETTINGS_FILENAME); - fos = new FileOutputStream(f); - - props.store(fos, "## Size and Pos for SDK Manager Windows"); //$NON-NLS-1$ - - } catch (Exception e) { - // ignore - } finally { - if (fos != null) { - try { - fos.close(); - } catch (IOException e) { - } - } - } - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ILogUiProvider.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ILogUiProvider.java deleted file mode 100755 index 8f77b7a..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ILogUiProvider.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2011 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.tasks; - - -/** - * Interface for a user interface that displays the log from a task monitor. - */ -public interface ILogUiProvider { - - /** - * Sets the description in the current task dialog. - * This method can be invoked from a non-UI thread. - */ - public abstract void setDescription(String description); - - /** - * Logs a "normal" information line. - * This method can be invoked from a non-UI thread. - */ - public abstract void log(String log); - - /** - * Logs an "error" information line. - * This method can be invoked from a non-UI thread. - */ - public abstract void logError(String log); - - /** - * Logs a "verbose" information line, that is extra details which are typically - * not that useful for the end-user and might be hidden until explicitly shown. - * This method can be invoked from a non-UI thread. - */ - public abstract void logVerbose(String log); - -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/IProgressUiProvider.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/IProgressUiProvider.java deleted file mode 100755 index 4e2c131..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/IProgressUiProvider.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2011 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.tasks; - -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.UserCredentials; - -import org.eclipse.swt.widgets.ProgressBar; - -/** - * Interface for a user interface that displays both a task status - * (e.g. via an {@link ITaskMonitor}) and the progress state of the - * task (e.g. via a progress bar.) - * <p/> - * See {@link ITaskMonitor} for details on how a monitor expects to - * be displayed. - */ -interface IProgressUiProvider extends ILogUiProvider { - - public abstract boolean isCancelRequested(); - - /** - * Sets the description in the current task dialog. - * This method can be invoked from a non-UI thread. - */ - @Override - public abstract void setDescription(String description); - - /** - * Sets the max value of the progress bar. - * This method can be invoked from a non-UI thread. - * - * @see ProgressBar#setMaximum(int) - */ - public abstract void setProgressMax(int max); - - /** - * Sets the current value of the progress bar. - * This method can be invoked from a non-UI thread. - */ - public abstract void setProgress(int value); - - /** - * Returns the current value of the progress bar, - * between 0 and up to {@link #setProgressMax(int)} - 1. - * This method can be invoked from a non-UI thread. - */ - public abstract int getProgress(); - - /** - * Display a yes/no question dialog box. - * - * This implementation allow this to be called from any thread, it - * makes sure the dialog is opened synchronously in the ui thread. - * - * @param title The title of the dialog box - * @param message The error message - * @return true if YES was clicked. - */ - public abstract boolean displayPrompt(String title, String message); - - /** - * Launch an interface which asks for login credentials. Implementations - * MUST allow this to be called from any thread, e.g. by making sure the - * dialog is opened synchronously in the UI thread. - * - * @param title The title of the dialog box. - * @param message The message to be displayed as an instruction. - * @return Returns user provided credentials - */ - public UserCredentials displayLoginCredentialsPrompt(String title, String message); - -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTask.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTask.java deleted file mode 100755 index d5404ae..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTask.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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.tasks; - -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskMonitor; - -import org.eclipse.swt.widgets.Shell; - - -/** - * An {@link ITaskMonitor} that displays a {@link ProgressTaskDialog}. - */ -public final class ProgressTask extends TaskMonitorImpl { - - private final String mTitle; - private final ProgressTaskDialog mDialog; - private volatile boolean mAutoClose = true; - - - /** - * Creates a new {@link ProgressTask} with the given title. - * This does NOT start the task. The caller must invoke {@link #start(ITask)}. - */ - public ProgressTask(Shell parent, String title) { - super(new ProgressTaskDialog(parent)); - mTitle = title; - mDialog = (ProgressTaskDialog) getUiProvider(); - mDialog.setText(mTitle); - } - - /** - * Execute the given task in a separate thread (not the UI thread). - * This blocks till the thread ends. - * <p/> - * The {@link ProgressTask} must not be reused after this call. - */ - public void start(ITask task) { - assert mDialog != null; - mDialog.open(createTaskThread(mTitle, task)); - } - - /** - * Changes the auto-close behavior of the dialog on task completion. - * - * @param autoClose True if the dialog should be closed automatically when the task - * has completed. - */ - public void setAutoClose(boolean autoClose) { - if (autoClose != mAutoClose) { - if (autoClose) { - mDialog.setAutoCloseRequested(); - } else { - mDialog.setManualCloseRequested(); - } - mAutoClose = autoClose; - } - } - - /** - * Creates a thread to run the task. The thread has not been started yet. - * When the task completes, requests to close the dialog. - * - * @return A new thread that will run the task. The thread has not been started yet. - */ - private Thread createTaskThread(String title, final ITask task) { - if (task != null) { - return new Thread(title) { - @Override - public void run() { - task.run(ProgressTask.this); - if (mAutoClose) { - mDialog.setAutoCloseRequested(); - } else { - mDialog.setManualCloseRequested(); - } - } - }; - } - return null; - } - - /** - * {@inheritDoc} - * <p/> - * Sets the dialog to not auto-close since we want the user to see the error - * (this is equivalent to calling {@code setAutoClose(false)}). - */ - @Override - public void logError(String format, Object...args) { - setAutoClose(false); - super.logError(format, args); - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTaskDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTaskDialog.java deleted file mode 100755 index 50f1e57..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTaskDialog.java +++ /dev/null @@ -1,520 +0,0 @@ -/* - * 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.tasks; - -import com.android.SdkConstants; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.UserCredentials; -import com.android.sdkuilib.ui.AuthenticationDialog; -import com.android.sdkuilib.ui.GridDialog; -import com.android.utils.Pair; - -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -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; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Dialog; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.ProgressBar; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; - - -/** - * Implements a {@link ProgressTaskDialog}, used by the {@link ProgressTask} class. - * This separates the dialog UI from the task logic. - * - * Note: this does not implement the {@link ITaskMonitor} interface to avoid confusing - * SWT Designer. - */ -final class ProgressTaskDialog extends Dialog implements IProgressUiProvider { - - /** - * Min Y location for dialog. Need to deal with the menu bar on mac os. - */ - private final static int MIN_Y = SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_DARWIN ? - 20 : 0; - - private static enum CancelMode { - /** Cancel button says "Cancel" and is enabled. Waiting for user to cancel. */ - ACTIVE, - /** Cancel button has been clicked. Waiting for thread to finish. */ - CANCEL_PENDING, - /** Close pending. Close button clicked or thread finished but there were some - * messages so the user needs to manually close. */ - CLOSE_MANUAL, - /** Close button clicked or thread finished. The window will automatically close. */ - CLOSE_AUTO - } - - /** The current mode of operation of the dialog. */ - private CancelMode mCancelMode = CancelMode.ACTIVE; - - /** Last dialog size for this session. */ - private static Point sLastSize; - - - // UI fields - private Shell mDialogShell; - private Composite mRootComposite; - private Label mLabel; - private ProgressBar mProgressBar; - private Button mCancelButton; - private Text mResultText; - - - /** - * Create the dialog. - * @param parent Parent container - */ - public ProgressTaskDialog(Shell parent) { - super(parent, SWT.APPLICATION_MODAL); - } - - /** - * Open the dialog and blocks till it gets closed - * @param taskThread The thread to run the task. Cannot be null. - */ - public void open(Thread taskThread) { - createContents(); - positionShell(); //$hide$ (hide from SWT designer) - mDialogShell.open(); - mDialogShell.layout(); - - startThread(taskThread); //$hide$ (hide from SWT designer) - - Display display = getParent().getDisplay(); - while (!mDialogShell.isDisposed() && mCancelMode != CancelMode.CLOSE_AUTO) { - if (!display.readAndDispatch()) { - display.sleep(); - } - } - - setCancelRequested(); //$hide$ (hide from SWT designer) - - if (!mDialogShell.isDisposed()) { - sLastSize = mDialogShell.getSize(); - mDialogShell.close(); - } - } - - /** - * Create contents of the 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()); - - mRootComposite = new Composite(mDialogShell, SWT.NONE); - mRootComposite.setLayout(new GridLayout(2, false)); - mRootComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); - - mLabel = new Label(mRootComposite, SWT.NONE); - mLabel.setText("Task"); - mLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); - - mProgressBar = new ProgressBar(mRootComposite, SWT.NONE); - mProgressBar.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); - mCancelButton = new Button(mRootComposite, SWT.NONE); - mCancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); - mCancelButton.setText("Cancel"); - - mCancelButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onCancelSelected(); //$hide$ - } - }); - - mResultText = new Text(mRootComposite, - SWT.BORDER | SWT.READ_ONLY | SWT.WRAP | - SWT.H_SCROLL | SWT.V_SCROLL | SWT.CANCEL | SWT.MULTI); - mResultText.setEditable(true); - mResultText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); - } - - // -- End of UI, Start of internal logic ---------- - // Hide everything down-below from SWT designer - //$hide>>$ - - @Override - public boolean isCancelRequested() { - return mCancelMode != CancelMode.ACTIVE; - } - - /** - * Sets the mode to cancel pending. - * The first time this grays the cancel button, to let the user know that the - * cancel operation is pending. - */ - public void setCancelRequested() { - if (!mDialogShell.isDisposed()) { - // The dialog is not disposed, make sure to run all this in the UI thread - // and lock on the cancel button mode. - mDialogShell.getDisplay().syncExec(new Runnable() { - - @Override - public void run() { - synchronized (mCancelMode) { - if (mCancelMode == CancelMode.ACTIVE) { - mCancelMode = CancelMode.CANCEL_PENDING; - - if (!mCancelButton.isDisposed()) { - mCancelButton.setEnabled(false); - } - } - } - } - }); - } else { - // The dialog is disposed. Just set the boolean. We shouldn't be here. - if (mCancelMode == CancelMode.ACTIVE) { - mCancelMode = CancelMode.CANCEL_PENDING; - } - } - } - - /** - * Sets the mode to close manual. - * The first time, this also ungrays the pause button and converts it to a close button. - */ - public void setManualCloseRequested() { - if (!mDialogShell.isDisposed()) { - // The dialog is not disposed, make sure to run all this in the UI thread - // and lock on the cancel button mode. - mDialogShell.getDisplay().syncExec(new Runnable() { - - @Override - public void run() { - synchronized (mCancelMode) { - if (mCancelMode != CancelMode.CLOSE_MANUAL && - mCancelMode != CancelMode.CLOSE_AUTO) { - mCancelMode = CancelMode.CLOSE_MANUAL; - - if (!mCancelButton.isDisposed()) { - mCancelButton.setEnabled(true); - mCancelButton.setText("Close"); - } - } - } - } - }); - } else { - // The dialog is disposed. Just set the booleans. We shouldn't be here. - if (mCancelMode != CancelMode.CLOSE_MANUAL && - mCancelMode != CancelMode.CLOSE_AUTO) { - mCancelMode = CancelMode.CLOSE_MANUAL; - } - } - } - - /** - * Sets the mode to close auto. - * The main loop will just exit and close the shell at the first opportunity. - */ - public void setAutoCloseRequested() { - synchronized (mCancelMode) { - if (mCancelMode != CancelMode.CLOSE_AUTO) { - mCancelMode = CancelMode.CLOSE_AUTO; - } - } - } - - /** - * Callback invoked when the cancel button is selected. - * When in closing mode, this simply closes the shell. Otherwise triggers a cancel. - */ - private void onCancelSelected() { - if (mCancelMode == CancelMode.CLOSE_MANUAL) { - setAutoCloseRequested(); - } else { - setCancelRequested(); - } - } - - /** - * Callback invoked when the shell is closed either by clicking the close button - * on by calling shell.close(). - * This does the same thing as clicking the cancel/close button unless the mode is - * to auto close in which case we should do nothing to let the shell close normally. - */ - private void onShellClosed(ShellEvent e) { - if (mCancelMode != CancelMode.CLOSE_AUTO) { - e.doit = false; // don't close directly - onCancelSelected(); - } - } - - /** - * Sets the description in the current task dialog. - * This method can be invoked from a non-UI thread. - */ - @Override - public void setDescription(final String description) { - mDialogShell.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - if (!mLabel.isDisposed()) { - mLabel.setText(description); - } - } - }); - } - - /** - * Adds to the log in the current task dialog. - * This method can be invoked from a non-UI thread. - */ - @Override - public void log(final String info) { - if (!mDialogShell.isDisposed()) { - mDialogShell.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - if (!mResultText.isDisposed()) { - mResultText.setVisible(true); - String lastText = mResultText.getText(); - if (lastText != null && - lastText.length() > 0 && - !lastText.endsWith("\n") && //$NON-NLS-1$ - !info.startsWith("\n")) { //$NON-NLS-1$ - mResultText.append("\n"); //$NON-NLS-1$ - } - mResultText.append(info); - } - } - }); - } - } - - @Override - public void logError(String info) { - log(info); - } - - @Override - public void logVerbose(String info) { - log(info); - } - - /** - * Sets the max value of the progress bar. - * This method can be invoked from a non-UI thread. - * - * @see ProgressBar#setMaximum(int) - */ - @Override - public void setProgressMax(final int max) { - if (!mDialogShell.isDisposed()) { - mDialogShell.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - if (!mProgressBar.isDisposed()) { - mProgressBar.setMaximum(max); - } - } - }); - } - } - - /** - * Sets the current value of the progress bar. - * This method can be invoked from a non-UI thread. - */ - @Override - public void setProgress(final int value) { - if (!mDialogShell.isDisposed()) { - mDialogShell.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - if (!mProgressBar.isDisposed()) { - mProgressBar.setSelection(value); - } - } - }); - } - } - - /** - * Returns the current value of the progress bar, - * between 0 and up to {@link #setProgressMax(int)} - 1. - * This method can be invoked from a non-UI thread. - */ - @Override - public int getProgress() { - final int[] result = new int[] { 0 }; - - if (!mDialogShell.isDisposed()) { - mDialogShell.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - if (!mProgressBar.isDisposed()) { - result[0] = mProgressBar.getSelection(); - } - } - }); - } - - return result[0]; - } - - /** - * Display a yes/no question dialog box. - * - * This implementation allow this to be called from any thread, it - * makes sure the dialog is opened synchronously in the ui thread. - * - * @param title The title of the dialog box - * @param message The error message - * @return true if YES was clicked. - */ - @Override - public boolean displayPrompt(final String title, final String message) { - Display display = mDialogShell.getDisplay(); - - // we need to ask the user what he wants to do. - final boolean[] result = new boolean[] { false }; - display.syncExec(new Runnable() { - @Override - public void run() { - result[0] = MessageDialog.openQuestion(mDialogShell, title, message); - } - }); - return result[0]; - } - - /** - * This method opens a pop-up window which requests for User Login and - * password. - * - * @param title The title of the window. - * @param message The message to displayed in the login/password window. - * @return Returns a {@link Pair} holding the entered login and password. - * The information must always be in the following order: - * Login,Password. So in order to retrieve the <b>login</b> callers - * should retrieve the first element, and the second value for the - * <b>password</b>. - * If operation is <b>canceled</b> by user the return value must be <b>null</b>. - * @see ITaskMonitor#displayLoginCredentialsPrompt(String, String) - */ - @Override - public UserCredentials displayLoginCredentialsPrompt( - final String title, final String message) { - Display display = mDialogShell.getDisplay(); - - // open dialog and request login and password - GetUserCredentialsTask task = new GetUserCredentialsTask(mDialogShell, title, message); - display.syncExec(task); - - return task.getUserCredentials(); - } - - private static class GetUserCredentialsTask implements Runnable { - private UserCredentials mResult = null; - - private Shell mShell; - private String mTitle; - private String mMessage; - - public GetUserCredentialsTask(Shell shell, String title, String message) { - mShell = shell; - mTitle = title; - mMessage = message; - } - - @Override - public void run() { - AuthenticationDialog authenticationDialog = new AuthenticationDialog(mShell, - mTitle, mMessage); - int dlgResult= authenticationDialog.open(); - if(dlgResult == GridDialog.OK) { - mResult = new UserCredentials( - authenticationDialog.getLogin(), - authenticationDialog.getPassword(), - authenticationDialog.getWorkstation(), - authenticationDialog.getDomain()); - } - } - - public UserCredentials getUserCredentials() { - return mResult; - } - } - - /** - * Starts the thread that runs the task. - * This is deferred till the UI is created. - */ - private void startThread(Thread taskThread) { - if (taskThread != null) { - taskThread.start(); - } - } - - /** - * Centers the dialog in its parent shell. - */ - private void positionShell() { - // Centers the dialog in its parent shell - Shell child = mDialogShell; - Shell parent = getParent(); - if (child != null && parent != null) { - - // get the parent client area with a location relative to the display - Rectangle parentArea = parent.getClientArea(); - Point parentLoc = parent.getLocation(); - int px = parentLoc.x; - int py = parentLoc.y; - int pw = parentArea.width; - int ph = parentArea.height; - - // Reuse the last size if there's one, otherwise use the default - Point childSize = sLastSize != null ? sLastSize : child.getSize(); - int cw = childSize.x; - int ch = childSize.y; - - int x = px + (pw - cw) / 2; - if (x < 0) x = 0; - - int y = py + (ph - ch) / 2; - if (y < MIN_Y) y = MIN_Y; - - child.setLocation(x, y); - child.setSize(cw, ch); - } - } - - // End of hiding from SWT Designer - //$hide<<$ -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTaskFactory.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTaskFactory.java deleted file mode 100755 index 17cba7a..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressTaskFactory.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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.tasks; - -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskFactory; -import com.android.sdklib.internal.repository.ITaskMonitor; - -import org.eclipse.swt.widgets.Shell; - -/** - * An {@link ITaskFactory} that creates a new {@link ProgressTask} dialog - * for each new task. - */ -public final class ProgressTaskFactory implements ITaskFactory { - - private final Shell mShell; - - public ProgressTaskFactory(Shell shell) { - mShell = shell; - } - - @Override - public void start(String title, ITask task) { - start(title, null /*parentMonitor*/, task); - } - - @Override - public void start(String title, ITaskMonitor parentMonitor, ITask task) { - - if (parentMonitor == null) { - ProgressTask p = new ProgressTask(mShell, title); - p.start(task); - } else { - // Use all the reminder of the parent monitor. - if (parentMonitor.getProgressMax() == 0) { - parentMonitor.setProgressMax(1); - } - - ITaskMonitor sub = parentMonitor.createSubMonitor( - parentMonitor.getProgressMax() - parentMonitor.getProgress()); - try { - task.run(sub); - } finally { - int delta = - sub.getProgressMax() - sub.getProgress(); - if (delta > 0) { - sub.incProgress(delta); - } - } - } - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressView.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressView.java deleted file mode 100755 index 8987351..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressView.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright (C) 2011 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.tasks; - -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.UserCredentials; -import com.android.sdkuilib.ui.AuthenticationDialog; -import com.android.sdkuilib.ui.GridDialog; - -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.ProgressBar; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Widget; - -import java.util.concurrent.atomic.AtomicReference; - - -/** - * Implements a "view" that uses an existing progress bar, status button and - * status text to display a {@link ITaskMonitor}. - */ -public final class ProgressView implements IProgressUiProvider { - - private static enum State { - /** View created but there's no task running. Next state can only be ACTIVE. */ - IDLE, - /** A task is currently running. Next state is either STOP_PENDING or IDLE. */ - ACTIVE, - /** Stop button has been clicked. Waiting for thread to finish. Next state is IDLE. */ - STOP_PENDING, - } - - /** The current mode of operation of the dialog. */ - private State mState = State.IDLE; - - - - // UI fields - private final Label mLabel; - private final Control mStopButton; - private final ProgressBar mProgressBar; - - /** Logger object. Cannot not be null. */ - private final ILogUiProvider mLog; - - /** - * Creates a new {@link ProgressView} object, a simple "holder" for the various - * widgets used to display and update a progress + status bar. - * - * @param label The label to display titles of status updates (e.g. task titles and - * calls to {@link #setDescription(String)}.) Must not be null. - * @param progressBar The progress bar to update during a task. Must not be null. - * @param stopButton The stop button. It will be disabled when there's no task that can - * be interrupted. A selection listener will be attached to it. Optional. Can be null. - * @param log A <em>mandatory</em> logger object that will be used to report all the log. - * Must not be null. - */ - public ProgressView( - Label label, - ProgressBar progressBar, - Control stopButton, - ILogUiProvider log) { - mLabel = label; - mProgressBar = progressBar; - mLog = log; - mProgressBar.setEnabled(false); - - mStopButton = stopButton; - if (mStopButton != null) { - mStopButton.addListener(SWT.Selection, new Listener() { - @Override - public void handleEvent(Event event) { - if (mState == State.ACTIVE) { - changeState(State.STOP_PENDING); - } - } - }); - } - } - - /** - * Starts the task and block till it's either finished or canceled. - * This can be called from a non-UI thread safely. - * <p/> - * When a task is started from within a monitor, it reuses the thread - * from the parent. Otherwise it starts a new thread and runs it own - * UI loop. This means the task can perform UI operations using - * {@link Display#asyncExec(Runnable)}. - * <p/> - * In either case, the method only returns when the task has finished. - */ - public void startTask( - final String title, - final ITaskMonitor parentMonitor, - final ITask task) { - if (task != null) { - try { - if (parentMonitor == null && !mProgressBar.isDisposed()) { - mLabel.setText(title); - mProgressBar.setSelection(0); - mProgressBar.setEnabled(true); - changeState(ProgressView.State.ACTIVE); - } - - Runnable r = new Runnable() { - @Override - public void run() { - if (parentMonitor == null) { - task.run(new TaskMonitorImpl(ProgressView.this)); - - } else { - // Use all the reminder of the parent monitor. - if (parentMonitor.getProgressMax() == 0) { - parentMonitor.setProgressMax(1); - } - ITaskMonitor sub = parentMonitor.createSubMonitor( - parentMonitor.getProgressMax() - parentMonitor.getProgress()); - try { - task.run(sub); - } finally { - int delta = - sub.getProgressMax() - sub.getProgress(); - if (delta > 0) { - sub.incProgress(delta); - } - } - } - } - }; - - // If for some reason the UI has been disposed, just abort the thread. - if (mProgressBar.isDisposed()) { - return; - } - - if (TaskMonitorImpl.isTaskMonitorImpl(parentMonitor)) { - // If there's a parent monitor and it's our own class, we know this parent - // is already running a thread and the base one is running an event loop. - // We should thus not run a second event loop and we can process the - // runnable right here instead of spawning a thread inside the thread. - r.run(); - - } else { - // No parent monitor. This is the first one so we need a thread and - // we need to process UI events. - - final Thread t = new Thread(r, title); - t.start(); - - // Process the app's event loop whilst we wait for the thread to finish - while (!mProgressBar.isDisposed() && t.isAlive()) { - Display display = mProgressBar.getDisplay(); - if (!mProgressBar.isDisposed() && !display.readAndDispatch()) { - display.sleep(); - } - } - } - } catch (Exception e) { - // TODO log - - } finally { - if (parentMonitor == null && !mProgressBar.isDisposed()) { - changeState(ProgressView.State.IDLE); - mProgressBar.setSelection(0); - mProgressBar.setEnabled(false); - } - } - } - } - - private void syncExec(final Widget widget, final Runnable runnable) { - if (widget != null && !widget.isDisposed()) { - widget.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - // Check again whether the widget got disposed between the time where - // we requested the syncExec and the time it actually happened. - if (!widget.isDisposed()) { - runnable.run(); - } - } - }); - } - } - - private void changeState(State state) { - if (mState != null ) { - mState = state; - } - - syncExec(mStopButton, new Runnable() { - @Override - public void run() { - mStopButton.setEnabled(mState == State.ACTIVE); - } - }); - - } - - // --- Implementation of ITaskUiProvider --- - - @Override - public boolean isCancelRequested() { - return mState != State.ACTIVE; - } - - /** - * Sets the description in the current task dialog. - * This method can be invoked from a non-UI thread. - */ - @Override - public void setDescription(final String description) { - syncExec(mLabel, new Runnable() { - @Override - public void run() { - mLabel.setText(description); - } - }); - - mLog.setDescription(description); - } - - /** - * Logs a "normal" information line. - * This method can be invoked from a non-UI thread. - */ - @Override - public void log(String log) { - mLog.log(log); - } - - /** - * Logs an "error" information line. - * This method can be invoked from a non-UI thread. - */ - @Override - public void logError(String log) { - mLog.logError(log); - } - - /** - * Logs a "verbose" information line, that is extra details which are typically - * not that useful for the end-user and might be hidden until explicitly shown. - * This method can be invoked from a non-UI thread. - */ - @Override - public void logVerbose(String log) { - mLog.logVerbose(log); - } - - /** - * Sets the max value of the progress bar. - * This method can be invoked from a non-UI thread. - * - * @see ProgressBar#setMaximum(int) - */ - @Override - public void setProgressMax(final int max) { - syncExec(mProgressBar, new Runnable() { - @Override - public void run() { - mProgressBar.setMaximum(max); - } - }); - } - - /** - * Sets the current value of the progress bar. - * This method can be invoked from a non-UI thread. - */ - @Override - public void setProgress(final int value) { - syncExec(mProgressBar, new Runnable() { - @Override - public void run() { - mProgressBar.setSelection(value); - } - }); - } - - /** - * Returns the current value of the progress bar, - * between 0 and up to {@link #setProgressMax(int)} - 1. - * This method can be invoked from a non-UI thread. - */ - @Override - public int getProgress() { - final int[] result = new int[] { 0 }; - - if (!mProgressBar.isDisposed()) { - mProgressBar.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - if (!mProgressBar.isDisposed()) { - result[0] = mProgressBar.getSelection(); - } - } - }); - } - - return result[0]; - } - - @Override - public boolean displayPrompt(final String title, final String message) { - final boolean[] result = new boolean[] { false }; - - syncExec(mProgressBar, new Runnable() { - @Override - public void run() { - Shell shell = mProgressBar.getShell(); - result[0] = MessageDialog.openQuestion(shell, title, message); - } - }); - - return result[0]; - } - - /** - * This method opens a pop-up window which requests for User Credentials. - * - * @param title The title of the window. - * @param message The message to displayed in the login/password window. - * @return Returns user provided credentials. - * If operation is <b>canceled</b> by user the return value must be <b>null</b>. - * @see ITaskMonitor#displayLoginCredentialsPrompt(String, String) - */ - @Override - public UserCredentials - displayLoginCredentialsPrompt(final String title, final String message) { - final AtomicReference<UserCredentials> result = new AtomicReference<UserCredentials>(null); - - // open dialog and request login and password - syncExec(mProgressBar, new Runnable() { - @Override - public void run() { - Shell shell = mProgressBar.getShell(); - AuthenticationDialog authenticationDialog = new AuthenticationDialog(shell, - title, - message); - int dlgResult = authenticationDialog.open(); - if (dlgResult == GridDialog.OK) { - result.set(new UserCredentials( - authenticationDialog.getLogin(), - authenticationDialog.getPassword(), - authenticationDialog.getWorkstation(), - authenticationDialog.getDomain())); - } - } - }); - - return result.get(); - } -} - diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressViewFactory.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressViewFactory.java deleted file mode 100755 index 2590169..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/ProgressViewFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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.tasks; - -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskFactory; -import com.android.sdklib.internal.repository.ITaskMonitor; - -/** - * An {@link ITaskFactory} that creates a new {@link ProgressTask} dialog - * for each new task. - */ -public final class ProgressViewFactory implements ITaskFactory { - - private ProgressView mProgressView; - - public ProgressViewFactory() { - } - - public void setProgressView(ProgressView progressView) { - mProgressView = progressView; - } - - @Override - public void start(String title, ITask task) { - start(title, null /*monitor*/, task); - } - - @Override - public void start(String title, ITaskMonitor parentMonitor, ITask task) { - assert mProgressView != null; - mProgressView.startTask(title, parentMonitor, task); - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/TaskMonitorImpl.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/TaskMonitorImpl.java deleted file mode 100755 index 4d4f3c9..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/tasks/TaskMonitorImpl.java +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright (C) 2011 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.tasks; - -import com.android.annotations.NonNull; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.UserCredentials; - -/** - * Internal class that implements the logic of an {@link ITaskMonitor}. - * It doesn't deal with any UI directly. Instead it delegates the UI to - * the provided {@link IProgressUiProvider}. - */ -class TaskMonitorImpl implements ITaskMonitor { - - private static final double MAX_COUNT = 10000.0; - - private interface ISubTaskMonitor extends ITaskMonitor { - public void subIncProgress(double realDelta); - } - - private double mIncCoef = 0; - private double mValue = 0; - private final IProgressUiProvider mUi; - - /** - * Returns true if the given {@code monitor} is an instance of {@link TaskMonitorImpl} - * or its private SubTaskMonitor. - */ - public static boolean isTaskMonitorImpl(ITaskMonitor monitor) { - return monitor instanceof TaskMonitorImpl || monitor instanceof SubTaskMonitor; - } - - /** - * Constructs a new {@link TaskMonitorImpl} that relies on the given - * {@link IProgressUiProvider} to change the user interface. - * @param ui The {@link IProgressUiProvider}. Cannot be null. - */ - public TaskMonitorImpl(IProgressUiProvider ui) { - mUi = ui; - } - - /** Returns the {@link IProgressUiProvider} passed to the constructor. */ - public IProgressUiProvider getUiProvider() { - return mUi; - } - - /** - * Sets the description in the current task dialog. - * This method can be invoked from a non-UI thread. - */ - @Override - public void setDescription(String format, Object... args) { - final String text = String.format(format, args); - mUi.setDescription(text); - } - - /** - * Logs a "normal" information line. - * This method can be invoked from a non-UI thread. - */ - @Override - public void log(String format, Object... args) { - String text = String.format(format, args); - mUi.log(text); - } - - /** - * Logs an "error" information line. - * This method can be invoked from a non-UI thread. - */ - @Override - public void logError(String format, Object... args) { - String text = String.format(format, args); - mUi.logError(text); - } - - /** - * Logs a "verbose" information line, that is extra details which are typically - * not that useful for the end-user and might be hidden until explicitly shown. - * This method can be invoked from a non-UI thread. - */ - @Override - public void logVerbose(String format, Object... args) { - String text = String.format(format, args); - mUi.logVerbose(text); - } - - /** - * Sets the max value of the progress bar. - * This method can be invoked from a non-UI thread. - * - * Weird things will happen if setProgressMax is called multiple times - * *after* {@link #incProgress(int)}: we don't try to adjust it on the - * fly. - */ - @Override - public void setProgressMax(int max) { - assert max > 0; - // Always set the dialog's progress max to 10k since it only handles - // integers and we want to have a better inner granularity. Instead - // we use the max to compute a coefficient for inc deltas. - mUi.setProgressMax((int) MAX_COUNT); - mIncCoef = max > 0 ? MAX_COUNT / max : 0; - assert mIncCoef > 0; - } - - @Override - public int getProgressMax() { - return mIncCoef > 0 ? (int) (MAX_COUNT / mIncCoef) : 0; - } - - /** - * Increments the current value of the progress bar. - * - * This method can be invoked from a non-UI thread. - */ - @Override - public void incProgress(int delta) { - if (delta > 0 && mIncCoef > 0) { - internalIncProgress(delta * mIncCoef); - } - } - - private void internalIncProgress(double realDelta) { - mValue += realDelta; - mUi.setProgress((int)mValue); - } - - /** - * Returns the current value of the progress bar, - * between 0 and up to {@link #setProgressMax(int)} - 1. - * - * This method can be invoked from a non-UI thread. - */ - @Override - public int getProgress() { - // mIncCoef is 0 if setProgressMax hasn't been used yet. - return mIncCoef > 0 ? (int)(mUi.getProgress() / mIncCoef) : 0; - } - - /** - * Returns true if the "Cancel" button was selected. - * It is up to the task thread to pool this and exit. - */ - @Override - public boolean isCancelRequested() { - return mUi.isCancelRequested(); - } - - /** - * Displays a yes/no question dialog box. - * - * This implementation allow this to be called from any thread, it - * makes sure the dialog is opened synchronously in the ui thread. - * - * @param title The title of the dialog box - * @param message The error message - * @return true if YES was clicked. - */ - @Override - public boolean displayPrompt(final String title, final String message) { - return mUi.displayPrompt(title, message); - } - - /** - * Displays a Login/Password dialog. This implementation allows this method to be - * called from any thread, it makes sure the dialog is opened synchronously - * in the ui thread. - * - * @param title The title of the dialog box - * @param message Message to be displayed - * @return Pair with entered login/password. Login is always the first - * element and Password is always the second. If any error occurs a - * pair with empty strings is returned. - */ - @Override - public UserCredentials displayLoginCredentialsPrompt(String title, String message) { - return mUi.displayLoginCredentialsPrompt(title, message); - } - - /** - * Creates a sub-monitor that will use up to tickCount on the progress bar. - * tickCount must be 1 or more. - */ - @Override - public ITaskMonitor createSubMonitor(int tickCount) { - assert mIncCoef > 0; - assert tickCount > 0; - return new SubTaskMonitor(this, null, mValue, tickCount * mIncCoef); - } - - // ----- ILogger interface ---- - - @Override - public void error(Throwable throwable, String errorFormat, Object... arg) { - if (errorFormat != null) { - logError("Error: " + errorFormat, arg); - } - - if (throwable != null) { - logError("%s", throwable.getMessage()); //$NON-NLS-1$ - } - } - - @Override - public void warning(@NonNull String warningFormat, Object... arg) { - log("Warning: " + warningFormat, arg); - } - - @Override - public void info(@NonNull String msgFormat, Object... arg) { - log(msgFormat, arg); - } - - @Override - public void verbose(@NonNull String msgFormat, Object... arg) { - log(msgFormat, arg); - } - - // ----- Sub Monitor ----- - - private static class SubTaskMonitor implements ISubTaskMonitor { - - private final TaskMonitorImpl mRoot; - private final ISubTaskMonitor mParent; - private final double mStart; - private final double mSpan; - private double mSubValue; - private double mSubCoef; - - /** - * Creates a new sub task monitor which will work for the given range [start, start+span] - * in its parent. - * - * @param taskMonitor The ProgressTask root - * @param parent The immediate parent. Can be the null or another sub task monitor. - * @param start The start value in the root's coordinates - * @param span The span value in the root's coordinates - */ - public SubTaskMonitor(TaskMonitorImpl taskMonitor, - ISubTaskMonitor parent, - double start, - double span) { - mRoot = taskMonitor; - mParent = parent; - mStart = start; - mSpan = span; - mSubValue = start; - } - - @Override - public boolean isCancelRequested() { - return mRoot.isCancelRequested(); - } - - @Override - public void setDescription(String format, Object... args) { - mRoot.setDescription(format, args); - } - - @Override - public void log(String format, Object... args) { - mRoot.log(format, args); - } - - @Override - public void logError(String format, Object... args) { - mRoot.logError(format, args); - } - - @Override - public void logVerbose(String format, Object... args) { - mRoot.logVerbose(format, args); - } - - @Override - public void setProgressMax(int max) { - assert max > 0; - mSubCoef = max > 0 ? mSpan / max : 0; - assert mSubCoef > 0; - } - - @Override - public int getProgressMax() { - return mSubCoef > 0 ? (int) (mSpan / mSubCoef) : 0; - } - - @Override - public int getProgress() { - // subCoef can be 0 if setProgressMax() and incProgress() haven't been called yet - assert mSubValue == mStart || mSubCoef > 0; - return mSubCoef > 0 ? (int)((mSubValue - mStart) / mSubCoef) : 0; - } - - @Override - public void incProgress(int delta) { - if (delta > 0 && mSubCoef > 0) { - subIncProgress(delta * mSubCoef); - } - } - - @Override - public void subIncProgress(double realDelta) { - mSubValue += realDelta; - if (mParent != null) { - mParent.subIncProgress(realDelta); - } else { - mRoot.internalIncProgress(realDelta); - } - } - - @Override - public boolean displayPrompt(String title, String message) { - return mRoot.displayPrompt(title, message); - } - - @Override - public UserCredentials displayLoginCredentialsPrompt(String title, String message) { - return mRoot.displayLoginCredentialsPrompt(title, message); - } - - @Override - public ITaskMonitor createSubMonitor(int tickCount) { - assert mSubCoef > 0; - assert tickCount > 0; - return new SubTaskMonitor(mRoot, - this, - mSubValue, - tickCount * mSubCoef); - } - - // ----- ILogger interface ---- - - @Override - public void error(Throwable throwable, String errorFormat, Object... arg) { - mRoot.error(throwable, errorFormat, arg); - } - - @Override - public void warning(@NonNull String warningFormat, Object... arg) { - mRoot.warning(warningFormat, arg); - } - - @Override - public void info(@NonNull String msgFormat, Object... arg) { - mRoot.info(msgFormat, arg); - } - - @Override - public void verbose(@NonNull String msgFormat, Object... arg) { - mRoot.verbose(msgFormat, arg); - } - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java deleted file mode 100644 index c583762..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java +++ /dev/null @@ -1,1392 +0,0 @@ -/* - * Copyright (C) 2012 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.SdkConstants; -import com.android.annotations.Nullable; -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.resources.Density; -import com.android.resources.ScreenSize; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.ISystemImage; -import com.android.sdklib.SdkManager; -import com.android.sdklib.devices.Camera; -import com.android.sdklib.devices.CameraLocation; -import com.android.sdklib.devices.Device; -import com.android.sdklib.devices.DeviceManager; -import com.android.sdklib.devices.Hardware; -import com.android.sdklib.devices.Screen; -import com.android.sdklib.devices.Software; -import com.android.sdklib.devices.Storage; -import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdklib.internal.avd.AvdManager.AvdConflict; -import com.android.sdklib.internal.avd.HardwareProperties; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.ui.GridDialog; -import com.android.utils.ILogger; -import com.android.utils.Pair; - -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.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.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.FileDialog; -import org.eclipse.swt.widgets.Group; -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.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class AvdCreationDialog extends GridDialog { - - private AvdManager mAvdManager; - private ImageFactory mImageFactory; - private ILogger mSdkLog; - private AvdInfo mAvdInfo; - private boolean mHaveSystemImage; - - private final TreeMap<String, IAndroidTarget> mCurrentTargets = - new TreeMap<String, IAndroidTarget>(); - - private Button mOkButton; - - private Text mAvdName; - - private Combo mDevice; - - private Combo mTarget; - private Combo mAbi; - - private Button mKeyboard; - private Button mSkin; - - private Combo mFrontCamera; - private Combo mBackCamera; - - private Button mSnapshot; - private Button mGpuEmulation; - - private Text mRam; - private Text mVmHeap; - - private Text mDataPartition; - private Combo mDataPartitionSize; - - private Button mSdCardSizeRadio; - private Text mSdCardSize; - private Combo mSdCardSizeCombo; - private Button mSdCardFileRadio; - private Text mSdCardFile; - private Button mBrowseSdCard; - - private Button mForceCreation; - private Composite mStatusComposite; - - private Label mStatusIcon; - private Label mStatusLabel; - - private Device mInitWithDevice; - private AvdInfo mCreatedAvd; - - /** - * {@link VerifyListener} for {@link Text} widgets that should only contains - * numbers. - */ - private final VerifyListener mDigitVerifier = new VerifyListener() { - @Override - public void verifyText(VerifyEvent event) { - int count = event.text.length(); - for (int i = 0; i < count; i++) { - char c = event.text.charAt(i); - if (c < '0' || c > '9') { - event.doit = false; - return; - } - } - } - }; - - public AvdCreationDialog(Shell shell, - AvdManager avdManager, - ImageFactory imageFactory, - ILogger log, - AvdInfo editAvdInfo) { - - super(shell, 2, false); - mAvdManager = avdManager; - mImageFactory = imageFactory; - mSdkLog = log; - mAvdInfo = editAvdInfo; - } - - /** Returns the AVD Created, if successful. */ - public AvdInfo getCreatedAvd() { - return mCreatedAvd; - } - - @Override - protected Control createContents(Composite parent) { - Control control = super.createContents(parent); - getShell().setText(mAvdInfo == null ? "Create new Android Virtual Device (AVD)" - : "Edit Android Virtual Device (AVD)"); - - mOkButton = getButton(IDialogConstants.OK_ID); - - if (mAvdInfo != null) { - fillExistingAvdInfo(mAvdInfo); - } else if (mInitWithDevice != null) { - fillInitialDeviceInfo(mInitWithDevice); - } - - validatePage(); - return control; - } - - @Override - public void createDialogContent(Composite parent) { - - Label label; - String tooltip; - ValidateListener validateListener = new ValidateListener(); - - // --- avd name - label = new Label(parent, SWT.NONE); - label.setText("AVD Name:"); - tooltip = "The name of the Android Virtual Device"; - label.setToolTipText(tooltip); - mAvdName = new Text(parent, SWT.BORDER); - mAvdName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mAvdName.addModifyListener(new CreateNameModifyListener()); - - // --- device selection - label = new Label(parent, SWT.NONE); - label.setText("Device:"); - tooltip = "The device this AVD will be based on"; - mDevice = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN); - mDevice.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - initializeDevices(); - mDevice.addSelectionListener(new DeviceSelectionListener()); - - // --- api target - label = new Label(parent, SWT.NONE); - label.setText("Target:"); - tooltip = "The target API of the AVD"; - label.setToolTipText(tooltip); - mTarget = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN); - mTarget.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mTarget.setToolTipText(tooltip); - mTarget.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - reloadAbiTypeCombo(); - validatePage(); - } - }); - - reloadTargetCombo(); - - // --- avd ABIs - label = new Label(parent, SWT.NONE); - label.setText("CPU/ABI:"); - tooltip = "The CPU/ABI of the virtual device"; - label.setToolTipText(tooltip); - mAbi = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN); - mAbi.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mAbi.setToolTipText(tooltip); - mAbi.addSelectionListener(validateListener); - - label = new Label(parent, SWT.NONE); - label.setText("Keyboard:"); - mKeyboard = new Button(parent, SWT.CHECK); - mKeyboard.setSelection(true); // default to having a keyboard irrespective of device - mKeyboard.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mKeyboard.setText("Hardware keyboard present"); - - label = new Label(parent, SWT.NONE); - label.setText("Skin:"); - mSkin = new Button(parent, SWT.CHECK); - mSkin.setSelection(true); - mSkin.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mSkin.setText("Display a skin with hardware controls"); - - label = new Label(parent, SWT.NONE); - label.setText("Front Camera:"); - tooltip = ""; - label.setToolTipText(tooltip); - mFrontCamera = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN); - mFrontCamera.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mFrontCamera.add("None"); - mFrontCamera.add("Emulated"); - mFrontCamera.add("Webcam0"); - mFrontCamera.select(0); - - label = new Label(parent, SWT.NONE); - label.setText("Back Camera:"); - tooltip = ""; - label.setToolTipText(tooltip); - mBackCamera = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN); - mBackCamera.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mBackCamera.add("None"); - mBackCamera.add("Emulated"); - mBackCamera.add("Webcam0"); - mBackCamera.select(0); - - toggleCameras(); - - // --- memory options group - label = new Label(parent, SWT.NONE); - label.setText("Memory Options:"); - - - Group memoryGroup = new Group(parent, SWT.BORDER); - memoryGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - memoryGroup.setLayout(new GridLayout(4, false)); - - label = new Label(memoryGroup, SWT.NONE); - label.setText("RAM:"); - tooltip = "The amount of RAM the emulated device should have in MiB"; - label.setToolTipText(tooltip); - mRam = new Text(memoryGroup, SWT.BORDER); - mRam.addVerifyListener(mDigitVerifier); - mRam.addModifyListener(validateListener); - mRam.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - label = new Label(memoryGroup, SWT.NONE); - label.setText("VM Heap:"); - tooltip = "The amount of memory, in MiB, available to typical Android applications"; - label.setToolTipText(tooltip); - mVmHeap = new Text(memoryGroup, SWT.BORDER); - mVmHeap.addVerifyListener(mDigitVerifier); - mVmHeap.addModifyListener(validateListener); - mVmHeap.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mVmHeap.setToolTipText(tooltip); - - // --- Data partition group - label = new Label(parent, SWT.NONE); - label.setText("Internal Storage:"); - tooltip = "The size of the data partition on the device."; - Group storageGroup = new Group(parent, SWT.NONE); - storageGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - storageGroup.setLayout(new GridLayout(2, false)); - mDataPartition = new Text(storageGroup, SWT.BORDER); - mDataPartition.setText("200"); - mDataPartition.addVerifyListener(mDigitVerifier); - mDataPartition.addModifyListener(validateListener); - mDataPartition.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mDataPartitionSize = new Combo(storageGroup, SWT.READ_ONLY | SWT.DROP_DOWN); - mDataPartitionSize.add("MiB"); - mDataPartitionSize.add("GiB"); - mDataPartitionSize.select(0); - mDataPartitionSize.addModifyListener(validateListener); - - // --- sd card group - label = new Label(parent, SWT.NONE); - label.setText("SD Card:"); - label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, - false, false)); - - final Group sdCardGroup = new Group(parent, SWT.NONE); - sdCardGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - sdCardGroup.setLayout(new GridLayout(3, false)); - - mSdCardSizeRadio = new Button(sdCardGroup, SWT.RADIO); - mSdCardSizeRadio.setText("Size:"); - mSdCardSizeRadio.setToolTipText("Create a new SD Card file"); - mSdCardSizeRadio.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - boolean sizeMode = mSdCardSizeRadio.getSelection(); - enableSdCardWidgets(sizeMode); - validatePage(); - } - }); - - mSdCardSize = new Text(sdCardGroup, SWT.BORDER); - mSdCardSize.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mSdCardSize.addVerifyListener(mDigitVerifier); - mSdCardSize.addModifyListener(validateListener); - mSdCardSize.setToolTipText("Size of the new SD Card file (must be at least 9 MiB)"); - - mSdCardSizeCombo = new Combo(sdCardGroup, SWT.DROP_DOWN | SWT.READ_ONLY); - mSdCardSizeCombo.add("KiB"); - mSdCardSizeCombo.add("MiB"); - mSdCardSizeCombo.add("GiB"); - mSdCardSizeCombo.select(1); - mSdCardSizeCombo.addSelectionListener(validateListener); - - mSdCardFileRadio = new Button(sdCardGroup, SWT.RADIO); - mSdCardFileRadio.setText("File:"); - mSdCardFileRadio.setToolTipText("Use an existing file for the SD Card"); - - mSdCardFile = new Text(sdCardGroup, SWT.BORDER); - mSdCardFile.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mSdCardFile.addModifyListener(validateListener); - mSdCardFile.setToolTipText("File to use for the SD Card"); - - mBrowseSdCard = new Button(sdCardGroup, SWT.PUSH); - mBrowseSdCard.setText("Browse..."); - mBrowseSdCard.setToolTipText("Select the file to use for the SD Card"); - mBrowseSdCard.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - onBrowseSdCard(); - validatePage(); - } - }); - - mSdCardSizeRadio.setSelection(true); - enableSdCardWidgets(true); - - // --- avd options group - label = new Label(parent, SWT.NONE); - label.setText("Emulation Options:"); - Group optionsGroup = new Group(parent, SWT.NONE); - optionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - optionsGroup.setLayout(new GridLayout(2, true)); - mSnapshot = new Button(optionsGroup, SWT.CHECK); - mSnapshot.setText("Snapshot"); - mSnapshot.setToolTipText("Emulator's state will be persisted between emulator executions"); - mSnapshot.addSelectionListener(validateListener); - mGpuEmulation = new Button(optionsGroup, SWT.CHECK); - mGpuEmulation.setText("Use Host GPU"); - mGpuEmulation.setToolTipText("Enable hardware OpenGLES emulation"); - mGpuEmulation.addSelectionListener(validateListener); - - // --- force creation group - mForceCreation = new Button(parent, SWT.CHECK); - mForceCreation.setText("Override the existing AVD with the same name"); - mForceCreation - .setToolTipText("There's already an AVD with the same name. Check this to delete it and replace it by the new AVD."); - mForceCreation.setLayoutData(new GridData(GridData.BEGINNING, 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(parent, 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(parent, 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(""); //$NON-NLS-1$ - } - - @Nullable - private Device getSelectedDevice() { - Device[] devices = (Device[]) mDevice.getData(); - if (devices != null) { - int index = mDevice.getSelectionIndex(); - if (index != -1 && index < devices.length) { - return devices[index]; - } - } - - return null; - } - - private void selectDevice(String manufacturer, String name) { - Device[] devices = (Device[]) mDevice.getData(); - if (devices != null) { - for (int i = 0, n = devices.length; i < n; i++) { - Device device = devices[i]; - if (device.getManufacturer().equals(manufacturer) - && device.getName().equals(name)) { - mDevice.select(i); - break; - } - } - } - } - - private void selectDevice(Device device) { - Device[] devices = (Device[]) mDevice.getData(); - if (devices != null) { - for (int i = 0, n = devices.length; i < n; i++) { - if (devices[i].equals(device)) { - mDevice.select(i); - break; - } - } - } - } - - private void initializeDevices() { - assert mDevice != null; - - SdkManager sdkManager = mAvdManager.getSdkManager(); - String location = sdkManager.getLocation(); - if (sdkManager != null && location != null) { - DeviceManager deviceManager = DeviceManager.createInstance(location, mSdkLog); - List<Device> deviceList = deviceManager.getDevices(DeviceManager.ALL_DEVICES); - - // Sort - List<Device> nexus = new ArrayList<Device>(deviceList.size()); - List<Device> other = new ArrayList<Device>(deviceList.size()); - for (Device device : deviceList) { - if (isNexus(device) && !isGeneric(device)) { - nexus.add(device); - } else { - other.add(device); - } - } - Collections.reverse(other); - Collections.sort(nexus, new Comparator<Device>() { - @Override - public int compare(Device device1, Device device2) { - // Descending order of age - return nexusRank(device2) - nexusRank(device1); - } - }); - List<Device> all = nexus; - all.addAll(other); - - Device[] devices = all.toArray(new Device[all.size()]); - String[] labels = new String[devices.length]; - for (int i = 0, n = devices.length; i < n; i++) { - Device device = devices[i]; - if (isNexus(device) && !isGeneric(device)) { - labels[i] = getNexusLabel(device); - } else { - labels[i] = getGenericLabel(device); - } - } - mDevice.setData(devices); - mDevice.setItems(labels); - } - } - - /** - * Can be called after the constructor to set the default device for this AVD. - * Useful especially for new AVDs. - * @param device - */ - public void selectInitialDevice(Device device) { - mInitWithDevice = device; - } - - /** - * {@link ModifyListener} used for live-validation of the fields content. - */ - private class ValidateListener extends SelectionAdapter implements ModifyListener { - @Override - public void modifyText(ModifyEvent e) { - validatePage(); - } - - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - validatePage(); - } - } - - /** - * Callback when the AVD name is changed. When creating a new AVD, enables - * the force checkbox if the name is a duplicate. When editing an existing - * AVD, it's OK for the name to match the existing AVD. - */ - private class CreateNameModifyListener implements ModifyListener { - @Override - public void modifyText(ModifyEvent e) { - String name = mAvdName.getText().trim(); - if (mAvdInfo == null || !name.equals(mAvdInfo.getName())) { - // Case where we're creating a new AVD or editing an existing - // one - // and the AVD name has been changed... check for name - // uniqueness. - - Pair<AvdConflict, String> conflict = mAvdManager.isAvdNameConflicting(name); - if (conflict.getFirst() != AvdManager.AvdConflict.NO_CONFLICT) { - // If we're changing the state from disabled to enabled, - // make sure - // to uncheck the button, to force the user to voluntarily - // re-enforce it. - // This happens when editing an existing AVD and changing - // the name from - // the existing AVD to another different existing AVD. - if (!mForceCreation.isEnabled()) { - mForceCreation.setEnabled(true); - mForceCreation.setSelection(false); - } - } else { - mForceCreation.setEnabled(false); - mForceCreation.setSelection(false); - } - } else { - // Case where we're editing an existing AVD with the name - // unchanged. - - mForceCreation.setEnabled(false); - mForceCreation.setSelection(false); - } - validatePage(); - } - } - - private class DeviceSelectionListener extends SelectionAdapter { - - @Override - public void widgetSelected(SelectionEvent arg0) { - Device currentDevice = getSelectedDevice(); - if (currentDevice != null) { - fillDeviceProperties(currentDevice); - } - - toggleCameras(); - validatePage(); - } - } - - private void fillDeviceProperties(Device device) { - Hardware hw = device.getDefaultHardware(); - Long ram = hw.getRam().getSizeAsUnit(Storage.Unit.MiB); - mRam.setText(Long.toString(ram)); - - // Set the default VM heap size. This is based on the Android CDD minimums for each - // screen size and density. - Screen s = hw.getScreen(); - ScreenSize size = s.getSize(); - Density density = s.getPixelDensity(); - int vmHeapSize = 32; - if (size.equals(ScreenSize.XLARGE)) { - switch (density) { - case LOW: - case MEDIUM: - vmHeapSize = 32; - break; - case TV: - case HIGH: - vmHeapSize = 64; - break; - case XHIGH: - case XXHIGH: - vmHeapSize = 128; - break; - case NODPI: - break; - } - } else { - switch (density) { - case LOW: - case MEDIUM: - vmHeapSize = 16; - break; - case TV: - case HIGH: - vmHeapSize = 32; - break; - case XHIGH: - case XXHIGH: - vmHeapSize = 64; - break; - case NODPI: - break; - } - } - mVmHeap.setText(Integer.toString(vmHeapSize)); - - List<Software> allSoftware = device.getAllSoftware(); - if (allSoftware != null && !allSoftware.isEmpty()) { - Software first = allSoftware.get(0); - int min = first.getMinSdkLevel();; - int max = first.getMaxSdkLevel();; - for (int i = 1; i < allSoftware.size(); i++) { - min = Math.min(min, first.getMinSdkLevel()); - max = Math.max(max, first.getMaxSdkLevel()); - } - if (mCurrentTargets != null) { - int bestApiLevel = Integer.MAX_VALUE; - IAndroidTarget bestTarget = null; - for (IAndroidTarget target : mCurrentTargets.values()) { - if (!target.isPlatform()) { - continue; - } - int apiLevel = target.getVersion().getApiLevel(); - if (apiLevel >= min && apiLevel <= max) { - if (bestTarget == null || apiLevel < bestApiLevel) { - bestTarget = target; - bestApiLevel = apiLevel; - } - } - } - - if (bestTarget != null) { - selectTarget(bestTarget); - reloadAbiTypeCombo(); - } - } - } - } - - private void toggleCameras() { - mFrontCamera.setEnabled(false); - mBackCamera.setEnabled(false); - Device d = getSelectedDevice(); - if (d != null) { - for (Camera c : d.getDefaultHardware().getCameras()) { - if (CameraLocation.FRONT.equals(c.getLocation())) { - mFrontCamera.setEnabled(true); - } - if (CameraLocation.BACK.equals(c.getLocation())) { - mBackCamera.setEnabled(true); - } - } - } - } - - private void reloadTargetCombo() { - String selected = null; - int index = mTarget.getSelectionIndex(); - if (index >= 0) { - selected = mTarget.getItem(index); - } - - mCurrentTargets.clear(); - mTarget.removeAll(); - - boolean found = false; - index = -1; - - List<IAndroidTarget> targetData = new ArrayList<IAndroidTarget>(); - SdkManager sdkManager = mAvdManager.getSdkManager(); - if (sdkManager != null) { - for (IAndroidTarget target : sdkManager.getTargets()) { - String name; - if (target.isPlatform()) { - name = String.format("%s - API Level %s", - target.getName(), - target.getVersion().getApiString()); - } else { - name = String.format("%s (%s) - API Level %s", - target.getName(), - target.getVendor(), - target.getVersion().getApiString()); - } - mCurrentTargets.put(name, target); - mTarget.add(name); - targetData.add(target); - if (!found) { - index++; - found = name.equals(selected); - } - } - } - - mTarget.setEnabled(mCurrentTargets.size() > 0); - mTarget.setData(targetData.toArray(new IAndroidTarget[targetData.size()])); - - if (found) { - mTarget.select(index); - } - } - - private void selectTarget(IAndroidTarget target) { - IAndroidTarget[] targets = (IAndroidTarget[]) mTarget.getData(); - if (targets != null) { - for (int i = 0; i < targets.length; i++) { - if (target == targets[i]) { - mTarget.select(i); - break; - } - } - } - } - - @SuppressWarnings("unused") - @Deprecated // FIXME unused, cleanup later - private IAndroidTarget getSelectedTarget() { - IAndroidTarget[] targets = (IAndroidTarget[]) mTarget.getData(); - int index = mTarget.getSelectionIndex(); - if (targets != null && index != -1 && index < targets.length) { - return targets[index]; - } - - return null; - } - - /** - * Reload all the abi types in the selection list - */ - private void reloadAbiTypeCombo() { - String selected = null; - boolean found = false; - - int index = mTarget.getSelectionIndex(); - if (index >= 0) { - String targetName = mTarget.getItem(index); - IAndroidTarget target = mCurrentTargets.get(targetName); - - ISystemImage[] systemImages = getSystemImages(target); - - mAbi.setEnabled(systemImages.length > 1); - - // If user explicitly selected an ABI before, preserve that option - // If user did not explicitly select before (only one option before) - // force them to select - index = mAbi.getSelectionIndex(); - if (index >= 0 && mAbi.getItemCount() > 1) { - selected = mAbi.getItem(index); - } - - mAbi.removeAll(); - - int i; - for (i = 0; i < systemImages.length; i++) { - String prettyAbiType = AvdInfo.getPrettyAbiType(systemImages[i].getAbiType()); - mAbi.add(prettyAbiType); - if (!found) { - found = prettyAbiType.equals(selected); - if (found) { - mAbi.select(i); - } - } - } - - mHaveSystemImage = systemImages.length > 0; - if (!mHaveSystemImage) { - mAbi.add("No system images installed for this target."); - mAbi.select(0); - } else if (systemImages.length == 1) { - mAbi.select(0); - } - } - } - - /** - * Enable or disable the sd card widgets. - * - * @param sizeMode if true the size-based widgets are to be enabled, and the - * file-based ones disabled. - */ - private void enableSdCardWidgets(boolean sizeMode) { - mSdCardSize.setEnabled(sizeMode); - mSdCardSizeCombo.setEnabled(sizeMode); - - mSdCardFile.setEnabled(!sizeMode); - mBrowseSdCard.setEnabled(!sizeMode); - } - - 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) { - mSdCardFile.setText(fileName); - } - } - - @Override - public void okPressed() { - if (createAvd()) { - super.okPressed(); - } - } - - private void validatePage() { - String error = null; - String warning = null; - boolean valid = true; - - if (mAvdName.getText().isEmpty()) { - error = "AVD Name cannot be empty"; - setPageValid(false, error, warning); - return; - } - - String avdName = mAvdName.getText(); - if (!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); - setPageValid(false, error, warning); - return; - } - - if (mDevice.getSelectionIndex() < 0) { - setPageValid(false, error, warning); - return; - } - - if (mTarget.getSelectionIndex() < 0 || - !mHaveSystemImage || mAbi.getSelectionIndex() < 0) { - setPageValid(false, error, warning); - return; - } - - if (mRam.getText().isEmpty()) { - setPageValid(false, error, warning); - return; - } - - if (mVmHeap.getText().isEmpty()) { - setPageValid(false, error, warning); - return; - } - - if (mDataPartition.getText().isEmpty() || mDataPartitionSize.getSelectionIndex() < 0) { - error = "Invalid Data partition size."; - setPageValid(false, error, warning); - return; - } - - // validate sdcard size or file - if (mSdCardSizeRadio.getSelection()) { - if (!mSdCardSize.getText().isEmpty() && mSdCardSizeCombo.getSelectionIndex() >= 0) { - try { - long sdSize = Long.parseLong(mSdCardSize.getText()); - - int sizeIndex = mSdCardSizeCombo.getSelectionIndex(); - if (sizeIndex >= 0) { - // index 0 shifts by 10 (1024=K), index 1 by 20, etc. - sdSize <<= 10 * (1 + sizeIndex); - } - - if (sdSize < AvdManager.SDCARD_MIN_BYTE_SIZE || - sdSize > AvdManager.SDCARD_MAX_BYTE_SIZE) { - valid = false; - error = "SD Card size is invalid. Range is 9 MiB..1023 GiB."; - } - } catch (NumberFormatException e) { - valid = false; - error = " SD Card size must be a valid integer between 9 MiB and 1023 GiB"; - } - } - } else { - if (mSdCardFile.getText().isEmpty() || !new File(mSdCardFile.getText()).isFile()) { - valid = false; - error = "SD Card path isn't valid."; - } - } - if (!valid) { - setPageValid(valid, error, warning); - return; - } - - if (mForceCreation.isEnabled() && !mForceCreation.getSelection()) { - valid = false; - error = String.format( - "The AVD name '%s' is already used.\n" + - "Check \"Override the existing AVD\" to delete the existing one.", - mAvdName.getText()); - } - - if (mAvdInfo != null && !mAvdInfo.getName().equals(mAvdName.getText())) { - warning = String.format("The AVD '%1$s' will be duplicated into '%2$s'.", - mAvdInfo.getName(), - mAvdName.getText()); - } - - // On Windows, display a warning if attempting to create AVD's with RAM > 512 MB. - // This restriction should go away when we switch to using a 64 bit emulator. - if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_WINDOWS) { - long ramSize = 0; - try { - ramSize = Long.parseLong(mRam.getText()); - } catch (NumberFormatException e) { - // ignore - } - - if (ramSize > 768) { - warning = "On Windows, emulating RAM greater than 768M may fail depending on the" - + " system load.\nTry progressively smaller values of RAM if the emulator" - + " fails to launch."; - } - } - - if (mGpuEmulation.getSelection() && mSnapshot.getSelection()) { - valid = false; - error = "GPU Emulation and Snapshot cannot be used simultaneously"; - } - - setPageValid(valid, error, warning); - return; - } - - private void setPageValid(boolean valid, String error, String warning) { - mOkButton.setEnabled(valid); - if (error != null) { - mStatusIcon.setImage(mImageFactory.getImageByName("reject_icon16.png")); //$NON-NLS-1$ - mStatusLabel.setText(error); - } else if (warning != null) { - mStatusIcon.setImage(mImageFactory.getImageByName("warning_icon16.png")); //$NON-NLS-1$ - mStatusLabel.setText(warning); - } else { - mStatusIcon.setImage(null); - mStatusLabel.setText(" \n "); //$NON-NLS-1$ - } - - mStatusComposite.pack(true); - } - - private boolean createAvd() { - - String avdName = mAvdName.getText(); - if (avdName == null || avdName.isEmpty()) { - return false; - } - - String targetName = mTarget.getItem(mTarget.getSelectionIndex()); - IAndroidTarget target = mCurrentTargets.get(targetName); - if (target == null) { - return false; - } - - // get the abi type - String abiType = SdkConstants.ABI_ARMEABI; - ISystemImage[] systemImages = getSystemImages(target); - if (systemImages.length > 0) { - int abiIndex = mAbi.getSelectionIndex(); - if (abiIndex >= 0) { - String prettyname = mAbi.getItem(abiIndex); - // Extract the abi type - int firstIndex = prettyname.indexOf("("); - int lastIndex = prettyname.indexOf(")"); - abiType = prettyname.substring(firstIndex + 1, lastIndex); - } - } - - // get the SD card data from the UI. - String sdName = null; - if (mSdCardSizeRadio.getSelection()) { - // size mode - String value = mSdCardSize.getText().trim(); - if (value.length() > 0) { - sdName = value; - // add the unit - switch (mSdCardSizeCombo.getSelectionIndex()) { - case 0: - sdName += "K"; //$NON-NLS-1$ - break; - case 1: - sdName += "M"; //$NON-NLS-1$ - break; - case 2: - sdName += "G"; //$NON-NLS-1$ - break; - default: - // shouldn't be here - assert false; - } - } - } else { - // file mode. - sdName = mSdCardFile.getText().trim(); - } - - // Get the device - Device device = getSelectedDevice(); - if (device == null) { - return false; - } - - Screen s = device.getDefaultHardware().getScreen(); - String skinName = s.getXDimension() + "x" + s.getYDimension(); - - ILogger log = mSdkLog; - if (log == null || log instanceof MessageBoxLog) { - // If the current logger is a message box, we use our own (to make sure - // to display errors right away and customize the title). - log = new MessageBoxLog( - String.format("Result of creating AVD '%s':", avdName), - getContents().getDisplay(), - false /* logErrorsOnly */); - } - - Map<String, String> hwProps = DeviceManager.getHardwareProperties(device); - if (mGpuEmulation.getSelection()) { - hwProps.put(AvdManager.AVD_INI_GPU_EMULATION, HardwareProperties.BOOLEAN_YES); - } - - File avdFolder = null; - try { - avdFolder = AvdInfo.getDefaultAvdFolder(mAvdManager, avdName); - } catch (AndroidLocationException e) { - return false; - } - - // Although the device has this information, some devices have more RAM than we'd want to - // allocate to an emulator. - hwProps.put(AvdManager.AVD_INI_RAM_SIZE, mRam.getText()); - hwProps.put(AvdManager.AVD_INI_VM_HEAP_SIZE, mVmHeap.getText()); - - String suffix; - switch (mDataPartitionSize.getSelectionIndex()) { - case 0: - suffix = "M"; - break; - case 1: - suffix = "G"; - break; - default: - suffix = "K"; - } - hwProps.put(AvdManager.AVD_INI_DATA_PARTITION_SIZE, mDataPartition.getText()+suffix); - - hwProps.put(HardwareProperties.HW_KEYBOARD, - mKeyboard.getSelection() ? - HardwareProperties.BOOLEAN_YES : HardwareProperties.BOOLEAN_NO); - - hwProps.put(AvdManager.AVD_INI_SKIN_DYNAMIC, - mSkin.getSelection() ? - HardwareProperties.BOOLEAN_YES : HardwareProperties.BOOLEAN_NO); - - if (mFrontCamera.isEnabled()) { - hwProps.put(AvdManager.AVD_INI_CAMERA_FRONT, - mFrontCamera.getText().toLowerCase()); - } - - if (mBackCamera.isEnabled()) { - hwProps.put(AvdManager.AVD_INI_CAMERA_BACK, - mBackCamera.getText().toLowerCase()); - } - - if (sdName != null) { - hwProps.put(HardwareProperties.HW_SDCARD, HardwareProperties.BOOLEAN_YES); - } - - AvdInfo avdInfo = mAvdManager.createAvd(avdFolder, - avdName, - target, - abiType, - skinName, - sdName, - hwProps, - mSnapshot.getSelection(), - mForceCreation.getSelection(), - mAvdInfo != null, // edit existing - log); - - mCreatedAvd = avdInfo; - boolean success = avdInfo != null; - - if (log instanceof MessageBoxLog) { - ((MessageBoxLog) log).displayResult(success); - } - return success; - } - - private void fillExistingAvdInfo(AvdInfo avd) { - mAvdName.setText(avd.getName()); - selectDevice(avd.getDeviceManufacturer(), avd.getDeviceName()); - toggleCameras(); - - IAndroidTarget target = avd.getTarget(); - - if (target != null && !mCurrentTargets.isEmpty()) { - // Try to select the target in the target combo. - // This will fail if the AVD needs to be repaired. - // - // This is a linear search but the list is always - // small enough and we only do this once. - int n = mTarget.getItemCount(); - for (int i = 0; i < n; i++) { - if (target.equals(mCurrentTargets.get(mTarget.getItem(i)))) { - mTarget.select(i); - reloadAbiTypeCombo(); - break; - } - } - } - - ISystemImage[] systemImages = getSystemImages(target); - if (target != null && systemImages.length > 0) { - mAbi.setEnabled(systemImages.length > 1); - String abiType = AvdInfo.getPrettyAbiType(avd.getAbiType()); - int n = mAbi.getItemCount(); - for (int i = 0; i < n; i++) { - if (abiType.equals(mAbi.getItem(i))) { - mAbi.select(i); - break; - } - } - } - - Map<String, String> props = avd.getProperties(); - - if (props != null) { - String snapshots = props.get(AvdManager.AVD_INI_SNAPSHOT_PRESENT); - if (snapshots != null && snapshots.length() > 0) { - mSnapshot.setSelection(snapshots.equals("true")); - } - - String gpuEmulation = props.get(AvdManager.AVD_INI_GPU_EMULATION); - mGpuEmulation.setSelection(gpuEmulation != null && - gpuEmulation.equals(HardwareProperties.BOOLEAN_VALUES[0])); - - String sdcard = props.get(AvdManager.AVD_INI_SDCARD_PATH); - if (sdcard != null && sdcard.length() > 0) { - enableSdCardWidgets(false); - mSdCardSizeRadio.setSelection(false); - mSdCardFileRadio.setSelection(true); - mSdCardFile.setText(sdcard); - } - - String ramSize = props.get(AvdManager.AVD_INI_RAM_SIZE); - if (ramSize != null) { - mRam.setText(ramSize); - } - - String vmHeapSize = props.get(AvdManager.AVD_INI_VM_HEAP_SIZE); - if (vmHeapSize != null) { - mVmHeap.setText(vmHeapSize); - } - - String dataPartitionSize = props.get(AvdManager.AVD_INI_DATA_PARTITION_SIZE); - if (dataPartitionSize != null) { - mDataPartition.setText( - dataPartitionSize.substring(0, dataPartitionSize.length() - 1)); - switch (dataPartitionSize.charAt(dataPartitionSize.length() - 1)) { - case 'M': - mDataPartitionSize.select(0); - break; - case 'G': - mDataPartitionSize.select(1); - break; - default: - mDataPartitionSize.select(-1); - } - } - - mKeyboard.setSelection( - HardwareProperties.BOOLEAN_YES.equalsIgnoreCase( - props.get(HardwareProperties.HW_KEYBOARD))); - mSkin.setSelection( - HardwareProperties.BOOLEAN_YES.equalsIgnoreCase( - props.get(AvdManager.AVD_INI_SKIN_DYNAMIC))); - - String cameraFront = props.get(AvdManager.AVD_INI_CAMERA_FRONT); - if (cameraFront != null) { - String[] items = mFrontCamera.getItems(); - for (int i = 0; i < items.length; i++) { - if (items[i].toLowerCase().equals(cameraFront)) { - mFrontCamera.select(i); - break; - } - } - } - - String cameraBack = props.get(AvdManager.AVD_INI_CAMERA_BACK); - if (cameraBack != null) { - String[] items = mBackCamera.getItems(); - for (int i = 0; i < items.length; i++) { - if (items[i].toLowerCase().equals(cameraBack)) { - mBackCamera.select(i); - break; - } - } - } - - sdcard = props.get(AvdManager.AVD_INI_SDCARD_SIZE); - if (sdcard != null && sdcard.length() > 0) { - String[] values = new String[2]; - long sdcardSize = AvdManager.parseSdcardSize(sdcard, values); - - if (sdcardSize != AvdManager.SDCARD_NOT_SIZE_PATTERN) { - enableSdCardWidgets(true); - mSdCardFileRadio.setSelection(false); - mSdCardSizeRadio.setSelection(true); - - mSdCardSize.setText(values[0]); - - String suffix = values[1]; - int n = mSdCardSizeCombo.getItemCount(); - for (int i = 0; i < n; i++) { - if (mSdCardSizeCombo.getItem(i).startsWith(suffix)) { - mSdCardSizeCombo.select(i); - } - } - } - } - } - } - - private void fillInitialDeviceInfo(Device device) { - String name = device.getManufacturer(); - if (!name.equals("Generic") && // TODO define & use constants - !name.equals("User") && - device.getName().indexOf(name) == -1) { - name = " by " + name; - } else { - name = ""; - } - name = "AVD for " + device.getName() + name; - // sanitize the name - name = name.replaceAll("[^0-9a-zA-Z_-]+", " ").trim().replaceAll("[ _]+", "_"); - mAvdName.setText(name); - - // Select the device - selectDevice(device); - toggleCameras(); - - // If there's only one target, select it by default. - // TODO: if there are more than 1 target, select the higher platform target as - // a likely default. - if (mTarget.getItemCount() == 1) { - mTarget.select(0); - reloadAbiTypeCombo(); - } - - fillDeviceProperties(device); - } - - /** - * Returns the list of system images of a target. - * <p/> - * If target is null, returns an empty list. If target is an add-on with no - * system images, return the list from its parent platform. - * - * @param target An IAndroidTarget. Can be null. - * @return A non-null ISystemImage array. Can be empty. - */ - private ISystemImage[] getSystemImages(IAndroidTarget target) { - if (target != null) { - ISystemImage[] images = target.getSystemImages(); - - if ((images == null || images.length == 0) && !target.isPlatform()) { - // If an add-on does not provide any system images, use the ones - // from the parent. - images = target.getParent().getSystemImages(); - } - - if (images != null) { - return images; - } - } - - return new ISystemImage[0]; - } - - // Code copied from DeviceMenuListener in ADT; unify post release - - private static final String NEXUS = "Nexus"; //$NON-NLS-1$ - private static final String GENERIC = "Generic"; //$NON-NLS-1$ - private static Pattern PATTERN = Pattern.compile( - "(\\d+\\.?\\d*)in (.+?)( \\(.*Nexus.*\\))?"); //$NON-NLS-1$ - - private static int nexusRank(Device device) { - String name = device.getName(); - if (name.endsWith(" One")) { //$NON-NLS-1$ - return 1; - } - if (name.endsWith(" S")) { //$NON-NLS-1$ - return 2; - } - if (name.startsWith("Galaxy")) { //$NON-NLS-1$ - return 3; - } - if (name.endsWith(" 7")) { //$NON-NLS-1$ - return 4; - } - if (name.endsWith(" 10")) { //$NON-NLS-1$ - return 5; - } - if (name.endsWith(" 4")) { //$NON-NLS-1$ - return 6; - } - - return 7; - } - - private static boolean isGeneric(Device device) { - return device.getManufacturer().equals(GENERIC); - } - - private static boolean isNexus(Device device) { - return device.getName().contains(NEXUS); - } - - private static String getGenericLabel(Device d) { - // * Replace "'in'" with '"' (e.g. 2.7" QVGA instead of 2.7in QVGA) - // * Use the same precision for all devices (all but one specify decimals) - // * Add some leading space such that the dot ends up roughly in the - // same space - // * Add in screen resolution and density - String name = d.getName(); - if (name.equals("3.7 FWVGA slider")) { //$NON-NLS-1$ - // Fix metadata: this one entry doesn't have "in" like the rest of them - name = "3.7in FWVGA slider"; //$NON-NLS-1$ - } - - Matcher matcher = PATTERN.matcher(name); - if (matcher.matches()) { - String size = matcher.group(1); - String n = matcher.group(2); - int dot = size.indexOf('.'); - if (dot == -1) { - size = size + ".0"; - dot = size.length() - 2; - } - for (int i = 0; i < 2 - dot; i++) { - size = ' ' + size; - } - name = size + "\" " + n; - } - - return String.format(java.util.Locale.US, "%1$s (%2$s)", name, - getResolutionString(d)); - } - - private static String getNexusLabel(Device d) { - String name = d.getName(); - Screen screen = d.getDefaultHardware().getScreen(); - float length = (float) screen.getDiagonalLength(); - return String.format(java.util.Locale.US, "%1$s (%3$s\", %2$s)", - name, getResolutionString(d), Float.toString(length)); - } - - @Nullable - private static String getResolutionString(Device device) { - Screen screen = device.getDefaultHardware().getScreen(); - return String.format(java.util.Locale.US, - "%1$d \u00D7 %2$d: %3$s", // U+00D7: Unicode multiplication sign - screen.getXDimension(), - screen.getYDimension(), - screen.getPixelDensity().getResourceValue()); - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java deleted file mode 100644 index ce40360..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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.AndroidVersion; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdklib.internal.avd.AvdInfo.AvdStatus; -import com.android.sdkuilib.ui.GridDataBuilder; -import com.android.sdkuilib.ui.GridLayoutBuilder; -import com.android.sdkuilib.ui.SwtBaseDialog; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; - -import java.util.HashMap; -import java.util.Map; - -/** - * Dialog displaying the details of an AVD. - */ -final class AvdDetailsDialog extends SwtBaseDialog { - - private final AvdInfo mAvdInfo; - - public AvdDetailsDialog(Shell shell, AvdInfo avdInfo) { - super(shell, SWT.APPLICATION_MODAL, "AVD details"); - mAvdInfo = avdInfo; - } - - /** - * Create contents of the dialog. - */ - @Override - protected void createContents() { - Shell shell = getShell(); - GridLayoutBuilder.create(shell).columns(2); - GridDataBuilder.create(shell).fill(); - - GridLayout gl; - - Composite c = new Composite(shell, SWT.NONE); - c.setLayout(gl = new GridLayout(2, false)); - gl.marginHeight = gl.marginWidth = 0; - c.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - if (mAvdInfo != null) { - displayValue(c, "Name:", mAvdInfo.getName()); - displayValue(c, "CPU/ABI:", AvdInfo.getPrettyAbiType(mAvdInfo.getAbiType())); - - displayValue(c, "Path:", mAvdInfo.getDataFolderPath()); - - if (mAvdInfo.getStatus() != AvdStatus.OK) { - displayValue(c, "Error:", mAvdInfo.getErrorMessage()); - } else { - IAndroidTarget target = mAvdInfo.getTarget(); - AndroidVersion version = target.getVersion(); - displayValue(c, "Target:", String.format("%s (API level %s)", - target.getName(), version.getApiString())); - - // display some extra values. - Map<String, String> properties = mAvdInfo.getProperties(); - if (properties != null) { - String skin = properties.get(AvdManager.AVD_INI_SKIN_NAME); - if (skin != null) { - displayValue(c, "Skin:", skin); - } - - String sdcard = properties.get(AvdManager.AVD_INI_SDCARD_SIZE); - if (sdcard == null) { - sdcard = properties.get(AvdManager.AVD_INI_SDCARD_PATH); - } - if (sdcard != null) { - displayValue(c, "SD Card:", sdcard); - } - - String snapshot = properties.get(AvdManager.AVD_INI_SNAPSHOT_PRESENT); - if (snapshot != null) { - displayValue(c, "Snapshot:", snapshot); - } - - // display other hardware - HashMap<String, String> copy = new HashMap<String, String>(properties); - // remove stuff we already displayed (or that we don't want to display) - copy.remove(AvdManager.AVD_INI_ABI_TYPE); - copy.remove(AvdManager.AVD_INI_CPU_ARCH); - copy.remove(AvdManager.AVD_INI_SKIN_NAME); - copy.remove(AvdManager.AVD_INI_SKIN_PATH); - copy.remove(AvdManager.AVD_INI_SDCARD_SIZE); - copy.remove(AvdManager.AVD_INI_SDCARD_PATH); - copy.remove(AvdManager.AVD_INI_IMAGES_1); - copy.remove(AvdManager.AVD_INI_IMAGES_2); - - if (copy.size() > 0) { - Label l = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL); - l.setLayoutData(new GridData( - GridData.FILL, GridData.CENTER, false, false, 2, 1)); - - c = new Composite(shell, SWT.NONE); - c.setLayout(gl = new GridLayout(2, false)); - gl.marginHeight = gl.marginWidth = 0; - c.setLayoutData(new GridData(GridData.FILL_BOTH)); - - for (Map.Entry<String, String> entry : copy.entrySet()) { - displayValue(c, entry.getKey() + ":", entry.getValue()); - } - } - } - } - } - } - - // -- Start of internal part ---------- - // Hide everything down-below from SWT designer - //$hide>>$ - - - @Override - protected void postCreate() { - // pass - } - - /** - * Displays a value with a label. - * - * @param parent the parent Composite in which to display the value. This Composite must use a - * {@link GridLayout} with 2 columns. - * @param label the label of the value to display. - * @param value the string value to display. - */ - private void displayValue(Composite parent, String label, String value) { - Label l = new Label(parent, SWT.NONE); - l.setText(label); - l.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false)); - - l = new Label(parent, SWT.NONE); - l.setText(value); - l.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false)); - } - - // End of hiding from SWT Designer - //$hide<<$ -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java deleted file mode 100644 index 67d161f..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java +++ /dev/null @@ -1,1252 +0,0 @@ -/* - * 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.SdkConstants; -import com.android.annotations.Nullable; -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.devices.Device; -import com.android.sdklib.devices.DeviceManager; -import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdklib.internal.avd.AvdInfo.AvdStatus; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.util.GrabProcessOutput; -import com.android.sdklib.util.GrabProcessOutput.IProcessOutput; -import com.android.sdklib.util.GrabProcessOutput.Wait; -import com.android.sdkuilib.internal.repository.SettingsController; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.internal.repository.ui.AvdManagerWindowImpl1; -import com.android.sdkuilib.internal.tasks.ProgressTask; -import com.android.sdkuilib.repository.AvdManagerWindow.AvdInvocationContext; -import com.android.sdkuilib.ui.GridDialog; -import com.android.utils.ILogger; -import com.android.utils.NullLogger; - -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; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.graphics.Image; -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.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; -import org.eclipse.swt.widgets.TableItem; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Formatter; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - - -/** - * The AVD selector is a table that is added to the given parent composite. - * <p/> - * After using one of the constructors, call {@link #setSelection(AvdInfo)}, - * {@link #setSelectionListener(SelectionListener)} and finally use - * {@link #getSelected()} to retrieve the selection. - */ -public final class AvdSelector { - private static int NUM_COL = 2; - - private final DisplayMode mDisplayMode; - - private AvdManager mAvdManager; - private final String mOsSdkPath; - - private Table mTable; - private Button mDeleteButton; - private Button mDetailsButton; - private Button mNewButton; - private Button mEditButton; - private Button mRefreshButton; - private Button mManagerButton; - private Button mRepairButton; - private Button mStartButton; - - private SelectionListener mSelectionListener; - private IAvdFilter mTargetFilter; - - /** Defaults to true. Changed by the {@link #setEnabled(boolean)} method to represent the - * "global" enabled state on this composite. */ - private boolean mIsEnabled = true; - - private ImageFactory mImageFactory; - private Image mOkImage; - private Image mBrokenImage; - private Image mInvalidImage; - - private SettingsController mController; - - private final ILogger mSdkLog; - - private boolean mInternalRefresh; - - - /** - * 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 - * and {@link AvdSelector#getSelected()} returns the line that is checked - * even if it is not the currently selected line. Only one line can - * be checked at once. - */ - 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 - * {@link AvdSelector#getSelected()} returns the line currently selected. - * Only one line can be selected at once. - */ - SIMPLE_SELECTION, - } - - /** - * A filter to control the whether or not an AVD should be displayed by the AVD Selector. - */ - public interface IAvdFilter { - /** - * Called before {@link #accept(AvdInfo)} is called for any AVD. - */ - void prepare(); - - /** - * Called to decided whether an AVD should be displayed. - * @param avd the AVD to test. - * @return true if the AVD should be displayed. - */ - boolean accept(AvdInfo avd); - - /** - * Called after {@link #accept(AvdInfo)} has been called on all the AVDs. - */ - 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; - } - - @Override - public void prepare() { - // nothing to prepare - } - - @Override - public boolean accept(AvdInfo avd) { - if (avd != null) { - return mTarget.canRunOn(avd.getTarget()); - } - - return false; - } - - @Override - public void cleanup() { - // nothing to clean up - } - } - - /** - * Creates a new SDK Target Selector, and fills it with a list of {@link AvdInfo}, filtered - * by a {@link IAndroidTarget}. - * <p/>Only the {@link AvdInfo} able to run application developed for the given - * {@link IAndroidTarget} will be displayed. - * - * @param parent The parent composite where the selector will be added. - * @param osSdkPath The SDK root path. When not null, enables the start button to start - * an emulator on a given AVD. - * @param manager the AVD manager. - * @param filter When non-null, will allow filtering the AVDs to display. - * @param displayMode The display mode ({@link DisplayMode}). - * @param sdkLog The logger. Cannot be null. - */ - public AvdSelector(Composite parent, - String osSdkPath, - AvdManager manager, - IAvdFilter filter, - DisplayMode displayMode, - ILogger sdkLog) { - mOsSdkPath = osSdkPath; - mAvdManager = manager; - mTargetFilter = filter; - mDisplayMode = displayMode; - mSdkLog = sdkLog; - - // get some bitmaps. - mImageFactory = new ImageFactory(parent.getDisplay()); - mOkImage = mImageFactory.getImageByName("accept_icon16.png"); - mBrokenImage = mImageFactory.getImageByName("broken_16.png"); - mInvalidImage = mImageFactory.getImageByName("reject_icon16.png"); - - // Layout has 2 columns - Composite group = new Composite(parent, SWT.NONE); - GridLayout gl; - group.setLayout(gl = new GridLayout(NUM_COL, false /*makeColumnsEqualWidth*/)); - gl.marginHeight = gl.marginWidth = 0; - group.setLayoutData(new GridData(GridData.FILL_BOTH)); - group.setFont(parent.getFont()); - group.addDisposeListener(new DisposeListener() { - @Override - public void widgetDisposed(DisposeEvent arg0) { - mImageFactory.dispose(); - } - }); - - int style = SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER; - if (displayMode == DisplayMode.SIMPLE_CHECK) { - style |= SWT.CHECK; - } - mTable = new Table(group, style); - mTable.setHeaderVisible(true); - mTable.setLinesVisible(false); - setTableHeightHint(0); - - Composite buttons = new Composite(group, SWT.NONE); - 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 (displayMode == DisplayMode.MANAGER) { - mNewButton = new Button(buttons, SWT.PUSH | SWT.FLAT); - mNewButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mNewButton.setText("New..."); - mNewButton.setToolTipText("Creates a new AVD."); - mNewButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - onNew(); - } - }); - - mEditButton = new Button(buttons, SWT.PUSH | SWT.FLAT); - mEditButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mEditButton.setText("Edit..."); - mEditButton.setToolTipText("Edit an existing AVD."); - mEditButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - onEdit(); - } - }); - - mDeleteButton = new Button(buttons, SWT.PUSH | SWT.FLAT); - mDeleteButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mDeleteButton.setText("Delete..."); - mDeleteButton.setToolTipText("Deletes the selected AVD."); - mDeleteButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - onDelete(); - } - }); - - mRepairButton = new Button(buttons, SWT.PUSH | SWT.FLAT); - mRepairButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mRepairButton.setText("Repair..."); - mRepairButton.setToolTipText("Repairs the selected AVD."); - mRepairButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - onRepair(); - } - }); - - Label l = new Label(buttons, SWT.SEPARATOR | SWT.HORIZONTAL); - l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - } - - mDetailsButton = new Button(buttons, SWT.PUSH | SWT.FLAT); - mDetailsButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mDetailsButton.setText("Details..."); - mDetailsButton.setToolTipText("Displays details of the selected AVD."); - mDetailsButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - onDetails(); - } - }); - - mStartButton = new Button(buttons, SWT.PUSH | SWT.FLAT); - mStartButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mStartButton.setText("Start..."); - mStartButton.setToolTipText("Starts the selected AVD."); - mStartButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - onStart(); - } - }); - - Composite padding = new Composite(buttons, SWT.NONE); - padding.setLayoutData(new GridData(GridData.FILL_VERTICAL)); - - mRefreshButton = new Button(buttons, SWT.PUSH | SWT.FLAT); - mRefreshButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mRefreshButton.setText("Refresh"); - mRefreshButton.setToolTipText("Reloads the list of AVD.\nUse this if you create AVDs from the command line."); - mRefreshButton.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.setToolTipText("Launches the AVD manager."); - mManagerButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onAvdManager(); - } - }); - } else { - Composite legend = new Composite(group, SWT.NONE); - legend.setLayout(gl = new GridLayout(4, false /*makeColumnsEqualWidth*/)); - gl.marginHeight = gl.marginWidth = 0; - legend.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, true, false, - NUM_COL, 1)); - legend.setFont(group.getFont()); - - new Label(legend, SWT.NONE).setImage(mOkImage); - new Label(legend, SWT.NONE).setText("A valid Android Virtual Device."); - new Label(legend, SWT.NONE).setImage(mBrokenImage); - new Label(legend, SWT.NONE).setText( - "A repairable Android Virtual Device."); - new Label(legend, SWT.NONE).setImage(mInvalidImage); - Label l = new Label(legend, SWT.NONE); - l.setText("An Android Virtual Device that failed to load. Click 'Details' to see the error."); - GridData gd; - l.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.horizontalSpan = 3; - } - - // create the table columns - final TableColumn column0 = new TableColumn(mTable, SWT.NONE); - column0.setText("AVD Name"); - final TableColumn column1 = new TableColumn(mTable, SWT.NONE); - column1.setText("Target Name"); - final TableColumn column2 = new TableColumn(mTable, SWT.NONE); - column2.setText("Platform"); - final TableColumn column3 = new TableColumn(mTable, SWT.NONE); - column3.setText("API Level"); - final TableColumn column4 = new TableColumn(mTable, SWT.NONE); - column4.setText("CPU/ABI"); - - adjustColumnsWidth(mTable, column0, column1, column2, column3, column4); - setupSelectionListener(mTable); - fillTable(mTable); - setEnabled(true); - } - - /** - * 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 manager the AVD manager. - * @param displayMode The display mode ({@link DisplayMode}). - * @param sdkLog The logger. Cannot be null. - */ - public AvdSelector(Composite parent, - String osSdkPath, - AvdManager manager, - DisplayMode displayMode, - ILogger sdkLog) { - this(parent, osSdkPath, manager, (IAvdFilter)null /* filter */, displayMode, sdkLog); - } - - /** - * 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 manager the AVD manager. - * @param filter Only shows the AVDs matching this target (must not be null). - * @param displayMode The display mode ({@link DisplayMode}). - * @param sdkLog The logger. Cannot be null. - */ - public AvdSelector(Composite parent, - String osSdkPath, - AvdManager manager, - IAndroidTarget filter, - DisplayMode displayMode, - ILogger sdkLog) { - this(parent, osSdkPath, manager, new TargetBasedFilter(filter), displayMode, sdkLog); - } - - /** - * Sets an optional SettingsController. - * @param controller the controller. - */ - public void setSettingsController(SettingsController controller) { - mController = controller; - } - - /** - * Sets the table grid layout data. - * - * @param heightHint If > 0, the height hint is set to the requested value. - */ - public void setTableHeightHint(int heightHint) { - GridData data = new GridData(); - if (heightHint > 0) { - data.heightHint = heightHint; - } - data.grabExcessVerticalSpace = true; - data.grabExcessHorizontalSpace = true; - data.horizontalAlignment = GridData.FILL; - data.verticalAlignment = GridData.FILL; - mTable.setLayoutData(data); - } - - /** - * Refresh the display of Android Virtual Devices. - * Tries to keep the selection. - * <p/> - * This must be called from the UI thread. - * - * @param reload if true, the AVD manager will reload the AVD from the disk. - * @return false if the reloading failed. This is always true if <var>reload</var> is - * <code>false</code>. - */ - public boolean refresh(boolean reload) { - if (!mInternalRefresh) { - try { - // Note that AvdManagerPage.onDevicesChange() will trigger a - // refresh while the AVDs are being reloaded so prevent from - // having a recursive call to here. - mInternalRefresh = true; - if (reload) { - try { - mAvdManager.reloadAvds(NullLogger.getLogger()); - } catch (AndroidLocationException e) { - return false; - } - } - - AvdInfo selected = getSelected(); - fillTable(mTable); - setSelection(selected); - return true; - } finally { - mInternalRefresh = false; - } - } - return false; - } - - /** - * Sets a new AVD manager - * This does not refresh the display. Call {@link #refresh(boolean)} to do so. - * @param manager the AVD manager. - */ - public void setManager(AvdManager manager) { - mAvdManager = 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; - } - } - - /** - * Sets a selection listener. Set it to null to remove it. - * The listener will be called <em>after</em> this table processed its selection - * events so that the caller can see the updated state. - * <p/> - * The event's item contains a {@link TableItem}. - * The {@link TableItem#getData()} contains an {@link IAndroidTarget}. - * <p/> - * It is recommended that the caller uses the {@link #getSelected()} method instead. - * <p/> - * The default behavior for double click (when not in {@link DisplayMode#SIMPLE_CHECK}) is to - * display the details of the selected AVD.<br> - * To disable it (when you provide your own double click action), set - * {@link SelectionEvent#doit} to false in - * {@link SelectionListener#widgetDefaultSelected(SelectionEvent)} - * - * @param selectionListener The new listener or null to remove it. - */ - public void setSelectionListener(SelectionListener selectionListener) { - mSelectionListener = selectionListener; - } - - /** - * Sets the current target selection. - * <p/> - * If the selection is actually changed, this will invoke the selection listener - * (if any) with a null event. - * - * @param target the target to be selected. Use null to deselect everything. - * @return true if the target could be selected, false otherwise. - */ - public boolean setSelection(AvdInfo target) { - boolean found = false; - boolean modified = false; - - int selIndex = mTable.getSelectionIndex(); - int index = 0; - for (TableItem i : mTable.getItems()) { - if (mDisplayMode == DisplayMode.SIMPLE_CHECK) { - if ((AvdInfo) i.getData() == target) { - found = true; - if (!i.getChecked()) { - modified = true; - i.setChecked(true); - } - } else if (i.getChecked()) { - modified = true; - i.setChecked(false); - } - } else { - if ((AvdInfo) i.getData() == target) { - found = true; - if (index != selIndex) { - mTable.setSelection(index); - modified = true; - } - break; - } - - index++; - } - } - - if (modified && mSelectionListener != null) { - mSelectionListener.widgetSelected(null); - } - - enableActionButtons(); - - return found; - } - - /** - * Returns the currently selected item. In {@link DisplayMode#SIMPLE_CHECK} mode this will - * return the {@link AvdInfo} that is checked instead of the list selection. - * - * @return The currently selected item or null. - */ - public AvdInfo getSelected() { - if (mDisplayMode == DisplayMode.SIMPLE_CHECK) { - for (TableItem i : mTable.getItems()) { - if (i.getChecked()) { - return (AvdInfo) i.getData(); - } - } - } else { - int selIndex = mTable.getSelectionIndex(); - if (selIndex >= 0) { - return (AvdInfo) mTable.getItem(selIndex).getData(); - } - } - - return null; - } - - /** - * Enables the receiver if the argument is true, and disables it otherwise. - * A disabled control is typically not selectable from the user interface - * and draws with an inactive or "grayed" look. - * - * @param enabled the new enabled state. - */ - public void setEnabled(boolean enabled) { - // We can only enable widgets if the AVD Manager is defined. - mIsEnabled = enabled && mAvdManager != null; - - mTable.setEnabled(mIsEnabled); - mRefreshButton.setEnabled(mIsEnabled); - - if (mNewButton != null) { - mNewButton.setEnabled(mIsEnabled); - } - if (mManagerButton != null) { - mManagerButton.setEnabled(mIsEnabled); - } - - enableActionButtons(); - } - - public boolean isEnabled() { - return mIsEnabled; - } - - /** - * Adds a listener to adjust the columns width when the parent is resized. - * <p/> - * If we need something more fancy, we might want to use this: - * http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet77.java?view=co - */ - private void adjustColumnsWidth(final Table table, - final TableColumn column0, - final TableColumn column1, - final TableColumn column2, - final TableColumn column3, - final TableColumn column4) { - // Add a listener to resize the column to the full width of the table - table.addControlListener(new ControlAdapter() { - @Override - public void controlResized(ControlEvent e) { - Rectangle r = table.getClientArea(); - column0.setWidth(r.width * 20 / 100); // 20% - column1.setWidth(r.width * 30 / 100); // 30% - column2.setWidth(r.width * 15 / 100); // 15% - column3.setWidth(r.width * 15 / 100); // 15% - column4.setWidth(r.width * 20 / 100); // 22% - } - }); - } - - /** - * Creates a selection listener that will check or uncheck the whole line when - * double-clicked (aka "the default selection"). - */ - private void setupSelectionListener(final Table table) { - // Add a selection listener that will check/uncheck items when they are double-clicked - table.addSelectionListener(new SelectionListener() { - - /** - * Handles single-click selection on the table. - * {@inheritDoc} - */ - @Override - public void widgetSelected(SelectionEvent e) { - if (e.item instanceof TableItem) { - TableItem i = (TableItem) e.item; - enforceSingleSelection(i); - } - - if (mSelectionListener != null) { - mSelectionListener.widgetSelected(e); - } - - enableActionButtons(); - } - - /** - * Handles double-click selection on the table. - * Note that the single-click handler will probably already have been called. - * - * On double-click, <em>always</em> check the table item. - * - * {@inheritDoc} - */ - @Override - public void widgetDefaultSelected(SelectionEvent e) { - if (e.item instanceof TableItem) { - TableItem i = (TableItem) e.item; - if (mDisplayMode == DisplayMode.SIMPLE_CHECK) { - i.setChecked(true); - } - enforceSingleSelection(i); - - } - - // whether or not we display details. default: true when not in SIMPLE_CHECK mode. - boolean showDetails = mDisplayMode != DisplayMode.SIMPLE_CHECK; - - if (mSelectionListener != null) { - mSelectionListener.widgetDefaultSelected(e); - showDetails &= e.doit; // enforce false in SIMPLE_CHECK - } - - if (showDetails) { - onDetails(); - } - - enableActionButtons(); - } - - /** - * To ensure single selection, uncheck all other items when this one is selected. - * This makes the chekboxes act as radio buttons. - */ - private void enforceSingleSelection(TableItem item) { - if (mDisplayMode == DisplayMode.SIMPLE_CHECK) { - if (item.getChecked()) { - Table parentTable = item.getParent(); - for (TableItem i2 : parentTable.getItems()) { - if (i2 != item && i2.getChecked()) { - i2.setChecked(false); - } - } - } - } else { - // pass - } - } - }); - } - - /** - * Fills the table with all AVD. - * The table columns are: - * <ul> - * <li>column 0: sdk name - * <li>column 1: sdk vendor - * <li>column 2: sdk api name - * <li>column 3: sdk version - * </ul> - */ - private void fillTable(final Table table) { - table.removeAll(); - - // get the AVDs - AvdInfo avds[] = null; - if (mAvdManager != null) { - if (mDisplayMode == DisplayMode.MANAGER) { - avds = mAvdManager.getAllAvds(); - } else { - avds = mAvdManager.getValidAvds(); - } - } - - if (avds != null && avds.length > 0) { - Arrays.sort(avds, new Comparator<AvdInfo>() { - @Override - public int compare(AvdInfo o1, AvdInfo o2) { - return o1.compareTo(o2); - } - }); - - table.setEnabled(true); - - if (mTargetFilter != null) { - mTargetFilter.prepare(); - } - - for (AvdInfo avd : avds) { - if (mTargetFilter == null || mTargetFilter.accept(avd)) { - TableItem item = new TableItem(table, SWT.NONE); - item.setData(avd); - item.setText(0, avd.getName()); - if (mDisplayMode == DisplayMode.MANAGER) { - AvdStatus status = avd.getStatus(); - item.setImage(0, status == AvdStatus.OK ? mOkImage : - isAvdRepairable(status) ? mBrokenImage : mInvalidImage); - } - IAndroidTarget target = avd.getTarget(); - if (target != null) { - item.setText(1, target.getFullName()); - item.setText(2, target.getVersionName()); - item.setText(3, target.getVersion().getApiString()); - item.setText(4, AvdInfo.getPrettyAbiType(avd.getAbiType())); - } else { - item.setText(1, "?"); - item.setText(2, "?"); - item.setText(3, "?"); - item.setText(4, "?"); - } - } - } - - if (mTargetFilter != null) { - mTargetFilter.cleanup(); - } - } - - if (table.getItemCount() == 0) { - table.setEnabled(false); - TableItem item = new TableItem(table, SWT.NONE); - item.setData(null); - item.setText(0, "--"); - item.setText(1, "No AVD available"); - item.setText(2, "--"); - item.setText(3, "--"); - } - } - - /** - * Returns the currently selected AVD in the table. - * <p/> - * Unlike {@link #getSelected()} this will always return the item being selected - * in the list, ignoring the check boxes state in {@link DisplayMode#SIMPLE_CHECK} mode. - */ - private AvdInfo getTableSelection() { - int selIndex = mTable.getSelectionIndex(); - if (selIndex >= 0) { - return (AvdInfo) mTable.getItem(selIndex).getData(); - } - - return null; - } - - /** - * Updates the enable state of the Details, Start, Delete and Update buttons. - */ - @SuppressWarnings("null") - private void enableActionButtons() { - if (mIsEnabled == false) { - mDetailsButton.setEnabled(false); - mStartButton.setEnabled(false); - - if (mEditButton != null) { - mEditButton.setEnabled(false); - } - if (mDeleteButton != null) { - mDeleteButton.setEnabled(false); - } - if (mRepairButton != null) { - mRepairButton.setEnabled(false); - } - } else { - AvdInfo selection = getTableSelection(); - boolean hasSelection = selection != null; - - mDetailsButton.setEnabled(hasSelection); - mStartButton.setEnabled(mOsSdkPath != null && - hasSelection && - selection.getStatus() == AvdStatus.OK); - - if (mEditButton != null) { - mEditButton.setEnabled(hasSelection); - } - if (mDeleteButton != null) { - mDeleteButton.setEnabled(hasSelection); - } - if (mRepairButton != null) { - mRepairButton.setEnabled(hasSelection && isAvdRepairable(selection.getStatus())); - } - } - } - - private void onNew() { - AvdCreationDialog dlg = new AvdCreationDialog(mTable.getShell(), - mAvdManager, - mImageFactory, - mSdkLog, - null); - - if (dlg.open() == Window.OK) { - refresh(false /*reload*/); - } - } - - private void onEdit() { - AvdInfo avdInfo = getTableSelection(); - GridDialog dlg; - if(!avdInfo.getDeviceName().isEmpty()) { - dlg = new AvdCreationDialog(mTable.getShell(), - mAvdManager, - mImageFactory, - mSdkLog, - avdInfo); - } else { - dlg = new LegacyAvdEditDialog(mTable.getShell(), - mAvdManager, - mImageFactory, - mSdkLog, - avdInfo); - } - - - if (dlg.open() == Window.OK) { - refresh(false /*reload*/); - } - } - - private void onDetails() { - AvdInfo avdInfo = getTableSelection(); - - AvdDetailsDialog dlg = new AvdDetailsDialog(mTable.getShell(), avdInfo); - dlg.open(); - } - - private void onDelete() { - final AvdInfo avdInfo = getTableSelection(); - - // get the current Display - final Display display = mTable.getDisplay(); - - // check if the AVD is running - if (avdInfo.isRunning()) { - display.asyncExec(new Runnable() { - @Override - public void run() { - Shell shell = display.getActiveShell(); - MessageDialog.openError(shell, - "Delete Android Virtual Device", - String.format( - "The Android Virtual Device '%1$s' is currently running in an emulator and cannot be deleted.", - avdInfo.getName())); - } - }); - return; - } - - // Confirm you want to delete this AVD - final boolean[] result = new boolean[1]; - display.syncExec(new Runnable() { - @Override - public void run() { - Shell shell = display.getActiveShell(); - result[0] = MessageDialog.openQuestion(shell, - "Delete Android Virtual Device", - String.format( - "Please confirm that you want to delete the Android Virtual Device named '%s'. This operation cannot be reverted.", - avdInfo.getName())); - } - }); - - if (result[0] == false) { - return; - } - - // log for this action. - ILogger log = mSdkLog; - if (log == null || log instanceof MessageBoxLog) { - // If the current logger is a message box, we use our own (to make sure - // to display errors right away and customize the title). - log = new MessageBoxLog( - String.format("Result of deleting AVD '%s':", avdInfo.getName()), - display, - false /*logErrorsOnly*/); - } - - // delete the AVD - boolean success = mAvdManager.deleteAvd(avdInfo, log); - - // display the result - if (log instanceof MessageBoxLog) { - ((MessageBoxLog) log).displayResult(success); - } - - if (success) { - refresh(false /*reload*/); - } - } - - /** - * Repairs the selected AVD. - * <p/> - * For now this only supports fixing the wrong value in image.sysdir.* - */ - private void onRepair() { - final AvdInfo avdInfo = getTableSelection(); - - // get the current Display - final Display display = mTable.getDisplay(); - - // log for this action. - ILogger log = mSdkLog; - if (log == null || log instanceof MessageBoxLog) { - // If the current logger is a message box, we use our own (to make sure - // to display errors right away and customize the title). - log = new MessageBoxLog( - String.format("Result of updating AVD '%s':", avdInfo.getName()), - display, - false /*logErrorsOnly*/); - } - - boolean success = true; - - if (avdInfo.getStatus() == AvdStatus.ERROR_IMAGE_DIR) { - // delete the AVD - try { - mAvdManager.updateAvd(avdInfo, log); - refresh(false /*reload*/); - } catch (IOException e) { - log.error(e, null); - success = false; - } - } else if (avdInfo.getStatus() == AvdStatus.ERROR_DEVICE_CHANGED) { - // Overwrite the properties derived from the device and nothing else - Map<String, String> properties = new HashMap<String, String>(avdInfo.getProperties()); - - DeviceManager devMan = DeviceManager.createInstance(mOsSdkPath, mSdkLog); - List<Device> devices = devMan.getDevices(DeviceManager.ALL_DEVICES); - String name = properties.get(AvdManager.AVD_INI_DEVICE_NAME); - String manufacturer = properties.get(AvdManager.AVD_INI_DEVICE_MANUFACTURER); - - if (properties != null && devices != null && name != null && manufacturer != null) { - for (Device d : devices) { - if (d.getName().equals(name) && d.getManufacturer().equals(manufacturer)) { - properties.putAll(DeviceManager.getHardwareProperties(d)); - try { - mAvdManager.updateAvd(avdInfo, properties, AvdStatus.OK, log); - } catch (IOException e) { - log.error(e,null); - success = false; - } - } - } - } else { - log.error(null, "Base device information incomplete or missing."); - success = false; - } - - // display the result - if (log instanceof MessageBoxLog) { - ((MessageBoxLog) log).displayResult(success); - } - refresh(false /*reload*/); - } else if (avdInfo.getStatus() == AvdStatus.ERROR_DEVICE_MISSING) { - onEdit(); - } - } - - private void onAvdManager() { - - // get the current Display - Display display = mTable.getDisplay(); - - // log for this action. - ILogger log = mSdkLog; - if (log == null || log instanceof MessageBoxLog) { - // If the current logger is a message box, we use our own (to make sure - // to display errors right away and customize the title). - log = new MessageBoxLog("Result of SDK Manager", display, true /*logErrorsOnly*/); - } - - try { - AvdManagerWindowImpl1 win = new AvdManagerWindowImpl1( - mTable.getShell(), - log, - mOsSdkPath, - AvdInvocationContext.DIALOG); - - win.open(); - } catch (Exception ignore) {} - - refresh(true /*reload*/); // UpdaterWindow uses its own AVD manager so this one must reload. - - if (log instanceof MessageBoxLog) { - ((MessageBoxLog) log).displayResult(true); - } - } - - private void onStart() { - AvdInfo avdInfo = getTableSelection(); - - if (avdInfo == null || mOsSdkPath == null) { - return; - } - - AvdStartDialog dialog = new AvdStartDialog(mTable.getShell(), avdInfo, mOsSdkPath, - mController, mSdkLog); - if (dialog.open() == Window.OK) { - String path = mOsSdkPath + File.separator - + SdkConstants.OS_SDK_TOOLS_FOLDER - + SdkConstants.FN_EMULATOR; - - final String avdName = avdInfo.getName(); - - // build the command line based on the available parameters. - ArrayList<String> list = new ArrayList<String>(); - list.add(path); - list.add("-avd"); //$NON-NLS-1$ - list.add(avdName); - if (dialog.hasWipeData()) { - list.add("-wipe-data"); //$NON-NLS-1$ - } - if (dialog.hasSnapshot()) { - if (!dialog.hasSnapshotLaunch()) { - list.add("-no-snapshot-load"); - } - if (!dialog.hasSnapshotSave()) { - list.add("-no-snapshot-save"); - } - } - float scale = dialog.getScale(); - if (scale != 0.f) { - // do the rounding ourselves. This is because %.1f will write .4899 as .4 - scale = Math.round(scale * 100); - scale /= 100.f; - list.add("-scale"); //$NON-NLS-1$ - // because the emulator expects English decimal values, don't use String.format - // but a Formatter. - Formatter formatter = new Formatter(Locale.US); - formatter.format("%.2f", scale); //$NON-NLS-1$ - list.add(formatter.toString()); - formatter.close(); - } - - // convert the list into an array for the call to exec. - final String[] command = list.toArray(new String[list.size()]); - - // launch the emulator - final ProgressTask progress = new ProgressTask(mTable.getShell(), - "Starting Android Emulator"); - progress.start(new ITask() { - volatile ITaskMonitor mMonitor = null; - - @Override - public void run(final ITaskMonitor monitor) { - mMonitor = monitor; - try { - monitor.setDescription( - "Starting emulator for AVD '%1$s'", - avdName); - monitor.log("Starting emulator for AVD '%1$s'", avdName); - - // we'll wait 100ms*100 = 10s. The emulator sometimes seem to - // start mostly OK just to crash a few seconds later. 10 seconds - // seems a good wait for that case. - int n = 100; - monitor.setProgressMax(n); - - Process process = Runtime.getRuntime().exec(command); - GrabProcessOutput.grabProcessOutput( - process, - Wait.ASYNC, - new IProcessOutput() { - @Override - public void out(@Nullable String line) { - filterStdOut(line); - } - - @Override - public void err(@Nullable String line) { - filterStdErr(line); - } - }); - - // This small wait prevents the dialog from closing too fast: - // When it works, the emulator returns immediately, even if - // no UI is shown yet. And when it fails (because the AVD is - // locked/running) this allows us to have time to capture the - // error and display it. - for (int i = 0; i < n; i++) { - try { - Thread.sleep(100); - monitor.incProgress(1); - } catch (InterruptedException e) { - // ignore - } - } - } catch (Exception e) { - monitor.logError("Failed to start emulator: %1$s", - e.getMessage()); - } finally { - mMonitor = null; - } - } - - private void filterStdOut(String line) { - ITaskMonitor m = mMonitor; - if (line == null || m == null) { - return; - } - - // Skip some non-useful messages. - if (line.indexOf("NSQuickDrawView") != -1) { //$NON-NLS-1$ - // Discard the MacOS warning: - // "This application, or a library it uses, is using NSQuickDrawView, - // which has been deprecated. Apps should cease use of QuickDraw and move - // to Quartz." - return; - } - - if (line.toLowerCase().indexOf("error") != -1 || //$NON-NLS-1$ - line.indexOf("qemu: fatal") != -1) { //$NON-NLS-1$ - // Sometimes the emulator seems to output errors on stdout. Catch these. - m.logError("%1$s", line); //$NON-NLS-1$ - return; - } - - m.log("%1$s", line); //$NON-NLS-1$ - } - - private void filterStdErr(String line) { - ITaskMonitor m = mMonitor; - if (line == null || m == null) { - return; - } - - if (line.indexOf("emulator: device") != -1 || //$NON-NLS-1$ - line.indexOf("HAX is working") != -1) { //$NON-NLS-1$ - // These are not errors. Output them as regular stdout messages. - m.log("%1$s", line); //$NON-NLS-1$ - return; - } - - m.logError("%1$s", line); //$NON-NLS-1$ - } - }); - } - } - - private boolean isAvdRepairable(AvdStatus avdStatus) { - return avdStatus == AvdStatus.ERROR_IMAGE_DIR - || avdStatus == AvdStatus.ERROR_DEVICE_CHANGED - || avdStatus == AvdStatus.ERROR_DEVICE_MISSING; - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdStartDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdStartDialog.java deleted file mode 100644 index 925b0cd..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdStartDialog.java +++ /dev/null @@ -1,630 +0,0 @@ -/* - * 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.devices.Device; -import com.android.sdklib.devices.DeviceManager; -import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdkuilib.internal.repository.SettingsController; -import com.android.sdkuilib.ui.GridDialog; -import com.android.utils.ILogger; - -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.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -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.Group; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; - -import java.awt.Toolkit; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Dialog dealing with emulator launch options. The following options are supported: - * <ul> - * <li>-wipe-data</li> - * <li>-scale</li> - * </ul> - * Values are stored (in the class as static field) to be reused while the app is still running. - * The Monitor dpi is stored in the settings if available. - */ -final class AvdStartDialog extends GridDialog { - // static field to reuse values during the same session. - private static boolean sWipeData = false; - private static boolean sSnapshotSave = true; - private static boolean sSnapshotLaunch = true; - private static int sMonitorDpi = 72; // used if there's no setting controller. - private static final Map<String, String> sSkinScaling = new HashMap<String, String>(); - - private static final Pattern sScreenSizePattern = Pattern.compile("\\d*(\\.\\d?)?"); - - private final AvdInfo mAvd; - private final String mSdkLocation; - private final SettingsController mSettingsController; - private final DeviceManager mDeviceManager; - - private Text mScreenSize; - private Text mMonitorDpi; - private Button mScaleButton; - - private float mScale = 0.f; - private boolean mWipeData = false; - private int mDensity = 160; // medium density - private int mSize1 = -1; - private int mSize2 = -1; - private String mSkinDisplay; - private boolean mEnableScaling = true; - private Label mScaleField; - private boolean mHasSnapshot = true; - private boolean mSnapshotSave = true; - private boolean mSnapshotLaunch = true; - private Button mSnapshotLaunchCheckbox; - - AvdStartDialog(Shell parentShell, AvdInfo avd, String sdkLocation, - SettingsController settingsController, ILogger sdkLog) { - super(parentShell, 2, false); - mAvd = avd; - mSdkLocation = sdkLocation; - mSettingsController = settingsController; - mDeviceManager = DeviceManager.createInstance(mSdkLocation, sdkLog); - if (mAvd == null) { - throw new IllegalArgumentException("avd cannot be null"); - } - if (mSdkLocation == null) { - throw new IllegalArgumentException("sdkLocation cannot be null"); - } - - computeSkinData(); - } - - public boolean hasWipeData() { - return mWipeData; - } - - /** - * Returns the scaling factor, or 0.f if none are set. - */ - public float getScale() { - return mScale; - } - - @Override - public void createDialogContent(final Composite parent) { - GridData gd; - - Label l = new Label(parent, SWT.NONE); - l.setText("Skin:"); - - l = new Label(parent, SWT.NONE); - l.setText(mSkinDisplay == null ? "None" : mSkinDisplay); - l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - l = new Label(parent, SWT.NONE); - l.setText("Density:"); - - l = new Label(parent, SWT.NONE); - l.setText(getDensityText()); - l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - mScaleButton = new Button(parent, SWT.CHECK); - mScaleButton.setText("Scale display to real size"); - mScaleButton.setEnabled(mEnableScaling); - boolean defaultState = mEnableScaling && sSkinScaling.get(mAvd.getName()) != null; - mScaleButton.setSelection(defaultState); - mScaleButton.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.horizontalSpan = 2; - final Group scaleGroup = new Group(parent, SWT.NONE); - scaleGroup.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.horizontalIndent = 30; - gd.horizontalSpan = 2; - scaleGroup.setLayout(new GridLayout(3, false)); - - l = new Label(scaleGroup, SWT.NONE); - l.setText("Screen Size (in):"); - mScreenSize = new Text(scaleGroup, SWT.BORDER); - mScreenSize.setText(getScreenSize()); - mScreenSize.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mScreenSize.addVerifyListener(new VerifyListener() { - @Override - public void verifyText(VerifyEvent event) { - // combine the current content and the new text - String text = mScreenSize.getText(); - text = text.substring(0, event.start) + event.text + text.substring(event.end); - - // now make sure it's a match for the regex - event.doit = sScreenSizePattern.matcher(text).matches(); - } - }); - mScreenSize.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent event) { - onScaleChange(); - } - }); - - // empty composite, only 2 widgets on this line. - new Composite(scaleGroup, SWT.NONE).setLayoutData(gd = new GridData()); - gd.widthHint = gd.heightHint = 0; - - l = new Label(scaleGroup, SWT.NONE); - l.setText("Monitor dpi:"); - mMonitorDpi = new Text(scaleGroup, SWT.BORDER); - mMonitorDpi.setText(Integer.toString(getMonitorDpi())); - mMonitorDpi.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.widthHint = 50; - mMonitorDpi.addVerifyListener(new VerifyListener() { - @Override - public void verifyText(VerifyEvent event) { - // check for digit only. - for (int i = 0 ; i < event.text.length(); i++) { - char letter = event.text.charAt(i); - if (letter < '0' || letter > '9') { - event.doit = false; - return; - } - } - } - }); - mMonitorDpi.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent event) { - onScaleChange(); - } - }); - - Button button = new Button(scaleGroup, SWT.PUSH | SWT.FLAT); - button.setText("?"); - button.setToolTipText("Click to figure out your monitor's pixel density"); - button.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - ResolutionChooserDialog dialog = new ResolutionChooserDialog(parent.getShell()); - if (dialog.open() == Window.OK) { - mMonitorDpi.setText(Integer.toString(dialog.getDensity())); - } - } - }); - - l = new Label(scaleGroup, SWT.NONE); - l.setText("Scale:"); - mScaleField = new Label(scaleGroup, SWT.NONE); - mScaleField.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, - true /*grabExcessHorizontalSpace*/, - true /*grabExcessVerticalSpace*/, - 2 /*horizontalSpan*/, - 1 /*verticalSpan*/)); - setScale(mScale); // set initial text value - - enableGroup(scaleGroup, defaultState); - - mScaleButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - boolean enabled = mScaleButton.getSelection(); - enableGroup(scaleGroup, enabled); - if (enabled) { - onScaleChange(); - } else { - setScale(0); - } - } - }); - - final Button wipeButton = new Button(parent, SWT.CHECK); - wipeButton.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.horizontalSpan = 2; - wipeButton.setText("Wipe user data"); - wipeButton.setSelection(mWipeData = sWipeData); - wipeButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - mWipeData = wipeButton.getSelection(); - updateSnapshotLaunchAvailability(); - } - }); - - Map<String, String> prop = mAvd.getProperties(); - String snapshotPresent = prop.get(AvdManager.AVD_INI_SNAPSHOT_PRESENT); - mHasSnapshot = (snapshotPresent != null) && snapshotPresent.equals("true"); - - mSnapshotLaunchCheckbox = new Button(parent, SWT.CHECK); - mSnapshotLaunchCheckbox.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.horizontalSpan = 2; - mSnapshotLaunchCheckbox.setText("Launch from snapshot"); - updateSnapshotLaunchAvailability(); - mSnapshotLaunchCheckbox.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - mSnapshotLaunch = mSnapshotLaunchCheckbox.getSelection(); - } - }); - - final Button snapshotSaveCheckbox = new Button(parent, SWT.CHECK); - snapshotSaveCheckbox.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.horizontalSpan = 2; - snapshotSaveCheckbox.setText("Save to snapshot"); - snapshotSaveCheckbox.setSelection((mSnapshotSave = sSnapshotSave) && mHasSnapshot); - snapshotSaveCheckbox.setEnabled(mHasSnapshot); - snapshotSaveCheckbox.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - mSnapshotSave = snapshotSaveCheckbox.getSelection(); - } - }); - - l = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL); - l.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.horizontalSpan = 2; - - // if the scaling is enabled by default, we must initialize the value of mScale - if (defaultState) { - onScaleChange(); - } - } - - /** On Windows we need to manually enable/disable the children of a group */ - private void enableGroup(final Group group, boolean enabled) { - group.setEnabled(enabled); - for (Control c : group.getChildren()) { - c.setEnabled(enabled); - } - } - - @Override - protected void configureShell(Shell newShell) { - super.configureShell(newShell); - newShell.setText("Launch Options"); - } - - @Override - protected Button createButton(Composite parent, int id, String label, boolean defaultButton) { - if (id == IDialogConstants.OK_ID) { - label = "Launch"; - } - - return super.createButton(parent, id, label, defaultButton); - } - - @Override - protected void okPressed() { - // override ok to store some info - // first the monitor dpi - String dpi = mMonitorDpi.getText(); - if (dpi.length() > 0) { - sMonitorDpi = Integer.parseInt(dpi); - - // if there is a setting controller, save it - if (mSettingsController != null) { - mSettingsController.setMonitorDensity(sMonitorDpi); - mSettingsController.saveSettings(); - } - } - - // now the scale factor - String key = mAvd.getName(); - sSkinScaling.remove(key); - if (mScaleButton.getSelection()) { - String size = mScreenSize.getText(); - if (size.length() > 0) { - sSkinScaling.put(key, size); - } - } - - // and then the wipe-data checkbox - sWipeData = mWipeData; - - // and the snapshot handling if those checkboxes are enabled. - if (mHasSnapshot) { - sSnapshotSave = mSnapshotSave; - if (!mWipeData) { - sSnapshotLaunch = mSnapshotLaunch; - } - } - - // finally continue with the ok action - super.okPressed(); - } - - private void computeSkinData() { - Map<String, String> prop = mAvd.getProperties(); - String dpi = prop.get("hw.lcd.density"); - if (dpi != null && dpi.length() > 0) { - mDensity = Integer.parseInt(dpi); - } - - findSkinResolution(); - } - - private void onScaleChange() { - String sizeStr = mScreenSize.getText(); - if (sizeStr.length() == 0) { - setScale(0); - return; - } - - String dpiStr = mMonitorDpi.getText(); - if (dpiStr.length() == 0) { - setScale(0); - return; - } - - int dpi = Integer.parseInt(dpiStr); - float size = Float.parseFloat(sizeStr); - /* - * We are trying to emulate the following device: - * resolution: 'mSize1'x'mSize2' - * density: 'mDensity' - * screen diagonal: 'size' - * ontop a monitor running at 'dpi' - */ - // We start by computing the screen diagonal in pixels, if the density was really mDensity - float diagonalPx = (float)Math.sqrt(mSize1*mSize1+mSize2*mSize2); - // Now we would convert this in actual inches: - // diagonalIn = diagonal / mDensity - // the scale factor is a mix of adapting to the new density and to the new size. - // (size/diagonalIn) * (dpi/mDensity) - // this can be simplified to: - setScale((size * dpi) / diagonalPx); - } - - private void setScale(float scale) { - mScale = scale; - - // Do the rounding exactly like AvdSelector will do. - scale = Math.round(scale * 100); - scale /= 100.f; - - if (scale == 0.f) { - mScaleField.setText("default"); //$NON-NLS-1$ - } else { - mScaleField.setText(String.format("%.2f", scale)); //$NON-NLS-1$ - } - } - - /** - * Returns the monitor dpi to start with. - * This can be coming from the settings, the session-based storage, or the from whatever Java - * can tell us. - */ - private int getMonitorDpi() { - if (mSettingsController != null) { - sMonitorDpi = mSettingsController.getSettings().getMonitorDensity(); - } - - if (sMonitorDpi == -1) { // first time? try to get a value - sMonitorDpi = Toolkit.getDefaultToolkit().getScreenResolution(); - } - - return sMonitorDpi; - } - - /** - * Returns the screen size to start with. - * <p/>If an emulator with the same skin was already launched, scaled, the size used is reused. - * <p/>If one hasn't been launched and the AVD is based on a device, use the device's screen - * size. Otherwise, use the default (3). - */ - private String getScreenSize() { - String size = sSkinScaling.get(mAvd.getName()); - if (size != null) { - return size; - } - - Map<String, String> properties = mAvd.getProperties(); - if (properties != null) { - String name = properties.get(AvdManager.AVD_INI_DEVICE_NAME); - String mfctr = properties.get(AvdManager.AVD_INI_DEVICE_MANUFACTURER); - if (name != null && mfctr != null) { - Device d = mDeviceManager.getDevice(name, mfctr); - if (d != null) { - double screenSize = - d.getDefaultHardware().getScreen().getDiagonalLength(); - return String.format("%.1f", screenSize); - } - } - } - - return "3"; - } - - /** - * Returns a display string for the density. - */ - private String getDensityText() { - switch (mDensity) { - case 120: - return "Low (120)"; - case 160: - return "Medium (160)"; - case 240: - return "High (240)"; - } - - return Integer.toString(mDensity); - } - - /** - * Finds the skin resolution and sets it in {@link #mSize1} and {@link #mSize2}. - */ - private void findSkinResolution() { - Map<String, String> prop = mAvd.getProperties(); - String skinName = prop.get(AvdManager.AVD_INI_SKIN_NAME); - - if (skinName != null) { - Matcher m = AvdManager.NUMERIC_SKIN_SIZE.matcher(skinName); - if (m != null && m.matches()) { - mSize1 = Integer.parseInt(m.group(1)); - mSize2 = Integer.parseInt(m.group(2)); - mSkinDisplay = skinName; - mEnableScaling = true; - return; - } - } - - // The resolution is inside the layout file of the skin. - mEnableScaling = false; // default to false for now. - - // path to the skin layout file. - String skinPath = prop.get(AvdManager.AVD_INI_SKIN_PATH); - if (skinPath != null) { - File skinFolder = new File(mSdkLocation, skinPath); - if (skinFolder.isDirectory()) { - File layoutFile = new File(skinFolder, "layout"); - if (layoutFile.isFile()) { - if (parseLayoutFile(layoutFile)) { - mSkinDisplay = String.format("%1$s (%2$dx%3$d)", skinName, mSize1, mSize2); - mEnableScaling = true; - } else { - mSkinDisplay = skinName; - } - } - } - } - } - - /** - * Parses a layout file. - * <p/> - * the format is relatively easy. It's a collection of items defined as - * ≶name> { - * ≶content> - * } - * - * content is either 1+ items or 1+ properties - * properties are defined as - * ≶name>≶whitespace>≶value> - * - * We're going to look for an item called display, with 2 properties height and width. - * This is very basic parser. - * - * @param layoutFile the file to parse - * @return true if both sizes where found. - */ - private boolean parseLayoutFile(File layoutFile) { - BufferedReader input = null; - try { - input = new BufferedReader(new FileReader(layoutFile)); - String line; - - while ((line = input.readLine()) != null) { - // trim to remove whitespace - line = line.trim(); - int len = line.length(); - if (len == 0) continue; - - // check if this is a new item - if (line.charAt(len-1) == '{') { - // this is the start of a node - String[] tokens = line.split(" "); - if ("display".equals(tokens[0])) { - // this is the one we're looking for! - while ((mSize1 == -1 || mSize2 == -1) && - (line = input.readLine()) != null) { - // trim to remove whitespace - line = line.trim(); - len = line.length(); - if (len == 0) continue; - - if ("}".equals(line)) { // looks like we're done with the item. - break; - } - - tokens = line.split(" "); - if (tokens.length >= 2) { - // there can be multiple space between the name and value - // in which case we'll get an extra empty token in the middle. - if ("width".equals(tokens[0])) { - mSize1 = Integer.parseInt(tokens[tokens.length-1]); - } else if ("height".equals(tokens[0])) { - mSize2 = Integer.parseInt(tokens[tokens.length-1]); - } - } - } - - return mSize1 != -1 && mSize2 != -1; - } - } - - } - // if it reaches here, display was not found. - // false is returned below. - } catch (IOException e) { - // ignore. - } finally { - if (input != null) { - try { - input.close(); - } catch (IOException e) { - // ignore - } - } - } - - return false; - } - - /** - * @return Whether there's a snapshot file available. - */ - public boolean hasSnapshot() { - return mHasSnapshot; - } - - /** - * @return Whether to launch and load snapshot. - */ - public boolean hasSnapshotLaunch() { - return mSnapshotLaunch && !hasWipeData(); - } - - /** - * @return Whether to preserve emulator state to snapshot. - */ - public boolean hasSnapshotSave() { - return mSnapshotSave; - } - - /** - * Updates snapshot launch availability, for when mWipeData value changes. - */ - private void updateSnapshotLaunchAvailability() { - boolean enabled = !mWipeData && mHasSnapshot; - mSnapshotLaunchCheckbox.setEnabled(enabled); - mSnapshotLaunch = enabled && sSnapshotLaunch; - mSnapshotLaunchCheckbox.setSelection(mSnapshotLaunch); - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/DeviceCreationDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/DeviceCreationDialog.java deleted file mode 100644 index 68c4fd5..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/DeviceCreationDialog.java +++ /dev/null @@ -1,1074 +0,0 @@ -/* - * Copyright (C) 2012 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.annotations.Nullable; -import com.android.resources.Density; -import com.android.resources.Keyboard; -import com.android.resources.KeyboardState; -import com.android.resources.Navigation; -import com.android.resources.NavigationState; -import com.android.resources.ResourceEnum; -import com.android.resources.ScreenOrientation; -import com.android.resources.ScreenRatio; -import com.android.resources.ScreenSize; -import com.android.resources.TouchScreen; -import com.android.sdklib.devices.Abi; -import com.android.sdklib.devices.ButtonType; -import com.android.sdklib.devices.Camera; -import com.android.sdklib.devices.CameraLocation; -import com.android.sdklib.devices.Device; -import com.android.sdklib.devices.DeviceManager; -import com.android.sdklib.devices.Hardware; -import com.android.sdklib.devices.Multitouch; -import com.android.sdklib.devices.Network; -import com.android.sdklib.devices.PowerType; -import com.android.sdklib.devices.Screen; -import com.android.sdklib.devices.ScreenType; -import com.android.sdklib.devices.Sensor; -import com.android.sdklib.devices.Software; -import com.android.sdklib.devices.State; -import com.android.sdklib.devices.Storage; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.ui.GridDataBuilder; -import com.android.sdkuilib.ui.GridDialog; -import com.android.sdkuilib.ui.GridLayoutBuilder; - -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.events.SelectionListener; -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.Group; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; - -import java.util.List; - -public class DeviceCreationDialog extends GridDialog { - - private static final String MANUFACTURER = "User"; - - private final ImageFactory mImageFactory; - private final DeviceManager mManager; - private List<Device> mUserDevices; - - private Device mDevice; - - private Text mDeviceName; - private Text mDiagonalLength; - private Text mXDimension; - private Text mYDimension; - private Button mKeyboard; - private Button mDpad; - private Button mTrackball; - private Button mNoNav; - private Text mRam; - private Combo mRamCombo; - private Combo mButtons; - private Combo mSize; - private Combo mDensity; - private Combo mRatio; - private Button mAccelerometer; // hw.accelerometer - private Button mGyro; // hw.sensors.orientation - private Button mGps; // hw.sensors.gps - private Button mProximitySensor; // hw.sensors.proximity - private Button mCameraFront; - private Button mCameraRear; - private Group mStateGroup; - private Button mPortrait; - private Label mPortraitLabel; - private Button mPortraitNav; - private Button mLandscape; - private Label mLandscapeLabel; - private Button mLandscapeNav; - private Button mPortraitKeys; - private Label mPortraitKeysLabel; - private Button mPortraitKeysNav; - private Button mLandscapeKeys; - private Label mLandscapeKeysLabel; - private Button mLandscapeKeysNav; - - private Button mForceCreation; - private Label mStatusIcon; - private Label mStatusLabel; - - private Button mOkButton; - - /** The hardware instance attached to each of the states of the created device. */ - private Hardware mHardware; - /** The instance of the Device created by the dialog, if the user pressed {@code mOkButton}. */ - private Device mCreatedDevice; - - /** - * This contains the Software for the device. Since it has no effect on the - * emulator whatsoever, we just use a single instance with reasonable - * defaults. */ - private static final Software mSoftware; - - static { - mSoftware = new Software(); - mSoftware.setLiveWallpaperSupport(true); - mSoftware.setGlVersion("2.0"); - } - - public DeviceCreationDialog(Shell parentShell, - DeviceManager manager, - ImageFactory imageFactory, - @Nullable Device device) { - super(parentShell, 3, false); - mImageFactory = imageFactory; - mDevice = device; - mManager = manager; - mUserDevices = mManager.getDevices(DeviceManager.USER_DEVICES); - } - - /** - * Returns the instance of the Device created by the dialog, - * if the user pressed the OK|create|edit|clone button. - * Typically only non-null if the dialog returns OK. - */ - public Device getCreatedDevice() { - return mCreatedDevice; - } - - @Override - protected Control createContents(Composite parent) { - Control control = super.createContents(parent); - - mOkButton = getButton(IDialogConstants.OK_ID); - - if (mDevice == null) { - getShell().setText("Create New Device"); - } else { - if (mUserDevices.contains(mDevice)) { - getShell().setText("Edit Device"); - } else { - getShell().setText("Clone Device"); - } - } - - Object ld = mOkButton.getLayoutData(); - if (ld instanceof GridData) { - ((GridData) ld).widthHint = 100; - } - - validatePage(); - - return control; - } - - @Override - public void createDialogContent(Composite parent) { - - ValidationListener validator = new ValidationListener(); - SizeListener sizeListener = new SizeListener(); - NavStateListener navListener = new NavStateListener(); - - Composite column1 = new Composite(parent, SWT.NONE); - GridDataBuilder.create(column1).hFill().vTop(); - GridLayoutBuilder.create(column1).columns(2); - - // vertical separator between column 1 and 2 - Label label = new Label(parent, SWT.SEPARATOR | SWT.VERTICAL); - GridDataBuilder.create(label).vFill().vGrab(); - - Composite column2 = new Composite(parent, SWT.NONE); - GridDataBuilder.create(column2).hFill().vTop(); - GridLayoutBuilder.create(column2).columns(2); - - // Column 1 - - String tooltip = "Name of the new device"; - generateLabel("Name:", tooltip, column1); - mDeviceName = generateText(column1, tooltip, new CreateNameModifyListener()); - - tooltip = "Diagonal length of the screen in inches"; - generateLabel("Screen Size (in):", tooltip, column1); - mDiagonalLength = generateText(column1, tooltip, sizeListener); - - tooltip = "The resolution of the device in pixels"; - generateLabel("Resolution (px):", tooltip, column1); - Composite dimensionGroup = new Composite(column1, SWT.NONE); // Like a Group with no border - GridDataBuilder.create(dimensionGroup).hFill(); - GridLayoutBuilder.create(dimensionGroup).columns(3).noMargins(); - mXDimension = generateText(dimensionGroup, tooltip, sizeListener); - new Label(dimensionGroup, SWT.NONE).setText("x"); - mYDimension = generateText(dimensionGroup, tooltip, sizeListener); - - label = new Label(column1, SWT.None); // empty space holder - GridDataBuilder.create(label).hFill().hGrab().hSpan(2); - - // Column 2 - - tooltip = "The screen size bucket that the device falls into"; - generateLabel("Size:", tooltip, column2); - mSize = generateCombo(column2, tooltip, ScreenSize.values(), 1, validator); - - tooltip = "The aspect ratio bucket the screen falls into. A \"long\" screen is wider."; - generateLabel("Screen Ratio:", tooltip, column2); - mRatio = generateCombo(column2, tooltip, ScreenRatio.values(), 1, validator); - - tooltip = "The pixel density bucket the device falls in"; - generateLabel("Density:", tooltip, column2); - mDensity = generateCombo(column2, tooltip, Density.values(), 3, validator); - - label = new Label(column2, SWT.None); // empty space holder - GridDataBuilder.create(label).hFill().hGrab().hSpan(2); - - - // Column 1, second row - - generateLabel("Sensors:", "The sensors available on the device", column1); - Group sensorGroup = new Group(column1, SWT.NONE); - sensorGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - sensorGroup.setLayout(new GridLayout(2, false)); - mAccelerometer = generateButton(sensorGroup, "Accelerometer", - "Presence of an accelerometer", SWT.CHECK, true, validator); - mGyro = generateButton(sensorGroup, "Gyroscope", - "Presence of a gyroscope", SWT.CHECK, true, validator); - mGps = generateButton(sensorGroup, "GPS", "Presence of a GPS", SWT.CHECK, true, validator); - mProximitySensor = generateButton(sensorGroup, "Proximity Sensor", - "Presence of a proximity sensor", SWT.CHECK, true, validator); - - generateLabel("Cameras", "The cameras available on the device", column1); - Group cameraGroup = new Group(column1, SWT.NONE); - cameraGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - cameraGroup.setLayout(new GridLayout(2, false)); - mCameraFront = generateButton(cameraGroup, "Front", "Presence of a front camera", - SWT.CHECK, false, validator); - mCameraRear = generateButton(cameraGroup, "Rear", "Presence of a rear camera", - SWT.CHECK, true, validator); - - generateLabel("Input:", "The input hardware on the given device", column1); - Group inputGroup = new Group(column1, SWT.NONE); - inputGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - inputGroup.setLayout(new GridLayout(3, false)); - mKeyboard = generateButton(inputGroup, "Keyboard", "Presence of a hardware keyboard", - SWT.CHECK, false, - new KeyboardListener()); - GridData gridData = new GridData(GridData.FILL_HORIZONTAL); - gridData.horizontalSpan = 3; - mKeyboard.setLayoutData(gridData); - mNoNav = generateButton(inputGroup, "No Nav", "No hardware navigation", - SWT.RADIO, true, navListener); - mDpad = generateButton(inputGroup, "DPad", "The device has a DPad navigation element", - SWT.RADIO, false, navListener); - mTrackball = generateButton(inputGroup, "Trackball", - "The device has a trackball navigation element", SWT.RADIO, false, navListener); - - tooltip = "The amount of RAM on the device"; - generateLabel("RAM:", tooltip, column1); - Group ramGroup = new Group(column1, SWT.NONE); - ramGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - ramGroup.setLayout(new GridLayout(2, false)); - mRam = generateText(ramGroup, tooltip, validator); - mRamCombo = new Combo(ramGroup, SWT.DROP_DOWN | SWT.READ_ONLY); - mRamCombo.setToolTipText(tooltip); - mRamCombo.add("MiB"); - mRamCombo.add("GiB"); - mRamCombo.select(0); - mRamCombo.addModifyListener(validator); - - // Column 2, second row - - tooltip = "Type of buttons (Home, Menu, etc.) on the device. " - + "This can be software buttons like on the Galaxy Nexus, or hardware buttons like " - + "the capacitive buttons on the Nexus S."; - generateLabel("Buttons:", tooltip, column2); - mButtons = new Combo(column2, SWT.DROP_DOWN | SWT.READ_ONLY); - mButtons.setToolTipText(tooltip); - mButtons.add(ButtonType.SOFT.getDescription()); - mButtons.add(ButtonType.HARD.getDescription()); - mButtons.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mButtons.select(0); - mButtons.addModifyListener(validator); - - generateLabel("Device States:", "The available states for the given device", column2); - - mStateGroup = new Group(column2, SWT.NONE); - mStateGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mStateGroup.setLayout(new GridLayout(2, true)); - - tooltip = "The device has a portait position with no keyboard available"; - mPortraitLabel = generateLabel("Portrait:", tooltip, mStateGroup); - gridData = new GridData(GridData.FILL_HORIZONTAL); - gridData.horizontalSpan = 2; - mPortraitLabel.setLayoutData(gridData); - mPortrait = generateButton(mStateGroup, "Enabled", tooltip, SWT.CHECK, true, - navListener); - mPortraitNav = generateButton(mStateGroup, "Navigation", - "Hardware navigation is available in this state", SWT.CHECK, true, validator); - mPortraitNav.setEnabled(false); - - tooltip = "The device has a landscape position with no keyboard available"; - mLandscapeLabel = generateLabel("Landscape:", tooltip, mStateGroup); - gridData = new GridData(GridData.FILL_HORIZONTAL); - gridData.horizontalSpan = 2; - mLandscapeLabel.setLayoutData(gridData); - mLandscape = generateButton(mStateGroup, "Enabled", tooltip, SWT.CHECK, true, - navListener); - mLandscapeNav = generateButton(mStateGroup, "Navigation", - "Hardware navigation is available in this state", SWT.CHECK, true, validator); - mLandscapeNav.setEnabled(false); - - tooltip = "The device has a portait position with a keyboard available"; - mPortraitKeysLabel = generateLabel("Portrait with keyboard:", tooltip, mStateGroup); - gridData = new GridData(GridData.FILL_HORIZONTAL); - gridData.horizontalSpan = 2; - mPortraitKeysLabel.setLayoutData(gridData); - mPortraitKeysLabel.setEnabled(false); - mPortraitKeys = generateButton(mStateGroup, "Enabled", tooltip, SWT.CHECK, true, - navListener); - mPortraitKeys.setEnabled(false); - mPortraitKeysNav = generateButton(mStateGroup, "Navigation", - "Hardware navigation is available in this state", SWT.CHECK, true, validator); - mPortraitKeysNav.setEnabled(false); - - tooltip = "The device has a landscape position with the keyboard open"; - mLandscapeKeysLabel = generateLabel("Landscape with keyboard:", tooltip, mStateGroup); - gridData = new GridData(GridData.FILL_HORIZONTAL); - gridData.horizontalSpan = 2; - mLandscapeKeysLabel.setLayoutData(gridData); - mLandscapeKeysLabel.setEnabled(false); - mLandscapeKeys = generateButton(mStateGroup, "Enabled", tooltip, SWT.CHECK, true, - navListener); - mLandscapeKeys.setEnabled(false); - mLandscapeKeysNav = generateButton(mStateGroup, "Navigation", - "Hardware navigation is available in this state", SWT.CHECK, true, validator); - mLandscapeKeysNav.setEnabled(false); - - - mForceCreation = new Button(column2, SWT.CHECK); - mForceCreation.setText("Override the existing device with the same name"); - mForceCreation.setToolTipText("There's already an AVD with the same name. Check this to delete it and replace it by the new AVD."); - mForceCreation.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, - true, false, 2, 1)); - mForceCreation.setEnabled(false); - mForceCreation.addSelectionListener(validator); - - - // -- third row - - // add a separator to separate from the ok/cancel button - label = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL); - label.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1)); - - // add stuff for the error display - Composite statusComposite = new Composite(parent, SWT.NONE); - GridLayout gl; - statusComposite.setLayoutData( - new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1)); - statusComposite.setLayout(gl = new GridLayout(2, false)); - gl.marginHeight = gl.marginWidth = 0; - - mStatusIcon = new Label(statusComposite, SWT.NONE); - mStatusIcon.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, - false, false)); - mStatusLabel = new Label(statusComposite, SWT.NONE); - mStatusLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mStatusLabel.setText(""); //$NON-NLS-1$ - - prefillWithDevice(mDevice); - - validatePage(); - } - - private Button generateButton(Composite parent, String text, String tooltip, int type, - boolean selected, SelectionListener listener) { - Button b = new Button(parent, type); - b.setText(text); - b.setToolTipText(tooltip); - b.setSelection(selected); - b.addSelectionListener(listener); - b.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - return b; - } - - /** - * Generates a combo widget attached to the given parent, then sets the - * tooltip, adds all of the {@link String}s returned by - * {@link ResourceEnum#getResourceValue()} for each {@link ResourceEnum}, - * sets the combo to the given index and adds the given - * {@link ModifyListener}. - */ - private Combo generateCombo(Composite parent, String tooltip, ResourceEnum[] values, - int selection, - ModifyListener validator) { - Combo c = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY); - c.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - c.setToolTipText(tooltip); - for (ResourceEnum r : values) { - c.add(r.getResourceValue()); - } - c.select(selection); - c.addModifyListener(validator); - return c; - } - - /** Generates a text widget with the given tooltip, parent and listener */ - private Text generateText(Composite parent, String tooltip, ModifyListener listener) { - Text t = new Text(parent, SWT.BORDER); - t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - t.setToolTipText(tooltip); - t.addModifyListener(listener); - return t; - } - - /** Generates a label and attaches it to the given parent */ - private Label generateLabel(String text, String tooltip, Composite parent) { - Label label = new Label(parent, SWT.NONE); - label.setText(text); - label.setToolTipText(tooltip); - label.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_CENTER)); - return label; - } - - /** - * Callback when the device name is changed. Enforces that device names - * don't conflict with already existing devices unless we're editing that - * device. - */ - private class CreateNameModifyListener implements ModifyListener { - @Override - public void modifyText(ModifyEvent e) { - String name = mDeviceName.getText(); - boolean nameCollision = false; - for (Device d : mUserDevices) { - if (MANUFACTURER.equals(d.getManufacturer()) && name.equals(d.getName())) { - nameCollision = true; - break; - } - } - mForceCreation.setEnabled(nameCollision); - mForceCreation.setSelection(!nameCollision); - - validatePage(); - } - } - - /** - * Callback attached to the diagonal length and resolution text boxes. Sets - * the screen size and display density based on their values, then validates - * the page. - */ - private class SizeListener implements ModifyListener { - @Override - public void modifyText(ModifyEvent e) { - - if (!mDiagonalLength.getText().isEmpty()) { - try { - double diagonal = Double.parseDouble(mDiagonalLength.getText()); - double diagonalDp = 160.0 * diagonal; - - // Set the Screen Size - if (diagonalDp >= 1200) { - mSize.select(ScreenSize.getIndex(ScreenSize.getEnum("xlarge"))); - } else if (diagonalDp >= 800) { - mSize.select(ScreenSize.getIndex(ScreenSize.getEnum("large"))); - } else if (diagonalDp >= 568) { - mSize.select(ScreenSize.getIndex(ScreenSize.getEnum("normal"))); - } else { - mSize.select(ScreenSize.getIndex(ScreenSize.getEnum("small"))); - } - if (!mXDimension.getText().isEmpty() && !mYDimension.getText().isEmpty()) { - - // Set the density based on which bucket it's closest to - double x = Double.parseDouble(mXDimension.getText()); - double y = Double.parseDouble(mYDimension.getText()); - double dpi = Math.sqrt(x * x + y * y) / diagonal; - double difference = Double.MAX_VALUE; - Density bucket = Density.MEDIUM; - for (Density d : Density.values()) { - if (Math.abs(d.getDpiValue() - dpi) < difference) { - difference = Math.abs(d.getDpiValue() - dpi); - bucket = d; - } - } - mDensity.select(Density.getIndex(bucket)); - } - } catch (NumberFormatException ignore) {} - } - } - } - - - /** - * Callback attached to the keyboard checkbox.Enables / disables device - * states based on the keyboard presence and then validates the page. - */ - private class KeyboardListener extends SelectionAdapter { - @Override - public void widgetSelected(SelectionEvent event) { - super.widgetSelected(event); - if (mKeyboard.getSelection()) { - mPortraitKeys.setEnabled(true); - mPortraitKeysLabel.setEnabled(true); - mLandscapeKeys.setEnabled(true); - mLandscapeKeysLabel.setEnabled(true); - } else { - mPortraitKeys.setEnabled(false); - mPortraitKeysLabel.setEnabled(false); - mLandscapeKeys.setEnabled(false); - mLandscapeKeysLabel.setEnabled(false); - } - toggleNav(); - validatePage(); - } - - } - - /** - * Listens for changes on widgets that affect nav availability and toggles - * the nav checkboxes for device states based on them. - */ - private class NavStateListener extends SelectionAdapter { - @Override - public void widgetSelected(SelectionEvent event) { - super.widgetSelected(event); - toggleNav(); - validatePage(); - } - } - - /** - * Method that inspects all of the relevant dialog state and enables or disables the nav - * elements accordingly. - */ - private void toggleNav() { - mPortraitNav.setEnabled(mPortrait.getSelection() && !mNoNav.getSelection()); - mLandscapeNav.setEnabled(mLandscape.getSelection() && !mNoNav.getSelection()); - mPortraitKeysNav.setEnabled(mPortraitKeys.getSelection() && mPortraitKeys.getEnabled() - && !mNoNav.getSelection()); - mLandscapeKeysNav.setEnabled(mLandscapeKeys.getSelection() - && mLandscapeKeys.getEnabled() && !mNoNav.getSelection()); - validatePage(); - } - - /** - * Callback that validates the page on modification events or widget - * selections - */ - private class ValidationListener extends SelectionAdapter implements ModifyListener { - @Override - public void modifyText(ModifyEvent e) { - validatePage(); - } - - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - validatePage(); - } - } - - /** - * Validates all of the config options to ensure a valid device can be - * created from them. - * - * @return Whether the config options will result in a valid device. - */ - private boolean validatePage() { - boolean valid = true; - String error = null; - String warning = null; - setError(null); - - String name = mDeviceName.getText(); - - /* If we're editing / cloning a device, this will get called when the name gets pre-filled - * but the ok button won't be populated yet, so we need to skip the initial setting. - */ - if (mOkButton != null) { - if (mDevice == null) { - getShell().setText("Create New Device"); - mOkButton.setText("Create Device"); - } else { - if (mDevice.getName().equals(name)){ - if (mUserDevices.contains(mDevice)) { - getShell().setText("Edit Device"); - mOkButton.setText("Edit Device"); - } else { - warning = "Only user created devices are editable.\nA clone of it will be created under " + - "the \"User\" category."; - getShell().setText("Clone Device"); - mOkButton.setText("Clone Device"); - } - } else { - warning = "The device \"" + mDevice.getName() +"\" will be duplicated into\n" + - "\"" + name + "\" under the \"User\" category"; - getShell().setText("Clone Device"); - mOkButton.setText("Clone Device"); - } - } - } - - if (valid && name.isEmpty()) { - warning = "Please enter a name for the device."; - valid = false; - } - if (valid && !validateFloat("Diagonal Length", mDiagonalLength.getText())) { - warning = "Please enter a screen size."; - valid = false; - } - if (valid && !validateInt("Resolution", mXDimension.getText())) { - warning = "Please enter the screen resolution."; - valid = false; - } - if (valid && !validateInt("Resolution", mYDimension.getText())) { - warning = "Please enter the screen resolution."; - valid = false; - } - if (valid && mSize.getSelectionIndex() < 0) { - error = "A size bucket must be selected."; - valid = false; - } - if (valid && mDensity.getSelectionIndex() < 0) { - error = "A screen density bucket must be selected"; - valid = false; - } - if (valid && mRatio.getSelectionIndex() < 0) { - error = "A screen ratio must be selected."; - valid = false; - } - if (valid && !mNoNav.getSelection() && !mTrackball.getSelection() && !mDpad.getSelection()) { - error = "A mode of hardware navigation, or no navigation, has to be selected."; - valid = false; - } - if (valid && !validateInt("RAM", mRam.getText())) { - warning = "Please enter a RAM amount."; - valid = false; - } - if (valid && mRamCombo.getSelectionIndex() < 0) { - error = "RAM must have a selected unit."; - valid = false; - } - if (valid && mButtons.getSelectionIndex() < 0) { - error = "A button type must be selected."; - valid = false; - } - if (valid) { - if (mKeyboard.getSelection()) { - if (!mPortraitKeys.getSelection() - && !mPortrait.getSelection() - && !mLandscapeKeys.getSelection() - && !mLandscape.getSelection()) { - error = "At least one device state must be enabled."; - valid = false; - } - } else { - if (!mPortrait.getSelection() && !mLandscape.getSelection()) { - error = "At least one device state must be enabled"; - valid = false; - } - } - } - if (mForceCreation.isEnabled() && !mForceCreation.getSelection()) { - error = "Name conflicts with an existing device."; - valid = false; - } - - if (mOkButton != null) { - mOkButton.setEnabled(valid); - } - - if (error != null) { - setError(error); - } else if (warning != null) { - setWarning(warning); - } - - return valid; - } - - /** - * Validates the string is a valid, positive float. If not, it sets the - * error at the bottom of the dialog and returns false. Note this does - * <b>not</b> unset the error message, it's up to the caller to unset it iff - * it knows there are no errors on the page. - */ - private boolean validateFloat(String box, String value) { - if (value == null || value.isEmpty()) { - return false; - } - boolean ret = true; - try { - double val = Double.parseDouble(value); - if (val <= 0) { - ret = false; - } - } catch (NumberFormatException e) { - ret = false; - } - if (!ret) { - setError(box + " must be a valid, positive number."); - } - return ret; - } - - /** - * Validates the string is a valid, positive integer. If not, it sets the - * error at the bottom of the dialog and returns false. Note this does - * <b>not</b> unset the error message, it's up to the caller to unset it iff - * it knows there are no errors on the page. - */ - private boolean validateInt(String box, String value) { - if (value == null || value.isEmpty()) { - return false; - } - boolean ret = true; - try { - int val = Integer.parseInt(value); - if (val <= 0) { - ret = false; - } - } catch (NumberFormatException e) { - ret = false; - } - - if (!ret) { - setError(box + " must be a valid, positive integer."); - } - - return ret; - } - - /** - * Sets the error to the given string. If null, removes the error message. - */ - private void setError(@Nullable String error) { - if (error == null) { - mStatusIcon.setImage(null); - mStatusLabel.setText(""); - } else { - mStatusIcon.setImage(mImageFactory.getImageByName("reject_icon16.png")); - mStatusLabel.setText(error); - } - } - - /** - * Sets the warning message to the given string. If null, removes the - * warning message. - */ - private void setWarning(@Nullable String warning) { - if (warning == null) { - mStatusIcon.setImage(null); - mStatusLabel.setText(""); - } else { - mStatusIcon.setImage(mImageFactory.getImageByName("warning_icon16.png")); - mStatusLabel.setText(warning); - } - } - - /** Sets the hardware for the new device */ - private void prefillWithDevice(@Nullable Device device) { - if (device == null) { - - // Setup the default hardware instance with reasonable values for - // the things which are configurable via this dialog. - mHardware = new Hardware(); - - Screen s = new Screen(); - s.setXdpi(316); - s.setYdpi(316); - s.setMultitouch(Multitouch.JAZZ_HANDS); - s.setMechanism(TouchScreen.FINGER); - s.setScreenType(ScreenType.CAPACITIVE); - mHardware.setScreen(s); - - mHardware.addNetwork(Network.BLUETOOTH); - mHardware.addNetwork(Network.WIFI); - mHardware.addNetwork(Network.NFC); - - mHardware.addSensor(Sensor.BAROMETER); - mHardware.addSensor(Sensor.COMPASS); - mHardware.addSensor(Sensor.LIGHT_SENSOR); - - mHardware.setHasMic(true); - mHardware.addInternalStorage(new Storage(4, Storage.Unit.GiB)); - mHardware.setCpu("Generic CPU"); - mHardware.setGpu("Generic GPU"); - - mHardware.addSupportedAbi(Abi.ARMEABI); - mHardware.addSupportedAbi(Abi.ARMEABI_V7A); - mHardware.addSupportedAbi(Abi.MIPS); - mHardware.addSupportedAbi(Abi.X86); - - mHardware.setChargeType(PowerType.BATTERY); - return; - } - mHardware = device.getDefaultHardware().deepCopy(); - mDeviceName.setText(device.getName()); - mForceCreation.setSelection(true); - Screen s = mHardware.getScreen(); - mDiagonalLength.setText(Double.toString(s.getDiagonalLength())); - mXDimension.setText(Integer.toString(s.getXDimension())); - mYDimension.setText(Integer.toString(s.getYDimension())); - String size = s.getSize().getResourceValue(); - for (int i = 0; i < mSize.getItemCount(); i++) { - if (size.equals(mSize.getItem(i))) { - mSize.select(i); - break; - } - } - String ratio = s.getRatio().getResourceValue(); - for (int i = 0; i < mRatio.getItemCount(); i++) { - if (ratio.equals(mRatio.getItem(i))) { - mRatio.select(i); - break; - } - } - String density = s.getPixelDensity().getResourceValue(); - for (int i = 0; i < mDensity.getItemCount(); i++) { - if (density.equals(mDensity.getItem(i))) { - mDensity.select(i); - break; - } - } - mKeyboard.setSelection(!Keyboard.NOKEY.equals(mHardware.getKeyboard())); - mDpad.setSelection(Navigation.DPAD.equals(mHardware.getNav())); - mTrackball.setSelection(Navigation.TRACKBALL.equals(mHardware.getNav())); - mNoNav.setSelection(Navigation.NONAV.equals(mHardware.getNav())); - mAccelerometer.setSelection(mHardware.getSensors().contains(Sensor.ACCELEROMETER)); - mGyro.setSelection(mHardware.getSensors().contains(Sensor.GYROSCOPE)); - mGps.setSelection(mHardware.getSensors().contains(Sensor.GPS)); - mProximitySensor.setSelection(mHardware.getSensors().contains(Sensor.PROXIMITY_SENSOR)); - mCameraFront.setSelection(false); - mCameraRear.setSelection(false); - for (Camera c : mHardware.getCameras()) { - if (CameraLocation.FRONT.equals(c.getLocation())) { - mCameraFront.setSelection(true); - } else if (CameraLocation.BACK.equals(c.getLocation())) { - mCameraRear.setSelection(true); - } - } - mRam.setText(Long.toString(mHardware.getRam().getSizeAsUnit(Storage.Unit.MiB))); - mRamCombo.select(0); - - for (int i = 0; i < mButtons.getItemCount(); i++) { - if (mButtons.getItem(i).equals(mHardware.getButtonType().getDescription())) { - mButtons.select(i); - break; - } - } - - for (State state : device.getAllStates()) { - Button nav = null; - if (state.getOrientation().equals(ScreenOrientation.PORTRAIT)) { - if (state.getKeyState().equals(KeyboardState.EXPOSED)) { - mPortraitKeys.setSelection(true); - nav = mPortraitKeysNav; - } else { - mPortrait.setSelection(true); - nav = mPortraitNav; - } - } else { - if (state.getKeyState().equals(KeyboardState.EXPOSED)) { - mLandscapeKeys.setSelection(true); - nav = mLandscapeKeysNav; - } else { - mLandscape.setSelection(true); - nav = mLandscapeNav; - } - } - nav.setSelection(state.getNavState().equals(NavigationState.EXPOSED) - && !mHardware.getNav().equals(Navigation.NONAV)); - } - } - - /** - * If given a valid page, generates the corresponding device. The device is - * then added to the user device list, replacing any previous device with - * its given name and manufacturer, and the list is saved out to disk. - */ - @Override - protected void okPressed() { - if (validatePage()) { - Device.Builder builder = new Device.Builder(); - builder.setManufacturer("User"); - builder.setName(mDeviceName.getText()); - builder.addSoftware(mSoftware); - Screen s = mHardware.getScreen(); - double diagonal = Double.parseDouble(mDiagonalLength.getText()); - int x = Integer.parseInt(mXDimension.getText()); - int y = Integer.parseInt(mYDimension.getText()); - s.setDiagonalLength(diagonal); - s.setXDimension(x); - s.setYDimension(y); - // The diagonal DPI will be somewhere in between the X and Y dpi if - // they differ - double dpi = Math.sqrt(x * x + y * y) / diagonal; - s.setXdpi(dpi); - s.setYdpi(dpi); - s.setPixelDensity(Density.getEnum(mDensity.getText())); - s.setSize(ScreenSize.getEnum(mSize.getText())); - s.setRatio(ScreenRatio.getEnum(mRatio.getText())); - if (mAccelerometer.getSelection()) { - mHardware.addSensor(Sensor.ACCELEROMETER); - } - if (mGyro.getSelection()) { - mHardware.addSensor(Sensor.GYROSCOPE); - } - if (mGps.getSelection()) { - mHardware.addSensor(Sensor.GPS); - } - if (mProximitySensor.getSelection()) { - mHardware.addSensor(Sensor.PROXIMITY_SENSOR); - } - if (mCameraFront.getSelection()) { - Camera c = new Camera(); - c.setAutofocus(true); - c.setFlash(true); - c.setLocation(CameraLocation.FRONT); - mHardware.addCamera(c); - } - if (mCameraRear.getSelection()) { - Camera c = new Camera(); - c.setAutofocus(true); - c.setFlash(true); - c.setLocation(CameraLocation.BACK); - mHardware.addCamera(c); - } - if (mKeyboard.getSelection()) { - mHardware.setKeyboard(Keyboard.QWERTY); - } else { - mHardware.setKeyboard(Keyboard.NOKEY); - } - if (mDpad.getSelection()) { - mHardware.setNav(Navigation.DPAD); - } else if (mTrackball.getSelection()) { - mHardware.setNav(Navigation.TRACKBALL); - } else { - mHardware.setNav(Navigation.NONAV); - } - long ram = Long.parseLong(mRam.getText()); - Storage.Unit unit = Storage.Unit.getEnum(mRamCombo.getText()); - mHardware.setRam(new Storage(ram, unit)); - if (mButtons.getText().equals(ButtonType.HARD.getDescription())) { - mHardware.setButtonType(ButtonType.HARD); - } else { - mHardware.setButtonType(ButtonType.SOFT); - } - - // Set the first enabled state to the default state - boolean defaultSelected = false; - if (mPortrait.getSelection()) { - State state = new State(); - state.setName("Portrait"); - state.setDescription("The device in portrait orientation"); - state.setOrientation(ScreenOrientation.PORTRAIT); - if (mHardware.getNav().equals(Navigation.NONAV) || !mPortraitNav.getSelection()) { - state.setNavState(NavigationState.HIDDEN); - } else { - state.setNavState(NavigationState.EXPOSED); - } - if (mHardware.getKeyboard().equals(Keyboard.NOKEY)) { - state.setKeyState(KeyboardState.SOFT); - } else { - state.setKeyState(KeyboardState.HIDDEN); - } - state.setHardware(mHardware); - if (!defaultSelected) { - state.setDefaultState(true); - defaultSelected = true; - } - builder.addState(state); - } - if (mLandscape.getSelection()) { - State state = new State(); - state.setName("Landscape"); - state.setDescription("The device in landscape orientation"); - state.setOrientation(ScreenOrientation.LANDSCAPE); - if (mHardware.getNav().equals(Navigation.NONAV) || !mLandscapeNav.getSelection()) { - state.setNavState(NavigationState.HIDDEN); - } else { - state.setNavState(NavigationState.EXPOSED); - } - if (mHardware.getKeyboard().equals(Keyboard.NOKEY)) { - state.setKeyState(KeyboardState.SOFT); - } else { - state.setKeyState(KeyboardState.HIDDEN); - } - state.setHardware(mHardware); - if (!defaultSelected) { - state.setDefaultState(true); - defaultSelected = true; - } - builder.addState(state); - } - if (mKeyboard.getSelection()) { - if (mPortraitKeys.getSelection()) { - State state = new State(); - state.setName("Portrait with keyboard"); - state.setDescription("The device in portrait orientation with a keyboard open"); - state.setOrientation(ScreenOrientation.LANDSCAPE); - if (mHardware.getNav().equals(Navigation.NONAV) - || !mPortraitKeysNav.getSelection()) { - state.setNavState(NavigationState.HIDDEN); - } else { - state.setNavState(NavigationState.EXPOSED); - } - state.setKeyState(KeyboardState.EXPOSED); - state.setHardware(mHardware); - if (!defaultSelected) { - state.setDefaultState(true); - defaultSelected = true; - } - builder.addState(state); - } - if (mLandscapeKeys.getSelection()) { - State state = new State(); - state.setName("Landscape with keyboard"); - state.setDescription("The device in landscape orientation with a keyboard open"); - state.setOrientation(ScreenOrientation.LANDSCAPE); - if (mHardware.getNav().equals(Navigation.NONAV) - || !mLandscapeKeysNav.getSelection()) { - state.setNavState(NavigationState.HIDDEN); - } else { - state.setNavState(NavigationState.EXPOSED); - } - state.setKeyState(KeyboardState.EXPOSED); - state.setHardware(mHardware); - if (!defaultSelected) { - state.setDefaultState(true); - defaultSelected = true; - } - builder.addState(state); - } - } - Device d = builder.build(); - if (mForceCreation.isEnabled() && mForceCreation.getSelection()) { - mManager.replaceUserDevice(d); - } else { - mManager.addUserDevice(d); - } - mManager.saveUserDevices(); - mCreatedDevice = d; - super.okPressed(); - } - } - -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/HardwarePropertyChooser.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/HardwarePropertyChooser.java deleted file mode 100644 index a07768c..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/HardwarePropertyChooser.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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.sdklib.internal.avd.HardwareProperties.HardwarePropertyType; -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.Comparator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeSet; - -/** - * 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>(); - - // Sort the combo entries by display name if available, otherwise by hardware name. - Set<Entry<String, HardwareProperty>> entries = - new TreeSet<Map.Entry<String,HardwareProperty>>( - new Comparator<Map.Entry<String,HardwareProperty>>() { - @Override - public int compare(Entry<String, HardwareProperty> entry0, - Entry<String, HardwareProperty> entry1) { - String s0 = entry0.getValue().getAbstract(); - String s1 = entry1.getValue().getAbstract(); - if (s0 != null && s1 != null) { - return s0.compareTo(s1); - } - return entry0.getKey().compareTo(entry1.getKey()); - } - }); - entries.addAll(mProperties.entrySet()); - - for (Entry<String, HardwareProperty> entry : entries) { - if (entry.getValue().isValidForUi() && - 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 = name == null ? null : mProperties.get(name); - - String type = "Unknown"; - String desc = "Unknown"; - - if (mChosenProperty != null) { - desc = mChosenProperty.getDescription(); - HardwarePropertyType vt = mChosenProperty.getType(); - if (vt != null) { - type = vt.getName(); - } - } - - mTypeLabel.setText(type); - mDescriptionLabel.setText(desc); - - if (pack) { - getShell().pack(); - } - } - -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/ImgDisabledButton.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/ImgDisabledButton.java deleted file mode 100755 index 62973a4..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/ImgDisabledButton.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2011 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 org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Composite; - -/** - * A label that can display 2 images depending on its enabled/disabled state. - * This acts as a button by firing the {@link SWT#Selection} listener. - */ -public class ImgDisabledButton extends ToggleButton { - public ImgDisabledButton( - Composite parent, - int style, - Image imageEnabled, - Image imageDisabled, - String tooltipEnabled, - String tooltipDisabled) { - super(parent, - style, - imageEnabled, - imageDisabled, - tooltipEnabled, - tooltipDisabled); - } - - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - updateImageAndTooltip(); - redraw(); - } - - @Override - public void setState(int state) { - throw new UnsupportedOperationException(); // not available for this type of button - } - - @Override - public int getState() { - return (isDisposed() || !isEnabled()) ? 1 : 0; - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/LegacyAvdEditDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/LegacyAvdEditDialog.java deleted file mode 100644 index 91f45c8..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/LegacyAvdEditDialog.java +++ /dev/null @@ -1,1425 +0,0 @@ -/* - * 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.SdkConstants; -import com.android.io.FileWrapper; -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.ISystemImage; -import com.android.sdklib.SdkManager; -import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdklib.internal.avd.AvdManager.AvdConflict; -import com.android.sdklib.internal.avd.HardwareProperties; -import com.android.sdklib.internal.avd.HardwareProperties.HardwareProperty; -import com.android.sdklib.internal.project.ProjectProperties; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.ui.GridDialog; -import com.android.utils.ILogger; -import com.android.utils.Pair; - -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.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.VerifyEvent; -import org.eclipse.swt.events.VerifyListener; -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.Group; -import org.eclipse.swt.widgets.Label; -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 java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.TreeMap; -import java.util.regex.Matcher; - -/** - * AVD creation or edit dialog. - * - * TODO: - * - use SdkTargetSelector instead of Combo - * - tooltips on widgets. - * - */ -final class LegacyAvdEditDialog extends GridDialog { - - private final AvdManager mAvdManager; - private final TreeMap<String, IAndroidTarget> mCurrentTargets = - 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 final ImageFactory mImageFactory; - private final ILogger mSdkLog; - /** - * The original AvdInfo if we're editing an existing AVD. - * Null when we're creating a new AVD. - */ - private final AvdInfo mEditAvdInfo; - - private Text mAvdName; - private Combo mTargetCombo; - - private Combo mAbiTypeCombo; - private String mAbiType; - - private Button mSdCardSizeRadio; - private Text mSdCardSize; - private Combo mSdCardSizeCombo; - - private Text mSdCardFile; - private Button mBrowseSdCard; - private Button mSdCardFileRadio; - - private Button mSnapshotCheck; - - private Button mSkinListRadio; - private Combo mSkinCombo; - - private Button mSkinSizeRadio; - private Text mSkinSizeWidth; - private Text mSkinSizeHeight; - - private TableViewer mHardwareViewer; - private Button mDeleteHardwareProp; - - private Button mForceCreation; - private Button mOkButton; - private Label mStatusIcon; - private Label mStatusLabel; - private Composite mStatusComposite; - - /** - * {@link VerifyListener} for {@link Text} widgets that should only contains numbers. - */ - private final VerifyListener mDigitVerifier = new VerifyListener() { - @Override - public void verifyText(VerifyEvent event) { - int count = event.text.length(); - for (int i = 0 ; i < count ; i++) { - char c = event.text.charAt(i); - if (c < '0' || c > '9') { - event.doit = false; - return; - } - } - } - }; - - /** - * Callback when the AVD name is changed. - * When creating a new AVD, enables the force checkbox if the name is a duplicate. - * When editing an existing AVD, it's OK for the name to match the existing AVD. - */ - private class CreateNameModifyListener implements ModifyListener { - @Override - public void modifyText(ModifyEvent e) { - String name = mAvdName.getText().trim(); - if (mEditAvdInfo == null || !name.equals(mEditAvdInfo.getName())) { - // Case where we're creating a new AVD or editing an existing one - // and the AVD name has been changed... check for name uniqueness. - - Pair<AvdConflict, String> conflict = mAvdManager.isAvdNameConflicting(name); - if (conflict.getFirst() != AvdManager.AvdConflict.NO_CONFLICT) { - // If we're changing the state from disabled to enabled, make sure - // to uncheck the button, to force the user to voluntarily re-enforce it. - // This happens when editing an existing AVD and changing the name from - // the existing AVD to another different existing AVD. - if (!mForceCreation.isEnabled()) { - mForceCreation.setEnabled(true); - mForceCreation.setSelection(false); - } - } else { - mForceCreation.setEnabled(false); - mForceCreation.setSelection(false); - } - } else { - // Case where we're editing an existing AVD with the name unchanged. - - mForceCreation.setEnabled(false); - mForceCreation.setSelection(false); - } - validatePage(); - } - } - - /** - * {@link ModifyListener} used for live-validation of the fields content. - */ - private class ValidateListener extends SelectionAdapter implements ModifyListener { - @Override - public void modifyText(ModifyEvent e) { - validatePage(); - } - - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - validatePage(); - } - } - - /** - * Creates the dialog. Caller should then use {@link Window#open()} and - * refresh if the status is {@link Window#OK}. - * - * @param parentShell The parent shell. - * @param avdManager The existing {@link AvdManager} to use. Must not be null. - * @param imageFactory An existing {@link ImageFactory} to use. Must not be null. - * @param log An existing {@link ILogger} where output will go. Must not be null. - * @param editAvdInfo An optional {@link AvdInfo}. When null, the dialog is used - * to create a new AVD. When non-null, the dialog is used to <em>edit</em> this AVD. - */ - protected LegacyAvdEditDialog(Shell parentShell, - AvdManager avdManager, - ImageFactory imageFactory, - ILogger log, - AvdInfo editAvdInfo) { - super(parentShell, 2, false); - mAvdManager = avdManager; - mImageFactory = imageFactory; - mSdkLog = log; - mEditAvdInfo = editAvdInfo; - - File hardwareDefs = null; - - SdkManager sdkMan = avdManager.getSdkManager(); - if (sdkMan != null) { - String sdkPath = sdkMan.getLocation(); - if (sdkPath != null) { - hardwareDefs = new File (sdkPath + File.separator + - SdkConstants.OS_SDK_TOOLS_LIB_FOLDER, SdkConstants.FN_HARDWARE_INI); - } - } - - if (hardwareDefs == null) { - log.error(null, "Failed to load file %s from SDK", SdkConstants.FN_HARDWARE_INI); - mHardwareMap = new HashMap<String, HardwareProperty>(); - } else { - mHardwareMap = HardwareProperties.parseHardwareDefinitions( - hardwareDefs, null /*sdkLog*/); - } - } - - @Override - public void create() { - super.create(); - - Point p = getShell().getSize(); - if (p.x < 400) { - p.x = 400; - } - getShell().setSize(p); - } - - @Override - protected Control createContents(Composite parent) { - Control control = super.createContents(parent); - getShell().setText(mEditAvdInfo == null ? "Create new Android Virtual Device (AVD)" - : "Edit Android Virtual Device (AVD)"); - - mOkButton = getButton(IDialogConstants.OK_ID); - - fillExistingAvdInfo(); - validatePage(); - - return control; - } - - @Override - public void createDialogContent(final Composite parent) { - GridData gd; - GridLayout gl; - - Label label = new Label(parent, SWT.NONE); - label.setText("Name:"); - String tooltip = "Name of the new Android Virtual Device"; - label.setToolTipText(tooltip); - - mAvdName = new Text(parent, SWT.BORDER); - mAvdName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mAvdName.addModifyListener(new CreateNameModifyListener()); - mAvdName.setToolTipText(tooltip); - - label = new Label(parent, SWT.NONE); - label.setText("Target:"); - tooltip = "The version of Android to use in the virtual device"; - label.setToolTipText(tooltip); - - mTargetCombo = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN); - mTargetCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mTargetCombo.setToolTipText(tooltip); - mTargetCombo.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - reloadSkinCombo(); - reloadAbiTypeCombo(); - validatePage(); - } - }); - - //ABI group - label = new Label(parent, SWT.NONE); - label.setText("CPU/ABI:"); - tooltip = "The CPU/ABI to use in the virtual device"; - label.setToolTipText(tooltip); - - mAbiTypeCombo = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN); - mAbiTypeCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mAbiTypeCombo.setToolTipText(tooltip); - mAbiTypeCombo.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - validatePage(); - } - }); - mAbiTypeCombo.setEnabled(false); - - // --- sd card group - label = new Label(parent, SWT.NONE); - label.setText("SD Card:"); - label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, - false, false)); - - final Group sdCardGroup = new Group(parent, SWT.NONE); - sdCardGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - sdCardGroup.setLayout(new GridLayout(3, false)); - - mSdCardSizeRadio = new Button(sdCardGroup, SWT.RADIO); - mSdCardSizeRadio.setText("Size:"); - mSdCardSizeRadio.setToolTipText("Create a new SD Card file"); - mSdCardSizeRadio.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - boolean sizeMode = mSdCardSizeRadio.getSelection(); - enableSdCardWidgets(sizeMode); - validatePage(); - } - }); - - ValidateListener validateListener = new ValidateListener(); - - mSdCardSize = new Text(sdCardGroup, SWT.BORDER); - mSdCardSize.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mSdCardSize.addVerifyListener(mDigitVerifier); - mSdCardSize.addModifyListener(validateListener); - mSdCardSize.setToolTipText("Size of the new SD Card file (must be at least 9 MiB)"); - - mSdCardSizeCombo = new Combo(sdCardGroup, SWT.DROP_DOWN | SWT.READ_ONLY); - mSdCardSizeCombo.add("KiB"); - mSdCardSizeCombo.add("MiB"); - mSdCardSizeCombo.add("GiB"); - mSdCardSizeCombo.select(1); - mSdCardSizeCombo.addSelectionListener(validateListener); - - mSdCardFileRadio = new Button(sdCardGroup, SWT.RADIO); - mSdCardFileRadio.setText("File:"); - mSdCardFileRadio.setToolTipText("Use an existing file for the SD Card"); - - mSdCardFile = new Text(sdCardGroup, SWT.BORDER); - mSdCardFile.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mSdCardFile.addModifyListener(validateListener); - mSdCardFile.setToolTipText("File to use for the SD Card"); - - mBrowseSdCard = new Button(sdCardGroup, SWT.PUSH); - mBrowseSdCard.setText("Browse..."); - mBrowseSdCard.setToolTipText("Select the file to use for the SD Card"); - mBrowseSdCard.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - onBrowseSdCard(); - validatePage(); - } - }); - - mSdCardSizeRadio.setSelection(true); - enableSdCardWidgets(true); - - // --- snapshot group - - label = new Label(parent, SWT.NONE); - label.setText("Snapshot:"); - label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, - false, false)); - - final Group snapshotGroup = new Group(parent, SWT.NONE); - snapshotGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - snapshotGroup.setLayout(new GridLayout(3, false)); - - mSnapshotCheck = new Button(snapshotGroup, SWT.CHECK); - mSnapshotCheck.setText("Enabled"); - mSnapshotCheck.setToolTipText( - "Emulator's state will be persisted between emulator executions"); - - // --- skin group - label = new Label(parent, SWT.NONE); - label.setText("Skin:"); - label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, - false, false)); - - final Group skinGroup = new Group(parent, SWT.NONE); - skinGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - skinGroup.setLayout(new GridLayout(4, false)); - - mSkinListRadio = new Button(skinGroup, SWT.RADIO); - mSkinListRadio.setText("Built-in:"); - mSkinListRadio.setToolTipText("Select an emulated screen size provided by the current Android target"); - mSkinListRadio.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - boolean listMode = mSkinListRadio.getSelection(); - enableSkinWidgets(listMode); - validatePage(); - } - }); - - mSkinCombo = new Combo(skinGroup, SWT.READ_ONLY | SWT.DROP_DOWN); - mSkinCombo.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - 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.setText("Resolution:"); - mSkinSizeRadio.setToolTipText("Select a custom emulated screen size"); - - mSkinSizeWidth = new Text(skinGroup, SWT.BORDER); - mSkinSizeWidth.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mSkinSizeWidth.addVerifyListener(mDigitVerifier); - mSkinSizeWidth.addModifyListener(validateListener); - mSkinSizeWidth.setToolTipText("Width in pixels of the emulated screen size"); - - new Label(skinGroup, SWT.NONE).setText("x"); - - mSkinSizeHeight = new Text(skinGroup, SWT.BORDER); - mSkinSizeHeight.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mSkinSizeHeight.addVerifyListener(mDigitVerifier); - mSkinSizeHeight.addModifyListener(validateListener); - mSkinSizeHeight.setToolTipText("Height in pixels of the emulated screen size"); - - mSkinListRadio.setSelection(true); - enableSkinWidgets(true); - - // --- hardware group - label = new Label(parent, SWT.NONE); - label.setText("Hardware:"); - label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, - false, false)); - - 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.setToolTipText("Add a new hardware property"); - 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.setToolTipText("Delete the selected hardware property"); - 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("Override the existing AVD with the same name"); - mForceCreation.setToolTipText("There's already an AVD with the same name. Check this to delete it and replace it by the new AVD."); - mForceCreation.setLayoutData(new GridData(GridData.BEGINNING, 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(parent, 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(parent, SWT.NONE); - mStatusComposite.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, - true, false, 3, 1)); - 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(); - } - - /** - * 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() { - @Override - 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() { - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - // we can just ignore this. we just use mProperties directly. - } - - @Override - public Object[] getElements(Object arg0) { - return mProperties.keySet().toArray(); - } - - @Override - 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) { - String name = cell.getElement().toString(); - HardwareProperty prop = mHardwareMap.get(name); - if (prop != null) { - cell.setText(prop.getAbstract()); - } else { - cell.setText(String.format("%1$s (Unknown)", name)); - } - } - }); - - // -- 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); - int index; - 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: - index = (Integer)value; - mProperties.put((String)element, HardwareProperties.BOOLEAN_VALUES[index]); - break; - case STRING_ENUM: - case INTEGER_ENUM: - // For a combo, value is the index of the enum to use. - index = (Integer)value; - String[] values = property.getEnum(); - if (values != null && values.length > index) { - mProperties.put((String)element, 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); - case STRING_ENUM: - case INTEGER_ENUM: - // For a combo, we need to return the index of the value in the enum - String[] values = property.getEnum(); - if (values != null) { - for (int i = 0; i < values.length; i++) { - if (values[i].equals(value)) { - return i; - } - } - } - } - - 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); - case STRING_ENUM: - case INTEGER_ENUM: - String[] values = property.getEnum(); - if (values != null && values.length > 0) { - return new ComboBoxCellEditor(hardwareTable, - 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); - } - - // -- Start of internal part ---------- - // Hide everything down-below from SWT designer - //$hide>>$ - - /** - * When editing an existing AVD info, fill the UI that has just been created with - * the values from the AVD. - */ - public void fillExistingAvdInfo() { - if (mEditAvdInfo == null) { - return; - } - - mAvdName.setText(mEditAvdInfo.getName()); - - Map<String, String> props = mEditAvdInfo.getProperties(); - - IAndroidTarget target = mEditAvdInfo.getTarget(); - if (target != null && !mCurrentTargets.isEmpty()) { - // Try to select the target in the target combo. - // This will fail if the AVD needs to be repaired. - // - // This is a linear search but the list is always - // small enough and we only do this once. - int n = mTargetCombo.getItemCount(); - for (int i = 0;i < n; i++) { - if (target.equals(mCurrentTargets.get(mTargetCombo.getItem(i)))) { - mTargetCombo.select(i); - reloadAbiTypeCombo(); - reloadSkinCombo(); - break; - } - } - } - - // select the abi type - ISystemImage[] systemImages = getSystemImages(target); - if (target != null && systemImages.length > 0) { - mAbiTypeCombo.setEnabled(systemImages.length > 1); - String abiType = AvdInfo.getPrettyAbiType(mEditAvdInfo.getAbiType()); - int n = mAbiTypeCombo.getItemCount(); - for (int i = 0; i < n; i++) { - if (abiType.equals(mAbiTypeCombo.getItem(i))) { - mAbiTypeCombo.select(i); - reloadSkinCombo(); - break; - } - } - } - - if (props != null) { - - // First try the skin name and if it doesn't work fallback on the skin path - nextSkin: for (int s = 0; s < 2; s++) { - String skin = props.get(s == 0 ? AvdManager.AVD_INI_SKIN_NAME - : AvdManager.AVD_INI_SKIN_PATH); - if (skin != null && skin.length() > 0) { - Matcher m = AvdManager.NUMERIC_SKIN_SIZE.matcher(skin); - if (m.matches() && m.groupCount() == 2) { - enableSkinWidgets(false); - mSkinListRadio.setSelection(false); - mSkinSizeRadio.setSelection(true); - mSkinSizeWidth.setText(m.group(1)); - mSkinSizeHeight.setText(m.group(2)); - break nextSkin; - } else { - enableSkinWidgets(true); - mSkinSizeRadio.setSelection(false); - mSkinListRadio.setSelection(true); - - int n = mSkinCombo.getItemCount(); - for (int i = 0; i < n; i++) { - if (skin.equals(mSkinCombo.getItem(i))) { - mSkinCombo.select(i); - break nextSkin; - } - } - } - } - } - - String sdcard = props.get(AvdManager.AVD_INI_SDCARD_PATH); - if (sdcard != null && sdcard.length() > 0) { - enableSdCardWidgets(false); - mSdCardSizeRadio.setSelection(false); - mSdCardFileRadio.setSelection(true); - mSdCardFile.setText(sdcard); - } - - sdcard = props.get(AvdManager.AVD_INI_SDCARD_SIZE); - if (sdcard != null && sdcard.length() > 0) { - String[] values = new String[2]; - long sdcardSize = AvdManager.parseSdcardSize(sdcard, values); - - if (sdcardSize != AvdManager.SDCARD_NOT_SIZE_PATTERN) { - enableSdCardWidgets(true); - mSdCardFileRadio.setSelection(false); - mSdCardSizeRadio.setSelection(true); - - mSdCardSize.setText(values[0]); - - String suffix = values[1]; - int n = mSdCardSizeCombo.getItemCount(); - for (int i = 0; i < n; i++) { - if (mSdCardSizeCombo.getItem(i).startsWith(suffix)) { - mSdCardSizeCombo.select(i); - } - } - } - } - - String snapshots = props.get(AvdManager.AVD_INI_SNAPSHOT_PRESENT); - if (snapshots != null && snapshots.length() > 0) { - mSnapshotCheck.setSelection(snapshots.equals("true")); - } - } - - mProperties.clear(); - - if (props != null) { - for (Entry<String, String> entry : props.entrySet()) { - HardwareProperty prop = mHardwareMap.get(entry.getKey()); - if (prop != null && prop.isValidForUi()) { - mProperties.put(entry.getKey(), entry.getValue()); - } - } - } - - // Cleanup known non-hardware properties - mProperties.remove(AvdManager.AVD_INI_ABI_TYPE); - mProperties.remove(AvdManager.AVD_INI_CPU_ARCH); - mProperties.remove(AvdManager.AVD_INI_SKIN_PATH); - mProperties.remove(AvdManager.AVD_INI_SKIN_NAME); - mProperties.remove(AvdManager.AVD_INI_SDCARD_SIZE); - mProperties.remove(AvdManager.AVD_INI_SDCARD_PATH); - mProperties.remove(AvdManager.AVD_INI_SNAPSHOT_PRESENT); - mProperties.remove(AvdManager.AVD_INI_IMAGES_1); - mProperties.remove(AvdManager.AVD_INI_IMAGES_2); - - mHardwareViewer.refresh(); - } - - @Override - protected void okPressed() { - if (createAvd()) { - super.okPressed(); - } - } - - /** - * Enable or disable the sd card widgets. - * @param sizeMode if true the size-based widgets are to be enabled, and the file-based ones - * disabled. - */ - private void enableSdCardWidgets(boolean sizeMode) { - mSdCardSize.setEnabled(sizeMode); - mSdCardSizeCombo.setEnabled(sizeMode); - - mSdCardFile.setEnabled(!sizeMode); - mBrowseSdCard.setEnabled(!sizeMode); - } - - /** - * Enable or disable the skin widgets. - * @param listMode if true the list-based widgets are to be enabled, and the size-based ones - * disabled. - */ - private void enableSkinWidgets(boolean listMode) { - mSkinCombo.setEnabled(listMode); - - mSkinSizeWidth.setEnabled(!listMode); - mSkinSizeHeight.setEnabled(!listMode); - } - - - 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) { - mSdCardFile.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; - if (target.isPlatform()) { - name = String.format("%s - API Level %s", - target.getName(), - target.getVersion().getApiString()); - } else { - name = String.format("%s (%s) - API Level %s", - target.getName(), - target.getVendor(), - target.getVersion().getApiString()); - } - 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 - loadSkin(); - } - } - } - } - - /** - * Reload all the abi types in the selection list - */ - private void reloadAbiTypeCombo() { - String selected = null; - boolean found = false; - - int index = mTargetCombo.getSelectionIndex(); - if (index >= 0) { - String targetName = mTargetCombo.getItem(index); - IAndroidTarget target = mCurrentTargets.get(targetName); - - ISystemImage[] systemImages = getSystemImages(target); - - mAbiTypeCombo.setEnabled(systemImages.length > 1); - - // If user explicitly selected an ABI before, preserve that option - // If user did not explicitly select before (only one option before) - // force them to select - index = mAbiTypeCombo.getSelectionIndex(); - if (index >= 0 && mAbiTypeCombo.getItemCount() > 1) { - selected = mAbiTypeCombo.getItem(index); - } - - mAbiTypeCombo.removeAll(); - - int i; - for ( i = 0; i < systemImages.length ; i++ ) { - String prettyAbiType = AvdInfo.getPrettyAbiType(systemImages[i].getAbiType()); - mAbiTypeCombo.add(prettyAbiType); - if (!found) { - found = prettyAbiType.equals(selected); - if (found) { - mAbiTypeCombo.select(i); - } - } - } - - if (systemImages.length == 1) { - mAbiTypeCombo.select(0); - } - } - } - - /** - * Validates the fields, displays errors and warnings. - * Enables the finish button if there are no errors. - */ - private void validatePage() { - String error = null; - String warning = null; - - // Validate AVD name - String avdName = mAvdName.getText().trim(); - boolean hasAvdName = avdName.length() > 0; - boolean isCreate = mEditAvdInfo == null || !avdName.equals(mEditAvdInfo.getName()); - - 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 abi type if the selected target supports multi archs. - if (hasAvdName && error == null && mTargetCombo.getSelectionIndex() > 0) { - int index = mTargetCombo.getSelectionIndex(); - String targetName = mTargetCombo.getItem(index); - IAndroidTarget target = mCurrentTargets.get(targetName); - ISystemImage[] systemImages = getSystemImages(target); - if (systemImages.length > 1 && mAbiTypeCombo.getSelectionIndex() < 0) { - error = "An ABI type must be selected in order to create an AVD."; - } - } - - // Validate SDCard path or value - if (error == null) { - // get the mode. We only need to check the file since the - // verifier on the size Text will prevent invalid input - boolean sdcardFileMode = mSdCardFileRadio.getSelection(); - if (sdcardFileMode) { - String sdName = mSdCardFile.getText().trim(); - if (sdName.length() > 0 && !new File(sdName).isFile()) { - error = "SD Card path isn't valid."; - } - } else { - String valueString = mSdCardSize.getText(); - if (valueString.length() > 0) { - long value = 0; - try { - value = Long.parseLong(valueString); - - int sizeIndex = mSdCardSizeCombo.getSelectionIndex(); - if (sizeIndex >= 0) { - // index 0 shifts by 10 (1024=K), index 1 by 20, etc. - value <<= 10*(1 + sizeIndex); - } - - if (value < AvdManager.SDCARD_MIN_BYTE_SIZE || - value > AvdManager.SDCARD_MAX_BYTE_SIZE) { - value = 0; - } - } catch (Exception e) { - // ignore, we'll test value below. - } - if (value <= 0) { - error = "SD Card size is invalid. Range is 9 MiB..1023 GiB."; - } else if (mEditAvdInfo != null) { - // When editing an existing AVD, compare with the existing - // sdcard size, if any. It only matters if there was an sdcard setting - // before. - Map<String, String> props = mEditAvdInfo.getProperties(); - if (props != null) { - String original = - mEditAvdInfo.getProperties().get(AvdManager.AVD_INI_SDCARD_SIZE); - if (original != null && original.length() > 0) { - long originalSize = - AvdManager.parseSdcardSize(original, null/*parsedStrings*/); - if (originalSize > 0 && value != originalSize) { - warning = "A new SD Card file will be created.\nThe current SD Card file will be lost."; - } - } - } - } - } - } - } - - // validate the skin - if (error == null) { - // get the mode, we should only check if it's in size mode since - // the built-in list mode is always valid. - if (mSkinSizeRadio.getSelection()) { - // need both with and heigh to be non null - String width = mSkinSizeWidth.getText(); // no need for trim, since the verifier - String height = mSkinSizeHeight.getText(); // rejects non digit. - - if (width.length() == 0 || height.length() == 0) { - error = "Skin size is incorrect.\nBoth dimensions must be > 0."; - } - } - } - - // Check for duplicate AVD name - if (isCreate && hasAvdName && error == null && !mForceCreation.getSelection()) { - Pair<AvdConflict, String> conflict = mAvdManager.isAvdNameConflicting(avdName); - assert conflict != null; - switch(conflict.getFirst()) { - case NO_CONFLICT: - break; - case CONFLICT_EXISTING_AVD: - case CONFLICT_INVALID_AVD: - error = String.format( - "The AVD name '%s' is already used.\n" + - "Check \"Override the existing AVD\" to delete the existing one.", - avdName); - break; - case CONFLICT_EXISTING_PATH: - error = String.format( - "Conflict with %s\n" + - "Check \"Override the existing AVD\" to delete the existing one.", - conflict.getSecond()); - break; - default: - // Hmm not supposed to happen... probably someone expanded the - // enum without adding something here. In this case just do an - // assert and use a generic error message. - error = String.format( - "Conflict %s with %s.\n" + - "Check \"Override the existing AVD\" to delete the existing one.", - conflict.getFirst().toString(), - conflict.getSecond()); - assert false; - break; - } - } - - if (error == null && mEditAvdInfo != null && isCreate) { - warning = String.format("The AVD '%1$s' will be duplicated into '%2$s'.", - mEditAvdInfo.getName(), - avdName); - } - - // Validate the create button - boolean can_create = hasAvdName && error == null; - if (can_create) { - can_create &= mTargetCombo.getSelectionIndex() >= 0; - } - mOkButton.setEnabled(can_create); - - // Adjust the create button label as needed - if (isCreate) { - mOkButton.setText("Create AVD"); - } else { - mOkButton.setText("Edit AVD"); - } - - // -- update UI - if (error != null) { - mStatusIcon.setImage(mImageFactory.getImageByName("reject_icon16.png")); //$NON-NLS-1$ - mStatusLabel.setText(error); - } else if (warning != null) { - mStatusIcon.setImage(mImageFactory.getImageByName("warning_icon16.png")); //$NON-NLS-1$ - mStatusLabel.setText(warning); - } else { - mStatusIcon.setImage(null); - mStatusLabel.setText(" \n "); //$NON-NLS-1$ - } - - 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) { - FileWrapper targetHardwareFile = new FileWrapper(target.getLocation(), - AvdManager.HARDWARE_INI); - if (targetHardwareFile.isFile()) { - Map<String, String> targetHardwareConfig = ProjectProperties.parsePropertyFile( - targetHardwareFile, null /*log*/); - - if (targetHardwareConfig != null) { - hardwareValues.putAll(targetHardwareConfig); - } - } - } - - // from the skin - FileWrapper skinHardwareFile = new FileWrapper(skin, AvdManager.HARDWARE_INI); - if (skinHardwareFile.isFile()) { - Map<String, String> skinHardwareConfig = ProjectProperties.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. - */ - private boolean createAvd() { - String avdName = mAvdName.getText().trim(); - int index = mTargetCombo.getSelectionIndex(); - - // quick check on the name and the target selection - if (avdName.length() == 0 || index < 0) { - return false; - } - - // resolve the target. - String targetName = mTargetCombo.getItem(index); - IAndroidTarget target = mCurrentTargets.get(targetName); - if (target == null) { - return false; - } - - // get the abi type - mAbiType = SdkConstants.ABI_ARMEABI; - ISystemImage[] systemImages = getSystemImages(target); - if (systemImages.length > 0) { - int abiIndex = mAbiTypeCombo.getSelectionIndex(); - if (abiIndex >= 0) { - String prettyname = mAbiTypeCombo.getItem(abiIndex); - //Extract the abi type - int firstIndex = prettyname.indexOf("("); - int lastIndex = prettyname.indexOf(")"); - mAbiType = prettyname.substring(firstIndex+1, lastIndex); - } - } - - // get the SD card data from the UI. - String sdName = null; - if (mSdCardSizeRadio.getSelection()) { - // size mode - String value = mSdCardSize.getText().trim(); - if (value.length() > 0) { - sdName = value; - // add the unit - switch (mSdCardSizeCombo.getSelectionIndex()) { - case 0: - sdName += "K"; //$NON-NLS-1$ - break; - case 1: - sdName += "M"; //$NON-NLS-1$ - break; - case 2: - sdName += "G"; //$NON-NLS-1$ - break; - default: - // shouldn't be here - assert false; - } - } - } else { - // file mode. - sdName = mSdCardFile.getText().trim(); - } - - // get the Skin data from the UI - String skinName = null; - if (mSkinListRadio.getSelection()) { - // built-in list provides the skin - int skinIndex = mSkinCombo.getSelectionIndex(); - if (skinIndex > 0) { - // index 0 is the default, we don't use it - skinName = mSkinCombo.getItem(skinIndex); - } - } else { - // size mode. get both size and writes it as a skin name - // thanks to validatePage() we know the content of the fields is correct - skinName = mSkinSizeWidth.getText() + "x" + mSkinSizeHeight.getText(); //$NON-NLS-1$ - } - - ILogger log = mSdkLog; - if (log == null || log instanceof MessageBoxLog) { - // If the current logger is a message box, we use our own (to make sure - // to display errors right away and customize the title). - log = new MessageBoxLog( - String.format("Result of creating AVD '%s':", avdName), - getContents().getDisplay(), - false /*logErrorsOnly*/); - } - - File avdFolder = null; - try { - avdFolder = AvdInfo.getDefaultAvdFolder(mAvdManager, avdName); - } catch (AndroidLocationException e) { - return false; - } - - boolean force = mForceCreation.getSelection(); - boolean snapshot = mSnapshotCheck.getSelection(); - - boolean success = false; - AvdInfo avdInfo = mAvdManager.createAvd( - avdFolder, - avdName, - target, - mAbiType, - skinName, - sdName, - mProperties, - snapshot, - force, - mEditAvdInfo != null, //edit existing - log); - - success = avdInfo != null; - - if (log instanceof MessageBoxLog) { - ((MessageBoxLog) log).displayResult(success); - } - return success; - } - - /** - * Returns the list of system images of a target. - * <p/> - * If target is null, returns an empty list. - * If target is an add-on with no system images, return the list from its parent platform. - * - * @param target An IAndroidTarget. Can be null. - * @return A non-null ISystemImage array. Can be empty. - */ - private ISystemImage[] getSystemImages(IAndroidTarget target) { - if (target != null) { - ISystemImage[] images = target.getSystemImages(); - - if ((images == null || images.length == 0) && !target.isPlatform()) { - // If an add-on does not provide any system images, use the ones from the parent. - images = target.getParent().getSystemImages(); - } - - if (images != null) { - return images; - } - } - - return new ISystemImage[0]; - } - - // End of hiding from SWT Designer - //$hide<<$ -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/MessageBoxLog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/MessageBoxLog.java deleted file mode 100755 index f5b75e0..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/MessageBoxLog.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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.annotations.NonNull; -import com.android.utils.ILogger; - -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; - -import java.util.ArrayList; - - -/** - * Collects all log and displays it in a message box dialog. - * <p/> - * This is good if only a few lines of log are expected. - * If you pass <var>logErrorsOnly</var> to the constructor, the message box - * will be shown only if errors were generated, which is the typical use-case. - * <p/> - * To use this: </br> - * - Construct a new {@link MessageBoxLog}. </br> - * - Pass the logger to the action. </br> - * - Once the action is completed, call {@link #displayResult(boolean)} - * indicating whether the operation was successful or not. - * - * When <var>logErrorsOnly</var> is true, if the operation was not successful or errors - * were generated, this will display the message box. - */ -public final class MessageBoxLog implements ILogger { - - final ArrayList<String> logMessages = new ArrayList<String>(); - private final String mMessage; - private final Display mDisplay; - private final boolean mLogErrorsOnly; - - /** - * Creates a logger that will capture all logs and eventually display them - * in a simple message box. - * - * @param message - * @param display - * @param logErrorsOnly - */ - public MessageBoxLog(String message, Display display, boolean logErrorsOnly) { - mMessage = message; - mDisplay = display; - mLogErrorsOnly = logErrorsOnly; - } - - @Override - public void error(Throwable throwable, String errorFormat, Object... arg) { - if (errorFormat != null) { - logMessages.add(String.format("Error: " + errorFormat, arg)); - } - - if (throwable != null) { - logMessages.add(throwable.getMessage()); - } - } - - @Override - public void warning(@NonNull String warningFormat, Object... arg) { - if (!mLogErrorsOnly) { - logMessages.add(String.format("Warning: " + warningFormat, arg)); - } - } - - @Override - public void info(@NonNull String msgFormat, Object... arg) { - if (!mLogErrorsOnly) { - logMessages.add(String.format(msgFormat, arg)); - } - } - - @Override - public void verbose(@NonNull String msgFormat, Object... arg) { - if (!mLogErrorsOnly) { - logMessages.add(String.format(msgFormat, arg)); - } - } - - /** - * Displays the log if anything was captured. - * <p/> - * @param success Used only when the logger was constructed with <var>logErrorsOnly</var>==true. - * In this case the dialog will only be shown either if success if false or some errors - * where captured. - */ - public void displayResult(final boolean success) { - if (logMessages.size() > 0) { - final StringBuilder sb = new StringBuilder(mMessage + "\n\n"); - for (String msg : logMessages) { - if (msg.length() > 0) { - if (msg.charAt(0) != '\n') { - int n = sb.length(); - if (n > 0 && sb.charAt(n-1) != '\n') { - sb.append('\n'); - } - } - sb.append(msg); - } - } - - // display the message - // dialog box only run in ui thread.. - if (mDisplay != null && !mDisplay.isDisposed()) { - mDisplay.asyncExec(new Runnable() { - @Override - public void run() { - // This is typically displayed at the end, so make sure the UI - // instances are not disposed. - Shell shell = null; - if (mDisplay != null && !mDisplay.isDisposed()) { - shell = mDisplay.getActiveShell(); - } - if (shell == null || shell.isDisposed()) { - return; - } - // Use the success icon if the call indicates success. - // However just use the error icon if the logger was only recording errors. - if (success && !mLogErrorsOnly) { - MessageDialog.openInformation(shell, "Android Virtual Devices Manager", - sb.toString()); - } else { - MessageDialog.openError(shell, "Android Virtual Devices Manager", - sb.toString()); - - } - } - }); - } - } - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/ResolutionChooserDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/ResolutionChooserDialog.java deleted file mode 100644 index 7454437..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/ResolutionChooserDialog.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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.sdkuilib.ui.GridDialog; - -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Rectangle; -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.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Monitor; -import org.eclipse.swt.widgets.Shell; - -/** - * Small dialog to let a user choose a screen size (from a fixed list) and a resolution - * (as returned by {@link Display#getMonitors()}). - - * After the dialog as returned, one can query {@link #getDensity()} to get the chosen monitor - * pixel density. - */ -public class ResolutionChooserDialog extends GridDialog { - public final static float[] MONITOR_SIZES = new float[] { - 13.3f, 14, 15.4f, 15.6f, 17, 19, 20, 21, 24, 30, - }; - - private Button mButton; - private Combo mScreenSizeCombo; - private Combo mMonitorCombo; - - private Monitor[] mMonitors; - private int mScreenSizeIndex = -1; - private int mMonitorIndex = 0; - - public ResolutionChooserDialog(Shell parentShell) { - super(parentShell, 2, false); - } - - /** - * Returns the pixel density of the user-chosen monitor. - */ - public int getDensity() { - float size = MONITOR_SIZES[mScreenSizeIndex]; - Rectangle rect = mMonitors[mMonitorIndex].getBounds(); - - // compute the density - double d = Math.sqrt(rect.width * rect.width + rect.height * rect.height) / size; - return (int)Math.round(d); - } - - @Override - protected void configureShell(Shell newShell) { - newShell.setText("Monitor Density"); - super.configureShell(newShell); - } - - @Override - protected Control createContents(Composite parent) { - Control control = super.createContents(parent); - mButton = getButton(IDialogConstants.OK_ID); - mButton.setEnabled(false); - return control; - } - - @Override - public void createDialogContent(Composite parent) { - Label l = new Label(parent, SWT.NONE); - l.setText("Screen Size:"); - - mScreenSizeCombo = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY); - for (float size : MONITOR_SIZES) { - if (Math.round(size) == size) { - mScreenSizeCombo.add(String.format("%.0f\"", size)); - } else { - mScreenSizeCombo.add(String.format("%.1f\"", size)); - } - } - mScreenSizeCombo.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent arg0) { - mScreenSizeIndex = mScreenSizeCombo.getSelectionIndex(); - mButton.setEnabled(mScreenSizeIndex != -1); - } - }); - - l = new Label(parent, SWT.NONE); - l.setText("Resolution:"); - - mMonitorCombo = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY); - mMonitors = parent.getDisplay().getMonitors(); - for (Monitor m : mMonitors) { - Rectangle r = m.getBounds(); - mMonitorCombo.add(String.format("%d x %d", r.width, r.height)); - } - mMonitorCombo.select(mMonitorIndex); - mMonitorCombo.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetDefaultSelected(SelectionEvent arg0) { - mMonitorIndex = mMonitorCombo.getSelectionIndex(); - } - }); - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/SdkTargetSelector.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/SdkTargetSelector.java deleted file mode 100644 index 7d2e90f..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/SdkTargetSelector.java +++ /dev/null @@ -1,460 +0,0 @@ -/* - * 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.SdkConstants; -import com.android.sdklib.IAndroidTarget; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ControlAdapter; -import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Shell; -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.Comparator; - - -/** - * The SDK target selector is a table that is added to the given parent composite. - * <p/> - * To use, create it using {@link #SdkTargetSelector(Composite, IAndroidTarget[], boolean)} then - * call {@link #setSelection(IAndroidTarget)}, {@link #setSelectionListener(SelectionListener)} - * and finally use {@link #getSelected()} to retrieve the - * selection. - */ -public class SdkTargetSelector { - - private IAndroidTarget[] mTargets; - private final boolean mAllowSelection; - private SelectionListener mSelectionListener; - private Table mTable; - private Label mDescription; - private Composite mInnerGroup; - - /** Cache for {@link #getCheckboxWidth()} */ - private static int sCheckboxWidth = -1; - - /** - * 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. - */ - public SdkTargetSelector(Composite parent, IAndroidTarget[] targets) { - this(parent, targets, true /*allowSelection*/); - } - - /** - * 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. - */ - public SdkTargetSelector(Composite parent, IAndroidTarget[] targets, boolean allowSelection) { - // Layout has 1 column - mInnerGroup = new Composite(parent, SWT.NONE); - mInnerGroup.setLayout(new GridLayout()); - mInnerGroup.setLayoutData(new GridData(GridData.FILL_BOTH)); - mInnerGroup.setFont(parent.getFont()); - - mAllowSelection = allowSelection; - int style = SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION; - if (allowSelection) { - style |= SWT.CHECK; - } - mTable = new Table(mInnerGroup, style); - mTable.setHeaderVisible(true); - mTable.setLinesVisible(false); - - GridData data = new GridData(); - data.grabExcessVerticalSpace = true; - data.grabExcessHorizontalSpace = true; - data.horizontalAlignment = GridData.FILL; - data.verticalAlignment = GridData.FILL; - mTable.setLayoutData(data); - - mDescription = new Label(mInnerGroup, SWT.WRAP); - mDescription.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - // create the table columns - final TableColumn column0 = new TableColumn(mTable, SWT.NONE); - column0.setText("Target Name"); - final TableColumn column1 = new TableColumn(mTable, SWT.NONE); - column1.setText("Vendor"); - final TableColumn column2 = new TableColumn(mTable, SWT.NONE); - column2.setText("Platform"); - final TableColumn column3 = new TableColumn(mTable, SWT.NONE); - column3.setText("API Level"); - - adjustColumnsWidth(mTable, column0, column1, column2, column3); - setupSelectionListener(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. - * <p/> - * This is not a copy. Callers must <em>not</em> modify this array. - */ - public IAndroidTarget[] getTargets() { - 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; - if (mTargets != null) { - Arrays.sort(mTargets, new Comparator<IAndroidTarget>() { - @Override - public int compare(IAndroidTarget o1, IAndroidTarget o2) { - return o1.compareTo(o2); - } - }); - } - - 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 - * events so that the caller can see the updated state. - * <p/> - * The event's item contains a {@link TableItem}. - * The {@link TableItem#getData()} contains an {@link IAndroidTarget}. - * <p/> - * It is recommended that the caller uses the {@link #getSelected()} method instead. - * - * @param selectionListener The new listener or null to remove it. - */ - public void setSelectionListener(SelectionListener selectionListener) { - mSelectionListener = selectionListener; - } - - /** - * Sets the current target selection. - * <p/> - * If the selection is actually changed, this will invoke the selection listener - * (if any) with a null event. - * - * @param target the target to be selection - * @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; - - if (mTable != null && !mTable.isDisposed()) { - for (TableItem i : mTable.getItems()) { - if ((IAndroidTarget) i.getData() == target) { - found = true; - if (!i.getChecked()) { - modified = true; - i.setChecked(true); - } - } else if (i.getChecked()) { - modified = true; - i.setChecked(false); - } - } - } - - if (modified && mSelectionListener != null) { - mSelectionListener.widgetSelected(null); - } - - return found; - } - - /** - * Returns the selected item. - * - * @return The selected item or null. - */ - public IAndroidTarget getSelected() { - if (mTable == null || mTable.isDisposed()) { - return null; - } - - for (TableItem i : mTable.getItems()) { - if (i.getChecked()) { - return (IAndroidTarget) i.getData(); - } - } - return null; - } - - /** - * Adds a listener to adjust the columns width when the parent is resized. - * <p/> - * If we need something more fancy, we might want to use this: - * http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet77.java?view=co - */ - private void adjustColumnsWidth(final Table table, - final TableColumn column0, - final TableColumn column1, - final TableColumn column2, - final TableColumn column3) { - // Add a listener to resize the column to the full width of the table - table.addControlListener(new ControlAdapter() { - @Override - public void controlResized(ControlEvent e) { - Rectangle r = table.getClientArea(); - int width = r.width; - - // On the Mac, the width of the checkbox column is not included (and checkboxes - // are shown if mAllowSelection=true). Subtract this size from the available - // width to be distributed among the columns. - if (mAllowSelection - && SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_DARWIN) { - width -= getCheckboxWidth(); - } - - column0.setWidth(width * 30 / 100); // 30% - column1.setWidth(width * 45 / 100); // 45% - column2.setWidth(width * 15 / 100); // 15% - column3.setWidth(width * 10 / 100); // 10% - } - }); - } - - - /** - * Creates a selection listener that will check or uncheck the whole line when - * 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 */ - @Override - public void widgetDefaultSelected(SelectionEvent e) { - if (e.item instanceof TableItem) { - TableItem i = (TableItem) e.item; - i.setChecked(!i.getChecked()); - enforceSingleSelection(i); - updateDescription(i); - } - - if (mSelectionListener != null) { - mSelectionListener.widgetDefaultSelected(e); - } - } - - @Override - public void widgetSelected(SelectionEvent e) { - if (e.item instanceof TableItem) { - TableItem i = (TableItem) e.item; - enforceSingleSelection(i); - updateDescription(i); - } - - if (mSelectionListener != null) { - mSelectionListener.widgetSelected(e); - } - } - - /** - * If we're not in multiple selection mode, uncheck all other - * items when this one is selected. - */ - private void enforceSingleSelection(TableItem item) { - if (item.getChecked()) { - Table parentTable = item.getParent(); - for (TableItem i2 : parentTable.getItems()) { - if (i2 != item && i2.getChecked()) { - i2.setChecked(false); - } - } - } - } - }); - } - - - /** - * Fills the table with all SDK targets. - * The table columns are: - * <ul> - * <li>column 0: sdk name - * <li>column 1: sdk vendor - * <li>column 2: sdk api name - * <li>column 3: sdk version - * </ul> - */ - private void fillTable(final Table table) { - - if (table == null || table.isDisposed()) { - return; - } - - table.removeAll(); - - if (mTargets != null && mTargets.length > 0) { - table.setEnabled(true); - for (IAndroidTarget target : mTargets) { - TableItem item = new TableItem(table, SWT.NONE); - item.setData(target); - item.setText(0, target.getName()); - item.setText(1, target.getVendor()); - item.setText(2, target.getVersionName()); - item.setText(3, target.getVersion().getApiString()); - } - } else { - table.setEnabled(false); - TableItem item = new TableItem(table, SWT.NONE); - item.setData(null); - item.setText(0, "--"); - item.setText(1, "No target available"); - item.setText(2, "--"); - 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) { - - if (table == null || table.isDisposed()) { - return; - } - - /* - * 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() { - @Override - 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 description of the item's android target, if any. - */ - private void updateDescription(TableItem item) { - if (item != null) { - Object data = item.getData(); - if (data instanceof IAndroidTarget) { - String newTooltip = ((IAndroidTarget) data).getDescription(); - mDescription.setText(newTooltip == null ? "" : newTooltip); //$NON-NLS-1$ - } - } - } - - /** Enables or disables the controls. */ - public void setEnabled(boolean enabled) { - if (mInnerGroup != null && mTable != null && !mTable.isDisposed()) { - enableControl(mInnerGroup, enabled); - } - } - - /** Enables or disables controls; recursive for composite controls. */ - private void enableControl(Control c, boolean enabled) { - c.setEnabled(enabled); - if (c instanceof Composite) - for (Control c2 : ((Composite) c).getChildren()) { - enableControl(c2, enabled); - } - } - - /** Computes the width of a checkbox */ - private int getCheckboxWidth() { - if (sCheckboxWidth == -1) { - Shell shell = new Shell(mTable.getShell(), SWT.NO_TRIM); - Button checkBox = new Button(shell, SWT.CHECK); - sCheckboxWidth = checkBox.computeSize(SWT.DEFAULT, SWT.DEFAULT).x; - shell.dispose(); - } - - return sCheckboxWidth; - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/ToggleButton.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/ToggleButton.java deleted file mode 100755 index 7c66bcf..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/ToggleButton.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2011 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 org.eclipse.swt.SWT; -import org.eclipse.swt.custom.CLabel; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.MouseListener; -import org.eclipse.swt.events.MouseTrackListener; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Event; - -/** - * A label that can display 2 images depending on its internal state. - * This acts as a button by firing the {@link SWT#Selection} listener. - */ -public class ToggleButton extends CLabel { - private Image[] mImage = new Image[2]; - private String[] mTooltip = new String[2]; - private boolean mMouseIn; - private int mState = 0; - - - public ToggleButton( - Composite parent, - int style, - Image image1, - Image image2, - String tooltip1, - String tooltip2) { - super(parent, style); - mImage[0] = image1; - mImage[1] = image2; - mTooltip[0] = tooltip1; - mTooltip[1] = tooltip2; - updateImageAndTooltip(); - - addMouseListener(new MouseListener() { - @Override - public void mouseDown(MouseEvent e) { - // pass - } - - @Override - public void mouseUp(MouseEvent e) { - // We select on mouse-up, as it should be properly done since this is the - // only way a user can cancel a button click by moving out of the button. - if (mMouseIn && e.button == 1) { - notifyListeners(SWT.Selection, new Event()); - } - } - - @Override - public void mouseDoubleClick(MouseEvent e) { - if (mMouseIn && e.button == 1) { - notifyListeners(SWT.DefaultSelection, new Event()); - } - } - }); - - addMouseTrackListener(new MouseTrackListener() { - @Override - public void mouseExit(MouseEvent e) { - if (mMouseIn) { - mMouseIn = false; - redraw(); - } - } - - @Override - public void mouseEnter(MouseEvent e) { - if (!mMouseIn) { - mMouseIn = true; - redraw(); - } - } - - @Override - public void mouseHover(MouseEvent e) { - // pass - } - }); - } - - @Override - public int getStyle() { - int style = super.getStyle(); - if (mMouseIn) { - style |= SWT.SHADOW_IN; - } - return style; - } - - /** - * Sets current state. - * @param state A value 0 or 1. - */ - public void setState(int state) { - assert state == 0 || state == 1; - mState = state; - updateImageAndTooltip(); - redraw(); - } - - /** - * Returns the current state - * @return Returns the current state, either 0 or 1. - */ - public int getState() { - return mState; - } - - protected void updateImageAndTooltip() { - setImage(mImage[getState()]); - setToolTipText(mTooltip[getState()]); - } -} - diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/AvdManagerWindow.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/AvdManagerWindow.java deleted file mode 100755 index dd34bef..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/AvdManagerWindow.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2011 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.repository; - -import com.android.sdkuilib.internal.repository.ui.AvdManagerWindowImpl1; -import com.android.sdkuilib.internal.widgets.AvdSelector; -import com.android.utils.ILogger; - -import org.eclipse.swt.widgets.Shell; - -/** - * Opens an AVD Manager Window. - * - * This is the public entry point for using the window. - */ -public class AvdManagerWindow { - - /** The actual window implementation to which this class delegates. */ - private AvdManagerWindowImpl1 mWindow; - - /** - * Enum giving some indication of what is invoking this window. - * The behavior and UI will change slightly depending on the context. - * <p/> - * Note: if you add Android support to your specific IDE, you might want - * to specialize this context enum. - */ - public enum AvdInvocationContext { - /** - * The AVD Manager is invoked from the stand-alone 'android' tool. - * In this mode, we present an about box, a settings page. - * For SdkMan2, we also have a menu bar and link to the SDK Manager 2. - */ - STANDALONE, - - /** - * The AVD Manager is embedded as a dialog in the SDK Manager - * or in the {@link AvdSelector}. - * This is similar to the {@link #STANDALONE} mode except we don't need - * to display a menu bar at all since we don't want a menu item linking - * back to the SDK Manager and we don't need to redisplay the options - * and about which are already on the root window. - */ - DIALOG, - - /** - * The AVD Manager is invoked from an IDE. - * In this mode, we do not modify the menu bar. - * There is no about box and no settings. - */ - IDE, - } - - - /** - * Creates a new window. Caller must call open(), which will block. - * - * @param parentShell Parent shell. - * @param sdkLog Logger. Cannot be null. - * @param osSdkRoot The OS path to the SDK root. - * @param context The {@link AvdInvocationContext} to change the behavior depending on who's - * opening the SDK Manager. - */ - public AvdManagerWindow( - Shell parentShell, - ILogger sdkLog, - String osSdkRoot, - AvdInvocationContext context) { - mWindow = new AvdManagerWindowImpl1( - parentShell, - sdkLog, - osSdkRoot, - context); - } - - /** - * Opens the window. - */ - public void open() { - mWindow.open(); - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ISdkChangeListener.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ISdkChangeListener.java deleted file mode 100755 index e221f98..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ISdkChangeListener.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2010 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.repository; - - -/** - * Interface for listeners on SDK modifications by the SDK Manager UI. - * This notifies when the SDK manager is first loading the SDK or before/after it installed - * a package. - */ -public interface ISdkChangeListener { - /** - * Invoked when the content of the SDK is being loaded by the SDK Manager UI - * for the first time. - * This is generally followed by a call to {@link #onSdkReload()} - * or by a call to {@link #preInstallHook()}. - */ - void onSdkLoaded(); - - /** - * Invoked when the SDK Manager UI is about to start installing packages. - * This will be followed by a call to {@link #postInstallHook()}. - */ - void preInstallHook(); - - /** - * Invoked when the SDK Manager UI is done installing packages. - * Some new packages might have been installed or the user might have cancelled the operation. - * This is generally followed by a call to {@link #onSdkReload()}. - */ - void postInstallHook(); - - /** - * Invoked when the content of the SDK is being reloaded by the SDK Manager UI, - * typically after a package was installed. The SDK content might or might not - * have changed. - */ - void onSdkReload(); -} - diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/SdkUpdaterWindow.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/SdkUpdaterWindow.java deleted file mode 100755 index 6010e48..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/SdkUpdaterWindow.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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.repository; - -import com.android.sdkuilib.internal.repository.ISdkUpdaterWindow; -import com.android.sdkuilib.internal.repository.ui.SdkUpdaterWindowImpl2; -import com.android.utils.ILogger; - -import org.eclipse.swt.widgets.Shell; - -/** - * Opens an SDK Manager Window. - * - * This is the public entry point for using the window. - */ -public class SdkUpdaterWindow { - - /** The actual window implementation to which this class delegates. */ - private ISdkUpdaterWindow mWindow; - - /** - * Enum giving some indication of what is invoking this window. - * The behavior and UI will change slightly depending on the context. - * <p/> - * Note: if you add Android support to your specific IDE, you might want - * to specialize this context enum. - */ - public enum SdkInvocationContext { - /** - * The SDK Manager is invoked from the stand-alone 'android' tool. - * In this mode, we present an about box, a settings page. - * For SdkMan2, we also have a menu bar and link to the AVD manager. - */ - STANDALONE, - - /** - * The SDK Manager is invoked from the standalone AVD Manager. - * This is similar to the standalone mode except that in this case we - * don't display a menu item linking to the AVD Manager. - */ - AVD_MANAGER, - - /** - * The SDK Manager is invoked from an IDE. - * In this mode, we do not modify the menu bar. There is no about box - * and no settings (e.g. HTTP proxy settings are inherited from Eclipse.) - */ - IDE, - - /** - * The SDK Manager is invoked from the AVD Selector. - * For SdkMan1, this means the AVD page will be displayed first. - * For SdkMan2, we won't be using this. - */ - AVD_SELECTOR - } - - /** - * Creates a new window. Caller must call open(), which will block. - * - * @param parentShell Parent shell. - * @param sdkLog Logger. Cannot be null. - * @param osSdkRoot The OS path to the SDK root. - * @param context The {@link SdkInvocationContext} to change the behavior depending on who's - * opening the SDK Manager. - */ - public SdkUpdaterWindow( - Shell parentShell, - ILogger sdkLog, - String osSdkRoot, - SdkInvocationContext context) { - - mWindow = new SdkUpdaterWindowImpl2(parentShell, sdkLog, osSdkRoot, context); - } - - /** - * Adds a new listener to be notified when a change is made to the content of the SDK. - * This should be called before {@link #open()}. - */ - public void addListener(ISdkChangeListener listener) { - mWindow.addListener(listener); - } - - /** - * Removes a new listener to be notified anymore when a change is made to the content of - * the SDK. - */ - public void removeListener(ISdkChangeListener listener) { - mWindow.removeListener(listener); - } - - /** - * Opens the window. - */ - public void open() { - mWindow.open(); - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/ui/AuthenticationDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/ui/AuthenticationDialog.java deleted file mode 100644 index 07e65b7..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/ui/AuthenticationDialog.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2011 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.ui; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; - -/** - * Dialog which collects from the user his/her login and password. - */ -public class AuthenticationDialog extends GridDialog { - private Text mTxtLogin; - private Text mTxtPassword; - private Text mTxtWorkstation; - private Text mTxtDomain; - - private String mTitle; - private String mMessage; - - private static String sLogin = ""; - private static String sPassword = ""; - private static String sWorkstation = ""; - private static String sDomain = ""; - - /** - * Constructor which retrieves the parent {@link Shell} and the message to - * be displayed in this dialog. - * - * @param parentShell Parent Shell - * @param title Title of the window. - * @param message Message the be displayed in this dialog. - */ - public AuthenticationDialog(Shell parentShell, String title, String message) { - super(parentShell, 1, false); - // assign fields - mTitle = title; - mMessage = message; - } - - @Override - public void createDialogContent(Composite parent) { - // Configure Dialog - getShell().setText(mTitle); - GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); - parent.setLayoutData(data); - - // Upper Composite - Composite upperComposite = new Composite(parent, SWT.NONE); - GridLayout layout = new GridLayout(2, false); - layout.verticalSpacing = 10; - upperComposite.setLayout(layout); - data = new GridData(SWT.FILL, SWT.CENTER, true, true); - upperComposite.setLayoutData(data); - - // add message label - Label lblMessage = new Label(upperComposite, SWT.WRAP); - lblMessage.setText(mMessage); - data = new GridData(SWT.FILL, SWT.CENTER, true, true, 2, 1); - data.widthHint = 500; - lblMessage.setLayoutData(data); - - // add user name label and text field - Label lblUserName = new Label(upperComposite, SWT.NONE); - lblUserName.setText("Login:"); - data = new GridData(SWT.LEFT, SWT.CENTER, false, false); - lblUserName.setLayoutData(data); - - mTxtLogin = new Text(upperComposite, SWT.SINGLE | SWT.BORDER); - data = new GridData(SWT.FILL, SWT.CENTER, true, false); - mTxtLogin.setLayoutData(data); - mTxtLogin.setFocus(); - mTxtLogin.setText(sLogin); - mTxtLogin.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent arg0) { - sLogin = mTxtLogin.getText().trim(); - } - }); - - // add password label and text field - Label lblPassword = new Label(upperComposite, SWT.NONE); - lblPassword.setText("Password:"); - data = new GridData(SWT.LEFT, SWT.CENTER, false, false); - lblPassword.setLayoutData(data); - - mTxtPassword = new Text(upperComposite, SWT.SINGLE | SWT.PASSWORD | SWT.BORDER); - data = new GridData(SWT.FILL, SWT.CENTER, true, false); - mTxtPassword.setLayoutData(data); - mTxtPassword.setText(sPassword); - mTxtPassword.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent arg0) { - sPassword = mTxtPassword.getText(); - } - }); - - // add a label indicating that the following two fields are optional - Label lblInfo = new Label(upperComposite, SWT.NONE); - lblInfo.setText("Provide the following info if your proxy uses NTLM authentication. Leave blank otherwise."); - data = new GridData(); - data.horizontalSpan = 2; - lblInfo.setLayoutData(data); - - // add workstation label and text field - Label lblWorkstation = new Label(upperComposite, SWT.NONE); - lblWorkstation.setText("Workstation:"); - data = new GridData(SWT.LEFT, SWT.CENTER, false, false); - lblWorkstation.setLayoutData(data); - - mTxtWorkstation = new Text(upperComposite, SWT.SINGLE | SWT.BORDER); - data = new GridData(SWT.FILL, SWT.CENTER, true, false); - mTxtWorkstation.setLayoutData(data); - mTxtWorkstation.setText(sWorkstation); - mTxtWorkstation.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent arg0) { - sWorkstation = mTxtWorkstation.getText().trim(); - } - }); - - // add domain label and text field - Label lblDomain = new Label(upperComposite, SWT.NONE); - lblDomain.setText("Domain:"); - data = new GridData(SWT.LEFT, SWT.CENTER, false, false); - lblDomain.setLayoutData(data); - - mTxtDomain = new Text(upperComposite, SWT.SINGLE | SWT.BORDER); - data = new GridData(SWT.FILL, SWT.CENTER, true, false); - mTxtDomain.setLayoutData(data); - mTxtDomain.setText(sDomain); - mTxtDomain.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent arg0) { - sDomain = mTxtDomain.getText().trim(); - } - }); - } - - /** - * Retrieves the Login field information - * - * @return Login field value or empty String. Return value is never null - */ - public String getLogin() { - return sLogin; - } - - /** - * Retrieves the Password field information - * - * @return Password field value or empty String. Return value is never null - */ - public String getPassword() { - return sPassword; - } - - /** - * Retrieves the workstation field information - * - * @return Workstation field value or empty String. Return value is never null - */ - public String getWorkstation() { - return sWorkstation; - } - - /** - * Retrieves the domain field information - * - * @return Domain field value or empty String. Return value is never null - */ - public String getDomain() { - return sDomain; - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/ui/GridDataBuilder.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/ui/GridDataBuilder.java deleted file mode 100755 index 381dea0..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/ui/GridDataBuilder.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2010 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.ui; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Control; - -/** - * A little helper to create a new {@link GridData} and set its properties. - * <p/> - * Example of usage: <br/> - * <code> - * GridDataHelper.create(myControl).hSpan(2).hAlignCenter().fill(); - * </code> - */ -public final class GridDataBuilder { - - private GridData mGD; - - private GridDataBuilder() { - mGD = new GridData(); - } - - /** - * Creates new {@link GridData} and associates it on the <code>control</code> composite. - */ - static public GridDataBuilder create(Control control) { - GridDataBuilder gdh = new GridDataBuilder(); - control.setLayoutData(gdh.mGD); - return gdh; - } - - /** Sets <code>widthHint</code> to <code>w</code>. */ - public GridDataBuilder wHint(int w) { - mGD.widthHint = w; - return this; - } - - /** Sets <code>heightHint</code> to <code>h</code>. */ - public GridDataBuilder hHint(int h) { - mGD.heightHint = h; - return this; - } - - /** Sets <code>horizontalIndent</code> to <code>h</code>. */ - public GridDataBuilder hIndent(int h) { - mGD.horizontalIndent = h; - return this; - } - - /** Sets <code>horizontalSpan</code> to <code>h</code>. */ - public GridDataBuilder hSpan(int h) { - mGD.horizontalSpan = h; - return this; - } - - /** Sets <code>verticalSpan</code> to <code>v</code>. */ - public GridDataBuilder vSpan(int v) { - mGD.verticalSpan = v; - return this; - } - - /** Sets <code>horizontalAlignment</code> to {@link SWT#CENTER}. */ - public GridDataBuilder hCenter() { - mGD.horizontalAlignment = SWT.CENTER; - return this; - } - - /** Sets <code>verticalAlignment</code> to {@link SWT#CENTER}. */ - public GridDataBuilder vCenter() { - mGD.verticalAlignment = SWT.CENTER; - return this; - } - - /** Sets <code>verticalAlignment</code> to {@link SWT#TOP}. */ - public GridDataBuilder vTop() { - mGD.verticalAlignment = SWT.TOP; - return this; - } - - /** Sets <code>verticalAlignment</code> to {@link SWT#BOTTOM}. */ - public GridDataBuilder vBottom() { - mGD.verticalAlignment = SWT.BOTTOM; - return this; - } - - /** Sets <code>horizontalAlignment</code> to {@link SWT#LEFT}. */ - public GridDataBuilder hLeft() { - mGD.horizontalAlignment = SWT.LEFT; - return this; - } - - /** Sets <code>horizontalAlignment</code> to {@link SWT#RIGHT}. */ - public GridDataBuilder hRight() { - mGD.horizontalAlignment = SWT.RIGHT; - return this; - } - - /** Sets <code>horizontalAlignment</code> to {@link GridData#FILL}. */ - public GridDataBuilder hFill() { - mGD.horizontalAlignment = GridData.FILL; - return this; - } - - /** Sets <code>verticalAlignment</code> to {@link GridData#FILL}. */ - public GridDataBuilder vFill() { - mGD.verticalAlignment = GridData.FILL; - return this; - } - - /** - * Sets both <code>horizontalAlignment</code> and <code>verticalAlignment</code> - * to {@link GridData#FILL}. - */ - public GridDataBuilder fill() { - mGD.horizontalAlignment = GridData.FILL; - mGD.verticalAlignment = GridData.FILL; - return this; - } - - /** Sets <code>grabExcessHorizontalSpace</code> to true. */ - public GridDataBuilder hGrab() { - mGD.grabExcessHorizontalSpace = true; - return this; - } - - /** Sets <code>grabExcessVerticalSpace</code> to true. */ - public GridDataBuilder vGrab() { - mGD.grabExcessVerticalSpace = true; - return this; - } - - /** - * Sets both <code>grabExcessHorizontalSpace</code> and - * <code>grabExcessVerticalSpace</code> to true. - */ - public GridDataBuilder grab() { - mGD.grabExcessHorizontalSpace = true; - mGD.grabExcessVerticalSpace = true; - return this; - } - -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/ui/GridDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/ui/GridDialog.java deleted file mode 100644 index 9bf9c29..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/ui/GridDialog.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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.ui; - -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Shell; - -/** - * JFace-based dialog that properly sets up a {@link GridLayout} top composite with the proper - * margin. - * <p/> - * Implementing dialog must create the content of the dialog in - * {@link #createDialogContent(Composite)}. - * <p/> - * A JFace dialog is perfect if you want a typical "OK | cancel" workflow, with the OK and - * cancel things all handled for you using a predefined layout. If you want a different set - * of buttons or a different layout, consider {@link SwtBaseDialog} instead. - */ -public abstract class GridDialog extends Dialog { - - private final int mNumColumns; - private final boolean mMakeColumnsEqualWidth; - - /** - * Creates the dialog - * @param parentShell the parent {@link Shell}. - * @param numColumns the number of columns in the grid - * @param makeColumnsEqualWidth whether or not the columns will have equal width - */ - public GridDialog(Shell parentShell, int numColumns, boolean makeColumnsEqualWidth) { - super(parentShell); - mNumColumns = numColumns; - mMakeColumnsEqualWidth = makeColumnsEqualWidth; - } - - /** - * Creates the content of the dialog. The <var>parent</var> composite is a {@link GridLayout} - * created with the <var>numColumn</var> and <var>makeColumnsEqualWidth</var> parameters - * passed to {@link #GridDialog(Shell, int, boolean)}. - * @param parent the parent composite. - */ - public abstract void createDialogContent(Composite parent); - - @Override - protected Control createDialogArea(Composite parent) { - Composite top = new Composite(parent, SWT.NONE); - GridLayout layout = new GridLayout(mNumColumns, mMakeColumnsEqualWidth); - 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)); - - createDialogContent(top); - - applyDialogFont(top); - return top; - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/ui/GridLayoutBuilder.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/ui/GridLayoutBuilder.java deleted file mode 100755 index 7e8c161..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/ui/GridLayoutBuilder.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2010 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.ui; - -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; - -/** - * A little helper to create a new {@link GridLayout}, associate to a {@link Composite} - * and set its common attributes. - * <p/> - * Example of usage: <br/> - * <code> - * GridLayoutHelper.create(myComposite).noMargins().vSpacing(0).columns(2); - * </code> - */ -public final class GridLayoutBuilder { - - private GridLayout mGL; - - private GridLayoutBuilder() { - mGL = new GridLayout(); - } - - /** - * Creates new {@link GridLayout} and associates it on the <code>parent</code> composite. - */ - static public GridLayoutBuilder create(Composite parent) { - GridLayoutBuilder glh = new GridLayoutBuilder(); - parent.setLayout(glh.mGL); - return glh; - } - - /** Sets all margins to 0. */ - public GridLayoutBuilder noMargins() { - mGL.marginHeight = 0; - mGL.marginWidth = 0; - mGL.marginLeft = 0; - mGL.marginTop = 0; - mGL.marginRight = 0; - mGL.marginBottom = 0; - return this; - } - - /** Sets all margins to <code>n</code>. */ - public GridLayoutBuilder margins(int n) { - mGL.marginHeight = n; - mGL.marginWidth = n; - mGL.marginLeft = n; - mGL.marginTop = n; - mGL.marginRight = n; - mGL.marginBottom = n; - return this; - } - - /** Sets <code>numColumns</code> to <code>n</code>. */ - public GridLayoutBuilder columns(int n) { - mGL.numColumns = n; - return this; - } - - /** Sets <code>makeColumnsEqualWidth</code> to true. */ - public GridLayoutBuilder columnsEqual() { - mGL.makeColumnsEqualWidth = true; - return this; - } - - /** Sets <code>verticalSpacing</code> to <code>v</code>. */ - public GridLayoutBuilder vSpacing(int v) { - mGL.verticalSpacing = v; - return this; - } - - /** Sets <code>horizontalSpacing</code> to <code>h</code>. */ - public GridLayoutBuilder hSpacing(int h) { - mGL.horizontalSpacing = h; - return this; - } - - /** - * Sets <code>horizontalSpacing</code> and <code>verticalSpacing</code> - * to <code>s</code>. - */ - public GridLayoutBuilder spacing(int s) { - mGL.verticalSpacing = s; - mGL.horizontalSpacing = s; - return this; - } -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/ui/SwtBaseDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/ui/SwtBaseDialog.java deleted file mode 100755 index bb0210b..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/ui/SwtBaseDialog.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (C) 2011 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.ui; - -import com.android.SdkConstants; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Dialog; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; - -import java.util.HashMap; -import java.util.Map; - -/** - * A base class for an SWT Dialog. - * <p/> - * The base class offers the following goodies: <br/> - * - Dialog is automatically centered on its parent. <br/> - * - Dialog size is reused during the session. <br/> - * - A simple API with an {@link #open()} method that returns a boolean. <br/> - * <p/> - * A typical usage is: - * <pre> - * MyDialog extends SwtBaseDialog { ... } - * MyDialog d = new MyDialog(parentShell, "My Dialog Title"); - * if (d.open()) { - * ...do something like refresh parent list view - * } - * </pre> - * We also have a JFace-base {@link GridDialog}. - * The JFace dialog is good when you just want a typical OK/Cancel layout with the - * buttons all managed for you. - * This SWT base dialog has little decoration. - * It's up to you to manage whatever buttons you want, if any. - */ -public abstract class SwtBaseDialog extends Dialog { - - /** - * Min Y location for dialog. Need to deal with the menu bar on mac os. - */ - private final static int MIN_Y = - SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_DARWIN ? 20 : 0; - - /** Last dialog size for this session, different for each dialog class. */ - private static Map<Class<?>, Point> sLastSizeMap = new HashMap<Class<?>, Point>(); - - private volatile boolean mQuitRequested = false; - private boolean mReturnValue; - private Shell mShell; - - /** - * Create the dialog. - * - * @param parent The parent's shell - * @param title The dialog title. Can be null. - */ - public SwtBaseDialog(Shell parent, int swtStyle, String title) { - super(parent, swtStyle); - if (title != null) { - setText(title); - } - } - - /** - * Open the dialog. - * - * @return The last value set using {@link #setReturnValue(boolean)} or false by default. - */ - public boolean open() { - if (!mQuitRequested) { - createShell(); - } - if (!mQuitRequested) { - createContents(); - } - if (!mQuitRequested) { - positionShell(); - } - if (!mQuitRequested) { - postCreate(); - } - if (!mQuitRequested) { - mShell.open(); - mShell.layout(); - eventLoop(); - } - - return mReturnValue; - } - - /** - * Creates the shell for this dialog. - * The default shell has a size of 450x300, which is also its minimum size. - * You might want to override these values. - * <p/> - * Called before {@link #createContents()}. - */ - protected void createShell() { - mShell = new Shell(getParent(), SWT.DIALOG_TRIM | SWT.RESIZE | SWT.APPLICATION_MODAL); - mShell.setMinimumSize(new Point(450, 300)); - mShell.setSize(450, 300); - if (getText() != null) { - mShell.setText(getText()); - } - mShell.addDisposeListener(new DisposeListener() { - @Override - public void widgetDisposed(DisposeEvent e) { - saveSize(); - } - }); - } - - /** - * Creates the content and attaches it to the current shell (cf. {@link #getShell()}). - * <p/> - * Derived classes should consider creating the UI here and initializing their - * state in {@link #postCreate()}. - */ - protected abstract void createContents(); - - /** - * Called after {@link #createContents()} and after {@link #positionShell()} - * just before the dialog is actually shown on screen. - * <p/> - * Derived classes should consider creating the UI in {@link #createContents()} and - * initialize it here. - */ - protected abstract void postCreate(); - - /** - * Run the event loop. - * This is called from {@link #open()} after {@link #postCreate()} and - * after the window has been shown on screen. - * Derived classes might want to use this as a place to start automated - * tasks that will update the UI. - */ - protected void eventLoop() { - Display display = getParent().getDisplay(); - while (!mQuitRequested && !mShell.isDisposed()) { - if (!display.readAndDispatch()) { - display.sleep(); - } - } - } - - /** - * Returns the current value that {@link #open()} will return to the caller. - * Default is false. - */ - protected boolean getReturnValue() { - return mReturnValue; - } - - /** - * Sets the value that {@link #open()} will return to the caller. - * @param returnValue The new value to be returned by {@link #open()}. - */ - protected void setReturnValue(boolean returnValue) { - mReturnValue = returnValue; - } - - /** - * Returns the shell created by {@link #createShell()}. - * @return The current {@link Shell}. - */ - protected Shell getShell() { - return mShell; - } - - /** - * Saves the dialog size and close the dialog. - * The {@link #open()} method will given return value (see {@link #setReturnValue(boolean)}. - * <p/> - * It's safe to call this method before the shell is initialized, - * in which case the dialog will close as soon as possible. - */ - protected void close() { - if (mShell != null && !mShell.isDisposed()) { - saveSize(); - getShell().close(); - } - mQuitRequested = true; - } - - //------- - - /** - * Centers the dialog in its parent shell. - */ - private void positionShell() { - // Centers the dialog in its parent shell - Shell child = mShell; - Shell parent = getParent(); - if (child != null && parent != null) { - // get the parent client area with a location relative to the display - Rectangle parentArea = parent.getClientArea(); - Point parentLoc = parent.getLocation(); - int px = parentLoc.x; - int py = parentLoc.y; - int pw = parentArea.width; - int ph = parentArea.height; - - // Reuse the last size if there's one, otherwise use the default - Point childSize = sLastSizeMap.get(this.getClass()); - if (childSize == null) { - childSize = child.getSize(); - } - int cw = childSize.x; - int ch = childSize.y; - - int x = px + (pw - cw) / 2; - if (x < 0) x = 0; - - int y = py + (ph - ch) / 2; - if (y < MIN_Y) y = MIN_Y; - - child.setLocation(x, y); - child.setSize(cw, ch); - } - } - - private void saveSize() { - if (mShell != null && !mShell.isDisposed()) { - sLastSizeMap.put(this.getClass(), mShell.getSize()); - } - } - -} diff --git a/sdkmanager/libs/sdkuilib/tests/Android.mk b/sdkmanager/libs/sdkuilib/tests/Android.mk deleted file mode 100644 index a7ba9a7..0000000 --- a/sdkmanager/libs/sdkuilib/tests/Android.mk +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (C) 2011 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. - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -# Only compile source java files in this lib. -LOCAL_SRC_FILES := $(call all-subdir-java-files) - -LOCAL_MODULE := sdkuilib-tests -LOCAL_MODULE_TAGS := optional - -LOCAL_JAVA_LIBRARIES := \ - sdklib \ - sdklib-tests \ - sdkuilib \ - junit \ - swt \ - -include $(BUILD_HOST_JAVA_LIBRARY) diff --git a/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/MockDownloadCache.java b/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/MockDownloadCache.java deleted file mode 100755 index 04f2b04..0000000 --- a/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/MockDownloadCache.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (C) 2012 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.repository; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.sdklib.internal.repository.CanceledByUserException; -import com.android.sdklib.internal.repository.DownloadCache; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.utils.Pair; - -import org.apache.http.Header; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.ProtocolVersion; -import org.apache.http.message.BasicHttpResponse; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.TreeMap; - -/** A mock UpdaterData that simply records what would have been installed. */ -public class MockDownloadCache extends DownloadCache { - - private final File mCacheRoot; - - /** Map url => payload bytes, http code response. - * If the payload pair is null, an exception such as FNF is thrown. */ - private final Map<String, Payload> mDirectPayloads = new HashMap<String, Payload>(); - /** Map url => payload bytes, http code response. - * If the payload pair is null, an exception such as FNF is thrown. */ - private final Map<String, Payload> mCachedPayloads = new HashMap<String, Payload>(); - - private final Map<String, Integer> mDirectHits = new TreeMap<String, Integer>(); - private final Map<String, Integer> mCachedHits = new TreeMap<String, Integer>(); - - private Strategy mOverrideStrategy; - - public final static int THROW_FNF = -1; - - /** - * Creates a download cache with a {@code DIRECT} strategy and - * no root {@code $HOME/.android} folder, which effectively disables the cache. - */ - public MockDownloadCache() { - super(DownloadCache.Strategy.DIRECT); - mCacheRoot = null; - } - - /** - * Creates a download with the given strategy and the given cache root. - */ - public MockDownloadCache(DownloadCache.Strategy strategy, File cacheRoot) { - super(strategy); - mCacheRoot = cacheRoot; - } - - @Override - protected File initCacheRoot() { - return mCacheRoot; - } - - /** - * Override the {@link DownloadCache.Strategy} of the cache. - * This lets us set it temporarily to {@link DownloadCache.Strategy#ONLY_CACHE}, - * which will force {@link #openCachedUrl(String, ITaskMonitor)} to throw an FNF, - * essentially simulating an empty cache at first. - * <p/> - * Setting it back to null reverts the behavior to its default. - */ - public void overrideStrategy(DownloadCache.Strategy strategy) { - mOverrideStrategy = strategy; - } - - /** - * Register a direct payload response. - * - * @param url The URL to match. - * @param httpCode The expected response code. - * Use {@link #THROW_FNF} to mean an FNF should be thrown (which is what the - * httpClient stack seems to return instead of {@link HttpStatus#SC_NOT_FOUND}.) - * @param content The payload to return. - * As a shortcut a null will be replaced by an empty byte array. - */ - public void registerDirectPayload(String url, int httpCode, byte[] content) { - mDirectPayloads.put(url, new Payload(httpCode, content)); - } - - /** - * Register a cached payload response. - * - * @param url The URL to match. - * @param content The payload to return or null to throw a FNF. - */ - public void registerCachedPayload(String url, byte[] content) { - mCachedPayloads.put(url, - new Payload(content == null ? THROW_FNF : HttpStatus.SC_OK, content)); - } - - public String[] getDirectHits() { - ArrayList<String> list = new ArrayList<String>(); - synchronized (mDirectHits) { - for (Entry<String, Integer> entry : mDirectHits.entrySet()) { - list.add(String.format("<%1$s : %2$d>", - entry.getKey(), entry.getValue().intValue())); - } - } - return list.toArray(new String[list.size()]); - } - - public String[] getCachedHits() { - ArrayList<String> list = new ArrayList<String>(); - synchronized (mCachedHits) { - for (Entry<String, Integer> entry : mCachedHits.entrySet()) { - list.add(String.format("<%1$s : %2$d>", - entry.getKey(), entry.getValue().intValue())); - } - } - return list.toArray(new String[list.size()]); - } - - public void clearDirectHits() { - synchronized (mDirectHits) { - mDirectHits.clear(); - } - } - - public void clearCachedHits() { - synchronized (mCachedHits) { - mCachedHits.clear(); - } - } - - /** - * Override openDirectUrl to return one of the registered payloads or throw a FNF exception. - * This totally ignores the cache's {@link DownloadCache.Strategy}. - */ - @Override - public Pair<InputStream, HttpResponse> openDirectUrl( - @NonNull String urlString, - @Nullable Header[] headers, - @NonNull ITaskMonitor monitor) throws IOException, CanceledByUserException { - - synchronized (mDirectHits) { - Integer count = mDirectHits.get(urlString); - mDirectHits.put(urlString, (count == null ? 0 : count.intValue()) + 1); - } - - Payload payload = mDirectPayloads.get(urlString); - - if (payload == null || payload.mHttpCode == THROW_FNF) { - throw new FileNotFoundException(urlString); - } - - byte[] content = payload.mContent; - if (content == null) { - content = new byte[0]; - } - - InputStream is = new ByteArrayInputStream(content); - HttpResponse hr = new BasicHttpResponse( - new ProtocolVersion("HTTP", 1, 1), - payload.mHttpCode, - "Http-Code-" + payload.mHttpCode); - - return Pair.of(is, hr); - } - - /** - * Override openCachedUrl to return one of the registered payloads or throw a FNF exception. - * This totally ignores the cache's {@link DownloadCache.Strategy}. - * It will however throw a FNF if {@link #overrideStrategy(Strategy)} is set to - * {@link DownloadCache.Strategy#ONLY_CACHE}. - */ - @Override - public InputStream openCachedUrl(String urlString, ITaskMonitor monitor) - throws IOException, CanceledByUserException { - - synchronized (mCachedHits) { - Integer count = mCachedHits.get(urlString); - mCachedHits.put(urlString, (count == null ? 0 : count.intValue()) + 1); - } - - if (Strategy.ONLY_CACHE.equals(mOverrideStrategy)) { - // Override the cache to read only "local cached" data. - // In this first phase, we assume there's nothing cached. - // TODO register first-pass files later. - throw new FileNotFoundException(urlString); - } - - Payload payload = mCachedPayloads.get(urlString); - - if (payload == null || payload.mHttpCode != HttpStatus.SC_OK) { - throw new FileNotFoundException(urlString); - } - - byte[] content = payload.mContent; - if (content == null) { - content = new byte[0]; - } - - return new ByteArrayInputStream(content); - } - - private static class Payload { - final byte[] mContent; - final int mHttpCode; - - Payload(int httpCode, byte[] content) { - mHttpCode = httpCode; - mContent = content; - } - } - -} diff --git a/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/MockUpdaterData.java b/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/MockUpdaterData.java deleted file mode 100755 index f19bfcc..0000000 --- a/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/MockUpdaterData.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (C) 2011 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.repository; - -import com.android.sdklib.SdkManager; -import com.android.sdklib.internal.repository.DownloadCache; -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskFactory; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.MockEmptySdkManager; -import com.android.sdklib.internal.repository.NullTaskMonitor; -import com.android.sdklib.internal.repository.archives.ArchiveInstaller; -import com.android.sdklib.internal.repository.archives.ArchiveReplacement; -import com.android.sdklib.internal.repository.sources.SdkSourceCategory; -import com.android.sdklib.internal.repository.sources.SdkSources; -import com.android.sdklib.mock.MockLog; -import com.android.sdkuilib.internal.repository.SettingsController.Settings; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.utils.ILogger; -import com.android.utils.NullLogger; - -import org.eclipse.swt.graphics.Image; - -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -/** A mock UpdaterData that simply records what would have been installed. */ -public class MockUpdaterData extends UpdaterData { - - public final static String SDK_PATH = "/tmp/SDK"; - - private final List<ArchiveReplacement> mInstalled = new ArrayList<ArchiveReplacement>(); - - private DownloadCache mMockDownloadCache = new MockDownloadCache(); - - private final SdkSources mMockSdkSources = new SdkSources() { - @Override - public void loadUserAddons(ILogger log) { - // This source does not load user addons. - removeAll(SdkSourceCategory.USER_ADDONS); - }; - }; - - /** Creates a {@link MockUpdaterData} using a {@link MockEmptySdkManager}. */ - public MockUpdaterData() { - super(SDK_PATH, new MockLog()); - - setTaskFactory(new MockTaskFactory()); - setImageFactory(new NullImageFactory()); - } - - /** Creates a {@link MockUpdaterData} using the given {@link SdkManager}. */ - public MockUpdaterData(SdkManager sdkManager) { - super(sdkManager.getLocation(), new MockLog()); - setSdkManager(sdkManager); - setTaskFactory(new MockTaskFactory()); - setImageFactory(new NullImageFactory()); - } - - /** Gives access to the internal {@link #installArchives(List, int)}. */ - public void _installArchives(List<ArchiveInfo> result) { - installArchives(result, 0/*flags*/); - } - - public ArchiveReplacement[] getInstalled() { - return mInstalled.toArray(new ArchiveReplacement[mInstalled.size()]); - } - - /** Overrides the sdk manager with our mock instance. */ - @Override - protected void initSdk() { - setSdkManager(new MockEmptySdkManager(SDK_PATH)); - } - - /** Overrides the settings controller with our mock instance. */ - @Override - protected SettingsController initSettingsController() { - return createSettingsController(getSdkLog()); - } - - /** Override original implementation to do nothing. */ - @Override - public void reloadSdk() { - // nop - } - - /** - * Override original implementation to return a mock SdkSources that - * does not load user add-ons from the local .android/repository.cfg file. - */ - @Override - public SdkSources getSources() { - return mMockSdkSources; - } - - /** Returns a mock installer that simply records what would have been installed. */ - @Override - protected ArchiveInstaller createArchiveInstaler() { - return new ArchiveInstaller() { - @Override - public boolean install( - ArchiveReplacement archiveInfo, - String osSdkRoot, - boolean forceHttp, - SdkManager sdkManager, - DownloadCache cache, - ITaskMonitor monitor) { - mInstalled.add(archiveInfo); - return true; - } - }; - } - - /** Returns a mock download cache. */ - @Override - public DownloadCache getDownloadCache() { - return mMockDownloadCache; - } - - /** Overrides the mock download cache. */ - public void setMockDownloadCache(DownloadCache mockDownloadCache) { - mMockDownloadCache = mockDownloadCache; - } - - public void overrideSetting(String key, boolean boolValue) { - SettingsController sc = getSettingsController(); - assert sc instanceof MockSettingsController; - ((MockSettingsController)sc).overrideSetting(key, boolValue); - } - - //------------ - - public static SettingsController createSettingsController(ILogger sdkLog) { - Properties props = new Properties(); - Settings settings = new Settings(props) {}; // this constructor is protected - MockSettingsController controller = new MockSettingsController(sdkLog, settings); - controller.setProperties(props); - return controller; - } - - static class MockSettingsController extends SettingsController { - - private Properties mProperties; - - MockSettingsController(ILogger sdkLog, Settings settings) { - super(sdkLog, settings); - } - - void setProperties(Properties properties) { - mProperties = properties; - } - - public void overrideSetting(String key, boolean boolValue) { - mProperties.setProperty(key, Boolean.valueOf(boolValue).toString()); - } - - @Override - public void loadSettings() { - // This mock setting controller does not load live file settings. - } - - @Override - public void saveSettings() { - // This mock setting controller does not save live file settings. - } - } - - //------------ - - private class MockTaskFactory implements ITaskFactory { - @Override - public void start(String title, ITask task) { - start(title, null /*parentMonitor*/, task); - } - - @SuppressWarnings("unused") // works by side-effect of creating a new MockTask. - @Override - public void start(String title, ITaskMonitor parentMonitor, ITask task) { - new MockTask(task); - } - } - - //------------ - - private static class MockTask extends NullTaskMonitor { - public MockTask(ITask task) { - super(NullLogger.getLogger()); - task.run(this); - } - } - - //------------ - - private static class NullImageFactory extends ImageFactory { - public NullImageFactory() { - // pass - super(null /*display*/); - } - - @Override - public Image getImageByName(String imageName) { - return null; - } - - @Override - public Image getImageForObject(Object object) { - return null; - } - - @Override - public void dispose() { - // pass - } - - } -} diff --git a/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/SdkUpdaterLogicTest.java b/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/SdkUpdaterLogicTest.java deleted file mode 100755 index 6a93914..0000000 --- a/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/SdkUpdaterLogicTest.java +++ /dev/null @@ -1,495 +0,0 @@ -/* - * 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.repository; - -import com.android.sdklib.SdkManager; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdklib.internal.repository.DownloadCache; -import com.android.sdklib.internal.repository.ITaskFactory; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.packages.FullRevision; -import com.android.sdklib.internal.repository.packages.MockAddonPackage; -import com.android.sdklib.internal.repository.packages.MockBrokenPackage; -import com.android.sdklib.internal.repository.packages.MockPlatformPackage; -import com.android.sdklib.internal.repository.packages.MockPlatformToolPackage; -import com.android.sdklib.internal.repository.packages.MockToolPackage; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.internal.repository.sources.SdkSources; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.utils.ILogger; - -import org.eclipse.swt.widgets.Shell; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import junit.framework.TestCase; - -public class SdkUpdaterLogicTest extends TestCase { - - private static class NullUpdaterData implements IUpdaterData { - - @Override - public AvdManager getAvdManager() { - return null; - } - - @Override - public ImageFactory getImageFactory() { - return null; - } - - @Override - public ILogger getSdkLog() { - return null; - } - - @Override - public DownloadCache getDownloadCache() { - return null; - } - - @Override - public SdkManager getSdkManager() { - return null; - } - - @Override - public SettingsController getSettingsController() { - return null; - } - - @Override - public ITaskFactory getTaskFactory() { - return null; - } - - @Override - public Shell getWindowShell() { - return null; - } - - } - - private static class MockSdkUpdaterLogic extends SdkUpdaterLogic { - private final Package[] mRemotePackages; - - public MockSdkUpdaterLogic(IUpdaterData updaterData, Package[] remotePackages) { - super(updaterData); - mRemotePackages = remotePackages; - } - - @Override - protected void fetchRemotePackages(Collection<Package> remotePkgs, - SdkSource[] remoteSources) { - // Ignore remoteSources and instead uses the remotePackages list given to the - // constructor. - if (mRemotePackages != null) { - remotePkgs.addAll(Arrays.asList(mRemotePackages)); - } - } - } - - /** - * Addon packages depend on a base platform package. - * This test checks that UpdaterLogic.findPlatformToolsDependency(...) - * can find the base platform for a given addon. - */ - public void testFindAddonDependency() { - MockSdkUpdaterLogic mul = new MockSdkUpdaterLogic(new NullUpdaterData(), null); - - MockPlatformPackage p1 = new MockPlatformPackage(1, 1); - MockPlatformPackage p2 = new MockPlatformPackage(2, 1); - - MockAddonPackage a1 = new MockAddonPackage(p1, 1); - MockAddonPackage a2 = new MockAddonPackage(p2, 2); - - ArrayList<ArchiveInfo> out = new ArrayList<ArchiveInfo>(); - ArrayList<Archive> selected = new ArrayList<Archive>(); - ArrayList<Package> remote = new ArrayList<Package>(); - - // a2 depends on p2, which is not in the locals - Package[] localPkgs = { p1, a1 }; - ArchiveInfo[] locals = mul.createLocalArchives(localPkgs); - - SdkSource[] sources = null; - - // a2 now depends on a "fake" archive info with no newArchive that wraps the missing - // underlying platform. - ArchiveInfo fai = mul.findPlatformDependency(a2, out, selected, remote, sources, locals); - assertNotNull(fai); - assertNull(fai.getNewArchive()); - assertTrue(fai.isRejected()); - assertEquals(0, out.size()); - - // p2 is now selected, and should be scheduled for install in out - Archive p2_archive = p2.getArchives()[0]; - selected.add(p2_archive); - ArchiveInfo ai2 = mul.findPlatformDependency(a2, out, selected, remote, sources, locals); - assertNotNull(ai2); - assertSame(p2_archive, ai2.getNewArchive()); - assertEquals(1, out.size()); - assertSame(p2_archive, out.get(0).getNewArchive()); - } - - /** - * Broken add-on packages require an exact platform package to be present or installed. - * This tests checks that findExactApiLevelDependency() can find a base - * platform package for a given broken add-on package. - */ - public void testFindExactApiLevelDependency() { - MockSdkUpdaterLogic mul = new MockSdkUpdaterLogic(new NullUpdaterData(), null); - - MockPlatformPackage p1 = new MockPlatformPackage(1, 1); - MockPlatformPackage p2 = new MockPlatformPackage(2, 1); - - MockBrokenPackage a1 = new MockBrokenPackage(0, 1); - MockBrokenPackage a2 = new MockBrokenPackage(0, 2); - - ArrayList<ArchiveInfo> out = new ArrayList<ArchiveInfo>(); - ArrayList<Archive> selected = new ArrayList<Archive>(); - ArrayList<Package> remote = new ArrayList<Package>(); - - // a2 depends on p2, which is not in the locals - Package[] localPkgs = { p1, a1 }; - ArchiveInfo[] locals = mul.createLocalArchives(localPkgs); - - SdkSource[] sources = null; - - // a1 depends on p1, which can be found in the locals. p1 is already "installed" - // so we donn't need to suggest it as a dependency to solve any problem. - ArchiveInfo found = mul.findExactApiLevelDependency( - a1, out, selected, remote, sources, locals); - assertNull(found); - - // a2 now depends on a "fake" archive info with no newArchive that wraps the missing - // underlying platform. - found = mul.findExactApiLevelDependency(a2, out, selected, remote, sources, locals); - assertNotNull(found); - assertNull(found.getNewArchive()); - assertTrue(found.isRejected()); - assertEquals(0, out.size()); - - // p2 is now selected, and should be scheduled for install in out - Archive p2_archive = p2.getArchives()[0]; - selected.add(p2_archive); - found = mul.findExactApiLevelDependency(a2, out, selected, remote, sources, locals); - assertNotNull(found); - assertSame(p2_archive, found.getNewArchive()); - assertEquals(1, out.size()); - assertSame(p2_archive, out.get(0).getNewArchive()); - } - - /** - * Platform packages depend on a tool package. - * This tests checks that UpdaterLogic.findToolsDependency() can find a base - * tool package for a given platform package. - */ - public void testFindPlatformDependency() { - MockSdkUpdaterLogic mul = new MockSdkUpdaterLogic(new NullUpdaterData(), null); - - MockPlatformToolPackage pt1 = new MockPlatformToolPackage(1); - - MockToolPackage t1 = new MockToolPackage(1, 1); - MockToolPackage t2 = new MockToolPackage(2, 1); - - MockPlatformPackage p2 = new MockPlatformPackage(2, 1, 2); - - ArrayList<ArchiveInfo> out = new ArrayList<ArchiveInfo>(); - ArrayList<Archive> selected = new ArrayList<Archive>(); - ArrayList<Package> remote = new ArrayList<Package>(); - - // p2 depends on t2, which is not locally installed - Package[] localPkgs = { t1, pt1 }; - ArchiveInfo[] locals = mul.createLocalArchives(localPkgs); - - SdkSource[] sources = null; - - // p2 now depends on a "fake" archive info with no newArchive that wraps the missing - // underlying tool - ArchiveInfo fai = mul.findToolsDependency(p2, out, selected, remote, sources, locals); - assertNotNull(fai); - assertNull(fai.getNewArchive()); - assertTrue(fai.isRejected()); - assertEquals(0, out.size()); - - // t2 is now selected and can be used as a dependency - Archive t2_archive = t2.getArchives()[0]; - selected.add(t2_archive); - ArchiveInfo ai2 = mul.findToolsDependency(p2, out, selected, remote, sources, locals); - assertNotNull(ai2); - assertSame(t2_archive, ai2.getNewArchive()); - assertEquals(1, out.size()); - assertSame(t2_archive, out.get(0).getNewArchive()); - } - - /** - * Tool packages require a platform-tool package to be present or installed. - * This tests checks that UpdaterLogic.findPlatformToolsDependency() can find a base - * platform-tool package for a given tool package. - */ - public void testFindPlatformToolDependency() { - MockSdkUpdaterLogic mul = new MockSdkUpdaterLogic(new NullUpdaterData(), null); - - MockPlatformToolPackage t1 = new MockPlatformToolPackage(1); - MockPlatformToolPackage t2 = new MockPlatformToolPackage(2); - - MockToolPackage p2 = new MockToolPackage(2, 2); - - ArrayList<ArchiveInfo> out = new ArrayList<ArchiveInfo>(); - ArrayList<Archive> selected = new ArrayList<Archive>(); - ArrayList<Package> remote = new ArrayList<Package>(); - - // p2 depends on t2, which is not locally installed - Package[] localPkgs = { t1 }; - ArchiveInfo[] locals = mul.createLocalArchives(localPkgs); - - SdkSource[] sources = null; - - // p2 now depends on a "fake" archive info with no newArchive that wraps the missing - // underlying tool - ArchiveInfo fai = mul.findPlatformToolsDependency( - p2, out, selected, remote, sources, locals); - assertNotNull(fai); - assertNull(fai.getNewArchive()); - assertTrue(fai.isRejected()); - assertEquals(0, out.size()); - - // t2 is now selected and can be used as a dependency - Archive t2_archive = t2.getArchives()[0]; - selected.add(t2_archive); - ArchiveInfo ai2 = mul.findPlatformToolsDependency( - p2, out, selected, remote, sources, locals); - assertNotNull(ai2); - assertSame(t2_archive, ai2.getNewArchive()); - assertEquals(1, out.size()); - assertSame(t2_archive, out.get(0).getNewArchive()); - } - - public void testComputeRevisionUpdate() { - // Scenario: - // - user has tools rev 7 installed + plat-tools rev 1 installed - // - server has tools rev 8, depending on plat-tools rev 2 - // - server has tools rev 9, depending on plat-tools rev 3 - // - server has platform 9 that requires min-tools-rev 9 - // - // If we do an update all, we want to the installer to pick up: - // - the new platform 9 - // - the tools rev 9 (required by platform 9) - // - the plat-tools rev 3 (required by tools rev 9) - - final MockPlatformToolPackage pt1 = new MockPlatformToolPackage(1); - final MockPlatformToolPackage pt2 = new MockPlatformToolPackage(2); - final MockPlatformToolPackage pt3 = new MockPlatformToolPackage(3); - - final MockToolPackage t7 = new MockToolPackage(7, 1 /*min-plat-tools*/); - final MockToolPackage t8 = new MockToolPackage(8, 2 /*min-plat-tools*/); - final MockToolPackage t9 = new MockToolPackage(9, 3 /*min-plat-tools*/); - - final MockPlatformPackage p9 = new MockPlatformPackage(9, 1, 9 /*min-tools*/); - - // Note: the mock updater logic gets the remotes packages from the array given - // here and bypasses the source (to avoid fetching any actual URLs) - MockSdkUpdaterLogic mul = new MockSdkUpdaterLogic(new NullUpdaterData(), - new Package[] { t8, pt2, t9, pt3, p9 }); - - SdkSources sources = new SdkSources(); - Package[] localPkgs = { t7, pt1 }; - - List<ArchiveInfo> selected = mul.computeUpdates( - null /*selectedArchives*/, - sources, - localPkgs, - false /*includeObsoletes*/); - - assertEquals( - "[Android SDK Platform-tools, revision 3, " + - "Android SDK Tools, revision 9]", - Arrays.toString(selected.toArray())); - - mul.addNewPlatforms( - selected, - sources, - localPkgs, - false /*includeObsoletes*/); - - assertEquals( - "[Android SDK Platform-tools, revision 3, " + - "Android SDK Tools, revision 9, " + - "SDK Platform Android android-9, API 9, revision 1]", - Arrays.toString(selected.toArray())); - - // Now try again but reverse the order of the remote package list. - - mul = new MockSdkUpdaterLogic(new NullUpdaterData(), - new Package[] { p9, t9, pt3, t8, pt2 }); - - selected = mul.computeUpdates( - null /*selectedArchives*/, - sources, - localPkgs, - false /*includeObsoletes*/); - - assertEquals( - "[Android SDK Platform-tools, revision 3, " + - "Android SDK Tools, revision 9]", - Arrays.toString(selected.toArray())); - - mul.addNewPlatforms( - selected, - sources, - localPkgs, - false /*includeObsoletes*/); - - assertEquals( - "[Android SDK Platform-tools, revision 3, " + - "Android SDK Tools, revision 9, " + - "SDK Platform Android android-9, API 9, revision 1]", - Arrays.toString(selected.toArray())); - } - - public void testComputeRevisionUpdate2() { - // Scenario: - // - user has tools rev 2 installed and NO platform-tools - // - server has platform tools 1 rc 1 (a preview) and 2. - // - server has platform 2 that requires min-tools 2 that requires min-plat-tools 1rc1. - // - // One issue is that when there was only one instance of platform-tools possible, - // the computeUpdates() code would pick the first one. But now there can be 2 of - // them (preview, non-preview) and thus we need to pick up the higher one even if - // it's not the first choice. - - final MockPlatformToolPackage pt1rc = new MockPlatformToolPackage( - null, - new FullRevision(1, 0, 0, 1)); - final MockPlatformToolPackage pt2 = new MockPlatformToolPackage(2); - - // Tools rev 2 requires at least plat-tools 1rc1 - final MockToolPackage t2 = new MockToolPackage(null, - new FullRevision(2), // tools rev - new FullRevision(1, 0, 0, 1)); // min-pt-rev - - final MockPlatformPackage p2 = new MockPlatformPackage(2, 1, 2 /*min-tools*/); - - // Note: the mock updater logic gets the remotes packages from the array given - // here and bypasses the source (to avoid fetching any actual URLs) - // Remote available packages include both plat-tools 1rc1 and 2. - // - // Order DOES matter: the issue is that computeUpdates was selecting the first platform - // tools (so 1rc1) and ignoring the newer revision 2 because originally there could be - // only one platform-tool definition. Now with previews we can have 2 and we need to - // select the higher one even if it's not the first choice. - MockSdkUpdaterLogic mul = new MockSdkUpdaterLogic(new NullUpdaterData(), - new Package[] { t2, pt1rc, pt2, p2 }); - - // Local packages only have tools 2. - SdkSources sources = new SdkSources(); - Package[] localPkgs = { t2 }; - List<Archive> selectedArchives = Arrays.asList( p2.getArchives() ); - - List<ArchiveInfo> selected = mul.computeUpdates( - selectedArchives, - sources, - localPkgs, - false /*includeObsoletes*/); - - assertEquals( - "[SDK Platform Android android-2, API 2, revision 1, " + - "Android SDK Platform-tools, revision 2]", - Arrays.toString(selected.toArray())); - - mul.addNewPlatforms( - selected, - sources, - localPkgs, - false /*includeObsoletes*/); - - assertEquals( - "[SDK Platform Android android-2, API 2, revision 1, " + - "Android SDK Platform-tools, revision 2]", - Arrays.toString(selected.toArray())); - } - - public void testComputeRevisionUpdate3() { - // Scenario: - // - user has tools rev 2 installed and NO platform-tools - // - server has platform tools 1 rc 1 (a preview) and 2. - // - server has platform 2 that requires min-tools 2 that requires min-plat-tools 1rc1. - // - // One issue is that when there was only one instance of tools possible, - // the computeUpdates() code would pick the first one. But now there can be 2 of - // them (preview, non-preview) and thus we need to pick up the higher one even if - // it's not the first choice. - - final MockPlatformToolPackage pt1rc = new MockPlatformToolPackage( - null, - new FullRevision(1, 0, 0, 1)); - final MockPlatformToolPackage pt2 = new MockPlatformToolPackage(2); - - // Tools rev 1rc1 requires plat-tools 1rc1, and tools 2 requires plat-tools 2. - final MockToolPackage t1rc = new MockToolPackage(null, - new FullRevision(1, 0, 0, 1), // tools rev - new FullRevision(1, 0, 0, 1)); // min-pt-rev - final MockToolPackage t2 = new MockToolPackage(null, 2, 2); - - // Platform depends on min-tools 1rc1, so any of tools 1rc1 or 2 would satisfy. - final MockPlatformPackage p2 = new MockPlatformPackage(2, 1, new FullRevision(1, 0, 0, 1)); - - // Note: the mock updater logic gets the remotes packages from the array given - // here and bypasses the source (to avoid fetching any actual URLs) - // Remote available packages include both plat-tools 1rc1 and 2. - // - // Order DOES matter: the issue is that computeUpdates was selecting the first tools (1rc1) - // and ignoring the newer revision 2 because originally there could be only one tool - // definition. Now with previews we can have 2 and we need to select the higher version - // available even if it's not the first choice. - MockSdkUpdaterLogic mul = new MockSdkUpdaterLogic(new NullUpdaterData(), - new Package[] { t1rc, pt1rc, t2, pt2, p2 }); - - // Local packages only have tools 2. - SdkSources sources = new SdkSources(); - Package[] localPkgs = { }; - List<Archive> selectedArchives = Arrays.asList( p2.getArchives() ); - - List<ArchiveInfo> selected = mul.computeUpdates( - selectedArchives, - sources, - localPkgs, - false /*includeObsoletes*/); - - assertEquals( - "[Android SDK Platform-tools, revision 2, " + - "Android SDK Tools, revision 2, " + - "SDK Platform Android android-2, API 2, revision 1]", - Arrays.toString(selected.toArray())); - - mul.addNewPlatforms( - selected, - sources, - localPkgs, - false /*includeObsoletes*/); - - assertEquals( - "[Android SDK Platform-tools, revision 2, " + - "Android SDK Tools, revision 2, " + - "SDK Platform Android android-2, API 2, revision 1]", - Arrays.toString(selected.toArray())); - } -} diff --git a/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/UpdaterDataTest.java b/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/UpdaterDataTest.java deleted file mode 100755 index 6b8c850..0000000 --- a/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/UpdaterDataTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2011 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.repository; - -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.packages.MockEmptyPackage; - -import java.util.ArrayList; -import java.util.Arrays; - -import junit.framework.TestCase; - -public class UpdaterDataTest extends TestCase { - - private MockUpdaterData m; - - @Override - protected void setUp() throws Exception { - super.setUp(); - m = new MockUpdaterData(); - assertEquals("[]", Arrays.toString(m.getInstalled())); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - /** - * Tests the case where we have nothing to install. - */ - public void testInstallArchives_None() { - m._installArchives(new ArrayList<ArchiveInfo>()); - assertEquals("[]", Arrays.toString(m.getInstalled())); - } - - - /** - * Tests the case where there's a simple dependency, in the right order - * (e.g. install A1 then A2 that depends on A1). - */ - public void testInstallArchives_SimpleDependency() { - - ArrayList<ArchiveInfo> archives = new ArrayList<ArchiveInfo>(); - - Archive a1 = new MockEmptyPackage("a1").getLocalArchive(); - ArchiveInfo ai1 = new ArchiveInfo(a1, null, null); - - Archive a2 = new MockEmptyPackage("a2").getLocalArchive(); - ArchiveInfo ai2 = new ArchiveInfo(a2, null, new ArchiveInfo[] { ai1 } ); - - archives.add(ai1); - archives.add(ai2); - - m._installArchives(archives); - assertEquals( - "[MockEmptyPackage 'a1', MockEmptyPackage 'a2']", - Arrays.toString(m.getInstalled())); - } - - /** - * Tests the case where there's a simple dependency, in the wrong order - * (e.g. install A2 then A1 which A2 depends on) - */ - public void testInstallArchives_ReverseDependency() { - - ArrayList<ArchiveInfo> archives = new ArrayList<ArchiveInfo>(); - - Archive a1 = new MockEmptyPackage("a1").getLocalArchive(); - ArchiveInfo ai1 = new ArchiveInfo(a1, null, null); - - Archive a2 = new MockEmptyPackage("a2").getLocalArchive(); - ArchiveInfo ai2 = new ArchiveInfo(a2, null, new ArchiveInfo[] { ai1 } ); - - archives.add(ai2); - archives.add(ai1); - - m._installArchives(archives); - assertEquals( - "[MockEmptyPackage 'a1', MockEmptyPackage 'a2']", - Arrays.toString(m.getInstalled())); - } - -} diff --git a/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/core/PackagesDiffLogicTest.java b/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/core/PackagesDiffLogicTest.java deleted file mode 100755 index 1f7a27a..0000000 --- a/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/core/PackagesDiffLogicTest.java +++ /dev/null @@ -1,1814 +0,0 @@ -/* - * Copyright (C) 2011 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.repository.core; - -import com.android.SdkConstants; -import com.android.sdklib.internal.repository.packages.BrokenPackage; -import com.android.sdklib.internal.repository.packages.FullRevision; -import com.android.sdklib.internal.repository.packages.MockAddonPackage; -import com.android.sdklib.internal.repository.packages.MockBrokenPackage; -import com.android.sdklib.internal.repository.packages.MockEmptyPackage; -import com.android.sdklib.internal.repository.packages.MockExtraPackage; -import com.android.sdklib.internal.repository.packages.MockPlatformPackage; -import com.android.sdklib.internal.repository.packages.MockPlatformToolPackage; -import com.android.sdklib.internal.repository.packages.MockSystemImagePackage; -import com.android.sdklib.internal.repository.packages.MockToolPackage; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdklib.internal.repository.sources.SdkRepoSource; -import com.android.sdklib.internal.repository.sources.SdkSource; -import com.android.sdklib.repository.PkgProps; -import com.android.sdkuilib.internal.repository.ISettingsPage; -import com.android.sdkuilib.internal.repository.MockUpdaterData; -import com.android.sdkuilib.internal.repository.core.PackagesDiffLogic; -import com.android.sdkuilib.internal.repository.core.PkgCategory; -import com.android.sdkuilib.internal.repository.core.PkgItem; - -import java.util.Properties; - -import junit.framework.TestCase; - -public class PackagesDiffLogicTest extends TestCase { - - private PackagesDiffLogic m; - private MockUpdaterData u; - - @Override - protected void setUp() throws Exception { - super.setUp(); - - u = new MockUpdaterData(); - m = new PackagesDiffLogic(u); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - // ---- - // - // Test Details Note: the way load is implemented in PackageLoader, the - // loader processes each source and then for each source the packages are added - // to a list and the sorting algorithm is called with that list. Thus for - // one load, many calls to the sortByX/Y happen, with the list progressively - // being populated. - // However when the user switches sorting algorithm, the package list is not - // reloaded and is processed at once. - - public void testSortByApi_Empty() { - m.updateStart(); - assertFalse(m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[0])); - assertFalse(m.updateEnd(true /*sortByApi*/)); - - // We also keep these 2 categories even if they contain nothing - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n", - getTree(m, true /*displaySortByApi*/)); - } - - public void testSortByApi_AddSamePackage() { - SdkSource src1 = new SdkRepoSource("http://example.com/url", "repo1"); - - m.updateStart(); - // First insert local packages - assertTrue(m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "some pkg", 1) - })); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'some pkg' rev=1>\n", - getTree(m, true /*displaySortByApi*/)); - - // Insert the next source - // Same package as the one installed, so we don't display it - assertFalse(m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "some pkg", 1) - })); - - assertFalse(m.updateEnd(true /*sortByApi*/)); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'some pkg' rev=1>\n", - getTree(m, true /*displaySortByApi*/)); - } - - public void testSortByApi_AddOtherPackage() { - SdkSource src1 = new SdkRepoSource("http://example.com/url", "repo1"); - - m.updateStart(); - // First insert local packages - assertTrue(m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "some pkg", 1) - })); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'some pkg' rev=1>\n", - getTree(m, true /*displaySortByApi*/)); - - // Insert the next source - // Not the same package as the one installed, so we'll display it - assertTrue(m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "other pkg", 1) - })); - - assertFalse(m.updateEnd(true /*sortByApi*/)); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'some pkg' rev=1>\n" + - "-- <NEW, pkg:MockEmptyPackage 'other pkg' rev=1>\n", - getTree(m, true /*displaySortByApi*/)); - } - - public void testSortByApi_Update1() { - SdkSource src1 = new SdkRepoSource("http://example.com/url", "repo1"); - - // Typical case: user has a locally installed package in revision 1 - // The display list after sort should show that installed package. - m.updateStart(); - // First insert local packages - assertTrue(m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "type1", 1) - })); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1>\n", - getTree(m, true /*displaySortByApi*/)); - - assertTrue(m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "type1", 4), - new MockEmptyPackage(src1, "type1", 2) - })); - - assertFalse(m.updateEnd(true /*sortByApi*/)); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=4>\n", - getTree(m, true /*displaySortByApi*/)); - } - - public void testSortByApi_Reload() { - SdkSource src1 = new SdkRepoSource("http://example.com/url", "repo1"); - - // First load reveals a package local package and its update - m.updateStart(); - // First insert local packages - assertTrue(m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "type1", 1) - })); - assertTrue(m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "type1", 2) - })); - - assertFalse(m.updateEnd(true /*sortByApi*/)); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n", - getTree(m, true /*displaySortByApi*/)); - - // Now simulate a reload that clears the package list and creates similar - // objects but not the same references. The only difference is that updateXyz - // returns false since nothing changes. - - m.updateStart(); - // First insert local packages - assertFalse(m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "type1", 1) - })); - assertFalse(m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "type1", 2) - })); - - assertFalse(m.updateEnd(true /*sortByApi*/)); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n", - getTree(m, true /*displaySortByApi*/)); - } - - public void testSortByApi_InstallPackage() { - SdkSource src1 = new SdkRepoSource("http://example.com/url", "repo1"); - - // First load reveals a new package - m.updateStart(); - // No local packages at first - assertFalse(m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[0])); - assertTrue(m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "type1", 1) - })); - - assertFalse(m.updateEnd(true /*sortByApi*/)); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" + - "-- <NEW, pkg:MockEmptyPackage 'type1' rev=1>\n", - getTree(m, true /*displaySortByApi*/)); - - // Install it. - m.updateStart(); - // local packages - assertTrue(m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "type1", 1) - })); - assertFalse(m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "type1", 1) - })); - - assertTrue(m.updateEnd(true /*sortByApi*/)); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1>\n", - getTree(m, true /*displaySortByApi*/)); - - // Load reveals an update - m.updateStart(); - // local packages - assertFalse(m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "type1", 1) - })); - assertTrue(m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "type1", 2) - })); - - assertFalse(m.updateEnd(true /*sortByApi*/)); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n", - getTree(m, true /*displaySortByApi*/)); - } - - public void testSortByApi_DeletePackage() { - SdkSource src1 = new SdkRepoSource("http://example.com/url", "repo1"); - - // We have an installed package - m.updateStart(); - // local packages - assertTrue(m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "type1", 1) - })); - assertTrue(m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "type1", 2) - })); - - assertFalse(m.updateEnd(true /*sortByApi*/)); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n", - getTree(m, true /*displaySortByApi*/)); - - // User now deletes the installed package. - m.updateStart(); - // No local packages - assertTrue(m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[0])); - assertTrue(m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "type1", 1) - })); - - assertFalse(m.updateEnd(true /*sortByApi*/)); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" + - "-- <NEW, pkg:MockEmptyPackage 'type1' rev=1>\n", - getTree(m, true /*displaySortByApi*/)); - } - - public void testSortByApi_NoRemoteSources() { - SdkSource src1 = new SdkRepoSource("http://example.com/url1", "repo1"); - SdkSource src2 = new SdkRepoSource("http://example.com/url2", "repo2"); - - // We have a couple installed packages - m.updateStart(); - // local packages - assertTrue(m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockToolPackage(src1, 10, 3), - new MockPlatformToolPackage(src1, 3), - new MockExtraPackage(src2, "carrier", "custom_rom", 1, 0), - new MockExtraPackage(src2, "android", "usb_driver", 5, 3), - })); - // and no remote sources have been loaded (e.g. because there's no network) - assertFalse(m.updateEnd(true /*sortByApi*/)); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" + - "-- <INSTALLED, pkg:Android USB Driver, revision 5>\n" + - "-- <INSTALLED, pkg:Carrier Custom Rom, revision 1>\n", - getTree(m, true /*displaySortByApi*/)); - - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=2>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" + - "PkgCategorySource <source=repo2 (example.com), #items=2>\n" + - "-- <INSTALLED, pkg:Android USB Driver, revision 5>\n" + - "-- <INSTALLED, pkg:Carrier Custom Rom, revision 1>\n", - getTree(m, false /*displaySortByApi*/)); - } - - public void testSortByApi_CompleteUpdate() { - SdkSource src1 = new SdkRepoSource("http://1.example.com/url1", "repo1"); - SdkSource src2 = new SdkRepoSource("http://2.example.com/url2", "repo2"); - - // Resulting categories are sorted by Tools, descending platform API and finally Extras. - // Addons are sorted by name within their API. - // Extras are sorted by vendor name. - // The order packages are added to the mAllPkgItems list is purposedly different from - // the final order we get. - - // First update has the typical tools and a couple extras - m.updateStart(); - - assertTrue(m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockToolPackage(src1, 10, 3), - new MockPlatformToolPackage(src1, 3), - new MockExtraPackage(src1, "android", "usb_driver", 4, 3), - })); - assertTrue(m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockToolPackage(src1, 10, 3), - new MockPlatformToolPackage(src1, 3), - new MockExtraPackage(src1, "carrier", "custom_rom", 1, 0), - new MockExtraPackage(src1, "android", "usb_driver", 5, 3), - })); - assertFalse(m.updateEnd(true /*sortByApi*/)); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" + - "-- <INSTALLED, pkg:Android USB Driver, revision 4, updated by:Android USB Driver, revision 5>\n" + - "-- <NEW, pkg:Carrier Custom Rom, revision 1>\n", - getTree(m, true /*displaySortByApi*/)); - - // Next update adds platforms and addon, sorted in a category based on their API level - m.updateStart(); - MockPlatformPackage p1; - MockPlatformPackage p2; - @SuppressWarnings("unused") // keep p3 for clarity - MockPlatformPackage p3; - - assertTrue(m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockToolPackage(src1, 10, 3), - new MockPlatformToolPackage(src1, 3), - new MockExtraPackage(src1, "android", "usb_driver", 4, 3), - // second update - p1 = new MockPlatformPackage(src1, 1, 2, 3), // API 1 - p3 = new MockPlatformPackage(src1, 3, 6, 3), - new MockAddonPackage(src2, "addon A", p1, 5), - new MockAddonPackage(src2, "addon D", p1, 10), - })); - assertTrue(m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockToolPackage(src1, 10, 3), - new MockPlatformToolPackage(src1, 3), - new MockExtraPackage(src1, "carrier", "custom_rom", 1, 0), - new MockExtraPackage(src1, "android", "usb_driver", 5, 3), - // second update - p2 = new MockPlatformPackage(src1, 2, 4, 3), // API 2 - })); - assertTrue(m.updateSourcePackages(true /*sortByApi*/, src2, new Package[] { - new MockAddonPackage(src2, "addon C", p2, 9), - new MockAddonPackage(src2, "addon A", p1, 6), - // the rev 7+8 will be ignored since there's a rev 9 coming after - new MockAddonPackage(src2, "addon B", p2, 7), - new MockAddonPackage(src2, "addon B", p2, 8), - new MockAddonPackage(src2, "addon B", p2, 9), - // 11+12 should be ignored updates, 13 will update 10 - new MockAddonPackage(src2, "addon D", p1, 10), - new MockAddonPackage(src2, "addon D", p1, 12), // note: 12 listed before 11 - new MockAddonPackage(src2, "addon D", p1, 11), - new MockAddonPackage(src2, "addon D", p1, 13), - })); - assertFalse(m.updateEnd(true /*sortByApi*/)); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" + - "PkgCategoryApi <API=API 3, label=Android android-3 (API 3), #items=1>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-3, API 3, revision 6>\n" + - "PkgCategoryApi <API=API 2, label=Android android-2 (API 2), #items=3>\n" + - "-- <NEW, pkg:SDK Platform Android android-2, API 2, revision 4>\n" + - "-- <NEW, pkg:The addon B from vendor 2, Android API 2, revision 9>\n" + - "-- <NEW, pkg:The addon C from vendor 2, Android API 2, revision 9>\n" + - "PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=3>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "-- <INSTALLED, pkg:The addon A from vendor 1, Android API 1, revision 5, updated by:The addon A from vendor 1, Android API 1, revision 6>\n" + - "-- <INSTALLED, pkg:The addon D from vendor 1, Android API 1, revision 10, updated by:The addon D from vendor 1, Android API 1, revision 13>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" + - "-- <INSTALLED, pkg:Android USB Driver, revision 4, updated by:Android USB Driver, revision 5>\n" + - "-- <NEW, pkg:Carrier Custom Rom, revision 1>\n", - getTree(m, true /*displaySortByApi*/)); - - // Reloading the same thing should have no impact except for the update methods - // returning false when they don't change the current list. - m.updateStart(); - - assertFalse(m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockToolPackage(src1, 10, 3), - new MockPlatformToolPackage(src1, 3), - new MockExtraPackage(src1, "android", "usb_driver", 4, 3), - // second update - p1 = new MockPlatformPackage(src1, 1, 2, 3), - p3 = new MockPlatformPackage(src1, 3, 6, 3), - new MockAddonPackage(src2, "addon A", p1, 5), - new MockAddonPackage(src2, "addon D", p1, 10), - })); - assertFalse(m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockToolPackage(src1, 10, 3), - new MockPlatformToolPackage(src1, 3), - new MockExtraPackage(src1, "carrier", "custom_rom", 1, 0), - new MockExtraPackage(src1, "android", "usb_driver", 5, 3), - // second update - p2 = new MockPlatformPackage(src1, 2, 4, 3), - })); - assertTrue(m.updateSourcePackages(true /*sortByApi*/, src2, new Package[] { - new MockAddonPackage(src2, "addon C", p2, 9), - new MockAddonPackage(src2, "addon A", p1, 6), - // the rev 7+8 will be ignored since there's a rev 9 coming after - new MockAddonPackage(src2, "addon B", p2, 7), - new MockAddonPackage(src2, "addon B", p2, 8), - new MockAddonPackage(src2, "addon B", p2, 9), - // 11+12 should be ignored updates, 13 will update 10 - new MockAddonPackage(src2, "addon D", p1, 10), - new MockAddonPackage(src2, "addon D", p1, 12), // note: 12 listed before 11 - new MockAddonPackage(src2, "addon D", p1, 11), - new MockAddonPackage(src2, "addon D", p1, 13), - })); - assertFalse(m.updateEnd(true /*sortByApi*/)); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" + - "PkgCategoryApi <API=API 3, label=Android android-3 (API 3), #items=1>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-3, API 3, revision 6>\n" + - "PkgCategoryApi <API=API 2, label=Android android-2 (API 2), #items=3>\n" + - "-- <NEW, pkg:SDK Platform Android android-2, API 2, revision 4>\n" + - "-- <NEW, pkg:The addon B from vendor 2, Android API 2, revision 9>\n" + - "-- <NEW, pkg:The addon C from vendor 2, Android API 2, revision 9>\n" + - "PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=3>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "-- <INSTALLED, pkg:The addon A from vendor 1, Android API 1, revision 5, updated by:The addon A from vendor 1, Android API 1, revision 6>\n" + - "-- <INSTALLED, pkg:The addon D from vendor 1, Android API 1, revision 10, updated by:The addon D from vendor 1, Android API 1, revision 13>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" + - "-- <INSTALLED, pkg:Android USB Driver, revision 4, updated by:Android USB Driver, revision 5>\n" + - "-- <NEW, pkg:Carrier Custom Rom, revision 1>\n", - getTree(m, true /*displaySortByApi*/)); - } - - // ---- - - public void testSortBySource_Empty() { - m.updateStart(); - assertFalse(m.updateSourcePackages(false /*sortByApi*/, null /*locals*/, new Package[0])); - // UpdateEnd returns true since it removed the synthetic "unknown source" category - assertTrue(m.updateEnd(false /*sortByApi*/)); - - assertTrue(m.getCategories(false /*sortByApi*/).isEmpty()); - - assertEquals( - "", - getTree(m, false /*displaySortByApi*/)); - } - - public void testSortBySource_AddPackages() { - // Since we're sorting by source, items are grouped under their source - // even if installed. The 'local' source is only for installed items for - // which we don't know the source. - SdkSource src1 = new SdkRepoSource("http://example.com/url", "repo1"); - - m.updateStart(); - assertTrue(m.updateSourcePackages(false /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "known source", 2), - new MockEmptyPackage(null, "unknown source", 3), - })); - - assertEquals( - "PkgCategorySource <source=Local Packages (no.source), #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'unknown source' rev=3>\n" + - "PkgCategorySource <source=repo1 (example.com), #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'known source' rev=2>\n", - getTree(m, false /*displaySortByApi*/)); - - assertTrue(m.updateSourcePackages(false /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "new", 1), - })); - - assertFalse(m.updateEnd(false /*sortByApi*/)); - - assertEquals( - "PkgCategorySource <source=Local Packages (no.source), #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'unknown source' rev=3>\n" + - "PkgCategorySource <source=repo1 (example.com), #items=2>\n" + - "-- <NEW, pkg:MockEmptyPackage 'new' rev=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'known source' rev=2>\n", - getTree(m, false /*displaySortByApi*/)); - } - - public void testSortBySource_Update1() { - - // Typical case: user has a locally installed package in revision 1 - // The display list after sort should show that instaled package. - SdkSource src1 = new SdkRepoSource("http://example.com/url", "repo1"); - m.updateStart(); - assertTrue(m.updateSourcePackages(false /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "type1", 1), - })); - - assertEquals( - "PkgCategorySource <source=Local Packages (no.source), #items=0>\n" + - "PkgCategorySource <source=repo1 (example.com), #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1>\n", - getTree(m, false /*displaySortByApi*/)); - - // Edge case: the source reveals an update in revision 2. It is ignored since - // we already have a package in rev 4. - - assertTrue(m.updateSourcePackages(false /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "type1", 4), - new MockEmptyPackage(src1, "type1", 2), - })); - - assertTrue(m.updateEnd(false /*sortByApi*/)); - - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=4>\n", - getTree(m, false /*displaySortByApi*/)); - } - - public void testSortBySource_Reload() { - - // First load reveals a package local package and its update - SdkSource src1 = new SdkRepoSource("http://example.com/url", "repo1"); - m.updateStart(); - assertTrue(m.updateSourcePackages(false /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "type1", 1), - })); - assertTrue(m.updateSourcePackages(false /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "type1", 2), - })); - assertTrue(m.updateEnd(false /*sortByApi*/)); - - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n", - getTree(m, false /*displaySortByApi*/)); - - // Now simulate a reload that clears the package list and creates similar - // objects but not the same references. Update methods return false since - // they don't change anything. - m.updateStart(); - assertFalse(m.updateSourcePackages(false /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "type1", 1), - })); - assertFalse(m.updateSourcePackages(false /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "type1", 2), - })); - assertTrue(m.updateEnd(false /*sortByApi*/)); - - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n", - getTree(m, false /*displaySortByApi*/)); - } - - public void testSortBySource_InstallPackage() { - - // First load reveals a new package - SdkSource src1 = new SdkRepoSource("http://example.com/url", "repo1"); - m.updateStart(); - // no local package - assertFalse(m.updateSourcePackages(false /*sortByApi*/, null /*locals*/, new Package[0])); - assertTrue(m.updateSourcePackages(false /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "type1", 1), - })); - assertTrue(m.updateEnd(false /*sortByApi*/)); - - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=1>\n" + - "-- <NEW, pkg:MockEmptyPackage 'type1' rev=1>\n", - getTree(m, false /*displaySortByApi*/)); - - - // Install it. The display only shows the installed one, 'hiding' the remote package - m.updateStart(); - assertTrue(m.updateSourcePackages(false /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "type1", 1), - })); - assertFalse(m.updateSourcePackages(false /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "type1", 1), - })); - assertTrue(m.updateEnd(false /*sortByApi*/)); - - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1>\n", - getTree(m, false /*displaySortByApi*/)); - - // Now we have an update - m.updateStart(); - assertFalse(m.updateSourcePackages(false /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "type1", 1), - })); - assertTrue(m.updateSourcePackages(false /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "type1", 2), - })); - assertTrue(m.updateEnd(false /*sortByApi*/)); - - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n", - getTree(m, false /*displaySortByApi*/)); - } - - public void testSortBySource_DeletePackage() { - SdkSource src1 = new SdkRepoSource("http://example.com/url", "repo1"); - - // Start with an installed package and its matching remote package - m.updateStart(); - assertTrue(m.updateSourcePackages(false /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "type1", 1), - })); - assertFalse(m.updateSourcePackages(false /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "type1", 1), - })); - assertTrue(m.updateEnd(false /*sortByApi*/)); - - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=1>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1>\n", - getTree(m, false /*displaySortByApi*/)); - - // User now deletes the installed package. - m.updateStart(); - // no local package - assertTrue(m.updateSourcePackages(false /*sortByApi*/, null /*locals*/, new Package[0])); - assertTrue(m.updateSourcePackages(false /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "type1", 1), - })); - assertTrue(m.updateEnd(false /*sortByApi*/)); - - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=1>\n" + - "-- <NEW, pkg:MockEmptyPackage 'type1' rev=1>\n", - getTree(m, false /*displaySortByApi*/)); - } - - public void testSortBySource_CompleteUpdate() { - SdkSource src1 = new SdkRepoSource("http://1.example.com/url1", "repo1"); - SdkSource src2 = new SdkRepoSource("http://2.example.com/url2", "repo2"); - - // First update has the typical tools and a couple extras - m.updateStart(); - - assertTrue(m.updateSourcePackages(false /*sortByApi*/, null /*locals*/, new Package[] { - new MockToolPackage(src1, 10, 3), - new MockPlatformToolPackage(src1, 3), - new MockExtraPackage(src1, "android", "usb_driver", 4, 3), - })); - assertTrue(m.updateSourcePackages(false /*sortByApi*/, src1, new Package[] { - new MockToolPackage(src1, 10, 3), - new MockPlatformToolPackage(src1, 3), - new MockExtraPackage(src1, "carrier", "custom_rom", 1, 0), - new MockExtraPackage(src1, "android", "usb_driver", 5, 3), - })); - assertTrue(m.updateEnd(false /*sortByApi*/)); - - assertEquals( - "PkgCategorySource <source=repo1 (1.example.com), #items=4>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" + - "-- <INSTALLED, pkg:Android USB Driver, revision 4, updated by:Android USB Driver, revision 5>\n" + - "-- <NEW, pkg:Carrier Custom Rom, revision 1>\n", - getTree(m, false /*displaySortByApi*/)); - - // Next update adds platforms and addon, sorted in a category based on their API level - m.updateStart(); - MockPlatformPackage p1; - MockPlatformPackage p2; - @SuppressWarnings("unused") // keep p3 for clarity - MockPlatformPackage p3; - - assertTrue(m.updateSourcePackages(false /*sortByApi*/, null /*locals*/, new Package[] { - new MockToolPackage(src1, 10, 3), - new MockPlatformToolPackage(src1, 3), - new MockExtraPackage(src1, "android", "usb_driver", 4, 3), - // second update - p1 = new MockPlatformPackage(src1, 1, 2, 3), // API 1 - p3 = new MockPlatformPackage(src1, 3, 6, 3), - new MockPlatformPackage(src1, 3, 6, 3), // API 3 - new MockAddonPackage(src2, "addon A", p1, 5), - new MockAddonPackage(src2, "addon D", p1, 10), - })); - assertTrue(m.updateSourcePackages(false /*sortByApi*/, src1, new Package[] { - new MockToolPackage(src1, 10, 3), - new MockPlatformToolPackage(src1, 3), - new MockExtraPackage(src1, "carrier", "custom_rom", 1, 0), - new MockExtraPackage(src1, "android", "usb_driver", 5, 3), - // second update - p2 = new MockPlatformPackage(src1, 2, 4, 3), // API 2 - })); - assertTrue(m.updateSourcePackages(false /*sortByApi*/, src2, new Package[] { - new MockAddonPackage(src2, "addon C", p2, 9), - new MockAddonPackage(src2, "addon A", p1, 6), - // the rev 7+8 will be ignored since there's a rev 9 coming after - new MockAddonPackage(src2, "addon B", p2, 7), - new MockAddonPackage(src2, "addon B", p2, 8), - new MockAddonPackage(src2, "addon B", p2, 9), - // 11+12 should be ignored updates, 13 will update 10 - new MockAddonPackage(src2, "addon D", p1, 10), - new MockAddonPackage(src2, "addon D", p1, 12), // note: 12 listed before 11 - new MockAddonPackage(src2, "addon D", p1, 11), - new MockAddonPackage(src2, "addon D", p1, 13), - })); - assertTrue(m.updateEnd(false /*sortByApi*/)); - - assertEquals( - "PkgCategorySource <source=repo1 (1.example.com), #items=7>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-3, API 3, revision 6>\n" + - "-- <NEW, pkg:SDK Platform Android android-2, API 2, revision 4>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "-- <INSTALLED, pkg:Android USB Driver, revision 4, updated by:Android USB Driver, revision 5>\n" + - "-- <NEW, pkg:Carrier Custom Rom, revision 1>\n" + - "PkgCategorySource <source=repo2 (2.example.com), #items=4>\n" + - "-- <NEW, pkg:The addon B from vendor 2, Android API 2, revision 9>\n" + - "-- <NEW, pkg:The addon C from vendor 2, Android API 2, revision 9>\n" + - "-- <INSTALLED, pkg:The addon A from vendor 1, Android API 1, revision 5, updated by:The addon A from vendor 1, Android API 1, revision 6>\n" + - "-- <INSTALLED, pkg:The addon D from vendor 1, Android API 1, revision 10, updated by:The addon D from vendor 1, Android API 1, revision 13>\n", - getTree(m, false /*displaySortByApi*/)); - - // Reloading the same thing should have no impact except for the update methods - // returning false when they don't change the current list. - m.updateStart(); - - assertFalse(m.updateSourcePackages(false /*sortByApi*/, null /*locals*/, new Package[] { - new MockToolPackage(src1, 10, 3), - new MockPlatformToolPackage(src1, 3), - new MockExtraPackage(src1, "android", "usb_driver", 4, 3), - // second update - p1 = new MockPlatformPackage(src1, 1, 2, 3), // API 1 - p3 = new MockPlatformPackage(src1, 3, 6, 3), - new MockPlatformPackage(src1, 3, 6, 3), // API 3 - new MockAddonPackage(src2, "addon A", p1, 5), - new MockAddonPackage(src2, "addon D", p1, 10), - })); - assertFalse(m.updateSourcePackages(false /*sortByApi*/, src1, new Package[] { - new MockToolPackage(src1, 10, 3), - new MockPlatformToolPackage(src1, 3), - new MockExtraPackage(src1, "carrier", "custom_rom", 1, 0), - new MockExtraPackage(src1, "android", "usb_driver", 5, 3), - // second update - p2 = new MockPlatformPackage(src1, 2, 4, 3), - })); - assertTrue(m.updateSourcePackages(false /*sortByApi*/, src2, new Package[] { - new MockAddonPackage(src2, "addon C", p2, 9), - new MockAddonPackage(src2, "addon A", p1, 6), - // the rev 7+8 will be ignored since there's a rev 9 coming after - new MockAddonPackage(src2, "addon B", p2, 7), - new MockAddonPackage(src2, "addon B", p2, 8), - new MockAddonPackage(src2, "addon B", p2, 9), - // 11+12 should be ignored updates, 13 will update 10 - new MockAddonPackage(src2, "addon D", p1, 10), - new MockAddonPackage(src2, "addon D", p1, 12), // note: 12 listed before 11 - new MockAddonPackage(src2, "addon D", p1, 11), - new MockAddonPackage(src2, "addon D", p1, 13), - })); - assertTrue(m.updateEnd(false /*sortByApi*/)); - - assertEquals( - "PkgCategorySource <source=repo1 (1.example.com), #items=7>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-3, API 3, revision 6>\n" + - "-- <NEW, pkg:SDK Platform Android android-2, API 2, revision 4>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "-- <INSTALLED, pkg:Android USB Driver, revision 4, updated by:Android USB Driver, revision 5>\n" + - "-- <NEW, pkg:Carrier Custom Rom, revision 1>\n" + - "PkgCategorySource <source=repo2 (2.example.com), #items=4>\n" + - "-- <NEW, pkg:The addon B from vendor 2, Android API 2, revision 9>\n" + - "-- <NEW, pkg:The addon C from vendor 2, Android API 2, revision 9>\n" + - "-- <INSTALLED, pkg:The addon A from vendor 1, Android API 1, revision 5, updated by:The addon A from vendor 1, Android API 1, revision 6>\n" + - "-- <INSTALLED, pkg:The addon D from vendor 1, Android API 1, revision 10, updated by:The addon D from vendor 1, Android API 1, revision 13>\n", - getTree(m, false /*displaySortByApi*/)); - } - - // ---- - - public void testIsFirstLoadComplete() { - // isFirstLoadComplete is a simple toggle that goes from true to false when read once - assertTrue(m.isFirstLoadComplete()); - assertFalse(m.isFirstLoadComplete()); - assertFalse(m.isFirstLoadComplete()); - } - - public void testCheckNewUpdateItems_NewOnly() { - // Populate the list with a few items and an update - SdkSource src1 = new SdkRepoSource("http://example.com/url", "repo1"); - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "has update", 1), - new MockEmptyPackage(src1, "no update", 4) - }); - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "has update", 2), - new MockEmptyPackage(src1, "new stuff", 3), - }); - m.updateEnd(true /*sortByApi*/); - // Nothing is checked at first - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=3>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'has update' rev=1, updated by:MockEmptyPackage 'has update' rev=2>\n" + - "-- <NEW, pkg:MockEmptyPackage 'new stuff' rev=3>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'no update' rev=4>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=3>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'has update' rev=1, updated by:MockEmptyPackage 'has update' rev=2>\n" + - "-- <NEW, pkg:MockEmptyPackage 'new stuff' rev=3>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'no update' rev=4>\n", - getTree(m, false /*displaySortByApi*/)); - - // Now request to check new items only - m.checkNewUpdateItems(true, false, false, SdkConstants.PLATFORM_LINUX); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=3>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'has update' rev=1, updated by:MockEmptyPackage 'has update' rev=2>\n" + - "-- < * NEW, pkg:MockEmptyPackage 'new stuff' rev=3>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'no update' rev=4>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=3>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'has update' rev=1, updated by:MockEmptyPackage 'has update' rev=2>\n" + - "-- < * NEW, pkg:MockEmptyPackage 'new stuff' rev=3>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'no update' rev=4>\n", - getTree(m, false /*displaySortByApi*/)); - } - - public void testCheckNewUpdateItems_UpdateOnly() { - // Populate the list with a few items and an update - SdkSource src1 = new SdkRepoSource("http://example.com/url", "repo1"); - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "has update", 1), - new MockEmptyPackage(src1, "no update", 4) - }); - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "has update", 2), - new MockEmptyPackage(src1, "new stuff", 3), - }); - m.updateEnd(true /*sortByApi*/); - // Nothing is checked at first - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=3>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'has update' rev=1, updated by:MockEmptyPackage 'has update' rev=2>\n" + - "-- <NEW, pkg:MockEmptyPackage 'new stuff' rev=3>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'no update' rev=4>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=3>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'has update' rev=1, updated by:MockEmptyPackage 'has update' rev=2>\n" + - "-- <NEW, pkg:MockEmptyPackage 'new stuff' rev=3>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'no update' rev=4>\n", - getTree(m, false /*displaySortByApi*/)); - - // Now request to check update items only - m.checkNewUpdateItems(false, true, false, SdkConstants.PLATFORM_LINUX); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=3>\n" + - "-- < * INSTALLED, pkg:MockEmptyPackage 'has update' rev=1, updated by:MockEmptyPackage 'has update' rev=2>\n" + - "-- <NEW, pkg:MockEmptyPackage 'new stuff' rev=3>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'no update' rev=4>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=3>\n" + - "-- < * INSTALLED, pkg:MockEmptyPackage 'has update' rev=1, updated by:MockEmptyPackage 'has update' rev=2>\n" + - "-- <NEW, pkg:MockEmptyPackage 'new stuff' rev=3>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'no update' rev=4>\n", - getTree(m, false /*displaySortByApi*/)); - } - - public void testCheckNewUpdateItems_SelectInitial() { - // Populate the list with typical items: tools, platforms tools, extras, 2 platforms. - // With nothing installed, this should pick the top platform and its system images - // (the mock platform claims to not have any included abi) - // It's ok not to select the tools, since they are a dependency of all platforms. - - SdkSource src1 = new SdkRepoSource("http://1.example.com/url1", "repo1"); - SdkSource src2 = new SdkRepoSource("http://2.example.com/url2", "repo2"); - - m.updateStart(); - MockPlatformPackage p1; - MockPlatformPackage p2; - - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockToolPackage(src1, 10, 3), - new MockPlatformToolPackage(src1, 3), - new MockExtraPackage(src1, "google", "usb_driver", 5, 3), - p1 = new MockPlatformPackage(src1, 1, 2, 3), // API 1 - p2 = new MockPlatformPackage(src1, 2, 4, 3), // API 2 - new MockSystemImagePackage(src1, p2, 1, "armeabi"), - new MockSystemImagePackage(src1, p2, 1, "x86"), - }); - m.updateSourcePackages(true /*sortByApi*/, src2, new Package[] { - new MockAddonPackage(src2, "addon A", p1, 5), - new MockAddonPackage(src2, "addon B", p2, 7), - new MockExtraPackage(src2, "carrier", "custom_rom", 1, 0), - }); - m.updateEnd(true /*sortByApi*/); - - m.checkNewUpdateItems(false, true, true, SdkConstants.PLATFORM_LINUX); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 10>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 3>\n" + - "PkgCategoryApi <API=API 2, label=Android android-2 (API 2), #items=4>\n" + - "-- < * NEW, pkg:SDK Platform Android android-2, API 2, revision 4>\n" + - "-- < * NEW, pkg:ARM EABI System Image, Android API 2, revision 1>\n" + - "-- < * NEW, pkg:Intel x86 Atom System Image, Android API 2, revision 1>\n" + - "-- < * NEW, pkg:The addon B from vendor 2, Android API 2, revision 7>\n" + - "PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=2>\n" + - "-- <NEW, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "-- <NEW, pkg:The addon A from vendor 1, Android API 1, revision 5>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" + - "-- <NEW, pkg:Carrier Custom Rom, revision 1>\n" + - "-- <NEW, pkg:Google USB Driver, revision 5>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (1.example.com), #items=7>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 10>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 3>\n" + - "-- < * NEW, pkg:SDK Platform Android android-2, API 2, revision 4>\n" + - "-- <NEW, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "-- < * NEW, pkg:ARM EABI System Image, Android API 2, revision 1>\n" + - "-- < * NEW, pkg:Intel x86 Atom System Image, Android API 2, revision 1>\n" + - "-- <NEW, pkg:Google USB Driver, revision 5>\n" + - "PkgCategorySource <source=repo2 (2.example.com), #items=3>\n" + - "-- < * NEW, pkg:The addon B from vendor 2, Android API 2, revision 7>\n" + - "-- <NEW, pkg:The addon A from vendor 1, Android API 1, revision 5>\n" + - "-- <NEW, pkg:Carrier Custom Rom, revision 1>\n", - getTree(m, false /*displaySortByApi*/)); - - // We don't install the USB driver by default on Mac or Linux, only on Windows - m.clear(); - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockExtraPackage(src1, "google", "usb_driver", 5, 3), - }); - m.updateEnd(true /*sortByApi*/); - m.checkNewUpdateItems(false, true, true, SdkConstants.PLATFORM_LINUX); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" + - "-- <NEW, pkg:Google USB Driver, revision 5>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (1.example.com), #items=1>\n" + - "-- <NEW, pkg:Google USB Driver, revision 5>\n", - getTree(m, false /*displaySortByApi*/)); - - m.clear(); - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockExtraPackage(src1, "google", "usb_driver", 5, 3), - }); - m.updateEnd(true /*sortByApi*/); - m.checkNewUpdateItems(false, true, true, SdkConstants.PLATFORM_DARWIN); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" + - "-- <NEW, pkg:Google USB Driver, revision 5>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (1.example.com), #items=1>\n" + - "-- <NEW, pkg:Google USB Driver, revision 5>\n", - getTree(m, false /*displaySortByApi*/)); - - m.clear(); - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockExtraPackage(src1, "google", "usb_driver", 5, 3), - }); - m.updateEnd(true /*sortByApi*/); - m.checkNewUpdateItems(false, true, true, SdkConstants.PLATFORM_WINDOWS); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" + - "-- < * NEW, pkg:Google USB Driver, revision 5>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (1.example.com), #items=1>\n" + - "-- < * NEW, pkg:Google USB Driver, revision 5>\n", - getTree(m, false /*displaySortByApi*/)); - - } - - public void testCheckUncheckAllItems() { - // Populate the list with a couple items and an update - SdkSource src1 = new SdkRepoSource("http://example.com/url", "repo1"); - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockEmptyPackage(src1, "type1", 1) - }); - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockEmptyPackage(src1, "type1", 2), - new MockEmptyPackage(src1, "type3", 3), - }); - m.updateEnd(true /*sortByApi*/); - // Nothing is checked at first - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n" + - "-- <NEW, pkg:MockEmptyPackage 'type3' rev=3>\n", - getTree(m, true /*displaySortByApi*/)); - - // Manually check the items in the sort-by-API case, but not the source - for (PkgItem item : m.getAllPkgItems(true /*byApi*/, false /*bySource*/)) { - item.setChecked(true); - } - - // by-api sort should be checked but not by source - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" + - "-- < * INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n" + - "-- < * NEW, pkg:MockEmptyPackage 'type3' rev=3>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=2>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n" + - "-- <NEW, pkg:MockEmptyPackage 'type3' rev=3>\n", - getTree(m, false /*displaySortByApi*/)); - - // now uncheck them all - m.uncheckAllItems(); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n" + - "-- <NEW, pkg:MockEmptyPackage 'type3' rev=3>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=2>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n" + - "-- <NEW, pkg:MockEmptyPackage 'type3' rev=3>\n", - getTree(m, false /*displaySortByApi*/)); - - // Manually check the items in both by-api and by-source - for (PkgItem item : m.getAllPkgItems(true /*byApi*/, true /*bySource*/)) { - item.setChecked(true); - } - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" + - "-- < * INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n" + - "-- < * NEW, pkg:MockEmptyPackage 'type3' rev=3>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=2>\n" + - "-- < * INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n" + - "-- < * NEW, pkg:MockEmptyPackage 'type3' rev=3>\n", - getTree(m, false /*displaySortByApi*/)); - - // now uncheck them all - m.uncheckAllItems(); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n" + - "-- <NEW, pkg:MockEmptyPackage 'type3' rev=3>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=2>\n" + - "-- <INSTALLED, pkg:MockEmptyPackage 'type1' rev=1, updated by:MockEmptyPackage 'type1' rev=2>\n" + - "-- <NEW, pkg:MockEmptyPackage 'type3' rev=3>\n", - getTree(m, false /*displaySortByApi*/)); - } - - // ---- - - public void testLocalIsNewer() { - // This tests an edge case that typically happens only during development where - // one would have a local package which revision number is larger than what the - // remove repositories can offer. In this case we don't want to offer the remote - // package as an "upgrade" nor as a downgrade. - - // Populate the list with local revisions 5 and lower remote revisions 3 - SdkSource src1 = new SdkRepoSource("http://example.com/url", "repo1"); - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockToolPackage( src1, 5, 5), - new MockPlatformToolPackage(src1, 5), - }); - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockToolPackage( src1, 3, 3), - new MockPlatformToolPackage(src1, 3), - }); - m.updateEnd(true /*sortByApi*/); - - // The remote packages in rev 3 are hidden by the local packages in rev 5 - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 5>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 5>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=2>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 5>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 5>\n", - getTree(m, false /*displaySortByApi*/)); - } - - public void testSourceDups() { - // This tests an edge case were 2 remote repositories are giving the - // same kind of packages. In rev 14, we didn't want to merge them together - // unless they had the same hostname. In rev 15, we now treat them the same. - - // repo1, 2 and 3 have the same hostname so redundancy is ok - SdkSource src1 = new SdkRepoSource("http://example.com/url1", "repo1"); - SdkSource src2 = new SdkRepoSource("http://example.com/url2", "repo2"); - SdkSource src3 = new SdkRepoSource("http://example.com/url3", "repo3"); - // repo4 has a different hostname but as of rev 15, the packages will be merged together. - SdkSource src4 = new SdkRepoSource("http://4.example.com/url4", "repo4"); - MockPlatformPackage p1 = null; - - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockToolPackage( src1, 3, 3), - new MockPlatformToolPackage(src1, 3), - p1 = new MockPlatformPackage(src1, 1, 2, 3), // API 1 - }); - m.updateSourcePackages(true /*sortByApi*/, src2, new Package[] { - new MockAddonPackage(src2, "addon A", p1, 5), - new MockAddonPackage(src2, "addon B", p1, 6), - }); - m.updateSourcePackages(true /*sortByApi*/, src3, new Package[] { - new MockAddonPackage(src3, "addon A", p1, 5), // same as addon A rev 5 from src2 - new MockAddonPackage(src3, "addon B", p1, 7), // upgrades addon B rev 6 from src2 - }); - m.updateSourcePackages(true /*sortByApi*/, src4, new Package[] { - new MockAddonPackage(src4, "addon A", p1, 5), // same as addon A rev 5 from src2 - new MockAddonPackage(src4, "addon B", p1, 7), // upgrades addon B rev 6 from src2 - }); - m.updateEnd(true /*sortByApi*/); - - // The remote packages in rev 3 are hidden by the local packages in rev 5. - // When sorting by API, the user can tell where the packages come from by looking - // at the UI tooltip on the packages. - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 3>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" + - "PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=3>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "-- <NEW, pkg:The addon A from vendor 1, Android API 1, revision 5>\n" + // from src2+3+4 - "-- <NEW, pkg:The addon B from vendor 1, Android API 1, revision 7>\n" + // from src3+4 - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n", - getTree(m, true /*displaySortByApi*/)); - // When sorting by source, the src4 source is listed, however since its - // packages are the same as the ones from src2 or src3 the packages themselves - // are not shown. - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=3>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 3>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "PkgCategorySource <source=repo2 (example.com), #items=1>\n" + - "-- <NEW, pkg:The addon A from vendor 1, Android API 1, revision 5>\n" + // from src2+3+4 - "PkgCategorySource <source=repo3 (example.com), #items=1>\n" + - "-- <NEW, pkg:The addon B from vendor 1, Android API 1, revision 7>\n" + // from src3+4 - "PkgCategorySource <source=repo4 (4.example.com), #items=0>\n", - getTree(m, false /*displaySortByApi*/)); - } - - public void testRenamedExtraPackage() { - // Starting with schemas repo v5 and addon v3, an extra package can be renamed - // using the "old-paths" attribute. This test checks that the diff logic will - // match an old extra and its new name together. - - // First scenario: local pkg "old_path1" and remote pkg "new_path2". - // Since the new package does not provide an old_paths attribute, the - // new package is not treated as an update. - - SdkSource src1 = new SdkRepoSource("http://example.com/url1", "repo1"); - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockExtraPackage(src1, "vendor1", "old_path1", 1, 1), - }); - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockExtraPackage(src1, "vendor1", "new_path2", 2, 1), - }); - m.updateEnd(true /*sortByApi*/); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" + - "-- <NEW, pkg:Vendor1 New Path2, revision 2>\n" + - "-- <INSTALLED, pkg:Vendor1 Old Path1, revision 1>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=2>\n" + - "-- <NEW, pkg:Vendor1 New Path2, revision 2>\n" + - "-- <INSTALLED, pkg:Vendor1 Old Path1, revision 1>\n", - getTree(m, false /*displaySortByApi*/)); - - // Now, start again, but this time the new package uses the old-path attribute - Properties props = new Properties(); - props.setProperty(PkgProps.EXTRA_OLD_PATHS, "old_path1;oldpath2"); - m.clear(); - - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockExtraPackage(src1, "vendor1", "old_path1", 1, 1), - }); - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockExtraPackage(src1, props, "vendor1", "new_path2", 2), - }); - m.updateEnd(true /*sortByApi*/); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" + - "-- <INSTALLED, pkg:Vendor1 Old Path1, revision 1, updated by:Vendor1 New Path2, revision 2>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (example.com), #items=1>\n" + - "-- <INSTALLED, pkg:Vendor1 Old Path1, revision 1, updated by:Vendor1 New Path2, revision 2>\n", - getTree(m, false /*displaySortByApi*/)); - } - - public void testBrokenAddon() { - SdkSource src1 = new SdkRepoSource("http://1.example.com/url1", "repo1"); - SdkSource src2 = new SdkRepoSource("http://2.example.com/url2", "repo2"); - - MockPlatformPackage p1 = null; - MockAddonPackage a1 = null; - - // User has a platform + addon locally installed - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - p1 = new MockPlatformPackage(src1, 1, 2, 3), // API 1 - a1 = new MockAddonPackage(src2, "addon A", p1, 4), - }); - m.updateSourcePackages(true /*sortByApi*/, src1 /*locals*/, new Package[] { - p1 - }); - m.updateSourcePackages(true /*sortByApi*/, src2 /*locals*/, new Package[] { - a1 - }); - m.updateEnd(true /*sortByApi*/); - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=2>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "-- <INSTALLED, pkg:The addon A from vendor 1, Android API 1, revision 4>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (1.example.com), #items=1>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "PkgCategorySource <source=repo2 (2.example.com), #items=1>\n" + - "-- <INSTALLED, pkg:The addon A from vendor 1, Android API 1, revision 4>\n", - getTree(m, false /*displaySortByApi*/)); - - // Now user deletes the platform on disk and reload. - // The local package parser will only find a broken addon. - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockBrokenPackage(BrokenPackage.MIN_API_LEVEL_NOT_SPECIFIED, 1), - }); - m.updateSourcePackages(true /*sortByApi*/, src1 /*locals*/, new Package[] { - new MockPlatformPackage(src1, 1, 2, 3) - }); - m.updateSourcePackages(true /*sortByApi*/, src2 /*locals*/, new Package[] { - new MockAddonPackage(src2, "addon A", p1, 4) - }); - m.updateEnd(true /*sortByApi*/); - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=2>\n" + - "-- <NEW, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "-- <NEW, pkg:The addon A from vendor 1, Android API 1, revision 4>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" + - "-- <INSTALLED, pkg:Broken package for API 1>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (1.example.com), #items=1>\n" + - "-- <NEW, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "PkgCategorySource <source=repo2 (2.example.com), #items=1>\n" + - "-- <NEW, pkg:The addon A from vendor 1, Android API 1, revision 4>\n" + - "PkgCategorySource <source=Local Packages (no.source), #items=1>\n" + - "-- <INSTALLED, pkg:Broken package for API 1>\n", - getTree(m, false /*displaySortByApi*/)); - - // Now user restores the missing platform on disk. - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - p1 = new MockPlatformPackage(src1, 1, 2, 3), // API 1 - a1 = new MockAddonPackage(src2, "addon A", p1, 4), - }); - m.updateSourcePackages(true /*sortByApi*/, src1 /*locals*/, new Package[] { - p1 - }); - m.updateSourcePackages(true /*sortByApi*/, src2 /*locals*/, new Package[] { - a1 - }); - m.updateEnd(true /*sortByApi*/); - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" + - "PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=2>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "-- <INSTALLED, pkg:The addon A from vendor 1, Android API 1, revision 4>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (1.example.com), #items=1>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "PkgCategorySource <source=repo2 (2.example.com), #items=1>\n" + - "-- <INSTALLED, pkg:The addon A from vendor 1, Android API 1, revision 4>\n", - getTree(m, false /*displaySortByApi*/)); - } - - public void testToolsUpdate() { - SdkSource src1 = new SdkRepoSource("http://1.example.com/url1", "repo1"); - SdkSource src2 = new SdkRepoSource("http://2.example.com/url2", "repo2"); - MockPlatformPackage p1; - - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockToolPackage(3, 3), // tool package has no source defined - new MockPlatformToolPackage(src1, 3), - p1 = new MockPlatformPackage(src1, 1, 2, 3), // API 1 - }); - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockToolPackage(src1, 4, 4), - new MockPlatformToolPackage(src1, 4), - }); - m.updateSourcePackages(true /*sortByApi*/, src2, new Package[] { - new MockAddonPackage(src2, "addon A", p1, 5), - new MockAddonPackage(src2, "addon B", p1, 6), - }); - m.updateEnd(true /*sortByApi*/); - - // The remote packages in rev 3 are hidden by the local packages in rev 5 - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 3, updated by:Android SDK Tools, revision 4>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3, updated by:Android SDK Platform-tools, revision 4>\n" + - "PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=3>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "-- <NEW, pkg:The addon A from vendor 1, Android API 1, revision 5>\n" + - "-- <NEW, pkg:The addon B from vendor 1, Android API 1, revision 6>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=Local Packages (no.source), #items=1>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 3, updated by:Android SDK Tools, revision 4>\n" + - "PkgCategorySource <source=repo1 (1.example.com), #items=2>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3, updated by:Android SDK Platform-tools, revision 4>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "PkgCategorySource <source=repo2 (2.example.com), #items=2>\n" + - "-- <NEW, pkg:The addon A from vendor 1, Android API 1, revision 5>\n" + - "-- <NEW, pkg:The addon B from vendor 1, Android API 1, revision 6>\n", - getTree(m, false /*displaySortByApi*/)); - } - - public void testToolsMinorUpdate() { - // Test: Check a minor revision updates an installed major revision. - - SdkSource src1 = new SdkRepoSource("http://1.example.com/url1", "repo1"); - - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockToolPackage(3, 3), // Tools 3.0.0 - new MockPlatformToolPackage(src1, 3), - }); - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockToolPackage(src1, new FullRevision(3, 0, 1), 3), // Tools 3.0.1 - }); - m.updateEnd(true /*sortByApi*/); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 3, updated by:Android SDK Tools, revision 3.0.1>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=Local Packages (no.source), #items=1>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 3, updated by:Android SDK Tools, revision 3.0.1>\n" + - "PkgCategorySource <source=repo1 (1.example.com), #items=1>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n", - getTree(m, false /*displaySortByApi*/)); - } - - public void testToolsPreviewsDisabled() { - // Test: No local tools installed. The remote server has both tools and platforms - // in release and RC versions. However the settings "enable previews" is disabled - // (which is the default) so the previews are not actually loaded from the server. - - SdkSource src1 = new SdkRepoSource("http://1.example.com/url1", "repo1"); - - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockToolPackage(src1, new FullRevision(2, 0, 0), 3), // Tools 2 - new MockToolPackage(src1, new FullRevision(4, 0, 0, 1), 3), // Tools 4 rc1 - new MockPlatformToolPackage(src1, new FullRevision(3, 0, 0)), // Plat-T 3 - new MockPlatformToolPackage(src1, new FullRevision(5, 0, 0, 1)), // Plat-T 5 rc1 - }); - m.updateEnd(true /*sortByApi*/); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 2>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 3>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (1.example.com), #items=2>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 2>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 3>\n", - getTree(m, false /*displaySortByApi*/)); - } - - public void testToolsPreviews() { - // Test: No local tools installed. The remote server has both tools and platforms - // in release and RC versions. - - // Enable previews in the settings - u.overrideSetting(ISettingsPage.KEY_ENABLE_PREVIEWS, true); - - SdkSource src1 = new SdkRepoSource("http://1.example.com/url1", "repo1"); - - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockToolPackage(src1, new FullRevision(2, 0, 0), 3), // Tools 2 - new MockToolPackage(src1, new FullRevision(4, 0, 0, 1), 3), // Tools 4 rc1 - new MockPlatformToolPackage(src1, new FullRevision(3, 0, 0)), // Plat-T 3 - new MockPlatformToolPackage(src1, new FullRevision(5, 0, 0, 1)), // Plat-T 5 rc1 - }); - m.updateEnd(true /*sortByApi*/); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 2>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 3>\n" + - "PkgCategoryApi <API=TOOLS-PREVIEW, label=Tools (Preview Channel), #items=2>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 4 rc1>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 5 rc1>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (1.example.com), #items=4>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 2>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 4 rc1>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 3>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 5 rc1>\n", - getTree(m, false /*displaySortByApi*/)); - } - - public void testPreviewUpdateInstalledRelease() { - // Test: Local release Tools 3.0.0 installed, server has both a release 3.0.1 available - // and a Tools Preview 4.0.0 rc1 available. - // => v3 is updated by 3.0.1 - // => v4.0.0rc1 does not update 3.0.0, instead it's a separate download. - - // Enable previews in the settings - u.overrideSetting(ISettingsPage.KEY_ENABLE_PREVIEWS, true); - - SdkSource src1 = new SdkRepoSource("http://1.example.com/url1", "repo1"); - - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockToolPackage(3, 3), // tool package has no source defined - new MockPlatformToolPackage(src1, 3), - new MockPlatformPackage(src1, 1, 2, 3), // API 1 - }); - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockToolPackage(src1, 3, 3), // Tools 3 - new MockToolPackage(src1, new FullRevision(3, 0, 1), 3), // Tools 3.0.1 - new MockToolPackage(src1, new FullRevision(4, 0, 0, 1), 3), // Tools 4 rc1 - new MockPlatformToolPackage(src1, new FullRevision(3, 0, 1)), // PT 3.0.1 - new MockPlatformToolPackage(src1, new FullRevision(4, 0, 0, 1)), // PT 4 rc1 - }); - m.updateEnd(true /*sortByApi*/); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 3, updated by:Android SDK Tools, revision 3.0.1>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3, updated by:Android SDK Platform-tools, revision 3.0.1>\n" + - "PkgCategoryApi <API=TOOLS-PREVIEW, label=Tools (Preview Channel), #items=2>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 4 rc1>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 4 rc1>\n" + - "PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=1>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=Local Packages (no.source), #items=1>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 3, updated by:Android SDK Tools, revision 3.0.1>\n" + - "PkgCategorySource <source=repo1 (1.example.com), #items=4>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 4 rc1>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3, updated by:Android SDK Platform-tools, revision 3.0.1>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 4 rc1>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n", - getTree(m, false /*displaySortByApi*/)); - - // Now request to check new items and updates: - // Tools 4 rc1 is greater than the installed Tools 3, but it's a preview so we will NOT - // auto-select it by default even though we requested to select "NEW" packages. We - // want the user to manually opt-in into the rc/preview package. - // However Tools 3 has a 3.0.1 update that we'll auto-select. - m.checkNewUpdateItems(true, true, false, SdkConstants.PLATFORM_LINUX); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- < * INSTALLED, pkg:Android SDK Tools, revision 3, updated by:Android SDK Tools, revision 3.0.1>\n" + - "-- < * INSTALLED, pkg:Android SDK Platform-tools, revision 3, updated by:Android SDK Platform-tools, revision 3.0.1>\n" + - "PkgCategoryApi <API=TOOLS-PREVIEW, label=Tools (Preview Channel), #items=2>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 4 rc1>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 4 rc1>\n" + - "PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=1>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=Local Packages (no.source), #items=1>\n" + - "-- < * INSTALLED, pkg:Android SDK Tools, revision 3, updated by:Android SDK Tools, revision 3.0.1>\n" + - "PkgCategorySource <source=repo1 (1.example.com), #items=4>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 4 rc1>\n" + - "-- < * INSTALLED, pkg:Android SDK Platform-tools, revision 3, updated by:Android SDK Platform-tools, revision 3.0.1>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 4 rc1>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n", - getTree(m, false /*displaySortByApi*/)); - - } - - public void testPreviewUpdateInstalledPreview() { - // Test: Local preview Tools 3.0.1rc1 installed, server has both a release 3.0.0 available - // and a Tools Preview 3.0.1 rc2 available. - // => Installed 3.0.1rc1 can be updated by 3.0.1rc2 - // => There's a separate "new" download for 3.0.0, not installed and NOT updating 3.0.1rc1. - - // Enable previews in the settings - u.overrideSetting(ISettingsPage.KEY_ENABLE_PREVIEWS, true); - - SdkSource src1 = new SdkRepoSource("http://1.example.com/url1", "repo1"); - - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockToolPackage(src1, new FullRevision(3, 0, 1, 1), 4), // T 3.0.1rc1 - new MockPlatformToolPackage(src1, new FullRevision(4, 0, 1, 1)), // PT 4.0.1rc1 - new MockPlatformPackage(src1, 1, 2, 3), // API 1 - }); - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockToolPackage(src1, new FullRevision(3, 0, 0), 4), // T 3.0.0 - new MockToolPackage(src1, new FullRevision(3, 0, 1, 2), 4), // T 3.0.1rc2 - new MockPlatformToolPackage(src1, new FullRevision(4, 0, 0)), // PT 4.0.0 - new MockPlatformToolPackage(src1, new FullRevision(4, 0, 1, 2)), // PT 4.0.1 rc2 - }); - m.updateEnd(true /*sortByApi*/); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 3>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 4>\n" + - "PkgCategoryApi <API=TOOLS-PREVIEW, label=Tools (Preview Channel), #items=2>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 3.0.1 rc1, updated by:Android SDK Tools, revision 3.0.1 rc2>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 4.0.1 rc1, updated by:Android SDK Platform-tools, revision 4.0.1 rc2>\n" + - "PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=1>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (1.example.com), #items=5>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 3>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 3.0.1 rc1, updated by:Android SDK Tools, revision 3.0.1 rc2>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 4>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 4.0.1 rc1, updated by:Android SDK Platform-tools, revision 4.0.1 rc2>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n", - getTree(m, false /*displaySortByApi*/)); - - // Auto select new and update items. In this case: - // - the previews have updates available. - // - we're not selecting the non-installed "3.0" version that is older than the - // currently installed "3.0.1rc1" version since that would be a downgrade. - m.checkNewUpdateItems(true, true, false, SdkConstants.PLATFORM_LINUX); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 3>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 4>\n" + - "PkgCategoryApi <API=TOOLS-PREVIEW, label=Tools (Preview Channel), #items=2>\n" + - "-- < * INSTALLED, pkg:Android SDK Tools, revision 3.0.1 rc1, updated by:Android SDK Tools, revision 3.0.1 rc2>\n" + - "-- < * INSTALLED, pkg:Android SDK Platform-tools, revision 4.0.1 rc1, updated by:Android SDK Platform-tools, revision 4.0.1 rc2>\n" + - "PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=1>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (1.example.com), #items=5>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 3>\n" + - "-- < * INSTALLED, pkg:Android SDK Tools, revision 3.0.1 rc1, updated by:Android SDK Tools, revision 3.0.1 rc2>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 4>\n" + - "-- < * INSTALLED, pkg:Android SDK Platform-tools, revision 4.0.1 rc1, updated by:Android SDK Platform-tools, revision 4.0.1 rc2>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n", - getTree(m, false /*displaySortByApi*/)); - - // ----- - - // Now simulate that the server has a final package (3.0.1) to replace the - // installed 3.0.1rc1 package. It's not installed yet, just available. - // - A new 3.0.1 will be available. - // - The server no longer lists the RC since there's a final package, yet it is - // still locally installed. - // - The 3.0.1 rc1 is not listed as having an update, since we treat the previews - // separately. TODO: consider having the 3.0.1 show up as both a new item /and/ - // as an update to the 3.0.1rc1. That may have some other side effects. - - m.uncheckAllItems(); - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockToolPackage(src1, new FullRevision(3, 0, 1, 1), 4), // T 3.0.1rc1 - new MockPlatformToolPackage(src1, new FullRevision(4, 0, 1, 1)), // PT 4.0.1rc1 - new MockPlatformPackage(src1, 1, 2, 3), // API 1 - }); - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockToolPackage(src1, new FullRevision(3, 0, 1), 4), // T 3.0.1 - new MockPlatformToolPackage(src1, new FullRevision(4, 0, 1)), // PT 4.0.1 - }); - m.updateEnd(true /*sortByApi*/); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 3.0.1>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 4.0.1>\n" + - "PkgCategoryApi <API=TOOLS-PREVIEW, label=Tools (Preview Channel), #items=2>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 3.0.1 rc1>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 4.0.1 rc1>\n" + - "PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=1>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (1.example.com), #items=5>\n" + - "-- <NEW, pkg:Android SDK Tools, revision 3.0.1>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 3.0.1 rc1>\n" + - "-- <NEW, pkg:Android SDK Platform-tools, revision 4.0.1>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 4.0.1 rc1>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n", - getTree(m, false /*displaySortByApi*/)); - - // Auto select new and update items. In this case the new items are considered - // updates and yet new at the same time. - // Test by selecting new items only: - m.checkNewUpdateItems(true, false, false, SdkConstants.PLATFORM_LINUX); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- < * NEW, pkg:Android SDK Tools, revision 3.0.1>\n" + - "-- < * NEW, pkg:Android SDK Platform-tools, revision 4.0.1>\n" + - "PkgCategoryApi <API=TOOLS-PREVIEW, label=Tools (Preview Channel), #items=2>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 3.0.1 rc1>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 4.0.1 rc1>\n" + - "PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=1>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n", - getTree(m, true /*displaySortByApi*/)); - - // Test by selecting update items only: - m.uncheckAllItems(); - m.checkNewUpdateItems(false, true, false, SdkConstants.PLATFORM_LINUX); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- < * NEW, pkg:Android SDK Tools, revision 3.0.1>\n" + - "-- < * NEW, pkg:Android SDK Platform-tools, revision 4.0.1>\n" + - "PkgCategoryApi <API=TOOLS-PREVIEW, label=Tools (Preview Channel), #items=2>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 3.0.1 rc1>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 4.0.1 rc1>\n" + - "PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=1>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n", - getTree(m, true /*displaySortByApi*/)); - - - // ----- - - // Now simulate that the user has installed the final package (3.0.1) to replace the - // installed 3.0.1rc1 package. - // - The 3.0.1 is installed. - // - The 3.0.1 rc1 isn't listed anymore by the server. - - m.uncheckAllItems(); - m.updateStart(); - m.updateSourcePackages(true /*sortByApi*/, null /*locals*/, new Package[] { - new MockToolPackage(src1, new FullRevision(3, 0, 1), 4), // T 3.0.1 - new MockPlatformToolPackage(src1, new FullRevision(4, 0, 1)), // PT 4.0.1 - new MockPlatformPackage(src1, 1, 2, 3), // API 1 - }); - m.updateSourcePackages(true /*sortByApi*/, src1, new Package[] { - new MockToolPackage(src1, new FullRevision(3, 0, 1), 4), // T 3.0.1 - new MockPlatformToolPackage(src1, new FullRevision(4, 0, 1)), // PT 4.0.1 - }); - m.updateEnd(true /*sortByApi*/); - - assertEquals( - "PkgCategoryApi <API=TOOLS, label=Tools, #items=2>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 3.0.1>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 4.0.1>\n" + - "PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=1>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" + - "PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n", - getTree(m, true /*displaySortByApi*/)); - assertEquals( - "PkgCategorySource <source=repo1 (1.example.com), #items=3>\n" + - "-- <INSTALLED, pkg:Android SDK Tools, revision 3.0.1>\n" + - "-- <INSTALLED, pkg:Android SDK Platform-tools, revision 4.0.1>\n" + - "-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n", - getTree(m, false /*displaySortByApi*/)); - } - - - - // ---- - - /** - * Simulates the display we would have in the Packages Tree. - * This always depends on mCurrentCategories like the tree does. - * The display format is something like: - * <pre> - * PkgCategory <description> - * -- <PkgItem description> - * </pre> - */ - public String getTree(PackagesDiffLogic l, boolean displaySortByApi) { - StringBuilder sb = new StringBuilder(); - - for (PkgCategory cat : m.getCategories(displaySortByApi)) { - sb.append(cat.toString()).append('\n'); - for (PkgItem item : cat.getItems()) { - sb.append("-- ").append(item.toString()).append('\n'); - } - } - - return sb.toString(); - } -} diff --git a/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/ui/MockPackagesPageImpl.java b/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/ui/MockPackagesPageImpl.java deleted file mode 100755 index 04b3027..0000000 --- a/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/ui/MockPackagesPageImpl.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (C) 2012 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.repository.ui; - -import com.android.sdklib.internal.repository.DownloadCache; -import com.android.sdklib.internal.repository.DownloadCache.Strategy; -import com.android.sdklib.util.SparseIntArray; -import com.android.sdkuilib.internal.repository.MockDownloadCache; -import com.android.sdkuilib.internal.repository.UpdaterData; -import com.android.sdkuilib.internal.repository.core.PackageLoader; -import com.android.sdkuilib.internal.repository.core.PkgCategory; -import com.android.sdkuilib.internal.repository.core.PkgContentProvider; - -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.swt.graphics.Font; - -import java.util.ArrayList; -import java.util.List; - -public class MockPackagesPageImpl extends PackagesPageImpl { - - public MockPackagesPageImpl(UpdaterData updaterData) { - super(updaterData); - } - - /** UI is never disposed in the unit test. */ - @Override - protected boolean isUiDisposed() { - return false; - } - - /** Sync exec always executes immediately in the unit test, no threading is used. */ - @Override - protected void syncExec(Runnable runnable) { - runnable.run(); - } - - @Override - protected void syncViewerSelection() { - // No-op. There is no real tree viewer to synchronize. - } - - private MockTreeViewer mTreeViewer; - - @Override - void postCreate() { - mTreeViewer = new MockTreeViewer(); - setITreeViewer(mTreeViewer); - - setIColumns(new MockTreeColumn(mTreeViewer), // columnName - new MockTreeColumn(mTreeViewer), // columnApi - new MockTreeColumn(mTreeViewer), // columnRevision - new MockTreeColumn(mTreeViewer)); // columnStatus - - super.postCreate(); - } - - @Override - protected void refreshViewerInput() { - super.setViewerInput(); - } - - @Override - protected boolean isSortByApi() { - return true; - } - - @Override - protected Font getTreeFontItalic() { - return null; - } - - @Override - protected void loadPackages(boolean useLocalCache, boolean overrideExisting) { - super.loadPackagesImpl(useLocalCache, overrideExisting); - } - - /** - * In this mock version, we use the default {@link PackageLoader} which will - * use the {@link DownloadCache} from the {@link UpdaterData}. This should be - * the mock download cache, in which case we change the strategy at run-time - * to set it to only-cache on the first manager update. - */ - @Override - protected PackageLoader getPackageLoader(boolean useLocalCache) { - DownloadCache dc = mUpdaterData.getDownloadCache(); - assert dc instanceof MockDownloadCache; - if (dc instanceof MockDownloadCache) { - ((MockDownloadCache) dc).overrideStrategy(useLocalCache ? Strategy.ONLY_CACHE : null); - } - return mUpdaterData.getPackageLoader(); - } - - /** - * Get a dump-out of the tree in a format suitable for unit testing. - */ - public String getMockTreeDisplay() throws Exception { - return mTreeViewer.getTreeDisplay(); - } - - private static class MockTreeViewer implements PackagesPageImpl.ICheckboxTreeViewer { - private final SparseIntArray mWidths = new SparseIntArray(); - private final List<MockTreeColumn> mColumns = new ArrayList<MockTreeColumn>(); - private List<PkgCategory> mInput; - private PkgContentProvider mPkgContentProvider; - private String mLastRefresh; - private static final String SPACE = " "; - - @Override - public void setInput(List<PkgCategory> input) { - mInput = input; - refresh(); - } - - @Override - public Object getInput() { - return mInput; - } - - @Override - public void setContentProvider(PkgContentProvider pkgContentProvider) { - mPkgContentProvider = pkgContentProvider; - } - - @Override - public void refresh() { - // Recompute the display of the tree - StringBuilder sb = new StringBuilder(); - boolean widthChanged = false; - - for (int render = 0; render < (widthChanged ? 2 : 1); render++) { - widthChanged = false; - sb.setLength(0); - for (Object cat : mPkgContentProvider.getElements(mInput)) { - if (cat == null) { - continue; - } - - if (sb.length() > 0) { - sb.append('\n'); - } - - widthChanged |= rowAsString(cat, sb, 3); - - Object[] children = mPkgContentProvider.getElements(cat); - if (children == null) { - continue; - } - for (Object child : children) { - sb.append("\n L_"); - widthChanged |= rowAsString(child, sb, 0); - } - } - } - - mLastRefresh = sb.toString(); - } - - boolean rowAsString(Object element, StringBuilder sb, int space) { - boolean widthChanged = false; - sb.append("[] "); - for (int col = 0; col < mColumns.size(); col++) { - if (col > 0) { - sb.append(" | "); - } - String t = mColumns.get(col).getLabelProvider().getText(element); - if (t == null) { - t = "(null)"; - } - int len = t.length(); - int w = mWidths.get(col); - if (len > w) { - widthChanged = true; - mWidths.put(col, len); - w = len; - } - String pad = len >= w ? "" : SPACE.substring(SPACE.length() - w + len); - if (col == 0 && space > 0) { - sb.append(SPACE.substring(SPACE.length() - space)); - } - if (col >= 1 && col <= 2) { - sb.append(pad); - } - sb.append(t); - if (col == 0 || col > 2) { - sb.append(pad); - } - } - return widthChanged; - } - - @Override - public Object[] getCheckedElements() { - return null; - } - - public void addColumn(MockTreeColumn mockTreeColumn) { - mColumns.add(mockTreeColumn); - } - - public String getTreeDisplay() { - return mLastRefresh; - } - } - - private static class MockTreeColumn implements PackagesPageImpl.ITreeViewerColumn { - private ColumnLabelProvider mLabelProvider; - - public MockTreeColumn(MockTreeViewer treeViewer) { - treeViewer.addColumn(this); - } - - @Override - public void setLabelProvider(ColumnLabelProvider labelProvider) { - mLabelProvider = labelProvider; - } - - public ColumnLabelProvider getLabelProvider() { - return mLabelProvider; - } - } -} diff --git a/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/ui/SdkManagerUpgradeTest.java b/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/ui/SdkManagerUpgradeTest.java deleted file mode 100755 index 00d9684..0000000 --- a/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/ui/SdkManagerUpgradeTest.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2012 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.repository.ui; - -import com.android.sdklib.SdkManager; -import com.android.sdklib.SdkManagerTestCase; -import com.android.sdklib.repository.SdkRepoConstants; -import com.android.sdkuilib.internal.repository.MockDownloadCache; -import com.android.sdkuilib.internal.repository.MockUpdaterData; - -import java.util.Arrays; - -public class SdkManagerUpgradeTest extends SdkManagerTestCase { - - @Override - public void setUp() throws Exception { - super.setUp(); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - } - - /** - * Create a mock page and list the current SDK state - */ - public void testPackagesPage1() throws Exception { - SdkManager sdkman = getSdkManager(); - - MockUpdaterData updaterData = new MockUpdaterData(sdkman); - MockDownloadCache cache = (MockDownloadCache) updaterData.getDownloadCache(); - updaterData.setupDefaultSources(); - - MockPackagesPageImpl pageImpl = new MockPackagesPageImpl(updaterData); - pageImpl.postCreate(); - pageImpl.performFirstLoad(); - - // We have no network access possible and no mock download cache items. - // The only thing visible in the display are the local packages as set by - // the fake locally-installed SDK. - String actual = pageImpl.getMockTreeDisplay(); - assertEquals( - "[] Tools | | | \n" + - " L_[] Android SDK Tools | | 0 | Installed\n" + - "[] Android 0.0 (API 0) | | | \n" + - " L_[] SDK Platform | | 1 | Installed\n" + - " L_[] Sources for Android SDK | | 0 | Installed\n" + - "[] Extras | | | ", - actual); - - assertEquals( - "[]", // there are no direct downloads till we try to install. - Arrays.toString(cache.getDirectHits())); - assertEquals( - "[<https://dl-ssl.google.com/android/repository/addons_list-1.xml : 1>, " + - "<https://dl-ssl.google.com/android/repository/addons_list-2.xml : 1>, " + - "<https://dl-ssl.google.com/android/repository/repository-5.xml : 2>, " + - "<https://dl-ssl.google.com/android/repository/repository-6.xml : 2>, " + - "<https://dl-ssl.google.com/android/repository/repository-7.xml : 2>, " + - "<https://dl-ssl.google.com/android/repository/repository.xml : 2>]", - Arrays.toString(cache.getCachedHits())); - - - // Now prepare a tools update on the server and reload - setupToolsXml1(cache); - cache.clearDirectHits(); - cache.clearCachedHits(); - pageImpl.fullReload(); - - actual = pageImpl.getMockTreeDisplay(); - assertEquals( - "[] Tools | | | \n" + - " L_[] Android SDK Tools | | 0 | Update available: rev. 20.0.3\n" + - " L_[] Android SDK Platform-tools | | 14 | Not installed \n" + - "[] Android 0.0 (API 0) | | | \n" + - " L_[] SDK Platform | | 1 | Installed \n" + - " L_[] Sources for Android SDK | | 0 | Installed \n" + - "[] Extras | | | ", - actual); - - assertEquals( - "[]", // there are no direct downloads till we try to install. - Arrays.toString(cache.getDirectHits())); - assertEquals( - "[<https://dl-ssl.google.com/android/repository/repository-5.xml : 1>, " + - "<https://dl-ssl.google.com/android/repository/repository-6.xml : 1>, " + - "<https://dl-ssl.google.com/android/repository/repository-7.xml : 1>, " + - "<https://dl-ssl.google.com/android/repository/repository.xml : 1>]", - Arrays.toString(cache.getCachedHits())); - - - // We should get the same display if we restart the manager page from scratch - // (e.g. simulate a first load) - - cache.clearDirectHits(); - cache.clearCachedHits(); - pageImpl = new MockPackagesPageImpl(updaterData); - pageImpl.postCreate(); - pageImpl.performFirstLoad(); - - actual = pageImpl.getMockTreeDisplay(); - assertEquals( - "[] Tools | | | \n" + - " L_[] Android SDK Tools | | 0 | Update available: rev. 20.0.3\n" + - " L_[] Android SDK Platform-tools | | 14 | Not installed \n" + - "[] Android 0.0 (API 0) | | | \n" + - " L_[] SDK Platform | | 1 | Installed \n" + - " L_[] Sources for Android SDK | | 0 | Installed \n" + - "[] Extras | | | ", - actual); - - assertEquals( - "[]", // there are no direct downloads till we try to install. - Arrays.toString(cache.getDirectHits())); - assertEquals( - "[<https://dl-ssl.google.com/android/repository/repository-5.xml : 1>, " + - "<https://dl-ssl.google.com/android/repository/repository-6.xml : 1>, " + - "<https://dl-ssl.google.com/android/repository/repository-7.xml : 1>, " + - "<https://dl-ssl.google.com/android/repository/repository.xml : 1>]", - Arrays.toString(cache.getCachedHits())); - } - - private void setupToolsXml1(MockDownloadCache cache) throws Exception { - String repoXml = - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + - "<sdk:sdk-repository xmlns:sdk=\"http://schemas.android.com/sdk/android/repository/7\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" + - "<sdk:license id=\"android-sdk-license\" type=\"text\">Blah blah blah.</sdk:license>\n" + - "\n" + - "<sdk:platform-tool>\n" + - " <sdk:revision>\n" + - " <sdk:major>14</sdk:major>\n" + - " </sdk:revision>\n" + - " <sdk:archives>\n" + - " <sdk:archive arch=\"any\" os=\"windows\">\n" + - " <sdk:size>11159472</sdk:size>\n" + - " <sdk:checksum type=\"sha1\">6028258d8f2fba14d8b40c3cf507afa0289aaa13</sdk:checksum>\n" + - " <sdk:url>platform-tools_r14-windows.zip</sdk:url>\n" + - " </sdk:archive>\n" + - " <sdk:archive arch=\"any\" os=\"linux\">\n" + - " <sdk:size>10985068</sdk:size>\n" + - " <sdk:checksum type=\"sha1\">6e2bc329c9485eb383172cbc2cde8b0c0cd1843f</sdk:checksum>\n" + - " <sdk:url>platform-tools_r14-linux.zip</sdk:url>\n" + - " </sdk:archive>\n" + - " <sdk:archive arch=\"any\" os=\"macosx\">\n" + - " <sdk:size>11342461</sdk:size>\n" + - " <sdk:checksum type=\"sha1\">4a015090c6a209fc33972acdbc65745e0b3c08b9</sdk:checksum>\n" + - " <sdk:url>platform-tools_r14-macosx.zip</sdk:url>\n" + - " </sdk:archive>\n" + - " </sdk:archives>\n" + - "</sdk:platform-tool>\n" + - "\n" + - "<sdk:tool>\n" + - " <sdk:revision>\n" + - " <sdk:major>20</sdk:major>\n" + - " <sdk:minor>0</sdk:minor>\n" + - " <sdk:micro>3</sdk:micro>\n" + - " </sdk:revision>\n" + - " <sdk:min-platform-tools-rev>\n" + - " <sdk:major>12</sdk:major>\n" + - " </sdk:min-platform-tools-rev>\n" + - " <sdk:archives>\n" + - " <sdk:archive arch=\"any\" os=\"windows\">\n" + - " <sdk:size>90272048</sdk:size>\n" + - " <sdk:checksum type=\"sha1\">54fb94168e631e211910f88aa40c532205730dd4</sdk:checksum>\n" + - " <sdk:url>tools_r20.0.3-windows.zip</sdk:url>\n" + - " </sdk:archive>\n" + - " <sdk:archive arch=\"any\" os=\"linux\">\n" + - " <sdk:size>82723559</sdk:size>\n" + - " <sdk:checksum type=\"sha1\">09bc633b406ae81981e3a0db19426acbb01ef219</sdk:checksum>\n" + - " <sdk:url>tools_r20.0.3-linux.zip</sdk:url>\n" + - " </sdk:archive>\n" + - " <sdk:archive arch=\"any\" os=\"macosx\">\n" + - " <sdk:size>58197071</sdk:size>\n" + - " <sdk:checksum type=\"sha1\">09cee5ff3226277a6f0c07dcd29cba4ffc2e1da4</sdk:checksum>\n" + - " <sdk:url>tools_r20.0.3-macosx.zip</sdk:url>\n" + - " </sdk:archive>\n" + - " </sdk:archives>\n" + - "</sdk:tool>\n" + - "\n" + - "</sdk:sdk-repository>\n"; - - String url = SdkRepoConstants.URL_GOOGLE_SDK_SITE + - String.format(SdkRepoConstants.URL_DEFAULT_FILENAME, SdkRepoConstants.NS_LATEST_VERSION); - - cache.registerCachedPayload(url, repoXml.getBytes("UTF-8")); - } - -} |