diff --git a/tools/sdkmanager/libs/sdkuilib/.classpath b/tools/sdkmanager/libs/sdkuilib/.classpath index 5e78ee75c..5a1790fc2 100644 --- a/tools/sdkmanager/libs/sdkuilib/.classpath +++ b/tools/sdkmanager/libs/sdkuilib/.classpath @@ -1,8 +1,9 @@ - - - - - - - - + + + + + + + + + diff --git a/tools/sdkmanager/libs/sdkuilib/src/Android.mk b/tools/sdkmanager/libs/sdkuilib/src/Android.mk index 282de28e9..970c1220c 100644 --- a/tools/sdkmanager/libs/sdkuilib/src/Android.mk +++ b/tools/sdkmanager/libs/sdkuilib/src/Android.mk @@ -8,6 +8,7 @@ LOCAL_JAVA_RESOURCE_DIRS := . LOCAL_JAVA_LIBRARIES := \ sdklib \ + androidprefs \ swt \ org.eclipse.jface_3.4.2.M20090107-0800 \ org.eclipse.equinox.common_3.4.0.v20080421-2006 \ diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AvdManagerPage.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AvdManagerPage.java new file mode 100755 index 000000000..52582f40f --- /dev/null +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AvdManagerPage.java @@ -0,0 +1,165 @@ +/* + * 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.avd.AvdManager; +import com.android.sdklib.internal.avd.AvdManager.AvdInfo; +import com.android.sdkuilib.internal.repository.UpdaterData.ISdkListener; +import com.android.sdkuilib.internal.widgets.AvdSelector; +import com.android.sdkuilib.internal.widgets.AvdSelector.SelectionMode; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; + +import java.util.HashSet; + +public class AvdManagerPage extends Composite implements ISdkListener { + + private Button mRefreshButton; + private AvdSelector mAvdSelector; + + private final HashSet mKnownAvdNames = new HashSet(); + private final UpdaterData mUpdaterData; + + /** + * Create the composite. + * @param parent The parent of the composite. + * @param updaterData An instance of {@link UpdaterData}. If null, a local + * one will be allocated just to help with the SWT Designer. + */ + public AvdManagerPage(Composite parent, UpdaterData updaterData) { + super(parent, SWT.BORDER); + + mUpdaterData = updaterData != null ? updaterData : new UpdaterData(); + mUpdaterData.addListeners(this); + + createContents(this); + postCreate(); //$hide$ + } + + private void createContents(Composite parent) { + parent.setLayout(new GridLayout(3, false)); + + Label label = new Label(parent, SWT.NONE); + label.setText("List of existing Android Virtual Devices:"); + label.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, true, false, 2, 1)); + + mRefreshButton = new Button(parent, SWT.PUSH); + mRefreshButton.setText("Refresh"); + mRefreshButton.setLayoutData(new GridData(SWT.END, SWT.CENTER, false, false)); + mRefreshButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + onRefreshSelected(); //$hide$ + } + }); + + Composite group = new Composite(parent, SWT.NONE); + group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); + GridLayout gl; + group.setLayout(gl = new GridLayout(1, false /*makeColumnsEqualWidth*/)); + gl.marginHeight = gl.marginWidth = 0; + + mAvdSelector = new AvdSelector(group, + SelectionMode.SELECT, + new AvdSelector.IExtraAction() { + public String label() { + return "Delete AVD..."; + } + + public boolean isEnabled() { + return mAvdSelector != null && mAvdSelector.getSelected() != null; + } + + public void run() { + //onDelete(); + } + }); + } + + @Override + public void dispose() { + mUpdaterData.removeListener(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() { + reloadAvdList(); + } + + /** + * Reloads the AVD list in the AVD selector. + * Tries to preserve the selection. + */ + private void reloadAvdList() { + AvdInfo selected = mAvdSelector.getSelected(); + + AvdInfo[] avds = null; + + AvdManager manager = mUpdaterData.getAvdManager(); + if (manager != null) { + avds = manager.getValidAvds(); + } + + mAvdSelector.setAvds(avds, null /*filter*/); + + // Keep the list of known AVD names to check if they exist quickly. however + // use the list of all AVDs, including broken ones (unless we don't know their + // name). + mKnownAvdNames.clear(); + if (manager != null) { + for (AvdInfo avd : manager.getAllAvds()) { + String name = avd.getName(); + if (name != null) { + mKnownAvdNames.add(name); + } + } + } + + mAvdSelector.setSelection(selected); + } + + public void onSdkChange() { + reloadAvdList(); + } + + private void onRefreshSelected() { + mUpdaterData.reloadAvds(); + reloadAvdList(); + } + + // End of hiding from SWT Designer + //$hide<<$ +} diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/LocalPackagesPage.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/LocalPackagesPage.java index 4f0700919..f423358ff 100755 --- a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/LocalPackagesPage.java +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/LocalPackagesPage.java @@ -18,9 +18,8 @@ package com.android.sdkuilib.internal.repository; import com.android.sdklib.internal.repository.Archive; import com.android.sdklib.internal.repository.IDescription; -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskMonitor; import com.android.sdklib.internal.repository.Package; +import com.android.sdkuilib.internal.repository.UpdaterData.ISdkListener; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; @@ -53,9 +52,8 @@ import java.io.File; * - refresh callback */ -public class LocalPackagesPage extends Composite { +public class LocalPackagesPage extends Composite implements ISdkListener { - private final UpdaterWindowImpl mUpdaterWindow; private final UpdaterData mUpdaterData; private Label mSdkLocLabel; @@ -79,15 +77,13 @@ public class LocalPackagesPage extends Composite { * @param parent The parent of the composite. * @param updaterData An instance of {@link UpdaterData}. If null, a local * one will be allocated just to help with the SWT Designer. - * @param updaterWindow The parent window. */ public LocalPackagesPage(Composite parent, - UpdaterData updaterData, - UpdaterWindowImpl updaterWindow) { + UpdaterData updaterData) { super(parent, SWT.BORDER); - mUpdaterWindow = updaterWindow; mUpdaterData = updaterData != null ? updaterData : new UpdaterData(); + mUpdaterData.addListeners(this); createContents(this); postCreate(); //$hide$ @@ -186,6 +182,12 @@ public class LocalPackagesPage extends Composite { } } + @Override + public void dispose() { + mUpdaterData.removeListener(this); + super.dispose(); + } + @Override protected void checkSubclass() { // Disable the check that prevents subclassing of SWT components @@ -195,16 +197,6 @@ public class LocalPackagesPage extends Composite { // Hide everything down-below from SWT designer //$hide>>$ - /** - * Must be called once to set the adapter input for the package table viewer. - */ - public void setInput(LocalSdkAdapter localSdkAdapter) { - mTableViewerPackages.setLabelProvider( localSdkAdapter.getLabelProvider()); - mTableViewerPackages.setContentProvider(localSdkAdapter.getContentProvider()); - mTableViewerPackages.setInput(localSdkAdapter); - onTreeSelected(); - } - /** * Called by the constructor right after {@link #createContents(Composite)}. */ @@ -249,8 +241,8 @@ public class LocalPackagesPage extends Composite { } private void onUpdateInstalledPackage() { - if (mUpdaterWindow != null) { - mUpdaterWindow.updateAll(); + if (mUpdaterData != null) { + mUpdaterData.reloadSdk(); } } @@ -297,9 +289,15 @@ public class LocalPackagesPage extends Composite { } private void onRefreshSelected() { - if (mUpdaterWindow != null) { - mUpdaterWindow.scanLocalSdkFolders(); - } + mUpdaterData.reloadSdk(); + } + + public void onSdkChange() { + LocalSdkAdapter localSdkAdapter = mUpdaterData.getLocalSdkAdapter(); + mTableViewerPackages.setLabelProvider( localSdkAdapter.getLabelProvider()); + mTableViewerPackages.setContentProvider(localSdkAdapter.getContentProvider()); + mTableViewerPackages.setInput(localSdkAdapter); + onTreeSelected(); } // End of hiding from SWT Designer diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/LocalSdkAdapter.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/LocalSdkAdapter.java index 330be18a6..1deee9261 100755 --- a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/LocalSdkAdapter.java +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/LocalSdkAdapter.java @@ -33,16 +33,10 @@ import org.eclipse.swt.graphics.Image; */ class LocalSdkAdapter { - private final LocalSdkParser mLocalSdkParser; - private String mOsSdkRoot; + private final UpdaterData mUpdaterData; - public LocalSdkAdapter(LocalSdkParser localSdkParser) { - mLocalSdkParser = localSdkParser; - } - - public void setSdkRoot(String osSdkRoot) { - mOsSdkRoot = osSdkRoot; - mLocalSdkParser.clearPackages(); + public LocalSdkAdapter(UpdaterData updaterData) { + mUpdaterData = updaterData; } public ILabelProvider getLabelProvider() { @@ -95,13 +89,13 @@ class LocalSdkAdapter { public Object[] getElements(Object inputElement) { if (inputElement instanceof LocalSdkAdapter) { LocalSdkAdapter adapter = (LocalSdkAdapter) inputElement; - LocalSdkParser parser = adapter.mLocalSdkParser; + LocalSdkParser parser = adapter.mUpdaterData.getLocalSdkParser(); Package[] packages = parser.getPackages(); if (packages == null) { // load on demand the first time - packages = parser.parseSdk(adapter.mOsSdkRoot); + packages = parser.parseSdk(adapter.mUpdaterData.getOsSdkRoot()); } if (packages != null) { diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/RemotePackagesPage.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/RemotePackagesPage.java index 712821d30..4f3314fd3 100755 --- a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/RemotePackagesPage.java +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/RemotePackagesPage.java @@ -21,6 +21,7 @@ import com.android.sdklib.internal.repository.Archive; import com.android.sdklib.internal.repository.IDescription; import com.android.sdklib.internal.repository.Package; import com.android.sdklib.internal.repository.RepoSource; +import com.android.sdkuilib.internal.repository.UpdaterData.ISdkListener; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTreeViewer; @@ -60,9 +61,8 @@ import java.util.ArrayList; * - install selected callback */ -public class RemotePackagesPage extends Composite { +public class RemotePackagesPage extends Composite implements ISdkListener { - private final UpdaterWindowImpl mUpdaterWindow; private final UpdaterData mUpdaterData; private CheckboxTreeViewer mTreeViewerSources; @@ -82,15 +82,13 @@ public class RemotePackagesPage extends Composite { * @param parent The parent of the composite. * @param updaterData An instance of {@link UpdaterData}. If null, a local * one will be allocated just to help with the SWT Designer. - * @param updaterWindow The parent window. */ RemotePackagesPage(Composite parent, - UpdaterData updaterData, - UpdaterWindowImpl updaterWindow) { + UpdaterData updaterData) { super(parent, SWT.BORDER); - mUpdaterWindow = updaterWindow; mUpdaterData = updaterData != null ? updaterData : new UpdaterData(); + mUpdaterData.addListeners(this); createContents(this); postCreate(); //$hide$ @@ -173,6 +171,12 @@ public class RemotePackagesPage extends Composite { mInstallSelectedButton.setText("Install Selected"); } + @Override + public void dispose() { + mUpdaterData.removeListener(this); + super.dispose(); + } + @Override protected void checkSubclass() { // Disable the check that prevents subclassing of SWT components @@ -182,16 +186,6 @@ public class RemotePackagesPage extends Composite { // Hide everything down-below from SWT designer //$hide>>$ - /** - * Must be called once to set the adapter input for the sources tree viewer. - */ - public void setInput(RepoSourcesAdapter sources) { - mTreeViewerSources.setContentProvider(sources.getContentProvider()); - mTreeViewerSources.setLabelProvider( sources.getLabelProvider()); - mTreeViewerSources.setInput(sources); - onTreeSelected(); - } - /** * Called by the constructor right after {@link #createContents(Composite)}. */ @@ -289,8 +283,8 @@ public class RemotePackagesPage extends Composite { } } - if (mUpdaterWindow != null) { - mUpdaterWindow.installArchives(archives); + if (mUpdaterData != null) { + mUpdaterData.installArchives(archives); } } @@ -303,11 +297,19 @@ public class RemotePackagesPage extends Composite { } private void onRefreshSelected() { - if (mUpdaterWindow != null) { - mUpdaterWindow.refreshSources(false /*forceFetching*/, null /*monitor*/); + if (mUpdaterData != null) { + mUpdaterData.refreshSources(false /*forceFetching*/, null /*monitor*/); } } + public void onSdkChange() { + RepoSourcesAdapter sources = mUpdaterData.getSourcesAdapter(); + mTreeViewerSources.setContentProvider(sources.getContentProvider()); + mTreeViewerSources.setLabelProvider( sources.getLabelProvider()); + mTreeViewerSources.setInput(sources); + onTreeSelected(); + } + // End of hiding from SWT Designer //$hide<<$ } diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterData.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterData.java index 47ce3acc9..055fbd2b3 100755 --- a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterData.java +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterData.java @@ -16,32 +16,78 @@ package com.android.sdkuilib.internal.repository; +import com.android.prefs.AndroidLocation.AndroidLocationException; import com.android.sdklib.ISdkLog; +import com.android.sdklib.SdkManager; +import com.android.sdklib.internal.avd.AvdManager; +import com.android.sdklib.internal.repository.Archive; +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.RepoSource; import com.android.sdklib.internal.repository.RepoSources; +import org.eclipse.swt.widgets.Display; + +import java.util.ArrayList; +import java.util.Collection; + /** * Data shared between {@link UpdaterWindowImpl} and its pages. */ class UpdaterData { - private ISdkLog mSdkLog; private String mOsSdkRoot; + + private final ISdkLog mSdkLog; + private ITaskFactory mTaskFactory; private boolean mUserCanChangeSdkRoot; + private SdkManager mSdkManager; + private AvdManager mAvdManager; + private final LocalSdkParser mLocalSdkParser = new LocalSdkParser(); private final RepoSources mSources = new RepoSources(); - private final LocalSdkAdapter mLocalSdkAdapter = new LocalSdkAdapter(mLocalSdkParser); + private final LocalSdkAdapter mLocalSdkAdapter = new LocalSdkAdapter(this); private final RepoSourcesAdapter mSourcesAdapter = new RepoSourcesAdapter(mSources); - public void setOsSdkRoot(String osSdkRoot) { + private final ArrayList mListeners = new ArrayList(); + + public interface ISdkListener { + void onSdkChange(); + } + + public UpdaterData(String osSdkRoot, ISdkLog sdkLog) { mOsSdkRoot = osSdkRoot; + mSdkLog = sdkLog; + + initSdk(); + } + + /** + * default access constructor used by the pages when instantiated by the SWT designer. + */ + UpdaterData() { + mOsSdkRoot = null; + mSdkLog = null; + } + + public void setOsSdkRoot(String osSdkRoot) { + if (mOsSdkRoot == null || mOsSdkRoot.equals(osSdkRoot) == false) { + mOsSdkRoot = osSdkRoot; + initSdk(); + } } public String getOsSdkRoot() { return mOsSdkRoot; } + public void setTaskFactory(ITaskFactory taskFactory) { + mTaskFactory = taskFactory; + } + public void setUserCanChangeSdkRoot(boolean userCanChangeSdkRoot) { mUserCanChangeSdkRoot = userCanChangeSdkRoot; } @@ -66,11 +112,207 @@ class UpdaterData { return mLocalSdkAdapter; } - public void setSdkLog(ISdkLog sdkLog) { - mSdkLog = sdkLog; - } - public ISdkLog getSdkLog() { return mSdkLog; } + + public SdkManager getSdkManager() { + return mSdkManager; + } + + public AvdManager getAvdManager() { + return mAvdManager; + } + + public void addListeners(ISdkListener listener) { + if (mListeners.contains(listener) == false) { + mListeners.add(listener); + } + } + + public void removeListener(ISdkListener listener) { + mListeners.remove(listener); + } + + /** + * Reloads the SDK content (targets). + *

This also reloads the AVDs in case their status changed. + *

This does not notify the listeners ({@link ISdkListener}). + */ + public void reloadSdk() { + // reload SDK + mSdkManager.reloadSdk(mSdkLog); + + // reload AVDs + if (mAvdManager != null) { + try { + mAvdManager.reloadAvds(); + } catch (AndroidLocationException e) { + // FIXME + } + } + + // notify adapters? + // TODO + + // notify listeners + notifyListeners(); + } + + /** + * Reloads the AVDs. + *

This does not notify the listeners. + */ + public void reloadAvds() { + // reload AVDs + if (mAvdManager != null) { + try { + mAvdManager.reloadAvds(); + } catch (AndroidLocationException e) { + // FIXME + } + } + } + + /** + * Notify the listeners ({@link ISdkListener}) that the SDK was reloaded. + *

This can be called from any thread. + */ + public void notifyListeners() { + Display display = Display.getCurrent(); + if (display != null && mListeners.size() > 0) { + display.syncExec(new Runnable() { + public void run() { + for (ISdkListener listener : mListeners) { + try { + listener.onSdkChange(); + } catch (Throwable t) { + // TODO: log error + } + } + } + }); + } + } + + /** + * Install the list of given {@link Archive}s. + * @param archives The archives to install. Incompatible ones will be skipped. + */ + public void installArchives(final Collection archives) { + if (mTaskFactory == null) { + throw new IllegalArgumentException("Task Factory is null"); + } + + // TODO filter the archive list to: a/ display a list of what is going to be installed, + // b/ display licenses and c/ check that the selected packages are actually upgrades + // or ask user to confirm downgrades. All this should be done in a separate class+window + // which will then call this method with the final list. + + // TODO move most parts to SdkLib, maybe as part of Archive, making archives self-installing. + mTaskFactory.start("Installing Archives", new ITask() { + public void run(ITaskMonitor monitor) { + + final int progressPerArchive = 2 * Archive.NUM_MONITOR_INC; + monitor.setProgressMax(archives.size() * progressPerArchive); + monitor.setDescription("Preparing to install archives"); + + int numInstalled = 0; + for (Archive archive : archives) { + + int nextProgress = monitor.getProgress() + progressPerArchive; + try { + if (monitor.isCancelRequested()) { + break; + } + + if (archive.install(mOsSdkRoot, monitor)) { + numInstalled++; + } + + } catch (Throwable t) { + // Display anything unexpected in the monitor. + monitor.setResult("Unexpected Error: %1$s", t.getMessage()); + + } 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 (numInstalled == 0) { + monitor.setDescription("Done. Nothing was installed."); + } else { + monitor.setDescription("Done. %1$d %2$s installed.", + numInstalled, + numInstalled == 1 ? "package" : "packages"); + } + } + }); + } + + public void updateAll() { + if (mTaskFactory == null) { + throw new IllegalArgumentException("Task Factory is null"); + } + + mTaskFactory.start("Update Archives", new ITask() { + public void run(ITaskMonitor monitor) { + monitor.setProgressMax(3); + + monitor.setDescription("Refresh sources"); + refreshSources(true, monitor.createSubMonitor(1)); + } + }); + } + + /** + * Refresh sources + * + * @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, ITaskMonitor monitor) { + ITask task = new ITask() { + public void run(ITaskMonitor monitor) { + ArrayList sources = mSources.getSources(); + monitor.setProgressMax(sources.size()); + for (RepoSource source : sources) { + if (forceFetching || source.getPackages() != null) { + source.load(monitor.createSubMonitor(1)); + } + monitor.incProgress(1); + + } + } + }; + + if (monitor != null) { + task.run(monitor); + } else { + mTaskFactory.start("Refresh Sources", task); + } + } + + /** + * Initializes the {@link SdkManager} and the {@link AvdManager}. + */ + private void initSdk() { + mSdkManager = SdkManager.createManager(mOsSdkRoot, mSdkLog); + try { + mAvdManager = null; // remove the old one if needed. + mAvdManager = new AvdManager(mSdkManager, mSdkLog); + } catch (AndroidLocationException e) { + mSdkLog.error(e, "Unable to read AVDs"); + } + + // notify adapters/parsers + // TODO + + // notify listeners. + notifyListeners(); + } } diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java index c788eebb5..2740958ab 100755 --- a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java @@ -19,9 +19,6 @@ package com.android.sdkuilib.internal.repository; import com.android.sdklib.ISdkLog; import com.android.sdklib.SdkConstants; -import com.android.sdklib.internal.repository.Archive; -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskMonitor; import com.android.sdklib.internal.repository.RepoSource; import com.android.sdklib.repository.SdkRepository; @@ -45,7 +42,6 @@ import org.eclipse.swt.widgets.Shell; import java.io.InputStream; import java.lang.reflect.Constructor; import java.util.ArrayList; -import java.util.Collection; /** * This is the private implementation of the UpdateWindow. @@ -53,7 +49,7 @@ import java.util.Collection; public class UpdaterWindowImpl { /** Internal data shared between the window and its pages. */ - private final UpdaterData mUpdaterData = new UpdaterData(); + private final UpdaterData mUpdaterData; /** The array of pages instances. Only one is visible at a time. */ private ArrayList mPages = new ArrayList(); /** Indicates a page change is due to an internal request. Prevents callbacks from looping. */ @@ -73,12 +69,12 @@ public class UpdaterWindowImpl { private Composite mPagesRootComposite; private LocalPackagesPage mLocalPackagePage; private RemotePackagesPage mRemotePackagesPage; + private AvdManagerPage mAvdManagerPage; private StackLayout mStackLayout; private Image mIconImage; public UpdaterWindowImpl(ISdkLog sdkLog, String osSdkRoot, boolean userCanChangeSdkRoot) { - mUpdaterData.setSdkLog(sdkLog); - mUpdaterData.setOsSdkRoot(osSdkRoot); + mUpdaterData = new UpdaterData(osSdkRoot, sdkLog); mUpdaterData.setUserCanChangeSdkRoot(userCanChangeSdkRoot); } @@ -136,8 +132,9 @@ public class UpdaterWindowImpl { mStackLayout = new StackLayout(); mPagesRootComposite.setLayout(mStackLayout); - mLocalPackagePage = new LocalPackagesPage(mPagesRootComposite, mUpdaterData, this); - mRemotePackagesPage = new RemotePackagesPage(mPagesRootComposite, mUpdaterData, this); + mAvdManagerPage = new AvdManagerPage(mPagesRootComposite, mUpdaterData); + mLocalPackagePage = new LocalPackagesPage(mPagesRootComposite, mUpdaterData); + mRemotePackagesPage = new RemotePackagesPage(mPagesRootComposite, mUpdaterData); mSashForm.setWeights(new int[] {150, 576}); } @@ -214,7 +211,9 @@ public class UpdaterWindowImpl { */ private void firstInit() { mTaskFactory = new ProgressTaskFactory(getShell()); + mUpdaterData.setTaskFactory(mTaskFactory); + addPage(mAvdManagerPage, "Virtual Devices"); addPage(mLocalPackagePage, "Installed Packages"); addPage(mRemotePackagesPage, "Available Packages"); addExtraPages(); @@ -225,8 +224,8 @@ public class UpdaterWindowImpl { // TODO read and apply settings // TODO read add-on sources from some file setupSources(); - scanLocalSdkFolders(); initializeSettings(); + mUpdaterData.notifyListeners(); } // --- page switching --- @@ -325,16 +324,8 @@ public class UpdaterWindowImpl { } } - mRemotePackagesPage.setInput(mUpdaterData.getSourcesAdapter()); - } - /** - * Used to scan the local SDK folders the first time. - */ - public void scanLocalSdkFolders() { - mUpdaterData.getLocalSdkAdapter().setSdkRoot(mUpdaterData.getOsSdkRoot()); - - mLocalPackagePage.setInput(mUpdaterData.getLocalSdkAdapter()); + mRemotePackagesPage.onSdkChange(); } /** @@ -353,101 +344,6 @@ public class UpdaterWindowImpl { } } - /** - * Install the list of given {@link Archive}s. - * @param archives The archives to install. Incompatible ones will be skipped. - */ - public void installArchives(final Collection archives) { - - // TODO filter the archive list to: a/ display a list of what is going to be installed, - // b/ display licenses and c/ check that the selected packages are actually upgrades - // or ask user to confirm downgrades. All this should be done in a separate class+window - // which will then call this method with the final list. - - // TODO move most parts to SdkLib, maybe as part of Archive, making archives self-installing. - mTaskFactory.start("Installing Archives", new ITask() { - public void run(ITaskMonitor monitor) { - - final int progressPerArchive = 2 * Archive.NUM_MONITOR_INC; - monitor.setProgressMax(archives.size() * progressPerArchive); - monitor.setDescription("Preparing to install archives"); - - int numInstalled = 0; - for (Archive archive : archives) { - - int nextProgress = monitor.getProgress() + progressPerArchive; - try { - if (monitor.isCancelRequested()) { - break; - } - - if (archive.install(mUpdaterData.getOsSdkRoot(), monitor)) { - numInstalled++; - } - - } catch (Throwable t) { - // Display anything unexpected in the monitor. - monitor.setResult("Unexpected Error: %1$s", t.getMessage()); - - } 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 (numInstalled == 0) { - monitor.setDescription("Done. Nothing was installed."); - } else { - monitor.setDescription("Done. %1$d %2$s installed.", - numInstalled, - numInstalled == 1 ? "package" : "packages"); - } - } - }); - } - - public void updateAll() { - mTaskFactory.start("Update Archives", new ITask() { - public void run(ITaskMonitor monitor) { - monitor.setProgressMax(3); - - monitor.setDescription("Refresh sources"); - refreshSources(true, monitor.createSubMonitor(1)); - } - }); - } - - /** - * Refresh sources - * - * @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, ITaskMonitor monitor) { - ITask task = new ITask() { - public void run(ITaskMonitor monitor) { - ArrayList sources = mUpdaterData.getSources().getSources(); - monitor.setProgressMax(sources.size()); - for (RepoSource source : sources) { - if (forceFetching || source.getPackages() != null) { - source.load(monitor.createSubMonitor(1)); - } - monitor.incProgress(1); - - } - } - }; - - if (monitor != null) { - task.run(monitor); - } else { - mTaskFactory.start("Refresh Sources", task); - } - } - // End of hiding from SWT Designer //$hide<<$ } diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java index 0d77ccb94..205600865 100644 --- a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java @@ -124,7 +124,9 @@ public final class AvdSelector { // Layout has 2 columns Composite group = new Composite(parent, SWT.NONE); - group.setLayout(new GridLayout(NUM_COL, false /*makeColumnsEqualWidth*/)); + 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());