diff options
Diffstat (limited to 'sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PackagesPageImpl.java')
-rwxr-xr-x | sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PackagesPageImpl.java | 568 |
1 files changed, 0 insertions, 568 deletions
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 3ca0ee3..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PackagesPageImpl.java +++ /dev/null @@ -1,568 +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); - - 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); - } - - /** - * 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); - } -} |