# HG changeset patch # User dadubrow # Date 1284646621 18000 # Node ID ff6b4aae1c1ebb7d7f97bbe414916c7328ef0b4d # Parent 2a1cbc6a1c85705810cf9249f7fd6ac96c4533e4 Bug 11620 - provide support for links (including special support for installer page link) in description column of remote connections view diff -r 2a1cbc6a1c85 -r ff6b4aae1c1e connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/internal/ui/ConnectionUIUtils.java --- 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. diff -r 2a1cbc6a1c85 -r ff6b4aae1c1e connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/messages.properties --- 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 diff -r 2a1cbc6a1c85 -r ff6b4aae1c1e connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/settings/ui/ConnectionSettingsPage.java --- 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$ diff -r 2a1cbc6a1c85 -r ff6b4aae1c1e connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/settings/ui/SettingsWizard.java --- 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 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; + } } diff -r 2a1cbc6a1c85 -r ff6b4aae1c1e connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/view/ConnectionsView.java --- 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 serviceSelectedActions; private List 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)) diff -r 2a1cbc6a1c85 -r ff6b4aae1c1e connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/view/DescriptionLabelProvider.java --- /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("(.*?)", 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 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 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 parseText(String text) { + List elements = new ArrayList(); + 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 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