diff options
Diffstat (limited to 'sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PackagesPage.java')
-rwxr-xr-x | sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PackagesPage.java | 1280 |
1 files changed, 0 insertions, 1280 deletions
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PackagesPage.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PackagesPage.java deleted file mode 100755 index 025be46..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ui/PackagesPage.java +++ /dev/null @@ -1,1280 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.sdkuilib.internal.repository.ui; - -import com.android.sdklib.internal.repository.ITask; -import com.android.sdklib.internal.repository.ITaskMonitor; -import com.android.sdklib.internal.repository.archives.Archive; -import com.android.sdklib.internal.repository.archives.ArchiveInstaller; -import com.android.sdklib.internal.repository.packages.Package; -import com.android.sdkuilib.internal.repository.UpdaterData; -import com.android.sdkuilib.internal.repository.core.PkgCategory; -import com.android.sdkuilib.internal.repository.core.PkgCategoryApi; -import com.android.sdkuilib.internal.repository.core.PkgContentProvider; -import com.android.sdkuilib.internal.repository.core.PkgItem; -import com.android.sdkuilib.internal.repository.core.PkgItem.PkgState; -import com.android.sdkuilib.internal.repository.icons.ImageFactory; -import com.android.sdkuilib.repository.ISdkChangeListener; -import com.android.sdkuilib.repository.SdkUpdaterWindow.SdkInvocationContext; -import com.android.sdkuilib.ui.GridDataBuilder; -import com.android.sdkuilib.ui.GridLayoutBuilder; - -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.CheckStateChangedEvent; -import org.eclipse.jface.viewers.CheckboxTreeViewer; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; -import org.eclipse.jface.viewers.DoubleClickEvent; -import org.eclipse.jface.viewers.ICheckStateListener; -import org.eclipse.jface.viewers.IDoubleClickListener; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.ITreeSelection; -import org.eclipse.jface.viewers.TreeViewerColumn; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerFilter; -import org.eclipse.jface.window.ToolTip; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.FontData; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Group; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Link; -import org.eclipse.swt.widgets.MenuItem; -import org.eclipse.swt.widgets.Text; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.swt.widgets.TreeColumn; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -/** - * Page that displays both locally installed packages as well as all known - * remote available packages. This gives an overview of what is installed - * vs what is available and allows the user to update or install packages. - */ -public final class PackagesPage extends Composite implements ISdkChangeListener { - - enum MenuAction { - RELOAD (SWT.NONE, "Reload"), - SHOW_ADDON_SITES (SWT.NONE, "Manage Add-on Sites..."), - TOGGLE_SHOW_ARCHIVES (SWT.CHECK, "Show Archives Details"), - TOGGLE_SHOW_INSTALLED_PKG (SWT.CHECK, "Show Installed Packages"), - TOGGLE_SHOW_OBSOLETE_PKG (SWT.CHECK, "Show Obsolete Packages"), - TOGGLE_SHOW_UPDATE_NEW_PKG (SWT.CHECK, "Show Updates/New Packages"), - SORT_API_LEVEL (SWT.RADIO, "Sort by API Level"), - SORT_SOURCE (SWT.RADIO, "Sort by Repository") - ; - - private final int mMenuStyle; - private final String mMenuTitle; - - MenuAction(int menuStyle, String menuTitle) { - mMenuStyle = menuStyle; - mMenuTitle = menuTitle; - } - - public int getMenuStyle() { - return mMenuStyle; - } - - public String getMenuTitle() { - return mMenuTitle; - } - }; - - private final Map<MenuAction, MenuItem> mMenuActions = new HashMap<MenuAction, MenuItem>(); - - private final PackagesPageImpl mImpl; - private final SdkInvocationContext mContext; - - private boolean mDisplayArchives = false; - private boolean mOperationPending; - - private Composite mGroupPackages; - private Text mTextSdkOsPath; - private Button mCheckSortSource; - private Button mCheckSortApi; - private Button mCheckFilterObsolete; - private Button mCheckFilterInstalled; - private Button mCheckFilterNew; - private Composite mGroupOptions; - private Composite mGroupSdk; - private Button mButtonDelete; - private Button mButtonInstall; - private Font mTreeFontItalic; - private TreeColumn mTreeColumnName; - private CheckboxTreeViewer mTreeViewer; - - public PackagesPage( - Composite parent, - int swtStyle, - UpdaterData updaterData, - SdkInvocationContext context) { - super(parent, swtStyle); - mImpl = new PackagesPageImpl(updaterData) { - @Override - protected boolean isUiDisposed() { - return mGroupPackages == null || mGroupPackages.isDisposed(); - }; - @Override - protected void syncExec(Runnable runnable) { - if (!isUiDisposed()) { - mGroupPackages.getDisplay().syncExec(runnable); - } - }; - @Override - protected void refreshViewerInput() { - PackagesPage.this.refreshViewerInput(); - } - - @Override - protected boolean isSortByApi() { - return PackagesPage.this.isSortByApi(); - } - - @Override - protected Font getTreeFontItalic() { - return mTreeFontItalic; - } - - @Override - protected void loadPackages(boolean useLocalCache, boolean overrideExisting) { - PackagesPage.this.loadPackages(useLocalCache, overrideExisting); - } - }; - mContext = context; - - createContents(this); - postCreate(); //$hide$ - } - - public void performFirstLoad() { - mImpl.performFirstLoad(); - } - - @SuppressWarnings("unused") - private void createContents(Composite parent) { - GridLayoutBuilder.create(parent).noMargins().columns(2); - - mGroupSdk = new Composite(parent, SWT.NONE); - GridDataBuilder.create(mGroupSdk).hFill().vCenter().hGrab().hSpan(2); - GridLayoutBuilder.create(mGroupSdk).columns(2); - - Label label1 = new Label(mGroupSdk, SWT.NONE); - label1.setText("SDK Path:"); - - mTextSdkOsPath = new Text(mGroupSdk, SWT.NONE); - GridDataBuilder.create(mTextSdkOsPath).hFill().vCenter().hGrab(); - mTextSdkOsPath.setEnabled(false); - - Group groupPackages = new Group(parent, SWT.NONE); - mGroupPackages = groupPackages; - GridDataBuilder.create(mGroupPackages).fill().grab().hSpan(2); - groupPackages.setText("Packages"); - GridLayoutBuilder.create(groupPackages).columns(1); - - mTreeViewer = new CheckboxTreeViewer(groupPackages, SWT.BORDER); - mImpl.setITreeViewer(new PackagesPageImpl.ICheckboxTreeViewer() { - @Override - public Object getInput() { - return mTreeViewer.getInput(); - } - - @Override - public void setInput(List<PkgCategory> cats) { - mTreeViewer.setInput(cats); - } - - @Override - public void setContentProvider(PkgContentProvider pkgContentProvider) { - mTreeViewer.setContentProvider(pkgContentProvider); - } - - @Override - public void refresh() { - mTreeViewer.refresh(); - } - - @Override - public Object[] getCheckedElements() { - return mTreeViewer.getCheckedElements(); - } - }); - mTreeViewer.addFilter(new ViewerFilter() { - @Override - public boolean select(Viewer viewer, Object parentElement, Object element) { - return filterViewerItem(element); - } - }); - - mTreeViewer.addCheckStateListener(new ICheckStateListener() { - @Override - public void checkStateChanged(CheckStateChangedEvent event) { - onTreeCheckStateChanged(event); //$hide$ - } - }); - - mTreeViewer.addDoubleClickListener(new IDoubleClickListener() { - @Override - public void doubleClick(DoubleClickEvent event) { - onTreeDoubleClick(event); //$hide$ - } - }); - - Tree tree = mTreeViewer.getTree(); - tree.setLinesVisible(true); - tree.setHeaderVisible(true); - GridDataBuilder.create(tree).fill().grab(); - - // column name icon is set when loading depending on the current filter type - // (e.g. API level or source) - TreeViewerColumn columnName = new TreeViewerColumn(mTreeViewer, SWT.NONE); - mTreeColumnName = columnName.getColumn(); - mTreeColumnName.setText("Name"); - mTreeColumnName.setWidth(340); - - TreeViewerColumn columnApi = new TreeViewerColumn(mTreeViewer, SWT.NONE); - TreeColumn treeColumn2 = columnApi.getColumn(); - treeColumn2.setText("API"); - treeColumn2.setAlignment(SWT.CENTER); - treeColumn2.setWidth(50); - - TreeViewerColumn columnRevision = new TreeViewerColumn(mTreeViewer, SWT.NONE); - TreeColumn treeColumn3 = columnRevision.getColumn(); - treeColumn3.setText("Rev."); - treeColumn3.setToolTipText("Revision currently installed"); - treeColumn3.setAlignment(SWT.CENTER); - treeColumn3.setWidth(50); - - - TreeViewerColumn columnStatus = new TreeViewerColumn(mTreeViewer, SWT.NONE); - TreeColumn treeColumn4 = columnStatus.getColumn(); - treeColumn4.setText("Status"); - treeColumn4.setAlignment(SWT.LEAD); - treeColumn4.setWidth(190); - - mImpl.setIColumns( - wrapColumn(columnName), - wrapColumn(columnApi), - wrapColumn(columnRevision), - wrapColumn(columnStatus)); - - mGroupOptions = new Composite(groupPackages, SWT.NONE); - GridDataBuilder.create(mGroupOptions).hFill().vCenter().hGrab(); - GridLayoutBuilder.create(mGroupOptions).columns(6).noMargins(); - - // Options line 1, 6 columns - - Label label3 = new Label(mGroupOptions, SWT.NONE); - label3.setText("Show:"); - - mCheckFilterNew = new Button(mGroupOptions, SWT.CHECK); - mCheckFilterNew.setText("Updates/New"); - mCheckFilterNew.setToolTipText("Show Updates and New"); - mCheckFilterNew.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - refreshViewerInput(); - } - }); - mCheckFilterNew.setSelection(true); - - mCheckFilterInstalled = new Button(mGroupOptions, SWT.CHECK); - mCheckFilterInstalled.setToolTipText("Show Installed"); - mCheckFilterInstalled.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - refreshViewerInput(); - } - }); - mCheckFilterInstalled.setSelection(true); - mCheckFilterInstalled.setText("Installed"); - - mCheckFilterObsolete = new Button(mGroupOptions, SWT.CHECK); - mCheckFilterObsolete.setText("Obsolete"); - mCheckFilterObsolete.setToolTipText("Also show obsolete packages"); - mCheckFilterObsolete.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - refreshViewerInput(); - } - }); - mCheckFilterObsolete.setSelection(false); - - Link linkSelectNew = new Link(mGroupOptions, SWT.NONE); - // Note for i18n: we need to identify which link is used, and this is done by using the - // text itself so for translation purposes we want to keep the <a> link strings separate. - final String strLinkNew = "New"; - final String strLinkUpdates = "Updates"; - linkSelectNew.setText( - String.format("Select <a>%1$s</a> or <a>%2$s</a>", strLinkNew, strLinkUpdates)); - linkSelectNew.setToolTipText("Selects all items that are either new or updates."); - GridDataBuilder.create(linkSelectNew).hFill().hGrab(); - linkSelectNew.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - boolean selectNew = e.text == null || e.text.equals(strLinkNew); - onSelectNewUpdates(selectNew, !selectNew, false/*selectTop*/); - } - }); - - mButtonInstall = new Button(mGroupOptions, SWT.NONE); - mButtonInstall.setText(""); //$NON-NLS-1$ placeholder, filled in updateButtonsState() - mButtonInstall.setToolTipText("Install one or more packages"); - GridDataBuilder.create(mButtonInstall).hFill().vCenter().hGrab(); - mButtonInstall.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onButtonInstall(); //$hide$ - } - }); - - // Options line 2, 6 columns - - Label label2 = new Label(mGroupOptions, SWT.NONE); - label2.setText("Sort by:"); - - mCheckSortApi = new Button(mGroupOptions, SWT.RADIO); - mCheckSortApi.setToolTipText("Sort by API level"); - mCheckSortApi.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - if (mCheckSortApi.getSelection()) { - refreshViewerInput(); - copySelection(true /*toApi*/); - syncViewerSelection(); - } - } - }); - mCheckSortApi.setText("API level"); - mCheckSortApi.setSelection(true); - - mCheckSortSource = new Button(mGroupOptions, SWT.RADIO); - mCheckSortSource.setText("Repository"); - mCheckSortSource.setToolTipText("Sort by Repository"); - mCheckSortSource.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - if (mCheckSortSource.getSelection()) { - refreshViewerInput(); - copySelection(false /*toApi*/); - syncViewerSelection(); - } - } - }); - - new Label(mGroupOptions, SWT.NONE); - - Link linkDeselect = new Link(mGroupOptions, SWT.NONE); - linkDeselect.setText("<a>Deselect All</a>"); - linkDeselect.setToolTipText("Deselects all the currently selected items"); - GridDataBuilder.create(linkDeselect).hFill().hGrab(); - linkDeselect.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - onDeselectAll(); - } - }); - - mButtonDelete = new Button(mGroupOptions, SWT.NONE); - mButtonDelete.setText(""); //$NON-NLS-1$ placeholder, filled in updateButtonsState() - mButtonDelete.setToolTipText("Delete one ore more installed packages"); - GridDataBuilder.create(mButtonDelete).hFill().vCenter().hGrab(); - mButtonDelete.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onButtonDelete(); //$hide$ - } - }); - } - - private PackagesPageImpl.ITreeViewerColumn wrapColumn(final TreeViewerColumn column) { - return new PackagesPageImpl.ITreeViewerColumn() { - @Override - public void setLabelProvider(ColumnLabelProvider labelProvider) { - column.setLabelProvider(labelProvider); - } - }; - } - - private Image getImage(String filename) { - if (mImpl.mUpdaterData != null) { - ImageFactory imgFactory = mImpl.mUpdaterData.getImageFactory(); - if (imgFactory != null) { - return imgFactory.getImageByName(filename); - } - } - return null; - } - - - // -- Start of internal part ---------- - // Hide everything down-below from SWT designer - //$hide>>$ - - - // --- menu interactions --- - - public void registerMenuAction(final MenuAction action, MenuItem item) { - item.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - Button button = null; - - switch (action) { - case RELOAD: - mImpl.fullReload(); - break; - case SHOW_ADDON_SITES: - AddonSitesDialog d = new AddonSitesDialog(getShell(), mImpl.mUpdaterData); - if (d.open()) { - mImpl.loadPackages(); - } - break; - case TOGGLE_SHOW_ARCHIVES: - mDisplayArchives = !mDisplayArchives; - // Force the viewer to be refreshed - ((PkgContentProvider) mTreeViewer.getContentProvider()). - setDisplayArchives(mDisplayArchives); - mTreeViewer.setInput(null); - refreshViewerInput(); - syncViewerSelection(); - updateButtonsState(); - break; - case TOGGLE_SHOW_INSTALLED_PKG: - button = mCheckFilterInstalled; - break; - case TOGGLE_SHOW_OBSOLETE_PKG: - button = mCheckFilterObsolete; - break; - case TOGGLE_SHOW_UPDATE_NEW_PKG: - button = mCheckFilterNew; - break; - case SORT_API_LEVEL: - button = mCheckSortApi; - break; - case SORT_SOURCE: - button = mCheckSortSource; - break; - } - - if (button != null && !button.isDisposed()) { - // Toggle this button (radio or checkbox) - - boolean value = button.getSelection(); - - // SWT doesn't automatically switch radio buttons when using the - // Widget#setSelection method, so we'll do it here manually. - if (!value && (button.getStyle() & SWT.RADIO) != 0) { - // we'll be selecting this radio button, so deselect all ther other ones - // in the parent group. - for (Control child : button.getParent().getChildren()) { - if (child instanceof Button && - child != button && - (child.getStyle() & SWT.RADIO) != 0) { - ((Button) child).setSelection(value); - } - } - } - - button.setSelection(!value); - - // SWT doesn't actually invoke the listeners when using Widget#setSelection - // so let's run the actual action. - button.notifyListeners(SWT.Selection, new Event()); - } - - updateMenuCheckmarks(); - } - }); - - mMenuActions.put(action, item); - } - - // --- internal methods --- - - private void updateMenuCheckmarks() { - - for (Entry<MenuAction, MenuItem> entry : mMenuActions.entrySet()) { - MenuAction action = entry.getKey(); - MenuItem item = entry.getValue(); - - if (action.getMenuStyle() == SWT.NONE) { - continue; - } - - boolean value = false; - Button button = null; - - switch (action) { - case TOGGLE_SHOW_ARCHIVES: - value = mDisplayArchives; - break; - case TOGGLE_SHOW_INSTALLED_PKG: - button = mCheckFilterInstalled; - break; - case TOGGLE_SHOW_OBSOLETE_PKG: - button = mCheckFilterObsolete; - break; - case TOGGLE_SHOW_UPDATE_NEW_PKG: - button = mCheckFilterNew; - break; - case SORT_API_LEVEL: - button = mCheckSortApi; - break; - case SORT_SOURCE: - button = mCheckSortSource; - break; - } - - if (button != null && !button.isDisposed()) { - value = button.getSelection(); - } - - if (!item.isDisposed()) { - item.setSelection(value); - } - } - } - - private void postCreate() { - mImpl.postCreate(); - - if (mImpl.mUpdaterData != null) { - mTextSdkOsPath.setText(mImpl.mUpdaterData.getOsSdkRoot()); - } - - ((PkgContentProvider) mTreeViewer.getContentProvider()).setDisplayArchives( - mDisplayArchives); - - ColumnViewerToolTipSupport.enableFor(mTreeViewer, ToolTip.NO_RECREATE); - - Tree tree = mTreeViewer.getTree(); - FontData fontData = tree.getFont().getFontData()[0]; - fontData.setStyle(SWT.ITALIC); - mTreeFontItalic = new Font(tree.getDisplay(), fontData); - - tree.addDisposeListener(new DisposeListener() { - @Override - public void widgetDisposed(DisposeEvent e) { - mTreeFontItalic.dispose(); - mTreeFontItalic = null; - } - }); - } - - private void loadPackages(boolean useLocalCache, boolean overrideExisting) { - if (mImpl.mUpdaterData == null) { - return; - } - - // LoadPackage is synchronous but does not block the UI. - // Consequently it's entirely possible for the user - // to request the app to close whilst the packages are loading. Any - // action done after loadPackages must check the UI hasn't been - // disposed yet. Otherwise hilarity ensues. - - boolean displaySortByApi = isSortByApi(); - - if (mTreeColumnName.isDisposed()) { - // If the UI got disposed, don't try to load anything since we won't be - // able to display it anyway. - return; - } - - mTreeColumnName.setImage(getImage( - displaySortByApi ? PackagesPageIcons.ICON_SORT_BY_API - : PackagesPageIcons.ICON_SORT_BY_SOURCE)); - - mImpl.loadPackagesImpl(useLocalCache, overrideExisting); - } - - private void refreshViewerInput() { - // Dynamically update the table while we load after each source. - // Since the official Android source gets loaded first, it makes the - // window look non-empty a lot sooner. - if (!mGroupPackages.isDisposed()) { - try { - mImpl.setViewerInput(); - } catch (Exception ignore) {} - - // set the initial expanded state - expandInitial(mTreeViewer.getInput()); - - updateButtonsState(); - updateMenuCheckmarks(); - } - } - - private boolean isSortByApi() { - return mCheckSortApi != null && !mCheckSortApi.isDisposed() && mCheckSortApi.getSelection(); - } - - /** - * Decide whether to keep an item in the current tree based on user-chosen filter options. - */ - private boolean filterViewerItem(Object treeElement) { - if (treeElement instanceof PkgCategory) { - PkgCategory cat = (PkgCategory) treeElement; - - if (!cat.getItems().isEmpty()) { - // A category is hidden if all of its content is hidden. - // However empty categories are always visible. - for (PkgItem item : cat.getItems()) { - if (filterViewerItem(item)) { - // We found at least one element that is visible. - return true; - } - } - return false; - } - } - - if (treeElement instanceof PkgItem) { - PkgItem item = (PkgItem) treeElement; - - if (!mCheckFilterObsolete.getSelection()) { - if (item.isObsolete()) { - return false; - } - } - - if (!mCheckFilterInstalled.getSelection()) { - if (item.getState() == PkgState.INSTALLED) { - return false; - } - } - - if (!mCheckFilterNew.getSelection()) { - if (item.getState() == PkgState.NEW || item.hasUpdatePkg()) { - return false; - } - } - } - - return true; - } - - /** - * Performs the initial expansion of the tree. This expands categories that contain - * at least one installed item and collapses the ones with nothing installed. - * - * TODO: change this to only change the expanded state on categories that have not - * been touched by the user yet. Once we do that, call this every time a new source - * is added or the list is reloaded. - */ - private void expandInitial(Object elem) { - if (elem == null) { - return; - } - if (mTreeViewer != null && !mTreeViewer.getTree().isDisposed()) { - - boolean enablePreviews = - mImpl.mUpdaterData.getSettingsController().getSettings().getEnablePreviews(); - - mTreeViewer.setExpandedState(elem, true); - nextCategory: for (Object pkg : - ((ITreeContentProvider) mTreeViewer.getContentProvider()). - getChildren(elem)) { - if (pkg instanceof PkgCategory) { - PkgCategory cat = (PkgCategory) pkg; - - // Always expand the Tools category (and the preview one, if enabled) - if (cat.getKey().equals(PkgCategoryApi.KEY_TOOLS) || - (enablePreviews && - cat.getKey().equals(PkgCategoryApi.KEY_TOOLS_PREVIEW))) { - expandInitial(pkg); - continue nextCategory; - } - - - for (PkgItem item : cat.getItems()) { - if (item.getState() == PkgState.INSTALLED) { - expandInitial(pkg); - continue nextCategory; - } - } - } - } - } - } - - /** - * Handle checking and unchecking of the tree items. - * - * When unchecking, all sub-tree items checkboxes are cleared too. - * When checking a source, all of its packages are checked too. - * When checking a package, only its compatible archives are checked. - */ - private void onTreeCheckStateChanged(CheckStateChangedEvent event) { - boolean checked = event.getChecked(); - Object elem = event.getElement(); - - assert event.getSource() == mTreeViewer; - - // When selecting, we want to only select compatible archives and expand the super nodes. - checkAndExpandItem(elem, checked, true/*fixChildren*/, true/*fixParent*/); - updateButtonsState(); - } - - private void onTreeDoubleClick(DoubleClickEvent event) { - assert event.getSource() == mTreeViewer; - ISelection sel = event.getSelection(); - if (sel.isEmpty() || !(sel instanceof ITreeSelection)) { - return; - } - ITreeSelection tsel = (ITreeSelection) sel; - Object elem = tsel.getFirstElement(); - if (elem == null) { - return; - } - - ITreeContentProvider provider = - (ITreeContentProvider) mTreeViewer.getContentProvider(); - Object[] children = provider.getElements(elem); - if (children == null) { - return; - } - - if (children.length > 0) { - // If the element has children, expand/collapse it. - if (mTreeViewer.getExpandedState(elem)) { - mTreeViewer.collapseToLevel(elem, 1); - } else { - mTreeViewer.expandToLevel(elem, 1); - } - } else { - // If the element is a terminal one, select/deselect it. - checkAndExpandItem( - elem, - !mTreeViewer.getChecked(elem), - false /*fixChildren*/, - true /*fixParent*/); - updateButtonsState(); - } - } - - private void checkAndExpandItem( - Object elem, - boolean checked, - boolean fixChildren, - boolean fixParent) { - ITreeContentProvider provider = - (ITreeContentProvider) mTreeViewer.getContentProvider(); - - // fix the item itself - if (checked != mTreeViewer.getChecked(elem)) { - mTreeViewer.setChecked(elem, checked); - } - if (elem instanceof PkgItem) { - // update the PkgItem to reflect the selection - ((PkgItem) elem).setChecked(checked); - } - - if (!checked) { - if (fixChildren) { - // when de-selecting, we deselect all children too - mTreeViewer.setSubtreeChecked(elem, checked); - for (Object child : provider.getChildren(elem)) { - checkAndExpandItem(child, checked, fixChildren, false/*fixParent*/); - } - } - - // fix the parent when deselecting - if (fixParent) { - Object parent = provider.getParent(elem); - if (parent != null && mTreeViewer.getChecked(parent)) { - mTreeViewer.setChecked(parent, false); - } - } - return; - } - - // When selecting, we also select sub-items (for a category) - if (fixChildren) { - if (elem instanceof PkgCategory || elem instanceof PkgItem) { - Object[] children = provider.getChildren(elem); - for (Object child : children) { - checkAndExpandItem(child, true, fixChildren, false/*fixParent*/); - } - // only fix the parent once the last sub-item is set - if (elem instanceof PkgCategory) { - if (children.length > 0) { - checkAndExpandItem( - children[0], true, false/*fixChildren*/, true/*fixParent*/); - } else { - mTreeViewer.setChecked(elem, false); - } - } - } else if (elem instanceof Package) { - // in details mode, we auto-select compatible packages - selectCompatibleArchives(elem, provider); - } - } - - if (fixParent && checked && elem instanceof PkgItem) { - Object parent = provider.getParent(elem); - if (!mTreeViewer.getChecked(parent)) { - Object[] children = provider.getChildren(parent); - boolean allChecked = children.length > 0; - for (Object e : children) { - if (!mTreeViewer.getChecked(e)) { - allChecked = false; - break; - } - } - if (allChecked) { - mTreeViewer.setChecked(parent, true); - } - } - } - } - - private void selectCompatibleArchives(Object pkg, ITreeContentProvider provider) { - for (Object archive : provider.getChildren(pkg)) { - if (archive instanceof Archive) { - mTreeViewer.setChecked(archive, ((Archive) archive).isCompatible()); - } - } - } - - /** - * Checks all PkgItems that are either new or have updates or select top platform - * for initial run. - */ - private void onSelectNewUpdates(boolean selectNew, boolean selectUpdates, boolean selectTop) { - // This does not update the tree itself, syncViewerSelection does it below. - mImpl.onSelectNewUpdates(selectNew, selectUpdates, selectTop); - syncViewerSelection(); - updateButtonsState(); - } - - /** - * Deselect all checked PkgItems. - */ - private void onDeselectAll() { - // This does not update the tree itself, syncViewerSelection does it below. - mImpl.onDeselectAll(); - syncViewerSelection(); - updateButtonsState(); - } - - /** - * When switching between the tree-by-api and the tree-by-source, copy the selection - * (aka the checked items) from one list to the other. - * This does not update the tree itself. - */ - private void copySelection(boolean fromSourceToApi) { - List<PkgItem> fromItems = - mImpl.mDiffLogic.getAllPkgItems(!fromSourceToApi, fromSourceToApi); - List<PkgItem> toItems = - mImpl.mDiffLogic.getAllPkgItems(fromSourceToApi, !fromSourceToApi); - - // deselect all targets - for (PkgItem item : toItems) { - item.setChecked(false); - } - - // mark new one from the source - for (PkgItem source : fromItems) { - if (source.isChecked()) { - // There should typically be a corresponding item in the target side - for (PkgItem target : toItems) { - if (target.isSameMainPackageAs(source.getMainPackage())) { - target.setChecked(true); - break; - } - } - } - } - } - - /** - * Synchronize the 'checked' state of PkgItems in the tree with their internal isChecked state. - */ - private void syncViewerSelection() { - ITreeContentProvider provider = (ITreeContentProvider) mTreeViewer.getContentProvider(); - - Object input = mTreeViewer.getInput(); - if (input == null) { - return; - } - for (Object cat : provider.getElements(input)) { - Object[] children = provider.getElements(cat); - boolean allChecked = children.length > 0; - for (Object child : children) { - if (child instanceof PkgItem) { - PkgItem item = (PkgItem) child; - boolean checked = item.isChecked(); - allChecked &= checked; - - if (checked != mTreeViewer.getChecked(item)) { - if (checked) { - if (!mTreeViewer.getExpandedState(cat)) { - mTreeViewer.setExpandedState(cat, true); - } - } - checkAndExpandItem(item, checked, true/*fixChildren*/, false/*fixParent*/); - } - } - } - - if (allChecked != mTreeViewer.getChecked(cat)) { - mTreeViewer.setChecked(cat, allChecked); - } - } - } - - /** - * Indicate an install/delete operation is pending. - * This disables the install/delete buttons. - * Use {@link #endOperationPending()} to revert, typically in a {@code try..finally} block. - */ - private void beginOperationPending() { - mOperationPending = true; - updateButtonsState(); - } - - private void endOperationPending() { - mOperationPending = false; - updateButtonsState(); - } - - /** - * Updates the Install and Delete Package buttons. - */ - private void updateButtonsState() { - if (!mButtonInstall.isDisposed()) { - int numPackages = getArchivesForInstall(null /*archives*/); - - mButtonInstall.setEnabled((numPackages > 0) && !mOperationPending); - mButtonInstall.setText( - numPackages == 0 ? "Install packages..." : // disabled button case - numPackages == 1 ? "Install 1 package..." : - String.format("Install %d packages...", numPackages)); - } - - if (!mButtonDelete.isDisposed()) { - // We can only delete local archives - int numPackages = getArchivesToDelete(null /*outMsg*/, null /*outArchives*/); - - mButtonDelete.setEnabled((numPackages > 0) && !mOperationPending); - mButtonDelete.setText( - numPackages == 0 ? "Delete packages..." : // disabled button case - numPackages == 1 ? "Delete 1 package..." : - String.format("Delete %d packages...", numPackages)); - } - } - - /** - * Called when the Install Package button is selected. - * Collects the packages to be installed and shows the installation window. - */ - private void onButtonInstall() { - ArrayList<Archive> archives = new ArrayList<Archive>(); - getArchivesForInstall(archives); - - if (mImpl.mUpdaterData != null) { - boolean needsRefresh = false; - try { - beginOperationPending(); - - List<Archive> installed = mImpl.mUpdaterData.updateOrInstallAll_WithGUI( - archives, - mCheckFilterObsolete.getSelection() /* includeObsoletes */, - mContext == SdkInvocationContext.IDE ? - UpdaterData.TOOLS_MSG_UPDATED_FROM_ADT : - UpdaterData.TOOLS_MSG_UPDATED_FROM_SDKMAN); - needsRefresh = installed != null && !installed.isEmpty(); - } finally { - endOperationPending(); - - if (needsRefresh) { - // The local package list has changed, make sure to refresh it - mImpl.localReload(); - } - } - } - } - - /** - * Selects the archives that can be installed. - * This can be used with a null {@code outArchives} just to count the number of - * installable archives. - * - * @param outArchives An archive list where to add the archives that can be installed. - * This can be null. - * @return The number of archives that can be installed. - */ - private int getArchivesForInstall(List<Archive> outArchives) { - if (mTreeViewer == null || - mTreeViewer.getTree() == null || - mTreeViewer.getTree().isDisposed()) { - return 0; - } - Object[] checked = mTreeViewer.getCheckedElements(); - if (checked == null) { - return 0; - } - - int count = 0; - - // Give us a way to force install of incompatible archives. - boolean checkIsCompatible = - System.getenv(ArchiveInstaller.ENV_VAR_IGNORE_COMPAT) == null; - - if (mDisplayArchives) { - // In detail mode, we display archives so we can install only the - // archives that are actually selected. - - for (Object c : checked) { - if (c instanceof Archive) { - Archive a = (Archive) c; - if (a != null) { - if (checkIsCompatible && !a.isCompatible()) { - continue; - } - count++; - if (outArchives != null) { - outArchives.add((Archive) c); - } - } - } - } - } else { - // In non-detail mode, we install all the compatible archives - // found in the selected pkg items. We also automatically - // select update packages rather than the root package if any. - - for (Object c : checked) { - Package p = null; - if (c instanceof Package) { - // This is an update package - p = (Package) c; - } else if (c instanceof PkgItem) { - p = ((PkgItem) c).getMainPackage(); - - PkgItem pi = (PkgItem) c; - if (pi.getState() == PkgState.INSTALLED) { - // We don't allow installing items that are already installed - // unless they have a pending update. - p = pi.getUpdatePkg(); - - } else if (pi.getState() == PkgState.NEW) { - p = pi.getMainPackage(); - } - } - if (p != null) { - for (Archive a : p.getArchives()) { - if (a != null) { - if (checkIsCompatible && !a.isCompatible()) { - continue; - } - count++; - if (outArchives != null) { - outArchives.add(a); - } - } - } - } - } - } - - return count; - } - - /** - * Called when the Delete Package button is selected. - * Collects the packages to be deleted, prompt the user for confirmation - * and actually performs the deletion. - */ - private void onButtonDelete() { - final String title = "Delete SDK Package"; - StringBuilder msg = new StringBuilder("Are you sure you want to delete:"); - - // A list of archives to delete - final ArrayList<Archive> archives = new ArrayList<Archive>(); - - getArchivesToDelete(msg, archives); - - if (!archives.isEmpty()) { - msg.append("\n").append("This cannot be undone."); //$NON-NLS-1$ - if (MessageDialog.openQuestion(getShell(), title, msg.toString())) { - try { - beginOperationPending(); - - mImpl.mUpdaterData.getTaskFactory().start("Delete Package", new ITask() { - @Override - public void run(ITaskMonitor monitor) { - monitor.setProgressMax(archives.size() + 1); - for (Archive a : archives) { - monitor.setDescription("Deleting '%1$s' (%2$s)", - a.getParentPackage().getShortDescription(), - a.getLocalOsPath()); - - // Delete the actual package - a.deleteLocal(); - - monitor.incProgress(1); - if (monitor.isCancelRequested()) { - break; - } - } - - monitor.incProgress(1); - monitor.setDescription("Done"); - } - }); - } finally { - endOperationPending(); - - // The local package list has changed, make sure to refresh it - mImpl.localReload(); - } - } - } - } - - /** - * Selects the archives that can be deleted and collect their names. - * This can be used with a null {@code outArchives} and a null {@code outMsg} - * just to count the number of archives to be deleted. - * - * @param outMsg A StringBuilder where the names of the packages to be deleted is - * accumulated. This is used to confirm deletion with the user. - * @param outArchives An archive list where to add the archives that can be installed. - * This can be null. - * @return The number of archives that can be deleted. - */ - private int getArchivesToDelete(StringBuilder outMsg, List<Archive> outArchives) { - if (mTreeViewer == null || - mTreeViewer.getTree() == null || - mTreeViewer.getTree().isDisposed()) { - return 0; - } - Object[] checked = mTreeViewer.getCheckedElements(); - if (checked == null) { - // This should not happen since the button should be disabled - return 0; - } - - int count = 0; - - if (mDisplayArchives) { - // In detail mode, select archives that can be deleted - - for (Object c : checked) { - if (c instanceof Archive) { - Archive a = (Archive) c; - if (a != null && a.isLocal()) { - count++; - if (outMsg != null) { - String osPath = a.getLocalOsPath(); - File dir = new File(osPath); - Package p = a.getParentPackage(); - if (p != null && dir.isDirectory()) { - outMsg.append("\n - ") //$NON-NLS-1$ - .append(p.getShortDescription()); - } - } - if (outArchives != null) { - outArchives.add(a); - } - } - } - } - } else { - // In non-detail mode, select archives of selected packages that can be deleted. - - for (Object c : checked) { - if (c instanceof PkgItem) { - PkgItem pi = (PkgItem) c; - PkgState state = pi.getState(); - if (state == PkgState.INSTALLED) { - Package p = pi.getMainPackage(); - - for (Archive a : p.getArchives()) { - if (a != null && a.isLocal()) { - count++; - if (outMsg != null) { - String osPath = a.getLocalOsPath(); - File dir = new File(osPath); - if (dir.isDirectory()) { - outMsg.append("\n - ") //$NON-NLS-1$ - .append(p.getShortDescription()); - } - } - if (outArchives != null) { - outArchives.add(a); - } - } - } - } - } - } - } - - return count; - } - - // ---------------------- - - - // --- Implementation of ISdkChangeListener --- - - @Override - public void onSdkLoaded() { - onSdkReload(); - } - - @Override - public void onSdkReload() { - // The sdkmanager finished reloading its data. We must not call localReload() from here - // since we don't want to alter the sdkmanager's data that just finished loading. - mImpl.loadPackages(); - } - - @Override - public void preInstallHook() { - // nothing to be done for now. - } - - @Override - public void postInstallHook() { - // nothing to be done for now. - } - - - // --- End of hiding from SWT Designer --- - //$hide<<$ -} |