18daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll/* 28daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Copyright (C) 2012 The Android Open Source Project 38daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * 48daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Licensed under the Apache License, Version 2.0 (the "License"); 58daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * you may not use this file except in compliance with the License. 68daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * You may obtain a copy of the License at 78daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * 88daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * http://www.apache.org/licenses/LICENSE-2.0 98daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * 108daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Unless required by applicable law or agreed to in writing, software 118daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * distributed under the License is distributed on an "AS IS" BASIS, 128daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * See the License for the specific language governing permissions and 148daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * limitations under the License. 158daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll */ 168daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 178daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollpackage com.android.sdkuilib.internal.repository.ui; 188daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 198daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport com.android.SdkConstants; 208daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport com.android.sdklib.internal.repository.DownloadCache; 218daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport com.android.sdklib.internal.repository.DownloadCache.Strategy; 228daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport com.android.sdklib.internal.repository.IDescription; 238daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport com.android.sdklib.internal.repository.archives.Archive; 248daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport com.android.sdklib.internal.repository.packages.Package; 258daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport com.android.sdklib.internal.repository.sources.SdkSource; 268daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport com.android.sdkuilib.internal.repository.UpdaterData; 278daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport com.android.sdkuilib.internal.repository.core.PackageLoader; 288daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport com.android.sdkuilib.internal.repository.core.PackageLoader.ISourceLoadedCallback; 298daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport com.android.sdkuilib.internal.repository.core.PackagesDiffLogic; 308daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport com.android.sdkuilib.internal.repository.core.PkgCategory; 318daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport com.android.sdkuilib.internal.repository.core.PkgCategoryApi; 328daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport com.android.sdkuilib.internal.repository.core.PkgContentProvider; 338daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport com.android.sdkuilib.internal.repository.core.PkgItem; 348daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport com.android.sdkuilib.internal.repository.core.PkgItem.PkgState; 358daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport com.android.sdkuilib.internal.repository.icons.ImageFactory; 368daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 378daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport org.eclipse.jface.viewers.ColumnLabelProvider; 388daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport org.eclipse.jface.viewers.IInputProvider; 398daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport org.eclipse.jface.viewers.ITableFontProvider; 408daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport org.eclipse.swt.graphics.Font; 418daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport org.eclipse.swt.graphics.Image; 428daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport org.eclipse.swt.graphics.Point; 438daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 448daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport java.net.MalformedURLException; 458daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport java.net.URL; 468daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollimport java.util.List; 478daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 488daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll/** 498daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Base class for {@link PackagesPage} that holds most of the logic to display 508daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * the tree/list of packages. This class holds most of the logic and {@link PackagesPage} 518daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * holds most of the UI (creating the UI, dealing with menus and buttons and tree 528daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * selection.) This makes it easier to test the functionality by mocking only a 538daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * subset of the UI. 548daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll */ 558daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Mollabstract class PackagesPageImpl { 568daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 578daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll final UpdaterData mUpdaterData; 588daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll final PackagesDiffLogic mDiffLogic; 598daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 608daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll private ICheckboxTreeViewer mITreeViewer; 618daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll private ITreeViewerColumn mIColumnName; 628daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll private ITreeViewerColumn mIColumnApi; 638daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll private ITreeViewerColumn mIColumnRevision; 648daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll private ITreeViewerColumn mIColumnStatus; 658daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 668daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll PackagesPageImpl(UpdaterData updaterData) { 678daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mUpdaterData = updaterData; 688daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mDiffLogic = new PackagesDiffLogic(updaterData); 698daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 708daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 718daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll /** 728daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Utility method that derived classes can override to check whether the UI is disposed. 738daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * When the UI is disposed, most operations that affect the UI will be bypassed. 748daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * @return True if UI is not available and should not be touched. 758daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll */ 768daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll abstract protected boolean isUiDisposed(); 778daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 788daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll /** 798daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Utility method to execute a runnable on the main UI thread. 808daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Will do nothing if {@link #isUiDisposed()} returns false. 818daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * @param runnable The runnable to execute on the main UI thread. 828daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll */ 838daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll abstract protected void syncExec(Runnable runnable); 848daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 858daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll void performFirstLoad() { 868daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // First a package loader is created that only checks 878daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // the local cache xml files. It populates the package 888daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // list based on what the client got last, essentially. 898daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll loadPackages(true /*useLocalCache*/, false /*overrideExisting*/); 908daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 918daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // Next a regular package loader is created that will 928daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // respect the expiration and refresh parameters of the 938daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // download cache. 948daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll loadPackages(false /*useLocalCache*/, true /*overrideExisting*/); 958daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 968daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 978daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll public void setITreeViewer(ICheckboxTreeViewer iTreeViewer) { 988daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mITreeViewer = iTreeViewer; 998daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 1008daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 1018daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll public void setIColumns( 1028daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll ITreeViewerColumn columnName, 1038daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll ITreeViewerColumn columnApi, 1048daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll ITreeViewerColumn columnRevision, 1058daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll ITreeViewerColumn columnStatus) { 1068daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mIColumnName = columnName; 1078daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mIColumnApi = columnApi; 1088daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mIColumnRevision = columnRevision; 1098daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mIColumnStatus = columnStatus; 1108daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 1118daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 1128daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll void postCreate() { 1138daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // Caller needs to call setITreeViewer before this. 1148daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll assert mITreeViewer != null; 1158daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // Caller needs to call setIColumns before this. 1168daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll assert mIColumnApi != null; 1178daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll assert mIColumnName != null; 1188daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll assert mIColumnStatus != null; 1198daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll assert mIColumnRevision != null; 1208daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 1218daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mITreeViewer.setContentProvider(new PkgContentProvider(mITreeViewer)); 1228daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 1238daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mIColumnApi.setLabelProvider( 1248daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll new PkgTreeColumnViewerLabelProvider(new PkgCellLabelProvider(mIColumnApi))); 1258daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mIColumnName.setLabelProvider( 1268daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll new PkgTreeColumnViewerLabelProvider(new PkgCellLabelProvider(mIColumnName))); 1278daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mIColumnStatus.setLabelProvider( 1288daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll new PkgTreeColumnViewerLabelProvider(new PkgCellLabelProvider(mIColumnStatus))); 1298daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mIColumnRevision.setLabelProvider( 1308daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll new PkgTreeColumnViewerLabelProvider(new PkgCellLabelProvider(mIColumnRevision))); 1318daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 1328daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 1338daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll /** 1348daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Performs a full reload by removing all cached packages data, including the platforms 1358daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * and addons from the sdkmanager instance. This will perform a full local parsing 1368daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * as well as a full reload of the remote data (by fetching all sources again.) 1378daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll */ 1388daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll void fullReload() { 1398daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // Clear all source information, forcing them to be refreshed. 1408daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mUpdaterData.getSources().clearAllPackages(); 1418daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // Clear and reload all local data too. 1428daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll localReload(); 1438daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 1448daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 1458daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll /** 1468daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Performs a full reload of all the local package information, including the platforms 1478daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * and addons from the sdkmanager instance. This will perform a full local parsing. 1488daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * <p/> 1498daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * This method does NOT force a new fetch of the remote sources. 1508daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * 1518daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * @see #fullReload() 1528daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll */ 1538daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll void localReload() { 1548daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // Clear all source caches, otherwise loading will use the cached data 1558daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mUpdaterData.getLocalSdkParser().clearPackages(); 1568daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mUpdaterData.getSdkManager().reloadSdk(mUpdaterData.getSdkLog()); 1578daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll loadPackages(); 1588daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 1598daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 1608daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll /** 1618daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Performs a "normal" reload of the package information, use the default download 1628daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * cache and refreshing strategy as needed. 1638daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll */ 1648daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll void loadPackages() { 1658daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll loadPackages(false /*useLocalCache*/, false /*overrideExisting*/); 1668daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 1678daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 1688daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll /** 1698daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Performs a reload of the package information. 1708daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * 1718daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * @param useLocalCache When true, the {@link PackageLoader} is switched to use 1728daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * a specific {@link DownloadCache} using the {@link Strategy#ONLY_CACHE}, meaning 1738daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * it will only use data from the local cache. It will not try to fetch or refresh 1748daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * manifests. This is used once the very first time the sdk manager window opens 1758daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * and is typically followed by a regular load with refresh. 1768daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll */ 1778daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll abstract protected void loadPackages(boolean useLocalCache, boolean overrideExisting); 1788daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 1798daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll /** 1808daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Actual implementation of {@link #loadPackages(boolean, boolean)}. 1818daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Derived implementations must call this to do the actual work after setting up the UI. 1828daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll */ 1838daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll void loadPackagesImpl(final boolean useLocalCache, final boolean overrideExisting) { 1848daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (mUpdaterData == null) { 1858daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return; 1868daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 1878daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 1888daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll final boolean displaySortByApi = isSortByApi(); 1898daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 1908daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll PackageLoader packageLoader = getPackageLoader(useLocalCache); 1918daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll assert packageLoader != null; 1928daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 1938daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mDiffLogic.updateStart(); 1948daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll packageLoader.loadPackages(overrideExisting, new ISourceLoadedCallback() { 1958daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll @Override 1968daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll public boolean onUpdateSource(SdkSource source, Package[] newPackages) { 1978daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // This runs in a thread and must not access UI directly. 1988daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll final boolean changed = mDiffLogic.updateSourcePackages( 1998daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll displaySortByApi, source, newPackages); 2008daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 2018daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll syncExec(new Runnable() { 2028daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll @Override 2038daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll public void run() { 2048daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (changed || 2058daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mITreeViewer.getInput() != mDiffLogic.getCategories(isSortByApi())) { 2068daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll refreshViewerInput(); 2078daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 2088daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 2098daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll }); 2108daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 2118daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // Return true to tell the loader to continue with the next source. 2128daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // Return false to stop the loader if any UI has been disposed, which can 2138daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // happen if the user is trying to close the window during the load operation. 2148daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return !isUiDisposed(); 2158daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 2168daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 2178daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll @Override 2188daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll public void onLoadCompleted() { 2198daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // This runs in a thread and must not access UI directly. 2208daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll final boolean changed = mDiffLogic.updateEnd(displaySortByApi); 2218daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 2228daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll syncExec(new Runnable() { 2238daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll @Override 2248daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll public void run() { 2258daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (changed || 2268daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mITreeViewer.getInput() != mDiffLogic.getCategories(isSortByApi())) { 2278daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll try { 2288daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll refreshViewerInput(); 2298daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } catch (Exception ignore) {} 2308daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 2318daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 2328daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (!useLocalCache && 2338daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mDiffLogic.isFirstLoadComplete() && 2348daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll !isUiDisposed()) { 2358daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // At the end of the first load, if nothing is selected then 2368daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // automatically select all new and update packages. 2378daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll Object[] checked = mITreeViewer.getCheckedElements(); 2388daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (checked == null || checked.length == 0) { 2398daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll onSelectNewUpdates( 2408daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll false, //selectNew 2418daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll true, //selectUpdates, 2428daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll true); //selectTop 2438daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 2448daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 2458daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 2468daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll }); 2478daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 2488daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll }); 2498daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 2508daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 2518daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll /** 2528daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Used by {@link #loadPackagesImpl(boolean, boolean)} to get the package 2538daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * loader for the first or second pass update. When starting the manager 2548daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * starts with a first pass that reads only from the local cache, with no 2558daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * extra network access. That's {@code useLocalCache} being true. 2568daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * <p/> 2578daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Leter it does a second pass with {@code useLocalCache} set to false 2588daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * and actually uses the download cache specified in {@link UpdaterData}. 2598daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * 2608daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * This is extracted so that we can control this cache via unit tests. 2618daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll */ 2628daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll protected PackageLoader getPackageLoader(boolean useLocalCache) { 2638daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (useLocalCache) { 2648daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return new PackageLoader(mUpdaterData, new DownloadCache(Strategy.ONLY_CACHE)); 2658daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } else { 2668daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return mUpdaterData.getPackageLoader(); 2678daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 2688daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 2698daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 2708daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll /** 2718daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Overridden by the UI to respond to a request to refresh the tree viewer 2728daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * when the input has changed. 2738daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * The implementation must call {@link #setViewerInput()} somehow and will 2748daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * also need to adjust the expand state of the tree items and/or update 2758daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * some buttons or other state. 2768daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll */ 2778daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll abstract protected void refreshViewerInput(); 2788daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 2798daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll /** 2808daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Invoked from {@link #refreshViewerInput()} to actually either set the 2818daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * input of the tree viewer or refresh it if it's the <em>same</em> input 2828daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * object. 2838daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll */ 2848daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll protected void setViewerInput() { 2858daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll List<PkgCategory> cats = mDiffLogic.getCategories(isSortByApi()); 2868daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (mITreeViewer.getInput() != cats) { 2878daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // set initial input 2888daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mITreeViewer.setInput(cats); 2898daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } else { 2908daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // refresh existing, which preserves the expanded state, the selection 2918daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // and the checked state. 2928daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mITreeViewer.refresh(); 2938daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 2948daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 2958daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 2968daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll /** 2978daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Overridden by the UI to determine if the tree should display packages sorted 2988daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * by API (returns true) or by repository source (returns false.) 2998daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll */ 3008daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll abstract protected boolean isSortByApi(); 3018daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 3028daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll /** 3038daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Checks all PkgItems that are either new or have updates or select top platform 3048daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * for initial run. 3058daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll */ 3068daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll void onSelectNewUpdates(boolean selectNew, boolean selectUpdates, boolean selectTop) { 3078daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // This does not update the tree itself, syncViewerSelection does it in the caller. 3088daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mDiffLogic.checkNewUpdateItems( 3098daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll selectNew, 3108daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll selectUpdates, 3118daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll selectTop, 3128daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll SdkConstants.CURRENT_PLATFORM); 3138daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 3148daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 3158daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll /** 3168daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll * Deselect all checked PkgItems. 3178daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll */ 3188daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll void onDeselectAll() { 3198daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // This does not update the tree itself, syncViewerSelection does it in the caller. 3208daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mDiffLogic.uncheckAllItems(); 3218daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 3228daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 3238daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // ---------------------- 3248daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 3258daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll abstract protected Font getTreeFontItalic(); 3268daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 3278daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll class PkgCellLabelProvider extends ColumnLabelProvider implements ITableFontProvider { 3288daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 3298daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll private final ITreeViewerColumn mColumn; 3308daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 3318daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll public PkgCellLabelProvider(ITreeViewerColumn column) { 3328daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll super(); 3338daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll mColumn = column; 3348daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 3358daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 3368daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll @Override 3378daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll public String getText(Object element) { 3388daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 3398daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (mColumn == mIColumnName) { 3408daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (element instanceof PkgCategory) { 3418daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return ((PkgCategory) element).getLabel(); 3428daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } else if (element instanceof PkgItem) { 3438daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return getPkgItemName((PkgItem) element); 3448daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } else if (element instanceof IDescription) { 3458daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return ((IDescription) element).getShortDescription(); 3468daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 3478daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 3488daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } else if (mColumn == mIColumnApi) { 3498daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll int api = -1; 3508daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (element instanceof PkgItem) { 3518daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll api = ((PkgItem) element).getApi(); 3528daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 3538daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (api >= 1) { 3548daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return Integer.toString(api); 3558daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 3568daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 3578daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } else if (mColumn == mIColumnRevision) { 3588daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (element instanceof PkgItem) { 3598daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll PkgItem pkg = (PkgItem) element; 3608daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return pkg.getRevision().toShortString(); 3618daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 3628daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 3638daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } else if (mColumn == mIColumnStatus) { 3648daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (element instanceof PkgItem) { 3658daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll PkgItem pkg = (PkgItem) element; 3668daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 3678daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll switch(pkg.getState()) { 3688daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll case INSTALLED: 3698daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll Package update = pkg.getUpdatePkg(); 3708daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (update != null) { 3718daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return String.format( 3728daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll "Update available: rev. %1$s", 3738daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll update.getRevision().toShortString()); 3748daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 3758daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return "Installed"; 3768daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 3778daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll case NEW: 3788daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll Package p = pkg.getMainPackage(); 3798daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (p != null && p.hasCompatibleArchive()) { 3808daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return "Not installed"; 3818daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } else { 3828daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return String.format("Not compatible with %1$s", 3838daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll SdkConstants.currentPlatformName()); 3848daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 3858daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 3868daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return pkg.getState().toString(); 3878daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 3888daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } else if (element instanceof Package) { 3898daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // This is an update package. 3908daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return "New revision " + ((Package) element).getRevision().toShortString(); 3918daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 3928daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 3938daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 3948daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return ""; //$NON-NLS-1$ 3958daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 3968daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 3978daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll private String getPkgItemName(PkgItem item) { 3988daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll String name = item.getName().trim(); 3998daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 4008daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (isSortByApi()) { 4018daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // When sorting by API, the package name might contains the API number 4028daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // or the platform name at the end. If we find it, cut it out since it's 4038daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // redundant. 4048daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 4058daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll PkgCategoryApi cat = (PkgCategoryApi) findCategoryForItem(item); 4068daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll String apiLabel = cat.getApiLabel(); 4078daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll String platLabel = cat.getPlatformName(); 4088daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 4098daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (platLabel != null && name.endsWith(platLabel)) { 4108daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return name.substring(0, name.length() - platLabel.length()); 4118daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 4128daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } else if (apiLabel != null && name.endsWith(apiLabel)) { 4138daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return name.substring(0, name.length() - apiLabel.length()); 4148daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 4158daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } else if (platLabel != null && item.isObsolete() && name.indexOf(platLabel) > 0) { 4168daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // For obsolete items, the format is "<base name> <platform name> (Obsolete)" 4178daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // so in this case only accept removing a platform name that is not at 4188daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // the end. 4198daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll name = name.replace(platLabel, ""); //$NON-NLS-1$ 4208daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 4218daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 4228daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 4238daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // Collapse potential duplicated spacing 4248daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll name = name.replaceAll(" +", " "); //$NON-NLS-1$ //$NON-NLS-2$ 4258daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 4268daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return name; 4278daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 4288daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 4298daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll private PkgCategory findCategoryForItem(PkgItem item) { 4308daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll List<PkgCategory> cats = mDiffLogic.getCategories(isSortByApi()); 4318daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll for (PkgCategory cat : cats) { 4328daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll for (PkgItem i : cat.getItems()) { 4338daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (i == item) { 4348daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return cat; 4358daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 4368daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 4378daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 4388daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 4398daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return null; 4408daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 4418daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 4428daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll @Override 4438daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll public Image getImage(Object element) { 4448daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll ImageFactory imgFactory = mUpdaterData.getImageFactory(); 4458daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 4468daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (imgFactory != null) { 4478daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (mColumn == mIColumnName) { 4488daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (element instanceof PkgCategory) { 4498daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return imgFactory.getImageForObject(((PkgCategory) element).getIconRef()); 4508daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } else if (element instanceof PkgItem) { 4518daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return imgFactory.getImageForObject(((PkgItem) element).getMainPackage()); 4528daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 4538daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return imgFactory.getImageForObject(element); 4548daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 4558daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } else if (mColumn == mIColumnStatus && element instanceof PkgItem) { 4568daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll PkgItem pi = (PkgItem) element; 4578daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll switch(pi.getState()) { 4588daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll case INSTALLED: 4598daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (pi.hasUpdatePkg()) { 4608daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return imgFactory.getImageByName(PackagesPageIcons.ICON_PKG_UPDATE); 4618daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } else { 4628daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return imgFactory.getImageByName(PackagesPageIcons.ICON_PKG_INSTALLED); 4638daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 4648daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll case NEW: 4658daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll Package p = pi.getMainPackage(); 4668daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (p != null && p.hasCompatibleArchive()) { 4678daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return imgFactory.getImageByName(PackagesPageIcons.ICON_PKG_NEW); 4688daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } else { 4698daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return imgFactory.getImageByName(PackagesPageIcons.ICON_PKG_INCOMPAT); 4708daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 4718daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 4728daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 4738daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 4748daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return super.getImage(element); 4758daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 4768daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 4778daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // -- ITableFontProvider 4788daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 4798daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll @Override 4808daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll public Font getFont(Object element, int columnIndex) { 4818daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (element instanceof PkgItem) { 4828daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (((PkgItem) element).getState() == PkgState.NEW) { 4838daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return getTreeFontItalic(); 4848daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 4858daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } else if (element instanceof Package) { 4868daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // update package 4878daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return getTreeFontItalic(); 4888daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 4898daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return super.getFont(element); 4908daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 4918daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 4928daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // -- Tooltip support 4938daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 4948daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll @Override 4958daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll public String getToolTipText(Object element) { 4968daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll PkgItem pi = element instanceof PkgItem ? (PkgItem) element : null; 4978daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (pi != null) { 4988daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll element = pi.getMainPackage(); 4998daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 5008daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (element instanceof IDescription) { 5018daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll String s = getTooltipDescription((IDescription) element); 5028daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 5038daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (pi != null && pi.hasUpdatePkg()) { 5048daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll s += "\n-----------------" + //$NON-NLS-1$ 5058daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll "\nUpdate Available:\n" + //$NON-NLS-1$ 5068daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll getTooltipDescription(pi.getUpdatePkg()); 5078daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 5088daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 5098daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return s; 5108daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 5118daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return super.getToolTipText(element); 5128daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 5138daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 5148daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll private String getTooltipDescription(IDescription element) { 5158daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll String s = element.getLongDescription(); 5168daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (element instanceof Package) { 5178daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll Package p = (Package) element; 5188daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 5198daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (!p.isLocal()) { 5208daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // For non-installed item, try to find a download size 5218daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll for (Archive a : p.getArchives()) { 5228daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (!a.isLocal() && a.isCompatible()) { 5238daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll s += '\n' + a.getSizeDescription(); 5248daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll break; 5258daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 5268daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 5278daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 5288daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 5298daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll // Display info about where this package comes/came from 5308daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll SdkSource src = p.getParentSource(); 5318daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (src != null) { 5328daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll try { 5338daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll URL url = new URL(src.getUrl()); 5348daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll String host = url.getHost(); 5358daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll if (p.isLocal()) { 5368daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll s += String.format("\nInstalled from %1$s", host); 5378daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } else { 5388daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll s += String.format("\nProvided by %1$s", host); 5398daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 5408daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } catch (MalformedURLException ignore) { 5418daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 5428daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 5438daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 5448daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return s; 5458daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 5468daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 5478daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll @Override 5488daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll public Point getToolTipShift(Object object) { 5498daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return new Point(15, 5); 5508daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 5518daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 5528daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll @Override 5538daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll public int getToolTipDisplayDelayTime(Object object) { 5548daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll return 500; 5558daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 5568daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 5578daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 5588daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll interface ICheckboxTreeViewer extends IInputProvider { 5598daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll void setContentProvider(PkgContentProvider pkgContentProvider); 5608daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll void refresh(); 5618daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll void setInput(List<PkgCategory> cats); 5628daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll Object[] getCheckedElements(); 5638daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 5648daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll 5658daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll interface ITreeViewerColumn { 5668daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll void setLabelProvider(ColumnLabelProvider labelProvider); 5678daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll } 5688daea84228bdda8d714f2ab4dfc19a3c2f10271bRaphael Moll} 569