blob: b4d41210949cc2cd62a2891e49a727f3b23bba2a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2015 Tasktop Technologies and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*
* Tasktop Technologies - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.internal.discovery.ui.wizards;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.jface.resource.FontDescriptor;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.mylyn.commons.ui.CommonImages;
import org.eclipse.mylyn.commons.ui.GradientCanvas;
import org.eclipse.mylyn.commons.ui.SelectionProviderAdapter;
import org.eclipse.mylyn.commons.ui.compatibility.CommonThemes;
import org.eclipse.mylyn.commons.workbench.browser.BrowserUtil;
import org.eclipse.mylyn.internal.discovery.core.model.AbstractDiscoverySource;
import org.eclipse.mylyn.internal.discovery.core.model.BundleDiscoveryStrategy;
import org.eclipse.mylyn.internal.discovery.core.model.ConnectorDescriptor;
import org.eclipse.mylyn.internal.discovery.core.model.ConnectorDescriptorKind;
import org.eclipse.mylyn.internal.discovery.core.model.ConnectorDiscovery;
import org.eclipse.mylyn.internal.discovery.core.model.DiscoveryCategory;
import org.eclipse.mylyn.internal.discovery.core.model.DiscoveryConnector;
import org.eclipse.mylyn.internal.discovery.core.model.Icon;
import org.eclipse.mylyn.internal.discovery.core.model.Overview;
import org.eclipse.mylyn.internal.discovery.core.model.RemoteBundleDiscoveryStrategy;
import org.eclipse.mylyn.internal.discovery.core.util.DiscoveryCategoryComparator;
import org.eclipse.mylyn.internal.discovery.core.util.DiscoveryConnectorComparator;
import org.eclipse.mylyn.internal.discovery.ui.DiscoveryImages;
import org.eclipse.mylyn.internal.discovery.ui.DiscoveryUi;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleControlAdapter;
import org.eclipse.swt.accessibility.AccessibleControlEvent;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Resource;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
import org.eclipse.ui.forms.IFormColors;
import org.eclipse.ui.progress.WorkbenchJob;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.ui.themes.IThemeManager;
import org.osgi.framework.Bundle;
import org.osgi.framework.Version;
/**
* The main wizard page that allows users to select connectors that they wish to install.
*
* @author David Green
* @author Steffen Pingel
*/
public class DiscoveryViewer {
public class ConnectorBorderPaintListener implements PaintListener {
public void paintControl(PaintEvent e) {
Composite composite = (Composite) e.widget;
Rectangle bounds = composite.getBounds();
GC gc = e.gc;
gc.setLineStyle(SWT.LINE_DOT);
gc.drawLine(bounds.x, bounds.y, bounds.x + bounds.width, bounds.y);
}
}
private class ConnectorDescriptorItemUi implements PropertyChangeListener, Runnable {
private final DiscoveryConnector connector;
private final Button checkbox;
private final Label iconLabel;
private final Label nameLabel;
private ToolItem infoButton;
private final Link providerLabel;
private final Label description;
private final Composite checkboxAndIconContainer;
private final Composite checkboxContainer;
private final Composite connectorContainer;
private final Display display;
private Image iconImage;
// private Image warningIconImage;
public ConnectorDescriptorItemUi(final DiscoveryConnector connector, Composite categoryChildrenContainer,
Color background) {
display = categoryChildrenContainer.getDisplay();
this.connector = connector;
connector.addPropertyChangeListener(this);
connectorContainer = new Composite(categoryChildrenContainer, SWT.NULL);
configureLook(connectorContainer, background);
GridDataFactory.fillDefaults().grab(true, false).applyTo(connectorContainer);
GridLayout layout = new GridLayout(4, false);
layout.marginLeft = 7;
layout.marginTop = 2;
layout.marginBottom = 2;
connectorContainer.setLayout(layout);
checkboxAndIconContainer = new Composite(connectorContainer, SWT.NULL);
configureLook(checkboxAndIconContainer, background);
GridDataFactory.swtDefaults().align(SWT.CENTER, SWT.BEGINNING).span(1, 2).applyTo(checkboxAndIconContainer);
GridLayoutFactory.fillDefaults().spacing(1, 1).numColumns(2).applyTo(checkboxAndIconContainer);
checkboxContainer = new Composite(checkboxAndIconContainer, SWT.NULL);
GridLayout checkboxLayout = new GridLayout(1, false);
checkboxLayout.marginRight = 7;
checkboxContainer.setLayout(checkboxLayout);
configureLook(checkboxContainer, background);
checkbox = new Button(checkboxContainer, SWT.CHECK);
// help UI tests
checkbox.setData("connectorId", connector.getId()); //$NON-NLS-1$
checkbox.setVisible(connector.isInstallable());
checkbox.setSelection(installableConnectors.contains(connector));
checkbox.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
bodyScrolledComposite.showControl(connectorContainer);
}
});
GridDataFactory.swtDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(checkbox);
iconLabel = new Label(checkboxAndIconContainer, SWT.NULL);
configureLook(iconLabel, background);
GridDataFactory.swtDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(iconLabel);
if (connector.getIcon() != null) {
iconImage = computeIconImage(connector.getSource(), connector.getIcon(), 32, false);
if (iconImage != null) {
iconLabel.setImage(iconImage);
}
}
nameLabel = new Label(connectorContainer, SWT.NULL);
configureLook(nameLabel, background);
GridDataFactory.fillDefaults().grab(true, false).align(SWT.BEGINNING, SWT.CENTER).applyTo(nameLabel);
nameLabel.setFont(h2Font);
if (connector.isInstalled()) {
nameLabel.setText(NLS.bind(Messages.DiscoveryViewer_X_installed, connector.getName()));
} else {
nameLabel.setText(connector.getName());
}
providerLabel = new Link(connectorContainer, SWT.RIGHT);
configureLook(providerLabel, background);
GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(providerLabel);
if (connector.getCertification() != null) {
providerLabel.setText(NLS.bind(Messages.DiscoveryViewer_Certification_Label0,
new String[] { connector.getProvider(), connector.getLicense(),
connector.getCertification().getName() }));
if (connector.getCertification().getUrl() != null) {
providerLabel.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
BrowserUtil.openUrl(connector.getCertification().getUrl(),
IWorkbenchBrowserSupport.AS_EXTERNAL);
}
});
}
Overview overview = new Overview();
overview.setSummary(connector.getCertification().getDescription());
overview.setUrl(connector.getCertification().getUrl());
Image image = computeIconImage(connector.getSource(), connector.getCertification().getIcon(), 48, true);
hookTooltip(providerLabel, providerLabel, connectorContainer, providerLabel, connector.getSource(),
overview, image);
} else {
providerLabel.setText(NLS.bind(Messages.ConnectorDiscoveryWizardMainPage_provider_and_license,
connector.getProvider(), connector.getLicense()));
}
if (hasTooltip(connector)) {
ToolBar toolBar = new ToolBar(connectorContainer, SWT.FLAT);
toolBar.setBackground(background);
infoButton = new ToolItem(toolBar, SWT.PUSH);
infoButton.setImage(infoImage);
infoButton.setToolTipText(Messages.ConnectorDiscoveryWizardMainPage_tooltip_showOverview);
hookTooltip(toolBar, infoButton, connectorContainer, nameLabel, connector.getSource(),
connector.getOverview(), null);
GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(toolBar);
} else {
Label label = new Label(connectorContainer, SWT.NULL);
label.setText(" "); //$NON-NLS-1$
configureLook(label, background);
}
description = new Label(connectorContainer, SWT.NULL | SWT.WRAP);
configureLook(description, background);
GridDataFactory.fillDefaults().grab(true, false).span(3, 1).hint(100, SWT.DEFAULT).applyTo(description);
String descriptionText = connector.getDescription();
int maxDescriptionLength = 162;
if (descriptionText.length() > maxDescriptionLength) {
descriptionText = descriptionText.substring(0, maxDescriptionLength);
}
description.setText(descriptionText.replaceAll("(\\r\\n)|\\n|\\r", " ")); //$NON-NLS-1$ //$NON-NLS-2$
// always disabled color to make it less prominent
providerLabel.setForeground(colorDisabled);
checkbox.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
public void widgetSelected(SelectionEvent e) {
boolean selected = checkbox.getSelection();
maybeModifySelection(selected);
}
});
MouseListener connectorItemMouseListener = new MouseAdapter() {
@Override
public void mouseUp(MouseEvent e) {
boolean selected = !checkbox.getSelection();
if (maybeModifySelection(selected)) {
checkbox.setSelection(selected);
}
}
};
checkboxAndIconContainer.addMouseListener(connectorItemMouseListener);
checkboxContainer.addMouseListener(connectorItemMouseListener);
connectorContainer.addMouseListener(connectorItemMouseListener);
iconLabel.addMouseListener(connectorItemMouseListener);
nameLabel.addMouseListener(connectorItemMouseListener);
// the provider has clickable links
//providerLabel.addMouseListener(connectorItemMouseListener);
description.addMouseListener(connectorItemMouseListener);
}
protected boolean maybeModifySelection(boolean selected) {
if (selected) {
if (connector.isInstalled()) {
MessageDialog.openWarning(shellProvider.getShell(),
Messages.DiscoveryViewer_Install_Connector_Title,
NLS.bind(Messages.DiscoveryViewer_Already_installed_Error, connector.getName()));
return false;
}
if (!connector.isInstallable()) {
if (connector.getInstallMessage() != null) {
MessageDialog.openInformation(shellProvider.getShell(),
Messages.DiscoveryViewer_Install_Connector_Title, connector.getInstallMessage());
}
return false;
}
if (connector.getAvailable() != null && !connector.getAvailable()) {
MessageDialog.openWarning(shellProvider.getShell(),
Messages.ConnectorDiscoveryWizardMainPage_warningTitleConnectorUnavailable, NLS.bind(
Messages.ConnectorDiscoveryWizardMainPage_warningMessageConnectorUnavailable,
connector.getName()));
return false;
}
}
DiscoveryViewer.this.modifySelection(connector, selected);
return true;
}
public void propertyChange(PropertyChangeEvent evt) {
display.asyncExec(this);
}
public void run() {
if (!connectorContainer.isDisposed()) {
updateAvailability();
}
}
public void updateAvailability() {
boolean enabled = !connector.isInstalled()
&& (connector.getAvailable() == null || connector.getAvailable());
checkbox.setEnabled(enabled);
nameLabel.setEnabled(enabled);
providerLabel.setEnabled(enabled);
description.setEnabled(enabled);
Color foreground;
if (enabled) {
foreground = connectorContainer.getForeground();
} else {
foreground = colorDisabled;
}
nameLabel.setForeground(foreground);
description.setForeground(foreground);
if (iconImage != null) {
// boolean unavailable = !enabled && connector.getAvailable() != null;
// if (unavailable) {
// if (warningIconImage == null) {
// warningIconImage = new DecorationOverlayIcon(iconImage, DiscoveryImages.OVERLAY_WARNING_32,
// IDecoration.BOTTOM_RIGHT).createImage();
// disposables.add(warningIconImage);
// }
// iconLabel.setImage(warningIconImage);
// } else if (warningIconImage != null) {
iconLabel.setImage(iconImage);
// }
}
}
}
private static final int MINIMUM_HEIGHT = 100;
private static boolean useNativeSearchField(Composite composite) {
if (useNativeSearchField == null) {
useNativeSearchField = Boolean.FALSE;
Text testText = null;
try {
testText = new Text(composite, SWT.SEARCH | SWT.ICON_CANCEL);
useNativeSearchField = Boolean.valueOf((testText.getStyle() & SWT.ICON_CANCEL) != 0);
} finally {
if (testText != null) {
testText.dispose();
}
}
}
return useNativeSearchField;
}
private boolean showConnectorDescriptorKindFilter;
private boolean showConnectorDescriptorTextFilter;
private static final String COLOR_WHITE = "white"; //$NON-NLS-1$
private static final String COLOR_DARK_GRAY = "DarkGray"; //$NON-NLS-1$
private static Boolean useNativeSearchField;
private final List<ConnectorDescriptor> installableConnectors = new ArrayList<ConnectorDescriptor>();
private volatile ConnectorDiscovery discovery;
private Composite body;
private final List<Resource> disposables;
private Font h2Font;
private Font h1Font;
private Color colorWhite;
private Text filterText;
private WorkbenchJob refreshJob;
private String previousFilterText = ""; //$NON-NLS-1$
private Pattern filterPattern;
private Label clearFilterTextControl;
private Set<String> installedFeatures;
private Image infoImage;
private Cursor handCursor;
private Color colorCategoryGradientStart;
private Color colorCategoryGradientEnd;
private Color colorDisabled;
private ScrolledComposite bodyScrolledComposite;
private boolean verifyUpdateSiteAvailability;
private final Map<ConnectorDescriptorKind, Boolean> connectorDescriptorKindToVisibility = new HashMap<ConnectorDescriptorKind, Boolean>();
{
for (ConnectorDescriptorKind kind : ConnectorDescriptorKind.values()) {
connectorDescriptorKindToVisibility.put(kind, true);
}
}
private Dictionary<Object, Object> environment;
private boolean complete;
private final IRunnableContext context;
private final IShellProvider shellProvider;
private Control control;
private String directoryUrl;
private final SelectionProviderAdapter selectionProvider;
private List<DiscoveryConnector> allConnectors;
private int minimumHeight;
private final List<ViewerFilter> filters = new ArrayList<ViewerFilter>();
private boolean showInstalledFilterEnabled;
private boolean showInstalled;
public DiscoveryViewer(IShellProvider shellProvider, IRunnableContext context) {
this.shellProvider = shellProvider;
this.context = context;
this.selectionProvider = new SelectionProviderAdapter();
this.allConnectors = Collections.emptyList();
this.disposables = new ArrayList<Resource>();
setShowConnectorDescriptorKindFilter(true);
setShowConnectorDescriptorTextFilter(true);
setMinimumHeight(MINIMUM_HEIGHT);
createEnvironment();
setComplete(false);
}
public void addSelectionChangedListener(ISelectionChangedListener listener) {
selectionProvider.addSelectionChangedListener(listener);
}
private void clearDisposables() {
disposables.clear();
h1Font = null;
h2Font = null;
infoImage = null;
handCursor = null;
colorCategoryGradientStart = null;
colorCategoryGradientEnd = null;
}
private void clearFilterText() {
filterText.setText(""); //$NON-NLS-1$
filterTextChanged();
}
private Image computeIconImage(AbstractDiscoverySource discoverySource, Icon icon, int dimension, boolean fallback) {
String imagePath;
switch (dimension) {
case 64:
imagePath = icon.getImage64();
if (imagePath != null || !fallback) {
break;
}
case 48:
imagePath = icon.getImage48();
if (imagePath != null || !fallback) {
break;
}
case 32:
imagePath = icon.getImage32();
break;
default:
throw new IllegalArgumentException();
}
if (imagePath != null && imagePath.length() > 0) {
URL resource = discoverySource.getResource(imagePath);
if (resource != null) {
ImageDescriptor descriptor = ImageDescriptor.createFromURL(resource);
Image image = descriptor.createImage();
if (image != null) {
disposables.add(image);
return image;
}
}
}
return null;
}
private IStatus computeStatus(InvocationTargetException e, String message) {
Throwable cause = e.getCause();
IStatus statusCause;
if (cause instanceof CoreException) {
statusCause = ((CoreException) cause).getStatus();
} else {
statusCause = new Status(IStatus.ERROR, DiscoveryUi.ID_PLUGIN, cause.getMessage(), cause);
}
if (statusCause.getMessage() != null) {
message = NLS.bind(Messages.ConnectorDiscoveryWizardMainPage_message_with_cause, message,
statusCause.getMessage());
}
IStatus status = new MultiStatus(DiscoveryUi.ID_PLUGIN, 0, new IStatus[] { statusCause }, message, cause);
return status;
}
private void configureLook(Control control, Color background) {
control.setBackground(background);
}
/**
* cause the UI to respond to a change in visibility filters
*
* @see #setVisibility(ConnectorDescriptorKind, boolean)
*/
public void connectorDescriptorKindVisibilityUpdated() {
createBodyContents();
}
public void createBodyContents() {
// remove any existing contents
for (Control child : body.getChildren()) {
child.dispose();
}
clearDisposables();
allConnectors = new ArrayList<DiscoveryConnector>();
initializeCursors();
initializeImages();
initializeFonts();
initializeColors();
GridLayoutFactory.fillDefaults().applyTo(body);
bodyScrolledComposite = new ScrolledComposite(body, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
configureLook(bodyScrolledComposite, colorWhite);
GridDataFactory.fillDefaults().grab(true, true).applyTo(bodyScrolledComposite);
final Composite scrolledContents = new Composite(bodyScrolledComposite, SWT.NONE);
configureLook(scrolledContents, colorWhite);
scrolledContents.setRedraw(false);
try {
createDiscoveryContents(scrolledContents);
} finally {
scrolledContents.layout(true);
scrolledContents.setRedraw(true);
}
Point size = scrolledContents.computeSize(body.getSize().x, SWT.DEFAULT, true);
scrolledContents.setSize(size);
bodyScrolledComposite.setExpandHorizontal(true);
bodyScrolledComposite.setMinWidth(100);
bodyScrolledComposite.setExpandVertical(true);
bodyScrolledComposite.setMinHeight(1);
bodyScrolledComposite.addControlListener(new ControlAdapter() {
@Override
public void controlResized(ControlEvent e) {
// XXX small offset in case list has a scroll bar
Point size = scrolledContents.computeSize(body.getSize().x - 20, SWT.DEFAULT, true);
scrolledContents.setSize(size);
bodyScrolledComposite.setMinHeight(size.y);
}
});
bodyScrolledComposite.setContent(scrolledContents);
Dialog.applyDialogFont(body);
// we've changed it so it needs to know
body.layout(true);
}
private Label createClearFilterTextControl(Composite filterContainer, final Text filterText) {
final Image inactiveImage = CommonImages.FIND_CLEAR_DISABLED.createImage();
final Image activeImage = CommonImages.FIND_CLEAR.createImage();
final Image pressedImage = new Image(filterContainer.getDisplay(), activeImage, SWT.IMAGE_GRAY);
final Label clearButton = new Label(filterContainer, SWT.NONE);
clearButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false));
clearButton.setImage(inactiveImage);
clearButton.setToolTipText(Messages.ConnectorDiscoveryWizardMainPage_clearButton_toolTip);
clearButton.setBackground(filterContainer.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
clearButton.addMouseListener(new MouseAdapter() {
private MouseMoveListener fMoveListener;
private boolean isMouseInButton(MouseEvent e) {
Point buttonSize = clearButton.getSize();
return 0 <= e.x && e.x < buttonSize.x && 0 <= e.y && e.y < buttonSize.y;
}
@Override
public void mouseDown(MouseEvent e) {
clearButton.setImage(pressedImage);
fMoveListener = new MouseMoveListener() {
private boolean fMouseInButton = true;
public void mouseMove(MouseEvent e) {
boolean mouseInButton = isMouseInButton(e);
if (mouseInButton != fMouseInButton) {
fMouseInButton = mouseInButton;
clearButton.setImage(mouseInButton ? pressedImage : inactiveImage);
}
}
};
clearButton.addMouseMoveListener(fMoveListener);
}
@Override
public void mouseUp(MouseEvent e) {
if (fMoveListener != null) {
clearButton.removeMouseMoveListener(fMoveListener);
fMoveListener = null;
boolean mouseInButton = isMouseInButton(e);
clearButton.setImage(mouseInButton ? activeImage : inactiveImage);
if (mouseInButton) {
clearFilterText();
filterText.setFocus();
}
}
}
});
clearButton.addMouseTrackListener(new MouseTrackListener() {
public void mouseEnter(MouseEvent e) {
clearButton.setImage(activeImage);
}
public void mouseExit(MouseEvent e) {
clearButton.setImage(inactiveImage);
}
public void mouseHover(MouseEvent e) {
}
});
clearButton.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
inactiveImage.dispose();
activeImage.dispose();
pressedImage.dispose();
}
});
clearButton.getAccessible().addAccessibleListener(new AccessibleAdapter() {
@Override
public void getName(AccessibleEvent e) {
e.result = Messages.ConnectorDiscoveryWizardMainPage_clearButton_accessibleListener;
}
});
clearButton.getAccessible().addAccessibleControlListener(new AccessibleControlAdapter() {
@Override
public void getRole(AccessibleControlEvent e) {
e.detail = ACC.ROLE_PUSHBUTTON;
}
});
return clearButton;
}
public void createControl(Composite parent) {
createRefreshJob();
Composite container = new Composite(parent, SWT.NULL);
container.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
refreshJob.cancel();
if (disposables != null) {
for (Resource resource : disposables) {
resource.dispose();
}
clearDisposables();
}
if (discovery != null) {
discovery.dispose();
}
}
});
GridLayout layout = new GridLayout(1, false);
layout.marginHeight = 0;
layout.marginWidth = 0;
container.setLayout(layout);
//
{ // header
Composite header = new Composite(container, SWT.NULL);
GridLayoutFactory.fillDefaults().applyTo(header);
GridDataFactory.fillDefaults().grab(true, false).applyTo(header);
// TODO: refresh button?
if (isShowConnectorDescriptorKindFilter() || isShowConnectorDescriptorTextFilter()) {
Composite filterContainer = new Composite(header, SWT.NULL);
GridDataFactory.fillDefaults().grab(true, false).applyTo(filterContainer);
Label label = new Label(filterContainer, SWT.NULL);
label.setText(Messages.ConnectorDiscoveryWizardMainPage_filterLabel);
if (isShowConnectorDescriptorTextFilter()) {
Composite textFilterContainer;
boolean nativeSearch = useNativeSearchField(header);
if (nativeSearch) {
textFilterContainer = new Composite(filterContainer, SWT.NULL);
} else {
textFilterContainer = new Composite(filterContainer, SWT.BORDER);
textFilterContainer.setBackground(header.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
}
GridDataFactory.fillDefaults().grab(true, false).applyTo(textFilterContainer);
GridLayoutFactory.fillDefaults().numColumns(2).applyTo(textFilterContainer);
if (nativeSearch) {
filterText = new Text(textFilterContainer, SWT.SINGLE | SWT.BORDER | SWT.SEARCH
| SWT.ICON_CANCEL);
} else {
filterText = new Text(textFilterContainer, SWT.SINGLE);
}
filterText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
filterTextChanged();
}
});
if (nativeSearch) {
filterText.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {
if (e.detail == SWT.ICON_CANCEL) {
clearFilterText();
}
}
});
GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(filterText);
} else {
GridDataFactory.fillDefaults().grab(true, false).applyTo(filterText);
clearFilterTextControl = createClearFilterTextControl(textFilterContainer, filterText);
clearFilterTextControl.setVisible(false);
}
}
if (isShowInstalledFilterEnabled()) {
final Button checkbox = new Button(filterContainer, SWT.CHECK);
checkbox.setSelection(false);
checkbox.setText(Messages.DiscoveryViewer_Show_Installed);
checkbox.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
public void widgetSelected(SelectionEvent e) {
setShowInstalled(checkbox.getSelection());
}
});
}
if (isShowConnectorDescriptorKindFilter()) { // filter
// buttons
for (final ConnectorDescriptorKind kind : ConnectorDescriptorKind.values()) {
final Button checkbox = new Button(filterContainer, SWT.CHECK);
checkbox.setSelection(isVisible(kind));
checkbox.setText(getFilterLabel(kind));
checkbox.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
public void widgetSelected(SelectionEvent e) {
boolean selection = checkbox.getSelection();
setVisibility(kind, selection);
connectorDescriptorKindVisibilityUpdated();
}
});
}
}
GridLayoutFactory.fillDefaults()
.numColumns(filterContainer.getChildren().length)
.applyTo(filterContainer);
}
}
{ // container
body = new Composite(container, SWT.NULL);
GridDataFactory.fillDefaults().grab(true, true).hint(SWT.DEFAULT, minimumHeight).applyTo(body);
}
Dialog.applyDialogFont(container);
setControl(container);
}
public void setMinimumHeight(int minimumHeight) {
this.minimumHeight = minimumHeight;
if (body != null) {
GridDataFactory.fillDefaults().grab(true, true).hint(SWT.DEFAULT, minimumHeight).applyTo(body);
}
}
public static int getMinimumHeight() {
return MINIMUM_HEIGHT;
}
private void createDiscoveryContents(Composite container) {
Color background = container.getBackground();
if (discovery == null || isEmpty(discovery)) {
GridLayoutFactory.fillDefaults().margins(5, 5).applyTo(container);
boolean atLeastOneKindFiltered = false;
for (ConnectorDescriptorKind kind : ConnectorDescriptorKind.values()) {
if (!isVisible(kind)) {
atLeastOneKindFiltered = true;
break;
}
}
Control helpTextControl;
if (filterPattern != null) {
Link link = new Link(container, SWT.WRAP);
link.setFont(container.getFont());
link.setText(Messages.ConnectorDiscoveryWizardMainPage_noMatchingItems_withFilterText);
link.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
clearFilterText();
filterText.setFocus();
}
});
helpTextControl = link;
} else {
Label helpText = new Label(container, SWT.WRAP);
helpText.setFont(container.getFont());
if (atLeastOneKindFiltered) {
helpText.setText(Messages.ConnectorDiscoveryWizardMainPage_noMatchingItems_filteredType);
} else {
helpText.setText(Messages.ConnectorDiscoveryWizardMainPage_noMatchingItems_noFilter);
}
helpTextControl = helpText;
}
configureLook(helpTextControl, background);
GridDataFactory.fillDefaults().grab(true, false).hint(100, SWT.DEFAULT).applyTo(helpTextControl);
} else {
GridLayoutFactory.fillDefaults().numColumns(2).spacing(0, 0).applyTo(container);
List<DiscoveryCategory> categories = new ArrayList<DiscoveryCategory>(discovery.getCategories());
Collections.sort(categories, new DiscoveryCategoryComparator());
Composite categoryChildrenContainer = null;
for (DiscoveryCategory category : categories) {
if (isEmpty(category)) {
// don't add empty categories
continue;
}
{ // category header
final GradientCanvas categoryHeaderContainer = new GradientCanvas(container, SWT.NONE);
categoryHeaderContainer.setSeparatorVisible(true);
categoryHeaderContainer.setSeparatorAlignment(SWT.TOP);
categoryHeaderContainer.setBackgroundGradient(new Color[] { colorCategoryGradientStart,
colorCategoryGradientEnd }, new int[] { 100 }, true);
categoryHeaderContainer.putColor(IFormColors.H_BOTTOM_KEYLINE1, colorCategoryGradientStart);
categoryHeaderContainer.putColor(IFormColors.H_BOTTOM_KEYLINE2, colorCategoryGradientEnd);
GridDataFactory.fillDefaults().span(2, 1).applyTo(categoryHeaderContainer);
GridLayoutFactory.fillDefaults()
.numColumns(3)
.margins(5, 5)
.equalWidth(false)
.applyTo(categoryHeaderContainer);
Label iconLabel = new Label(categoryHeaderContainer, SWT.NULL);
if (category.getIcon() != null) {
Image image = computeIconImage(category.getSource(), category.getIcon(), 48, true);
if (image != null) {
iconLabel.setImage(image);
}
}
iconLabel.setBackground(null);
GridDataFactory.swtDefaults().align(SWT.CENTER, SWT.BEGINNING).span(1, 2).applyTo(iconLabel);
Label nameLabel = new Label(categoryHeaderContainer, SWT.NULL);
nameLabel.setFont(h1Font);
nameLabel.setText(category.getName());
nameLabel.setBackground(null);
GridDataFactory.fillDefaults().grab(true, false).applyTo(nameLabel);
if (hasTooltip(category)) {
ToolBar toolBar = new ToolBar(categoryHeaderContainer, SWT.FLAT);
toolBar.setBackground(null);
ToolItem infoButton = new ToolItem(toolBar, SWT.PUSH);
infoButton.setImage(infoImage);
infoButton.setToolTipText(Messages.ConnectorDiscoveryWizardMainPage_tooltip_showOverview);
hookTooltip(toolBar, infoButton, categoryHeaderContainer, nameLabel, category.getSource(),
category.getOverview(), null);
GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(toolBar);
} else {
new Label(categoryHeaderContainer, SWT.NULL).setText(" "); //$NON-NLS-1$
}
Label description = new Label(categoryHeaderContainer, SWT.WRAP);
GridDataFactory.fillDefaults()
.grab(true, false)
.span(2, 1)
.hint(100, SWT.DEFAULT)
.applyTo(description);
description.setBackground(null);
description.setText(category.getDescription());
}
categoryChildrenContainer = new Composite(container, SWT.NULL);
configureLook(categoryChildrenContainer, background);
GridDataFactory.fillDefaults().span(2, 1).grab(true, false).applyTo(categoryChildrenContainer);
GridLayoutFactory.fillDefaults().spacing(0, 0).applyTo(categoryChildrenContainer);
int numChildren = 0;
List<DiscoveryConnector> connectors = new ArrayList<DiscoveryConnector>(category.getConnectors());
Collections.sort(connectors, new DiscoveryConnectorComparator(category));
for (final DiscoveryConnector connector : connectors) {
if (isFiltered(connector)) {
continue;
}
if (++numChildren > 1) {
// a separator between connector descriptors
Composite border = new Composite(categoryChildrenContainer, SWT.NULL);
GridDataFactory.fillDefaults().grab(true, false).hint(SWT.DEFAULT, 1).applyTo(border);
GridLayoutFactory.fillDefaults().applyTo(border);
border.addPaintListener(new ConnectorBorderPaintListener());
}
ConnectorDescriptorItemUi itemUi = new ConnectorDescriptorItemUi(connector,
categoryChildrenContainer, background);
itemUi.updateAvailability();
allConnectors.add(connector);
}
}
// last one gets a border
Composite border = new Composite(categoryChildrenContainer, SWT.NULL);
GridDataFactory.fillDefaults().grab(true, false).hint(SWT.DEFAULT, 1).applyTo(border);
GridLayoutFactory.fillDefaults().applyTo(border);
border.addPaintListener(new ConnectorBorderPaintListener());
}
container.layout(true);
container.redraw();
}
private void createEnvironment() {
environment = new Hashtable<Object, Object>(System.getProperties());
// add the installed Mylyn version to the environment so that we can
// have
// connectors that are filtered based on version of Mylyn
Bundle bundle = Platform.getBundle("org.eclipse.mylyn.tasks.core"); //$NON-NLS-1$
String versionString = (String) bundle.getHeaders().get("Bundle-Version"); //$NON-NLS-1$
if (versionString != null) {
Version version = new Version(versionString);
environment.put("org.eclipse.mylyn.version", version.toString()); //$NON-NLS-1$
environment.put("org.eclipse.mylyn.version.major", version.getMajor()); //$NON-NLS-1$
environment.put("org.eclipse.mylyn.version.minor", version.getMinor()); //$NON-NLS-1$
environment.put("org.eclipse.mylyn.version.micro", version.getMicro()); //$NON-NLS-1$
}
}
protected Pattern createPattern(String filterText) {
if (filterText == null || filterText.length() == 0) {
return null;
}
String regex = filterText;
regex.replace("\\", "\\\\").replace("?", ".").replace("*", ".*?"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
return Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
}
private void createRefreshJob() {
refreshJob = new WorkbenchJob("filter") { //$NON-NLS-1$
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
if (filterText.isDisposed()) {
return Status.CANCEL_STATUS;
}
String text = filterText.getText();
text = text.trim();
if (!previousFilterText.equals(text)) {
previousFilterText = text;
filterPattern = createPattern(previousFilterText);
if (clearFilterTextControl != null) {
clearFilterTextControl.setVisible(filterPattern != null);
}
createBodyContents();
}
return Status.OK_STATUS;
}
};
refreshJob.setSystem(true);
}
private void discoveryUpdated(boolean wasCancelled) {
createBodyContents();
if (discovery != null && !wasCancelled) {
int categoryWithConnectorCount = 0;
for (DiscoveryCategory category : discovery.getCategories()) {
categoryWithConnectorCount += category.getConnectors().size();
}
if (categoryWithConnectorCount == 0) {
// nothing was discovered: notify the user
MessageDialog.openWarning(getShell(), Messages.ConnectorDiscoveryWizardMainPage_noConnectorsFound,
Messages.ConnectorDiscoveryWizardMainPage_noConnectorsFound_description);
}
}
selectionProvider.setSelection(StructuredSelection.EMPTY);
}
private boolean filterMatches(String text) {
return text != null && filterPattern.matcher(text).find();
}
private void filterTextChanged() {
refreshJob.cancel();
refreshJob.schedule(200L);
}
public Control getControl() {
return control;
}
public String getDirectoryUrl() {
return directoryUrl;
}
public ConnectorDiscovery getDiscovery() {
return discovery;
}
/**
* the environment in which discovery should be performed.
*
* @see ConnectorDiscovery#getEnvironment()
*/
public Dictionary<Object, Object> getEnvironment() {
return environment;
}
private String getFilterLabel(ConnectorDescriptorKind kind) {
switch (kind) {
case DOCUMENT:
return Messages.ConnectorDiscoveryWizardMainPage_filter_documents;
case TASK:
return Messages.ConnectorDiscoveryWizardMainPage_filter_tasks;
case VCS:
return Messages.ConnectorDiscoveryWizardMainPage_filter_vcs;
default:
throw new IllegalStateException(kind.name());
}
}
public String getFilterText() {
return filterText.getText();
}
public List<ConnectorDescriptor> getInstallableConnectors() {
return installableConnectors;
}
public IStructuredSelection getSelection() {
return (IStructuredSelection) selectionProvider.getSelection();
}
private Shell getShell() {
return shellProvider.getShell();
}
public boolean getVerifyUpdateSiteAvailability() {
return verifyUpdateSiteAvailability;
}
private boolean hasTooltip(final DiscoveryCategory category) {
return category.getOverview() != null && category.getOverview().getSummary() != null
&& category.getOverview().getSummary().length() > 0;
}
private boolean hasTooltip(final DiscoveryConnector connector) {
return connector.getOverview() != null && connector.getOverview().getSummary() != null
&& connector.getOverview().getSummary().length() > 0;
}
private void hookRecursively(Control control, Listener listener) {
control.addListener(SWT.Dispose, listener);
control.addListener(SWT.MouseHover, listener);
control.addListener(SWT.MouseMove, listener);
control.addListener(SWT.MouseExit, listener);
control.addListener(SWT.MouseDown, listener);
control.addListener(SWT.MouseWheel, listener);
if (control instanceof Composite) {
for (Control child : ((Composite) control).getChildren()) {
hookRecursively(child, listener);
}
}
}
private void hookTooltip(final Control parent, final Widget tipActivator, final Control exitControl,
final Control titleControl, AbstractDiscoverySource source, Overview overview, Image image) {
final OverviewToolTip toolTip = new OverviewToolTip(parent, source, overview, image);
Listener listener = new Listener() {
public void handleEvent(Event event) {
switch (event.type) {
case SWT.MouseHover:
toolTip.show(titleControl);
break;
case SWT.Dispose:
case SWT.MouseWheel:
toolTip.hide();
break;
}
}
};
tipActivator.addListener(SWT.Dispose, listener);
tipActivator.addListener(SWT.MouseWheel, listener);
if (image != null) {
tipActivator.addListener(SWT.MouseHover, listener);
}
Listener selectionListener = new Listener() {
public void handleEvent(Event event) {
toolTip.show(titleControl);
}
};
tipActivator.addListener(SWT.Selection, selectionListener);
Listener exitListener = new Listener() {
public void handleEvent(Event event) {
switch (event.type) {
case SWT.MouseWheel:
toolTip.hide();
break;
case SWT.MouseExit:
/*
* Check if the mouse exit happened because we move over the
* tooltip
*/
Rectangle containerBounds = exitControl.getBounds();
Point displayLocation = exitControl.getParent().toDisplay(containerBounds.x, containerBounds.y);
containerBounds.x = displayLocation.x;
containerBounds.y = displayLocation.y;
if (containerBounds.contains(Display.getCurrent().getCursorLocation())) {
break;
}
toolTip.hide();
break;
}
}
};
hookRecursively(exitControl, exitListener);
}
private void initializeColors() {
IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager();
if (colorWhite == null) {
ColorRegistry colorRegistry = JFaceResources.getColorRegistry();
if (!colorRegistry.hasValueFor(COLOR_WHITE)) {
colorRegistry.put(COLOR_WHITE, new RGB(255, 255, 255));
}
colorWhite = colorRegistry.get(COLOR_WHITE);
}
if (colorDisabled == null) {
ColorRegistry colorRegistry = JFaceResources.getColorRegistry();
if (!colorRegistry.hasValueFor(COLOR_DARK_GRAY)) {
colorRegistry.put(COLOR_DARK_GRAY, new RGB(0x69, 0x69, 0x69));
}
colorDisabled = colorRegistry.get(COLOR_DARK_GRAY);
}
if (colorCategoryGradientStart == null) {
colorCategoryGradientStart = themeManager.getCurrentTheme()
.getColorRegistry()
.get(CommonThemes.COLOR_CATEGORY_GRADIENT_START);
colorCategoryGradientEnd = themeManager.getCurrentTheme()
.getColorRegistry()
.get(CommonThemes.COLOR_CATEGORY_GRADIENT_END);
}
}
private void initializeCursors() {
if (handCursor == null) {
handCursor = new Cursor(getShell().getDisplay(), SWT.CURSOR_HAND);
disposables.add(handCursor);
}
}
private FontDescriptor createFontDescriptor(int style, float heightMultiplier) {
Font baseFont = JFaceResources.getDialogFont();
FontData[] fontData = baseFont.getFontData();
FontData[] newFontData = new FontData[fontData.length];
for (int i = 0; i < newFontData.length; i++) {
newFontData[i] = new FontData(fontData[i].getName(), (int) (fontData[i].getHeight() * heightMultiplier),
fontData[i].getStyle() | style);
}
return FontDescriptor.createFrom(newFontData);
}
private void initializeFonts() {
// create a level-2 heading font
if (h2Font == null) {
h2Font = new Font(Display.getCurrent(), createFontDescriptor(SWT.BOLD, 1.25f).getFontData());
disposables.add(h2Font);
}
// create a level-1 heading font
if (h1Font == null) {
h1Font = new Font(Display.getCurrent(), createFontDescriptor(SWT.BOLD, 1.35f).getFontData());
disposables.add(h1Font);
}
}
private void initializeImages() {
if (infoImage == null) {
infoImage = DiscoveryImages.MESSAGE_INFO.createImage();
disposables.add(infoImage);
}
}
public boolean isComplete() {
return complete;
}
/**
* indicate if there is nothing to display in the UI, given the current state of
* {@link ConnectorDiscoveryWizard#isVisible(ConnectorDescriptorKind) filters}.
*/
private boolean isEmpty(ConnectorDiscovery discovery) {
for (DiscoveryCategory category : discovery.getCategories()) {
if (!isEmpty(category)) {
return false;
}
}
return true;
}
/**
* indicate if the category has nothing to display in the UI, given the current state of
* {@link ConnectorDiscoveryWizard#isVisible(ConnectorDescriptorKind) filters}.
*/
private boolean isEmpty(DiscoveryCategory category) {
if (category.getConnectors().isEmpty()) {
return true;
}
for (ConnectorDescriptor descriptor : category.getConnectors()) {
if (!isFiltered(descriptor)) {
return false;
}
}
return true;
}
public void addFilter(ViewerFilter filter) {
filters.add(filter);
}
public void removeFilter(ViewerFilter filter) {
filters.remove(filter);
}
private boolean isFiltered(ConnectorDescriptor descriptor) {
boolean kindFiltered = true;
for (ConnectorDescriptorKind kind : descriptor.getKind()) {
if (isVisible(kind)) {
kindFiltered = false;
break;
}
}
if (kindFiltered) {
return true;
}
if (!showInstalled && descriptor.isInstalled()) {
return true;
}
if (filterPattern != null) {
if (!(filterMatches(descriptor.getName()) || filterMatches(descriptor.getDescription())
|| filterMatches(descriptor.getProvider()) || filterMatches(descriptor.getLicense()))) {
return true;
}
}
for (ViewerFilter filter : filters) {
if (!filter.select(null, null, descriptor)) {
return true;
}
}
return false;
}
/**
* indicate if the connector descriptor filters should be shown in the UI. Changing this setting only has an effect
* before the UI is presented.
*/
public boolean isShowConnectorDescriptorKindFilter() {
return showConnectorDescriptorKindFilter;
}
/**
* indicate if a text field should be provided to allow the user to filter connector descriptors
*/
public boolean isShowConnectorDescriptorTextFilter() {
return showConnectorDescriptorTextFilter;
}
public boolean isShowInstalled() {
return showInstalled;
}
public boolean isShowInstalledFilterEnabled() {
return showInstalledFilterEnabled;
}
/**
* indicate if the given kind of connector is currently visible in the wizard
*
* @see #setVisibility(ConnectorDescriptorKind, boolean)
*/
public boolean isVisible(ConnectorDescriptorKind kind) {
if (kind == null) {
throw new IllegalArgumentException();
}
return connectorDescriptorKindToVisibility.get(kind);
}
private void modifySelection(final DiscoveryConnector connector, boolean selected) {
modifySelectionInternal(connector, selected);
updateState();
}
private void modifySelectionInternal(final DiscoveryConnector connector, boolean selected) {
connector.setSelected(selected);
if (selected) {
installableConnectors.add(connector);
} else {
installableConnectors.remove(connector);
}
}
public void removeSelectionChangedListener(ISelectionChangedListener listener) {
selectionProvider.removeSelectionChangedListener(listener);
}
public void setComplete(boolean complete) {
this.complete = complete;
}
protected void setControl(Control control) {
this.control = control;
}
public void setDirectoryUrl(String directoryUrl) {
this.directoryUrl = directoryUrl;
}
/**
* the environment in which discovery should be performed.
*
* @see ConnectorDiscovery#getEnvironment()
*/
public void setEnvironment(Dictionary<Object, Object> environment) {
if (environment == null) {
throw new IllegalArgumentException();
}
this.environment = environment;
}
public void setFilterText(String text) {
Assert.isNotNull(text);
filterText.setText(text);
filterTextChanged();
}
public void setSelection(IStructuredSelection selection) {
Set<ConnectorDescriptor> selected = new HashSet<ConnectorDescriptor>();
for (Object descriptor : selection.toArray()) {
if (descriptor instanceof ConnectorDescriptor) {
selected.add((ConnectorDescriptor) descriptor);
}
}
for (DiscoveryConnector connector : allConnectors) {
modifySelectionInternal(connector, selected.contains(connector));
}
updateState();
}
/**
* indicate if the connector descriptor filters should be shown in the UI. Changing this setting only has an effect
* before the UI is presented.
*/
public void setShowConnectorDescriptorKindFilter(boolean showConnectorDescriptorKindFilter) {
this.showConnectorDescriptorKindFilter = showConnectorDescriptorKindFilter;
}
/**
* indicate if a text field should be provided to allow the user to filter connector descriptors
*/
public void setShowConnectorDescriptorTextFilter(boolean showConnectorDescriptorTextFilter) {
this.showConnectorDescriptorTextFilter = showConnectorDescriptorTextFilter;
}
public void setShowInstalled(boolean showInstalled) {
this.showInstalled = showInstalled;
connectorDescriptorKindVisibilityUpdated();
}
public void setShowInstalledFilterEnabled(boolean showInstalledFilter) {
this.showInstalledFilterEnabled = showInstalledFilter;
}
public void setVerifyUpdateSiteAvailability(boolean verifyUpdateSiteAvailability) {
this.verifyUpdateSiteAvailability = verifyUpdateSiteAvailability;
}
/**
* configure the page to show or hide connector descriptors of the given kind
*
* @see #connectorDescriptorKindVisibilityUpdated()
*/
public void setVisibility(ConnectorDescriptorKind kind, boolean visible) {
if (kind == null) {
throw new IllegalArgumentException();
}
connectorDescriptorKindToVisibility.put(kind, visible);
}
public void updateDiscovery() {
final Dictionary<Object, Object> environment = getEnvironment();
boolean wasCancelled = false;
try {
final IStatus[] result = new IStatus[1];
context.run(true, true, new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
if (DiscoveryViewer.this.installedFeatures == null) {
DiscoveryViewer.this.installedFeatures = getInstalledFeatures(monitor);
}
ConnectorDiscovery connectorDiscovery = new ConnectorDiscovery();
// look for descriptors from installed bundles
connectorDiscovery.getDiscoveryStrategies().add(new BundleDiscoveryStrategy());
// look for remote descriptor
if (directoryUrl != null) {
RemoteBundleDiscoveryStrategy remoteDiscoveryStrategy = new RemoteBundleDiscoveryStrategy();
remoteDiscoveryStrategy.setDirectoryUrl(directoryUrl);
connectorDiscovery.getDiscoveryStrategies().add(remoteDiscoveryStrategy);
}
connectorDiscovery.setEnvironment(environment);
connectorDiscovery.setVerifyUpdateSiteAvailability(false);
try {
result[0] = connectorDiscovery.performDiscovery(monitor);
} finally {
DiscoveryViewer.this.discovery = connectorDiscovery;
postDiscovery(connectorDiscovery);
}
if (monitor.isCanceled()) {
throw new InterruptedException();
}
}
});
if (result[0] != null && !result[0].isOK()) {
StatusManager.getManager().handle(result[0],
StatusManager.SHOW | StatusManager.BLOCK | StatusManager.LOG);
}
} catch (InvocationTargetException e) {
IStatus status = computeStatus(e, Messages.ConnectorDiscoveryWizardMainPage_unexpectedException);
StatusManager.getManager().handle(status, StatusManager.SHOW | StatusManager.BLOCK | StatusManager.LOG);
} catch (InterruptedException e) {
// cancelled by user so nothing to do here.
wasCancelled = true;
}
// check if control was closed
if (body.isDisposed()) {
return;
}
if (discovery != null) {
discoveryUpdated(wasCancelled);
if (verifyUpdateSiteAvailability && !discovery.getConnectors().isEmpty()) {
try {
context.run(true, true, new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException,
InterruptedException {
discovery.verifySiteAvailability(monitor);
}
});
} catch (InvocationTargetException e) {
IStatus status = computeStatus(e, Messages.ConnectorDiscoveryWizardMainPage_unexpectedException);
StatusManager.getManager().handle(status,
StatusManager.SHOW | StatusManager.BLOCK | StatusManager.LOG);
} catch (InterruptedException e) {
// cancelled by user so nothing to do here.
wasCancelled = true;
}
}
// check if control was closed
if (body.isDisposed()) {
return;
}
// createBodyContents() shouldn't be necessary but for some
// reason checkboxes don't
// regain their enabled state
createBodyContents();
}
// help UI tests
body.setData("discoveryComplete", "true"); //$NON-NLS-1$ //$NON-NLS-2$
}
private void updateState() {
setComplete(!installableConnectors.isEmpty());
selectionProvider.setSelection(new StructuredSelection(getInstallableConnectors()));
}
protected void postDiscovery(ConnectorDiscovery connectorDiscovery) {
for (DiscoveryConnector connector : connectorDiscovery.getConnectors()) {
connector.setInstalled(installedFeatures != null
&& installedFeatures.containsAll(connector.getInstallableUnits()));
}
}
protected Set<String> getInstalledFeatures(IProgressMonitor monitor) throws InterruptedException {
return DiscoveryUi.createInstallJob().getInstalledFeatures(monitor);
}
}