Bug 11620 - provide support for links (including special support for installer page link) in description column of remote connections view
--- a/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/internal/ui/ConnectionUIUtils.java Thu Sep 16 09:07:54 2010 -0500
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/internal/ui/ConnectionUIUtils.java Thu Sep 16 09:17:01 2010 -0500
@@ -20,6 +20,7 @@
import java.util.Collection;
import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.JFaceColors;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
@@ -76,6 +77,7 @@
public static final Color COLOR_GREEN = new Color(Display.getDefault(), 0, 128, 0);
public static final Color COLOR_ELECTRIC = new Color(Display.getDefault(), 0, 0, 255);
public static final Color COLOR_GREY = new Color(Display.getDefault(), 96, 96, 96);
+ public static final Color COLOR_HYPERLINK = JFaceColors.getHyperlinkText(Display.getDefault());
/**
* Get the image representing the connection status.
--- a/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/messages.properties Thu Sep 16 09:07:54 2010 -0500
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/messages.properties Thu Sep 16 09:17:01 2010 -0500
@@ -67,7 +67,6 @@
ConnectionsView.ToggleServicesLabel=Toggle periodic service testing
ConnectionsView.TypeColumnHeader=Type
ConnectionsView.InUseLabel=In use
-ConnectionsView.InUseDesc=At least one service is using this connection
ConnectionsView.DisconnectedLabel=Disconnected
ConnectionsView.DisconnectedDesc=Connection has been disconnected while in use, please reconnect
ConnectionTypePage.ConnectionNameInUseError=The connection name ''{0}'' is in use
@@ -87,6 +86,7 @@
ConnectionStatusSelectorContribution.NotInUse=Not in use
ConnectionStatusSelectorContribution.StatusFormat=Connection is {0}: {1}
ConnectionStatusSelectorContribution.TestServicesMenuLabel=Test services
+DescriptionLabelProvider_InUseDesc=At least one service is using this connection
DeviceDiscoveryPrequisiteErrorDialog_Description=At least one device discovery agent had load errors that prevent it from discovering connections to devices. Select one to get more information about its error.
DeviceDiscoveryPrequisiteErrorDialog_DontAskAgainLabel=Don't ask again
DeviceDiscoveryPrequisiteErrorDialog_DontAskAgainToolTipText=Check this to ignore further discovery agent load errors
--- a/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/settings/ui/ConnectionSettingsPage.java Thu Sep 16 09:07:54 2010 -0500
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/settings/ui/ConnectionSettingsPage.java Thu Sep 16 09:17:01 2010 -0500
@@ -189,6 +189,9 @@
createSetupTabComposite(tabFolder);
createAgentTestTabComposite(tabFolder);
createInstallTabComposite(tabFolder);
+ int index = settingsWizard.getSelectedTabIndexInConnectionSettingsPage();
+ if (index >= 0 && index < 3)
+ tabFolder.setSelection(index);
RemoteConnectionsActivator.setHelp(tabFolder, ".connection_settings_page"); //$NON-NLS-1$
--- a/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/settings/ui/SettingsWizard.java Thu Sep 16 09:07:54 2010 -0500
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/settings/ui/SettingsWizard.java Thu Sep 16 09:17:01 2010 -0500
@@ -45,6 +45,7 @@
private IConnection connectionToEdit;
private IService serviceToRestrict;
private Map<IConnectedService, Boolean> savedEnabledStates;
+ private int selectedTabIndexInConnectionSettingsPage;
public SettingsWizard(IConnection connectionToEdit, IService serviceToRestrict) {
this.connectionToEdit = connectionToEdit;
@@ -162,4 +163,16 @@
connectionSettingsPage.updateDynamicUI();
getContainer().updateButtons();
}
+
+ /**
+ * Call before opening the wizard to set which tab will be selected in the setting page
+ * @param index int
+ */
+ public void setSelectedTabInSettingsPage(int index) {
+ this.selectedTabIndexInConnectionSettingsPage = index;
+ }
+
+ int getSelectedTabIndexInConnectionSettingsPage() {
+ return selectedTabIndexInConnectionSettingsPage;
+ }
}
--- a/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/view/ConnectionsView.java Thu Sep 16 09:07:54 2010 -0500
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/view/ConnectionsView.java Thu Sep 16 09:17:01 2010 -0500
@@ -89,16 +89,15 @@
import com.nokia.carbide.remoteconnections.interfaces.IConnectionsManager.IConnectionsManagerListener;
import com.nokia.carbide.remoteconnections.internal.ToggleDiscoveryAgentAction;
import com.nokia.carbide.remoteconnections.internal.api.IConnection2;
-import com.nokia.carbide.remoteconnections.internal.api.IToggleServicesTestingListener;
import com.nokia.carbide.remoteconnections.internal.api.IConnection2.IConnectionStatus;
import com.nokia.carbide.remoteconnections.internal.api.IConnection2.IConnectionStatus.EConnectionStatus;
import com.nokia.carbide.remoteconnections.internal.api.IConnection2.IConnectionStatusChangedListener;
import com.nokia.carbide.remoteconnections.internal.api.IDeviceDiscoveryAgent;
+import com.nokia.carbide.remoteconnections.internal.api.IToggleServicesTestingListener;
import com.nokia.carbide.remoteconnections.internal.registry.Registry;
import com.nokia.carbide.remoteconnections.internal.ui.ConnectionUIUtils;
import com.nokia.carbide.remoteconnections.settings.ui.SettingsWizard;
import com.nokia.cpp.internal.api.utils.core.ObjectUtils;
-import com.nokia.cpp.internal.api.utils.core.TextUtils;
/**
@@ -119,7 +118,7 @@
private List<Action> serviceSelectedActions;
private List<Action> discoveryAgentActions;
private static final String UID = ".uid"; //$NON-NLS-1$
-
+
private static final ImageDescriptor CONNECTION_NEW_IMGDESC = RemoteConnectionsActivator.getImageDescriptor("icons/connectionNew.png"); //$NON-NLS-1$
private static final ImageDescriptor CONNECTION_EDIT_IMGDESC = RemoteConnectionsActivator.getImageDescriptor("icons/connectionEdit.png"); //$NON-NLS-1$
private static final ImageDescriptor SERVICE_TEST_IMGDESC = RemoteConnectionsActivator.getImageDescriptor("icons/serviceTest.png"); //$NON-NLS-1$
@@ -265,9 +264,6 @@
return getNodeDisplayName(obj);
}
- /* (non-Javadoc)
- * @see org.eclipse.jface.viewers.ColumnLabelProvider#getFont(java.lang.Object)
- */
@Override
public Font getFont(Object element) {
if (element instanceof TreeNode) {
@@ -345,9 +341,6 @@
return null;
}
- /* (non-Javadoc)
- * @see org.eclipse.jface.viewers.ColumnLabelProvider#getFont(java.lang.Object)
- */
@Override
public Font getFont(Object element) {
// we need this to avoid letting the bold name column influence the others
@@ -355,46 +348,6 @@
}
}
- public class DescriptionLabelProvider extends ColumnLabelProvider {
-
- @Override
- public String getText(Object obj) {
- TreeNode node = (TreeNode) obj;
- Object value = node.getValue();
- if (value instanceof IConnectedService) {
- IStatus status = ((IConnectedService) value).getStatus();
- IConnection connection = findConnection((IConnectedService) value);
- if (!status.getEStatus().equals(EStatus.IN_USE) ||
- !(connection != null && ConnectionUIUtils.isSomeServiceInUse(connection))) { // if in-use, we show it in the connection row
- String longDescription = status.getLongDescription();
- if (longDescription != null)
- longDescription = TextUtils.canonicalizeNewlines(longDescription, " "); //$NON-NLS-1$
- return longDescription;
- }
- }
- else if (value instanceof IConnection) {
- IConnectionStatus status = getConnectionStatus((IConnection) value);
- if (status != null) {
- return status.getLongDescription();
- }
- else if (ConnectionUIUtils.isSomeServiceInUse((IConnection) value)) {
- return Messages.getString("ConnectionsView.InUseDesc"); //$NON-NLS-1$
- }
- }
-
- return null;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.jface.viewers.ColumnLabelProvider#getFont(java.lang.Object)
- */
- @Override
- public Font getFont(Object element) {
- // we need this to avoid letting the bold name column influence the others
- return JFaceResources.getDefaultFont();
- }
- }
-
private class TypeLabelProvider extends ColumnLabelProvider {
public String getText(Object obj) {
@@ -406,9 +359,6 @@
return null;
}
- /* (non-Javadoc)
- * @see org.eclipse.jface.viewers.ColumnLabelProvider#getFont(java.lang.Object)
- */
@Override
public Font getFont(Object element) {
// we need this to avoid letting the bold name column influence the others
@@ -466,9 +416,6 @@
}
}
- /* (non-Javadoc)
- * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
- */
public void createPartControl(Composite parent) {
viewer = new TreeViewer(parent, SWT.H_SCROLL | SWT.V_SCROLL);
@@ -495,7 +442,7 @@
statusColumn.getColumn().setText(Messages.getString("ConnectionsView.StatusColumnHeader")); //$NON-NLS-1$
TreeViewerColumn descriptionColumn = new TreeViewerColumn(viewer, SWT.LEFT);
- descriptionColumn.setLabelProvider(new DescriptionLabelProvider());
+ descriptionColumn.setLabelProvider(new DescriptionLabelProvider(this, descriptionColumn));
descriptionColumn.getColumn().setText(Messages.getString("ConnectionsView.DescriptionColumnHeader")); //$NON-NLS-1$
viewer.setContentProvider(new TreeNodeContentProvider());
@@ -601,7 +548,7 @@
}
// returns non-null status when status is not EConnectionStatus.NONE
- private IConnectionStatus getConnectionStatus(IConnection connection) {
+ public IConnectionStatus getConnectionStatus(IConnection connection) {
if (connection instanceof IConnection2) {
IConnectionStatus status = ((IConnection2) connection).getStatus();
if (status != null && status.getEConnectionStatus() != EConnectionStatus.NONE)
@@ -973,7 +920,7 @@
super.dispose();
}
- private static IConnection findConnection(IConnectedService cs) {
+ public static IConnection findConnection(IConnectedService cs) {
for (IConnection connection : Registry.instance().getConnections()) {
for (IConnectedService connectedService : Registry.instance().getConnectedServices(connection)) {
if (cs.equals(connectedService))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/view/DescriptionLabelProvider.java Thu Sep 16 09:17:01 2010 -0500
@@ -0,0 +1,285 @@
+package com.nokia.carbide.remoteconnections.view;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.StyledCellLabelProvider;
+import org.eclipse.jface.viewers.StyledString;
+import org.eclipse.jface.viewers.StyledString.Styler;
+import org.eclipse.jface.viewers.TreeNode;
+import org.eclipse.jface.viewers.TreeViewerColumn;
+import org.eclipse.jface.viewers.ViewerCell;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.TextStyle;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.swt.widgets.Widget;
+
+import com.nokia.carbide.remoteconnections.Messages;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectedService;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectedService.IStatus;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectedService.IStatus.EStatus;
+import com.nokia.carbide.remoteconnections.interfaces.IConnection;
+import com.nokia.carbide.remoteconnections.internal.api.IConnection2.IConnectionStatus;
+import com.nokia.carbide.remoteconnections.internal.ui.ConnectionUIUtils;
+import com.nokia.carbide.remoteconnections.settings.ui.SettingsWizard;
+import com.nokia.cpp.internal.api.utils.core.TextUtils;
+import com.nokia.cpp.internal.api.utils.ui.WorkbenchUtils;
+
+public class DescriptionLabelProvider extends StyledCellLabelProvider {
+
+ private class Element {
+ private String text;
+
+ public Element(String text) {
+ this.text = text;
+ }
+
+ public String getText() {
+ return text;
+ }
+ }
+
+ private class LinkElement extends Element {
+ private String href;
+
+ public LinkElement(String href, String text) {
+ super(text);
+ this.href = href;
+ }
+
+ public String getHref() {
+ return href;
+ }
+ }
+
+ private static final Pattern HREF_PATTERN =
+ Pattern.compile("<a href=\"([^\"]*)\">(.*?)</a>", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
+ private static final String AGENT_INSTALLERS_URL = "about:agentInstallers"; //$NON-NLS-1$
+
+ private final ConnectionsView connectionsView;
+ private Styler hyperLinkStyler;
+ private TreeViewerColumn treeViewerColumn;
+ private Listener mouseListener;
+
+ public DescriptionLabelProvider(ConnectionsView connectionsView, TreeViewerColumn treeViewerColumn) {
+ this.connectionsView = connectionsView;
+ this.treeViewerColumn = treeViewerColumn;
+ hookColumn();
+ hyperLinkStyler = new Styler() {
+ @Override
+ public void applyStyles(TextStyle textStyle) {
+ textStyle.foreground = ConnectionUIUtils.COLOR_HYPERLINK;
+ textStyle.underline = true;
+ }
+ };
+ }
+
+ private void hookColumn() {
+ final Control control = treeViewerColumn.getViewer().getControl();
+ final Cursor originalCursor = control.getCursor();
+ final Cursor handCursor = treeViewerColumn.getColumn().getDisplay().getSystemCursor(SWT.CURSOR_HAND);
+ mouseListener = new Listener() {
+ public void handleEvent(Event event) {
+ switch (event.type) {
+ case SWT.MouseEnter:
+ case SWT.MouseMove:
+ if (getLinkHRef(event) != null) {
+ control.setCursor(handCursor);
+ }
+ else {
+ control.setCursor(originalCursor);
+ }
+ break;
+ case SWT.MouseExit:
+ control.setCursor(originalCursor);
+ break;
+ case SWT.MouseDown:
+ String linkHRef = getLinkHRef(event);
+ handleLinkClicked(linkHRef, event);
+ break;
+ default:
+ }
+ }
+
+ private String getLinkHRef(Event event) {
+ Point pt = new Point(50, event.y);
+ ViewerCell cell = getViewer().getCell(pt);
+ if (cell == null)
+ return null;
+ TreeItem item = (TreeItem) cell.getItem();
+ String text = getText(cell.getElement());
+ List<Element> elements = parseText(text);
+ if (elements.isEmpty())
+ return null;
+ int locMouseX = event.x - item.getTextBounds(3).x;
+ GC gc = new GC(item.getDisplay());
+ try {
+ gc.setFont(item.getFont());
+ int elementStartX = 0;
+ int elementEndX = 0;
+ for (Element element : elements) {
+ elementEndX += gc.stringExtent(element.getText()).x;
+ if (element instanceof LinkElement) {
+ if (locMouseX >= elementStartX && locMouseX < elementEndX) {
+ LinkElement linkElement = (LinkElement) element;
+ return linkElement.getHref();
+ }
+ }
+ elementStartX = elementEndX + 1;
+ }
+ }
+ finally {
+ gc.dispose();
+ }
+ return null;
+ }
+
+ private void handleLinkClicked(final String linkHRef, final Event event) {
+ BusyIndicator.showWhile(Display.getDefault(), new Runnable() {
+ public void run() {
+ if (linkHRef.equalsIgnoreCase(AGENT_INSTALLERS_URL)) {
+ Point pt = new Point(50, event.y);
+ ViewerCell cell = getViewer().getCell(pt);
+ if (cell == null)
+ return;
+ TreeItem treeItem = findParentTreeItem((TreeItem) cell.getItem());
+ TreeNode node = (TreeNode) treeItem.getData();
+ final Object value = node.getValue();
+ if (value instanceof IConnection) {
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ SettingsWizard wizard = new SettingsWizard((IConnection) value);
+ wizard.setSelectedTabInSettingsPage(2);
+ wizard.open(connectionsView.getViewSite().getShell());
+ }
+ });
+ }
+ }
+ else {
+ try {
+ URL url = new URL(linkHRef);
+ WorkbenchUtils.showWebPageInExternalBrowser(url.toExternalForm());
+ } catch (MalformedURLException e) {
+ }
+ }
+ }
+ });
+ }
+
+ private TreeItem findParentTreeItem(TreeItem item) {
+ TreeItem parentItem = item.getParentItem();
+ while (parentItem != null) {
+ item = parentItem;
+ parentItem = item.getParentItem();
+ }
+ return item;
+ }
+
+ };
+ Widget widget = treeViewerColumn.getViewer().getControl();
+ widget.addListener(SWT.MouseEnter, mouseListener);
+ widget.addListener(SWT.MouseMove, mouseListener);
+ widget.addListener(SWT.MouseExit, mouseListener);
+ widget.addListener(SWT.MouseDown, mouseListener);
+ }
+
+ private void unhookColumn() {
+ Widget widget = treeViewerColumn.getViewer().getControl();
+ if (widget == null || widget.isDisposed())
+ return;
+ widget.removeListener(SWT.MouseEnter, mouseListener);
+ widget.removeListener(SWT.MouseMove, mouseListener);
+ widget.removeListener(SWT.MouseExit, mouseListener);
+ widget.removeListener(SWT.MouseDown, mouseListener);
+ }
+
+ @Override
+ public void update(ViewerCell cell) {
+ Object element = cell.getElement();
+ String text = getText(element);
+ List<Element> elements = parseText(text);
+
+ StyledString styledString = getStyledString(elements);
+ cell.setText(styledString.toString());
+ cell.setStyleRanges(styledString.getStyleRanges());
+
+ // we need this to avoid letting the bold name column influence the others
+ cell.setFont(JFaceResources.getDefaultFont());
+
+ super.update(cell);
+ }
+
+ private List<Element> parseText(String text) {
+ List<Element> elements = new ArrayList<Element>();
+ if (text != null) {
+ Matcher m = HREF_PATTERN.matcher(text);
+ int start = 0;
+ int end;
+ while (m.find()) {
+ end = m.start();
+ if (start <= end)
+ elements.add(new Element(text.substring(start, end)));
+ elements.add(new LinkElement(m.group(1), m.group(2)));
+ start = m.end();
+ }
+ end = text.length();
+ if (start <= end)
+ elements.add(new Element(text.substring(start, end)));
+ }
+ return elements;
+ }
+
+ private StyledString getStyledString(List<Element> elements) {
+ StyledString styledString = new StyledString();
+ for (Element element : elements) {
+ styledString.append(element.getText(), element instanceof LinkElement ? hyperLinkStyler : null);
+ }
+ return styledString;
+ }
+
+ private String getText(Object obj) {
+ TreeNode node = (TreeNode) obj;
+ Object value = node.getValue();
+ if (value instanceof IConnectedService) {
+ IStatus status = ((IConnectedService) value).getStatus();
+ IConnection connection = ConnectionsView.findConnection((IConnectedService) value);
+ if (!status.getEStatus().equals(EStatus.IN_USE) ||
+ !(connection != null && ConnectionUIUtils.isSomeServiceInUse(connection))) { // if in-use, we show it in the connection row
+ String longDescription = status.getLongDescription();
+ if (longDescription != null)
+ longDescription = TextUtils.canonicalizeNewlines(longDescription, " "); //$NON-NLS-1$
+ return longDescription;
+ }
+ }
+ else if (value instanceof IConnection) {
+ IConnectionStatus status = this.connectionsView.getConnectionStatus((IConnection) value);
+ if (status != null) {
+ return status.getLongDescription();
+ }
+ else if (ConnectionUIUtils.isSomeServiceInUse((IConnection) value)) {
+ return Messages.getString("DescriptionLabelProvider_InUseDesc"); //$NON-NLS-1$
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public void dispose() {
+ unhookColumn();
+ super.dispose();
+ }
+}
\ No newline at end of file