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>