| /******************************************************************************* |
| * Copyright (c) 2010 The Eclipse Foundation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * The Eclipse Foundation - initial API and implementation |
| * Yatta Solutions - news (bug 401721), public API (bug 432803), performance (bug 413871), |
| * bug 461603: featured market |
| * JBoss (Pascal Rapicault) - Bug 406907 - Add p2 remediation page to MPC install flow |
| *******************************************************************************/ |
| package org.eclipse.epp.internal.mpc.ui.wizards; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.NoSuchElementException; |
| import java.util.Set; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.epp.internal.mpc.core.model.CatalogBranding; |
| import org.eclipse.epp.internal.mpc.ui.CatalogRegistry; |
| import org.eclipse.epp.internal.mpc.ui.MarketplaceClientUi; |
| import org.eclipse.epp.internal.mpc.ui.MarketplaceClientUiPlugin; |
| import org.eclipse.epp.internal.mpc.ui.catalog.MarketplaceCatalog; |
| import org.eclipse.epp.internal.mpc.ui.catalog.MarketplaceNodeCatalogItem; |
| import org.eclipse.epp.internal.mpc.ui.catalog.MarketplaceNodeInstallableUnitItem; |
| import org.eclipse.epp.internal.mpc.ui.catalog.ResourceProvider.ResourceReceiver; |
| import org.eclipse.epp.internal.mpc.ui.util.Util; |
| import org.eclipse.epp.internal.mpc.ui.wizards.MarketplaceViewer.ContentType; |
| import org.eclipse.epp.internal.mpc.ui.wizards.MarketplaceWizard.WizardState; |
| import org.eclipse.epp.mpc.core.model.ICatalogBranding; |
| import org.eclipse.epp.mpc.core.model.ICategory; |
| import org.eclipse.epp.mpc.core.model.IMarket; |
| import org.eclipse.epp.mpc.core.model.INews; |
| import org.eclipse.epp.mpc.core.model.INode; |
| import org.eclipse.epp.mpc.core.service.IUserFavoritesService; |
| import org.eclipse.epp.mpc.core.service.ServiceHelper; |
| import org.eclipse.epp.mpc.ui.CatalogDescriptor; |
| import org.eclipse.epp.mpc.ui.Operation; |
| import org.eclipse.equinox.internal.p2.discovery.model.CatalogItem; |
| import org.eclipse.equinox.internal.p2.ui.discovery.DiscoveryImages; |
| import org.eclipse.equinox.internal.p2.ui.discovery.wizards.CatalogPage; |
| import org.eclipse.equinox.internal.p2.ui.discovery.wizards.CatalogViewer; |
| import org.eclipse.jface.dialogs.IMessageProvider; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.layout.GridDataFactory; |
| import org.eclipse.jface.layout.GridLayoutFactory; |
| import org.eclipse.jface.operation.IRunnableWithProgress; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.SelectionChangedEvent; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.jface.wizard.IWizardContainer; |
| import org.eclipse.jface.wizard.IWizardPage; |
| import org.eclipse.jface.wizard.WizardPage; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.SWTException; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.events.SelectionListener; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.layout.FillLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.Link; |
| import org.eclipse.swt.widgets.TabFolder; |
| import org.eclipse.swt.widgets.TabItem; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.plugin.AbstractUIPlugin; |
| |
| /** |
| * @author Steffen Pingel |
| * @author Carsten Reckord |
| */ |
| public class MarketplacePage extends CatalogPage implements IWizardButtonLabelProvider { |
| |
| private static final String WIDGET_ID_TAB_FAVORITES = "tab:favorites"; //$NON-NLS-1$ |
| |
| public static final String WIDGET_ID_TAB_SEARCH = "tab:search"; //$NON-NLS-1$ |
| |
| public static final String WIDGET_ID_TAB_FEATURED_MARKET = "tab:featured-market"; //$NON-NLS-1$ |
| |
| public static final String WIDGET_ID_TAB_RECENT = "tab:recent"; //$NON-NLS-1$ |
| |
| public static final String WIDGET_ID_TAB_POPULAR = "tab:popular"; //$NON-NLS-1$ |
| |
| public static final String WIDGET_ID_TAB_RELATED = "tab:related"; //$NON-NLS-1$ |
| |
| public static final String WIDGET_ID_TAB_INSTALLED = "tab:installed"; //$NON-NLS-1$ |
| |
| public static final String WIDGET_ID_TAB_NEWS = "tab:news"; //$NON-NLS-1$ |
| |
| public static final String WIDGET_ID_KEY = MarketplacePage.class.getName() + "::part"; //$NON-NLS-1$ |
| |
| private static final String CONTENT_TYPE_KEY = ContentType.class.getName(); |
| |
| static { |
| registerSearchControlIcons(); |
| } |
| |
| /** |
| * Workaround for bug 484487 |
| */ |
| private static void registerSearchControlIcons() { |
| String clearIconKey = "org.eclipse.ui.internal.dialogs.CLEAR_ICON"; //$NON-NLS-1$ |
| String findIconKey = "org.eclipse.ui.internal.dialogs.FIND_ICON"; //$NON-NLS-1$ |
| ImageDescriptor clearDescriptor = JFaceResources.getImageRegistry().getDescriptor(clearIconKey); |
| ImageDescriptor findDescriptor = JFaceResources.getImageRegistry().getDescriptor(findIconKey); |
| if (clearDescriptor == null || findDescriptor == null) { |
| try { |
| Class.forName( |
| "org.eclipse.equinox.internal.p2.ui.discovery.util.TextSearchControl", true, //$NON-NLS-1$ |
| MarketplacePage.class.getClassLoader()); |
| clearDescriptor = JFaceResources.getImageRegistry().getDescriptor(clearIconKey); |
| findDescriptor = JFaceResources.getImageRegistry().getDescriptor(findIconKey); |
| } catch (ClassNotFoundException e) { |
| //ignore |
| } |
| } |
| if (clearDescriptor == null) { |
| clearDescriptor = AbstractUIPlugin.imageDescriptorFromPlugin(PlatformUI.PLUGIN_ID, |
| "$nl$/icons/full/etool16/clear_co.png"); //$NON-NLS-1$ |
| if (clearDescriptor == null) { |
| clearDescriptor = ImageDescriptor.getMissingImageDescriptor(); |
| } |
| JFaceResources.getImageRegistry().put(clearIconKey, clearDescriptor); |
| } |
| if (findDescriptor == null) { |
| findDescriptor = ImageDescriptor.getMissingImageDescriptor(); |
| JFaceResources.getImageRegistry().put(findIconKey, findDescriptor); |
| } |
| } |
| |
| private final MarketplaceCatalogConfiguration configuration; |
| |
| private CatalogDescriptor previousCatalogDescriptor; |
| |
| private boolean updated; |
| |
| private Link contentListLinks; |
| |
| private ActionLink selectionLink; |
| |
| private TabFolder tabFolder; |
| |
| private TabItem searchTabItem; |
| |
| private TabItem recentTabItem; |
| |
| private TabItem popularTabItem; |
| |
| private TabItem favoritedTabItem; |
| |
| private TabItem featuredMarketTabItem; |
| |
| private TabItem relatedTabItem; |
| |
| private TabItem newsTabItem; |
| |
| private Control tabContent; |
| |
| private TabItem installedTabItem; |
| |
| private NewsViewer newsViewer; |
| |
| private CatalogSwitcher marketplaceSwitcher; |
| |
| private ICatalogBranding currentBranding = getDefaultBranding(); |
| |
| protected boolean disableTabSelection; |
| |
| protected CatalogDescriptor lastSelection; |
| |
| private ContentType currentContentType; |
| |
| private ContentType previousContentType; |
| |
| private final List<ActionLink> actionLinks = new ArrayList<ActionLink>(); |
| |
| private final Map<String, ActionLink> actions = new HashMap<String, ActionLink>(); |
| |
| public MarketplacePage(MarketplaceCatalog catalog, MarketplaceCatalogConfiguration configuration) { |
| super(catalog); |
| this.configuration = configuration; |
| setDescription(Messages.MarketplacePage_selectSolutionsToInstall); |
| setTitle(Messages.MarketplacePage_eclipseMarketplaceSolutions); |
| updateTitle(); |
| } |
| |
| private void updateTitle() { |
| if (configuration.getCatalogDescriptor() != null) { |
| setTitle(configuration.getCatalogDescriptor().getLabel()); |
| } |
| } |
| |
| @Override |
| public void createControl(final Composite parent) { |
| currentBranding = getDefaultBranding(); |
| boolean needSwitchMarketplaceControl = configuration.getCatalogDescriptors().size() > 1; |
| |
| Composite pageContent = new Composite(parent, SWT.NULL); |
| GridLayoutFactory.fillDefaults().numColumns(1).spacing(0, 5).applyTo(pageContent); |
| |
| tabFolder = new TabFolder(pageContent, SWT.TOP); |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(tabFolder); |
| |
| super.createControl(tabFolder); |
| |
| tabContent = getControl(); |
| searchTabItem = createCatalogTab(-1, ContentType.SEARCH, WIDGET_ID_TAB_SEARCH, |
| currentBranding.getSearchTabName()); |
| recentTabItem = createCatalogTab(-1, ContentType.RECENT, WIDGET_ID_TAB_RECENT, |
| currentBranding.getRecentTabName()); |
| popularTabItem = createCatalogTab(-1, ContentType.POPULAR, WIDGET_ID_TAB_POPULAR, |
| currentBranding.getPopularTabName()); |
| favoritedTabItem = createCatalogTab(-1, ContentType.FAVORITES, WIDGET_ID_TAB_FAVORITES, |
| getFavoritedTabName(currentBranding)); |
| installedTabItem = createCatalogTab(-1, ContentType.INSTALLED, WIDGET_ID_TAB_INSTALLED, |
| Messages.MarketplacePage_installed); |
| updateNewsTab(); |
| |
| searchTabItem.setControl(tabContent); |
| tabFolder.setSelection(searchTabItem); |
| |
| tabFolder.addSelectionListener(new SelectionListener() { |
| public void widgetSelected(SelectionEvent e) { |
| if (e.item.isDisposed()) { |
| return; |
| } |
| setActiveTab((TabItem) e.item); |
| } |
| |
| public void widgetDefaultSelected(SelectionEvent e) { |
| widgetSelected(e); |
| } |
| }); |
| |
| { |
| contentListLinks = new Link(pageContent, SWT.NULL);//TODO id |
| contentListLinks.setToolTipText(Messages.MarketplacePage_showSelection); |
| contentListLinks.addSelectionListener(new SelectionListener() { |
| public void widgetSelected(SelectionEvent e) { |
| String actionId = e.text; |
| ActionLink actionLink = actions.get(actionId); |
| if (actionLink != null) { |
| actionLink.selected(); |
| } |
| } |
| |
| public void widgetDefaultSelected(SelectionEvent e) { |
| widgetSelected(e); |
| } |
| }); |
| GridDataFactory.swtDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(contentListLinks); |
| updateSelectionLink(); |
| } |
| |
| if (needSwitchMarketplaceControl) { |
| createMarketplaceSwitcher(pageContent); |
| } |
| updateBranding(); |
| |
| // bug 312411: a selection listener so that we can streamline install of single product |
| getViewer().addSelectionChangedListener(new ISelectionChangedListener() { |
| |
| private int previousSelectionSize = 0; |
| |
| public void selectionChanged(SelectionChangedEvent event) { |
| if (!isCurrentPage()) { |
| return; |
| } |
| SelectionModel selectionModel = getWizard().getSelectionModel(); |
| int newSelectionSize = selectionModel.getItemToSelectedOperation().size(); |
| |
| // important: we don't do anything if the selection is empty, since CatalogViewer |
| // sets the empty selection whenever the catalog is updated. |
| if (!event.getSelection().isEmpty()) { |
| |
| if (previousSelectionSize == 0 && newSelectionSize > 0 |
| && selectionModel.computeProvisioningOperationViableForFeatureSelection()) { |
| showNextPage(); |
| } |
| } |
| previousSelectionSize = newSelectionSize; |
| } |
| }); |
| getViewer().addPropertyChangeListener(new IPropertyChangeListener() { |
| |
| public void propertyChange(PropertyChangeEvent event) { |
| if (event.getProperty().equals(MarketplaceViewer.CONTENT_TYPE_PROPERTY) && event.getNewValue() != null) { |
| setActiveTab((ContentType) event.getNewValue()); |
| } |
| } |
| }); |
| setControl(pageContent); |
| if (!tabContent.isDisposed()) { |
| // bug 473031 - no clue how this can happen during createControl... |
| MarketplaceClientUi.setDefaultHelp(tabContent); |
| } |
| } |
| |
| protected void showNextPage() { |
| IWizardContainer container = getContainer(); |
| if (container == null) { |
| return; |
| } |
| IWizardPage currentPage = container.getCurrentPage(); |
| if (currentPage == MarketplacePage.this && currentPage.isPageComplete()) { |
| IWizardPage nextPage = getNextPage(); |
| if (nextPage != null && nextPage instanceof WizardPage) { |
| ((WizardPage) nextPage).setPageComplete(true); |
| container.showPage(nextPage); |
| } |
| } |
| } |
| |
| @Override |
| public boolean canFlipToNextPage() { |
| if (isPageComplete()) { |
| MarketplaceWizard wizard = getWizard(); |
| if (wizard != null) { |
| return wizard.getNextPageInList(this) != null; |
| } |
| } |
| return false; |
| } |
| |
| protected boolean canSkipFeatureSelection() { |
| SelectionModel selectionModel = getWizard().getSelectionModel(); |
| Map<CatalogItem, Operation> selectedOperations = selectionModel.getItemToSelectedOperation(); |
| Set<Entry<CatalogItem, Operation>> entrySet = selectedOperations.entrySet(); |
| Operation mode = null; |
| for (Entry<CatalogItem, Operation> entry : entrySet) { |
| if (!(entry.getKey() instanceof MarketplaceNodeCatalogItem)) { |
| return false; |
| } |
| MarketplaceNodeCatalogItem item = (MarketplaceNodeCatalogItem) entry.getKey(); |
| Operation value = entry.getValue(); |
| switch (value) { |
| case NONE: |
| continue; |
| case INSTALL: |
| case UPDATE: |
| if (mode == null) { |
| mode = Operation.INSTALL; |
| } else if (mode == Operation.UNINSTALL) { |
| return false; |
| } |
| if (hasOptionalFeatures(item)) { |
| return false; |
| } |
| break; |
| case UNINSTALL: |
| if (mode == null) { |
| mode = Operation.UNINSTALL; |
| } else if (mode == Operation.INSTALL) { |
| return false; |
| } |
| if (hasOptionalFeatures(item)) { |
| return false; |
| } |
| break; |
| case CHANGE: |
| return false; |
| } |
| } |
| if (mode == null) { |
| return false; |
| } |
| return true; |
| } |
| |
| private boolean hasOptionalFeatures(MarketplaceNodeCatalogItem item) { |
| List<MarketplaceNodeInstallableUnitItem> installableUnitItems = item.getInstallableUnitItems(); |
| if (installableUnitItems.size() > 1) { |
| for (MarketplaceNodeInstallableUnitItem iuItem : installableUnitItems) { |
| if (iuItem.isOptional()) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| private void setActiveTab(TabItem tab) { |
| if (disableTabSelection) { |
| return; |
| } |
| if (tab == newsTabItem) { |
| final INews news = getNews(); |
| boolean wasUpdated = newsViewer.isUpdated(news); |
| newsViewer.showNews(news); |
| if (wasUpdated) { |
| updateBranding(); |
| TabItem currentTabItem = getSelectedTabItem(); |
| if (currentTabItem != newsTabItem) { |
| tabFolder.setSelection(newsTabItem); |
| // required for Mac to not switch back to first tab |
| getControl().getDisplay().asyncExec(new Runnable() { |
| public void run() { |
| tabFolder.setSelection(newsTabItem); |
| } |
| }); |
| } |
| } |
| return; |
| } |
| ContentType currentContentType = getViewer().getContentType(); |
| if (currentContentType != null) { |
| TabItem tabItem = getTabItem(currentContentType); |
| if (tabItem == tab) { |
| setActiveTab(currentContentType); |
| return; |
| } |
| } |
| for (ContentType contentType : ContentType.values()) { |
| if (getTabItem(contentType) == tab) { |
| setActiveTab(contentType); |
| return; |
| } |
| } |
| throw new IllegalArgumentException(tab.getText()); |
| } |
| |
| public void setPreviouslyActiveTab() { |
| if (previousContentType == null) { |
| setActiveTab(tabFolder.getItem(0)); |
| } else { |
| setActiveTab(previousContentType); |
| } |
| } |
| |
| public void setActiveTab(ContentType contentType) { |
| if (disableTabSelection) { |
| return; |
| } |
| boolean showSelected = false; |
| if (contentType == ContentType.SELECTION) { |
| showSelected = true; |
| contentType = ContentType.SEARCH; |
| } |
| |
| if (contentType != currentContentType) { |
| previousContentType = currentContentType; |
| currentContentType = contentType; |
| } |
| final TabItem tabItem = getTabItem(contentType); |
| TabItem currentTabItem = getSelectedTabItem(); |
| if (currentTabItem != tabItem) { |
| if (currentTabItem.getControl() == tabContent) { |
| currentTabItem.setControl(null); |
| } |
| tabFolder.setSelection(tabItem); |
| } |
| tabItem.setControl(null); |
| if (tabContent != null && !tabContent.isDisposed()) { |
| tabItem.setControl(tabContent); |
| } |
| if (previousContentType != contentType) { |
| contentTypeChanged(previousContentType, contentType); |
| } |
| if (showSelected) { |
| getViewer().showSelected(); |
| } else { |
| getViewer().setContentType(contentType); |
| } |
| } |
| |
| private void contentTypeChanged(ContentType previousContentType, ContentType contentType) { |
| actionLinks.clear(); |
| actions.clear(); |
| if (selectionLink != null) { |
| doAddActionLink(0, selectionLink); |
| } |
| if (contentType == ContentType.FAVORITES) { |
| doAddActionLink(-1, new ImportFavoritesActionLink(this)); |
| doAddActionLink(-1, new InstallAllActionLink(this)); |
| } |
| updateContentListLinks(); |
| } |
| |
| public ContentType getActiveTab() { |
| TabItem selectedTabItem = getSelectedTabItem(); |
| return selectedTabItem == null ? null : getContentType(selectedTabItem); |
| } |
| |
| private ContentType getContentType(TabItem tabItem) { |
| if (tabItem != null && !tabItem.isDisposed()) { |
| Object data = tabItem.getData(CONTENT_TYPE_KEY); |
| if (data instanceof ContentType) { |
| return (ContentType) data; |
| } |
| } |
| return null; |
| } |
| |
| private TabItem getSelectedTabItem() { |
| int currentTabIndex = tabFolder.getSelectionIndex(); |
| TabItem currentTabItem = null; |
| if (currentTabIndex != -1) { |
| currentTabItem = tabFolder.getItem(currentTabIndex); |
| } |
| return currentTabItem; |
| } |
| |
| private TabItem getTabItem(ContentType content) { |
| switch (content) { |
| case INSTALLED: |
| return installedTabItem; |
| case FEATURED_MARKET: |
| return featuredMarketTabItem; |
| case POPULAR: |
| return popularTabItem; |
| case RECENT: |
| return recentTabItem; |
| case SEARCH: |
| return searchTabItem; |
| case RELATED: |
| return relatedTabItem; |
| case SELECTION: |
| return searchTabItem; |
| case FAVORITES: |
| return favoritedTabItem; |
| default: |
| throw new IllegalArgumentException(); |
| } |
| } |
| |
| private TabItem createCatalogTab(int index, ContentType contentType, String widgetId, String label) { |
| return createTab(index, contentType, widgetId, label, null); |
| } |
| |
| private TabItem createTab(int index, ContentType contentType, String widgetId, String label, Control tabControl) { |
| TabItem tabItem; |
| if (index == -1) { |
| tabItem = new TabItem(tabFolder, SWT.NULL); |
| } else { |
| tabItem = new TabItem(tabFolder, SWT.NULL, index); |
| } |
| tabItem.setData(WIDGET_ID_KEY, widgetId); |
| tabItem.setData(CONTENT_TYPE_KEY, contentType); |
| tabItem.setText(label); |
| tabItem.setControl(tabControl); |
| return tabItem; |
| } |
| |
| private void createNewsTab() { |
| newsTabItem = new TabItem(tabFolder, SWT.NULL | SWT.BOLD); |
| newsTabItem.setText(Messages.MarketplacePage_DefaultNewsTitle); |
| newsTabItem.setData(WIDGET_ID_KEY, WIDGET_ID_TAB_NEWS); |
| |
| if (newsViewer == null || newsViewer.getControl().isDisposed()) { |
| createNewsViewer(tabFolder); |
| } |
| newsTabItem.setControl(newsViewer.getControl()); |
| } |
| |
| private void updateNewsTab() { |
| if (newsTabItem == null) { |
| createNewsTab(); |
| } |
| INews news = getNews(); |
| if (news == null) { |
| if (!newsTabItem.isDisposed()) { |
| newsTabItem.dispose(); |
| } |
| return; |
| } else if (newsTabItem.isDisposed()) { |
| createNewsTab(); |
| } |
| if (news.getShortTitle() != null && news.getShortTitle().length() > 0) { |
| String title = news.getShortTitle(); |
| String tooltip = title; |
| if (title.length() > 40) { |
| tooltip = title; |
| title = title.substring(0, 39) + '\u2026'; |
| } |
| newsTabItem.setText(title); |
| newsTabItem.setToolTipText(tooltip); |
| } |
| |
| updateNewsStatus(); |
| } |
| |
| private void updateNewsStatus() { |
| INews news = getNews(); |
| |
| Image tabImage = null; |
| if (news != null && newsViewer.isUpdated(news)) { |
| tabImage = MarketplaceClientUiPlugin.getInstance() |
| .getImageRegistry() |
| .get(MarketplaceClientUiPlugin.NEWS_ICON_UPDATE); |
| } |
| newsTabItem.setImage(tabImage); |
| newsTabItem.getParent().layout(); |
| } |
| |
| private INews getNews() { |
| CatalogDescriptor descriptor = configuration.getCatalogDescriptor(); |
| INews news = CatalogRegistry.getInstance().getCatalogNews(descriptor); |
| return news; |
| } |
| |
| private void createNewsViewer(Composite parent) { |
| newsViewer = new NewsViewer(getWizard()); |
| newsViewer.createControl(parent); |
| } |
| |
| private void createMarketplaceSwitcher(Composite parent) { |
| Composite composite = new Composite(parent, SWT.NONE); |
| composite.setLayout(new FillLayout()); |
| |
| final CatalogSwitcher switcher = new CatalogSwitcher(composite, SWT.BORDER, configuration); |
| switcher.addSelectionChangedListener(new ISelectionChangedListener() { |
| |
| public void selectionChanged(SelectionChangedEvent event) { |
| CatalogDescriptor descriptor = (CatalogDescriptor) ((IStructuredSelection) event.getSelection()).getFirstElement(); |
| showMarketplace(descriptor); |
| } |
| }); |
| CatalogDescriptor selectedDescriptor = configuration.getCatalogDescriptor(); |
| if (selectedDescriptor != null) { |
| switcher.setSelection(new StructuredSelection(selectedDescriptor)); |
| lastSelection = selectedDescriptor; |
| } |
| marketplaceSwitcher = switcher; |
| GridDataFactory.fillDefaults() |
| .align(SWT.FILL, SWT.FILL) |
| .grab(true, false) |
| .minSize(1, SWT.DEFAULT) |
| .hint(500, SWT.DEFAULT) |
| .applyTo(composite); |
| } |
| |
| private void updateContentListLinks() { |
| if (contentListLinks != null) { |
| final String originalText = contentListLinks.getText(); |
| |
| StringBuilder bldr = new StringBuilder(); |
| boolean first = true; |
| for (ActionLink actionLink : actionLinks) { |
| if (first) { |
| first = false; |
| } else { |
| bldr.append(" | "); //$NON-NLS-1$ |
| } |
| bldr.append(NLS.bind("<a href=\"{0}\">{1}</a>", actionLink.getId(), actionLink.getLabel())); //$NON-NLS-1$ |
| } |
| String text = bldr.toString(); |
| if (!text.equals(originalText)) { |
| contentListLinks.setText(text); |
| contentListLinks.getParent().layout(true, false); |
| } |
| } |
| } |
| |
| private void updateSelectionLink() { |
| if (contentListLinks != null) { |
| final String originalText = selectionLink == null ? "" : selectionLink.getLabel(); //$NON-NLS-1$ |
| |
| String text = ""; //$NON-NLS-1$ |
| int count = getWizard().getSelectionModel().getItemToSelectedOperation().size(); |
| if (count == 1) { |
| text = Messages.MarketplacePage_linkShowSelection_One; |
| } else if (count > 0) { |
| text = NLS.bind(Messages.MarketplacePage_linkShowSelection_Multiple, Integer.valueOf(count)); |
| } |
| if (!text.equals(originalText)) { |
| if (text.equals("")) { //$NON-NLS-1$ |
| if (selectionLink != null) { |
| removeActionLink(selectionLink); |
| selectionLink = null; |
| } |
| } else { |
| ActionLink newSelectionLink = createSelectionLink(text); |
| if (selectionLink != null) { |
| updateActionLink(selectionLink, newSelectionLink); |
| } else { |
| addActionLink(0, newSelectionLink); |
| } |
| selectionLink = newSelectionLink; |
| } |
| } |
| } |
| } |
| |
| private ActionLink createSelectionLink(String text) { |
| return new ActionLink("showSelection", text, Messages.MarketplacePage_showSelection) { |
| |
| @Override |
| public void selected() { |
| selectionLinkActivated(); |
| } |
| }; |
| } |
| |
| protected void selectionLinkActivated() { |
| // tabFolder.setSelection(searchTabItem); |
| // getViewer().showSelected(); |
| setActiveTab(ContentType.SELECTION); |
| } |
| |
| @Override |
| public IWizardPage getPreviousPage() { |
| return super.getPreviousPage(); |
| } |
| |
| @Override |
| public MarketplaceWizard getWizard() { |
| return (MarketplaceWizard) super.getWizard(); |
| } |
| |
| @Override |
| protected MarketplaceViewer getViewer() { |
| return (MarketplaceViewer) super.getViewer(); |
| } |
| |
| @Override |
| protected CatalogViewer doCreateViewer(Composite parent) { |
| MarketplaceViewer viewer = new MarketplaceViewer(getCatalog(), this, getWizard()); |
| viewer.setMinimumHeight(MINIMUM_HEIGHT); |
| viewer.createControl(parent); |
| return viewer; |
| } |
| |
| @Override |
| protected void doUpdateCatalog() { |
| if (!updated) { |
| updated = true; |
| Display.getCurrent().asyncExec(new Runnable() { |
| public void run() { |
| if (!getControl().isDisposed() && isCurrentPage()) { |
| safeUpdateCatalog(); |
| } |
| } |
| }); |
| } |
| } |
| |
| private void safeUpdateCatalog() { |
| try { |
| getWizard().updateNews(); |
| getViewer().updateCatalog(); |
| updateBranding(); |
| } catch (SWTException ex) { |
| if (ex.code == SWT.ERROR_WIDGET_DISPOSED) { |
| //ignore - this happens if the wizard is closed during the update |
| return; |
| } |
| throw ex; |
| } |
| } |
| |
| @Override |
| public void setVisible(boolean visible) { |
| if (visible) { |
| CatalogDescriptor catalogDescriptor = configuration.getCatalogDescriptor(); |
| if (catalogDescriptor != null) { |
| setTitle(catalogDescriptor.getLabel()); |
| } |
| if (previousCatalogDescriptor == null || !previousCatalogDescriptor.equals(catalogDescriptor)) { |
| previousCatalogDescriptor = catalogDescriptor; |
| tabFolder.setSelection(searchTabItem); |
| getViewer().setContentType(ContentType.SEARCH); |
| getWizard().initializeCatalog(); |
| updated = false; |
| } |
| } |
| super.setVisible(visible); |
| } |
| |
| @Override |
| public void setPageComplete(boolean complete) { |
| MarketplaceWizard wizard = getWizard(); |
| if (wizard != null) { |
| if (complete) { |
| complete = wizard.getSelectionModel().computeProvisioningOperationViableForFeatureSelection(); |
| } |
| if (wizard.getContainer() != null) { |
| computeMessages(); |
| } |
| } |
| super.setPageComplete(complete); |
| } |
| |
| private void computeMessages() { |
| computeStatusMessage(); |
| updateSelectionLink(); |
| } |
| |
| private void computeStatusMessage() { |
| String message = null; |
| int messageType = IMessageProvider.NONE; |
| |
| if (getWizard() != null) { |
| IStatus viability = getWizard().getSelectionModel().computeProvisioningOperationViability(); |
| if (viability != null) { |
| message = viability.getMessage(); |
| messageType = Util.computeMessageType(viability); |
| } |
| } |
| |
| setMessage(message, messageType); |
| } |
| |
| @Override |
| public void performHelp() { |
| getControl().notifyListeners(SWT.Help, new Event()); |
| } |
| |
| private void updateBranding() { |
| disableTabSelection = true; |
| updateTitle(); |
| CatalogDescriptor descriptor = configuration.getCatalogDescriptor(); |
| ICatalogBranding oldBranding = currentBranding; |
| ICatalogBranding branding = descriptor == null ? null : descriptor.getCatalogBranding(); |
| if (branding == null) { |
| branding = getDefaultBranding(); |
| } |
| currentBranding = branding; |
| |
| TabItem selectedTabItem = getSelectedTabItem(); |
| |
| int tabIndex = 0; |
| boolean hasTab = branding.hasSearchTab(); |
| searchTabItem = updateTab(searchTabItem, ContentType.SEARCH, WIDGET_ID_TAB_SEARCH, branding.getSearchTabName(), |
| hasTab, |
| oldBranding.hasSearchTab(), |
| tabIndex); |
| if (hasTab) { |
| tabIndex++; |
| } |
| hasTab = hasFeaturedMarketTab(branding); |
| featuredMarketTabItem = updateTab(featuredMarketTabItem, ContentType.SEARCH, WIDGET_ID_TAB_FEATURED_MARKET, |
| branding.getFeaturedMarketTabName(), hasTab, hasFeaturedMarketTab(oldBranding), tabIndex); |
| if (hasTab) { |
| tabIndex++; |
| } |
| hasTab = branding.hasRecentTab(); |
| recentTabItem = updateTab(recentTabItem, ContentType.SEARCH, WIDGET_ID_TAB_RECENT, branding.getRecentTabName(), |
| hasTab, |
| oldBranding.hasRecentTab(), |
| tabIndex); |
| if (hasTab) { |
| tabIndex++; |
| } |
| hasTab = branding.hasPopularTab(); |
| popularTabItem = updateTab(popularTabItem, ContentType.SEARCH, WIDGET_ID_TAB_POPULAR, |
| branding.getPopularTabName(), hasTab, |
| oldBranding.hasPopularTab(), |
| tabIndex); |
| if (hasTab) { |
| tabIndex++; |
| } |
| hasTab = branding.hasRelatedTab(); |
| relatedTabItem = updateTab(relatedTabItem, ContentType.SEARCH, WIDGET_ID_TAB_RELATED, |
| branding.getRelatedTabName(), hasTab, |
| oldBranding.hasRelatedTab(), tabIndex); |
| if (hasTab) { |
| tabIndex++; |
| } |
| hasTab = hasFavoritedTab(branding); |
| favoritedTabItem = updateTab(favoritedTabItem, ContentType.SEARCH, WIDGET_ID_TAB_FAVORITES, |
| getFavoritedTabName(branding), hasTab, hasFavoritedTab(oldBranding), |
| tabIndex); |
| if (hasTab) { |
| tabIndex++; |
| } |
| |
| updateNewsTab(); |
| |
| if (selectedTabItem == null || selectedTabItem.isDisposed()) { |
| tabFolder.setSelection(0); |
| } |
| |
| final ImageDescriptor defaultWizardIconDescriptor = DiscoveryImages.BANNER_DISOVERY; |
| if (branding.getWizardIcon() == null) { |
| setImageDescriptor(defaultWizardIconDescriptor); |
| } else { |
| final Display display = Display.getCurrent(); |
| MarketplaceClientUiPlugin.getInstance() |
| .getResourceProvider() |
| .provideResource(new ResourceReceiver<ImageDescriptor>() { |
| |
| public ImageDescriptor processResource(URL resource) { |
| return ImageDescriptor.createFromURL(resource); |
| } |
| |
| public void setResource(final ImageDescriptor resource) { |
| display.asyncExec(new Runnable() { |
| |
| public void run() { |
| try { |
| setImageDescriptor(resource); |
| } catch (SWTException ex) { |
| // broken image |
| setImageDescriptor(defaultWizardIconDescriptor); |
| } |
| } |
| }); |
| } |
| }, branding.getWizardIcon(), defaultWizardIconDescriptor); |
| } |
| disableTabSelection = false; |
| } |
| |
| private boolean hasFavoritedTab(ICatalogBranding branding) { |
| if (branding.hasFavoritesTab()) { |
| return true; |
| } |
| CatalogDescriptor catalogDescriptor = this.configuration.getCatalogDescriptor(); |
| if (catalogDescriptor == null) { |
| return false; |
| } |
| URL url = catalogDescriptor.getUrl(); |
| IUserFavoritesService favoritesService = url == null ? null |
| : ServiceHelper.getMarketplaceServiceLocator().getFavoritesService(url.toString()); |
| return favoritesService != null; |
| } |
| |
| private String getFavoritedTabName(ICatalogBranding branding) { |
| String favoritesTabName = branding.getFavoritesTabName(); |
| if (favoritesTabName == null) { |
| return Messages.MarketplacePage_favorites; |
| } |
| return favoritesTabName; |
| } |
| |
| private boolean hasFeaturedMarketTab(ICatalogBranding branding) { |
| if (branding.hasFeaturedMarketTab()) { |
| String marketName = branding.getFeaturedMarketTabName(); |
| if (marketName != null && marketName.length() > 0) { |
| List<IMarket> markets = getCatalog().getMarkets(); |
| for (IMarket market : markets) { |
| if (marketName.equals(market.getName())) { |
| return true; |
| } |
| } |
| } |
| } |
| return false; |
| } |
| |
| private TabItem updateTab(TabItem tabItem, ContentType contentType, String widgetId, String tabLabel, |
| boolean hasTab, boolean hadTab, |
| int tabIndex) { |
| if (hasTab) { |
| if (!hadTab) { |
| tabItem = createCatalogTab(tabIndex, contentType, widgetId, tabLabel); |
| } else { |
| tabItem.setText(tabLabel); |
| } |
| } else if (tabItem != null && !tabItem.isDisposed()) { |
| tabItem.dispose(); |
| } |
| return tabItem; |
| } |
| |
| private ICatalogBranding getDefaultBranding() { |
| CatalogBranding branding = new CatalogBranding(); |
| branding.setHasSearchTab(true); |
| branding.setHasPopularTab(true); |
| branding.setHasRecentTab(true); |
| branding.setHasRelatedTab(false); |
| branding.setHasFavoritesTab(false); |
| branding.setHasFeaturedMarketTab(false); |
| branding.setSearchTabName(Messages.MarketplacePage_search); |
| branding.setPopularTabName(Messages.MarketplacePage_popular); |
| branding.setRecentTabName(Messages.MarketplacePage_recent); |
| branding.setRelatedTabName(Messages.MarketplacePage_related); |
| branding.setFeaturedMarketTabName(Messages.MarketplacePage_featuredMarket); |
| branding.setFavoritesTabName(Messages.MarketplacePage_favorites); |
| branding.setWizardTitle(Messages.MarketplacePage_eclipseMarketplaceSolutions); |
| branding.setWizardIcon(null); |
| return branding; |
| } |
| |
| public IStatus showMarketplace(CatalogDescriptor catalogDescriptor) { |
| if (configuration.getCatalogDescriptor() != catalogDescriptor) { |
| if (getWizard().getSelectionModel().getSelectedCatalogItems().size() > 0) { |
| boolean discardSelection = MessageDialog.openConfirm(getShell(), |
| Messages.MarketplacePage_selectionSolutions, Messages.MarketplacePage_discardPendingSolutions); |
| if (discardSelection) { |
| getWizard().getSelectionModel().clear(); |
| updateSelectionLink(); |
| } else { |
| if (marketplaceSwitcher != null) { |
| if (lastSelection == null) { |
| lastSelection = configuration.getCatalogDescriptor(); |
| } |
| marketplaceSwitcher.setSelection(new StructuredSelection(lastSelection)); |
| } |
| return Status.CANCEL_STATUS; |
| } |
| } |
| lastSelection = catalogDescriptor; |
| configuration.setCatalogDescriptor(catalogDescriptor); |
| if (marketplaceSwitcher != null) { |
| marketplaceSwitcher.setSelection(new StructuredSelection(catalogDescriptor)); |
| } |
| updateCatalog(); |
| } |
| return Status.OK_STATUS; |
| } |
| |
| private void updateCatalog() { |
| try { |
| getContainer().run(false, true, new IRunnableWithProgress() { |
| |
| public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { |
| if (getViewer().getControl().isDisposed()) { |
| return; |
| } |
| getWizard().initializeCatalog(); |
| safeUpdateCatalog(); |
| } |
| }); |
| } catch (InvocationTargetException e) { |
| MarketplaceClientUi.error(e.getCause()); |
| } catch (InterruptedException e) { |
| //cancelled, ignore this |
| } |
| } |
| |
| public void showNews(CatalogDescriptor catalogDescriptor) { |
| IStatus proceed = Status.OK_STATUS; |
| if (catalogDescriptor != null) { |
| proceed = showMarketplace(catalogDescriptor); |
| } |
| if (proceed.isOK()) { |
| setActiveTab(newsTabItem); |
| } |
| } |
| |
| public void show(CatalogDescriptor catalogDescriptor, MarketplaceViewer.ContentType content) { |
| IStatus proceed = Status.OK_STATUS; |
| if (catalogDescriptor != null) { |
| proceed = showMarketplace(catalogDescriptor); |
| } |
| if (proceed.isOK()) { |
| setActiveTab(content); |
| } |
| } |
| |
| public void show(CatalogDescriptor catalogDescriptor, final Set<? extends INode> nodes) { |
| IStatus proceed = Status.OK_STATUS; |
| if (catalogDescriptor != null) { |
| proceed = showMarketplace(catalogDescriptor); |
| } |
| if (proceed.isOK()) { |
| setActiveTab(searchTabItem); |
| getViewer().show(nodes); |
| } |
| } |
| |
| public void search(CatalogDescriptor catalogDescriptor, final IMarket searchMarket, final ICategory searchCategory, |
| final String searchString) { |
| IStatus proceed = Status.OK_STATUS; |
| if (catalogDescriptor != null) { |
| proceed = showMarketplace(catalogDescriptor); |
| } |
| if (proceed.isOK()) { |
| setActiveTab(searchTabItem); |
| getViewer().search(searchMarket, searchCategory, searchString); |
| } |
| } |
| |
| protected void initialize(WizardState initialState) { |
| ContentType contentType = initialState.getContentType(); |
| if (contentType != null && contentType != ContentType.SEARCH) { |
| show(configuration.getCatalogDescriptor(), contentType); |
| } else if (initialState.getContent() != null && !initialState.getContent().isEmpty()) { |
| show(configuration.getCatalogDescriptor(), initialState.getContent()); |
| } else { |
| IMarket market = initialState.getFilterMarket(); |
| ICategory category = initialState.getFilterCategory(); |
| String query = initialState.getFilterQuery(); |
| if (market != null || category != null || query != null) { |
| search(configuration.getCatalogDescriptor(), market, category, query); |
| } |
| } |
| } |
| |
| protected void addActionLink(int pos, ActionLink actionLink) { |
| doAddActionLink(pos, actionLink); |
| updateContentListLinks(); |
| } |
| |
| private void doAddActionLink(int pos, ActionLink actionLink) { |
| ActionLink existingAction = actions.get(actionLink.getId()); |
| if (existingAction != null && existingAction != actionLink) { |
| throw new IllegalArgumentException(); |
| } |
| int insertIndex = pos == -1 || pos > actionLinks.size() ? actionLinks.size() : pos; |
| actionLinks.add(insertIndex, actionLink); |
| actions.put(actionLink.getId(), actionLink); |
| } |
| |
| protected void removeActionLink(ActionLink actionLink) { |
| doRemoveActionLink(actionLink); |
| updateContentListLinks(); |
| } |
| |
| private void doRemoveActionLink(ActionLink actionLink) { |
| actionLinks.remove(actionLink); |
| if (actions.get(actionLink.getId()) == actionLink) { |
| actions.remove(actionLink.getId()); |
| } |
| } |
| |
| protected void updateActionLink(ActionLink oldLink, ActionLink newLink) { |
| if (oldLink == newLink) { |
| return; |
| } |
| doUpdateActionLink(oldLink, newLink); |
| updateContentListLinks(); |
| } |
| |
| private void doUpdateActionLink(ActionLink oldLink, ActionLink newLink) { |
| int index = actionLinks.indexOf(oldLink); |
| if (index != -1) { |
| String id = oldLink.getId(); |
| if (actions.get(id) != oldLink) { |
| throw new IllegalArgumentException(); |
| } |
| if (!id.equals(newLink.getId())) { |
| throw new IllegalArgumentException(); |
| } |
| actionLinks.set(index, newLink); |
| actions.put(id, newLink); |
| } else { |
| throw new NoSuchElementException(); |
| } |
| } |
| |
| @Override |
| public MarketplaceCatalog getCatalog() { |
| return (MarketplaceCatalog) super.getCatalog(); |
| } |
| |
| @Override |
| public void dispose() { |
| if (marketplaceSwitcher != null) { |
| marketplaceSwitcher.dispose(); |
| } |
| super.dispose(); |
| } |
| |
| public void reloadCatalog() { |
| getViewer().reload(); |
| } |
| |
| public String getNextButtonLabel() { |
| return Messages.MarketplaceWizardDialog_Install_Now; |
| } |
| |
| public String getBackButtonLabel() { |
| return null; |
| } |
| } |