Bug 530835: Preference page for URI Scheme handler Link Handlers Preference page is used to choose handler instance of eclipse for URI Schemes which are created in URI Scheme extensions Change-Id: Iab91cd10451a6bc52aab8bcdf1a35fefba27b418 Signed-off-by: Arunkumar <arunkumar.s@sap.com> Signed-off-by: Marcus Hoepfner <marcus.hoepfner@sap.com>
diff --git a/bundles/org.eclipse.ui.ide.application/plugin.properties b/bundles/org.eclipse.ui.ide.application/plugin.properties index 0333c3b..2ae6ca9 100644 --- a/bundles/org.eclipse.ui.ide.application/plugin.properties +++ b/bundles/org.eclipse.ui.ide.application/plugin.properties
@@ -17,6 +17,7 @@ PreferencePages.Startup = Startup and Shutdown PreferencePages.Startup.Workspaces = Workspaces +PreferencePages.General.LinkHandlers = Link Handlers Perspective.resourcePerspective = Resource Perspective.resourceDescription = This perspective is designed to provide general resource viewing and navigation. @@ -40,4 +41,7 @@ command.zoomIn.mnemonic=I command.zoomOut.mnemonic=O -keyword.problems = problems \ No newline at end of file +keyword.problems = problems +keyword.linkhanders = link handlers schemes + +page.name = Link Handlers \ No newline at end of file
diff --git a/bundles/org.eclipse.ui.ide.application/plugin.xml b/bundles/org.eclipse.ui.ide.application/plugin.xml index 945d1e9..1fdda9b 100644 --- a/bundles/org.eclipse.ui.ide.application/plugin.xml +++ b/bundles/org.eclipse.ui.ide.application/plugin.xml
@@ -27,6 +27,15 @@ id="org.eclipse.ui.preferencePages.Startup.Workspaces"> <keywordReference id="org.eclipse.ui.ide.recentWorkspaces"/> </page> + <page + category="org.eclipse.ui.preferencePages.Workbench" + class="org.eclipse.ui.internal.ide.application.dialogs.UriSchemeHandlerPreferencePage" + id="org.eclipse.ui.preferencePages.General.LinkHandlers" + name="%PreferencePages.General.LinkHandlers"> + <keywordReference + id="org.eclipse.ui.ide.application.linkhandler"> + </keywordReference> + </page> </extension> <extension point="org.eclipse.ui.perspectives"> @@ -168,5 +177,9 @@ id="org.eclipse.ui.ide.application.problems" label="%keyword.problems"> </keyword> + <keyword + id="org.eclipse.ui.ide.application.linkhandler" + label="%keyword.linkhanders"> + </keyword> </extension> </plugin>
diff --git a/bundles/org.eclipse.ui.ide.application/src/org/eclipse/ui/internal/ide/application/dialogs/UriSchemeHandlerPreferencePage.java b/bundles/org.eclipse.ui.ide.application/src/org/eclipse/ui/internal/ide/application/dialogs/UriSchemeHandlerPreferencePage.java new file mode 100644 index 0000000..8c8c59a --- /dev/null +++ b/bundles/org.eclipse.ui.ide.application/src/org/eclipse/ui/internal/ide/application/dialogs/UriSchemeHandlerPreferencePage.java
@@ -0,0 +1,309 @@ +/******************************************************************************* +* Copyright (c) 2018 SAP SE 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: +* SAP SE - initial API and implementation +*******************************************************************************/ +package org.eclipse.ui.internal.ide.application.dialogs; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.layout.PixelConverter; +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.internal.ide.IDEWorkbenchMessages; +import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; +import org.eclipse.ui.statushandlers.StatusManager; +import org.eclipse.urischeme.IOperatingSystemRegistration; +import org.eclipse.urischeme.ISchemeInformation; +import org.eclipse.urischeme.IUriSchemeExtensionReader; +import org.eclipse.urischeme.IUriSchemeExtensionReader.Scheme; + +/** + * This page contributes to URL handler for URISchemes in preference page of + * General section + * + */ +public class UriSchemeHandlerPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { + + private Label handlerLocation; + private TableViewer tableViewer; + private IOperatingSystemRegistration operatingSystemRegistration; + private Collection<UiSchemeInformation> schemeInformationList = null; + private String currentLocation = null; + + @SuppressWarnings("javadoc") + public UriSchemeHandlerPreferencePage() { + super.setDescription(IDEWorkbenchMessages.UrlHandlerPreferencePage_Page_Description); + } + + @Override + protected Control createContents(Composite parent) { + noDefaultAndApplyButton(); + addFiller(parent, 2); + createTableViewerForSchemes(parent); + GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1); + handlerLocation = new Label(parent, SWT.FILL); + handlerLocation.setLayoutData(gridData); + return parent; + } + + private void createTableViewerForSchemes(Composite parent) { + Composite editorComposite = new Composite(parent, SWT.NONE); + GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false); + gridData.horizontalSpan = 2; + gridData.horizontalIndent = 0; + editorComposite.setLayoutData(gridData); + Table schemeTable = new Table(editorComposite, + SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION | SWT.CHECK); + schemeTable.setHeaderVisible(true); + schemeTable.setLinesVisible(true); + schemeTable.setFont(parent.getFont()); + // Selection listener for both check and selection + schemeTable.addListener(SWT.Selection, new TableSchemeSelectionListener()); + + // Table columns, Scheme name and Scheme Descriptions + TableColumnLayout tableColumnlayout = new TableColumnLayout(); + editorComposite.setLayout(tableColumnlayout); + + TableColumn nameColumn = new TableColumn(schemeTable, SWT.NONE, 0); + nameColumn.setText(IDEWorkbenchMessages.UrlHandlerPreferencePage_ColumnName_SchemeName); + + TableColumn descriptionColumn = new TableColumn(schemeTable, SWT.NONE, 1); + descriptionColumn.setText(IDEWorkbenchMessages.UrlHandlerPreferencePage_ColumnName_SchemeDescription); + + tableColumnlayout.setColumnData(nameColumn, new ColumnWeightData(20)); + tableColumnlayout.setColumnData(descriptionColumn, new ColumnWeightData(80)); + + tableViewer = new TableViewer(schemeTable); + tableViewer.setContentProvider(ArrayContentProvider.getInstance()); + tableViewer.setLabelProvider(new ItemLabelProvider()); + + // Gets the schemes from extension points for URI schemes + try { + schemeInformationList = retrieveSchemeInformationList(); + } catch (Exception e) { + IStatus status = new Status(IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH, 1, + IDEWorkbenchMessages.UrlHandlerPreferencePage_Error_Reading_Scheme, e); + StatusManager.getManager().handle(status, StatusManager.BLOCK | StatusManager.LOG); + } + tableViewer.setInput(schemeInformationList); + TableItem[] tableSchemes = tableViewer.getTable().getItems(); + // Initialize the check state for schemes which are already registered to this + // scheme instance + if (tableSchemes == null) { + return; + } + for (TableItem tableScheme : tableSchemes) { + UiSchemeInformation schemeInformation = (UiSchemeInformation) (tableScheme.getData()); + if (schemeInformation != null) { + tableScheme.setChecked(schemeInformation.checked); + } + } + } + + private void addFiller(Composite composite, int horizontalSpan) { + PixelConverter pixelConverter = new PixelConverter(composite); + Label filler = new Label(composite, SWT.LEFT); + GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); + gd.horizontalSpan = horizontalSpan; + gd.heightHint = pixelConverter.convertHeightInCharsToPixels(1) / 2; + filler.setLayoutData(gd); + } + + /** + * Schemes which are part of extension points for URI Schemes and are registered + * to operating system are consolidated here + * + * @return the supported and registered URI schemes of this instance of eclipse + * @throws Exception + */ + private Collection<UiSchemeInformation> retrieveSchemeInformationList() throws Exception { + Collection<UiSchemeInformation> returnList = new ArrayList<>(); + Collection<Scheme> schemes = IUriSchemeExtensionReader.INSTANCE.getSchemes(); + if (operatingSystemRegistration != null) { + for (ISchemeInformation info : operatingSystemRegistration.getSchemesInformation(schemes)) { + returnList.add(new UiSchemeInformation(info.isHandled(), info)); + } + } + return returnList; + } + + @Override + public void init(IWorkbench workbench) { + operatingSystemRegistration = IOperatingSystemRegistration.getInstance(); + if (operatingSystemRegistration != null) { + currentLocation = operatingSystemRegistration.getEclipseLauncher(); + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.preference.PreferencePage#performOk() + */ + @Override + public boolean performOk() { + if (operatingSystemRegistration == null) { + return true; + } + + List<ISchemeInformation> toAdd = new ArrayList<>(); + List<ISchemeInformation> toRemove = new ArrayList<>(); + for (UiSchemeInformation info : schemeInformationList) { + if (info.checked && !info.information.isHandled()) { + toAdd.add(info.information); + } + if (!info.checked && info.information.isHandled()) { + toRemove.add(info.information); + } + } + + try { + operatingSystemRegistration.handleSchemes(toAdd, toRemove); + } catch (Exception e) { + IStatus status = new Status(IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH, 1, + IDEWorkbenchMessages.UrlHandlerPreferencePage_Error_Writing_Scheme, e); + StatusManager.getManager().handle(status, StatusManager.BLOCK | StatusManager.LOG); + } + return true; + } + + private class TableSchemeSelectionListener implements Listener { + @Override + public void handleEvent(Event event) { + if (event.detail == SWT.CHECK) { + handleCheckbox(event); + } else { + handleSelection(); + } + } + + private void handleSelection() { + IStructuredSelection selection = tableViewer.getStructuredSelection(); + Object firstElement = selection != null ? selection.getFirstElement() : null; + if (firstElement != null && firstElement instanceof UiSchemeInformation) { + setSchemeDetails((UiSchemeInformation) firstElement); + } + } + + private void setSchemeDetails(UiSchemeInformation schemeInfo) { + if (schemeInfo.checked) { + handlerLocation.setText( + NLS.bind(IDEWorkbenchMessages.UrlHandlerPreferencePage_Label_Message_Current_Application, + currentLocation)); + + } else if (schemeIsHandledByOther(schemeInfo.information)) { + handlerLocation + .setText(NLS.bind(IDEWorkbenchMessages.UrlHandlerPreferencePage_Label_Message_Other_Application, + schemeInfo.information.getHandlerInstanceLocation())); + } else { + // checkbox not checked and: + // - no other handler handles it + // - or this eclipse handled it before (checkbox was unchecked but not yet + // applied) + handlerLocation.setText(IDEWorkbenchMessages.UrlHandlerPreferencePage_Label_Message_No_Application); + } + } + + private void handleCheckbox(Event event) { + TableItem tableItem = (TableItem) event.item; + if (tableItem != null && tableItem.getData() instanceof UiSchemeInformation) { + UiSchemeInformation schemeInformation = (UiSchemeInformation) tableItem.getData(); + + if (tableItem.getChecked() && schemeIsHandledByOther(schemeInformation.information)) { + // macOS: As lsregister always registers all plist files we cannot set a handler + // for a scheme that is already handled by another application. + // For Windows and Linux this might work - needs to be tested. + // As we think this is a edge case we start with a restrictive implementation. + event.doit = false; + tableItem.setChecked(false); + MessageDialog.openWarning(getShell(), + IDEWorkbenchMessages.UriHandlerPreferencePage_Warning_OtherApp, + NLS.bind(IDEWorkbenchMessages.UriHandlerPreferencePage_Warning_OtherApp_Description, + schemeInformation.information.getHandlerInstanceLocation(), + schemeInformation.information.getScheme())); + return; + } + schemeInformation.checked = tableItem.getChecked(); + setSchemeDetails(schemeInformation); + } + } + } + + private boolean schemeIsHandledByOther(ISchemeInformation info) { + boolean schemeIsNotHandled = !info.isHandled(); + boolean handlerLocationIsSet = info.getHandlerInstanceLocation() != null + && !info.getHandlerInstanceLocation().isEmpty(); + return schemeIsNotHandled && handlerLocationIsSet; + } + + private final class ItemLabelProvider extends LabelProvider implements ITableLabelProvider { + + @Override + public Image getColumnImage(Object element, int columnIndex) { + return null; + } + + @Override + public String getColumnText(Object element, int columnIndex) { + if (element instanceof UiSchemeInformation) { + UiSchemeInformation schemeInfo = (UiSchemeInformation) element; + switch (columnIndex) { + case 0: + return schemeInfo.information.getScheme(); + case 1: + return schemeInfo.information.getDescription(); + default: + throw new IllegalArgumentException("Unknown column"); //$NON-NLS-1$ + } + } + return null; // cannot happen + } + + @Override + public boolean isLabelProperty(Object element, String property) { + return false; + } + } + + private final static class UiSchemeInformation { + public boolean checked; + public ISchemeInformation information; + + public UiSchemeInformation(boolean checked, ISchemeInformation information) { + this.checked = checked; + this.information = information; + } + + } +}
diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/IDEWorkbenchMessages.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/IDEWorkbenchMessages.java index 3626843..80b6d89 100644 --- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/IDEWorkbenchMessages.java +++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/IDEWorkbenchMessages.java
@@ -525,6 +525,20 @@ public static String WorkbenchPreference_unsupportedEncoding; public static String WorkbenchPreference_encoding_encodingMessage; + public static String UriHandlerPreferencePage_Warning_OtherApp; + + public static String UriHandlerPreferencePage_Warning_OtherApp_Description; + + // --- Link Handler Preference Page --- + public static String UrlHandlerPreferencePage_Label_Message_Current_Application; + public static String UrlHandlerPreferencePage_Label_Message_Other_Application; + public static String UrlHandlerPreferencePage_Label_Message_No_Application; + public static String UrlHandlerPreferencePage_Page_Description; + public static String UrlHandlerPreferencePage_ColumnName_SchemeName; + public static String UrlHandlerPreferencePage_ColumnName_SchemeDescription; + public static String UrlHandlerPreferencePage_Error_Reading_Scheme; + public static String UrlHandlerPreferencePage_Error_Writing_Scheme; + // ---workspace --- public static String IDEWorkspacePreference_autobuild; public static String IDEWorkspacePreference_autobuildToolTip;
diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/messages.properties b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/messages.properties index e1dc5ce..e036d70 100644 --- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/messages.properties +++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/messages.properties
@@ -504,6 +504,18 @@ WorkbenchPreference_encoding_encodingMessage = Byte Order Mark is {0} +# --- Link Handler Preference Page --- +UriHandlerPreferencePage_Warning_OtherApp=Action not possible +UriHandlerPreferencePage_Warning_OtherApp_Description=Another application ({0}) handles the "{1}" scheme.\n\nRemove the "{1}" scheme in the other application first. +UrlHandlerPreferencePage_Label_Message_Current_Application=Handler: This application ({0}) +UrlHandlerPreferencePage_Label_Message_Other_Application=Handler: Other application ({0}) +UrlHandlerPreferencePage_Label_Message_No_Application=Handler: No application +UrlHandlerPreferencePage_Page_Description=Link Handlers can handle links with a given scheme.\nThis page allows you to enable and disable link handlers in this application. +UrlHandlerPreferencePage_ColumnName_SchemeName=Scheme +UrlHandlerPreferencePage_ColumnName_SchemeDescription=Description +UrlHandlerPreferencePage_Error_Reading_Scheme=Error while reading Scheme information from Operating System +UrlHandlerPreferencePage_Error_Writing_Scheme=Error while writing Scheme information to Operating System + # ---Workspace IDEWorkspacePreference_autobuild = &Build automatically IDEWorkspacePreference_autobuildToolTip = Build automatically on resource modification
diff --git a/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/IOperatingSystemRegistration.java b/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/IOperatingSystemRegistration.java index ac3f036..84dc609 100644 --- a/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/IOperatingSystemRegistration.java +++ b/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/IOperatingSystemRegistration.java
@@ -18,6 +18,7 @@ import org.eclipse.urischeme.internal.registration.RegistrationLinux; import org.eclipse.urischeme.internal.registration.RegistrationMacOsX; import org.eclipse.urischeme.internal.registration.RegistrationWindows; + /** * Interface for registration or uri schemes in the different operating systems * (MacOSX, Linux and Windows)<br /> @@ -50,8 +51,7 @@ * @param toRemove the uri schemes which this Eclipse should not handle anymore * @throws Exception something went wrong */ - void handleSchemes(Collection<ISchemeInformation> toAdd, Collection<ISchemeInformation> toRemove) - throws Exception; + void handleSchemes(Collection<ISchemeInformation> toAdd, Collection<ISchemeInformation> toRemove) throws Exception; /** * Takes the given schemes and fills information like whether they are
diff --git a/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/ISchemeInformation.java b/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/ISchemeInformation.java index b4ac84c..e366541 100644 --- a/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/ISchemeInformation.java +++ b/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/ISchemeInformation.java
@@ -35,6 +35,13 @@ boolean isHandled(); /** + * Sets the handled value to true if scheme is handled by current Eclipse + * installation and false otherwise + * @param value + */ + void setHandled(boolean value); + + /** * @return the path of the application */ String getHandlerInstanceLocation();
diff --git a/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/internal/registration/SchemeInformation.java b/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/internal/registration/SchemeInformation.java index 37aae39..344909d 100644 --- a/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/internal/registration/SchemeInformation.java +++ b/bundles/org.eclipse.urischeme/src/org/eclipse/urischeme/internal/registration/SchemeInformation.java
@@ -46,7 +46,7 @@ return handlerInstanceLocation; } - @SuppressWarnings("javadoc") + @Override public void setHandled(boolean handled) { this.handled = handled; } @@ -60,5 +60,4 @@ public String getDescription() { return schemeDescription; } - -} \ No newline at end of file +}
diff --git a/examples/org.eclipse.ui.examples.uriSchemeHandler/plugin.xml b/examples/org.eclipse.ui.examples.uriSchemeHandler/plugin.xml index e31a92f..37b3d90 100644 --- a/examples/org.eclipse.ui.examples.uriSchemeHandler/plugin.xml +++ b/examples/org.eclipse.ui.examples.uriSchemeHandler/plugin.xml
@@ -65,6 +65,16 @@ uriSchemeDescription="The Hello World demo protocol" uriScheme="hello"> </uriSchemeHandler> + <uriSchemeHandler + class="org.eclipse.ui.examples.urischemehandler.uriHandlers.HelloSchemeHandler" + uriSchemeDescription="The Hello World demo protocol" + uriScheme="hello2"> + </uriSchemeHandler> + <uriSchemeHandler + class="org.eclipse.ui.examples.urischemehandler.uriHandlers.HelloSchemeHandler" + uriSchemeDescription="The Hello World demo protocol" + uriScheme="hello3"> + </uriSchemeHandler> </extension> </plugin>